Merge branch 'main' of http://it.fairylandtech.com:8666/zhaowei.huang/Migu2.0
This commit is contained in:
@@ -75,8 +75,9 @@ function onDragStart(e: DragEvent, type: string) {
|
||||
|
||||
<style scoped>
|
||||
.node-palette {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
@delete="onDeleteWorkflow"
|
||||
/>
|
||||
<div class="wf-panel-title">控件库</div>
|
||||
<NodePalette class="wf-palette-body" />
|
||||
<div class="wf-palette-body">
|
||||
<NodePalette />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="wf-panel wf-panel-center">
|
||||
@@ -362,7 +364,8 @@ async function onImportJson() {
|
||||
}
|
||||
|
||||
const warnCount = prepared.reduce(
|
||||
(sum, w) => sum + validateWorkflow(w).filter((i) => i.level === 'warning').length,
|
||||
(sum, w) =>
|
||||
sum + validateWorkflow(w).filter((i) => i.level === 'warning').length,
|
||||
0
|
||||
)
|
||||
if (warnCount > 0) {
|
||||
@@ -657,6 +660,8 @@ async function onClearCanvas() {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.wf-panel-center {
|
||||
flex: 1;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="mission-page">
|
||||
<ReflectionManagerPanel
|
||||
kind="process"
|
||||
kind-label="任务"
|
||||
title="任务编排(Mission / 进程,含插件 MissionType 实例化)"
|
||||
empty-text="当前没有任务;点击右上角「新建任务」从已加载的 MissionType 中选一个实例化。"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* /admin/missions 路由的页面入口。
|
||||
*
|
||||
* 由于「任务」与「进程」在后端 ReflectionApiController 共用 kind=process / mission
|
||||
* (UiDiscoveryCache.MissionCreatableTypes 同源),这里直接用 ReflectionManagerPanel
|
||||
* 接入,按下「新建任务」会列出所有 MissionType 子类(含 taskflow / trigger)。
|
||||
*
|
||||
* 旧版本的 DataTablePro + listMissions mock 已经下线,所有数据走 SimpleLite 反射 API。
|
||||
*/
|
||||
import ReflectionManagerPanel from '@/components/reflection/ReflectionManagerPanel.vue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mission-page {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 12px 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="orchestration-page">
|
||||
<el-tabs v-model="tab" class="orch-tabs" type="border-card" @tab-change="onTabChange">
|
||||
<el-tab-pane label="车辆" name="cars">
|
||||
<CarPanelView v-if="tab === 'cars'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="进程" name="process">
|
||||
<MissionEditorView v-if="tab === 'process'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="脚本" name="script">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'script'"
|
||||
kind="script"
|
||||
empty-text="脚本(继承 CarProgram 的子类型)未发现可暴露条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="任务流" name="taskflow">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'taskflow'"
|
||||
kind="mission"
|
||||
extra-filter="taskflow"
|
||||
empty-text="未发现任务流条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="触发器" name="trigger">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'trigger'"
|
||||
kind="mission"
|
||||
extra-filter="trigger"
|
||||
empty-text="未发现触发器条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import CarPanelView from '@/views/admin/CarPanelView.vue'
|
||||
import MissionEditorView from '@/views/admin/MissionEditorView.vue'
|
||||
import ReflectionKindTable from '@/components/orchestration/ReflectionKindTable.vue'
|
||||
|
||||
const tab = ref<'cars' | 'process' | 'script' | 'taskflow' | 'trigger'>('cars')
|
||||
|
||||
function onTabChange(name: string | number) {
|
||||
tab.value = name as typeof tab.value
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const cached = sessionStorage.getItem('orchestration.tab')
|
||||
if (cached) tab.value = cached as typeof tab.value
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.orchestration-page {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 12px;
|
||||
}
|
||||
.orch-tabs {
|
||||
height: 100%;
|
||||
}
|
||||
.orch-tabs :deep(.el-tabs__content) {
|
||||
height: calc(100% - 40px);
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { ParamFieldDef } from '@/types/workflow'
|
||||
|
||||
export const ASSIGN_STRATEGY_OPTIONS = [
|
||||
{ label: '指定车辆', value: 'fixed' },
|
||||
{ label: '指定类型', value: 'byType' }
|
||||
{ label: '指定车辆', value: 'carId' },
|
||||
{ label: '指定类型', value: 'carType' }
|
||||
] as const
|
||||
|
||||
const FIXED = { key: 'strategy', equals: 'fixed' as const }
|
||||
const BY_TYPE = { key: 'strategy', equals: 'byType' as const }
|
||||
const BY_CAR_ID = { key: 'strategy', equals: 'carId' as const }
|
||||
const BY_CAR_TYPE = { key: 'strategy', equals: 'carType' as const }
|
||||
|
||||
/** 分配车辆:指定车辆 / 指定类型 */
|
||||
export function assignCarParams(): ParamFieldDef[] {
|
||||
@@ -16,7 +16,7 @@ export function assignCarParams(): ParamFieldDef[] {
|
||||
label: '分配策略',
|
||||
type: 'select',
|
||||
required: true,
|
||||
defaultValue: 'fixed',
|
||||
defaultValue: 'carId',
|
||||
options: [...ASSIGN_STRATEGY_OPTIONS]
|
||||
},
|
||||
{
|
||||
@@ -25,7 +25,7 @@ export function assignCarParams(): ParamFieldDef[] {
|
||||
type: 'string',
|
||||
required: true,
|
||||
placeholder: '如 C01',
|
||||
when: FIXED
|
||||
when: BY_CAR_ID
|
||||
},
|
||||
{
|
||||
key: 'carType',
|
||||
@@ -33,7 +33,7 @@ export function assignCarParams(): ParamFieldDef[] {
|
||||
type: 'string',
|
||||
required: true,
|
||||
placeholder: '如 Forklift / SimpleLite.RCS.Cars.AgvCar',
|
||||
when: BY_TYPE
|
||||
when: BY_CAR_TYPE
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ export const DEMO_WORKFLOW: WorkflowDefinition = {
|
||||
viewport: { x: 0, y: 0, zoom: 1 },
|
||||
nodes: [
|
||||
{ id: 'n1', type: 'start', label: '开始', position: { x: 60, y: 200 }, params: {} },
|
||||
{ id: 'n2', type: 'assignCar', label: '分配车辆', position: { x: 240, y: 180 }, params: { strategy: 'fixed', carId: 'C01' } },
|
||||
{ id: 'n2', type: 'assignCar', label: '分配车辆', position: { x: 240, y: 180 }, params: { strategy: 'carId', carId: 'C01' } },
|
||||
{ id: 'n3', type: 'gotoSite', label: '前往入库点', position: { x: 460, y: 180 }, params: { siteId: 'S001' } },
|
||||
{
|
||||
id: 'n4',
|
||||
@@ -140,7 +140,7 @@ export const DEMO_WORKFLOW: WorkflowDefinition = {
|
||||
label: '取货',
|
||||
position: { x: 680, y: 180 },
|
||||
params: {
|
||||
actionType: 'pick',
|
||||
actionType: 'fetch',
|
||||
actionParameters: '[{"key":"loadType","value":"pallet"}]'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,9 +2,8 @@ import type { ParamFieldDef } from '@/types/workflow'
|
||||
|
||||
/** 动作类型选项 */
|
||||
export const ACTION_TYPE_OPTIONS = [
|
||||
{ label: '取货', value: 'pick' },
|
||||
{ label: '放货', value: 'drop' },
|
||||
{ label: '充电', value: 'startCharging' }
|
||||
{ label: '取货', value: 'fetch' },
|
||||
{ label: '放货', value: 'put' }
|
||||
] as const
|
||||
|
||||
/** 执行动作:对齐 VDA5050 Order.actions[] 单条 Action 结构(不含 actionId,下发时由运行时生成) */
|
||||
@@ -15,7 +14,7 @@ export function executeActionParams(): ParamFieldDef[] {
|
||||
label: '动作类型',
|
||||
type: 'select',
|
||||
required: true,
|
||||
defaultValue: 'pick',
|
||||
defaultValue: 'fetch',
|
||||
options: [...ACTION_TYPE_OPTIONS]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { toRaw } from 'vue'
|
||||
import type { ParamFieldDef, WorkflowDefinition, WorkflowEdgeDef, WorkflowNodeDef } from '@/types/workflow'
|
||||
import type { WorkflowCatalogExport } from '@/workflow/workflowLibrary'
|
||||
import { NODE_CATALOG_MAP, defaultParamsForType } from '@/workflow/nodeCatalog'
|
||||
import { defaultParamsForType, NODE_CATALOG_MAP } from '@/workflow/nodeCatalog'
|
||||
import { WAIT_EVENT_HANDLES, WAIT_EVENT_HANDLE_LABELS } from '@/workflow/waitEventParams'
|
||||
|
||||
/** 深拷贝流程定义(workflow 为纯 JSON 结构,避免 structuredClone 对 Proxy/不可克隆对象报错) */
|
||||
@@ -72,8 +72,10 @@ export const WORKFLOW_CATALOG_VERSION = 3
|
||||
export const WORKFLOW_EDITOR_STORAGE_KEY = 'workflowEditor.draft'
|
||||
|
||||
const DEPRECATED_ASSIGN_STRATEGY: Record<string, string> = {
|
||||
nearest: 'fixed',
|
||||
idle: 'byType'
|
||||
nearest: 'carId',
|
||||
idle: 'carType',
|
||||
fixed: 'carId',
|
||||
byType: 'carType'
|
||||
}
|
||||
|
||||
function isFieldVisible(field: ParamFieldDef, params: Record<string, unknown>): boolean {
|
||||
@@ -268,11 +270,12 @@ export function attachNextIds(
|
||||
})
|
||||
}
|
||||
|
||||
/** 导出用:附带 nextId 的流程快照 */
|
||||
/** 导出用:附带 nextId 的流程快照(params 按当前控件 schema 规范化) */
|
||||
export function workflowForExport(def: WorkflowDefinition): WorkflowDefinition {
|
||||
const normalized = normalizeWorkflow(def)
|
||||
return {
|
||||
...def,
|
||||
nodes: attachNextIds(def.nodes, def.edges)
|
||||
...normalized,
|
||||
nodes: attachNextIds(normalized.nodes, normalized.edges)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user