乐菲 1 month ago
parent
commit
5957964e4c

+ 281 - 214
src/components/BpmnProcessDesigner/package/designer/ProcessViewer.vue

@@ -7,334 +7,401 @@
 </template>
 
 <script>
-import BpmnViewer from 'bpmn-js/lib/Viewer'
-import DefaultEmptyXML from './plugins/defaultEmpty'
+import BpmnViewer from "bpmn-js/lib/Viewer";
+import DefaultEmptyXML from "./plugins/defaultEmpty";
 
 export default {
-  name: 'MyProcessViewer',
-  componentName: 'MyProcessViewer',
+  name: "MyProcessViewer",
+  componentName: "MyProcessViewer",
   props: {
-    value: { // BPMN XML 字符串
+    value: {
+      // BPMN XML 字符串
       type: String,
-      default: ''
+      default: "",
     },
-    prefix: { // 使用哪个引擎
+    prefix: {
+      // 使用哪个引擎
       type: String,
-      default: 'camunda'
+      default: "camunda",
     },
-    activityData: { // 活动的数据。传递时,可高亮流程
+    activityData: {
+      // 活动的数据。传递时,可高亮流程
       type: Array,
-      default: () => []
+      default: () => [],
     },
-    processInstanceData: { // 流程实例的数据。传递时,可展示流程发起人等信息
+    processInstanceData: {
+      // 流程实例的数据。传递时,可展示流程发起人等信息
       type: Object,
-      default: () => {}
+      default: () => {},
     },
-    taskData: { // 任务实例的数据。传递时,可展示 UserTask 审核相关的信息
+    taskData: {
+      // 任务实例的数据。传递时,可展示 UserTask 审核相关的信息
       type: Array,
-      default: () => []
-    }
+      default: () => [],
+    },
   },
   data() {
     return {
-      xml: '',
+      xml: "",
       activityList: [],
       processInstance: undefined,
-      taskList: []
-    }
+      taskList: [],
+    };
   },
   watch: {
-    value: function(newValue) { // 在 xmlString 发生变化时,重新创建,从而绘制流程图
-      this.xml = newValue
-      this.createNewDiagram(this.xml)
+    value: function (newValue) {
+      // 在 xmlString 发生变化时,重新创建,从而绘制流程图
+      this.xml = newValue;
+      this.createNewDiagram(this.xml);
+    },
+    activityData: function (newActivityData) {
+      this.activityList = newActivityData;
+      this.createNewDiagram(this.xml);
     },
-    activityData: function(newActivityData) {
-      this.activityList = newActivityData
-      this.createNewDiagram(this.xml)
+    processInstanceData: function (newProcessInstanceData) {
+      this.processInstance = newProcessInstanceData;
+      this.createNewDiagram(this.xml);
     },
-    processInstanceData: function(newProcessInstanceData) {
-      this.processInstance = newProcessInstanceData
-      this.createNewDiagram(this.xml)
+    taskData: function (newTaskListData) {
+      this.taskList = newTaskListData;
+      this.createNewDiagram(this.xml);
     },
-    taskData: function(newTaskListData) {
-      this.taskList = newTaskListData
-      this.createNewDiagram(this.xml)
-    }
   },
   mounted() {
-    this.xml = this.value
-    this.activityList = this.activityData
+    this.xml = this.value;
+    this.activityList = this.activityData;
     // 初始化
-    this.initBpmnModeler()
-    this.createNewDiagram(this.xml)
-    this.$once('hook:beforeDestroy', () => {
-      if (this.bpmnModeler) this.bpmnModeler.destroy()
-      this.$emit('destroy', this.bpmnModeler)
-      this.bpmnModeler = null
-    })
+    this.initBpmnModeler();
+    this.createNewDiagram(this.xml);
+    this.$once("hook:beforeDestroy", () => {
+      if (this.bpmnModeler) this.bpmnModeler.destroy();
+      this.$emit("destroy", this.bpmnModeler);
+      this.bpmnModeler = null;
+    });
     // 初始模型的监听器
-    this.initModelListeners()
+    this.initModelListeners();
   },
   methods: {
     initBpmnModeler() {
-      if (this.bpmnModeler) return
+      if (this.bpmnModeler) return;
       this.bpmnModeler = new BpmnViewer({
-        container: this.$refs['bpmn-canvas'],
-        bpmnRenderer: {
-        }
-      })
+        container: this.$refs["bpmn-canvas"],
+        bpmnRenderer: {},
+      });
     },
     /* 创建新的流程图 */
     async createNewDiagram(xml) {
       // 将字符串转换成图显示出来
-      const newId = `Process_${new Date().getTime()}`
-      const newName = `业务流程_${new Date().getTime()}`
-      const xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix)
+      const newId = `Process_${new Date().getTime()}`;
+      const newName = `业务流程_${new Date().getTime()}`;
+      const xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
       try {
         // console.log(this.bpmnModeler.importXML);
-        const { warnings } = await this.bpmnModeler.importXML(xmlString)
+        const { warnings } = await this.bpmnModeler.importXML(xmlString);
         if (warnings && warnings.length) {
-          warnings.forEach(warn => console.warn(warn))
+          warnings.forEach((warn) => console.warn(warn));
         }
         // 高亮流程图
-        await this.highlightDiagram()
-        const canvas = this.bpmnModeler.get('canvas')
-        canvas.zoom('fit-viewport', 'auto')
+        await this.highlightDiagram();
+        const canvas = this.bpmnModeler.get("canvas");
+        canvas.zoom("fit-viewport", "auto");
       } catch (e) {
-        console.error(e)
+        console.error(e);
         // console.error(`[Process Designer Warn]: ${e?.message || e}`);
       }
     },
     /* 高亮流程图 */
     // TODO 芋艿:如果多个 endActivity 的话,目前的逻辑可能有一定的问题。https://www.jdon.com/workflow/multi-events.html
     async highlightDiagram() {
-      const activityList = this.activityList
+      const activityList = this.activityList;
       if (activityList.length === 0) {
-        return
+        return;
       }
       // 参考自 https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-ui/src/components/Process/index.vue#L222 实现
       // 再次基础上,增加不同审批结果的颜色等等
-      const canvas = this.bpmnModeler.get('canvas')
-      const todoActivity = activityList.find(m => !m.endTime) // 找到待办的任务
-      const endActivity = activityList[activityList.length - 1] // 获得最后一个任务
+      const canvas = this.bpmnModeler.get("canvas");
+      const todoActivity = activityList.find((m) => !m.endTime); // 找到待办的任务
+      const endActivity = activityList[activityList.length - 1]; // 获得最后一个任务
       // debugger
       // console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements);
-      this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => {
-        const activity = activityList.find(m => m.key === n.id) // 找到对应的活动
-        if (!activity) {
-          return
-        }
-        if (n.$type === 'bpmn:UserTask') { // 用户任务
-          // 处理用户任务的高亮
-          const task = this.taskList.find(m => m.id === activity.taskId) // 找到活动对应的 taskId
-          if (!task) {
-            return
+      this.bpmnModeler
+        .getDefinitions()
+        .rootElements[0].flowElements?.forEach((n) => {
+          const activity = activityList.find((m) => m.key === n.id); // 找到对应的活动
+          if (!activity) {
+            return;
           }
-          // 高亮任务
-          canvas.addMarker(n.id, this.getResultCss(task.result))
+          if (n.$type === "bpmn:UserTask") {
+            // 用户任务
+            // 处理用户任务的高亮
+            const task = this.taskList.find((m) => m.id === activity.taskId); // 找到活动对应的 taskId
+            if (!task) {
+              return;
+            }
+            // 高亮任务
+            canvas.addMarker(n.id, this.getResultCss(task.status));
 
-          // 如果非通过,就不走后面的线条了
-          if (task.result !== 2) {
-            return
-          }
-          // 处理 outgoing 出线
-          const outgoing = this.getActivityOutgoing(activity)
-          outgoing?.forEach(nn => {
-            // debugger
-            const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
-            // 如果目标活动存在,则根据该活动是否结束,进行【bpmn:SequenceFlow】连线的高亮设置
-            if (targetActivity) {
-              canvas.addMarker(nn.id, targetActivity.endTime ? 'highlight' : 'highlight-todo')
-            } else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') { // TODO 芋艿:这个流程,暂时没走到过
-              canvas.addMarker(nn.id, activity.endTime ? 'highlight' : 'highlight-todo')
-              canvas.addMarker(nn.targetRef.id, activity.endTime ? 'highlight' : 'highlight-todo')
-            } else if (nn.targetRef.$type === 'bpmn:EndEvent') { // TODO 芋艿:这个流程,暂时没走到过
-              if (!todoActivity && endActivity.key === n.id) {
-                canvas.addMarker(nn.id, 'highlight')
-                canvas.addMarker(nn.targetRef.id, 'highlight')
+            // 如果非通过,就不走后面的线条了
+            if (task.status !== 2) {
+              return;
+            }
+            // 处理 outgoing 出线
+            const outgoing = this.getActivityOutgoing(activity);
+            outgoing?.forEach((nn) => {
+              // debugger
+              const targetActivity = activityList.find(
+                (m) => m.key === nn.targetRef.id
+              );
+              // 如果目标活动存在,则根据该活动是否结束,进行【bpmn:SequenceFlow】连线的高亮设置
+              if (targetActivity) {
+                canvas.addMarker(
+                  nn.id,
+                  targetActivity.endTime ? "highlight" : "highlight-todo"
+                );
+              } else if (nn.targetRef.$type === "bpmn:ExclusiveGateway") {
+                // TODO 芋艿:这个流程,暂时没走到过
+                canvas.addMarker(
+                  nn.id,
+                  activity.endTime ? "highlight" : "highlight-todo"
+                );
+                canvas.addMarker(
+                  nn.targetRef.id,
+                  activity.endTime ? "highlight" : "highlight-todo"
+                );
+              } else if (nn.targetRef.$type === "bpmn:EndEvent") {
+                // TODO 芋艿:这个流程,暂时没走到过
+                if (!todoActivity && endActivity.key === n.id) {
+                  canvas.addMarker(nn.id, "highlight");
+                  canvas.addMarker(nn.targetRef.id, "highlight");
+                }
+                if (!activity.endTime) {
+                  canvas.addMarker(nn.id, "highlight-todo");
+                  canvas.addMarker(nn.targetRef.id, "highlight-todo");
+                }
               }
-              if (!activity.endTime) {
-                canvas.addMarker(nn.id, 'highlight-todo')
-                canvas.addMarker(nn.targetRef.id, 'highlight-todo')
+            });
+          } else if (n.$type === "bpmn:ExclusiveGateway") {
+            // 排它网关
+            // 设置【bpmn:ExclusiveGateway】排它网关的高亮
+            canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
+            // 查找需要高亮的连线
+            let matchNN;
+            let matchActivity;
+            n.outgoing?.forEach((nn) => {
+              const targetActivity = activityList.find(
+                (m) => m.key === nn.targetRef.id
+              );
+              if (!targetActivity) {
+                return;
               }
+              // 特殊判断 endEvent 类型的原因,ExclusiveGateway 可能后续连有 2 个路径:
+              //  1. 一个是 UserTask => EndEvent
+              //  2. 一个是 EndEvent
+              // 在选择路径 1 时,其实 EndEvent 可能也存在,导致 1 和 2 都高亮,显然是不正确的。
+              // 所以,在 matchActivity 为 EndEvent 时,需要进行覆盖~~
+              if (!matchActivity || matchActivity.type === "endEvent") {
+                matchNN = nn;
+                matchActivity = targetActivity;
+              }
+            });
+            if (matchNN && matchActivity) {
+              canvas.addMarker(
+                matchNN.id,
+                this.getActivityHighlightCss(matchActivity)
+              );
             }
-          })
-        } else if (n.$type === 'bpmn:ExclusiveGateway') { // 排它网关
-          // 设置【bpmn:ExclusiveGateway】排它网关的高亮
-          canvas.addMarker(n.id, this.getActivityHighlightCss(activity))
-          // 查找需要高亮的连线
-          let matchNN
-          let matchActivity
-          n.outgoing?.forEach(nn => {
-            const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
-            if (!targetActivity) {
-              return
-            }
-            // 特殊判断 endEvent 类型的原因,ExclusiveGateway 可能后续连有 2 个路径:
-            //  1. 一个是 UserTask => EndEvent
-            //  2. 一个是 EndEvent
-            // 在选择路径 1 时,其实 EndEvent 可能也存在,导致 1 和 2 都高亮,显然是不正确的。
-            // 所以,在 matchActivity 为 EndEvent 时,需要进行覆盖~~
-            if (!matchActivity || matchActivity.type === 'endEvent') {
-              matchNN = nn
-              matchActivity = targetActivity
+          } else if (n.$type === "bpmn:ParallelGateway") {
+            // 并行网关
+            // 设置【bpmn:ParallelGateway】并行网关的高亮
+            canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
+            n.outgoing?.forEach((nn) => {
+              // 获得连线是否有指向目标。如果有,则进行高亮
+              const targetActivity = activityList.find(
+                (m) => m.key === nn.targetRef.id
+              );
+              if (targetActivity) {
+                canvas.addMarker(
+                  nn.id,
+                  this.getActivityHighlightCss(targetActivity)
+                ); // 高亮【bpmn:SequenceFlow】连线
+                // 高亮【...】目标。其中 ... 可以是 bpm:UserTask、也可以是其它的。当然,如果是 bpm:UserTask 的话,其实不做高亮也没问题,因为上面有逻辑做了这块。
+                canvas.addMarker(
+                  nn.targetRef.id,
+                  this.getActivityHighlightCss(targetActivity)
+                );
+              }
+            });
+          } else if (n.$type === "bpmn:StartEvent") {
+            // 开始节点
+            n.outgoing?.forEach((nn) => {
+              // outgoing 例如说【bpmn:SequenceFlow】连线
+              // 获得连线是否有指向目标。如果有,则进行高亮
+              const targetActivity = activityList.find(
+                (m) => m.key === nn.targetRef.id
+              );
+              if (targetActivity) {
+                canvas.addMarker(nn.id, "highlight"); // 高亮【bpmn:SequenceFlow】连线
+                canvas.addMarker(n.id, "highlight"); // 高亮【bpmn:StartEvent】开始节点(自己)
+              }
+            });
+          } else if (n.$type === "bpmn:EndEvent") {
+            // 结束节点
+            if (!this.processInstance || this.processInstance.result === 1) {
+              return;
             }
-          })
-          if (matchNN && matchActivity) {
-            canvas.addMarker(matchNN.id, this.getActivityHighlightCss(matchActivity))
-          }
-        } else if (n.$type === 'bpmn:ParallelGateway') { // 并行网关
-          // 设置【bpmn:ParallelGateway】并行网关的高亮
-          canvas.addMarker(n.id, this.getActivityHighlightCss(activity))
-          n.outgoing?.forEach(nn => {
-            // 获得连线是否有指向目标。如果有,则进行高亮
-            const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
-            if (targetActivity) {
-              canvas.addMarker(nn.id, this.getActivityHighlightCss(targetActivity)) // 高亮【bpmn:SequenceFlow】连线
-              // 高亮【...】目标。其中 ... 可以是 bpm:UserTask、也可以是其它的。当然,如果是 bpm:UserTask 的话,其实不做高亮也没问题,因为上面有逻辑做了这块。
-              canvas.addMarker(nn.targetRef.id, this.getActivityHighlightCss(targetActivity))
+            canvas.addMarker(
+              n.id,
+              this.getResultCss(this.processInstance.result)
+            );
+          } else if (n.$type === "bpmn:ServiceTask") {
+            // 服务任务
+            if (activity.startTime > 0 && activity.endTime === 0) {
+              // 进入执行,标识进行色
+              canvas.addMarker(n.id, this.getResultCss(1));
             }
-          })
-        } else if (n.$type === 'bpmn:StartEvent') { // 开始节点
-          n.outgoing?.forEach(nn => { // outgoing 例如说【bpmn:SequenceFlow】连线
-            // 获得连线是否有指向目标。如果有,则进行高亮
-            const targetActivity = activityList.find(m => m.key === nn.targetRef.id)
-            if (targetActivity) {
-              canvas.addMarker(nn.id, 'highlight') // 高亮【bpmn:SequenceFlow】连线
-              canvas.addMarker(n.id, 'highlight') // 高亮【bpmn:StartEvent】开始节点(自己)
+            if (activity.endTime > 0) {
+              // 执行完成,节点标识完成色, 所有outgoing标识完成色。
+              canvas.addMarker(n.id, this.getResultCss(2));
+              const outgoing = this.getActivityOutgoing(activity);
+              outgoing?.forEach((out) => {
+                canvas.addMarker(out.id, this.getResultCss(2));
+              });
             }
-          })
-        } else if (n.$type === 'bpmn:EndEvent') { // 结束节点
-          if (!this.processInstance || this.processInstance.result === 1) {
-            return
-          }
-          canvas.addMarker(n.id, this.getResultCss(this.processInstance.result))
-        } else if (n.$type === 'bpmn:ServiceTask') { // 服务任务
-          if (activity.startTime > 0 && activity.endTime === 0) { // 进入执行,标识进行色
-            canvas.addMarker(n.id, this.getResultCss(1))
-          }
-          if (activity.endTime > 0) { // 执行完成,节点标识完成色, 所有outgoing标识完成色。
-            canvas.addMarker(n.id, this.getResultCss(2))
-            const outgoing = this.getActivityOutgoing(activity)
-            outgoing?.forEach(out => {
-              canvas.addMarker(out.id, this.getResultCss(2))
-            })
           }
-        }
-      })
+        });
     },
     getActivityHighlightCss(activity) {
-      return activity.endTime ? 'highlight' : 'highlight-todo'
+      return activity.endTime ? "highlight" : "highlight-todo";
     },
     getResultCss(result) {
-      if (result === 1) { // 审批中
-        return 'highlight-todo'
-      } else if (result === 2) { // 已通过
-        return 'highlight'
-      } else if (result === 3) { // 不通过
-        return 'highlight-reject'
-      } else if (result === 4) { // 已取消
-        return 'highlight-cancel'
+      if (result === 1) {
+        // 审批中
+        return "highlight-todo";
+      } else if (result === 2) {
+        // 已通过
+        return "highlight";
+      } else if (result === 3) {
+        // 不通过
+        return "highlight-reject";
+      } else if (result === 4) {
+        // 已取消
+        return "highlight-cancel";
       }
-      return ''
+      return "highlight-none";
     },
     getActivityOutgoing(activity) {
       // 如果有 outgoing,则直接使用它
       if (activity.outgoing && activity.outgoing.length > 0) {
-        return activity.outgoing
+        return activity.outgoing;
       }
       // 如果没有,则遍历获得起点为它的【bpmn:SequenceFlow】节点们。原因是:bpmn-js 的 UserTask 拿不到 outgoing
-      const flowElements = this.bpmnModeler.getDefinitions().rootElements[0].flowElements
-      const outgoing = []
-      flowElements.forEach(item => {
-        if (item.$type !== 'bpmn:SequenceFlow') {
-          return
+      const flowElements =
+        this.bpmnModeler.getDefinitions().rootElements[0].flowElements;
+      const outgoing = [];
+      flowElements.forEach((item) => {
+        if (item.$type !== "bpmn:SequenceFlow") {
+          return;
         }
         if (item.sourceRef.id === activity.key) {
-          outgoing.push(item)
+          outgoing.push(item);
         }
-      })
-      return outgoing
+      });
+      return outgoing;
     },
     initModelListeners() {
-      const EventBus = this.bpmnModeler.get('eventBus')
-      const that = this
+      const EventBus = this.bpmnModeler.get("eventBus");
+      const that = this;
       // 注册需要的监听事件
-      EventBus.on('element.hover', function(eventObj) {
-        const element = eventObj ? eventObj.element : null
-        that.elementHover(element)
-      })
-      EventBus.on('element.out', function(eventObj) {
-        const element = eventObj ? eventObj.element : null
-        that.elementOut(element)
-      })
+      EventBus.on("element.hover", function (eventObj) {
+        const element = eventObj ? eventObj.element : null;
+        that.elementHover(element);
+      });
+      EventBus.on("element.out", function (eventObj) {
+        const element = eventObj ? eventObj.element : null;
+        that.elementOut(element);
+      });
     },
     // 流程图的元素被 hover
     elementHover(element) {
-      this.element = element
-      !this.elementOverlayIds && (this.elementOverlayIds = {})
-      !this.overlays && (this.overlays = this.bpmnModeler.get('overlays'))
+      this.element = element;
+      !this.elementOverlayIds && (this.elementOverlayIds = {});
+      !this.overlays && (this.overlays = this.bpmnModeler.get("overlays"));
       // 展示信息
-      const activity = this.activityList.find(m => m.key === element.id)
+      const activity = this.activityList.find((m) => m.key === element.id);
       if (!activity) {
-        return
+        return;
       }
-      if (!this.elementOverlayIds[element.id] && element.type !== 'bpmn:Process') {
+      if (
+        !this.elementOverlayIds[element.id] &&
+        element.type !== "bpmn:Process"
+      ) {
         let html = `<div class="element-overlays">
             <p>Elemet id: ${element.id}</p>
             <p>Elemet type: ${element.type}</p>
-          </div>` // 默认值
-        if (element.type === 'bpmn:StartEvent' && this.processInstance) {
+          </div>`; // 默认值
+        if (element.type === "bpmn:StartEvent" && this.processInstance) {
           html = `<p>发起人:${this.processInstance.startUser.nickname}</p>
                   <p>部门:${this.processInstance.startUser.deptName}</p>
-                  <p>创建时间:${this.parseTime(this.processInstance.createTime)}`
-        } else if (element.type === 'bpmn:UserTask') {
+                  <p>创建时间:${this.parseTime(
+                    this.processInstance.createTime
+                  )}`;
+        } else if (element.type === "bpmn:UserTask") {
           // debugger
-          const task = this.taskList.find(m => m.id === activity.taskId) // 找到活动对应的 taskId
+          const task = this.taskList.find((m) => m.id === activity.taskId); // 找到活动对应的 taskId
           if (!task) {
-            return
+            return;
           }
           html = `<p>审批人:${task.assigneeUser.nickname}</p>
                   <p>部门:${task.assigneeUser.deptName}</p>
-                  <p>结果:${this.getDictDataLabel(this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, task.result)}</p>
-                  <p>创建时间:${this.parseTime(task.createTime)}</p>`
+                  <p>结果:${this.getDictDataLabel(
+                    this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
+                    task.status
+                  )}</p>
+                  <p>创建时间:${this.parseTime(task.createTime)}</p>`;
           if (task.endTime) {
-            html += `<p>结束时间:${this.parseTime(task.endTime)}</p>`
+            html += `<p>结束时间:${this.parseTime(task.endTime)}</p>`;
           }
           if (task.reason) {
-            html += `<p>审批建议:${task.reason}</p>`
+            html += `<p>审批建议:${task.reason}</p>`;
           }
-        } else if (element.type === 'bpmn:ServiceTask' && this.processInstance) {
+        } else if (
+          element.type === "bpmn:ServiceTask" &&
+          this.processInstance
+        ) {
           if (activity.startTime > 0) {
-            html = `<p>创建时间:${this.parseTime(activity.startTime)}</p>`
+            html = `<p>创建时间:${this.parseTime(activity.startTime)}</p>`;
           }
           if (activity.endTime > 0) {
-            html += `<p>结束时间:${this.parseTime(activity.endTime)}</p>`
+            html += `<p>结束时间:${this.parseTime(activity.endTime)}</p>`;
           }
-          console.log(html)
-        } else if (element.type === 'bpmn:EndEvent' && this.processInstance) {
-          html = `<p>结果:${this.getDictDataLabel(this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT, this.processInstance.result)}</p>`
+          console.log(html);
+        } else if (element.type === "bpmn:EndEvent" && this.processInstance) {
+          html = `<p>结果:${this.getDictDataLabel(
+            this.DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
+            this.processInstance.result
+          )}</p>`;
           if (this.processInstance.endTime) {
-            html += `<p>结束时间:${this.parseTime(this.processInstance.endTime)}</p>`
+            html += `<p>结束时间:${this.parseTime(
+              this.processInstance.endTime
+            )}</p>`;
           }
         }
         this.elementOverlayIds[element.id] = this.overlays.add(element, {
           position: { left: 0, bottom: 0 },
-          html: `<div class="element-overlays">${html}</div>`
-        })
+          html: `<div class="element-overlays">${html}</div>`,
+        });
       }
     },
     // 流程图的元素被 out
     elementOut(element) {
-      this.overlays.remove({ element })
-      this.elementOverlayIds[element.id] = null
-    }
-  }
-}
+      this.overlays.remove({ element });
+      this.elementOverlayIds[element.id] = null;
+    },
+  },
+};
 </script>
 
 <style>
-
 /** 处理中 */
 .highlight-todo.djs-connection > .djs-visual > path {
   stroke: #1890ff !important;

+ 213 - 166
src/views/rtkwms/inrequest/InRequestForm.vue

@@ -21,8 +21,16 @@
               <i class="el-icon-arrow-down el-icon--right" />
             </el-button>
             <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item :disabled="isButtonDisabled('commit')" @click.native="commit">提交</el-dropdown-item>
-              <el-dropdown-item :disabled="isButtonDisabled('cancel')" @click.native="cancel">撤销</el-dropdown-item>
+              <el-dropdown-item
+                :disabled="isButtonDisabled('commit')"
+                @click.native="commit"
+                >提交</el-dropdown-item
+              >
+              <el-dropdown-item
+                :disabled="isButtonDisabled('cancel')"
+                @click.native="cancel"
+                >撤销</el-dropdown-item
+              >
             </el-dropdown-menu>
           </el-dropdown>
 
@@ -33,8 +41,16 @@
               <i class="el-icon-arrow-down el-icon--right" />
             </el-button>
             <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item :disabled="isButtonDisabled('audit')" @click.native="audit">审核</el-dropdown-item>
-              <el-dropdown-item :disabled="isButtonDisabled('antiAudit')" @click.native="antiAudit">反审核</el-dropdown-item>
+              <el-dropdown-item
+                :disabled="isButtonDisabled('audit')"
+                @click.native="audit"
+                >审核</el-dropdown-item
+              >
+              <el-dropdown-item
+                :disabled="isButtonDisabled('antiAudit')"
+                @click.native="antiAudit"
+                >反审核</el-dropdown-item
+              >
             </el-dropdown-menu>
           </el-dropdown>
           <!-- <el-button @click="reset" plain>重置</el-button> -->
@@ -43,7 +59,8 @@
             size="mini"
             plain
             :disabled="isFormDisabled"
-            @click="add()">新增明细
+            @click="add()"
+            >新增明细
           </el-button>
           <el-button plain size="mini" @click="handleCancel">返回</el-button>
         </div>
@@ -83,7 +100,7 @@
               :disabled="true"
               placeholder="保存后自动生成"
             /> </el-form-item
-          ></el-col>
+        ></el-col>
         <el-col :span="12">
           <el-form-item label="部门" prop="deptCode">
             <DepartMentSelect
@@ -240,165 +257,187 @@
       </el-row>
     </el-form>
 
-    <el-table :data="formData.list" border size="mini">
-      <el-table-column
-        label="源单编号"
-        align="center"
-        prop="sourceRequestId"
-        width="160"
-        show-overflow-tooltip
-      />
-      <el-table-column
-        label="源单行号"
-        align="center"
-        prop="sourceLineNo"
-        width="160"
-        show-overflow-tooltip
-      />
-      <el-table-column
-        label="物料编码"
-        align="center"
-        prop="materialNo"
-        width="200"
-        show-overflow-tooltip
-      >
-        <template v-slot="scope">
-          <el-select
-            v-model="scope.row.materialNo"
-            filterable
-            remote
-            reserve-keyword
-            placeholder="请选择物料编码"
-            :remote-method="
-              (query) => remoteMaterialSearch(query, 'code', scope.$index)
-            "
-            :loading="loading"
-            @change="(value) => changeMaterial(value, scope.$index, 'code')"
+    <el-tabs v-model="activeName" @tab-click="handleClick">
+      <el-tab-pane label="明细信息" name="detail">
+        <el-table :data="formData.list" border size="mini">
+          <el-table-column
+            label="源单编号"
+            align="center"
+            prop="sourceRequestId"
+            width="160"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="源单行号"
+            align="center"
+            prop="sourceLineNo"
+            width="160"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="物料编码"
+            align="center"
+            prop="materialNo"
+            width="200"
+            show-overflow-tooltip
           >
-            <el-option
-              v-for="item in materialNoList"
-              :key="item.code"
-              :label="item.code"
-              :value="item.code"
-            />
-          </el-select>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="物料名称"
-        align="center"
-        prop="materialName"
-        width="200"
-        show-overflow-tooltip
-      >
-        <template v-slot="scope">
-          <el-select
-            v-model="scope.row.materialName"
-            filterable
-            remote
-            reserve-keyword
-            placeholder="请选择物料名称"
-            :remote-method="
-              (query) => remoteMaterialSearch(query, 'name', scope.$index)
-            "
-            :loading="loading"
-            @change="(value) => changeMaterial(value, scope.$index, 'name')"
+            <template v-slot="scope">
+              <el-select
+                v-model="scope.row.materialNo"
+                filterable
+                remote
+                reserve-keyword
+                placeholder="请选择物料编码"
+                :remote-method="
+                  (query) => remoteMaterialSearch(query, 'code', scope.$index)
+                "
+                :loading="loading"
+                @change="(value) => changeMaterial(value, scope.$index, 'code')"
+              >
+                <el-option
+                  v-for="item in materialNoList"
+                  :key="item.code"
+                  :label="item.code"
+                  :value="item.code"
+                />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="物料名称"
+            align="center"
+            prop="materialName"
+            width="200"
+            show-overflow-tooltip
           >
-            <el-option
-              v-for="item in materialNameList"
-              :key="item.code"
-              :label="item.name"
-              :value="item.name"
-            />
-          </el-select>
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="客户编码"
-        align="center"
-        prop="customerCode"
-        width="150"
-        show-overflow-tooltip
-      />
-      <el-table-column
-        label="客户名称"
-        align="center"
-        prop="customerName"
-        width="160"
-        show-overflow-tooltip
-      />
-      <el-table-column
-        label="本次申请数量"
-        align="center"
-        prop="nowDeliveredQty"
-        width="160"
-      >
-        <template slot-scope="scope">
-          <el-input
-            v-model="scope.row.nowDeliveredQty"
-            :disabled="isFormDisabled"
-            @change="deliverChange"
+            <template v-slot="scope">
+              <el-select
+                v-model="scope.row.materialName"
+                filterable
+                remote
+                reserve-keyword
+                placeholder="请选择物料名称"
+                :remote-method="
+                  (query) => remoteMaterialSearch(query, 'name', scope.$index)
+                "
+                :loading="loading"
+                @change="(value) => changeMaterial(value, scope.$index, 'name')"
+              >
+                <el-option
+                  v-for="item in materialNameList"
+                  :key="item.code"
+                  :label="item.name"
+                  :value="item.name"
+                />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="客户编码"
+            align="center"
+            prop="customerCode"
+            width="150"
+            show-overflow-tooltip
           />
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="已入库数量"
-        align="center"
-        prop="completedQty"
-        width="120"
-      />
-      <el-table-column
-        label="源单计划数量"
-        align="center"
-        prop="planQty"
-        width="120"
-      />
-      <el-table-column
-        label="单位"
-        align="center"
-        prop="unitName"
-        width="150"
-        show-overflow-tooltip
-      />
-      <el-table-column label="行备注" align="center" prop="remark" width="200">
-        <template slot-scope="scope">
-          <el-input v-model="scope.row.remark" :disabled="isFormDisabled" />
-        </template>
-      </el-table-column>
-      <el-table-column
-        label="操作"
-        align="center"
-        fixed="right"
-        width="150px"
-        class-name="small-padding fixed-width"
-      >
-        <template v-slot="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            :disabled="isFormDisabled"
-            @click="handleDelete(scope)"
-            >删除</el-button
+          <el-table-column
+            label="客户名称"
+            align="center"
+            prop="customerName"
+            width="160"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="本次申请数量"
+            align="center"
+            prop="nowDeliveredQty"
+            width="160"
           >
-        </template>
-      </el-table-column>
-    </el-table>
+            <template slot-scope="scope">
+              <el-input
+                v-model="scope.row.nowDeliveredQty"
+                :disabled="isFormDisabled"
+                @change="deliverChange"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="已入库数量"
+            align="center"
+            prop="completedQty"
+            width="120"
+          />
+          <el-table-column
+            label="源单计划数量"
+            align="center"
+            prop="planQty"
+            width="120"
+          />
+          <el-table-column
+            label="单位"
+            align="center"
+            prop="unitName"
+            width="150"
+            show-overflow-tooltip
+          />
+          <el-table-column
+            label="行备注"
+            align="center"
+            prop="remark"
+            width="200"
+          >
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.remark" :disabled="isFormDisabled" />
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="操作"
+            align="center"
+            fixed="right"
+            width="150px"
+            class-name="small-padding fixed-width"
+          >
+            <template v-slot="scope">
+              <el-button
+                size="mini"
+                type="text"
+                icon="el-icon-delete"
+                :disabled="isFormDisabled"
+                @click="handleDelete(scope)"
+                >删除</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-tab-pane>
+      <el-tab-pane label="审批任务" name="approvalTask" lazy>
+        <ApprovalTask
+          v-if="
+            activeName === 'approvalTask' &&
+            formData.bpmInstanceId !== null &&
+            formData.bpmInstanceId !== undefined
+          "
+          :id="formData.bpmInstanceId"
+        />
+        <div v-else class="isNotApproval">暂未开启工作流</div>
+      </el-tab-pane>
+    </el-tabs>
   </div>
 </template>
 
 <script>
 import * as InRequestApi from "@/api/wms/output/inrequest";
 import DepartMentSelect from "./components/DepartMentSelect.vue";
-// import ShipmentNotification from "./ShipmentNotification.vue";
+// 审批任务
+import ApprovalTask from "../../wms/quality/iqcInspection/components/ApprovalTaskNew.vue";
 export default {
   name: "InRequestForm",
   components: {
-    // ShipmentNotification,
     DepartMentSelect,
+    ApprovalTask,
   },
   data() {
     return {
+      activeName: "detail",
       materialNameList: [],
       materialNoList: [],
       sourceOrderNoList: [],
@@ -443,12 +482,11 @@ export default {
         erpErrMsg: undefined,
         erpBackId: undefined,
         list: [],
+        bpmInstanceId: undefined,
       },
       // 表单校验
       formRules: {
-        deptCode: [
-          { required: true, message: "请选择部门", trigger: "blur" },
-        ],
+        deptCode: [{ required: true, message: "请选择部门", trigger: "blur" }],
         requestNo: [
           { required: true, message: "申请单号不能为空", trigger: "blur" },
         ],
@@ -502,11 +540,15 @@ export default {
       const status = parseInt(this.formData.status || "0");
       return hasId && status >= 2;
     },
-    //计算属性判断修改状态下是否可编辑
+    // 计算属性判断修改状态下是否可编辑
     isEditable() {
       // 有 id 表示是编辑模式,不可编辑
       // 没有 id 表示是新增模式,可编辑
-      return this.formData.id === undefined || this.formData.id === null || this.formData.id === '';
+      return (
+        this.formData.id === undefined ||
+        this.formData.id === null ||
+        this.formData.id === ""
+      );
     },
   },
   watch: {
@@ -541,19 +583,24 @@ export default {
     isButtonDisabled(buttonType) {
       const status = Number(this.formData.status);
 
-      switch(buttonType) {
-        case 'commit':
-          return status !== 0;  // 提交,status=0时可点击
-        case 'cancel':
-          return status !== 1;  // 撤销,status=1时可点击
-        case 'audit':
-          return status !== 1;  // 审核,status=1时可点击
-        case 'antiAudit':
-          return status < 2;    // 反审核,status>=2时可点击
+      switch (buttonType) {
+        case "commit":
+          return status !== 0; // 提交,status=0时可点击
+        case "cancel":
+          return status !== 1; // 撤销,status=1时可点击
+        case "audit":
+          return status !== 1; // 审核,status=1时可点击
+        case "antiAudit":
+          return status < 2; // 反审核,status>=2时可点击
         default:
           return true;
       }
     },
+    // 标签页切换处理
+    handleClick(tab, event) {
+      // 可以在这里添加标签切换时的逻辑
+      console.log(tab, event);
+    },
     handleDelete(row) {
       console.log(row);
       this.formData.list.splice(row.$index, 1);
@@ -780,7 +827,7 @@ export default {
       await InRequestApi.commitInRequest(data);
       this.$modal.msgSuccess("提交成功");
       // 状态变化
-      this.$set(this.formData, 'status', "1");
+      this.$set(this.formData, "status", "1");
     },
     /** 撤销按钮 */
     async cancel() {
@@ -789,7 +836,7 @@ export default {
       await InRequestApi.cancelInRequest(data);
       this.$modal.msgSuccess("撤销成功");
       // 状态变化
-      this.$set(this.formData, 'status', "0");
+      this.$set(this.formData, "status", "0");
     },
     /** 审核按钮 */
     async audit() {
@@ -798,7 +845,7 @@ export default {
       await InRequestApi.auditInRequest(data);
       this.$modal.msgSuccess("审核成功");
       // 状态变化
-      this.$set(this.formData, 'status', "2");
+      this.$set(this.formData, "status", "2");
     },
     /** 反审核按钮 */
     async antiAudit() {
@@ -807,7 +854,7 @@ export default {
       await InRequestApi.antiAuditInRequest(data);
       this.$modal.msgSuccess("反审核成功");
       // 状态变化
-      this.$set(this.formData, 'status', "0");
+      this.$set(this.formData, "status", "0");
     },
     /** 返回按钮 */
     handleCancel() {

+ 1 - 0
src/views/system/menu/index.vue

@@ -93,6 +93,7 @@
       <el-table-column prop="path" label="路由地址" width="150" />
       <el-table-column prop="icon" label="图标" align="center" width="100">
         <template slot-scope="scope">
+          <!-- <svg-icon :icon-class="scope.row.icon || ''" /> -->
           <svg-icon :icon-class="scope.row.icon" />
         </template>
       </el-table-column>

File diff suppressed because it is too large
+ 446 - 402
src/views/wms/output/inrequest/components/InRequestForm.vue


+ 79 - 77
src/views/wms/quality/iqcInspection/components/ApprovalTaskNew.vue

@@ -2,71 +2,73 @@
   <div class="app-container">
     <el-row>
       <el-col :span="12">
-    <!-- 审批信息 -->
-    <el-card
-      v-for="(item, index) in runningTasks"
-      :key="index"
-      v-loading="processInstanceLoading"
-      class="box-card"
-    >
-      <div slot="header" class="clearfix">
-        <span class="el-icon-picture-outline">审批任务【{{ item.name }}】</span>
-      </div>
-      <el-col :span="16" :offset="6">
-        <el-form
-          :ref="'form' + index"
-          :model="auditForms[index]"
-          :rules="auditRule"
-          label-width="100px"
+        <!-- 审批信息 -->
+        <el-card
+          v-for="(item, index) in runningTasks"
+          :key="index"
+          v-loading="processInstanceLoading"
+          class="box-card"
         >
-          <el-form-item
-            v-if="processInstance && processInstance.name"
-            label="流程名"
-          >
-            {{ processInstance.name }}
-          </el-form-item>
-          <el-form-item
-            v-if="processInstance && processInstance.startUser"
-            label="流程发起人"
-          >
-            {{ processInstance.startUser.nickname }}
-            <el-tag type="info" size="mini">{{
-              processInstance.startUser.deptName
-            }}</el-tag>
-          </el-form-item>
-          <el-form-item label="审批建议" prop="reason">
-            <el-input
-              v-model="auditForms[index].reason"
-              type="textarea"
-              placeholder="请输入审批建议"
-            />
-          </el-form-item>
-        </el-form>
-        <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
-          <el-button
-            icon="el-icon-edit-outline"
-            type="success"
-            size="mini"
-            @click="handleAudit(item, 'Y')"
-            >通过</el-button
-          >
-          <el-button
-            icon="el-icon-circle-close"
-            type="danger"
-            size="mini"
-            @click="handleAudit(item, 'N')"
-            >不通过</el-button
-          >
-          <el-button
-            icon="el-icon-edit-outline"
-            type="primary"
-            size="mini"
-            @click="handleUpdateAssignee(item)"
-            >转办</el-button
-          >
-        </div>
-      </el-col>
-    </el-card>
+          <div slot="header" class="clearfix">
+            <span class="el-icon-picture-outline"
+              >审批任务【{{ item.name }}】</span
+            >
+          </div>
+          <el-col :span="16" :offset="6">
+            <el-form
+              :ref="'form' + index"
+              :model="auditForms[index]"
+              :rules="auditRule"
+              label-width="100px"
+            >
+              <el-form-item
+                v-if="processInstance && processInstance.name"
+                label="流程名"
+              >
+                {{ processInstance.name }}
+              </el-form-item>
+              <el-form-item
+                v-if="processInstance && processInstance.startUser"
+                label="流程发起人"
+              >
+                {{ processInstance.startUser.nickname }}
+                <el-tag type="info" size="mini">{{
+                  processInstance.startUser.deptName
+                }}</el-tag>
+              </el-form-item>
+              <el-form-item label="审批建议" prop="reason">
+                <el-input
+                  v-model="auditForms[index].reason"
+                  type="textarea"
+                  placeholder="请输入审批建议"
+                />
+              </el-form-item>
+            </el-form>
+            <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+              <el-button
+                icon="el-icon-edit-outline"
+                type="success"
+                size="mini"
+                @click="handleAudit(item, 'Y')"
+                >通过</el-button
+              >
+              <el-button
+                icon="el-icon-circle-close"
+                type="danger"
+                size="mini"
+                @click="handleAudit(item, 'N')"
+                >不通过</el-button
+              >
+              <el-button
+                icon="el-icon-edit-outline"
+                type="primary"
+                size="mini"
+                @click="handleUpdateAssignee(item)"
+                >转办</el-button
+              >
+            </div>
+          </el-col>
+        </el-card>
         <!-- 审批记录 -->
         <el-card v-loading="tasksLoad" class="box-card">
           <div slot="header" class="clearfix">
@@ -268,9 +270,6 @@ export default {
       categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
     };
   },
-  created() {
-    this.getUserList();
-  },
   watch: {
     id: {
       handler() {
@@ -283,6 +282,9 @@ export default {
       immediate: true,
     },
   },
+  created() {
+    this.getUserList();
+  },
   methods: {
     // 查询用户列表
     getUserList(nickname) {
@@ -369,7 +371,7 @@ export default {
           this.tasks = [];
           // 移除已取消的审批
           response.data.forEach((task) => {
-            if (task.result !== 4) {
+            if (task.status !== 4) {
               this.tasks.push(task);
             }
           });
@@ -391,7 +393,7 @@ export default {
           // 需要审核的记录
           const userId = store.getters.userId;
           this.tasks.forEach((task) => {
-            if (task.result !== 1) {
+            if (task.status !== 1) {
               // 只有待处理才需要
               return;
             }
@@ -434,31 +436,31 @@ export default {
       return getDate(ms);
     },
     getTimelineItemIcon(item) {
-      if (item.result === 1) {
+      if (item.status === 1) {
         return "el-icon-time";
       }
-      if (item.result === 2) {
+      if (item.status === 2) {
         return "el-icon-check";
       }
-      if (item.result === 3) {
+      if (item.status === 3) {
         return "el-icon-close";
       }
-      if (item.result === 4) {
+      if (item.status === 4) {
         return "el-icon-remove-outline";
       }
       return "";
     },
     getTimelineItemType(item) {
-      if (item.result === 1) {
+      if (item.status === 1) {
         return "primary";
       }
-      if (item.result === 2) {
+      if (item.status === 2) {
         return "success";
       }
-      if (item.result === 3) {
+      if (item.status === 3) {
         return "danger";
       }
-      if (item.result === 4) {
+      if (item.status === 4) {
         return "info";
       }
       return "";

Some files were not shown because too many files changed in this diff