Merge remote-tracking branch 'origin/lxl-dev' into lxl-dev

This commit is contained in:
lixiaolong 2026-08-12 13:49:33 +08:00
commit 24b3acd2fd
5 changed files with 68 additions and 14 deletions

View File

@ -59,14 +59,50 @@ export const loadFlowItemRuntimeRoles = async (items = []) => {
return mergeResourceRoleDefinitions(roleGroups)
}
/**
* Loads runtime roles without merging equal role keys across flow items.
* Task orchestration needs one independent assignment per detection item because
* two items may use different physical robots even when their workflows define
* the same logical role (for example, `default_robot`).
*/
export const loadFlowItemScopedRuntimeRoles = async (items = []) => {
if (items.some((item) => !item?.itemId)) throw new Error('任务编排中存在缺少流程项ID的数据')
if (!items.length) throw new Error('当前任务没有编排任何流程项')
const occurrences = new Map()
const roleGroups = await Promise.all(items.map(async (item) => {
const occurrence = (occurrences.get(String(item.itemId)) || 0) + 1
occurrences.set(String(item.itemId), occurrence)
const response = await getDetect(item.itemId)
const graph = parseFlowData(item.itemName || item.itemId, response.data?.flowData)
return getResourceRoles(graph).map((role) => ({
...clone([role])[0],
roleKey: `${item.itemId}:${occurrence}:${role.roleKey}`,
sourceRoleKey: role.roleKey,
itemId: item.itemId,
itemName: item.itemName || String(item.itemId),
displayName: `${item.itemName || item.itemId} / ${role.displayName}`,
}))
}))
return roleGroups.flat()
}
export const loadTaskRuntimeRoles = async (taskId) => {
if (!taskId) throw new Error('任务没有关联流程编排')
const response = await getFlowParamsApi(taskId)
return loadFlowItemRuntimeRoles(response.rows || [])
}
export const loadTaskScopedRuntimeRoles = async (taskId) => {
if (!taskId) throw new Error('任务没有关联流程编排')
const response = await getFlowParamsApi(taskId)
return loadFlowItemScopedRuntimeRoles(response.rows || [])
}
export const createRuntimeAssignments = (roles = [], primaryRobotId = '') => roles.map((role, index) => ({
roleKey: role.roleKey,
...(role.sourceRoleKey ? { sourceRoleKey: role.sourceRoleKey } : {}),
...(role.itemId != null ? { itemId: role.itemId } : {}),
members: [{
memberKey: `${role.roleKey}_1`,
robotId: index === 0 ? primaryRobotId || role.legacyRobotId || '' : role.legacyRobotId || '',

View File

@ -154,6 +154,8 @@ const initialize = async () => {
const existingMember = existingAssignment?.members?.[0]
return {
roleKey: role.roleKey,
...(role.sourceRoleKey ? { sourceRoleKey: role.sourceRoleKey } : {}),
...(role.itemId != null ? { itemId: role.itemId } : {}),
members: [{
...existingMember,
memberKey: `${role.roleKey}_1`,

View File

@ -140,12 +140,14 @@
</el-dialog>
<el-dialog title="本次执行安排" v-model="startDialogVisible" width="560px" append-to-body>
<div class="start-dialog-content">
<RuntimeAssignmentsEditor
ref="runtimeEditorRef"
v-model="runtimeAssignments"
:roles="runtimeRoles"
:required-map-id="runtimeMapId"
/>
</div>
<template #footer>
<el-button @click="startDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="startSubmitting" @click="confirmStartTask">开始执行</el-button>
@ -168,7 +170,7 @@ import RuntimeAssignmentsEditor from '@/views/flow/components/RuntimeAssignments
import {
createRuntimeAssignments,
firstAssignedRobotId,
loadTaskRuntimeRoles,
loadTaskScopedRuntimeRoles,
} from '@/utils/flowExecution'
const topContainerRef = ref();
@ -328,7 +330,7 @@ const startTask = async (task) => {
return
}
try {
const roles = await loadTaskRuntimeRoles(taskDefinition.taskConfigId)
const roles = await loadTaskScopedRuntimeRoles(taskDefinition.taskConfigId)
runtimeAssignments.value = createRuntimeAssignments(roles, task.robotIdentity)
runtimeMapId.value = taskDefinition.mapId || ''
runtimeRoles.value = roles
@ -653,4 +655,10 @@ onUnmounted(() => {
}
}
}
.start-dialog-content {
max-height: 65vh;
padding-right: 6px;
overflow-y: auto;
}
</style>

View File

@ -152,8 +152,10 @@
</el-dialog>
<el-dialog title="本次执行安排" v-model="startDialogVisible" width="560px" append-to-body>
<div class="start-dialog-content">
<div class="start-dialog-tip">手机和车辆沿用任务配置,这里只安排执行流程的机器人和设备。</div>
<RuntimeAssignmentsEditor ref="runtimeEditorRef" v-model="runtimeAssignments" :roles="runtimeRoles" />
</div>
<template #footer>
<el-button @click="startDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="startSubmitting" @click="confirmStartTask">开始执行</el-button>
@ -187,7 +189,7 @@ import RuntimeAssignmentsEditor from '@/views/flow/components/RuntimeAssignments
import {
createRuntimeAssignments,
firstAssignedRobotId,
loadTaskRuntimeRoles,
loadTaskScopedRuntimeRoles,
} from '@/utils/flowExecution'
const topContainerRef = ref();
@ -370,7 +372,7 @@ const startTask = async (task) => {
return
}
try {
const roles = await loadTaskRuntimeRoles(taskDefinition.taskConfigId)
const roles = await loadTaskScopedRuntimeRoles(taskDefinition.taskConfigId)
runtimeAssignments.value = createRuntimeAssignments(roles)
runtimeRoles.value = roles
pendingStartTask.value = task
@ -706,4 +708,10 @@ onUnmounted(() => {
color: var(--el-text-color-secondary);
font-size: 13px;
}
.start-dialog-content {
max-height: 65vh;
padding-right: 6px;
overflow-y: auto;
}
</style>

View File

@ -71,7 +71,7 @@ import { taskExecute } from "@/api/test/config"
import RuntimeAssignmentsEditor from '@/views/flow/components/RuntimeAssignmentsEditor.vue'
import {
firstAssignedRobotId,
loadFlowItemRuntimeRoles,
loadFlowItemScopedRuntimeRoles,
} from '@/utils/flowExecution'
const props = defineProps({
@ -104,7 +104,7 @@ const getFlowParams = async () => {
const data = parseConfig(res.rows)
formData.value.tableData = data
runtimeAssignments.value = []
roles.value = await loadFlowItemRuntimeRoles(data)
roles.value = await loadFlowItemScopedRuntimeRoles(data)
}
};