feat: 流程添加注释
This commit is contained in:
parent
8e2afcbaa6
commit
6c9ead2603
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:节点组件库侧栏,负责分类、搜索和拖拽创建。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="component-library">
|
<div class="component-library">
|
||||||
<div class="library-header">
|
<div class="library-header">
|
||||||
@ -75,6 +79,11 @@ watch(keyword, (value) => {
|
|||||||
if (value.trim()) activeNames.value = filteredGroups.value.map((group) => group.collapseTitle);
|
if (value.trim()) activeNames.value = filteredGroups.value.map((group) => group.collapseTitle);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleDragCustom 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const handleDragCustom = (event, node) => {
|
const handleDragCustom = (event, node) => {
|
||||||
event.dataTransfer.effectAllowed = "copy";
|
event.dataTransfer.effectAllowed = "copy";
|
||||||
event.dataTransfer.setData("flowNode", JSON.stringify(node));
|
event.dataTransfer.setData("flowNode", JSON.stringify(node));
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:递归参数表单,负责嵌套字段的增删和类型切换。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<!-- components/FormItemRecursive.vue -->
|
<!-- components/FormItemRecursive.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div class="form-item-recursive">
|
<div class="form-item-recursive">
|
||||||
@ -147,6 +151,10 @@ const { formType, currentList, propPath, depth, isFirstLevel, endDepth, parentPa
|
|||||||
const emit = defineEmits(['add-item', 'delete-item'])
|
const emit = defineEmits(['add-item', 'delete-item'])
|
||||||
|
|
||||||
// 处理类型变化(清空或添加子项)
|
// 处理类型变化(清空或添加子项)
|
||||||
|
/**
|
||||||
|
* 处理 handleTypeChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} item 调用方传入的 item 参数
|
||||||
|
*/
|
||||||
const handleTypeChange = (item) => {
|
const handleTypeChange = (item) => {
|
||||||
if (!["object", "array<object>"].includes(item.type)) {
|
if (!["object", "array<object>"].includes(item.type)) {
|
||||||
item.children = []; // 非对象类型清空子项
|
item.children = []; // 非对象类型清空子项
|
||||||
@ -156,6 +164,10 @@ const handleTypeChange = (item) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 添加子项
|
// 添加子项
|
||||||
|
/**
|
||||||
|
* 处理 handleAddChild 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} parentItem 调用方传入的 parentItem 参数
|
||||||
|
*/
|
||||||
const handleAddChild = (parentItem) => {
|
const handleAddChild = (parentItem) => {
|
||||||
parentItem.children.push({
|
parentItem.children.push({
|
||||||
name: "",
|
name: "",
|
||||||
@ -168,6 +180,10 @@ const handleAddChild = (parentItem) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 删除当前项
|
// 删除当前项
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
// 完整路径 = 父级路径 + 当前索引(如果是顶层,parentPath为undefined)
|
// 完整路径 = 父级路径 + 当前索引(如果是顶层,parentPath为undefined)
|
||||||
const fullPath = parentPath ? [...parentPath, index] : [index];
|
const fullPath = parentPath ? [...parentPath, index] : [index];
|
||||||
@ -175,6 +191,10 @@ const handleDelete = (index) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 接收子组件的删除事件,继续向上传递
|
// 接收子组件的删除事件,继续向上传递
|
||||||
|
/**
|
||||||
|
* 处理 handleChildDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} childFullPath 调用方传入的 childFullPath 参数
|
||||||
|
*/
|
||||||
const handleChildDelete = (childFullPath) => {
|
const handleChildDelete = (childFullPath) => {
|
||||||
emit("delete-item", childFullPath);
|
emit("delete-item", childFullPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:节点运行状态面板,展示耗时、输入、输出和错误。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div v-if="showState !== 'NORMAL'" class="node-state" :class="`node-state--${showState.toLowerCase()}`">
|
<div v-if="showState !== 'NORMAL'" class="node-state" :class="`node-state--${showState.toLowerCase()}`">
|
||||||
<div class="node-state__summary">
|
<div class="node-state__summary">
|
||||||
@ -66,6 +70,9 @@ watch(() => props.state, (value) => {
|
|||||||
showState.value = value;
|
showState.value = value;
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
showState.value = "NORMAL";
|
showState.value = "NORMAL";
|
||||||
popoverVisible.value = false;
|
popoverVisible.value = false;
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:节点标题栏,负责重命名、删除和单节点执行。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node-title">
|
<div class="node-title">
|
||||||
<div class="node-title__main">
|
<div class="node-title__main">
|
||||||
@ -108,12 +112,18 @@ const typeLabel = computed(() => {
|
|||||||
return { EDGE: "设备", LLM: "模型", AE: "评估" }[props.nodeType] || props.nodeType;
|
return { EDGE: "设备", LLM: "模型", AE: "评估" }[props.nodeType] || props.nodeType;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 sourceName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const sourceName = () => props.nodeProperties?.name || props.nodeName || "未命名节点";
|
const sourceName = () => props.nodeProperties?.name || props.nodeName || "未命名节点";
|
||||||
|
|
||||||
watch(sourceName, (value) => {
|
watch(sourceName, (value) => {
|
||||||
if (!isEditing.value) localName.value = value;
|
if (!isEditing.value) localName.value = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 startEditing 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const startEditing = async () => {
|
const startEditing = async () => {
|
||||||
isEditing.value = true;
|
isEditing.value = true;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
@ -121,6 +131,9 @@ const startEditing = async () => {
|
|||||||
nameInputRef.value?.select?.();
|
nameInputRef.value?.select?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认 confirmNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const confirmNodeName = () => {
|
const confirmNodeName = () => {
|
||||||
const name = localName.value.trim();
|
const name = localName.value.trim();
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
@ -129,11 +142,17 @@ const confirmNodeName = () => {
|
|||||||
isEditing.value = false;
|
isEditing.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 cancelNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const cancelNodeName = () => {
|
const cancelNodeName = () => {
|
||||||
localName.value = sourceName();
|
localName.value = sourceName();
|
||||||
isEditing.value = false;
|
isEditing.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 deleteNode 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const deleteNode = async () => {
|
const deleteNode = async () => {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm(
|
await ElMessageBox.confirm(
|
||||||
@ -155,6 +174,9 @@ const deleteNode = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 execute 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const execute = () => {
|
const execute = () => {
|
||||||
document.dispatchEvent(new CustomEvent("singleNodeExecution", {
|
document.dispatchEvent(new CustomEvent("singleNodeExecution", {
|
||||||
bubbles: false,
|
bubbles: false,
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:动态节点包装器,挂载具体节点并同步内容变化。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__box">
|
<div class="node__box">
|
||||||
<component :is="componentId" :model="props.model" :properties="props.properties" ref="nodeRef" @contentChange="contentChange"></component>
|
<component :is="componentId" :model="props.model" :properties="props.properties" ref="nodeRef" @contentChange="contentChange"></component>
|
||||||
@ -18,6 +22,9 @@ const emits = defineEmits(['contentChange', 'bindRef'])
|
|||||||
|
|
||||||
const componentId = ref(props.component)
|
const componentId = ref(props.component)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 contentChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const contentChange = () => {
|
const contentChange = () => {
|
||||||
emits('contentChange')
|
emits('contentChange')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:节点参数抽屉,统一触发参数校验和保存。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer
|
||||||
:model-value="props.drawer"
|
:model-value="props.drawer"
|
||||||
@ -55,6 +59,9 @@ const currentComponent = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 这里提供一个公开方法供父组件调用
|
// 这里提供一个公开方法供父组件调用
|
||||||
|
/**
|
||||||
|
* 确认 confirmSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const confirmSave = async () => {
|
const confirmSave = async () => {
|
||||||
if (paramsComponentRef.value && typeof paramsComponentRef.value.validateAndSave === 'function') {
|
if (paramsComponentRef.value && typeof paramsComponentRef.value.validateAndSave === 'function') {
|
||||||
await paramsComponentRef.value.validateAndSave()
|
await paramsComponentRef.value.validateAndSave()
|
||||||
@ -67,6 +74,9 @@ const confirmSave = async () => {
|
|||||||
defineExpose({ confirmSave })
|
defineExpose({ confirmSave })
|
||||||
|
|
||||||
// 保存成功 / 失败处理
|
// 保存成功 / 失败处理
|
||||||
|
/**
|
||||||
|
* 处理 handleSaveSuccess 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const handleSaveSuccess = () => {
|
const handleSaveSuccess = () => {
|
||||||
emitter.emit('setProperties', { id: props.data.id })
|
emitter.emit('setProperties', { id: props.data.id })
|
||||||
emitter.emit("throwAnError", { id: props.data.id, hasError: false, type: props.data.type });
|
emitter.emit("throwAnError", { id: props.data.id, hasError: false, type: props.data.type });
|
||||||
@ -74,6 +84,9 @@ const handleSaveSuccess = () => {
|
|||||||
emits('close')
|
emits('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleSaveError 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const handleSaveError = () => {
|
const handleSaveError = () => {
|
||||||
emitter.emit('setProperties', { id: props.data.id })
|
emitter.emit('setProperties', { id: props.data.id })
|
||||||
emitter.emit("throwAnError", { id: props.data.id, hasError: true, type: props.data.type });
|
emitter.emit("throwAnError", { id: props.data.id, hasError: true, type: props.data.type });
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:流程试运行抽屉,收集运行参数并绑定机器人设备。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer
|
||||||
:model-value="props.drawer"
|
:model-value="props.drawer"
|
||||||
@ -93,14 +97,27 @@ const tableData = ref([])
|
|||||||
// 按流程缓存整套试运行参数,关闭或执行后再次打开时继续使用。
|
// 按流程缓存整套试运行参数,关闭或执行后再次打开时继续使用。
|
||||||
const trialRunCache = new Map()
|
const trialRunCache = new Map()
|
||||||
const bindingLoading = ref(false)
|
const bindingLoading = ref(false)
|
||||||
|
/**
|
||||||
|
* 处理 emptyBindingSummary 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} robotId 机器人 ID
|
||||||
|
*/
|
||||||
const emptyBindingSummary = (robotId = '') => ({ robotId, matched: 0, missing: 0, untouched: 0 })
|
const emptyBindingSummary = (robotId = '') => ({ robotId, matched: 0, missing: 0, untouched: 0 })
|
||||||
const bindingSummary = ref(emptyBindingSummary())
|
const bindingSummary = ref(emptyBindingSummary())
|
||||||
|
|
||||||
const emits = defineEmits(['close', 'changeState'])
|
const emits = defineEmits(['close', 'changeState'])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 克隆 cloneData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} data 待处理的数据
|
||||||
|
*/
|
||||||
const cloneData = (data) => JSON.parse(JSON.stringify(data || []))
|
const cloneData = (data) => JSON.parse(JSON.stringify(data || []))
|
||||||
|
|
||||||
// 根据参数层级恢复缓存值,同时兼容流程参数结构发生增删的情况。
|
// 根据参数层级恢复缓存值,同时兼容流程参数结构发生增删的情况。
|
||||||
|
/**
|
||||||
|
* 合并 mergeCachedValues 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} source 源数据
|
||||||
|
* @param {*} cached 缓存数据
|
||||||
|
*/
|
||||||
const mergeCachedValues = (source, cached) => {
|
const mergeCachedValues = (source, cached) => {
|
||||||
const cachedByName = new Map((cached || []).map(item => [item.name, item]))
|
const cachedByName = new Map((cached || []).map(item => [item.name, item]))
|
||||||
return (source || []).map((item, index) => {
|
return (source || []).map((item, index) => {
|
||||||
@ -115,14 +132,23 @@ const mergeCachedValues = (source, cached) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 cacheKey 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const cacheKey = () => props.flowId || '__new_flow__'
|
const cacheKey = () => props.flowId || '__new_flow__'
|
||||||
|
|
||||||
// 深拷贝快照,避免后续表单编辑直接修改缓存内容。
|
// 深拷贝快照,避免后续表单编辑直接修改缓存内容。
|
||||||
|
/**
|
||||||
|
* 缓存 rememberTrialRunParams 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const rememberTrialRunParams = () => {
|
const rememberTrialRunParams = () => {
|
||||||
if (!tableData.value.length) return
|
if (!tableData.value.length) return
|
||||||
trialRunCache.set(cacheKey(), cloneData(tableData.value))
|
trialRunCache.set(cacheKey(), cloneData(tableData.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleClose 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
rememberTrialRunParams()
|
rememberTrialRunParams()
|
||||||
ruleFormRef.value?.clearValidate()
|
ruleFormRef.value?.clearValidate()
|
||||||
@ -142,6 +168,9 @@ watch(() => props.drawer,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认 confirm 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
rememberTrialRunParams()
|
rememberTrialRunParams()
|
||||||
lf.fitView()
|
lf.fitView()
|
||||||
@ -174,7 +203,13 @@ const confirm = () => {
|
|||||||
|
|
||||||
const robotIdOptions = ref([])
|
const robotIdOptions = ref([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleRobotChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} robotId 机器人 ID
|
||||||
|
*/
|
||||||
const handleRobotChange = async (robotId) => {
|
const handleRobotChange = async (robotId) => {
|
||||||
|
// 先拉取机器人设备,再按每个设备节点声明的设备类型筛选候选项。
|
||||||
|
// 仅在候选唯一时自动回填;无候选或多候选均交由用户确认,避免绑定错误设备。
|
||||||
bindingSummary.value = emptyBindingSummary(robotId || '')
|
bindingSummary.value = emptyBindingSummary(robotId || '')
|
||||||
if (!robotId) return
|
if (!robotId) return
|
||||||
bindingLoading.value = true
|
bindingLoading.value = true
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:通用节点参数面板,配置输入输出及机器人动作调试。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
<!-- 输入参数 -->
|
<!-- 输入参数 -->
|
||||||
@ -142,6 +146,11 @@ const activeNames = ref(['1', '2'])
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -156,11 +165,20 @@ const addFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入参数(非递归)
|
// 删除输入参数(非递归)
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
formData.nodeParams.splice(index, 1)
|
formData.nodeParams.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
||||||
|
/**
|
||||||
|
* 删除 deleteTopLevelItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteTopLevelItem = (fullPath, propPath) => {
|
const deleteTopLevelItem = (fullPath, propPath) => {
|
||||||
let currentLevel = formData[propPath]
|
let currentLevel = formData[propPath]
|
||||||
for (let i = 0; i < fullPath.length - 1; i++) {
|
for (let i = 0; i < fullPath.length - 1; i++) {
|
||||||
@ -171,6 +189,9 @@ const deleteTopLevelItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
||||||
@ -187,6 +208,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
let inputValid = true
|
let inputValid = true
|
||||||
let outputValid = true
|
let outputValid = true
|
||||||
@ -224,6 +248,9 @@ const robotOptions = ref([])
|
|||||||
const deviceOptions = ref([])
|
const deviceOptions = ref([])
|
||||||
const deviceLoading = ref(false)
|
const deviceLoading = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadRobotOptions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const loadRobotOptions = async () => {
|
const loadRobotOptions = async () => {
|
||||||
const response = await getRobotList({ pageNum: 1, pageSize: 1000, connectStatus: '1' })
|
const response = await getRobotList({ pageNum: 1, pageSize: 1000, connectStatus: '1' })
|
||||||
robotOptions.value = (response.rows || []).map(robot => ({
|
robotOptions.value = (response.rows || []).map(robot => ({
|
||||||
@ -232,6 +259,10 @@ const loadRobotOptions = async () => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadRobotDevices 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} robotId 机器人 ID
|
||||||
|
*/
|
||||||
const loadRobotDevices = async (robotId) => {
|
const loadRobotDevices = async (robotId) => {
|
||||||
robotForm.deviceId = ''
|
robotForm.deviceId = ''
|
||||||
deviceOptions.value = []
|
deviceOptions.value = []
|
||||||
@ -250,6 +281,10 @@ const loadRobotDevices = async (robotId) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试 testRule 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} property 参数属性
|
||||||
|
*/
|
||||||
const testRule = (property) => {
|
const testRule = (property) => {
|
||||||
if (property?.name === 'stationId' && props.data.properties.action === 'AGV_MOVE_TO_STATION') {
|
if (property?.name === 'stationId' && props.data.properties.action === 'AGV_MOVE_TO_STATION') {
|
||||||
return [
|
return [
|
||||||
@ -311,6 +346,9 @@ const robotDialogTitle = computed(() => {
|
|||||||
return '选择机器人设备'
|
return '选择机器人设备'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 submitRobotForm 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const submitRobotForm = () => {
|
const submitRobotForm = () => {
|
||||||
if (robotFormAction.value === 'AGV_MOVE_TO_POINT') {
|
if (robotFormAction.value === 'AGV_MOVE_TO_POINT') {
|
||||||
robotFormRef.value.validate(async (valid) => {
|
robotFormRef.value.validate(async (valid) => {
|
||||||
@ -440,6 +478,10 @@ const submitRobotForm = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 toStationOptions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} stations 站点集合
|
||||||
|
*/
|
||||||
const toStationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
const toStationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
||||||
.filter(station => station?.id !== undefined && station?.id !== null && String(station.id).trim())
|
.filter(station => station?.id !== undefined && station?.id !== null && String(station.id).trim())
|
||||||
.map(station => {
|
.map(station => {
|
||||||
@ -451,6 +493,10 @@ const toStationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开 openRobotForm 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} action 节点动作类型
|
||||||
|
*/
|
||||||
const openRobotForm = async (action) => {
|
const openRobotForm = async (action) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
robotFormAction.value = action
|
robotFormAction.value = action
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:代码节点参数面板,编辑并校验脚本和输入输出字段。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
@ -211,6 +215,9 @@ const formData = reactive({
|
|||||||
const codeRef = ref()
|
const codeRef = ref()
|
||||||
let editorInstance
|
let editorInstance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 hasErrors 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
function hasErrors() {
|
function hasErrors() {
|
||||||
const model = editorInstance.getModel();
|
const model = editorInstance.getModel();
|
||||||
if (!model) return false;
|
if (!model) return false;
|
||||||
@ -220,6 +227,10 @@ function hasErrors() {
|
|||||||
// 检查是否存在错误级别标记
|
// 检查是否存在错误级别标记
|
||||||
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 初始化 initEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const initEditor = (type) => {
|
const initEditor = (type) => {
|
||||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
||||||
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
||||||
@ -260,6 +271,10 @@ const initEditor = (type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置代码值
|
// 设置代码值
|
||||||
|
/**
|
||||||
|
* 设置 setValue 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
*/
|
||||||
const setValue = (value) => {
|
const setValue = (value) => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.setValue(value)
|
editorInstance.setValue(value)
|
||||||
@ -267,6 +282,9 @@ const setValue = (value) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 销毁编辑器
|
// 销毁编辑器
|
||||||
|
/**
|
||||||
|
* 销毁 disposeEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const disposeEditor = () => {
|
const disposeEditor = () => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.dispose()
|
editorInstance.dispose()
|
||||||
@ -284,6 +302,11 @@ const activeNames = ref(['1', '2'])
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -298,11 +321,20 @@ const addFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入参数(非递归)
|
// 删除输入参数(非递归)
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
formData.nodeParams.splice(index, 1)
|
formData.nodeParams.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
||||||
|
/**
|
||||||
|
* 删除 deleteTopLevelItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteTopLevelItem = (fullPath, propPath) => {
|
const deleteTopLevelItem = (fullPath, propPath) => {
|
||||||
let currentLevel = formData[propPath]
|
let currentLevel = formData[propPath]
|
||||||
for (let i = 0; i < fullPath.length - 1; i++) {
|
for (let i = 0; i < fullPath.length - 1; i++) {
|
||||||
@ -313,6 +345,9 @@ const deleteTopLevelItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
||||||
@ -329,6 +364,9 @@ const initData = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
const targetObj = formData.nodeParams.find(item => item.name === 'code');
|
const targetObj = formData.nodeParams.find(item => item.name === 'code');
|
||||||
if (targetObj) {
|
if (targetObj) {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:通用设备参数面板,选择设备并配置脚本和参数。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
@ -260,6 +264,9 @@ const formData = reactive({
|
|||||||
const codeRef = ref()
|
const codeRef = ref()
|
||||||
let editorInstance
|
let editorInstance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 hasErrors 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
function hasErrors() {
|
function hasErrors() {
|
||||||
const model = editorInstance.getModel();
|
const model = editorInstance.getModel();
|
||||||
if (!model) return false;
|
if (!model) return false;
|
||||||
@ -269,6 +276,10 @@ function hasErrors() {
|
|||||||
// 检查是否存在错误级别标记
|
// 检查是否存在错误级别标记
|
||||||
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 初始化 initEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const initEditor = (type) => {
|
const initEditor = (type) => {
|
||||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
||||||
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
||||||
@ -309,6 +320,10 @@ const initEditor = (type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置代码值
|
// 设置代码值
|
||||||
|
/**
|
||||||
|
* 设置 setValue 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
*/
|
||||||
const setValue = (value) => {
|
const setValue = (value) => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.setValue(value)
|
editorInstance.setValue(value)
|
||||||
@ -316,6 +331,9 @@ const setValue = (value) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 销毁编辑器
|
// 销毁编辑器
|
||||||
|
/**
|
||||||
|
* 销毁 disposeEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const disposeEditor = () => {
|
const disposeEditor = () => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.dispose()
|
editorInstance.dispose()
|
||||||
@ -341,6 +359,9 @@ const deviceFormRules = {
|
|||||||
deviceId: [{ required: true, message: '请选择执行设备', trigger: 'change' }]
|
deviceId: [{ required: true, message: '请选择执行设备', trigger: 'change' }]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadRobotOptions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const loadRobotOptions = async () => {
|
const loadRobotOptions = async () => {
|
||||||
robotLoading.value = true
|
robotLoading.value = true
|
||||||
try {
|
try {
|
||||||
@ -354,6 +375,10 @@ const loadRobotOptions = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadRobotDevices 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} robotId 机器人 ID
|
||||||
|
*/
|
||||||
const loadRobotDevices = async (robotId) => {
|
const loadRobotDevices = async (robotId) => {
|
||||||
deviceForm.deviceId = ''
|
deviceForm.deviceId = ''
|
||||||
deviceOptions.value = []
|
deviceOptions.value = []
|
||||||
@ -370,6 +395,9 @@ const loadRobotDevices = async (robotId) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开 openDeviceDialog 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const openDeviceDialog = async () => {
|
const openDeviceDialog = async () => {
|
||||||
deviceDialogVisible.value = true
|
deviceDialogVisible.value = true
|
||||||
deviceForm.robotId = ''
|
deviceForm.robotId = ''
|
||||||
@ -378,6 +406,9 @@ const openDeviceDialog = async () => {
|
|||||||
await loadRobotOptions()
|
await loadRobotOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认 confirmDevice 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const confirmDevice = async () => {
|
const confirmDevice = async () => {
|
||||||
const valid = await deviceFormRef.value?.validate().catch(() => false)
|
const valid = await deviceFormRef.value?.validate().catch(() => false)
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
@ -397,6 +428,11 @@ const confirmDevice = async () => {
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -411,11 +447,20 @@ const addFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入参数(非递归)
|
// 删除输入参数(非递归)
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
formData.nodeParams.splice(index, 1)
|
formData.nodeParams.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
||||||
|
/**
|
||||||
|
* 删除 deleteTopLevelItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteTopLevelItem = (fullPath, propPath) => {
|
const deleteTopLevelItem = (fullPath, propPath) => {
|
||||||
let currentLevel = formData[propPath]
|
let currentLevel = formData[propPath]
|
||||||
for (let i = 0; i < fullPath.length - 1; i++) {
|
for (let i = 0; i < fullPath.length - 1; i++) {
|
||||||
@ -426,6 +471,9 @@ const deleteTopLevelItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
||||||
@ -442,6 +490,9 @@ const initData = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
const targetObj = formData.nodeParams.find(item => item.name === 'requestJson');
|
const targetObj = formData.nodeParams.find(item => item.name === 'requestJson');
|
||||||
if (targetObj) {
|
if (targetObj) {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:HTTP 节点参数面板,配置请求及输出字段。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-form :inline="true" :model="httpNodeData" :rules="rules" class="http-form" ref="dynamicFormRef"
|
<el-form :inline="true" :model="httpNodeData" :rules="rules" class="http-form" ref="dynamicFormRef"
|
||||||
label-position="top" label-width="auto">
|
label-position="top" label-width="auto">
|
||||||
@ -352,6 +356,9 @@ const formData = reactive({
|
|||||||
const codeRef = ref()
|
const codeRef = ref()
|
||||||
let editorInstance
|
let editorInstance
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 hasErrors 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
function hasErrors() {
|
function hasErrors() {
|
||||||
const model = editorInstance.getModel();
|
const model = editorInstance.getModel();
|
||||||
if (!model) return false;
|
if (!model) return false;
|
||||||
@ -362,6 +369,10 @@ function hasErrors() {
|
|||||||
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
return markers.some(marker => marker.severity === monaco.MarkerSeverity.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 initEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const initEditor = (type) => {
|
const initEditor = (type) => {
|
||||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
||||||
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
||||||
@ -402,6 +413,10 @@ const initEditor = (type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置代码值
|
// 设置代码值
|
||||||
|
/**
|
||||||
|
* 设置 setValue 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
*/
|
||||||
const setValue = (value) => {
|
const setValue = (value) => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.setValue(value)
|
editorInstance.setValue(value)
|
||||||
@ -409,6 +424,9 @@ const setValue = (value) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 销毁编辑器
|
// 销毁编辑器
|
||||||
|
/**
|
||||||
|
* 销毁 disposeEditor 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const disposeEditor = () => {
|
const disposeEditor = () => {
|
||||||
if (editorInstance) {
|
if (editorInstance) {
|
||||||
editorInstance.dispose()
|
editorInstance.dispose()
|
||||||
@ -424,6 +442,11 @@ const activeNames = ref(['1', '2', '3', '4'])
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -438,11 +461,20 @@ const addFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入参数(非递归)
|
// 删除输入参数(非递归)
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
formData.nodeParams.splice(index, 1)
|
formData.nodeParams.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
||||||
|
/**
|
||||||
|
* 删除 deleteTopLevelItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteTopLevelItem = (fullPath, propPath) => {
|
const deleteTopLevelItem = (fullPath, propPath) => {
|
||||||
let currentLevel = formData[propPath]
|
let currentLevel = formData[propPath]
|
||||||
for (let i = 0; i < fullPath.length - 1; i++) {
|
for (let i = 0; i < fullPath.length - 1; i++) {
|
||||||
@ -461,6 +493,11 @@ const httpNodeData = ref({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addHttpNodeFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addHttpNodeFormItem = (e, type) => {
|
const addHttpNodeFormItem = (e, type) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (type === 'body') {
|
if (type === 'body') {
|
||||||
@ -476,6 +513,11 @@ const addHttpNodeFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleHttpNodeDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleHttpNodeDelete = (type, index) => {
|
const handleHttpNodeDelete = (type, index) => {
|
||||||
if (type === 'body') {
|
if (type === 'body') {
|
||||||
httpNodeData.value.body.formData.splice(index, 1);
|
httpNodeData.value.body.formData.splice(index, 1);
|
||||||
@ -485,6 +527,9 @@ const handleHttpNodeDelete = (type, index) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const transformedData = transformHttpNodeData(nodeParams);
|
const transformedData = transformHttpNodeData(nodeParams);
|
||||||
@ -503,7 +548,12 @@ const initData = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
|
// 分区校验动态输入、请求头、查询参数和请求体;JSON 请求体还需通过编辑器语法检查。
|
||||||
|
// 全部分区有效后才一次性写回节点属性,防止半成品配置覆盖画布中的可用数据。
|
||||||
let inputValid = true
|
let inputValid = true
|
||||||
if (dynamicFormRef.value) {
|
if (dynamicFormRef.value) {
|
||||||
await dynamicFormRef.value.validate((valid) => { if (!valid) inputValid = false })
|
await dynamicFormRef.value.validate((valid) => { if (!valid) inputValid = false })
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:识别节点参数面板,配置识别条件和告警规则。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-form :inline="true" :model="RecognizeNodeData" :rules="rules" ref="dynamicFormRef" class="http-form"
|
<el-form :inline="true" :model="RecognizeNodeData" :rules="rules" ref="dynamicFormRef" class="http-form"
|
||||||
label-position="top" label-width="auto">
|
label-position="top" label-width="auto">
|
||||||
@ -134,6 +138,11 @@ const activeNames = ref(['1', '2'])
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -159,6 +168,10 @@ const alarmOperators = [
|
|||||||
{ label: '不等于(NE)', value: 'NE' }
|
{ label: '不等于(NE)', value: 'NE' }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addAlarmRule 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const addAlarmRule = (e) => {
|
const addAlarmRule = (e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
RecognizeNodeData.value.alarmRules.push({
|
RecognizeNodeData.value.alarmRules.push({
|
||||||
@ -169,15 +182,28 @@ const addAlarmRule = (e) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 deleteAlarmRule 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const deleteAlarmRule = (index) => {
|
const deleteAlarmRule = (index) => {
|
||||||
RecognizeNodeData.value.alarmRules.splice(index, 1)
|
RecognizeNodeData.value.alarmRules.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addRecognizeItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const addRecognizeItem = (e) => {
|
const addRecognizeItem = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
RecognizeNodeData.value.outputParams.push({ name: "", type: "string", input: "" });
|
RecognizeNodeData.value.outputParams.push({ name: "", type: "string", input: "" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 deleteRecognizeItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteRecognizeItem = (fullPath, propPath) => {
|
const deleteRecognizeItem = (fullPath, propPath) => {
|
||||||
// 从顶层数据开始查找
|
// 从顶层数据开始查找
|
||||||
let currentLevel = RecognizeNodeData.value[propPath];
|
let currentLevel = RecognizeNodeData.value[propPath];
|
||||||
@ -195,6 +221,9 @@ const deleteRecognizeItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
||||||
@ -214,6 +243,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
let inputValid = true
|
let inputValid = true
|
||||||
let outputValid = true
|
let outputValid = true
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:智能体参数面板,配置智能体调用和语音合成。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-form :inline="true" :model="sdAgentNodeData" :rules="rules" ref="dynamicFormRef" class="http-form"
|
<el-form :inline="true" :model="sdAgentNodeData" :rules="rules" ref="dynamicFormRef" class="http-form"
|
||||||
label-position="top" label-width="auto">
|
label-position="top" label-width="auto">
|
||||||
@ -162,6 +166,11 @@ const activeNames = ref(['1', '2'])
|
|||||||
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
const { quoteOptions, cascaderRefs, handleTypeChange, cascaderChange, visibleChange } = useQuote(props.data.id)
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -178,6 +187,9 @@ const addFormItem = (e, type) => {
|
|||||||
// 商道智能体
|
// 商道智能体
|
||||||
const sdAgentNodeData = ref({})
|
const sdAgentNodeData = ref({})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 voiceOptions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const voiceOptions = () => {
|
const voiceOptions = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 'x4_xiaoyan',
|
value: 'x4_xiaoyan',
|
||||||
@ -185,6 +197,10 @@ const voiceOptions = () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleTtsChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} val 变更值
|
||||||
|
*/
|
||||||
const handleTtsChange = (val) => {
|
const handleTtsChange = (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
sdAgentNodeData.value.tts = []
|
sdAgentNodeData.value.tts = []
|
||||||
@ -200,11 +216,20 @@ const handleTtsChange = (val) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addSdAgentItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const addSdAgentItem = (e) => {
|
const addSdAgentItem = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
sdAgentNodeData.value.outputParams.push({ name: "", type: "string", input: "" });
|
sdAgentNodeData.value.outputParams.push({ name: "", type: "string", input: "" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 deleteSdAgentItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteSdAgentItem = (fullPath, propPath) => {
|
const deleteSdAgentItem = (fullPath, propPath) => {
|
||||||
// 从顶层数据开始查找
|
// 从顶层数据开始查找
|
||||||
let currentLevel = sdAgentNodeData.value[propPath];
|
let currentLevel = sdAgentNodeData.value[propPath];
|
||||||
@ -222,6 +247,9 @@ const deleteSdAgentItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
|
||||||
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
|
||||||
@ -241,6 +269,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
let inputValid = true
|
let inputValid = true
|
||||||
let outputValid = true
|
let outputValid = true
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:开始节点参数面板,配置流程入口参数。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
<el-collapse-item name="1" icon-position="left">
|
<el-collapse-item name="1" icon-position="left">
|
||||||
@ -42,6 +46,11 @@ const dynamicFormRef = ref()
|
|||||||
const activeNames = ref(['1', '2'])
|
const activeNames = ref(['1', '2'])
|
||||||
|
|
||||||
// 添加表单项
|
// 添加表单项
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const addFormItem = (e, type) => {
|
const addFormItem = (e, type) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const obj = {
|
const obj = {
|
||||||
@ -56,11 +65,20 @@ const addFormItem = (e, type) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除输入参数(非递归)
|
// 删除输入参数(非递归)
|
||||||
|
/**
|
||||||
|
* 处理 handleDelete 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (index) => {
|
||||||
formData.nodeParams.splice(index, 1)
|
formData.nodeParams.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
// 删除顶层输出参数(递归删除通过 FormItemRecursive 的 emit 处理)
|
||||||
|
/**
|
||||||
|
* 删除 deleteTopLevelItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} fullPath 字段完整路径
|
||||||
|
* @param {*} propPath 字段校验路径
|
||||||
|
*/
|
||||||
const deleteTopLevelItem = (fullPath, propPath) => {
|
const deleteTopLevelItem = (fullPath, propPath) => {
|
||||||
let currentLevel = formData[propPath]
|
let currentLevel = formData[propPath]
|
||||||
for (let i = 0; i < fullPath.length - 1; i++) {
|
for (let i = 0; i < fullPath.length - 1; i++) {
|
||||||
@ -71,6 +89,9 @@ const deleteTopLevelItem = (fullPath, propPath) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
|
/**
|
||||||
|
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const initData = () => {
|
const initData = () => {
|
||||||
const inputParams = JSON.parse(JSON.stringify(props.data.properties.inputParams || []))
|
const inputParams = JSON.parse(JSON.stringify(props.data.properties.inputParams || []))
|
||||||
formData.inputParams = inputParams;
|
formData.inputParams = inputParams;
|
||||||
@ -85,6 +106,9 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 保存验证
|
// 保存验证
|
||||||
|
/**
|
||||||
|
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const validateAndSave = async () => {
|
const validateAndSave = async () => {
|
||||||
let inputValid = true
|
let inputValid = true
|
||||||
if (dynamicFormRef.value) {
|
if (dynamicFormRef.value) {
|
||||||
|
|||||||
@ -1,10 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 文件说明:参数引用组合逻辑,维护可引用字段和级联选择状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
*/
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { getInput } from '@/utils/flow'
|
import { getInput } from '@/utils/flow'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 useQuote 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} nodeId 流程节点 ID
|
||||||
|
*/
|
||||||
export function useQuote(nodeId) {
|
export function useQuote(nodeId) {
|
||||||
const quoteOptions = ref([])
|
const quoteOptions = ref([])
|
||||||
const cascaderRefs = ref([])
|
const cascaderRefs = ref([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleTypeChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
* @param {*} formData 参数表单数据
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
const handleTypeChange = (index, formData, type = 'default') => {
|
const handleTypeChange = (index, formData, type = 'default') => {
|
||||||
// 根据节点类型处理不同数据源
|
// 根据节点类型处理不同数据源
|
||||||
// 这里简化为通用逻辑,具体实现需根据实际数据结构调整
|
// 这里简化为通用逻辑,具体实现需根据实际数据结构调整
|
||||||
@ -17,6 +31,13 @@ export function useQuote(nodeId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 cascaderChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
* @param {*} formData 参数表单数据
|
||||||
|
* @param {*} field 调用方传入的 field 参数
|
||||||
|
*/
|
||||||
const cascaderChange = (value, index, formData, field = 'nodeParams') => {
|
const cascaderChange = (value, index, formData, field = 'nodeParams') => {
|
||||||
const selectedOptions = cascaderRefs.value[index]?.getCheckedNodes(true)
|
const selectedOptions = cascaderRefs.value[index]?.getCheckedNodes(true)
|
||||||
if (selectedOptions && selectedOptions.length) {
|
if (selectedOptions && selectedOptions.length) {
|
||||||
@ -25,6 +46,14 @@ export function useQuote(nodeId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 visibleChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} visible 是否可见
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
* @param {*} currentQuote 调用方传入的 currentQuote 参数
|
||||||
|
* @param {*} formData 参数表单数据
|
||||||
|
* @param {*} field 调用方传入的 field 参数
|
||||||
|
*/
|
||||||
const visibleChange = (visible, index, currentQuote, formData, field = 'nodeParams') => {
|
const visibleChange = (visible, index, currentQuote, formData, field = 'nodeParams') => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
const option = getInput(nodeId)
|
const option = getInput(nodeId)
|
||||||
|
|||||||
@ -1,9 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* 文件说明:流程事件订阅组合逻辑,并在卸载时释放监听器。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
*/
|
||||||
import { onUnmounted } from "vue";
|
import { onUnmounted } from "vue";
|
||||||
import { emitter } from "@/utils/eventBus";
|
import { emitter } from "@/utils/eventBus";
|
||||||
|
|
||||||
export const useFlowEvents = () => {
|
export const useFlowEvents = () => {
|
||||||
const listeners = [];
|
const listeners = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅 onFlowEvent 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
* @param {*} handler 事件处理函数
|
||||||
|
*/
|
||||||
const onFlowEvent = (type, handler) => {
|
const onFlowEvent = (type, handler) => {
|
||||||
emitter.on(type, handler);
|
emitter.on(type, handler);
|
||||||
listeners.push([type, handler]);
|
listeners.push([type, handler]);
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* 文件说明:定义流程设计器可用的节点、表单字段及下拉选项等静态配置。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
*/
|
||||||
import cameraSvg from './icon/camera.svg'
|
import cameraSvg from './icon/camera.svg'
|
||||||
import videoSvg from './icon/video.svg'
|
import videoSvg from './icon/video.svg'
|
||||||
import loopSvg from './icon/loop.svg'
|
import loopSvg from './icon/loop.svg'
|
||||||
@ -12,6 +16,9 @@ import audioSvg from './icon/audio.svg'
|
|||||||
import touchSvg from './icon/touch.svg'
|
import touchSvg from './icon/touch.svg'
|
||||||
import expressionSvg from './icon/expression.svg'
|
import expressionSvg from './icon/expression.svg'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理与 http method options 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
*/
|
||||||
const httpMethodOptions = () => {
|
const httpMethodOptions = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 'POST',
|
value: 'POST',
|
||||||
@ -28,6 +35,9 @@ const httpMethodOptions = () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理与 express options 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
*/
|
||||||
const expressOptions = () => {
|
const expressOptions = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 1,
|
value: 1,
|
||||||
@ -50,6 +60,9 @@ const expressOptions = () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理与 task type options 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
*/
|
||||||
const taskTypeOptions = () => {
|
const taskTypeOptions = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 'voice',
|
value: 'voice',
|
||||||
@ -60,6 +73,9 @@ const taskTypeOptions = () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理与 voice options 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
*/
|
||||||
const voiceOptions = () => {
|
const voiceOptions = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 'x4_xiaoyan',
|
value: 'x4_xiaoyan',
|
||||||
@ -67,6 +83,9 @@ const voiceOptions = () => {
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理与 inspection event types 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
*/
|
||||||
const inspectionEventTypes = () => {
|
const inspectionEventTypes = () => {
|
||||||
return [{
|
return [{
|
||||||
value: 'No-Glove',
|
value: 'No-Glove',
|
||||||
@ -245,6 +264,10 @@ export const collapseList = [
|
|||||||
{ name: "input", type: "input", input: "", required: true },
|
{ name: "input", type: "input", input: "", required: true },
|
||||||
{ name: "code", type: "input", input: `
|
{ name: "code", type: "input", input: `
|
||||||
// 方法定义不能修改
|
// 方法定义不能修改
|
||||||
|
/**
|
||||||
|
* 处理与 r 相关的状态或数据,该影响范围仅限当前模块。
|
||||||
|
* @param {*} params 待处理的参数集合
|
||||||
|
*/
|
||||||
function handler(params) {
|
function handler(params) {
|
||||||
// 返回值是一个可序列化成 json 的 dict 或 object
|
// 返回值是一个可序列化成 json 的 dict 或 object
|
||||||
const result ={
|
const result ={
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:流程设计器主页面,负责编辑、校验、试运行、执行跟踪和快捷操作。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<el-container class="page__container">
|
<el-container class="page__container">
|
||||||
@ -314,10 +318,18 @@ const defaultEdgeOptions = {
|
|||||||
style: { stroke: "#ff6b35", strokeWidth: 2 },
|
style: { stroke: "#ff6b35", strokeWidth: 2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 dragover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const dragover = (e) => {
|
const dragover = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 drop 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const drop = (e) => {
|
const drop = (e) => {
|
||||||
let node = e.dataTransfer.getData("flowNode");
|
let node = e.dataTransfer.getData("flowNode");
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
@ -349,6 +361,10 @@ const drop = (e) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleConnect 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} connection 连接信息
|
||||||
|
*/
|
||||||
const handleConnect = (connection) => {
|
const handleConnect = (connection) => {
|
||||||
if (!connection.source || !connection.target) return;
|
if (!connection.source || !connection.target) return;
|
||||||
const edge = lf.addEdge({
|
const edge = lf.addEdge({
|
||||||
@ -361,6 +377,10 @@ const handleConnect = (connection) => {
|
|||||||
lf.emit("edge:add", { data: edge });
|
lf.emit("edge:add", { data: edge });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleNodeDoubleClick 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} { node } 调用方传入的 { node } 参数
|
||||||
|
*/
|
||||||
const handleNodeDoubleClick = ({ node }) => {
|
const handleNodeDoubleClick = ({ node }) => {
|
||||||
const data = lf.getGraphData().nodes.find((item) => item.id === node.id);
|
const data = lf.getGraphData().nodes.find((item) => item.id === node.id);
|
||||||
if (!data || ["selectArea", "branch", "stopLoop", "subStart", "subEnd", "end"].includes(data.type)) return;
|
if (!data || ["selectArea", "branch", "stopLoop", "subStart", "subEnd", "end"].includes(data.type)) return;
|
||||||
@ -368,6 +388,10 @@ const handleNodeDoubleClick = ({ node }) => {
|
|||||||
paramsDrawerData.value = data;
|
paramsDrawerData.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找 findLoopAtPoint 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} point 画布坐标
|
||||||
|
*/
|
||||||
const findLoopAtPoint = (point) => {
|
const findLoopAtPoint = (point) => {
|
||||||
return (vueFlow.getNodes.value || []).find((candidate) => {
|
return (vueFlow.getNodes.value || []).find((candidate) => {
|
||||||
if (candidate.data?.flowType !== "loop") return false;
|
if (candidate.data?.flowType !== "loop") return false;
|
||||||
@ -381,6 +405,10 @@ const findLoopAtPoint = (point) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找 findContainingLoop 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const findContainingLoop = (node) => {
|
const findContainingLoop = (node) => {
|
||||||
const position = node.computedPosition || node.position;
|
const position = node.computedPosition || node.position;
|
||||||
const width = Number(node.dimensions?.width || node.data?.size?.width || 0);
|
const width = Number(node.dimensions?.width || node.data?.size?.width || 0);
|
||||||
@ -388,12 +416,21 @@ const findContainingLoop = (node) => {
|
|||||||
return findLoopAtPoint({ x: position.x + width / 2, y: position.y + height / 2 });
|
return findLoopAtPoint({ x: position.x + width / 2, y: position.y + height / 2 });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 eventClientPoint 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const eventClientPoint = (event) => {
|
const eventClientPoint = (event) => {
|
||||||
const pointer = event?.touches?.[0] || event?.changedTouches?.[0] || event;
|
const pointer = event?.touches?.[0] || event?.changedTouches?.[0] || event;
|
||||||
if (!Number.isFinite(pointer?.clientX) || !Number.isFinite(pointer?.clientY)) return null;
|
if (!Number.isFinite(pointer?.clientX) || !Number.isFinite(pointer?.clientY)) return null;
|
||||||
return { x: pointer.clientX, y: pointer.clientY };
|
return { x: pointer.clientX, y: pointer.clientY };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleNodeDragStart 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} { node 调用方传入的 { node 参数
|
||||||
|
* @param {*} event } 调用方传入的 event } 参数
|
||||||
|
*/
|
||||||
const handleNodeDragStart = ({ node, event }) => {
|
const handleNodeDragStart = ({ node, event }) => {
|
||||||
const drag = lf.prepareLoopChildDrag(node.id);
|
const drag = lf.prepareLoopChildDrag(node.id);
|
||||||
const clientPoint = eventClientPoint(event);
|
const clientPoint = eventClientPoint(event);
|
||||||
@ -405,6 +442,11 @@ const handleNodeDragStart = ({ node, event }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新 updateLoopChildDrag 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} { node 调用方传入的 { node 参数
|
||||||
|
* @param {*} event } 调用方传入的 event } 参数
|
||||||
|
*/
|
||||||
const updateLoopChildDrag = ({ node, event }) => {
|
const updateLoopChildDrag = ({ node, event }) => {
|
||||||
const drag = loopChildDragContexts.get(node.id);
|
const drag = loopChildDragContexts.get(node.id);
|
||||||
const clientPoint = eventClientPoint(event);
|
const clientPoint = eventClientPoint(event);
|
||||||
@ -416,8 +458,16 @@ const updateLoopChildDrag = ({ node, event }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleNodeDrag 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} payload 事件数据
|
||||||
|
*/
|
||||||
const handleNodeDrag = (payload) => updateLoopChildDrag(payload);
|
const handleNodeDrag = (payload) => updateLoopChildDrag(payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleNodeDragStop 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} payload 事件数据
|
||||||
|
*/
|
||||||
const handleNodeDragStop = (payload) => {
|
const handleNodeDragStop = (payload) => {
|
||||||
const { node } = payload;
|
const { node } = payload;
|
||||||
updateLoopChildDrag(payload);
|
updateLoopChildDrag(payload);
|
||||||
@ -435,21 +485,37 @@ const handleNodeDragStop = (payload) => {
|
|||||||
lf.markChanged();
|
lf.markChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleNodesChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} changes 变更集合
|
||||||
|
*/
|
||||||
const handleNodesChange = (changes) => {
|
const handleNodesChange = (changes) => {
|
||||||
if (changes.some((change) => ["add", "remove"].includes(change.type) || (change.type === "position" && change.dragging === false))) {
|
if (changes.some((change) => ["add", "remove"].includes(change.type) || (change.type === "position" && change.dragging === false))) {
|
||||||
lf.markChanged();
|
lf.markChanged();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleEdgesChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} changes 变更集合
|
||||||
|
*/
|
||||||
const handleEdgesChange = (changes) => {
|
const handleEdgesChange = (changes) => {
|
||||||
if (changes.some((change) => ["add", "remove"].includes(change.type))) lf.markChanged();
|
if (changes.some((change) => ["add", "remove"].includes(change.type))) lf.markChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleEdgeClick 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} { event 调用方传入的 { event 参数
|
||||||
|
* @param {*} edge } 调用方传入的 edge } 参数
|
||||||
|
*/
|
||||||
const handleEdgeClick = ({ event, edge }) => {
|
const handleEdgeClick = ({ event, edge }) => {
|
||||||
event?.stopPropagation?.();
|
event?.stopPropagation?.();
|
||||||
lf.selectElementById(edge.id);
|
lf.selectElementById(edge.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handlePaneClick 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const handlePaneClick = () => lf.clearSelectElements();
|
const handlePaneClick = () => lf.clearSelectElements();
|
||||||
|
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
@ -507,6 +573,9 @@ const testRun = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 流程暂停
|
// 流程暂停
|
||||||
|
/**
|
||||||
|
* 处理 flowPauseFn 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const flowPauseFn = async () => {
|
const flowPauseFn = async () => {
|
||||||
const res = await flowPause(instId.value);
|
const res = await flowPause(instId.value);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@ -520,6 +589,9 @@ const hasRunResult = ref(false);
|
|||||||
let flowPollTimer = null;
|
let flowPollTimer = null;
|
||||||
let flowDisposed = false;
|
let flowDisposed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理 clearFlowPollTimer 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const clearFlowPollTimer = () => {
|
const clearFlowPollTimer = () => {
|
||||||
if (flowPollTimer !== null) {
|
if (flowPollTimer !== null) {
|
||||||
window.clearTimeout(flowPollTimer);
|
window.clearTimeout(flowPollTimer);
|
||||||
@ -527,6 +599,12 @@ const clearFlowPollTimer = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调度 scheduleFlowView 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} currentInstId 当前流程实例 ID
|
||||||
|
* @param {*} taskId 任务 ID
|
||||||
|
* @param {*} delay 延迟毫秒数
|
||||||
|
*/
|
||||||
const scheduleFlowView = (currentInstId, taskId = null, delay = 2000) => {
|
const scheduleFlowView = (currentInstId, taskId = null, delay = 2000) => {
|
||||||
clearFlowPollTimer();
|
clearFlowPollTimer();
|
||||||
flowPollTimer = window.setTimeout(() => {
|
flowPollTimer = window.setTimeout(() => {
|
||||||
@ -535,6 +613,9 @@ const scheduleFlowView = (currentInstId, taskId = null, delay = 2000) => {
|
|||||||
}, delay);
|
}, delay);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 flowResumeFn 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const flowResumeFn = async () => {
|
const flowResumeFn = async () => {
|
||||||
const res = await flowResume(instId.value);
|
const res = await flowResume(instId.value);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@ -545,6 +626,9 @@ const flowResumeFn = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 flowStopFn 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const flowStopFn = async () => {
|
const flowStopFn = async () => {
|
||||||
const res = await flowStop(instId.value);
|
const res = await flowStop(instId.value);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@ -593,6 +677,8 @@ const hasSameEdge = (edge, ignoredId) => lf.getGraphData().edges.some((item) =>
|
|||||||
));
|
));
|
||||||
|
|
||||||
const validEdge = (data) => {
|
const validEdge = (data) => {
|
||||||
|
// 校验思路:先确认端点存在,再按节点类型限制方向;最后结合锚点名称和现有连线判重。
|
||||||
|
// 任一阶段失败都会删除候选连线,避免非法边进入可保存的画布数据。
|
||||||
const sourceModel = lf.getNodeModelById(data.sourceNodeId);
|
const sourceModel = lf.getNodeModelById(data.sourceNodeId);
|
||||||
const targetModel = lf.getNodeModelById(data.targetNodeId);
|
const targetModel = lf.getNodeModelById(data.targetNodeId);
|
||||||
if (!sourceModel || !targetModel) {
|
if (!sourceModel || !targetModel) {
|
||||||
@ -664,6 +750,8 @@ const changeState = (value) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loopFlowView = async (instId, taskId = null) => {
|
const loopFlowView = async (instId, taskId = null) => {
|
||||||
|
// 轮询思路:优先使用任务 ID 查询指定执行,否则查询实例最新状态,再统一映射节点状态。
|
||||||
|
// 仅在非日志模式下根据终态停止或续排定时器,日志回放保持为一次性快照。
|
||||||
const params = {
|
const params = {
|
||||||
itemId: flowInfoData.value.itemId,
|
itemId: flowInfoData.value.itemId,
|
||||||
instId,
|
instId,
|
||||||
@ -1009,6 +1097,10 @@ const handleSingleNodeRobotChange = async (robotId) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 stationOptions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} stations 站点集合
|
||||||
|
*/
|
||||||
const stationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
const stationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
||||||
.filter((station) => station?.id !== undefined && station?.id !== null && String(station.id).trim())
|
.filter((station) => station?.id !== undefined && station?.id !== null && String(station.id).trim())
|
||||||
.map((station) => {
|
.map((station) => {
|
||||||
@ -1017,6 +1109,9 @@ const stationOptions = (stations) => (Array.isArray(stations) ? stations : [])
|
|||||||
return { value: id, label: description ? `${id} - ${description}` : id };
|
return { value: id, label: description ? `${id} - ${description}` : id };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadSingleNodeStations 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const loadSingleNodeStations = async () => {
|
const loadSingleNodeStations = async () => {
|
||||||
stationLoading.value = true;
|
stationLoading.value = true;
|
||||||
try {
|
try {
|
||||||
@ -1040,6 +1135,9 @@ const loadSingleNodeStations = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载 loadSingleNodeRobots 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const loadSingleNodeRobots = async () => {
|
const loadSingleNodeRobots = async () => {
|
||||||
const response = await getRobotList({ pageNum: 1, pageSize: 1000, connectStatus: '1' });
|
const response = await getRobotList({ pageNum: 1, pageSize: 1000, connectStatus: '1' });
|
||||||
singleNodeRobotOptions.value = (response.rows || []).map(item => ({
|
singleNodeRobotOptions.value = (response.rows || []).map(item => ({
|
||||||
@ -1048,6 +1146,10 @@ const loadSingleNodeRobots = async () => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 singleNodeExecution 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const singleNodeExecution = async (e) => {
|
const singleNodeExecution = async (e) => {
|
||||||
rememberSingleNodeRobot();
|
rememberSingleNodeRobot();
|
||||||
const { name, nodeType, nodeParams, action, nodeId } = e.detail;
|
const { name, nodeType, nodeParams, action, nodeId } = e.detail;
|
||||||
@ -1090,6 +1192,9 @@ const singleNodeExecution = async (e) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 execute 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const execute = async () => {
|
const execute = async () => {
|
||||||
if (nodeAction.value === "AGV_MOVE_TO_STATION") {
|
if (nodeAction.value === "AGV_MOVE_TO_STATION") {
|
||||||
const stationParam = formData.nodeParams.find((item) => item.name === "stationId");
|
const stationParam = formData.nodeParams.find((item) => item.name === "stationId");
|
||||||
@ -1124,6 +1229,9 @@ const execute = async () => {
|
|||||||
const showParamsDrawer = ref(false);
|
const showParamsDrawer = ref(false);
|
||||||
const paramsDrawerData = ref({});
|
const paramsDrawerData = ref({});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理 clearRun 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const clearRun = () => {
|
const clearRun = () => {
|
||||||
const { nodes } = lf.getGraphData();
|
const { nodes } = lf.getGraphData();
|
||||||
nodes.forEach((item) => {
|
nodes.forEach((item) => {
|
||||||
@ -1155,10 +1263,18 @@ const EDITABLE_SELECTOR = [
|
|||||||
"[role='dialog']",
|
"[role='dialog']",
|
||||||
].join(",");
|
].join(",");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 isEditableElement 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} element 调用方传入的 element 参数
|
||||||
|
*/
|
||||||
const isEditableElement = (element) => (
|
const isEditableElement = (element) => (
|
||||||
element instanceof Element && Boolean(element.closest(EDITABLE_SELECTOR))
|
element instanceof Element && Boolean(element.closest(EDITABLE_SELECTOR))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 isTextEditing 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const isTextEditing = (event) => {
|
const isTextEditing = (event) => {
|
||||||
const eventPath = typeof event.composedPath === "function" ? event.composedPath() : [];
|
const eventPath = typeof event.composedPath === "function" ? event.composedPath() : [];
|
||||||
if (eventPath.some(isEditableElement)) return true;
|
if (eventPath.some(isEditableElement)) return true;
|
||||||
@ -1166,13 +1282,23 @@ const isTextEditing = (event) => {
|
|||||||
return Boolean(window.getSelection()?.toString());
|
return Boolean(window.getSelection()?.toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制 copySelectedNodes 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const copySelectedNodes = (event) => {
|
const copySelectedNodes = (event) => {
|
||||||
|
// 复制只保留选中节点及它们之间的内部连线,避免粘贴时重建指向未选节点的关系。
|
||||||
|
// 节点数据在此深拷贝,后续生成新 ID 时不会反向污染原画布对象。
|
||||||
const selectedNodes = lf.getSelectElements().nodes;
|
const selectedNodes = lf.getSelectElements().nodes;
|
||||||
if (!selectedNodes.length) return;
|
if (!selectedNodes.length) return;
|
||||||
|
|
||||||
const graph = lf.getGraphData();
|
const graph = lf.getGraphData();
|
||||||
const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
|
const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
|
||||||
const selectedIds = new Set(selectedNodes.map((node) => node.id));
|
const selectedIds = new Set(selectedNodes.map((node) => node.id));
|
||||||
|
/**
|
||||||
|
* 新增 addChildren 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} nodeId 流程节点 ID
|
||||||
|
*/
|
||||||
const addChildren = (nodeId) => {
|
const addChildren = (nodeId) => {
|
||||||
const node = nodeById.get(nodeId);
|
const node = nodeById.get(nodeId);
|
||||||
(node?.children || []).forEach((childId) => {
|
(node?.children || []).forEach((childId) => {
|
||||||
@ -1200,11 +1326,23 @@ const copySelectedNodes = (event) => {
|
|||||||
pasteCount = 0;
|
pasteCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重映射 remapNodeAnchorId 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} anchorId 锚点 ID
|
||||||
|
* @param {*} oldNodeId 原节点 ID
|
||||||
|
* @param {*} newNodeId 新节点 ID
|
||||||
|
*/
|
||||||
const remapNodeAnchorId = (anchorId, oldNodeId, newNodeId) => {
|
const remapNodeAnchorId = (anchorId, oldNodeId, newNodeId) => {
|
||||||
if (!anchorId || !String(anchorId).startsWith(`${oldNodeId}_`)) return anchorId;
|
if (!anchorId || !String(anchorId).startsWith(`${oldNodeId}_`)) return anchorId;
|
||||||
return `${newNodeId}${String(anchorId).slice(oldNodeId.length)}`;
|
return `${newNodeId}${String(anchorId).slice(oldNodeId.length)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重映射 remapCopiedNodeReferences 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
* @param {*} idMap 节点 ID 映射
|
||||||
|
* @param {*} parentKey 递归父键名
|
||||||
|
*/
|
||||||
const remapCopiedNodeReferences = (value, idMap, parentKey = "") => {
|
const remapCopiedNodeReferences = (value, idMap, parentKey = "") => {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const result = value.map((item) => remapCopiedNodeReferences(item, idMap));
|
const result = value.map((item) => remapCopiedNodeReferences(item, idMap));
|
||||||
@ -1219,7 +1357,13 @@ const remapCopiedNodeReferences = (value, idMap, parentKey = "") => {
|
|||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 粘贴 pasteCopiedNodes 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const pasteCopiedNodes = (event) => {
|
const pasteCopiedNodes = (event) => {
|
||||||
|
// 先为全部节点建立旧 ID 到新 ID 的映射,再重建父子引用、锚点和内部连线。
|
||||||
|
// 该顺序保证循环、分组和分支之间的交叉引用都能解析到新的目标 ID。
|
||||||
if (!copiedGraph.nodes.length || flowStore.disableForm) return;
|
if (!copiedGraph.nodes.length || flowStore.disableForm) return;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -1297,6 +1441,10 @@ const pasteCopiedNodes = (event) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleKeyboardShortcut 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} event 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleKeyboardShortcut = (event) => {
|
const handleKeyboardShortcut = (event) => {
|
||||||
if (isTextEditing(event)) return;
|
if (isTextEditing(event)) return;
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:流程正常结束节点。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container">
|
<div class="node__container">
|
||||||
<div class="terminal-node">
|
<div class="terminal-node">
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:节点分组容器并展示成员数量。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="group__container">
|
<div class="group__container">
|
||||||
<NodeTitle
|
<NodeTitle
|
||||||
@ -33,6 +37,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, { ...properties, name });
|
lf.setProperties(props.model.id, { ...properties, name });
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:通用服务节点并响应运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -63,6 +67,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -80,6 +88,9 @@ const errorInfoData = ref('');
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:流程入口节点并响应运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
@ -42,6 +46,9 @@ const outputJsonData = ref({});
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:代码执行节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -61,6 +65,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -78,6 +86,9 @@ const errorInfoData = ref('');
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:当前循环上下文节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -47,6 +51,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -63,6 +71,9 @@ const outputJsonData = ref({});
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:通用设备执行节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -61,6 +65,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -78,6 +86,9 @@ const errorInfoData = ref('');
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:HTTP 请求执行节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -62,6 +66,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -79,6 +87,9 @@ const errorInfoData = ref('');
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:循环容器节点,管理循环体节点拖入和布局。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="group__container"
|
class="group__container"
|
||||||
@ -46,15 +50,27 @@ const emits = defineEmits(["bindRef", "addToGroup", "contentChange"]);
|
|||||||
const isDragOver = ref(false);
|
const isDragOver = ref(false);
|
||||||
const actualChildCount = computed(() => props.childCount ?? props.model?.children?.size ?? 0);
|
const actualChildCount = computed(() => props.childCount ?? props.model?.children?.size ?? 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleDragover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleDragover = (e) => {
|
const handleDragover = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
isDragOver.value = true;
|
isDragOver.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleDragleave 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleDragleave = (e) => {
|
const handleDragleave = (e) => {
|
||||||
if (!e.currentTarget.contains(e.relatedTarget)) isDragOver.value = false;
|
if (!e.currentTarget.contains(e.relatedTarget)) isDragOver.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleDrop 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleDrop = (e) => {
|
const handleDrop = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -84,6 +100,10 @@ const handleDrop = (e) => {
|
|||||||
lf.addToGroup(props.model.id, node.id, point.canvasOverlayPosition);
|
lf.addToGroup(props.model.id, node.id, point.canvasOverlayPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:识别执行节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -48,6 +52,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -64,6 +72,9 @@ const outputJsonData = ref({});
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:智能体执行节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -48,6 +52,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -64,6 +72,9 @@ const outputJsonData = ref({});
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:延时等待节点并展示运行状态。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" :class="props.model.id">
|
<div class="node__container" :class="props.model.id">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -47,6 +51,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(["contentChange"]);
|
const emits = defineEmits(["contentChange"]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -63,6 +71,9 @@ const outputJsonData = ref({});
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:终止循环节点,用于结束当前循环。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" >
|
<div class="node__container" >
|
||||||
<!-- 状态栏 -->
|
<!-- 状态栏 -->
|
||||||
@ -16,6 +20,10 @@ const props = defineProps({
|
|||||||
text: String,
|
text: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:循环体单次执行出口节点。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container">
|
<div class="node__container">
|
||||||
<div class="terminal-node">
|
<div class="terminal-node">
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:循环体单次执行入口节点。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container">
|
<div class="node__container">
|
||||||
<div class="terminal-node">
|
<div class="terminal-node">
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:条件分支节点,配置条件组和动态分支锚点。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="node__container" ref="switchRef" @mouseleave="setNodeProperties">
|
<div class="node__container" ref="switchRef" @mouseleave="setNodeProperties">
|
||||||
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
<NodeState :state="nodeOperatingStatus" :runtimes="runtimes" ref="nodeStateRef">
|
||||||
@ -299,10 +303,18 @@ const formData = reactive({
|
|||||||
nodeParams: props.properties?.conditions || [],
|
nodeParams: props.properties?.conditions || [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const addFormItem = () => {
|
const addFormItem = () => {
|
||||||
addCondition(0);
|
addCondition(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除 deleteFormItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const deleteFormItem = (id, index) => {
|
const deleteFormItem = (id, index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return;
|
return;
|
||||||
@ -316,6 +328,11 @@ const deleteFormItem = (id, index) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const quoteOptions = ref([]);
|
const quoteOptions = ref([]);
|
||||||
|
/**
|
||||||
|
* 处理 handleTypeChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} pIndex 条件组索引
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
*/
|
||||||
const handleTypeChange = (pIndex, index) => {
|
const handleTypeChange = (pIndex, index) => {
|
||||||
if (formData.nodeParams[pIndex].list[index].type === "input") {
|
if (formData.nodeParams[pIndex].list[index].type === "input") {
|
||||||
formData.nodeParams[pIndex].list[index].quote = "";
|
formData.nodeParams[pIndex].list[index].quote = "";
|
||||||
@ -328,6 +345,10 @@ const handleTypeChange = (pIndex, index) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addCondition 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} height 锚点纵向位置
|
||||||
|
*/
|
||||||
const addCondition = (height) => {
|
const addCondition = (height) => {
|
||||||
const id = randomUUID().replace(/-/g, "");
|
const id = randomUUID().replace(/-/g, "");
|
||||||
formData.nodeParams.push({
|
formData.nodeParams.push({
|
||||||
@ -351,6 +372,11 @@ const addCondition = (height) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增 addListItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} pIndex 条件组索引
|
||||||
|
* @param {*} cIndex 条件项索引
|
||||||
|
*/
|
||||||
const addListItem = (pIndex, cIndex) => {
|
const addListItem = (pIndex, cIndex) => {
|
||||||
formData.nodeParams[pIndex].list.push({
|
formData.nodeParams[pIndex].list.push({
|
||||||
name: "",
|
name: "",
|
||||||
@ -365,6 +391,11 @@ const addListItem = (pIndex, cIndex) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除 removeListItem 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} pIndex 条件组索引
|
||||||
|
* @param {*} cIndex 条件项索引
|
||||||
|
*/
|
||||||
const removeListItem = (pIndex, cIndex) => {
|
const removeListItem = (pIndex, cIndex) => {
|
||||||
if (cIndex === 0) {
|
if (cIndex === 0) {
|
||||||
return;
|
return;
|
||||||
@ -378,7 +409,12 @@ const removeListItem = (pIndex, cIndex) => {
|
|||||||
let anchorSyncFrame = null;
|
let anchorSyncFrame = null;
|
||||||
let resizeObserver = null;
|
let resizeObserver = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步 syncAnchorPositions 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const syncAnchorPositions = () => {
|
const syncAnchorPositions = () => {
|
||||||
|
// 从实际渲染后的条件卡片读取纵向中心点,再批量通知节点壳更新锚点。
|
||||||
|
// 批量同步可避免条件增删时逐个更新导致边路径在同一帧内反复抖动。
|
||||||
const root = switchRef.value;
|
const root = switchRef.value;
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
const rootRect = root.getBoundingClientRect();
|
const rootRect = root.getBoundingClientRect();
|
||||||
@ -393,6 +429,9 @@ const syncAnchorPositions = () => {
|
|||||||
emits("syncAnchors", positions);
|
emits("syncAnchors", positions);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调度 scheduleAnchorSync 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const scheduleAnchorSync = () => {
|
const scheduleAnchorSync = () => {
|
||||||
if (anchorSyncFrame !== null) cancelAnimationFrame(anchorSyncFrame);
|
if (anchorSyncFrame !== null) cancelAnimationFrame(anchorSyncFrame);
|
||||||
anchorSyncFrame = requestAnimationFrame(() => {
|
anchorSyncFrame = requestAnimationFrame(() => {
|
||||||
@ -401,6 +440,9 @@ const scheduleAnchorSync = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeProperties 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const setNodeProperties = async () => {
|
const setNodeProperties = async () => {
|
||||||
try {
|
try {
|
||||||
const valid = await dynamicForm.value.validate();
|
const valid = await dynamicForm.value.validate();
|
||||||
@ -418,6 +460,10 @@ const setNodeProperties = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 setNodeName 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
*/
|
||||||
const setNodeName = (name) => {
|
const setNodeName = (name) => {
|
||||||
const properties = lf.getProperties(props.model.id);
|
const properties = lf.getProperties(props.model.id);
|
||||||
lf.setProperties(props.model.id, {
|
lf.setProperties(props.model.id, {
|
||||||
@ -427,6 +473,13 @@ const setNodeName = (name) => {
|
|||||||
emits("contentChange");
|
emits("contentChange");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 visibleChange 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
* @param {*} index 目标项索引
|
||||||
|
* @param {*} pIndex 条件组索引
|
||||||
|
*/
|
||||||
const visibleChange = async (value, type, index, pIndex) => {
|
const visibleChange = async (value, type, index, pIndex) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
const option = getInput(props.model.id);
|
const option = getInput(props.model.id);
|
||||||
@ -468,6 +521,9 @@ watch(
|
|||||||
|
|
||||||
const nodeStateRef = ref(null);
|
const nodeStateRef = ref(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭 closePopover 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
*/
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
if (nodeStateRef.value) {
|
if (nodeStateRef.value) {
|
||||||
nodeStateRef.value.closePopover();
|
nodeStateRef.value.closePopover();
|
||||||
@ -475,6 +531,10 @@ const closePopover = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isEditing = ref(false)
|
const isEditing = ref(false)
|
||||||
|
/**
|
||||||
|
* 处理 handleInputFocus 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleInputFocus = (e) => {
|
const handleInputFocus = (e) => {
|
||||||
// 阻止事件冒泡到流程画布
|
// 阻止事件冒泡到流程画布
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@ -482,6 +542,10 @@ const handleInputFocus = (e) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 handleInputKeydown 对应的数据或交互;作用范围仅限当前组件或模块。
|
||||||
|
* @param {*} e 触发操作的浏览器事件
|
||||||
|
*/
|
||||||
const handleInputKeydown = (e) => {
|
const handleInputKeydown = (e) => {
|
||||||
// 阻止事件冒泡到流程节点,避免被画布快捷键拦截
|
// 阻止事件冒泡到流程节点,避免被画布快捷键拦截
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:Vue Flow 连线渲染组件,负责路径展示及选中状态下的删除操作。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<BaseEdge
|
<BaseEdge
|
||||||
:id="id"
|
:id="id"
|
||||||
@ -54,6 +58,9 @@ const deleteActionStyle = computed(() => ({
|
|||||||
transform: `translate(-50%, -50%) translate(${pathData.value[1]}px, ${pathData.value[2]}px)`,
|
transform: `translate(-50%, -50%) translate(${pathData.value[1]}px, ${pathData.value[2]}px)`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除与 edge 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
*/
|
||||||
const deleteEdge = () => {
|
const deleteEdge = () => {
|
||||||
window.lf?.deleteEdge(props.id);
|
window.lf?.deleteEdge(props.id);
|
||||||
window.lf?.clearSelectElements();
|
window.lf?.clearSelectElements();
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
<!--
|
||||||
|
* 文件说明:Vue Flow 节点壳组件,负责锚点、连接规则、分支位置及分组交互适配。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="flow-node-shell"
|
class="flow-node-shell"
|
||||||
@ -130,22 +134,39 @@ const branchAnchors = computed(() => {
|
|||||||
});
|
});
|
||||||
const model = computed(() => window.lf?.getNodeModelById(props.id));
|
const model = computed(() => window.lf?.getNodeModelById(props.id));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取与 loop scope 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} nodeId 流程节点 ID
|
||||||
|
*/
|
||||||
const getLoopScope = (nodeId) => {
|
const getLoopScope = (nodeId) => {
|
||||||
const node = vueFlow.findNode(nodeId);
|
const node = vueFlow.findNode(nodeId);
|
||||||
const parent = node?.parentNode ? vueFlow.findNode(node.parentNode) : null;
|
const parent = node?.parentNode ? vueFlow.findNode(node.parentNode) : null;
|
||||||
return parent?.data?.flowType === "loop" ? parent.id : null;
|
return parent?.data?.flowType === "loop" ? parent.id : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断与 valid loop connection 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} connection 待校验或创建的连接信息
|
||||||
|
*/
|
||||||
const isValidLoopConnection = (connection) => {
|
const isValidLoopConnection = (connection) => {
|
||||||
if (!connection.source || !connection.target || connection.source === connection.target) return false;
|
if (!connection.source || !connection.target || connection.source === connection.target) return false;
|
||||||
return getLoopScope(connection.source) === getLoopScope(connection.target);
|
return getLoopScope(connection.source) === getLoopScope(connection.target);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步与 anchors 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} anchors 需要同步的锚点集合
|
||||||
|
*/
|
||||||
const syncAnchors = (anchors) => {
|
const syncAnchors = (anchors) => {
|
||||||
window.lf?.setProperties(props.id, { ...window.lf.getProperties(props.id), anchor: anchors });
|
window.lf?.setProperties(props.id, { ...window.lf.getProperties(props.id), anchor: anchors });
|
||||||
vueFlow.updateNodeInternals([props.id]);
|
vueFlow.updateNodeInternals([props.id]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增与 anchor 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} height 锚点纵向位置
|
||||||
|
* @param {*} anchorId 分支锚点 ID
|
||||||
|
*/
|
||||||
const addAnchor = (height, anchorId) => {
|
const addAnchor = (height, anchorId) => {
|
||||||
const anchors = [...branchAnchors.value];
|
const anchors = [...branchAnchors.value];
|
||||||
if (!anchors.some((anchor) => anchor.id === anchorId)) {
|
if (!anchors.some((anchor) => anchor.id === anchorId)) {
|
||||||
@ -154,8 +175,21 @@ const addAnchor = (height, anchorId) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除与 anchor 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} anchorId 分支锚点 ID
|
||||||
|
*/
|
||||||
const removeAnchor = (anchorId) => syncAnchors(branchAnchors.value.filter((anchor) => anchor.id !== anchorId));
|
const removeAnchor = (anchorId) => syncAnchors(branchAnchors.value.filter((anchor) => anchor.id !== anchorId));
|
||||||
|
/**
|
||||||
|
* 更新与 anchor 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} height 锚点纵向位置
|
||||||
|
* @param {*} anchorId 分支锚点 ID
|
||||||
|
*/
|
||||||
const changeAnchor = (height, anchorId) => syncAnchors(branchAnchors.value.map((anchor) => anchor.id === anchorId ? { ...anchor, height } : anchor));
|
const changeAnchor = (height, anchorId) => syncAnchors(branchAnchors.value.map((anchor) => anchor.id === anchorId ? { ...anchor, height } : anchor));
|
||||||
|
/**
|
||||||
|
* 同步与 branch anchors 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} positions 分支锚点位置集合
|
||||||
|
*/
|
||||||
const syncBranchAnchors = (positions = []) => {
|
const syncBranchAnchors = (positions = []) => {
|
||||||
if (!positions.length) return;
|
if (!positions.length) return;
|
||||||
const positionMap = new Map(positions.map((item) => [item.id, Number(item.height || 0)]));
|
const positionMap = new Map(positions.map((item) => [item.id, Number(item.height || 0)]));
|
||||||
@ -176,11 +210,23 @@ const syncBranchAnchors = (positions = []) => {
|
|||||||
if (changed) syncAnchors(anchors);
|
if (changed) syncAnchors(anchors);
|
||||||
else vueFlow.updateNodeInternals([props.id]);
|
else vueFlow.updateNodeInternals([props.id]);
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 处理与 content changed 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
*/
|
||||||
const contentChanged = () => {
|
const contentChanged = () => {
|
||||||
vueFlow.updateNodeInternals([props.id]);
|
vueFlow.updateNodeInternals([props.id]);
|
||||||
window.lf?.markChanged();
|
window.lf?.markChanged();
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 绑定与 component 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} instance 节点组件实例
|
||||||
|
*/
|
||||||
const bindComponent = (instance) => window.lf?.registerComponentInstance(props.id, instance);
|
const bindComponent = (instance) => window.lf?.registerComponentInstance(props.id, instance);
|
||||||
|
/**
|
||||||
|
* 新增与 to group 相关的状态或数据,该影响范围仅限当前组件。
|
||||||
|
* @param {*} childId 子节点 ID
|
||||||
|
* @param {*} dropCenter 拖放中心点坐标
|
||||||
|
*/
|
||||||
const addToGroup = (childId, dropCenter) => window.lf?.addToGroup(props.id, childId, dropCenter);
|
const addToGroup = (childId, dropCenter) => window.lf?.addToGroup(props.id, childId, dropCenter);
|
||||||
|
|
||||||
onMounted(() => bindComponent(componentRef.value));
|
onMounted(() => bindComponent(componentRef.value));
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* 文件说明:旧流程数据与 Vue Flow 状态、操作 API 之间的兼容适配层。
|
||||||
|
* 作用范围:仅服务于流程设计器模块。
|
||||||
|
*/
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
import { MarkerType } from "@vue-flow/core";
|
import { MarkerType } from "@vue-flow/core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 克隆 clone 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} value 待处理的新值
|
||||||
|
*/
|
||||||
const clone = (value) => JSON.parse(JSON.stringify(value ?? {}));
|
const clone = (value) => JSON.parse(JSON.stringify(value ?? {}));
|
||||||
|
|
||||||
const GROUP_TYPES = new Set(["loop", "selectArea"]);
|
const GROUP_TYPES = new Set(["loop", "selectArea"]);
|
||||||
@ -11,6 +19,9 @@ const LOOP_BODY_INSET = { left: 24, top: 112, right: 24, bottom: 24 };
|
|||||||
const GROUP_BODY_INSET = { left: 24, top: 120, right: 24, bottom: 24 };
|
const GROUP_BODY_INSET = { left: 24, top: 120, right: 24, bottom: 24 };
|
||||||
const LOOP_MIN_SIZE = { width: 520, height: 360 };
|
const LOOP_MIN_SIZE = { width: 520, height: 360 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 loopChildExtent 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const loopChildExtent = () => ({
|
const loopChildExtent = () => ({
|
||||||
range: "parent",
|
range: "parent",
|
||||||
padding: [
|
padding: [
|
||||||
@ -21,6 +32,9 @@ const loopChildExtent = () => ({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编组 groupChildExtent 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const groupChildExtent = () => ({
|
const groupChildExtent = () => ({
|
||||||
range: "parent",
|
range: "parent",
|
||||||
padding: [
|
padding: [
|
||||||
@ -31,6 +45,10 @@ const groupChildExtent = () => ({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 nodeSize 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const nodeSize = (node) => {
|
const nodeSize = (node) => {
|
||||||
const width = Number(node.properties?.width || node.width);
|
const width = Number(node.properties?.width || node.width);
|
||||||
const height = Number(node.properties?.height || node.height);
|
const height = Number(node.properties?.height || node.height);
|
||||||
@ -45,9 +63,21 @@ const nodeSize = (node) => {
|
|||||||
return { width: 372, height: 180 };
|
return { width: 372, height: 180 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 edgeId 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const edgeId = () => `edge_${uuid().replace(/-/g, "")}`;
|
const edgeId = () => `edge_${uuid().replace(/-/g, "")}`;
|
||||||
|
/**
|
||||||
|
* 处理 nodeId 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const nodeId = () => uuid().replace(/-/g, "");
|
const nodeId = () => uuid().replace(/-/g, "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 toVueNode 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
* @param {*} sizeOverride 调用方传入的 sizeOverride 参数
|
||||||
|
* @param {*} positionOverride 调用方传入的 positionOverride 参数
|
||||||
|
*/
|
||||||
const toVueNode = (node, sizeOverride, positionOverride) => {
|
const toVueNode = (node, sizeOverride, positionOverride) => {
|
||||||
const normalized = clone(node);
|
const normalized = clone(node);
|
||||||
normalized.id ||= nodeId();
|
normalized.id ||= nodeId();
|
||||||
@ -98,6 +128,10 @@ const toVueNode = (node, sizeOverride, positionOverride) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 toVueEdge 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} edge 调用方传入的 edge 参数
|
||||||
|
*/
|
||||||
const toVueEdge = (edge) => {
|
const toVueEdge = (edge) => {
|
||||||
const normalized = clone(edge);
|
const normalized = clone(edge);
|
||||||
normalized.id ||= edgeId();
|
normalized.id ||= edgeId();
|
||||||
@ -124,7 +158,13 @@ const toVueEdge = (edge) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联 attachChildrenToGroups 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} nodes 调用方传入的 nodes 参数
|
||||||
|
*/
|
||||||
const attachChildrenToGroups = (nodes) => {
|
const attachChildrenToGroups = (nodes) => {
|
||||||
|
// 先建立节点索引和显式父子关系,再用旧数据中的 children 补齐缺失关系。
|
||||||
|
// 最后统一换算相对坐标,避免父节点尚未就绪时提前计算造成位置漂移。
|
||||||
const nodeLookup = new Map(nodes.map((node) => [node.id, node]));
|
const nodeLookup = new Map(nodes.map((node) => [node.id, node]));
|
||||||
const declaredParents = new Map();
|
const declaredParents = new Map();
|
||||||
|
|
||||||
@ -200,9 +240,19 @@ export const createFlowFacade = (store) => {
|
|||||||
let history = [];
|
let history = [];
|
||||||
let historyIndex = -1;
|
let historyIndex = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 getNodes 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const getNodes = () => store.getNodes.value || [];
|
const getNodes = () => store.getNodes.value || [];
|
||||||
|
/**
|
||||||
|
* 获取 getEdges 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const getEdges = () => store.getEdges.value || [];
|
const getEdges = () => store.getEdges.value || [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 backendNode 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const backendNode = (node) => {
|
const backendNode = (node) => {
|
||||||
const result = clone(node.data.backend);
|
const result = clone(node.data.backend);
|
||||||
const size = {
|
const size = {
|
||||||
@ -242,6 +292,10 @@ export const createFlowFacade = (store) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 backendEdge 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} edge 调用方传入的 edge 参数
|
||||||
|
*/
|
||||||
const backendEdge = (edge) => ({
|
const backendEdge = (edge) => ({
|
||||||
...clone(edge.data?.backend),
|
...clone(edge.data?.backend),
|
||||||
id: edge.id,
|
id: edge.id,
|
||||||
@ -252,10 +306,18 @@ export const createFlowFacade = (store) => {
|
|||||||
targetAnchorId: edge.targetHandle || `${edge.target}_3`,
|
targetAnchorId: edge.targetHandle || `${edge.target}_3`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 emit 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
* @param {*} payload 事件数据
|
||||||
|
*/
|
||||||
const emit = (name, payload) => {
|
const emit = (name, payload) => {
|
||||||
(handlers.get(name) || []).forEach((handler) => handler(payload));
|
(handlers.get(name) || []).forEach((handler) => handler(payload));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 recordHistory 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const recordHistory = () => {
|
const recordHistory = () => {
|
||||||
if (historySuspended) return;
|
if (historySuspended) return;
|
||||||
const graph = facade.getGraphData();
|
const graph = facade.getGraphData();
|
||||||
@ -267,12 +329,19 @@ export const createFlowFacade = (store) => {
|
|||||||
historyIndex = history.length - 1;
|
historyIndex = history.length - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新 changed 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const changed = () => {
|
const changed = () => {
|
||||||
if (historySuspended) return;
|
if (historySuspended) return;
|
||||||
recordHistory();
|
recordHistory();
|
||||||
emit("history:change", { data: facade.getGraphData() });
|
emit("history:change", { data: facade.getGraphData() });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 getNodeRect 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const getNodeRect = (node) => {
|
const getNodeRect = (node) => {
|
||||||
const parent = node.parentNode ? store.findNode(node.parentNode) : null;
|
const parent = node.parentNode ? store.findNode(node.parentNode) : null;
|
||||||
const parentPosition = parent?.position || parent?.computedPosition || { x: 0, y: 0 };
|
const parentPosition = parent?.position || parent?.computedPosition || { x: 0, y: 0 };
|
||||||
@ -287,9 +356,17 @@ export const createFlowFacade = (store) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 getLoopLayoutState 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} group 调用方传入的 group 参数
|
||||||
|
*/
|
||||||
const getLoopLayoutState = (group) => {
|
const getLoopLayoutState = (group) => {
|
||||||
const current = getNodeRect(group);
|
const current = getNodeRect(group);
|
||||||
const existing = loopLayoutStates.get(group.id);
|
const existing = loopLayoutStates.get(group.id);
|
||||||
|
/**
|
||||||
|
* 处理 if 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} !existing 调用方传入的 !existing 参数
|
||||||
|
*/
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
const state = { base: { ...current }, last: { ...current } };
|
const state = { base: { ...current }, last: { ...current } };
|
||||||
loopLayoutStates.set(group.id, state);
|
loopLayoutStates.set(group.id, state);
|
||||||
@ -298,6 +375,10 @@ export const createFlowFacade = (store) => {
|
|||||||
|
|
||||||
const sizeChanged = Math.abs(current.width - existing.last.width) > 1
|
const sizeChanged = Math.abs(current.width - existing.last.width) > 1
|
||||||
|| Math.abs(current.height - existing.last.height) > 1;
|
|| Math.abs(current.height - existing.last.height) > 1;
|
||||||
|
/**
|
||||||
|
* 处理 if 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} sizeChanged 调用方传入的 sizeChanged 参数
|
||||||
|
*/
|
||||||
if (sizeChanged) {
|
if (sizeChanged) {
|
||||||
existing.base = { ...current };
|
existing.base = { ...current };
|
||||||
} else {
|
} else {
|
||||||
@ -310,6 +391,12 @@ export const createFlowFacade = (store) => {
|
|||||||
return existing;
|
return existing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 布局 layoutLoop 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} group 调用方传入的 group 参数
|
||||||
|
* @param {*} activeChildId 调用方传入的 activeChildId 参数
|
||||||
|
* @param {*} activePosition 调用方传入的 activePosition 参数
|
||||||
|
*/
|
||||||
const layoutLoop = (group, activeChildId, activePosition) => {
|
const layoutLoop = (group, activeChildId, activePosition) => {
|
||||||
const state = getLoopLayoutState(group);
|
const state = getLoopLayoutState(group);
|
||||||
const children = getNodes().filter((node) => node.parentNode === group.id);
|
const children = getNodes().filter((node) => node.parentNode === group.id);
|
||||||
@ -365,8 +452,16 @@ export const createFlowFacade = (store) => {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 getAnchors 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
const getAnchors = (node) => {
|
const getAnchors = (node) => {
|
||||||
const type = node.data.flowType;
|
const type = node.data.flowType;
|
||||||
|
/**
|
||||||
|
* 处理 if 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} type 目标类型
|
||||||
|
*/
|
||||||
if (type === "branch") {
|
if (type === "branch") {
|
||||||
return [
|
return [
|
||||||
{ id: `${node.id}_entry`, name: "left" },
|
{ id: `${node.id}_entry`, name: "left" },
|
||||||
@ -382,6 +477,10 @@ export const createFlowFacade = (store) => {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 modelFor 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
const modelFor = (id) => {
|
const modelFor = (id) => {
|
||||||
const node = store.findNode(id);
|
const node = store.findNode(id);
|
||||||
if (!node) return null;
|
if (!node) return null;
|
||||||
@ -415,31 +514,58 @@ export const createFlowFacade = (store) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const facade = {
|
const facade = {
|
||||||
|
/**
|
||||||
|
* 订阅 on 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
* @param {*} handler 事件处理函数
|
||||||
|
*/
|
||||||
on(name, handler) {
|
on(name, handler) {
|
||||||
const list = handlers.get(name) || [];
|
const list = handlers.get(name) || [];
|
||||||
list.push(handler);
|
list.push(handler);
|
||||||
handlers.set(name, list);
|
handlers.set(name, list);
|
||||||
return () => facade.off(name, handler);
|
return () => facade.off(name, handler);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 订阅 once 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
* @param {*} handler 事件处理函数
|
||||||
|
*/
|
||||||
once(name, handler) {
|
once(name, handler) {
|
||||||
|
/**
|
||||||
|
* 处理 wrapped 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} payload 事件数据
|
||||||
|
*/
|
||||||
const wrapped = (payload) => {
|
const wrapped = (payload) => {
|
||||||
facade.off(name, wrapped);
|
facade.off(name, wrapped);
|
||||||
handler(payload);
|
handler(payload);
|
||||||
};
|
};
|
||||||
facade.on(name, wrapped);
|
facade.on(name, wrapped);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 取消订阅 off 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} name 名称或事件名称
|
||||||
|
* @param {*} handler 事件处理函数
|
||||||
|
*/
|
||||||
off(name, handler) {
|
off(name, handler) {
|
||||||
if (!handler) handlers.delete(name);
|
if (!handler) handlers.delete(name);
|
||||||
else handlers.set(name, (handlers.get(name) || []).filter((item) => item !== handler));
|
else handlers.set(name, (handlers.get(name) || []).filter((item) => item !== handler));
|
||||||
},
|
},
|
||||||
emit,
|
emit,
|
||||||
markChanged: changed,
|
markChanged: changed,
|
||||||
|
/**
|
||||||
|
* 获取 getGraphData 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
getGraphData() {
|
getGraphData() {
|
||||||
return {
|
return {
|
||||||
nodes: getNodes().map(backendNode),
|
nodes: getNodes().map(backendNode),
|
||||||
edges: getEdges().map(backendEdge),
|
edges: getEdges().map(backendEdge),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 渲染 render 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} graph 调用方传入的 graph 参数
|
||||||
|
* @param {*} options 行为配置
|
||||||
|
*/
|
||||||
render(graph, options = {}) {
|
render(graph, options = {}) {
|
||||||
historySuspended = true;
|
historySuspended = true;
|
||||||
loopLayoutStates.clear();
|
loopLayoutStates.clear();
|
||||||
@ -456,6 +582,9 @@ export const createFlowFacade = (store) => {
|
|||||||
}))
|
}))
|
||||||
: options.nodePositions;
|
: options.nodePositions;
|
||||||
const data = toVueFlowData(graph, { nodeSizes, nodePositions });
|
const data = toVueFlowData(graph, { nodeSizes, nodePositions });
|
||||||
|
/**
|
||||||
|
* 处理 finishRender 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const finishRender = () => {
|
const finishRender = () => {
|
||||||
historySuspended = false;
|
historySuspended = false;
|
||||||
if (options.resetHistory !== false) {
|
if (options.resetHistory !== false) {
|
||||||
@ -465,6 +594,9 @@ export const createFlowFacade = (store) => {
|
|||||||
}
|
}
|
||||||
nextTick(() => store.updateNodeInternals());
|
nextTick(() => store.updateNodeInternals());
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* 处理 applyData 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
const applyData = () => {
|
const applyData = () => {
|
||||||
store.setNodes(data.nodes);
|
store.setNodes(data.nodes);
|
||||||
store.setEdges(data.edges);
|
store.setEdges(data.edges);
|
||||||
@ -482,12 +614,20 @@ export const createFlowFacade = (store) => {
|
|||||||
applyData();
|
applyData();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 新增 addNode 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} node 当前流程节点
|
||||||
|
*/
|
||||||
addNode(node) {
|
addNode(node) {
|
||||||
const vueNode = toVueNode(node);
|
const vueNode = toVueNode(node);
|
||||||
store.addNodes(vueNode);
|
store.addNodes(vueNode);
|
||||||
changed();
|
changed();
|
||||||
return backendNode(vueNode);
|
return backendNode(vueNode);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 删除 deleteNode 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
deleteNode(id) {
|
deleteNode(id) {
|
||||||
const target = store.findNode(id);
|
const target = store.findNode(id);
|
||||||
if (target?.data?.flowType === "selectArea") {
|
if (target?.data?.flowType === "selectArea") {
|
||||||
@ -513,6 +653,10 @@ export const createFlowFacade = (store) => {
|
|||||||
changed();
|
changed();
|
||||||
if (parentId) nextTick(() => facade.resizeGroupToChildren(parentId));
|
if (parentId) nextTick(() => facade.resizeGroupToChildren(parentId));
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 新增 addEdge 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} edge 调用方传入的 edge 参数
|
||||||
|
*/
|
||||||
addEdge(edge) {
|
addEdge(edge) {
|
||||||
const vueEdge = toVueEdge(edge);
|
const vueEdge = toVueEdge(edge);
|
||||||
const source = store.findNode(vueEdge.source);
|
const source = store.findNode(vueEdge.source);
|
||||||
@ -522,17 +666,34 @@ export const createFlowFacade = (store) => {
|
|||||||
changed();
|
changed();
|
||||||
return backendEdge(vueEdge);
|
return backendEdge(vueEdge);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 删除 deleteEdge 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
deleteEdge(id) {
|
deleteEdge(id) {
|
||||||
store.removeEdges(id);
|
store.removeEdges(id);
|
||||||
changed();
|
changed();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 删除 deleteEdgeByNodeId 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
deleteEdgeByNodeId(id) {
|
deleteEdgeByNodeId(id) {
|
||||||
store.removeEdges(getEdges().filter((edge) => edge.source === id || edge.target === id));
|
store.removeEdges(getEdges().filter((edge) => edge.source === id || edge.target === id));
|
||||||
changed();
|
changed();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 获取 getProperties 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
getProperties(id) {
|
getProperties(id) {
|
||||||
return clone(store.findNode(id)?.data?.properties || {});
|
return clone(store.findNode(id)?.data?.properties || {});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 设置 setProperties 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
* @param {*} properties 调用方传入的 properties 参数
|
||||||
|
*/
|
||||||
setProperties(id, properties) {
|
setProperties(id, properties) {
|
||||||
const node = store.findNode(id);
|
const node = store.findNode(id);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
@ -541,15 +702,25 @@ export const createFlowFacade = (store) => {
|
|||||||
changed();
|
changed();
|
||||||
},
|
},
|
||||||
getNodeModelById: modelFor,
|
getNodeModelById: modelFor,
|
||||||
|
/**
|
||||||
|
* 获取 getSelectElements 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
getSelectElements() {
|
getSelectElements() {
|
||||||
return {
|
return {
|
||||||
nodes: (store.getSelectedNodes.value || []).map(backendNode),
|
nodes: (store.getSelectedNodes.value || []).map(backendNode),
|
||||||
edges: (store.getSelectedEdges.value || []).map(backendEdge),
|
edges: (store.getSelectedEdges.value || []).map(backendEdge),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 清理 clearSelectElements 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
clearSelectElements() {
|
clearSelectElements() {
|
||||||
store.removeSelectedElements();
|
store.removeSelectedElements();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 selectElementById 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
*/
|
||||||
selectElementById(id) {
|
selectElementById(id) {
|
||||||
store.removeSelectedElements();
|
store.removeSelectedElements();
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
@ -558,33 +729,63 @@ export const createFlowFacade = (store) => {
|
|||||||
const edge = store.findEdge(id);
|
const edge = store.findEdge(id);
|
||||||
if (edge) store.addSelectedEdges([edge]);
|
if (edge) store.addSelectedEdges([edge]);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 selectElementsByIds 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} ids 调用方传入的 ids 参数
|
||||||
|
*/
|
||||||
selectElementsByIds(ids = []) {
|
selectElementsByIds(ids = []) {
|
||||||
store.removeSelectedElements();
|
store.removeSelectedElements();
|
||||||
const nodes = ids.map((id) => store.findNode(id)).filter(Boolean);
|
const nodes = ids.map((id) => store.findNode(id)).filter(Boolean);
|
||||||
if (nodes.length) store.addSelectedNodes(nodes);
|
if (nodes.length) store.addSelectedNodes(nodes);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 focusOn 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} { id } 调用方传入的 { id } 参数
|
||||||
|
*/
|
||||||
focusOn({ id }) {
|
focusOn({ id }) {
|
||||||
const node = store.findNode(id);
|
const node = store.findNode(id);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
const center = backendNode(node);
|
const center = backendNode(node);
|
||||||
store.setCenter(center.x, center.y, { zoom: Math.max(store.viewport.value?.zoom || 1, 0.7), duration: 300 });
|
store.setCenter(center.x, center.y, { zoom: Math.max(store.viewport.value?.zoom || 1, 0.7), duration: 300 });
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 fitView 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
fitView() {
|
fitView() {
|
||||||
return store.fitView({ padding: 0.18, duration: 300 });
|
return store.fitView({ padding: 0.18, duration: 300 });
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 translateCenter 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
translateCenter() {
|
translateCenter() {
|
||||||
return facade.fitView();
|
return facade.fitView();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 缩放 zoom 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} scale 缩放比例
|
||||||
|
* @param {*} center 缩放中心
|
||||||
|
*/
|
||||||
zoom(scale, center) {
|
zoom(scale, center) {
|
||||||
if (Array.isArray(center) && center.length === 2) {
|
if (Array.isArray(center) && center.length === 2) {
|
||||||
return store.setCenter(center[0], center[1], { zoom: scale, duration: 250 });
|
return store.setCenter(center[0], center[1], { zoom: scale, duration: 250 });
|
||||||
}
|
}
|
||||||
return store.zoomTo(scale, { duration: 250 });
|
return store.zoomTo(scale, { duration: 250 });
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 获取 getPointByClient 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} x 客户端横坐标
|
||||||
|
* @param {*} y 客户端纵坐标
|
||||||
|
*/
|
||||||
getPointByClient(x, y) {
|
getPointByClient(x, y) {
|
||||||
const point = store.screenToFlowCoordinate({ x, y });
|
const point = store.screenToFlowCoordinate({ x, y });
|
||||||
return { canvasOverlayPosition: point, domOverlayPosition: point };
|
return { canvasOverlayPosition: point, domOverlayPosition: point };
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 新增 addToGroup 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} groupId 分组节点 ID
|
||||||
|
* @param {*} childId 子节点 ID
|
||||||
|
* @param {*} dropCenter 拖放中心坐标
|
||||||
|
*/
|
||||||
addToGroup(groupId, childId, dropCenter) {
|
addToGroup(groupId, childId, dropCenter) {
|
||||||
const group = store.findNode(groupId);
|
const group = store.findNode(groupId);
|
||||||
const child = store.findNode(childId);
|
const child = store.findNode(childId);
|
||||||
@ -610,7 +811,14 @@ export const createFlowFacade = (store) => {
|
|||||||
changed();
|
changed();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 编组 groupNodes 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} groupNode 调用方传入的 groupNode 参数
|
||||||
|
* @param {*} childIds 子节点 ID 集合
|
||||||
|
*/
|
||||||
groupNodes(groupNode, childIds = []) {
|
groupNodes(groupNode, childIds = []) {
|
||||||
|
// 先计算选中节点的外接矩形确定容器尺寸,再把子节点坐标转换为容器内相对坐标。
|
||||||
|
// 与分组外节点相连的边保持不变,此处仅更新节点层级和几何信息。
|
||||||
const graph = facade.getGraphData();
|
const graph = facade.getGraphData();
|
||||||
const selectedIds = new Set(childIds);
|
const selectedIds = new Set(childIds);
|
||||||
const children = graph.nodes.filter((node) => (
|
const children = graph.nodes.filter((node) => (
|
||||||
@ -641,6 +849,10 @@ export const createFlowFacade = (store) => {
|
|||||||
});
|
});
|
||||||
return clone(group);
|
return clone(group);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 处理 ungroup 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} groupId 分组节点 ID
|
||||||
|
*/
|
||||||
ungroup(groupId) {
|
ungroup(groupId) {
|
||||||
const graph = facade.getGraphData();
|
const graph = facade.getGraphData();
|
||||||
const group = graph.nodes.find((node) => node.id === groupId && node.type === "selectArea");
|
const group = graph.nodes.find((node) => node.id === groupId && node.type === "selectArea");
|
||||||
@ -668,6 +880,10 @@ export const createFlowFacade = (store) => {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 准备 prepareLoopChildDrag 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} childId 子节点 ID
|
||||||
|
*/
|
||||||
prepareLoopChildDrag(childId) {
|
prepareLoopChildDrag(childId) {
|
||||||
const child = store.findNode(childId);
|
const child = store.findNode(childId);
|
||||||
const group = child?.parentNode ? store.findNode(child.parentNode) : null;
|
const group = child?.parentNode ? store.findNode(child.parentNode) : null;
|
||||||
@ -680,16 +896,35 @@ export const createFlowFacade = (store) => {
|
|||||||
const rect = getNodeRect(child);
|
const rect = getNodeRect(child);
|
||||||
return { groupId: group.id, position: { x: rect.x, y: rect.y } };
|
return { groupId: group.id, position: { x: rect.x, y: rect.y } };
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 布局 layoutLoopDuringDrag 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} groupId 分组节点 ID
|
||||||
|
* @param {*} childId 子节点 ID
|
||||||
|
* @param {*} position 调用方传入的 position 参数
|
||||||
|
*/
|
||||||
layoutLoopDuringDrag(groupId, childId, position) {
|
layoutLoopDuringDrag(groupId, childId, position) {
|
||||||
const group = store.findNode(groupId);
|
const group = store.findNode(groupId);
|
||||||
if (!group || group.data.flowType !== "loop" || !position) return;
|
if (!group || group.data.flowType !== "loop" || !position) return;
|
||||||
layoutLoop(group, childId, position);
|
layoutLoop(group, childId, position);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 调整 resizeGroupToChildren 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} groupId 分组节点 ID
|
||||||
|
* @param {*} options 行为配置
|
||||||
|
*/
|
||||||
resizeGroupToChildren(groupId, options = {}) {
|
resizeGroupToChildren(groupId, options = {}) {
|
||||||
|
// 循环容器沿用统一的内边距和最小尺寸约束,并按配置决定是否记录变更。
|
||||||
|
// 拖拽过程可关闭变更标记,避免高频移动产生多余历史记录。
|
||||||
const group = store.findNode(groupId);
|
const group = store.findNode(groupId);
|
||||||
if (!group || group.data.flowType !== "loop") return;
|
if (!group || group.data.flowType !== "loop") return;
|
||||||
if (layoutLoop(group) && options.markChanged !== false) changed();
|
if (layoutLoop(group) && options.markChanged !== false) changed();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 移动 moveNodeBy 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
* @param {*} dx 横向位移
|
||||||
|
* @param {*} dy 纵向位移
|
||||||
|
*/
|
||||||
moveNodeBy(id, dx, dy) {
|
moveNodeBy(id, dx, dy) {
|
||||||
const node = store.findNode(id);
|
const node = store.findNode(id);
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
@ -701,6 +936,9 @@ export const createFlowFacade = (store) => {
|
|||||||
});
|
});
|
||||||
changed();
|
changed();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 撤销 undo 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
undo() {
|
undo() {
|
||||||
if (historyIndex <= 0) return false;
|
if (historyIndex <= 0) return false;
|
||||||
historyIndex -= 1;
|
historyIndex -= 1;
|
||||||
@ -709,6 +947,9 @@ export const createFlowFacade = (store) => {
|
|||||||
nextTick(() => emit("history:change", { data: facade.getGraphData() }));
|
nextTick(() => emit("history:change", { data: facade.getGraphData() }));
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 重做 redo 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
*/
|
||||||
redo() {
|
redo() {
|
||||||
if (historyIndex >= history.length - 1) return false;
|
if (historyIndex >= history.length - 1) return false;
|
||||||
historyIndex += 1;
|
historyIndex += 1;
|
||||||
@ -717,6 +958,11 @@ export const createFlowFacade = (store) => {
|
|||||||
nextTick(() => emit("history:change", { data: facade.getGraphData() }));
|
nextTick(() => emit("history:change", { data: facade.getGraphData() }));
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 注册 registerComponentInstance 对应的数据或交互;作用范围仅限画布适配层。
|
||||||
|
* @param {*} id 目标元素 ID
|
||||||
|
* @param {*} instance 组件实例
|
||||||
|
*/
|
||||||
registerComponentInstance(id, instance) {
|
registerComponentInstance(id, instance) {
|
||||||
if (instance) componentInstances.set(id, instance);
|
if (instance) componentInstances.set(id, instance);
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user