工作流管理相关

This commit is contained in:
2026-08-06 09:31:34 +08:00
parent a951f864f4
commit cb8effc769
4 changed files with 48 additions and 10 deletions
@@ -45,7 +45,6 @@
v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, prev, pager, next"
small
@current-change="handlePageChange"
@@ -145,6 +144,11 @@ const fetchModelList = async () => {
const res = await getWorkflowModelList(params);
modelList.value = res.data?.list || [];
pagination.total = res.data?.total || 0;
// 预选项仅为部分信息(切换节点后无 id)时,按名称匹配当前页以高亮
if (selectedModel.value && !selectedModel.value.id && selectedModel.value.modelName) {
const matched = modelList.value.find((m) => m.modelName === selectedModel.value!.modelName);
if (matched) selectedModel.value = matched;
}
} catch {
modelList.value = [];
pagination.total = 0;
@@ -6,6 +6,13 @@
<el-form-item label="节点名称">
<el-input :model-value="selectedNode.data?.label" @update:model-value="updateNodeLabel" />
</el-form-item>
<el-form-item v-if="!isStartNode" label="节点描述">
<el-input
:model-value="selectedNode.data?.desc || ''"
placeholder="请输入节点描述"
@update:model-value="updateNodeDesc"
/>
</el-form-item>
<el-form-item label="节点类型">
<el-tag>{{ selectedNode.data?.nodeCode }}</el-tag>
</el-form-item>
@@ -74,7 +81,7 @@
:placeholder="field.required ? '必填' : '选填'"
class="w100"
>
<el-option v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value" />
<el-option v-for="opt in field.options" :key="opt.key || opt.value" :label="opt.value" :value="opt.value" />
</el-select>
<KeyValueEditor
v-else-if="field.type === 'keyValue'"
@@ -120,6 +127,7 @@ import { JsonEditor } from '/@/components/json-schema-editor';
interface NodeData {
label?: string;
nodeCode?: string;
desc?: string;
formConfig?: any[];
modelConfig?: any;
skillName?: string;
@@ -145,6 +153,9 @@ const isVideoModelSelected = computed(() => {
return t >= 600 && t <= 605;
});
// 开始节点不展示节点描述
const isStartNode = computed(() => props.selectedNode?.data?.nodeCode === '__start__');
const emit = defineEmits<{
(e: 'update:selectedNode', node: Node<NodeData, any, string>): void;
(e: 'openModelSelector'): void;
@@ -183,6 +194,18 @@ const updateNodeLabel = (newLabel: string) => {
emit('update:selectedNode', updatedNode);
};
const updateNodeDesc = (newDesc: string) => {
if (!props.selectedNode?.data) return;
const updatedNode = {
...props.selectedNode,
data: {
...props.selectedNode.data,
desc: newDesc,
},
};
emit('update:selectedNode', updatedNode);
};
const getFieldValue = (fieldName: string) => {
if (!props.selectedNode?.data?.formConfig) return '';
const field = props.selectedNode.data.formConfig.find((f: any) => f.field === fieldName);
@@ -34,7 +34,6 @@
v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, prev, pager, next"
small
@current-change="handlePageChange"
@@ -82,6 +81,7 @@ watch(
visible.value = val;
if (val) {
selectedSkill.value = props.defaultSkill || null;
pagination.pageNum = 1;
fetchSkillList();
}
}
@@ -100,6 +100,11 @@ const fetchSkillList = async () => {
const res = await getWorkflowSkillList(params);
skillList.value = res.data?.list || [];
pagination.total = res.data?.total || 0;
// 预选项仅为部分信息(切换节点后无 id)时,按名称匹配当前页以高亮
if (selectedSkill.value && !selectedSkill.value.id && selectedSkill.value.name) {
const matched = skillList.value.find((s) => s.name === selectedSkill.value!.name);
if (matched) selectedSkill.value = matched;
}
} catch {
skillList.value = [];
pagination.total = 0;
+13 -7
View File
@@ -30,7 +30,7 @@
<!-- 中间VueFlow 画布节点库在画布内 -->
<div class="flow-wrapper">
<NodeLibraryPanel
:node-library-groups="filteredNodeLibraryGroups"
:node-library-groups="nodeLibraryGroups"
:collapsed="nodeLibraryCollapsed"
@update:collapsed="nodeLibraryCollapsed = $event"
@add-node="addNodeFromLibrary"
@@ -108,6 +108,7 @@ import SkillSelector from './component/SkillSelector.vue';
interface NodeData {
label?: string;
nodeCode?: string;
desc?: string;
formConfig?: any[];
modelConfig?: any;
skillName?: string;
@@ -124,10 +125,6 @@ const JUDGE_KEYWORDS = ['判断', 'judge', 'condition', 'if', 'branch', 'gateway
const nodeLibraryGroups = ref<NodeLibraryGroup[]>([]);
const nodeLibraryCollapsed = ref(false);
const filteredNodeLibraryGroups = computed(() => {
return nodeLibraryGroups.value;
});
// 节点配置映射:nodeCode -> 节点配置
const nodeConfigMap = computed(() => {
const map = new Map<
@@ -243,6 +240,11 @@ const onConnect = (connection: Connection) => {
const onNodeClick = (event: { node: Node<NodeData, any, string> }) => {
selectedNode.value = event.node;
// 同步选择器预选项,避免展示上一个节点的模型/技能
const mc = event.node.data?.modelConfig;
selectedModelData.value = mc?.modelName ? { modelName: mc.modelName, modelType: mc.modelType } : null;
const sk = event.node.data?.skillName;
selectedSkillData.value = sk ? { name: sk } : null;
};
const updateSelectedNode = (updatedNode: Node<NodeData, any, string>) => {
@@ -444,6 +446,7 @@ const getNodeLibrary = async () => {
nodeLibraryGroups.value = res.data?.groups || [];
} catch {
nodeLibraryGroups.value = [];
ElMessage.error('节点库加载失败');
}
};
@@ -469,7 +472,7 @@ const addNodeFromLibrary = (nodeCode: string, nodeName: string) => {
id: `node-${++nodeId}`,
type: 'default',
position: { x: spawnX, y: spawnY },
data: { label: nodeName, nodeCode, patchLayout: false },
data: { label: nodeName, nodeCode, desc: '', patchLayout: false },
style: { background: '#fff', border: '2px solid #3b82f6', borderRadius: '8px', padding: '10px 20px' },
},
]);
@@ -547,6 +550,7 @@ const loadWorkflowFromDsl = (dsl: any) => {
data: {
label: n.name || '',
nodeCode: n.nodeCode,
desc: n.desc || '',
formConfig: n.formConfig || null,
modelConfig: n.modelConfig || null,
skillName: n.skillName || null,
@@ -605,14 +609,16 @@ const confirmSaveWorkflow = async () => {
return;
}
const startNode = nodes.value.find((n) => isStartNode(n));
const workflowDsl = {
version: '1.0.0',
startNodeId: nodes.value[0]?.id || '',
startNodeId: startNode?.id || '',
nodes: nodes.value.map((n) => ({
id: n.id,
nodeCode: n.data?.nodeCode || 'unknown',
name: n.data?.label || '',
type: n.type || 'default',
desc: n.data?.desc || null,
skillName: n.data?.skillName || null,
patchLayout: n.data?.patchLayout || false,
config: {