refactor(flow): 优化流程参数初始化和运行时分配逻辑

- 修改 DeviceUniversal.vue 中的 initData 函数,使用可选链操作符安全访问属性
- 将 setTimeout 替换为 nextTick 确保编辑器值正确设置
- 添加对 props.data 的监听以响应数据变化
- 重构 RobotExecutionTarget.vue 中的初始化函数名称和监听逻辑
- 在 flowExecution.js 中添加 itemOccurrence 字段支持
- 优化 RuntimeAssignmentsEditor.vue 中的设备复用检查逻辑
- 实现基于检测项范围的设备键值生成策略
This commit is contained in:
lixiaolong 2026-08-12 14:13:16 +08:00
parent 24b3acd2fd
commit e88a81049b
4 changed files with 31 additions and 12 deletions

View File

@ -80,6 +80,7 @@ export const loadFlowItemScopedRuntimeRoles = async (items = []) => {
roleKey: `${item.itemId}:${occurrence}:${role.roleKey}`,
sourceRoleKey: role.roleKey,
itemId: item.itemId,
itemOccurrence: occurrence,
itemName: item.itemName || String(item.itemId),
displayName: `${item.itemName || item.itemId} / ${role.displayName}`,
}))
@ -103,6 +104,7 @@ export const createRuntimeAssignments = (roles = [], primaryRobotId = '') => rol
roleKey: role.roleKey,
...(role.sourceRoleKey ? { sourceRoleKey: role.sourceRoleKey } : {}),
...(role.itemId != null ? { itemId: role.itemId } : {}),
...(role.itemOccurrence != null ? { itemOccurrence: role.itemOccurrence } : {}),
members: [{
memberKey: `${role.roleKey}_1`,
robotId: index === 0 ? primaryRobotId || role.legacyRobotId || '' : role.legacyRobotId || '',

View File

@ -156,6 +156,7 @@ const initialize = async () => {
roleKey: role.roleKey,
...(role.sourceRoleKey ? { sourceRoleKey: role.sourceRoleKey } : {}),
...(role.itemId != null ? { itemId: role.itemId } : {}),
...(role.itemOccurrence != null ? { itemOccurrence: role.itemOccurrence } : {}),
members: [{
...existingMember,
memberKey: `${role.roleKey}_1`,
@ -182,7 +183,12 @@ const validate = () => {
if (slot.required && !member.devices[slot.slotKey]) return `请为“${role.displayName}”选择“${slot.displayName}”`
const deviceId = member.devices[slot.slotKey]
if (!deviceId) continue
const physicalKey = `${member.robotId}:${deviceId}`
// 不同检测项按顺序独立执行,可以复用同一台机器人及其设备。
// 仅同一检测项内部的多个角色/用途需要遵守设备复用规则。
const itemScope = role.itemId == null
? 'task'
: `${role.itemId}:${role.itemOccurrence || 1}`
const physicalKey = `${itemScope}:${member.robotId}:${deviceId}`
const existingUse = physicalDeviceUses.get(physicalKey)
if (existingUse && (!slot.allowReuse || !existingUse.allowReuse)) {
return `“${existingUse.roleName} / ${existingUse.slotName}”和“${role.displayName} / ${slot.displayName}”不能使用同一个设备`

View File

@ -356,21 +356,28 @@ const deleteTopLevelItem = (fullPath, propPath) => {
* 初始化 initData 对应的数据或交互;作用范围仅限当前组件或模块。
*/
const initData = () => {
const nodeParams = JSON.parse(JSON.stringify(props.data.properties.nodeParams || []))
const outputParams = JSON.parse(JSON.stringify(props.data.properties.outputParams || []))
const properties = props.data?.properties || {}
const nodeParams = JSON.parse(JSON.stringify(properties.nodeParams || []))
const outputParams = JSON.parse(JSON.stringify(properties.outputParams || []))
formData.nodeParams = nodeParams;
formData.outputParams = outputParams;
formData.executionTarget = JSON.parse(JSON.stringify(props.data.properties.executionTarget || {}));
const codeParams = props.data.properties.nodeParams.find(item => item.name === 'requestJson')
formData.executionTarget = JSON.parse(JSON.stringify(properties.executionTarget || {}));
const codeParams = nodeParams.find(item => item.name === 'requestJson')
if (codeParams) {
setTimeout(() => {
nextTick(() => {
if (editorInstance) {
setValue(codeParams.input)
setValue(codeParams.input)
}
}, 100)
})
}
}
watch(
() => props.data,
initData,
{ immediate: true, deep: true }
)
// 保存验证
/**
* 校验 validateAndSave 对应的数据或交互;作用范围仅限当前组件或模块。
@ -420,7 +427,8 @@ const validateAndSave = async () => {
onMounted(() => {
nextTick(() => {
initEditor('requestJson')
initData()
const codeParams = formData.nodeParams.find(item => item.name === 'requestJson')
if (codeParams) setValue(codeParams.input)
})
})

View File

@ -79,7 +79,7 @@ const handleRoleChange = () => {
emitTarget()
}
const init = () => {
const syncFromModel = () => {
roles.value = getResourceRoles()
const value = props.modelValue || {}
localTarget.roleKey = roles.value.some((role) => role.roleKey === value.roleKey)
@ -88,10 +88,13 @@ const init = () => {
localTarget.dispatchPolicy = value.dispatchPolicy || 'ONE'
deviceSlotKey.value = value.deviceSlotKey || value.deviceBindings?.[0]?.slotKey || ''
selectDefaultSlot()
emitTarget()
}
watch(() => props.data.id, init, { immediate: true })
watch(
[() => props.data.id, () => props.modelValue],
syncFromModel,
{ immediate: true, deep: true }
)
</script>
<style scoped lang="scss">