Skip to content

Commit 4fee07e

Browse files
feat(nl2sql): separate debug and release mode (alibaba#2032)
1 parent 93ba7d1 commit 4fee07e

File tree

2 files changed

+155
-5
lines changed

2 files changed

+155
-5
lines changed

spring-ai-alibaba-nl2sql/spring-ai-alibaba-nl2sql-web-ui/src/components/AgentDebugPanel.vue

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ export default {
269269
}
270270
},
271271
setup(props) {
272+
// 调试模式下的 Agent ID 偏移量
273+
const DEBUG_AGENT_ID_OFFSET = 999999
274+
const debugAgentId = props.agentId + DEBUG_AGENT_ID_OFFSET
275+
272276
// 响应式数据
273277
const debugQuery = ref('查询用户总数')
274278
const isDebugging = ref(false)
@@ -341,7 +345,7 @@ export default {
341345
streamingSections.value = []
342346
343347
try {
344-
const eventSource = new EventSource(`/nl2sql/stream/search?query=${encodeURIComponent(debugQuery.value)}&agentId=${props.agentId}`)
348+
const eventSource = new EventSource(`/nl2sql/stream/search?query=${encodeURIComponent(debugQuery.value)}&agentId=${debugAgentId}`)
345349
currentEventSource = eventSource
346350
347351
// 使用与 AgentWorkspace.vue 完全相同的流式数据处理逻辑
@@ -816,7 +820,7 @@ export default {
816820
if (!schemaInitForm.selectedDatasource) return
817821
818822
try {
819-
const response = await fetch(`/api/agent/${props.agentId}/schema/datasources/${schemaInitForm.selectedDatasource.id}/tables`)
823+
const response = await fetch(`/api/agent/${debugAgentId}/schema/datasources/${schemaInitForm.selectedDatasource.id}/tables`)
820824
821825
if (!response.ok) {
822826
throw new Error(`HTTP error! status: ${response.status}`)
@@ -850,7 +854,7 @@ export default {
850854
try {
851855
schemaInitializing.value = true
852856
853-
const response = await fetch(`/api/agent/${props.agentId}/schema/init`, {
857+
const response = await fetch(`/api/agent/${debugAgentId}/schema/init`, {
854858
method: 'POST',
855859
headers: {
856860
'Content-Type': 'application/json'
@@ -885,7 +889,7 @@ export default {
885889
886890
const getSchemaStatistics = async () => {
887891
try {
888-
const response = await fetch(`/api/agent/${props.agentId}/schema/statistics`)
892+
const response = await fetch(`/api/agent/${debugAgentId}/schema/statistics`)
889893
890894
if (!response.ok) {
891895
throw new Error(`HTTP error! status: ${response.status}`)
@@ -912,7 +916,7 @@ export default {
912916
if (!confirm('确定要清空所有Schema数据吗?此操作不可恢复。')) return
913917
914918
try {
915-
const response = await fetch(`/api/agent/${props.agentId}/schema/clear`, {
919+
const response = await fetch(`/api/agent/${debugAgentId}/schema/clear`, {
916920
method: 'DELETE'
917921
})
918922

spring-ai-alibaba-nl2sql/spring-ai-alibaba-nl2sql-web-ui/src/views/AgentDetail.vue

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@
7878
</div>
7979
</div>
8080
</div>
81+
<div class="agent-actions">
82+
<button
83+
class="btn btn-publish"
84+
@click="publishAgent"
85+
:disabled="isPublishing"
86+
:class="{ loading: isPublishing }"
87+
>
88+
<i class="bi bi-cloud-upload" v-if="!isPublishing"></i>
89+
<div class="spinner" v-if="isPublishing"></div>
90+
{{ isPublishing ? '发布中...' : '发布' }}
91+
</button>
92+
</div>
8193
</div>
8294
</div>
8395
</div>
@@ -1165,6 +1177,9 @@ export default {
11651177
const schemaInitializing = ref(false)
11661178
const schemaStatistics = ref(null)
11671179
1180+
// 发布相关数据
1181+
const isPublishing = ref(false)
1182+
11681183
// 方法
11691184
const setActiveTab = (tab) => {
11701185
activeTab.value = tab
@@ -1846,6 +1861,82 @@ export default {
18461861
const hideMessage = () => {
18471862
message.show = false
18481863
}
1864+
1865+
// 发布智能体
1866+
const publishAgent = async () => {
1867+
if (isPublishing.value) return
1868+
1869+
try {
1870+
isPublishing.value = true
1871+
showMessage('开始发布智能体...', 'info')
1872+
1873+
// 1. 获取智能体配置的数据源
1874+
const agentDatasources = await datasourceApi.getAgentDatasources(agent.id)
1875+
if (!agentDatasources || agentDatasources.length === 0) {
1876+
throw new Error('智能体未配置数据源,请先配置数据源')
1877+
}
1878+
1879+
// 2. 使用正常的 agentId 进行 schema 初始化
1880+
const enabledDatasources = agentDatasources.filter(ds => ds.isActive === 1)
1881+
if (enabledDatasources.length === 0) {
1882+
throw new Error('没有启用的数据源,请先启用至少一个数据源')
1883+
}
1884+
1885+
// 3. 为每个启用的数据源获取表列表并初始化
1886+
for (const agentDatasource of enabledDatasources) {
1887+
const datasource = agentDatasource.datasource
1888+
showMessage(`正在初始化数据源: ${datasource.name}...`, 'info')
1889+
1890+
// 获取数据源的所有表
1891+
const tablesResponse = await fetch(`/api/agent/${agent.id}/schema/datasources/${datasource.id}/tables`)
1892+
if (!tablesResponse.ok) {
1893+
console.warn(`获取数据源 ${datasource.name} 的表列表失败`)
1894+
continue
1895+
}
1896+
1897+
const tablesResult = await tablesResponse.json()
1898+
if (!tablesResult.success || !tablesResult.data) {
1899+
console.warn(`数据源 ${datasource.name} 没有可用的表`)
1900+
continue
1901+
}
1902+
1903+
// 使用正常的 agentId 初始化 schema
1904+
const initResponse = await fetch(`/api/agent/${agent.id}/schema/init`, {
1905+
method: 'POST',
1906+
headers: {
1907+
'Content-Type': 'application/json'
1908+
},
1909+
body: JSON.stringify({
1910+
datasourceId: datasource.id,
1911+
tables: tablesResult.data // 使用所有表
1912+
})
1913+
})
1914+
1915+
if (!initResponse.ok) {
1916+
console.warn(`数据源 ${datasource.name} 初始化失败`)
1917+
continue
1918+
}
1919+
1920+
const initResult = await initResponse.json()
1921+
if (!initResult.success) {
1922+
console.warn(`数据源 ${datasource.name} 初始化失败: ${initResult.message}`)
1923+
continue
1924+
}
1925+
}
1926+
1927+
// 4. 发布成功
1928+
showMessage('智能体发布成功!所有配置的数据源已完成初始化', 'success')
1929+
1930+
// 可以在这里更新智能体状态为已发布
1931+
// await updateAgentStatus('published')
1932+
1933+
} catch (error) {
1934+
console.error('发布智能体失败:', error)
1935+
showMessage(`发布失败: ${error.message}`, 'error')
1936+
} finally {
1937+
isPublishing.value = false
1938+
}
1939+
}
18491940
18501941
const getMessageIcon = (type) => {
18511942
const iconMap = {
@@ -2175,6 +2266,9 @@ export default {
21752266
showMessage,
21762267
hideMessage,
21772268
getMessageIcon,
2269+
// 发布相关
2270+
publishAgent,
2271+
isPublishing,
21782272
// 预设问题方法
21792273
presetQuestions,
21802274
addPresetQuestion,
@@ -2508,6 +2602,58 @@ html {
25082602
flex: 1;
25092603
}
25102604
2605+
.agent-actions {
2606+
display: flex;
2607+
align-items: center;
2608+
gap: 12px;
2609+
}
2610+
2611+
.btn-publish {
2612+
padding: 10px 20px;
2613+
background: linear-gradient(135deg, #52c41a, #73d13d);
2614+
color: white;
2615+
border: none;
2616+
border-radius: 6px;
2617+
font-size: 14px;
2618+
font-weight: 500;
2619+
cursor: pointer;
2620+
display: flex;
2621+
align-items: center;
2622+
gap: 6px;
2623+
transition: all 0.3s ease;
2624+
box-shadow: 0 2px 8px rgba(82, 196, 26, 0.25);
2625+
}
2626+
2627+
.btn-publish:hover:not(:disabled) {
2628+
background: linear-gradient(135deg, #389e0d, #52c41a);
2629+
transform: translateY(-1px);
2630+
box-shadow: 0 4px 12px rgba(82, 196, 26, 0.35);
2631+
}
2632+
2633+
.btn-publish:disabled {
2634+
opacity: 0.6;
2635+
cursor: not-allowed;
2636+
transform: none;
2637+
}
2638+
2639+
.btn-publish.loading {
2640+
pointer-events: none;
2641+
}
2642+
2643+
.btn-publish .spinner {
2644+
width: 14px;
2645+
height: 14px;
2646+
border: 2px solid rgba(255, 255, 255, 0.3);
2647+
border-top: 2px solid white;
2648+
border-radius: 50%;
2649+
animation: spin 1s linear infinite;
2650+
}
2651+
2652+
@keyframes spin {
2653+
0% { transform: rotate(0deg); }
2654+
100% { transform: rotate(360deg); }
2655+
}
2656+
25112657
.agent-avatar .avatar-icon {
25122658
width: 64px;
25132659
height: 64px;

0 commit comments

Comments
 (0)