瀏覽代碼

feat: 课程保存

zhanghaijun 11 月之前
父節點
當前提交
bb263259f1

+ 1 - 1
.env.development

@@ -10,4 +10,4 @@ VITE_API_URL = /api
 VITE_DROP_CONSOLE = false
 
 # 本地开发代理的目标后端地址(仅开发环境生效,用于解决跨域)
-VITE_API_PROXY_URL = http://haijunit.icu/course/api
+VITE_API_PROXY_URL = https://haijunit.icu/course/api

+ 37 - 5
src/api/course.api.ts

@@ -24,17 +24,49 @@ export interface Course {
 export class CourseServer {
   public static list = (params: Record<string, unknown>) => request.post<Course[]>('/course/list', params)
   public static detail = (courseId: string) => request.post<Course>('/course/detail/get', { courseId: Number(courseId) })
-  public static add = (data: Record<string, unknown>) => request.post('/course/add', data)
-  public static update = (data: Record<string, unknown>) => request.post('/course/update', data)
-  public static delete = (courseId: string) => request.post('/course/delete', { courseId })
-  public static deleteBatch = (courseIds: string[]) => request.post('/course/delete/batch', { courseIds })
+  public static add = (data: Record<string, unknown>) =>
+    request.post<{ courseId: number }>('/course/add', {
+      courseName: data.courseName /** 课程名称*/,
+      courseDesc: data.courseDesc /** 课程描述*/,
+      totalDuration: Number(data.totalDuration) /** 课程总时长*/,
+      typeID: Number(data.typeID) /** 分类ID*/,
+      courseDataStream: data.courseDataStream /** 课程数据流*/,
+      externalTypeID: Number(data.externalTypeID) /** 外部分类ID*/,
+      guideDesc: data.guideDesc /** 指导描述*/,
+      guideFilePath: data.guideFilePath /** 指导文件地址*/,
+      lineNo: Number(data.lineNo) /** 线路号*/,
+      runningMap: data.runningMap /** 运行图*/,
+      virtualRole: data.virtualRole /** 虚拟角色,使用逗号隔开*/
+    })
+  public static update = (data: Record<string, unknown>) =>
+    request.post('/course/update', {
+      courseID: Number(data.courseID) /** 课程ID*/,
+      courseName: data.courseName /** 课程名称*/,
+      courseDesc: data.courseDesc /** 课程描述*/,
+      totalDuration: data.totalDuration /** 课程总时长*/,
+      typeID: data.typeID /** 分类ID*/,
+      courseDataStream: data.courseDataStream /** 课程数据流*/,
+      externalTypeID: data.externalTypeID /** 外部分类ID*/,
+      courseGUID: data.courseGUID /** 课程GUID*/,
+      guideDesc: data.guideDesc /** 指导描述*/,
+      guideFilePath: data.guideFilePath /** 指导文件地址*/,
+      lineNo: data.lineNo /** 线路号*/,
+      runningMap: data.runningMap /** 运行图*/,
+      virtualRole: data.virtualRole /** 虚拟角色,使用逗号隔开*/,
+      virtualStartTime: data.virtualStartTime /** 虚拟起始时间*/
+    })
+  // 保存流程图
+  public static saveProcess = (courseId: string, courseDataStream: string) => request.post('/course/detail/set', { courseId: Number(courseId), courseDataStream })
+
+  public static delete = (courseId: string) => request.post('/course/delete', { courseId: Number(courseId) })
+  public static deleteBatch = (courseIds: string[]) => request.post('/course/delete/batch', { courseIds: courseIds.map((id) => Number(id)) })
   // 课程复制
   public static copy = (courseId: string) => request.post('/course/copy', { courseId: Number(courseId) })
   public static copyBatch = (courseIds: string[]) => request.post('/course/copy/batch', { courseIds: courseIds.map((id) => Number(id)) })
   // 课程导入
   public static import = (file: Blob | File) => request.upload('/course/import', { file })
   // 课程导出
-  public static export = (courseIds: string[]) => request.post('/course/export', { courseIds })
+  public static export = (courseIds: string[]) => request.post('/course/export', { courseIds: courseIds.map((id) => Number(id)) })
 }
 
 /** 用户角色 */

+ 2 - 2
src/components/business/EasyProcess/common/process.data.ts

@@ -1,4 +1,4 @@
-import { EasyProcess } from './process.type'
+import { Process } from './process.type'
 
 export const ProcessConstant = {
   KEY_PROCESS_VALIDATOR: 'process_validator',
@@ -8,7 +8,7 @@ export const ProcessConstant = {
 
 export const generateId = (): string => new Date().getTime() + '' + Math.floor(Math.random() * 1000 + 1)
 
-export const nodeConfigData: Record<EasyProcess.NodeType, EasyProcess.NodeMeta> = {
+export const nodeConfigData: Record<Process.NodeType, Process.NodeMeta> = {
   start: {
     title: '开始',
     bgColor: '#1e83e9',

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

@@ -1,4 +1,4 @@
-import { EasyProcess } from './process.type'
+import { Process } from './process.type'
 import { ref, reactive } from 'vue'
 
 /**
@@ -7,16 +7,16 @@ import { ref, reactive } from 'vue'
  * ==========================================
  */
 export class ProcessHelper {
-  processData: ReturnType<typeof ref<EasyProcess.NodeConfig>>
+  processData: ReturnType<typeof ref<Process.NodeConfig>>
 
-  constructor(processData: EasyProcess.NodeConfig) {
+  constructor(processData: Process.NodeConfig) {
     this.processData = ref(processData)
   }
 
-  public setProcessData(processData: EasyProcess.NodeConfig) {
+  public setProcessData(processData: Process.NodeConfig) {
     this.processData.value = processData
   }
-  public getProcessData(): EasyProcess.NodeConfig {
+  public getProcessData(): Process.NodeConfig {
     return this.processData.value!
   }
   /**
@@ -24,16 +24,16 @@ export class ProcessHelper {
    * @param nodeId 父节点ID
    * @param node 要添加的节点
    */
-  public addNode(nodeId: string, node: EasyProcess.NodeConfig): boolean {
+  public addNode(nodeId: string, node: Process.NodeConfig): boolean {
     const target = this.findNode(nodeId, this.getProcessData())
     if (!target) return false
 
     // 根据类型处理不同结构
     if (target.nodeType === 'router' && node.nodeType === 'condition') {
       // 路由节点添加条件分支
-      const router = target as EasyProcess.RouterNode
+      const router = target as Process.RouterNode
       if (!router.conditionNodes) router.conditionNodes = []
-      router.conditionNodes.push(node as EasyProcess.ConditionNode)
+      router.conditionNodes.push(node as Process.ConditionNode)
     } else {
       // 普通节点、条件节点添加 childNode
       const childNode = target.childNode
@@ -47,7 +47,7 @@ export class ProcessHelper {
    * 删除节点(递归查找)
    * @param nodeId 要删除的节点ID
    */
-  public deleteNode(nodeId: string, current: EasyProcess.NodeConfig = this.getProcessData()): boolean {
+  public deleteNode(nodeId: string, current: Process.NodeConfig = this.getProcessData()): boolean {
     // 禁止删除根节点
     if (this.processData.value?.nodeId === nodeId) return false
     // 删除子节点
@@ -57,7 +57,7 @@ export class ProcessHelper {
     }
     // 删除条件节点(router专用)
     if (current.nodeType === 'router') {
-      const router = current as EasyProcess.RouterNode
+      const router = current as Process.RouterNode
       const before = router.conditionNodes?.length ?? 0
       if (router.conditionNodes) {
         router.conditionNodes = router.conditionNodes.filter((c) => c.nodeId !== nodeId)
@@ -92,11 +92,11 @@ export class ProcessHelper {
   /**
    * 查找节点(深度优先)
    */
-  private findNode(nodeId: string, current: EasyProcess.NodeConfig): EasyProcess.NodeConfig | null {
+  private findNode(nodeId: string, current: Process.NodeConfig): Process.NodeConfig | null {
     if (current.nodeId === nodeId) return current
     // router 条件节点
     if (current.nodeType === 'router') {
-      const router = current as EasyProcess.RouterNode
+      const router = current as Process.RouterNode
       for (const c of router.conditionNodes || []) {
         const found = this.findNode(nodeId, c)
         if (found) return found
@@ -112,11 +112,11 @@ export class ProcessHelper {
   /**
    * 打印流程结构(调试用)
    */
-  public printTree(node: EasyProcess.NodeConfig = this.getProcessData(), indent = 0): void {
+  public printTree(node: Process.NodeConfig = this.getProcessData(), indent = 0): void {
     if (indent == 0) console.log('====== 流程结构 ======')
     console.log(`${' '.repeat(indent)}- ${node.nodeType} (${node.nodeName} | ${node.nodeId})`)
     if (node.nodeType === 'router') {
-      const router = node as EasyProcess.RouterNode
+      const router = node as Process.RouterNode
       router.conditionNodes?.forEach((cond) => this.printTree(cond, indent + 2))
     }
     if (node.childNode) this.printTree(node.childNode, indent + 2)

+ 1 - 1
src/components/business/EasyProcess/common/process.type.d.ts

@@ -5,7 +5,7 @@
  * 支持流程节点的类型声明、配置元数据及层级结构。
  * ==========================================
  */
-export declare namespace EasyProcess {
+export declare namespace Process {
   /**
    * ==========================================
    * 流程节点元信息定义(配置层)

+ 2 - 2
src/components/business/EasyProcess/core/drawer_default.vue

@@ -3,9 +3,9 @@
 </template>
 
 <script setup lang="ts">
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.NodeConfig }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.NodeConfig }>(), {})
   const title = computed(() => props.node.nodeType)
 </script>
 

+ 8 - 8
src/components/business/EasyProcess/core/drawer_wrap.vue

@@ -1,10 +1,10 @@
 <template>
   <Dialog>
     <div class="drawer_wrap">
-      <DrawerCondition v-if="node.nodeType === 'condition'" ref="conditionDrawerRef" :node="node as EasyProcess.ConditionNode" />
-      <DrawerOperation v-else-if="node.nodeType === 'operation'" ref="operationDrawerRef" :node="node as EasyProcess.OperationNode" />
-      <DrawerFault v-else-if="node.nodeType === 'fault'" ref="faultDrawerRef" :node="node as EasyProcess.FaultNode" />
-      <DrawerVoice v-else-if="node.nodeType === 'voice'" ref="voiceDrawerRef" :node="node as EasyProcess.VoiceNode" />
+      <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" />
+      <DrawerVoice v-else-if="node.nodeType === 'voice'" ref="voiceDrawerRef" :node="node as Process.VoiceNode" />
       <DrawerDefault v-else :node="node" />
     </div>
   </Dialog>
@@ -12,7 +12,7 @@
 
 <script setup lang="ts" name="DrawerWrap">
   import { useDialog } from '@/components/dialog'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
   import DrawerOperation from '../node/operation_drawer.vue'
   import DrawerFault from '../node/fault_drawer.vue'
@@ -22,9 +22,9 @@
   import { ProcessHelper } from '../common/process.helper'
   import { ProcessConstant } from '../common/process.data'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.NodeConfig }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.NodeConfig }>(), {})
   const processHelper = inject<ProcessHelper>(ProcessConstant.KEY_PROCESS_HELPER)
-  const processNode = ref<EasyProcess.NodeConfig>()
+  const processNode = ref<Process.NodeConfig>()
 
   const conditionDrawerRef = ref()
   const operationDrawerRef = ref()
@@ -69,7 +69,7 @@
     }
   })
   defineExpose({
-    show(node: EasyProcess.NodeConfig) {
+    show(node: Process.NodeConfig) {
       processNode.value = node
       dialogApi.setState({ title: props.node.nodeName || '节点配置' })
       dialogApi.open()

+ 5 - 5
src/components/business/EasyProcess/core/node_add.vue

@@ -15,14 +15,14 @@
 <script setup lang="ts" name="AddNode">
   import { ref, computed } from 'vue'
   import { nodeConfigData, ProcessConstant } from '../common/process.data'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import { ProcessHelper } from '../common/process.helper'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.NodeConfig }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.NodeConfig }>(), {})
 
   /** ---------- 选择添加节点 ---------- start */
-  interface NodeSelect extends Pick<EasyProcess.NodeMeta, 'title' | 'icon'> {
-    type: EasyProcess.NodeType
+  interface NodeSelect extends Pick<Process.NodeMeta, 'title' | 'icon'> {
+    type: Process.NodeType
     iconColor: string
   }
   const availableNodeTypes = computed(() => {
@@ -46,7 +46,7 @@
 
   const processHelper = inject<ProcessHelper>(ProcessConstant.KEY_PROCESS_HELPER)
 
-  const insertNodeIntoParent = (nodeType: EasyProcess.NodeType) => {
+  const insertNodeIntoParent = (nodeType: Process.NodeType) => {
     let typeConfig = nodeConfigData[nodeType]
     if (!typeConfig) {
       ElMessage.error(`节点类型${nodeType}不存在`)

+ 2 - 2
src/components/business/EasyProcess/core/node_base.vue

@@ -30,7 +30,7 @@
   import DrawerWrap from './drawer_wrap.vue'
   import NodeAdd from './node_add.vue'
   import { nodeConfigData, ProcessConstant } from '../common/process.data'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import { ProcessHelper, ProcessValidator } from '../common/process.helper'
 
   import NodeStart from '../node/start_node.vue'
@@ -47,7 +47,7 @@
     voice: NodeVoice
   })
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.NodeConfig }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.NodeConfig }>(), {})
 
   const isEdit = inject<boolean>(ProcessConstant.KEY_EDIT, true)
 

+ 2 - 2
src/components/business/EasyProcess/core/node_router.vue

@@ -28,9 +28,9 @@
   import AddNode from './node_add.vue'
   import { nodeConfigData, ProcessConstant } from '../common/process.data'
   import { ProcessHelper } from '../common/process.helper'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.RouterNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.RouterNode }>(), {})
   const processHelper = inject<ProcessHelper>(ProcessConstant.KEY_PROCESS_HELPER)
   const addCondition = () => processHelper?.addNode(props.node.nodeId, nodeConfigData['condition'].defaultNode())
 </script>

+ 3 - 3
src/components/business/EasyProcess/core/node_wrap.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="ep-node-wrap" v-if="props.node">
     <!-- 路由节点 -->
-    <RouterNode v-if="props.node.nodeType == 'router'" :node="node as EasyProcess.RouterNode" />
+    <RouterNode v-if="props.node.nodeType == 'router'" :node="node as Process.RouterNode" />
     <!-- 普通节点 -->
     <BaseNode v-else :node="props.node" />
     <!-- 子节点 -->
@@ -11,11 +11,11 @@
 
 <script setup lang="ts" name="NodeWrap">
   defineOptions({ name: 'NodeWrap' })
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import BaseNode from './node_base.vue'
   import RouterNode from './node_router.vue'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.NodeConfig }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.NodeConfig }>(), {})
 </script>
 
 <style lang="scss" scoped></style>

+ 17 - 6
src/components/business/EasyProcess/index.vue

@@ -26,17 +26,17 @@
   import { ref, provide } from 'vue'
   import { blankProcessData, ProcessConstant } from './common/process.data'
   import { ProcessHelper, ProcessValidator } from './common/process.helper'
-  import { EasyProcess } from './common/process.type'
+  import { Process } from './common/process.type'
 
   // 流程数据
-  const props = withDefaults(defineProps<{ data?: EasyProcess.NodeConfig; edit?: boolean }>(), { edit: true })
+  const props = withDefaults(defineProps<{ data?: string; edit?: boolean }>(), { edit: true })
 
-  const getProcessData = (data: EasyProcess.NodeConfig = props.data || blankProcessData()) => {
+  const getProcessData = (data: Process.NodeConfig = JSON.parse(props.data || '{}')) => {
     if (data?.nodeType === 'start') return data
     return blankProcessData()
   }
 
-  const processHelper = new ProcessHelper(getProcessData(props.data))
+  const processHelper = new ProcessHelper(getProcessData(JSON.parse(props.data || '{}') as Process.NodeConfig))
   provide<ProcessHelper>(ProcessConstant.KEY_PROCESS_HELPER, processHelper)
   const processData = computed(() => processHelper.getProcessData())
 
@@ -44,7 +44,7 @@
     () => props.data,
     (newVal) => {
       if (newVal) {
-        processHelper.setProcessData(getProcessData(newVal))
+        processHelper.setProcessData(getProcessData(JSON.parse(newVal) as Process.NodeConfig))
       }
     }
   )
@@ -69,7 +69,18 @@
   /** ====== 缩放 ====== end */
 
   // 暴露方法给父组件使用
-  defineExpose({ validate, getProcess: () => processHelper.getProcessData() })
+  defineExpose({
+    validate,
+    getProcess: (): string => {
+      validate((valid, messages) => {
+        if (!valid) {
+          ElMessage.error('请修复以下错误:\n' + messages.join('\n'))
+          return
+        }
+      })
+      return JSON.stringify(processHelper.getProcessData())
+    }
+  })
 </script>
 <style lang="scss" scoped>
   .ep-container {

+ 12 - 6
src/components/business/EasyProcess/node/condition_drawer.vue

@@ -1,14 +1,13 @@
 <template>
   <div>
-    <BasicForm :model="nodeData"> </BasicForm>
+    <BasicForm> </BasicForm>
   </div>
 </template>
 <script setup lang="ts" name="DrawerOperation">
   import { useForm } from '@/components/form'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.ConditionNode }>(), {})
-  const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
+  const props = withDefaults(defineProps<{ node: Process.ConditionNode }>(), {})
 
   const [BasicForm, formApi] = useForm({
     labelWidth: '100px',
@@ -29,11 +28,18 @@
     ]
   })
 
+  onMounted(async () => {
+    nextTick(() => {
+      formApi.setValues(props.node.nodeData || {})
+    })
+  })
+
   defineExpose({
-    getNodeData: (callback: (nodeData: Record<string, unknown>) => void) => {
+    getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
+      const data = await formApi.getValues()
       formApi.validate().then((valid) => {
         if (valid) {
-          callback(nodeData.value)
+          callback(data)
         } else {
           ElMessage.error('请检查节点配置是否完整')
         }

+ 9 - 6
src/components/business/EasyProcess/node/fault_drawer.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <BasicForm :model="nodeData">
+    <BasicForm>
       <template #templateID="{ model }">
         <el-select-v2
           v-model="model.templateID"
@@ -19,12 +19,11 @@
 </template>
 <script setup lang="ts" name="DrawerOperation">
   import { useForm } from '@/components/form'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import { ProcessFault, ProcessServer } from '@/api/course.api'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.FaultNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.FaultNode }>(), {})
 
-  const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
   const templateList = ref<ProcessFault[]>([])
   const templateSelected = ref<ProcessFault>()
 
@@ -173,13 +172,17 @@
   onMounted(async () => {
     const { data } = await ProcessServer.faultList()
     templateList.value = data || []
+    nextTick(() => {
+      formApi.setValues(props.node.nodeData || {})
+    })
   })
 
   defineExpose({
-    getNodeData: (callback: (nodeData: Record<string, unknown>) => void) => {
+    getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
+      const data = await formApi.getValues()
       formApi.validate().then((valid) => {
         if (valid) {
-          callback(nodeData.value)
+          callback(data)
         } else {
           ElMessage.error('请检查节点配置是否完整')
         }

+ 2 - 2
src/components/business/EasyProcess/node/fault_node.vue

@@ -5,9 +5,9 @@
   </div>
 </template>
 <script setup lang="ts">
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.FaultNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.FaultNode }>(), {})
   const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
   const roleIcon: string[] = ['role_default', 'role_substation', 'role_catenary', 'role_dispatch', 'role_isolator', 'role_supply']
 

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

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <BasicForm :model="nodeData">
+    <BasicForm>
       <template #templateID="{ model }">
         <el-select-v2
           v-model="model.templateID"
@@ -19,12 +19,11 @@
 </template>
 <script setup lang="ts" name="DrawerOperation">
   import { useForm } from '@/components/form'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import { ProcessOperate, ProcessServer } from '@/api/course.api'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.OperationNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.OperationNode }>(), {})
 
-  const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
   const templateList = ref<ProcessOperate[]>([])
   const templateSelected = ref<ProcessOperate>()
 
@@ -124,13 +123,15 @@
   onMounted(async () => {
     const { data } = await ProcessServer.operateList()
     templateList.value = data || []
+    formApi.setValues(props.node.nodeData || {})
   })
 
   defineExpose({
-    getNodeData: (callback: (nodeData: Record<string, unknown>) => void) => {
+    getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
+      const data = await formApi.getValues()
       formApi.validate().then((valid) => {
         if (valid) {
-          callback(nodeData.value)
+          callback(data)
         } else {
           ElMessage.error('请检查节点配置是否完整')
         }

+ 2 - 2
src/components/business/EasyProcess/node/operation_node.vue

@@ -5,9 +5,9 @@
   </div>
 </template>
 <script setup lang="ts">
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.OperationNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.OperationNode }>(), {})
   const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
 
   const roleIcon: string[] = ['role_default', 'role_substation', 'role_catenary', 'role_dispatch', 'role_isolator', 'role_supply']

+ 9 - 7
src/components/business/EasyProcess/node/voice_drawer.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <BasicForm :model="nodeData">
+    <BasicForm>
       <template #templateID="{ model }">
         <el-select-v2
           v-model="model.templateID"
@@ -19,12 +19,11 @@
 </template>
 <script setup lang="ts" name="DrawerOperation">
   import { useForm } from '@/components/form'
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
   import { ProcessVoice, ProcessServer } from '@/api/course.api'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.VoiceNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.VoiceNode }>(), {})
 
-  const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
   const templateList = ref<ProcessVoice[]>([])
   const templateSelected = ref<ProcessVoice>()
 
@@ -49,7 +48,6 @@
       const template = templateList.value.find((item) => item.templateID == val)
       if (template) {
         templateSelected.value = template
-        nodeData.value.subCategoryName = template.subCategoryName
       }
     }
   }
@@ -57,13 +55,17 @@
   onMounted(async () => {
     const { data } = await ProcessServer.voiceList()
     templateList.value = data || []
+    nextTick(() => {
+      formApi.setValues(props.node.nodeData || {})
+    })
   })
 
   defineExpose({
-    getNodeData: (callback: (nodeData: Record<string, unknown>) => void) => {
+    getNodeData: async (callback: (nodeData: Record<string, unknown>) => void) => {
+      const data = await formApi.getValues()
       formApi.validate().then((valid) => {
         if (valid) {
-          callback(nodeData.value)
+          callback(data)
         } else {
           ElMessage.error('请检查节点配置是否完整')
         }

+ 2 - 2
src/components/business/EasyProcess/node/voice_node.vue

@@ -5,9 +5,9 @@
   </div>
 </template>
 <script setup lang="ts">
-  import { EasyProcess } from '../common/process.type'
+  import { Process } from '../common/process.type'
 
-  const props = withDefaults(defineProps<{ node: EasyProcess.VoiceNode }>(), {})
+  const props = withDefaults(defineProps<{ node: Process.VoiceNode }>(), {})
   const nodeData = ref<Record<string, unknown>>(props.node.nodeData || {})
 
   const roleIcon: string[] = ['role_default', 'role_substation', 'role_catenary', 'role_dispatch', 'role_isolator', 'role_supply']

+ 2 - 2
src/utils/sys/mittBus.ts

@@ -4,7 +4,7 @@
  * mittBus.on('event', callback)
  * mittBus.emit('event', data)
  */
-import { EasyProcess } from '@/components/business/EasyProcess/common/process.type'
+import { Process } from '@/components/business/EasyProcess/common/process.type'
 import mitt, { type Emitter } from 'mitt'
 
 // 定义事件类型映射
@@ -20,7 +20,7 @@ type Events = {
   // 打开锁屏事件 - 无参数
   openLockScreen: void
   // 流程节点的选中事件 - 可选的节点ID参数
-  selectProcessNode: EasyProcess.NodeConfig | undefined
+  selectProcessNode: Process.NodeConfig | undefined
 }
 
 // 创建类型安全的事件总线实例

+ 0 - 27
src/views/train/course/detail/course-flow.vue

@@ -1,27 +0,0 @@
-<template>
-  <div class="art-full-height w-full">
-    <EasyProcess ref="processRef" :data="processData" :edit="edit" />
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { EasyProcess as ProcessType } from '@/components/business/EasyProcess/common/process.type'
-  import EasyProcess from '@/components/business/EasyProcess/index.vue'
-  import { onMounted, ref } from 'vue'
-
-  const props = withDefaults(defineProps<{ data?: string; edit?: boolean }>(), { edit: true })
-  // 定义 ProcessDesigner 的实例类型
-  type ProcessDesignerInstance = InstanceType<typeof EasyProcess>
-  // 审批数据
-  const processData = ref<ProcessType.NodeConfig>()
-  // 组件实例 ref
-  const processRef = ref<ProcessDesignerInstance>()
-
-  onMounted(() => {
-    if (props.data) {
-      processData.value = JSON.parse(props.data) as ProcessType.NodeConfig
-    }
-  })
-</script>
-
-<style lang="scss" scoped></style>

+ 18 - 5
src/views/train/course/detail/index.vue

@@ -12,7 +12,7 @@
     <div v-loading="loading" class="mt-4">
       <BasicForm :formModelInit="courseDetail" @change="handleChange">
         <template #courseDataStream>
-          <courseFlow />
+          <EasyProcess ref="easyProcessRef" />
         </template>
         <template #evaluate>
           <courseEvaluate />
@@ -22,19 +22,22 @@
   </div>
 </template>
 <script setup lang="ts">
-  import courseFlow from './course-flow.vue'
+  import EasyProcess from '@/components/business/EasyProcess/index.vue'
   import courseEvaluate from './course-evaluate.vue'
   import { schema, courseSchema, rules } from './course.schema'
   import { Course, CourseServer } from '@/api/course.api'
   import { useForm } from '@/components/form'
   import { router } from '@/router'
   import { ElMessageBox, ElMessage } from 'element-plus'
+  import { number } from 'echarts'
 
   // 路由参数
   const route = useRoute()
   const courseId = computed<string>(() => String(route.params.id))
   const query = computed(() => route.query)
 
+  const easyProcessRef = ref()
+
   const courseNew = computed(() => courseId.value === '0')
   const courseEdit = computed(() => !courseNew.value && query.value.edit === 'true')
   const courseQuery = computed(() => !courseNew.value && !courseEdit.value)
@@ -46,16 +49,26 @@
   const handleChange = (val: any) => (formData.value = val)
 
   const addCourse = async () => {
+    const processData = easyProcessRef.value.getProcess()
+    console.log(processData)
+    if (!processData) {
+      ElMessage.error('请设计课程流程')
+      return
+    }
     formApi
       .validate()
       .then(async () => {
-        const data = formData.value
+        const courseData = formData.value
         if (courseNew.value) {
-          await CourseServer.add(data)
+          const { data: { courseId } = { courseId: number } } = await CourseServer.add({ ...courseData, courseDataStream: processData })
+          // 保存流程图
+          await CourseServer.saveProcess(courseId.toString(), processData)
           ElMessage.success('新增课程成功')
           router.push({ path: '/course/list' })
         } else if (courseEdit.value) {
-          await CourseServer.update(data)
+          await CourseServer.update({ ...courseData, courseDataStream: processData })
+          // 保存流程图
+          await CourseServer.saveProcess(courseId.value.toString(), processData)
           ElMessage.success('编辑课程成功')
           router.push({ path: '/course/list' })
         } else {

+ 5 - 5
src/views/train/course/trainer_run/index.vue

@@ -18,7 +18,7 @@
     </div>
     <div class="flex h-full flex-1 flex-row gap-4">
       <div class="flex-1 border">
-        <course-flow :data="course?.courseDataStream" :edit="false"></course-flow>
+        <EasyProcess ref="processRef" :data="course?.courseDataStream" :edit="false" />
       </div>
       <div class="flex flex-col gap-4">
         <div class="h-[180px] w-[320px] border p-4">
@@ -40,14 +40,14 @@
   import { onMounted, ref, computed } from 'vue'
   import { useRoute } from 'vue-router'
   import mittBus from '@/utils/sys/mittBus'
-  import { EasyProcess } from '@/components/business/EasyProcess/common/process.type'
+  import EasyProcess from '@/components/business/EasyProcess/index.vue'
+  import { Process } from '@/components/business/EasyProcess/common/process.type'
   import cover1 from '@imgs/cover/img1.webp'
   import cover2 from '@imgs/cover/img2.webp'
   import cover3 from '@imgs/cover/img3.webp'
   import { Picture as IconPicture } from '@element-plus/icons-vue'
   import { Course, CourseServer, CourseRunServer } from '@/api/course.api'
   import courseDetail from './course-detail.vue'
-  import courseFlow from '../detail/course-flow.vue'
   import { useTimer } from '@/composables/useTimer'
 
   // 计时器
@@ -78,8 +78,8 @@
     return cover2
   }
 
-  const processData = ref<EasyProcess.NodeConfig>()
-  mittBus.on('selectProcessNode', (node: EasyProcess.NodeConfig | undefined) => {
+  const processData = ref<Process.NodeConfig>()
+  mittBus.on('selectProcessNode', (node: Process.NodeConfig | undefined) => {
     if (node) {
       processData.value = node
     }

+ 1 - 0
vite.config.ts

@@ -27,6 +27,7 @@ export default ({ mode }: { mode: string }) => {
         '/api': {
           target: VITE_API_PROXY_URL,
           changeOrigin: true,
+          secure: false,
           rewrite: (path) => path.replace(/^\/api/, '')
         }
       },