From 0de22fa7e1099be4cb774274298a1dfd29e99661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?cls=5F=E5=AE=81=E6=B3=A2=E6=9C=AC=E6=9C=BA?= <908705107@qq.com> Date: Tue, 9 Jun 2026 22:02:10 +0800 Subject: [PATCH] Restore full AI platform interactions --- .../agent/components/AgentChatPanel.vue | 110 +++- .../ai-platform/knowledge/detail/index.vue | 11 +- .../views/ai-platform/workflow-runs/data.ts | 9 +- .../views/ai-platform/workflow-runs/index.vue | 3 + .../workflow/editor/components/ChatPanel.vue | 318 ++++++++++- .../editor/components/NodeResultCard.vue | 2 +- .../workflow/editor/components/Panel.vue | 9 +- .../workflow/editor/components/RunPanel.vue | 10 +- .../editor/components/VariableSelector.vue | 526 ++++++++++++++++-- .../ai-platform/workflow/editor/index.vue | 23 +- .../workflow/editor/nodes/BaseNode.vue | 4 +- .../workflow/editor/nodes/SubflowNode.vue | 2 +- .../workflow/editor/panels/IntentPanel.vue | 2 +- .../workflow/editor/panels/StartPanel.vue | 41 +- .../workflow/shared/workflowNodeTypes.ts | 39 ++ 15 files changed, 1014 insertions(+), 95 deletions(-) diff --git a/web/apps/web-ele/src/views/ai-platform/agent/components/AgentChatPanel.vue b/web/apps/web-ele/src/views/ai-platform/agent/components/AgentChatPanel.vue index 3dd7b74..91fc316 100644 --- a/web/apps/web-ele/src/views/ai-platform/agent/components/AgentChatPanel.vue +++ b/web/apps/web-ele/src/views/ai-platform/agent/components/AgentChatPanel.vue @@ -23,7 +23,7 @@ import { sendAgentMessageStream, } from '#/api/ai-platform/ai-platform'; import { ChatBox } from '#/components/ChatBox/index'; -import { DesignEditorPanel } from '#/components/form-editor'; +import { AppDesignPanel, DesignEditorPanel } from '#/components/form-editor'; import AiWorkingAnimation from '../../../../components/ai-loading/AiWorkingAnimation.vue'; @@ -54,6 +54,7 @@ const emit = defineEmits<{ // 设计面板显示状态 const showDesignPanel = ref(false); +const showAppDesignPanel = ref(false); // 对话状态 const chatMessages = ref([]); @@ -71,9 +72,17 @@ const waitingConfig = ref(null); // 设计面板状态 const currentDesign = ref(null); + +// 应用设计面板状态 +const currentAppDesign = ref(null); @@ -273,7 +282,7 @@ async function doSendMessage(message: string, addUserMessage: boolean = true) { scrollToBottom(); // 发送流式请求 - // 业务上下文由 API 层按 Agent 配置解析 + // 系统变量(application_id 等)由 API 层自动注入 cancelStream = sendAgentMessageStream( props.agentId, { @@ -484,17 +493,31 @@ function handleStreamEvent( if (configData?.type === 'design_preview') { const previewType = configData.preview_type; - currentDesign.value = { - type: previewType, - title: - configData.title || - $t('ai-platform.agent.chatPanel.designPreview'), - data: configData.data || {}, - nodeId: event.node_id || '', - data_sources: configData.data_sources || configData.table_configs || [], - schema_fields: configData.schema_fields || configData.form_fields || [], - }; - showDesignPanel.value = true; + // 应用设计方案使用 AppDesignPanel(富文本编辑器) + if (previewType === 'app_design') { + currentAppDesign.value = { + type: previewType, + title: + configData.title || + $t('ai-platform.agent.chatPanel.appDesignTitle'), + data: configData.data || {}, + nodeId: event.node_id || '', + }; + showAppDesignPanel.value = true; + } else { + // 其他设计类型使用 DesignEditorPanel(表单编辑器) + currentDesign.value = { + type: previewType, + title: + configData.title || + $t('ai-platform.agent.chatPanel.designPreview'), + data: configData.data || {}, + nodeId: event.node_id || '', + form_fields: configData.form_fields || [], + table_configs: configData.table_configs || [], + }; + showDesignPanel.value = true; + } // 显示提示消息 const waitingContent = `**${configData.title}**\n\n${configData.message || $t('ai-platform.agent.chatPanel.designPanelHint')}`; @@ -772,6 +795,46 @@ function handleDesignCancel() { currentDesign.value = null; } +// 应用设计面板确认 +function handleAppDesignConfirm(data: Record) { + showAppDesignPanel.value = false; + + // 添加用户确认消息 + const userMsg: AgentMessage = { + id: generateId(), + role: 'user', + content: $t('ai-platform.agent.chatPanel.confirmAppDesign'), + status: 'completed', + reasoning_steps: [], + tool_calls: [], + prompt_tokens: 0, + completion_tokens: 0, + total_tokens: 0, + elapsed_time: 0, + error_message: '', + feedback: '', + created_at: new Date().toISOString(), + }; + chatMessages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + currentAppDesign.value = null; + + // 继续工作流,传递编辑后的数据 + doSendMessage(JSON.stringify(data), false); +} + +// 应用设计面板取消 +function handleAppDesignCancel() { + showAppDesignPanel.value = false; + waitingForInput.value = false; + waitingConfig.value = null; + currentAppDesign.value = null; +} + +// 暴露方法给父组件 defineExpose({ clearChat, scrollToBottom, @@ -838,13 +901,26 @@ onUnmounted(() => { title: currentDesign.title, data: currentDesign.data, nodeId: currentDesign.nodeId, - data_sources: currentDesign.data_sources, - schema_fields: currentDesign.schema_fields, + form_fields: currentDesign.form_fields, + table_configs: currentDesign.table_configs, }" @confirm="handleDesignConfirm" @close="handleDesignCancel" /> + +
+ +
diff --git a/web/apps/web-ele/src/views/ai-platform/knowledge/detail/index.vue b/web/apps/web-ele/src/views/ai-platform/knowledge/detail/index.vue index 8fa5837..4ba1fd0 100644 --- a/web/apps/web-ele/src/views/ai-platform/knowledge/detail/index.vue +++ b/web/apps/web-ele/src/views/ai-platform/knowledge/detail/index.vue @@ -291,12 +291,9 @@ async function handlePreviewDoc(doc: KnowledgeDocumentListItem) { docPreviewUrlList.value = [url]; docPreviewVisible.value = true; } else { - try { - const url = await getFileUrl(doc.file_id); - window.open(url, '_blank'); - } catch { - ElMessage.error($t('ai-platform.knowledge.chunkPreview.error')); - } + const ext = getDocFileExt(doc); + const query = new URLSearchParams({ name: doc.name || '', ext }); + window.open(`/file-preview/${doc.file_id}?${query.toString()}`, '_blank'); } } @@ -870,7 +867,7 @@ async function handleSaveSettings() { } function handleBack() { - router.push(appContextStore.getContextPath('/ai-platform/knowledge-base')); + router.push(appContextStore.getContextPath('/ai-platform/knowledge')); } // Tab 切换时加载数据 diff --git a/web/apps/web-ele/src/views/ai-platform/workflow-runs/data.ts b/web/apps/web-ele/src/views/ai-platform/workflow-runs/data.ts index 400946b..2117547 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow-runs/data.ts +++ b/web/apps/web-ele/src/views/ai-platform/workflow-runs/data.ts @@ -5,6 +5,7 @@ import type { VbenFormSchema } from '#/adapter/form'; import { $t } from '@vben/locales'; import { getWorkflowListApi } from '#/api/ai-platform/ai-platform'; +import { useAppContextStore } from '#/store/app-context'; type TagType = 'danger' | 'info' | 'primary' | 'success' | 'warning'; @@ -51,6 +52,8 @@ export function formatTime(value?: string) { } export function useSearchFormSchema(): VbenFormSchema[] { + const appContextStore = useAppContextStore(); + return [ { component: 'ApiSelect', @@ -58,7 +61,11 @@ export function useSearchFormSchema(): VbenFormSchema[] { label: $t('ai-platform.workflowRuns.filters.workflow'), componentProps: { api: async () => { - const res = await getWorkflowListApi({ page: 1, pageSize: 200 }); + const res = await getWorkflowListApi({ + page: 1, + pageSize: 200, + applicationId: appContextStore.currentApp?.id, + }); return (res.items || []).map((item) => ({ label: item.name, value: item.id, diff --git a/web/apps/web-ele/src/views/ai-platform/workflow-runs/index.vue b/web/apps/web-ele/src/views/ai-platform/workflow-runs/index.vue index 29bbc6d..70448a2 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow-runs/index.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow-runs/index.vue @@ -11,6 +11,7 @@ import { ElButton, ElTag } from 'element-plus'; import { getAllWorkflowRunsApi } from '#/api/ai-platform/ai-platform'; import { useZqTable } from '#/components/zq-table'; +import { useAppContextStore } from '#/store/app-context'; import RunStatusTag from './components/RunStatusTag.vue'; import { @@ -26,6 +27,7 @@ import DetailDialog from './modules/detail-dialog.vue'; defineOptions({ name: 'WorkflowRunHistory' }); +const appContextStore = useAppContextStore(); const detailRef = ref>(); const triggerOptions = getTriggerOptions(); @@ -36,6 +38,7 @@ const fetchRunList = async (params: any) => { workflowId: params.form?.workflowId || undefined, status: params.form?.status || undefined, triggerType: params.form?.triggerType || undefined, + applicationId: appContextStore.currentApp?.id, }); return { items: res.items, diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/ChatPanel.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/ChatPanel.vue index 9c91f9c..3574803 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/ChatPanel.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/ChatPanel.vue @@ -2,13 +2,18 @@ import type { WorkflowStreamEvent } from '#/api/ai-platform/ai-platform'; import type { ChatMessage, ReasoningStep } from '#/components/ChatBox/index'; import type { + AppDesignData, + AppSettingsData, + DashboardBasicInfoData, + DashboardDesignData, + DashboardPublishData, DesignData, SystemSummaryData, } from '#/components/form-editor'; import { computed, onUnmounted, ref, watch } from 'vue'; -import { Close, Setting } from '@element-plus/icons-vue'; +import { Settings2, X } from '@vben/icons'; import { $t } from '@vben/locales'; import { @@ -26,6 +31,11 @@ import { } from '#/api/ai-platform/ai-platform'; import { ChatBox } from '#/components/ChatBox/index'; import { + AppDesignPanel, + AppSettingsPanel, + DashboardBasicInfoConfirmPanel, + DashboardDesignConfirmPanel, + DashboardPublishConfirmPanel, DesignEditorPanel, SystemSummaryConfirmPanel, } from '#/components/form-editor'; @@ -64,6 +74,30 @@ const currentRunId = ref(''); const showDesignPanel = ref(false); const currentDesign = ref(undefined); +// 应用设计面板状态 +const showAppDesignPanel = ref(false); +const currentAppDesign = ref(undefined); + +// 应用设置面板状态 +const showAppSettingsPanel = ref(false); +const currentAppSettings = ref(undefined); + +// 仪表盘基础信息面板状态 +const showDashboardBasicInfoPanel = ref(false); +const currentDashboardBasicInfo = ref( + undefined, +); + +// 仪表盘设计面板状态 +const showDashboardDesignPanel = ref(false); +const currentDashboardDesign = ref(undefined); + +// 仪表盘发布面板状态 +const showDashboardPublishPanel = ref(false); +const currentDashboardPublish = ref( + undefined, +); + // 系统总结面板状态 const showSystemSummaryPanel = ref(false); const currentSystemSummary = ref(undefined); @@ -215,7 +249,7 @@ const runWorkflow = (userMessage: string, inputs: Record) => { running.value = true; // 流式运行(编辑器调试模式,使用草稿版本) - // 业务上下文由 API 层按 Workflow 配置解析 + // 系统变量(application_id 等)由 API 层自动注入 cancelStream = runWorkflowStreamApi( props.workflowId, inputs, @@ -566,6 +600,84 @@ const handleStreamEvent = (event: WorkflowStreamEvent, msgId: string) => { if (configData?.type === 'design_preview') { // 检查是否是应用设计类型 switch (configData.preview_type) { + case 'app_design': { + // 应用设计:打开专用的应用设计面板 + currentAppDesign.value = { + type: 'app_design', + title: + configData.title || + $t('ai-platform.workflow.editor.chatPanel.appDesignTitle'), + data: configData.data || {}, + nodeId: event.node_id || '', + }; + showAppDesignPanel.value = true; + + break; + } + case 'app_settings': { + // 应用设置:打开专用的应用设置面板 + currentAppSettings.value = { + type: 'app_settings', + title: + configData.title || + $t('ai-platform.workflow.editor.chatPanel.appSettingsTitle'), + data: configData.data || {}, + nodeId: event.node_id || '', + layoutOptions: configData.layoutOptions || [], + themeOptions: configData.themeOptions || [], + }; + showAppSettingsPanel.value = true; + + break; + } + case 'dashboard_basic_info': { + // 仪表盘基础信息:打开专用面板(在聊天框右侧) + currentDashboardBasicInfo.value = { + type: 'dashboard_basic_info', + title: + configData.title || + $t( + 'ai-platform.workflow.editor.chatPanel.dashboardBasicInfoTitle', + ), + data: configData.data || {}, + nodeId: event.node_id || '', + }; + showDashboardBasicInfoPanel.value = true; + + break; + } + case 'dashboard_design': { + // 仪表盘设计:打开设计器面板(在聊天框右侧) + currentDashboardDesign.value = { + type: 'dashboard_design', + title: + configData.title || + $t( + 'ai-platform.workflow.editor.chatPanel.dashboardDesignTitle', + ), + data: configData.data || {}, + nodeId: event.node_id || '', + }; + showDashboardDesignPanel.value = true; + + break; + } + case 'dashboard_publish': { + // 仪表盘发布:打开发布确认面板(在聊天框右侧) + currentDashboardPublish.value = { + type: 'dashboard_publish', + title: + configData.title || + $t( + 'ai-platform.workflow.editor.chatPanel.dashboardPublishTitle', + ), + data: configData.data || {}, + nodeId: event.node_id || '', + }; + showDashboardPublishPanel.value = true; + + break; + } case 'system_summary': { // 系统总结:打开总结展示面板 currentSystemSummary.value = { @@ -589,10 +701,8 @@ const handleStreamEvent = (event: WorkflowStreamEvent, msgId: string) => { $t('ai-platform.workflow.editor.chatPanel.designPreviewTitle'), data: configData.data || {}, nodeId: event.node_id || '', - data_sources: - configData.data_sources || configData.table_configs || [], - schema_fields: - configData.schema_fields || configData.form_fields || [], + form_fields: configData.form_fields || [], // 传递表单字段列表(用于列表设计) + table_configs: configData.table_configs || [], // 传递数据表配置(用于表单设计) }; showDesignPanel.value = true; } @@ -869,6 +979,153 @@ const handleDesignClose = () => { }; // 处理应用设计确认 +const handleAppDesignConfirm = (data: Record) => { + showAppDesignPanel.value = false; + currentAppDesign.value = undefined; + + // 添加用户确认消息 + const userMsg: ChatMessage = { + id: generateId(), + role: 'user', + content: $t('ai-platform.workflow.editor.chatPanel.confirmAppDesign'), + timestamp: new Date(), + }; + messages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + + // 恢复工作流,传递编辑后的数据 + resumeWorkflow(JSON.stringify(data)); +}; + +// 处理应用设计面板关闭 +const handleAppDesignClose = () => { + showAppDesignPanel.value = false; + currentAppDesign.value = undefined; +}; + +// 处理应用设置确认 +const handleAppSettingsConfirm = (data: Record) => { + showAppSettingsPanel.value = false; + currentAppSettings.value = undefined; + + // 添加用户确认消息 + const userMsg: ChatMessage = { + id: generateId(), + role: 'user', + content: $t('ai-platform.workflow.editor.chatPanel.confirmAppSettings'), + timestamp: new Date(), + }; + messages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + + // 恢复工作流,传递编辑后的数据 + resumeWorkflow(JSON.stringify(data)); +}; + +// 处理应用设置面板关闭 +const handleAppSettingsClose = () => { + showAppSettingsPanel.value = false; + currentAppSettings.value = undefined; +}; + +// 处理仪表盘基础信息确认 +const handleDashboardBasicInfoConfirm = (data: Record) => { + showDashboardBasicInfoPanel.value = false; + currentDashboardBasicInfo.value = undefined; + + // 添加用户确认消息 + const userMsg: ChatMessage = { + id: generateId(), + role: 'user', + content: $t( + 'ai-platform.workflow.editor.chatPanel.confirmDashboardBasicInfo', + ), + timestamp: new Date(), + }; + messages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + + // 恢复工作流,传递编辑后的数据 + resumeWorkflow(JSON.stringify(data)); +}; + +// 处理仪表盘基础信息面板关闭 +const handleDashboardBasicInfoClose = () => { + showDashboardBasicInfoPanel.value = false; + currentDashboardBasicInfo.value = undefined; +}; + +// 处理仪表盘设计确认 +const handleDashboardDesignConfirm = (data: Record) => { + showDashboardDesignPanel.value = false; + currentDashboardDesign.value = undefined; + + // 添加用户确认消息 + const userMsg: ChatMessage = { + id: generateId(), + role: 'user', + content: $t('ai-platform.workflow.editor.chatPanel.confirmDashboardDesign'), + timestamp: new Date(), + }; + messages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + + // 恢复工作流,传递编辑后的数据 + resumeWorkflow(JSON.stringify(data)); +}; + +// 处理仪表盘设计面板关闭 +const handleDashboardDesignClose = () => { + showDashboardDesignPanel.value = false; + currentDashboardDesign.value = undefined; +}; + +// 处理仪表盘发布确认 +const handleDashboardPublishConfirm = (data: Record) => { + console.log('[ChatPanel] 接收到发布确认数据:', data); + showDashboardPublishPanel.value = false; + currentDashboardPublish.value = undefined; + + // 添加用户确认消息 + const userMsg: ChatMessage = { + id: generateId(), + role: 'user', + content: $t('ai-platform.workflow.editor.chatPanel.publishToMenu', { + name: data.menu_name, + }), + timestamp: new Date(), + }; + messages.value.push(userMsg); + + // 重置等待状态 + waitingForInput.value = false; + waitingConfig.value = null; + + // 恢复工作流,传递发布数据 + const userInputStr = JSON.stringify(data); + console.log('[ChatPanel] 传递给 resumeWorkflow 的数据:', userInputStr); + resumeWorkflow(userInputStr); +}; + +// 处理仪表盘发布面板关闭 +const handleDashboardPublishClose = () => { + showDashboardPublishPanel.value = false; + currentDashboardPublish.value = undefined; +}; + +// 处理系统总结确认 const handleSystemSummaryConfirm = (data: Record) => { showSystemSummaryPanel.value = false; currentSystemSummary.value = undefined; @@ -920,11 +1177,11 @@ onUnmounted(() => { - + @@ -1001,6 +1258,51 @@ onUnmounted(() => { /> + + + + + + + + + + + + + + + { v-if="displayResult.tokens_used" class="text-muted-foreground text-sm" > - 消耗 Token:{{ displayResult.tokens_used }} + Tokens: {{ displayResult.tokens_used }}
diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/Panel.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/Panel.vue index 8821629..63469e5 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/Panel.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/Panel.vue @@ -54,6 +54,7 @@ const components: Record = { ), // 循环节点 loop: defineAsyncComponent(() => import('../panels/LoopPanel.vue')), + // 表单节点 form_basic_info: defineAsyncComponent( () => import('../panels/FormBasicInfoPanel.vue'), ), @@ -75,6 +76,7 @@ const components: Record = { form_publish: defineAsyncComponent( () => import('../panels/FormPublishPanel.vue'), ), + // 应用节点 app_create: defineAsyncComponent( () => import('../panels/AppCreatePanel.vue'), ), @@ -87,6 +89,7 @@ const components: Record = { app_update: defineAsyncComponent( () => import('../panels/AppUpdatePanel.vue'), ), + // 仪表盘节点 dashboard_basic_info: defineAsyncComponent( () => import('../panels/DashboardBasicInfoPanel.vue'), ), @@ -99,9 +102,13 @@ const components: Record = { dashboard_publish: defineAsyncComponent( () => import('../panels/DashboardPublishPanel.vue'), ), + // 系统总结节点 system_summary: defineAsyncComponent( () => import('../panels/SystemSummaryPanel.vue'), ), + // 子流程节点 + subflow: defineAsyncComponent(() => import('../panels/SubflowPanel.vue')), + // 表单数据节点 form_data_create: defineAsyncComponent( () => import('../panels/FormDataPanel.vue'), ), @@ -120,8 +127,6 @@ const components: Record = { form_schema_to_llm: defineAsyncComponent( () => import('../panels/FormDataPanel.vue'), ), - // 子流程节点 - subflow: defineAsyncComponent(() => import('../panels/SubflowPanel.vue')), // Text-to-SQL 节点 text_to_sql: defineAsyncComponent( () => import('../panels/TextToSqlPanel.vue'), diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/RunPanel.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/RunPanel.vue index 69b0a19..9381e21 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/RunPanel.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/components/RunPanel.vue @@ -90,7 +90,7 @@ const totalStats = computed(() => { (sum, s) => sum + (s.elapsed_time || 0), 0, ); - const totalTokenCount = completed.reduce( + const totalTokens = completed.reduce( (sum, s) => sum + (s.tokens_used || 0), 0, ); @@ -101,7 +101,7 @@ const totalStats = computed(() => { failed: states.filter((s) => s.status === 'failed').length, running: states.filter((s) => s.status === 'running').length, totalTime, - totalTokenCount, + totalTokens, }; }); @@ -547,8 +547,8 @@ const handleStop = () => { {{ totalStats.completed }}/{{ totalStats.total }} {{ $t('ai-platform.workflow.editor.runPanel.nodes') }} - - 消耗 Token:{{ totalStats.totalTokenCount }} + + {{ totalStats.totalTokens }} tokens {{ formatTime(totalStats.totalTime) }} @@ -631,7 +631,7 @@ const handleStop = () => { class="mt-1 pl-5" > - 消耗 Token:{{ state.tokens_used }} + {{ state.tokens_used }} tokens >(new Set()); // 定义不同节点的图标 const icons: any = { - start: VideoPlay, - llm: MagicStick, - http: Link, - code: Cpu, - template: Document, - end: Finished, - db_query: Coin, - db_insert: Coin, - db_update: Coin, - db_delete: Coin, - db_sql: Coin, - question: Help, - choice: Operation, - message: ChatLineRound, - confirm: Check, - snowflake_cortex_llm: DataAnalysis, - snowflake_cortex_analyst: DataAnalysis, - loop: Switch, - merge: Connection, - subflow: Guide, - knowledge_retrieval: Collection, + start: Play, + llm: Bot, + http: Globe, + code: Code, + template: LayoutTemplate, + end: Square, + db_query: Database, + db_insert: Database, + db_update: Database, + db_delete: Database, + db_sql: Database, + // 对话流节点 + question: HelpCircle, + choice: ListChecks, + message: MessageSquareText, + confirm: CircleHelp, + // Snowflake Cortex 节点 + snowflake_cortex_llm: Snowflake, + snowflake_cortex_analyst: Snowflake, + // 循环节点 + loop: Play, + // 合并节点 + merge: Combine, + // 表单节点 + form_basic_info: FileText, + form_database_design: Database, + form_database_create: Database, + // 应用节点 + app_create: AppWindow, + app_design: LayoutDashboard, + app_settings: LayoutDashboard, + app_update: LayoutDashboard, + // 仪表盘节点 + dashboard_basic_info: LayoutDashboard, + dashboard_design: LayoutDashboard, + dashboard_create: LayoutDashboard, + dashboard_publish: LayoutDashboard, + // 系统总结节点 + system_summary: ClipboardCheck, + // 子流程节点 + subflow: Play, + // 知识库检索节点 + knowledge_retrieval: BookOpen, }; +// 获取当前节点的父循环节点(如果存在) const getParentLoopNode = (nodeId: string) => { const currentNode = nodes.value.find((n) => n.id === nodeId); if (currentNode?.parentNode) { @@ -114,6 +139,92 @@ const availableNodes = computed(() => { // 根据节点类型获取输出变量 schema switch (node.type) { + case 'app_create': { + variables = [ + { + key: 'app_id', + label: $t('ai-platform.workflow.editor.variableSelector.appId'), + }, + { + key: 'app_code', + label: $t('ai-platform.workflow.editor.variableSelector.appCode'), + }, + { + key: 'app_name', + label: $t('ai-platform.workflow.editor.variableSelector.appName'), + }, + { + key: 'success', + label: $t( + 'ai-platform.workflow.editor.variableSelector.createSuccess', + ), + }, + ]; + break; + } + case 'app_design': { + variables = [ + { + key: 'design_content', + label: $t( + 'ai-platform.workflow.editor.variableSelector.designContent', + ), + }, + { + key: 'design_title', + label: $t( + 'ai-platform.workflow.editor.variableSelector.designTitle', + ), + }, + { + key: 'confirmed', + label: $t( + 'ai-platform.workflow.editor.variableSelector.isConfirmed', + ), + }, + ]; + break; + } + case 'app_settings': { + variables = [ + { + key: 'settings', + label: $t( + 'ai-platform.workflow.editor.variableSelector.appSettings', + ), + }, + { + key: 'confirmed', + label: $t( + 'ai-platform.workflow.editor.variableSelector.isConfirmed', + ), + }, + ]; + break; + } + case 'app_update': { + variables = [ + { + key: 'update_success', + label: $t( + 'ai-platform.workflow.editor.variableSelector.updateSuccess', + ), + }, + { + key: 'config_id', + label: $t( + 'ai-platform.workflow.editor.variableSelector.configId', + ), + }, + { + key: 'update_message', + label: $t( + 'ai-platform.workflow.editor.variableSelector.updateMessage', + ), + }, + ]; + break; + } case 'choice': { const choiceVar = node.data.variable_name || 'user_choice'; variables = [ @@ -169,6 +280,96 @@ const availableNodes = computed(() => { ]; break; } + case 'dashboard_basic_info': { + variables = [ + { + key: 'dashboard_basic_info', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dashboardBasicInfo', + ), + }, + { + key: 'dashboard_name', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dashboardName', + ), + }, + { + key: 'dashboard_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dashboardCode', + ), + }, + ]; + break; + } + case 'dashboard_create': { + variables = [ + { + key: 'dashboard_id', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dashboardId', + ), + }, + { + key: 'dashboard_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dashboardCode', + ), + }, + { + key: 'page_meta', + label: $t( + 'ai-platform.workflow.editor.variableSelector.pageMeta', + ), + }, + ]; + break; + } + case 'dashboard_design': { + variables = [ + { + key: 'page_config', + label: $t( + 'ai-platform.workflow.editor.variableSelector.pageConfig', + ), + }, + { + key: 'design_title', + label: $t( + 'ai-platform.workflow.editor.variableSelector.designTitle', + ), + }, + { + key: 'confirmed', + label: $t( + 'ai-platform.workflow.editor.variableSelector.isConfirmed', + ), + }, + ]; + break; + } + case 'dashboard_publish': { + variables = [ + { + key: 'menu_id', + label: $t('ai-platform.workflow.editor.variableSelector.menuId'), + }, + { + key: 'route_path', + label: $t( + 'ai-platform.workflow.editor.variableSelector.routePath', + ), + }, + { + key: 'publish_result', + label: $t( + 'ai-platform.workflow.editor.variableSelector.publishResult', + ), + }, + ]; + break; + } case 'db_delete': { const deleteOutputVar = node.data.output_variable || 'delete_result'; variables = [ @@ -259,6 +460,205 @@ const availableNodes = computed(() => { ]; break; } + case 'form_basic_info': { + variables = [ + { + key: 'form_basic_info', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formBasicInfoObj', + ), + }, + { + key: 'form_name', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formName', + ), + }, + { + key: 'form_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formCode', + ), + }, + { + key: 'form_type', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formType', + ), + }, + { + key: 'form_description', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formDescription', + ), + }, + { + key: 'form_sort', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formSort', + ), + }, + ]; + break; + } + case 'form_create': { + variables = [ + { + key: 'form_id', + label: $t('ai-platform.workflow.editor.variableSelector.formId'), + }, + { + key: 'form_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formCode', + ), + }, + { + key: 'form_meta', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formMeta', + ), + }, + ]; + break; + } + case 'form_database_create': { + variables = [ + { + key: 'creation_result', + label: $t( + 'ai-platform.workflow.editor.variableSelector.creationResult', + ), + }, + { + key: 'all_tables_ready', + label: $t( + 'ai-platform.workflow.editor.variableSelector.allTablesReady', + ), + }, + { + key: 'created_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.createdCount', + ), + }, + { + key: 'error_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.errorCount', + ), + }, + { + key: 'schema_name', + label: $t( + 'ai-platform.workflow.editor.variableSelector.schemaName', + ), + }, + { + key: 'table_name', + label: $t( + 'ai-platform.workflow.editor.variableSelector.tableName', + ), + }, + ]; + break; + } + case 'form_database_design': { + variables = [ + { + key: 'database_design', + label: $t( + 'ai-platform.workflow.editor.variableSelector.dbDesignObj', + ), + }, + { + key: 'table_name', + label: $t( + 'ai-platform.workflow.editor.variableSelector.tableName', + ), + }, + { + key: 'field_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.fieldCount', + ), + }, + ]; + break; + } + case 'form_list_design': { + variables = [ + { + key: 'list_config', + label: $t( + 'ai-platform.workflow.editor.variableSelector.listConfig', + ), + }, + { + key: 'query_field_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.queryFieldCount', + ), + }, + { + key: 'column_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.columnCount', + ), + }, + ]; + break; + } + case 'form_publish': { + variables = [ + { + key: 'menu_id', + label: $t('ai-platform.workflow.editor.variableSelector.menuId'), + }, + { + key: 'route_path', + label: $t( + 'ai-platform.workflow.editor.variableSelector.routePath', + ), + }, + { + key: 'publish_result', + label: $t( + 'ai-platform.workflow.editor.variableSelector.publishResult', + ), + }, + ]; + break; + } + case 'form_ui_design': { + variables = [ + { + key: 'form_ui_design', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formUiDesign', + ), + }, + { + key: 'form_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formCode', + ), + }, + { + key: 'field_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.fieldCount', + ), + }, + { + key: 'group_count', + label: $t( + 'ai-platform.workflow.editor.variableSelector.groupCount', + ), + }, + ]; + break; + } case 'http': { variables = [ { @@ -485,6 +885,23 @@ const availableNodes = computed(() => { ), isSystem: true, }, + { + key: 'application_id', + label: $t('ai-platform.workflow.editor.variableSelector.appId'), + isSystem: true, + }, + { + key: 'application_code', + label: $t('ai-platform.workflow.editor.variableSelector.appCode'), + isSystem: true, + }, + { + key: 'form_code', + label: $t( + 'ai-platform.workflow.editor.variableSelector.formCode', + ), + isSystem: true, + }, ]; // 加上自定义变量 variables.push( @@ -548,6 +965,33 @@ const availableNodes = computed(() => { } break; } + case 'system_summary': { + variables = [ + { + key: 'summary', + label: $t( + 'ai-platform.workflow.editor.variableSelector.summaryData', + ), + }, + { + key: 'total_forms', + label: $t( + 'ai-platform.workflow.editor.variableSelector.totalForms', + ), + }, + { + key: 'has_app', + label: $t('ai-platform.workflow.editor.variableSelector.hasApp'), + }, + { + key: 'has_dashboard', + label: $t( + 'ai-platform.workflow.editor.variableSelector.hasDashboard', + ), + }, + ]; + break; + } case 'template': { const templateOutputVar = node.data.output_variable || 'template_result'; @@ -663,7 +1107,7 @@ const handleSelect = (nodeId: string, variable: string) => { @click="toggleNodeCollapse(node.id)" > = { // 循环节点图标 RefreshCw, CornerDownLeft, + // 表单节点图标 FileText, TableProperties, - LayoutDashboard, - Settings, - FilePlus, - Upload, - ClipboardCheck, - // 表单节点图标 Send, // 应用节点图标 + LayoutDashboard, + Settings, Save, // 仪表盘节点图标 + FilePlus, + Upload, // 系统总结节点图标 + ClipboardCheck, // 子流程节点图标 Workflow, // 知识库节点图标 @@ -736,8 +741,10 @@ const iconComponents: Record = { // 过滤后的节点分类 const filteredNodeCategories = computed(() => { + // 首先根据工作流类型过滤分类 let categories = nodeCategories.value; + // 如果是通用类型,排除表单设计、应用管理、仪表盘分组 if (workflow.value?.workflow_type === 'general') { const excludeNames = new Set([ $t('ai-platform.workflow.editor.categories.appManage'), diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/BaseNode.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/BaseNode.vue index b31152e..b995139 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/BaseNode.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/BaseNode.vue @@ -279,7 +279,7 @@ const nodeColorConfig = computed(() => { class="size-3" /> - 运行中... + Running... {{ executionStatus.elapsed_time }}ms
@@ -357,7 +357,7 @@ const nodeColorConfig = computed(() => { " ref="addButtonRef" class="bg-primary hover:bg-primary/90 absolute -right-8 top-1/2 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full text-white opacity-0 shadow-md transition-opacity hover:scale-110 group-hover:opacity-100" - title="添加下一个节点" + title="{{ $t('ai-platform.workflow.nodes.common.addNextNode') }}" @click.stop="handleClick" > diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/SubflowNode.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/SubflowNode.vue index f3a626e..d8b179b 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/SubflowNode.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/nodes/SubflowNode.vue @@ -173,7 +173,7 @@ watch( - 运行中... + Running... {{ executionStatus.elapsed_time }}ms diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/editor/panels/IntentPanel.vue b/web/apps/web-ele/src/views/ai-platform/workflow/editor/panels/IntentPanel.vue index 89fe87f..44489a3 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/editor/panels/IntentPanel.vue +++ b/web/apps/web-ele/src/views/ai-platform/workflow/editor/panels/IntentPanel.vue @@ -124,7 +124,7 @@ const removeExample = (intentIndex: number, exampleIndex: number) => { import { ref, watch } from 'vue'; -import { Delete as Trash2, Plus } from '@element-plus/icons-vue'; +import { Plus, Trash2 } from '@vben/icons'; import { $t } from '@vben/locales'; import { ElButton, ElForm, ElInput, ElOption, ElSelect } from 'element-plus'; @@ -50,6 +50,45 @@ const handleDelete = (index: number) => { + +
+
+ application_id + {{ + $t('ai-platform.workflow.panels.common.sysVar') + }} +
+
+ {{ $t('ai-platform.workflow.panels.start.appIdDesc') }} +
+
+ + +
+
+ application_code + {{ + $t('ai-platform.workflow.panels.common.sysVar') + }} +
+
+ {{ $t('ai-platform.workflow.panels.start.appCodeDesc') }} +
+
+ + +
+
+ form_code + {{ + $t('ai-platform.workflow.panels.common.sysVar') + }} +
+
+ {{ $t('ai-platform.workflow.panels.start.formCodeDesc') }} +
+
+
{{ $t('ai-platform.workflow.panels.common.customVars') diff --git a/web/apps/web-ele/src/views/ai-platform/workflow/shared/workflowNodeTypes.ts b/web/apps/web-ele/src/views/ai-platform/workflow/shared/workflowNodeTypes.ts index ffe2598..1bdfce5 100644 --- a/web/apps/web-ele/src/views/ai-platform/workflow/shared/workflowNodeTypes.ts +++ b/web/apps/web-ele/src/views/ai-platform/workflow/shared/workflowNodeTypes.ts @@ -1,16 +1,32 @@ import { markRaw } from 'vue'; import AddButtonEdge from '../editor/edges/AddButtonEdge.vue'; +import AppCreateNode from '../editor/nodes/AppCreateNode.vue'; +import AppDesignNode from '../editor/nodes/AppDesignNode.vue'; +import AppSettingsNode from '../editor/nodes/AppSettingsNode.vue'; +import AppUpdateNode from '../editor/nodes/AppUpdateNode.vue'; import ChoiceNode from '../editor/nodes/ChoiceNode.vue'; import CodeNode from '../editor/nodes/CodeNode.vue'; import ConditionNode from '../editor/nodes/ConditionNode.vue'; import ConfirmNode from '../editor/nodes/ConfirmNode.vue'; +import DashboardBasicInfoNode from '../editor/nodes/DashboardBasicInfoNode.vue'; +import DashboardCreateNode from '../editor/nodes/DashboardCreateNode.vue'; +import DashboardDesignNode from '../editor/nodes/DashboardDesignNode.vue'; +import DashboardPublishNode from '../editor/nodes/DashboardPublishNode.vue'; import DbDeleteNode from '../editor/nodes/DbDeleteNode.vue'; import DbInsertNode from '../editor/nodes/DbInsertNode.vue'; import DbQueryNode from '../editor/nodes/DbQueryNode.vue'; import DbSqlNode from '../editor/nodes/DbSqlNode.vue'; import DbUpdateNode from '../editor/nodes/DbUpdateNode.vue'; import EndNode from '../editor/nodes/EndNode.vue'; +import FormBasicInfoNode from '../editor/nodes/FormBasicInfoNode.vue'; +import FormCreateNode from '../editor/nodes/FormCreateNode.vue'; +import FormDatabaseCreateNode from '../editor/nodes/FormDatabaseCreateNode.vue'; +import FormDatabaseDesignNode from '../editor/nodes/FormDatabaseDesignNode.vue'; +import FormDataNode from '../editor/nodes/FormDataNode.vue'; +import FormListDesignNode from '../editor/nodes/FormListDesignNode.vue'; +import FormPublishNode from '../editor/nodes/FormPublishNode.vue'; +import FormUIDesignNode from '../editor/nodes/FormUIDesignNode.vue'; import HttpNode from '../editor/nodes/HttpNode.vue'; import IntentNode from '../editor/nodes/IntentNode.vue'; import KnowledgeRetrievalNode from '../editor/nodes/KnowledgeRetrievalNode.vue'; @@ -24,6 +40,7 @@ import SnowflakeCortexAnalystNode from '../editor/nodes/SnowflakeCortexAnalystNo import SnowflakeCortexLLMNode from '../editor/nodes/SnowflakeCortexLLMNode.vue'; import StartNode from '../editor/nodes/StartNode.vue'; import SubflowNode from '../editor/nodes/SubflowNode.vue'; +import SystemSummaryNode from '../editor/nodes/SystemSummaryNode.vue'; import TemplateNode from '../editor/nodes/TemplateNode.vue'; import TextToSqlNode from '../editor/nodes/TextToSqlNode.vue'; @@ -50,7 +67,29 @@ export const workflowNodeTypes = { snowflake_cortex_llm: markRaw(SnowflakeCortexLLMNode), snowflake_cortex_analyst: markRaw(SnowflakeCortexAnalystNode), loop: markRaw(LoopNode), + form_basic_info: markRaw(FormBasicInfoNode), + form_database_design: markRaw(FormDatabaseDesignNode), + form_database_create: markRaw(FormDatabaseCreateNode), + form_ui_design: markRaw(FormUIDesignNode), + form_list_design: markRaw(FormListDesignNode), + form_create: markRaw(FormCreateNode), + form_publish: markRaw(FormPublishNode), + app_create: markRaw(AppCreateNode), + app_design: markRaw(AppDesignNode), + app_settings: markRaw(AppSettingsNode), + app_update: markRaw(AppUpdateNode), + dashboard_basic_info: markRaw(DashboardBasicInfoNode), + dashboard_design: markRaw(DashboardDesignNode), + dashboard_create: markRaw(DashboardCreateNode), + dashboard_publish: markRaw(DashboardPublishNode), + system_summary: markRaw(SystemSummaryNode), subflow: markRaw(SubflowNode), + form_data_create: markRaw(FormDataNode), + form_data_read: markRaw(FormDataNode), + form_data_update: markRaw(FormDataNode), + form_data_delete: markRaw(FormDataNode), + form_data_list: markRaw(FormDataNode), + form_schema_to_llm: markRaw(FormDataNode), text_to_sql: markRaw(TextToSqlNode), knowledge_retrieval: markRaw(KnowledgeRetrievalNode), };