Explorar el Código

refactor(EasyProcess): 重构节点抽屉组件及表单逻辑

- 将公共表单逻辑提取到核心组件drawer_course中
- 统一各节点类型的表单验证和值获取方式
- 优化表单字段配置,移除冗余字段
- 添加调试日志用于节点更新追踪
- 调整表单布局和样式,提升用户体验
zhanghaijun hace 11 meses
padre
commit
67c8b4600e

+ 1 - 0
src/components/business/EasyProcess/common/process.helper.ts

@@ -83,6 +83,7 @@ export class ProcessHelper {
    * @param nodeData 更新的字段
    */
   public updateNode(nodeId: string, nodeData: Record<string, unknown>) {
+    console.log('更新节点', nodeId, nodeData)
     const target = this.findNode(nodeId, this.getProcessData())
     if (!target) return false
     target.nodeData = { ...target.nodeData, ...nodeData }

+ 8 - 6
src/components/business/EasyProcess/node/course.scheme.ts

@@ -3,13 +3,14 @@
  */
 export const nodeDataCommon = [
   { prop: '', label: '', labelWidth: '0px', component: 'Divider', colSpan: 24, componentProps: { title: '基础配置' } },
-  { prop: 'bindRole', label: '选择角色', component: 'ApiSelect', componentProps: { api: '/role/list', labelField: 'roleName', valueField: 'roleID' } },
+  { prop: 'name', label: '节点名称', component: 'Input', rules: [{ required: true, message: '请输入节点名称', trigger: ['blur'] }] },
   { prop: 'nodeDetail', label: '节点详细信息', component: 'Input' },
-  { prop: 'delaySkip', label: '延时跳过,单位秒', component: 'InputNumber', componentProps: { min: 0, max: 120, step: 1, suffix: '秒' } },
+  { prop: 'bindRole', label: '选择角色', component: 'ApiSelect', componentProps: { api: '/role/list', labelField: 'roleName', valueField: 'roleID' } },
+  { prop: 'delaySkip', label: '延时跳过(秒)', component: 'InputNumber', defaultValue: 0, componentProps: { min: 0, max: 120, step: 1, suffix: '秒' } },
   {
     prop: 'loseItem',
     label: '失格项',
-    component: 'Select',
+    component: 'RadioGroup',
     defaultValue: '1',
     componentProps: {
       options: [
@@ -21,7 +22,7 @@ export const nodeDataCommon = [
   {
     prop: 'virtualOperation',
     label: '虚拟操作',
-    component: 'radiogroup',
+    component: 'RadioGroup',
     defaultValue: '0',
     componentProps: {
       options: [
@@ -50,10 +51,11 @@ export const nodeDataTrigger = [
         { label: '任意流程推进到立即出发', value: '3' },
         { label: '条件流程触发', value: '4' }
       ]
-    }
+    },
+    rules: [{ required: true, message: '请选择触发方式', trigger: ['change'] }]
   },
   { prop: 'event', label: '触发事件', component: 'Input' },
-  { prop: 'triggerDelay', label: '触发延迟,单位秒', component: 'InputNumber', componentProps: { min: 0, max: 120, step: 1, suffix: '秒' } },
+  { prop: 'triggerDelay', label: '触发延迟(秒)', component: 'InputNumber', defaultValue: 0, componentProps: { min: 0, max: 120, step: 1, suffix: '秒' } },
   { prop: 'textParam1', label: '参数1', component: 'Input' },
   { prop: 'textParam2', label: '参数2', component: 'Input' }
 ]

+ 30 - 21
src/components/business/EasyProcess/core/drawer_wrap.vue

@@ -1,6 +1,7 @@
 <template>
   <Dialog>
     <div class="drawer_wrap">
+      <DrawerCourse v-if="isCourse" ref="courseDrawerRef" :data="node.nodeData" />
       <DrawerCondition v-if="node.nodeType === 'condition'" ref="conditionDrawerRef" :node="node as Process.ConditionNode" />
       <DrawerOperation v-else-if="node.nodeType === 'operation'" ref="operationDrawerRef" :node="node as Process.OperationNode" />
       <DrawerFault v-else-if="node.nodeType === 'fault'" ref="faultDrawerRef" :node="node as Process.FaultNode" />
@@ -14,6 +15,7 @@
   import { useDialog } from '@/components/dialog'
   import { Process } from '../common/process.type'
 
+  import DrawerCourse from './drwer_course.vue'
   import DrawerOperation from '../node/operation_drawer.vue'
   import DrawerFault from '../node/fault_drawer.vue'
   import DrawerVoice from '../node/voice_drawer.vue'
@@ -26,42 +28,49 @@
   const processHelper = inject<ProcessHelper>(ProcessConstant.KEY_PROCESS_HELPER)
   const processNode = ref<Process.NodeConfig>()
 
+  const courseDrawerRef = ref()
   const conditionDrawerRef = ref()
   const operationDrawerRef = ref()
   const faultDrawerRef = ref()
   const voiceDrawerRef = ref()
 
+  const isCourse = computed(() => processNode.value?.nodeType === 'operation' || processNode.value?.nodeType === 'fault' || processNode.value?.nodeType === 'voice')
+
   const [Dialog, dialogApi] = useDialog({
     width: '40%',
     dialogType: 'drawer',
     modal: true,
     destroyOnClose: true,
-    onConfirm() {
+    async onConfirm() {
       switch (processNode.value?.nodeType) {
-        case 'operation':
-          operationDrawerRef.value.getNodeData((nodeData: Record<string, unknown>) => {
-            processHelper?.updateNode(props.node.nodeId, nodeData)
-            dialogApi.close()
-          })
+        case 'operation': {
+          const data = await courseDrawerRef.value.getValues()
+          const operationData = await operationDrawerRef.value.getValues()
+          console.log(data, operationData)
+          processHelper?.updateNode(props.node.nodeId, { ...data, nodeID: props.node.nodeId, operationNode: operationData })
+          dialogApi.close()
           break
-        case 'fault':
-          faultDrawerRef.value.getNodeData((nodeData: Record<string, unknown>) => {
-            processHelper?.updateNode(props.node.nodeId, nodeData)
-            dialogApi.close()
-          })
+        }
+        case 'fault': {
+          const data = await courseDrawerRef.value.getValues()
+          const faultData = await faultDrawerRef.value.getValues()
+          processHelper?.updateNode(props.node.nodeId, { ...data, nodeID: props.node.nodeId, faultNode: faultData })
+          dialogApi.close()
           break
-        case 'voice':
-          voiceDrawerRef.value.getNodeData((nodeData: Record<string, unknown>) => {
-            processHelper?.updateNode(props.node.nodeId, nodeData)
-            dialogApi.close()
-          })
+        }
+        case 'voice': {
+          const data = await courseDrawerRef.value.getValues()
+          const voiceData = await voiceDrawerRef.value.getValues()
+          processHelper?.updateNode(props.node.nodeId, { ...data, nodeID: props.node.nodeId, voiceNode: voiceData })
+          dialogApi.close()
           break
-        case 'condition':
-          conditionDrawerRef.value.getNodeData((nodeData: Record<string, unknown>) => {
-            processHelper?.updateNode(props.node.nodeId, nodeData)
-            dialogApi.close()
-          })
+        }
+        case 'condition': {
+          const conditionData = await conditionDrawerRef.value.getValues()
+          processHelper?.updateNode(props.node.nodeId, conditionData)
+          dialogApi.close()
           break
+        }
         default:
           ElMessage.error('错误节点类型')
           break

+ 40 - 0
src/components/business/EasyProcess/core/drwer_course.vue

@@ -0,0 +1,40 @@
+<template>
+  <CommonForm />
+  <TriggerForm />
+</template>
+
+<script setup lang="tsx">
+  import { onMounted } from 'vue'
+  import { useForm } from '@/components/form'
+  import { nodeDataCommon, nodeDataTrigger } from './course.scheme'
+
+  const props = withDefaults(defineProps<{ data: Record<string, unknown> }>(), {})
+
+  const [CommonForm, commonFormApi] = useForm({ labelWidth: '150px', schema: nodeDataCommon })
+  const [TriggerForm, triggerFormApi] = useForm({ labelWidth: '150px', schema: nodeDataTrigger })
+
+  onMounted(() => {
+    commonFormApi.setValues({
+      name: String(props.data?.name || ''),
+      bindRole: String(props.data?.bindRole || ''),
+      nodeDetail: props.data?.nodeDetail || '',
+      delaySkip: props.data?.delaySkip || 0,
+      loseItem: String(props.data?.loseItem || 1),
+      nodeJoinType: props.data?.nodeJoinType,
+      virtualOperation: String(props.data?.virtualOperation || 0)
+    })
+    triggerFormApi.setValues({ ...(props.data?.nodeTrigger ?? {}) })
+  })
+
+  defineExpose({
+    getValues: async () => {
+      await commonFormApi.validate()
+      await triggerFormApi.validate()
+      const values = await commonFormApi.getValues()
+      const nodeTrigger = await triggerFormApi.getValues()
+      return { ...values, nodeTrigger }
+    }
+  })
+</script>
+
+<style lang="scss" scoped></style>

+ 4 - 0
src/components/business/EasyProcess/node/condition_drawer.vue

@@ -36,6 +36,10 @@
   })
 
   defineExpose({
+    getValues: async () => {
+      await formApi.validate()
+      return formApi.getValues()
+    },
     getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
       const data = await formApi.getValues()
       formApi.validate().then((valid) => {

+ 7 - 16
src/components/business/EasyProcess/node/fault_drawer.vue

@@ -21,7 +21,6 @@
   import { useForm } from '@/components/form'
   import { Process } from '../common/process.type'
   import { ProcessFault, ProcessServer } from '@/api/course.api'
-  import { nodeDataCommon, nodeDataTrigger } from './course.scheme'
 
   const props = withDefaults(defineProps<{ node: Process.FaultNode }>(), {})
 
@@ -29,23 +28,11 @@
   const templateSelected = ref<ProcessFault>()
 
   const [BasicForm, formApi] = useForm({
-    labelWidth: '100px',
-    rules: {
-      name: [{ required: true, message: '请输入故障名称', trigger: ['blur'] }],
-      role: [{ required: true, message: '请选择角色', trigger: ['change'] }],
-      templateID: [{ required: true, message: '请选择操作模板', trigger: ['change'] }]
-    },
+    labelWidth: '150px',
     schema: [
-      ...nodeDataCommon,
-      ...nodeDataTrigger,
-      { prop: '', label: '', labelWidth: '0px', component: 'Divider', colSpan: 24, componentProps: { title: '故障信息' } },
-      { prop: 'name', label: '故障名称', component: 'Input' },
-      { prop: 'role', label: '选择角色', component: 'ApiSelect', componentProps: { api: '/role/list', labelField: 'roleName', valueField: 'roleID' } },
-      { prop: 'templateID', label: '操作模', component: 'Input' },
-      // { prop: 'templateType', label: '操作模板类型', component: 'Input' },
-      // { prop: 'category', label: '节点分类', component: 'Input' },
+      { prop: 'divider', label: '', labelWidth: '0px', component: 'Divider', colSpan: 24, componentProps: { title: '故障信息' } },
+      { prop: 'templateID', label: '操作模板', component: 'Input', rules: [{ required: true, message: '请选择操作模板', trigger: ['blur', 'change'] }] },
       { prop: 'categoryName', label: '分类名称', component: 'Input' },
-      // { prop: 'subCategory', label: '子分类', component: 'Input' },
       { prop: 'subCategoryName', label: '子分类名称', component: 'Input' },
       {
         prop: 'param1Type',
@@ -160,6 +147,10 @@
   })
 
   defineExpose({
+    getValues: async () => {
+      await formApi.validate()
+      return formApi.getValues()
+    },
     getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
       const data = await formApi.getValues()
       formApi.validate().then((valid) => {

+ 1 - 4
src/components/business/EasyProcess/node/fault_node.vue

@@ -27,12 +27,9 @@
     if (!nodeData.value?.name) {
       messages.push('请输入故障名称')
     }
-    if (!nodeData.value?.role) {
+    if (!nodeData.value?.bindRole) {
       messages.push('请选择故障角色')
     }
-    if (!nodeData.value?.templateID) {
-      messages.push('请选择故障模板')
-    }
     return { valid: messages.length === 0, message: messages.join(',') }
   })
 </script>

+ 7 - 5
src/components/business/EasyProcess/node/operation_drawer.vue

@@ -30,13 +30,9 @@
       templateID: [{ required: true, message: '请选择操作模板', trigger: ['change'] }]
     },
     schema: [
-      { prop: 'name', label: '操作名称', component: 'Input' },
-      { prop: 'role', label: '选择角色', component: 'ApiSelect', componentProps: { api: '/role/list', labelField: 'roleName', valueField: 'roleID' } },
+      { prop: 'divider', label: '', labelWidth: '0px', component: 'Divider', colSpan: 24, componentProps: { title: '操作信息' } },
       { prop: 'templateID', label: '操作模板', component: 'Input' },
-      // { prop: 'templateType', label: '操作模板类型', component: 'Input' },
-      // { prop: 'category', label: '节点分类', component: 'Input' },
       { prop: 'categoryName', label: '分类名称', component: 'Input' },
-      // { prop: 'subCategory', label: '子分类', component: 'Input' },
       { prop: 'subCategoryName', label: '子分类名称', component: 'Input' },
       {
         prop: 'param1Type',
@@ -127,6 +123,7 @@
         prop: 'score',
         label: '赋分',
         component: 'InputNumber',
+        defaultValue: 0,
         componentProps: { min: 0, max: 255, step: 1, suffix: '分' },
         rules: [{ required: true, message: '请输入赋分', trigger: ['blur'] }]
       },
@@ -134,6 +131,7 @@
         prop: 'deduction',
         label: '失分',
         component: 'InputNumber',
+        defaultValue: 0,
         componentProps: { min: 0, max: 255, step: 1, suffix: '分' },
         rules: [{ required: true, message: '请输入失分', trigger: ['blur'] }]
       }
@@ -164,6 +162,10 @@
   })
 
   defineExpose({
+    getValues: async () => {
+      await formApi.validate()
+      return formApi.getValues()
+    },
     getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
       const data = await formApi.getValues()
       formApi.validate().then((valid) => {

+ 1 - 4
src/components/business/EasyProcess/node/operation_node.vue

@@ -26,12 +26,9 @@
     if (!nodeData.value?.name) {
       messages.push('请输入操作名称')
     }
-    if (!nodeData.value?.role) {
+    if (!nodeData.value?.bindRole) {
       messages.push('请选择操作角色')
     }
-    if (!nodeData.value?.templateID) {
-      messages.push('请选择操作模板')
-    }
     return { valid: messages.length === 0, message: messages.join(',') }
   })
 </script>

+ 5 - 5
src/components/business/EasyProcess/node/voice_drawer.vue

@@ -36,13 +36,9 @@
       voiceContent: [{ required: true, message: '请输入语音内容', trigger: ['blur'] }]
     },
     schema: [
-      { prop: 'name', label: '语音名称', component: 'Input' },
-      { prop: 'role', label: '选择角色', component: 'ApiSelect', componentProps: { api: '/role/list', labelField: 'roleName', valueField: 'roleID' } },
+      { prop: 'divider', label: '', labelWidth: '0px', component: 'Divider', colSpan: 24, componentProps: { title: '语音信息' } },
       { prop: 'templateID', label: '语言模板', component: 'Input' },
-      // { prop: 'templateType', label: '语音模板类型', component: 'Input' },
-      // { prop: 'category', label: '节点分类', component: 'Input' },
       { prop: 'categoryName', label: '分类名称', component: 'Input' },
-      // { prop: 'subCategory', label: '子分类', component: 'Input' },
       { prop: 'subCategoryName', label: '子分类名称', component: 'Input' },
       { prop: 'voiceContent', label: '语音内容', component: 'Input' },
       { prop: 'evalTemplate', label: '评估模板', component: 'Input' },
@@ -75,6 +71,10 @@
   })
 
   defineExpose({
+    getValues: async () => {
+      await formApi.validate()
+      return formApi.getValues()
+    },
     getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
       const data = await formApi.getValues()
       formApi.validate().then((valid) => {

+ 1 - 4
src/components/business/EasyProcess/node/voice_node.vue

@@ -27,12 +27,9 @@
     if (!nodeData.value?.name) {
       messages.push('请输入语言名称')
     }
-    if (!nodeData.value?.role) {
+    if (!nodeData.value?.bindRole) {
       messages.push('请选择语言角色')
     }
-    if (!nodeData.value?.templateID) {
-      messages.push('请选择语言模板')
-    }
     return { valid: messages.length === 0, message: messages.join(',') }
   })
 </script>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 11715
src/views/train/fault/devices.json