From 538e15347300cb59185cf248d7b2e8d59720b229 Mon Sep 17 00:00:00 2001 From: 2910410219 <2910410219@qq.com> Date: Fri, 29 May 2026 14:20:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=99=A8=E4=BB=A5=E6=94=AF=E6=8C=81=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E7=B1=BB=E5=9E=8B=EF=BC=8C=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=A0=8F=E4=BB=A5=E7=A7=BB=E9=99=A4=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E6=8C=87=E4=BB=A4=E5=92=8C=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E7=A9=BA=E9=97=B4=E5=8A=9F=E8=83=BD=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E9=A2=84=E8=A7=88=E5=92=8C=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=BB=A5=E5=A2=9E=E5=BC=BA=E8=8A=82=E7=82=B9=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=A4=84=E7=90=86=E7=9A=84=E5=8F=AF=E9=80=89=E6=80=A7?= =?UTF-8?q?=E5=92=8C=E5=AE=89=E5=85=A8=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/model/ModelSelector.vue | 25 +- src/views/home/components/InputBar.vue | 83 +----- src/views/home/components/Sidebar.vue | 267 +++++++++++++++++- .../workflow/component/NodeLibraryPanel.vue | 19 +- .../workflow/component/WorkflowListPanel.vue | 3 +- src/views/settings/workflow/index.vue | 66 +++-- 6 files changed, 356 insertions(+), 107 deletions(-) diff --git a/src/components/model/ModelSelector.vue b/src/components/model/ModelSelector.vue index e83de2e..a59faea 100644 --- a/src/components/model/ModelSelector.vue +++ b/src/components/model/ModelSelector.vue @@ -219,9 +219,28 @@ watch( const getModelTypeName = (type: number | string) => { const typeMap: Record = { - 1: '推理模型', - 2: '图片模型', - 3: '音频模型', + 100: '推理模型', + 200: '图片模型', + 201: '图片模型-文生图', + 202: '图片模型-图生图', + 203: '图片模型-图片编辑', + 204: '图片模型-图片变体', + 300: '音频模型', + 301: '音频模型-文生音', + 302: '音频模型-音生文', + 303: '音频模型-音生音', + 400: '向量化模型', + 401: '向量化模型-文本嵌入', + 402: '向量化模型-重排序', + 500: '全模态模型', + 501: '全模态模型-文图音', + 502: '全模态模型-视觉理解', + 600: '视频模型', + 601: '视频模型-文生视频', + 602: '视频模型-图生视频', + 603: '视频模型-图文生视频', + 604: '视频模型-视频生视频', + 605: '视频模型-视频编辑', }; return typeMap[Number(type)] || '未知类型'; }; diff --git a/src/views/home/components/InputBar.vue b/src/views/home/components/InputBar.vue index d1cdff8..57202c4 100644 --- a/src/views/home/components/InputBar.vue +++ b/src/views/home/components/InputBar.vue @@ -16,26 +16,6 @@ - - 快捷指令 - - - - 快捷回复 - - {{ currentSkillDisplay }} @@ -49,18 +29,6 @@ - - - {{ currentWorkflowDisplay }} - - -
@@ -84,7 +52,6 @@ interface Emits { const emit = defineEmits(); const message = ref(''); const selectedSkill = ref('default'); -const selectedWorkflow = ref('none'); const skillLabels: Record = { default: '选择技能', @@ -93,36 +60,12 @@ const skillLabels: Record = { writing: '内容写作', }; -const workflowLabels: Record = { - none: '选择工作流', - 'review-test': '审查+测试', - 'doc-then-code': '文档再编码', -}; - const currentSkillDisplay = computed(() => { return selectedSkill.value === 'default' ? '选择技能' : skillLabels[selectedSkill.value]; }); -const currentWorkflowDisplay = computed(() => { - return selectedWorkflow.value === 'none' - ? '选择工作流' - : workflowLabels[selectedWorkflow.value]; -}); - -const quickCommands: Record = { - rewrite: '请帮我润色下面这段内容,保持原意并提升表达质感:', - summary: '请总结我们当前对话的重点,并给出 3 条执行建议。', - todo: '请把当前需求拆解成可执行的 TODO 列表。', -}; - -const quickReplies: Record = { - ok: '收到,我马上处理。', - confirm: '这个方向可以,继续。', - adjust: '这个比例还要再调一下。', -}; - const skills: Record = { default: '', 'code-review': '[技能:代码审查] 请帮我审查下面这段代码,找出潜在问题并给出改进建议:\n', @@ -130,19 +73,12 @@ const skills: Record = { writing: '[技能:内容写作] 请根据下面的需求帮我创作内容:\n', }; -const workflows: Record = { - none: '', - 'review-test': '[工作流:审查+测试] 完成后请自动生成单元测试:\n', - 'doc-then-code': '[工作流:文档再编码] 请先编写接口文档,再实现代码:\n', -}; - const handleSend = (event?: KeyboardEvent) => { if (event) event.preventDefault(); const msg = message.value.trim(); if (!msg) return; const skillPrefix = skills[selectedSkill.value] || ''; - const workflowPrefix = workflows[selectedWorkflow.value] || ''; - const finalMessage = (skillPrefix + workflowPrefix + msg).trim(); + const finalMessage = (skillPrefix + msg).trim(); emit('send', finalMessage); message.value = ''; }; @@ -151,29 +87,12 @@ const handleAttachment = () => { ElMessage.info('附件上传功能开发中...'); }; -const handleCommandSelect = (key: string | number | object) => { - const k = String(key); - message.value = quickCommands[k] || message.value; -}; - -const handleReplySelect = (key: string | number | object) => { - const k = String(key); - message.value = quickReplies[k] || message.value; -}; - const handleSkillSelect = (key: string | number | object) => { selectedSkill.value = String(key); if (selectedSkill.value !== 'default') { ElMessage.success(`已选择技能:${skillLabels[selectedSkill.value]}`); } }; - -const handleWorkflowSelect = (key: string | number | object) => { - selectedWorkflow.value = String(key); - if (selectedWorkflow.value !== 'none') { - ElMessage.success(`已选择工作流:${workflowLabels[selectedWorkflow.value]}`); - } -}; diff --git a/src/views/settings/workflow/component/NodeLibraryPanel.vue b/src/views/settings/workflow/component/NodeLibraryPanel.vue index dea426e..6a1c551 100644 --- a/src/views/settings/workflow/component/NodeLibraryPanel.vue +++ b/src/views/settings/workflow/component/NodeLibraryPanel.vue @@ -120,6 +120,7 @@ const emit = defineEmits<{ margin-bottom: 8px; padding-bottom: 4px; border-bottom: 1px solid #e7ecf3; + padding-left: 2px; } .node-group-items { @@ -129,9 +130,10 @@ const emit = defineEmits<{ } .node-item { - justify-content: flex-start; + justify-content: flex-start !important; width: 100%; - padding: 8px 10px; + padding: 0 !important; + margin: 0 !important; color: #475569; border-radius: 6px; font-size: 13px; @@ -139,11 +141,24 @@ const emit = defineEmits<{ background: transparent; border: none; transition: all 0.15s ease; + text-align: left !important; + min-height: 34px; + height: auto !important; + display: block !important; &:hover { background: #f1f5f9; color: #1e293b; } + + :deep(.el-button__inner) { + width: 100%; + padding: 8px !important; + margin: 0 !important; + text-align: left !important; + justify-content: flex-start !important; + display: block !important; + } } } diff --git a/src/views/settings/workflow/component/WorkflowListPanel.vue b/src/views/settings/workflow/component/WorkflowListPanel.vue index 572af6c..7e585e4 100644 --- a/src/views/settings/workflow/component/WorkflowListPanel.vue +++ b/src/views/settings/workflow/component/WorkflowListPanel.vue @@ -5,7 +5,6 @@ - 新建
@@ -65,7 +64,6 @@ const currentList = computed(() => { flex-direction: column; box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06); border: 1px solid #e6eaf0; -} .panel-header { display: flex; @@ -188,4 +186,5 @@ const currentList = computed(() => { padding: 4px 8px; } } +} diff --git a/src/views/settings/workflow/index.vue b/src/views/settings/workflow/index.vue index 6ea3709..b3f0d85 100644 --- a/src/views/settings/workflow/index.vue +++ b/src/views/settings/workflow/index.vue @@ -126,7 +126,7 @@ interface ParamRef { label: string; } -const { addNodes, addEdges, findNode, removeNodes, getNodes } = useVueFlow(); +const { addNodes, addEdges, findNode, removeNodes, getNodes, updateNode } = useVueFlow(); // 常量定义 const START_NODE_CODE = '__start__'; @@ -254,6 +254,8 @@ const onNodeClick = (event: { node: Node }) => { const updateSelectedNode = (updatedNode: Node) => { selectedNode.value = updatedNode; + // 使用 VueFlow 的 API 更新节点,确保内部状态同步 + updateNode(updatedNode.id, updatedNode); // 同步更新到 nodes 数组 const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { @@ -284,29 +286,47 @@ const availableParams = computed(() => { const addParam = (param: ParamRef) => { if (!selectedNode.value?.data) return; - if (!selectedNode.value.data.inputSource) { - selectedNode.value.data.inputSource = []; - } + const updatedNode: Node = { + ...selectedNode.value, + data: { + ...selectedNode.value.data, + inputSource: selectedNode.value.data.inputSource || [], + }, + }; // 查找是否已存在该节点的引用 - const existingIndex = selectedNode.value.data.inputSource.findIndex((item) => item.nodeId === param.id); + const existingIndex = updatedNode.data.inputSource!.findIndex((item) => item.nodeId === param.id); if (existingIndex >= 0) { // 已存在,添加 output 到 field 数组 - const existing = selectedNode.value.data.inputSource[existingIndex]; + const existing = updatedNode.data.inputSource![existingIndex]; if (!existing.field.includes('output')) { existing.field.push('output'); + selectedNode.value = updatedNode; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); + const index = nodes.value.findIndex((n) => n.id === updatedNode.id); + if (index >= 0) { + nodes.value[index] = updatedNode; + } ElMessage.success('已添加参数引用'); } else { ElMessage.info('该参数已被引用'); } } else { // 不存在,创建新的引用 - selectedNode.value.data.inputSource.push({ + updatedNode.data.inputSource!.push({ nodeId: param.id, field: ['output'], quoteOutput: false, }); + selectedNode.value = updatedNode; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); + const index = nodes.value.findIndex((n) => n.id === updatedNode.id); + if (index >= 0) { + nodes.value[index] = updatedNode; + } ElMessage.success('已添加参数引用'); } }; @@ -330,6 +350,8 @@ const handleModelConfirm = (model: any) => { selectedNode.value = updatedNode; selectedModelData.value = model; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { @@ -353,6 +375,8 @@ const handleRemoveModel = () => { selectedNode.value = updatedNode; selectedModelData.value = null; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { @@ -376,6 +400,8 @@ const handleSkillConfirm = (skill: any) => { selectedNode.value = updatedNode; selectedSkillData.value = skill; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { @@ -399,6 +425,8 @@ const handleRemoveSkill = () => { selectedNode.value = updatedNode; selectedSkillData.value = null; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { @@ -436,6 +464,8 @@ const handleRemoveField = (nodeId: string, fieldName: string) => { }; selectedNode.value = updatedNode; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { nodes.value[index] = updatedNode; @@ -478,6 +508,8 @@ const handleToggleOutput = (nodeId: string, enabled: boolean) => { }; selectedNode.value = updatedNode; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { nodes.value[index] = updatedNode; @@ -534,6 +566,8 @@ const handleAddParamByValue = (paramValue: string) => { }; selectedNode.value = updatedNode; + // 同步更新到 VueFlow 内部状态 + updateNode(updatedNode.id, updatedNode); const index = nodes.value.findIndex((n) => n.id === updatedNode.id); if (index >= 0) { nodes.value[index] = updatedNode; @@ -652,15 +686,15 @@ const fetchWorkflowList = async () => { // 添加默认开始节点 const addDefaultStartNode = () => { - addNodes([ - { - id: 'start-node', - type: 'input', - position: { x: 200, y: 200 }, - data: { label: '开始', nodeCode: '__start__', inputSource: null }, - style: { background: '#10b981', color: '#fff', border: '2px solid #059669', borderRadius: '8px', padding: '10px 20px' }, - }, - ]); + const startNode = { + id: 'start-node', + type: 'input', + position: { x: 200, y: 200 }, + data: { label: '开始', nodeCode: '__start__', inputSource: null }, + style: { background: '#10b981', color: '#fff', border: '2px solid #059669', borderRadius: '8px', padding: '10px 20px' }, + }; + addNodes([startNode]); + nodes.value.push(startNode); }; // 新建工作流