Procházet zdrojové kódy

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-mes into dengfei

695593266@qq.com před 1 rokem
rodič
revize
6dad2c83b4

+ 361 - 0
src/api/bpm/task.js

@@ -0,0 +1,361 @@
+import request from '@/utils/request';
+import store from '@/store';
+import Vue from 'vue';
+
+export async function getTodoTaskPage(query) {
+  const res = await request({
+    url: '/bpm/task/todo-page',
+    method: 'post',
+    data: query
+  });
+  if (res.data.code == 0) {
+    store.dispatch('user/setMenuBadge', {
+      path: '/todo',
+      value: res.data.data.count || 0,
+      color: 'danger'
+    });
+    // console.log('-----getTodoTaskPage---user--------');
+    // console.log(store.state.user);
+    // if (store.state.user.menus?.length) {
+    //   for (const p of store.state.user.menus) {
+    //     console.log('getTodoTaskPage----------------------');
+    //     console.log(p);
+    //     if (p.path === '/todo') {
+    //       console.log('进来了2~~~');
+
+    //       break;
+    //     }
+    //   }
+    // } else {
+    //   const unwatch = Vue.prototype.$watch(
+    //     '$store.state.user.menus',
+    //     () => {
+    //       console.log('-----getTodoTaskPage---user--------');
+    //       console.log(store.state.user);
+    //       if (store.state.user.menus?.length) {
+    //         for (const p of store.state.user.menus) {
+    //           console.log('getTodoTaskPage----------------------');
+    //           console.log(p);
+    //           if (p.path === '/todo') {
+    //             console.log('进来了2~~~');
+    //             store.dispatch('user/setMenuBadge', {
+    //               path: '/todo',
+    //               value: res.data.data.count || 0,
+    //               color: 'danger'
+    //             });
+    //             break;
+    //           }
+    //         }
+    //         unwatch();
+    //       }
+    //     },
+    //     {
+    //       immediate: true
+    //     }
+    //   );
+    // }
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function getDoneTaskPage(query) {
+  const res = await request({
+    url: '/bpm/task/done-page',
+    method: 'post',
+    data: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export function completeTask(data) {
+  return request({
+    url: '/bpm/task/complete',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export async function approveTask(data) {
+  const res = await request({
+    url: '/bpm/task/approve',
+    method: 'PUT',
+    data: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export function rejectTask(data) {
+  return request({
+    url: '/bpm/task/reject',
+    method: 'PUT',
+    data: data
+  });
+}
+export function cancelTask(data) {
+  return request({
+    url: '/bpm/process-instance/cancel',
+    method: 'post',
+    data: data
+  });
+}
+
+export function backTask(data) {
+  return request({
+    url: '/bpm/task/back',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export function updateTaskAssignee(data) {
+  return request({
+    url: '/bpm/task/update-assignee',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export async function getTaskListByProcessInstanceId(processInstanceId) {
+  const res = await request({
+    url:
+      '/bpm/task/list-by-process-instance-id?processInstanceId=' +
+      processInstanceId,
+    method: 'get'
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export function getReturnList(taskId) {
+  return request({
+    url: '/bpm/task/return-list?taskId=' + taskId,
+    method: 'get'
+  });
+}
+
+export function returnTask(data) {
+  return request({
+    url: '/bpm/task/return',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export function delegateTask(data) {
+  return request({
+    url: '/bpm/task/delegate',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export function approveTaskWithVariables(data) {
+  return request({
+    url: '/bpm/task/approveTaskWithVariables',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export function approveTaskWithVariablesOther(data) {
+  return request({
+    url: '/bpm/inwarehouse/assign',
+    method: 'post',
+    data: data
+  });
+}
+
+export function outApproveNotPass(data) {
+  return request({
+    url: '/bpm/outApprove/notPass',
+    method: 'PUT',
+    data: data
+  });
+}
+
+export function outinApproveNotPass(data) {
+  return request({
+    url: '/bpm/outinApprove/notPass',
+    method: 'PUT',
+    data: data
+  });
+}
+
+// 我的消息分页
+export async function notifyMessagePageAPI(data) {
+  const res = await request({
+    url: `/sys/notifymessage/page`,
+    method: 'post',
+    data: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新已读-指定消息ID
+ */
+export async function updateNotifyMessageReadByIdAPI(data) {
+  const res = await request({
+    url: `/sys/notifymessage/updateNotifyMessageRead`,
+    method: 'post',
+    data: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//工作流自定义表单集合
+export async function getBpmCustomFormPage(query) {
+  const res = await request({
+    url: '/flowable/bpmcustomform/page',
+    method: 'get',
+    params: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//工作流自定义权限过滤表单集合
+export async function getBpmCustomFormList(query) {
+  const res = await request({
+    url: '/flowable/bpmcustomform/list',
+    method: 'get',
+    params: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//工作流自定义表单保存
+export async function bpmCustomFormSave(data) {
+  const res = await request({
+    url: '/flowable/bpmcustomform/save',
+    method: 'post',
+    data
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//工作流自定义表单修改
+export async function bpmCustomFormUpdate(data) {
+  const res = await request({
+    url: '/flowable/bpmcustomform/update',
+    method: 'put',
+    data
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//工作流自定义表单修改
+export async function bpmCustomFormDelete(data) {
+  const res = await request({
+    url: '/flowable/bpmcustomform/delete',
+    method: 'delete',
+    data
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+export async function getProcessInstancePage(query) {
+  const res = await request({
+    url: '/bpm/process-instance/my-page',
+    method: 'post',
+    data: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+export async function getProcessInstanceDeptPage(query) {
+  const res = await request({
+    url: '/bpm/process-instance/my-dept-page',
+    method: 'post',
+    data: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+export async function getProcessInstanceNoticePage(query) {
+  const res = await request({
+    url: '/bpm/process-instance/my-notice-page',
+    method: 'post',
+    data: query
+  });
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 我的抄送分页
+export async function ccPage(data) {
+  console.log(data);
+
+  const res = await request({
+    url: `/bpm/task/cc-page`,
+    method: 'post',
+    data
+  });
+
+  const res1 = await request({
+    url: `/bpm/task/cc-page`,
+    method: 'post',
+    data: {
+      pageNum: 1,
+      size: -1
+    }
+  });
+
+  if (res1.data.code == 0) {
+    const num = res1.data.data.list.filter(
+      (item) => item.processResult == 1
+    ).length;
+
+    store.dispatch('user/setMenuBadge', {
+      path: '/carbonCopy',
+      value: num || 0,
+      color: 'danger'
+    });
+  }
+
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 16 - 0
src/api/warehouseManagement/index.js

@@ -359,6 +359,22 @@ export default {
     }
     return Promise.reject(new Error(res.data.message));
   },
+  // 调拨出入库
+  allot: async (data) => {
+    const res = await request.post('/wms/outintwo/allot', data);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 调拨驳回
+  notAllotPass: async (data) => {
+    const res = await request.post('/bpm/outinApprove/notAllotPass', data);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
   // 调拨保存
   allotApplySave: async (data) => {
     const res = await request.post('/wms/allotApply/save', data);

+ 1 - 1
src/api/workOrderList/index.js

@@ -180,7 +180,7 @@ export async function batchRecordPage(body) {
   const res = await request.post('/mes/workorder/batchRecordPage', body);
   console.log(res);
   if (res.data.code == 0) {
-    return res.data;
+    return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
 }

+ 534 - 469
src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue

@@ -7,520 +7,585 @@
 </template>
 
 <script>
-import BpmnViewer from "bpmn-js/lib/Viewer";
-import DefaultEmptyXML from "./plugins/defaultEmpty";
-import dictMixins from '@/mixins/dictMixins';
+  import BpmnViewer from 'bpmn-js/lib/Viewer';
+  import DefaultEmptyXML from './plugins/defaultEmpty';
+  import dictMixins from '@/mixins/dictMixins';
 
-export default {
-  name: "MyProcessViewer",
-  componentName: "MyProcessViewer",
-  mixins: [dictMixins],
+  export default {
+    name: 'MyProcessViewer',
+    componentName: 'MyProcessViewer',
+    mixins: [dictMixins],
 
-  props: {
-    value: {  // BPMN XML 字符串
-      type: String,
-    },
-    prefix: { // 使用哪个引擎
-      type: String,
-      default: "camunda",
-    },
-    activityData: { // 活动的数据。传递时,可高亮流程
-      type: Array,
-      default: () => [],
-    },
-    processInstanceData: { // 流程实例的数据。传递时,可展示流程发起人等信息
-      type: Object,
+    props: {
+      value: {
+        // BPMN XML 字符串
+        type: String
+      },
+      prefix: {
+        // 使用哪个引擎
+        type: String,
+        default: 'camunda'
+      },
+      activityData: {
+        // 活动的数据。传递时,可高亮流程
+        type: Array,
+        default: () => []
+      },
+      processInstanceData: {
+        // 流程实例的数据。传递时,可展示流程发起人等信息
+        type: Object
+      },
+      taskData: {
+        // 任务实例的数据。传递时,可展示 UserTask 审核相关的信息
+        type: Array,
+        default: () => []
+      }
     },
-    taskData: { // 任务实例的数据。传递时,可展示 UserTask 审核相关的信息
-      type: Array,
-      default: () => [],
-    }
-  },
-  data() {
-    return {
-      xml: '',
-      activityList: [],
-      processInstance: undefined,
-      taskList: [],
-    };
-  },
-  created(){
-    this.requestDict('流程实例的结果');
-
-  },
-  mounted() {
-    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.initModelListeners();
-  },
-  watch: {
-    value: function (newValue) { // 在 xmlString 发生变化时,重新创建,从而绘制流程图
-      this.xml = newValue;
-      this.createNewDiagram(this.xml);
+    data() {
+      return {
+        xml: '',
+        activityList: [],
+        processInstance: undefined,
+        taskList: []
+      };
     },
-    activityData: function (newActivityData) {
-      this.activityList = newActivityData;
-      this.createNewDiagram(this.xml);
+    created() {
+      this.requestDict('流程实例的结果');
     },
-    processInstanceData: function (newProcessInstanceData) {
-      this.processInstance = newProcessInstanceData;
+    mounted() {
+      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.initModelListeners();
     },
-    taskData: function (newTaskListData) {
-      this.taskList = newTaskListData;
-      this.createNewDiagram(this.xml);
-    }
-  },
-  methods: {
-    initBpmnModeler() {
-      if (this.bpmnModeler) return;
-      this.bpmnModeler = new BpmnViewer({
-        container: this.$refs["bpmn-canvas"],
-        bpmnRenderer: {
-        }
-      })
-    },
-    /* 创建新的流程图 */
-    async createNewDiagram(xml) {
-      // 将字符串转换成图显示出来
-      let newId = `Process_${new Date().getTime()}`;
-      let newName = `业务流程_${new Date().getTime()}`;
-      let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
-      try {
-        // console.log(this.bpmnModeler.importXML);
-        let { warnings } = await this.bpmnModeler.importXML(xmlString);
-        if (warnings && warnings.length) {
-          warnings.forEach(warn => console.warn(warn));
-        }
-        // 高亮流程图
-        await this.highlightDiagram();
-        const canvas = this.bpmnModeler.get('canvas');
-        canvas.zoom("fit-viewport", "auto");
-      } catch (e) {
-        console.error(e);
-        // console.error(`[Process Designer Warn]: ${e?.message || e}`);
+    watch: {
+      value: function (newValue) {
+        // 在 xmlString 发生变化时,重新创建,从而绘制流程图
+        this.xml = newValue;
+        this.createNewDiagram(this.xml);
+      },
+      activityData: function (newActivityData) {
+        this.activityList = newActivityData;
+        this.createNewDiagram(this.xml);
+      },
+      processInstanceData: function (newProcessInstanceData) {
+        this.processInstance = newProcessInstanceData;
+        this.createNewDiagram(this.xml);
+      },
+      taskData: function (newTaskListData) {
+        this.taskList = newTaskListData;
+        this.createNewDiagram(this.xml);
       }
     },
-    /* 高亮流程图 */
-    // TODO 芋艿:如果多个 endActivity 的话,目前的逻辑可能有一定的问题。https://www.jdon.com/workflow/multi-events.html
-    async highlightDiagram() {
-      const activityList = this.activityList;
-      if (activityList.length === 0) {
-        return;
-      }
-      // 参考自 https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-ui/src/components/Process/index.vue#L222 实现
-      // 再次基础上,增加不同审批结果的颜色等等
-      let canvas = this.bpmnModeler.get('canvas');
-      let todoActivity = activityList.find(m => !m.endTime) // 找到待办的任务
-      let endActivity = activityList[activityList.length - 1] // 获得最后一个任务
-      // debugger
-      // console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements);
-      this.bpmnModeler.getDefinitions().rootElements[0].flowElements?.forEach(n => {
-        let activity = activityList.find(m => m.key === n.id) // 找到对应的活动
-        if (!activity) {
+    methods: {
+      initBpmnModeler() {
+        if (this.bpmnModeler) return;
+        this.bpmnModeler = new BpmnViewer({
+          container: this.$refs['bpmn-canvas'],
+          bpmnRenderer: {}
+        });
+      },
+      /* 创建新的流程图 */
+      async createNewDiagram(xml) {
+        // 将字符串转换成图显示出来
+        let newId = `Process_${new Date().getTime()}`;
+        let newName = `业务流程_${new Date().getTime()}`;
+        let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix);
+        try {
+          // console.log(this.bpmnModeler.importXML);
+          let { warnings } = await this.bpmnModeler.importXML(xmlString);
+          if (warnings && warnings.length) {
+            warnings.forEach((warn) => console.warn(warn));
+          }
+          // 高亮流程图
+          await this.highlightDiagram();
+          const canvas = this.bpmnModeler.get('canvas');
+          canvas.zoom('fit-viewport', 'auto');
+        } catch (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;
+        if (activityList.length === 0) {
           return;
         }
-        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.result));
+        // 参考自 https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-ui/src/components/Process/index.vue#L222 实现
+        // 再次基础上,增加不同审批结果的颜色等等
+        let canvas = this.bpmnModeler.get('canvas');
+        let todoActivity = activityList.find((m) => !m.endTime); // 找到待办的任务
+        let endActivity = activityList[activityList.length - 1]; // 获得最后一个任务
+        // debugger
+        // console.log(this.bpmnModeler.getDefinitions().rootElements[0].flowElements);
+        this.bpmnModeler
+          .getDefinitions()
+          .rootElements[0].flowElements?.forEach((n) => {
+            let 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;
+              }
+              // 高亮任务
+              canvas.addMarker(n.id, this.getResultCss(task.result));
 
-          // 如果非通过,就不走后面的线条了
-          if (task.result !== 2) {
-            return;
-          }
-          // 处理 outgoing 出线
-          const outgoing = this.getActivityOutgoing(activity);
-          outgoing?.forEach(nn => {
-            // debugger
-            let 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.result !== 2) {
+                return;
               }
-              if (!activity.endTime) {
-                canvas.addMarker(nn.id, 'highlight-todo');
-                canvas.addMarker(nn.targetRef.id, 'highlight-todo');
+              // 处理 outgoing 出线
+              const outgoing = this.getActivityOutgoing(activity);
+              outgoing?.forEach((nn) => {
+                // debugger
+                let 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');
+                  }
+                }
+              });
+            } else if (n.$type === 'bpmn:ExclusiveGateway') {
+              // 排它网关
+              // 设置【bpmn:ExclusiveGateway】排它网关的高亮
+              canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
+              // 查找需要高亮的连线
+              let matchNN = undefined;
+              let matchActivity = undefined;
+              n.outgoing?.forEach((nn) => {
+                let 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: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】连线
+                // 获得连线是否有指向目标。如果有,则进行高亮
+                let 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;
+              }
+              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));
+                });
               }
             }
           });
-        } else if (n.$type === 'bpmn:ExclusiveGateway') { // 排它网关
-          // 设置【bpmn:ExclusiveGateway】排它网关的高亮
-          canvas.addMarker(n.id, this.getActivityHighlightCss(activity));
-          // 查找需要高亮的连线
-          let matchNN = undefined;
-          let matchActivity = undefined;
-          n.outgoing?.forEach(nn => {
-            let 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: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】连线
-            // 获得连线是否有指向目标。如果有,则进行高亮
-            let 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) {
+      },
+      getActivityHighlightCss(activity) {
+        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';
+        } else if (result === 5) {
+          // 已退回
+          return 'highlight-back';
+        } else if (result === 6) {
+          // 已委派
+          return 'highlight-todo';
+        }
+        return '';
+      },
+      getActivityOutgoing(activity) {
+        // 如果有 outgoing,则直接使用它
+        if (activity.outgoing && activity.outgoing.length > 0) {
+          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;
           }
-          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))
-            })
+          if (item.sourceRef.id === activity.key) {
+            outgoing.push(item);
           }
-        }
-      })
-    },
-    getActivityHighlightCss(activity) {
-      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';
-      } else if (result === 5) { // 已退回
-        return 'highlight-back';
-      } else if (result === 6) { // 已委派
-        return 'highlight-todo';
-      }
-      return '';
-    },
-    getActivityOutgoing(activity) {
-      // 如果有 outgoing,则直接使用它
-      if (activity.outgoing && activity.outgoing.length > 0) {
-        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 outgoing;
+      },
+      initModelListeners() {
+        const EventBus = this.bpmnModeler.get('eventBus');
+        const that = this;
+        // 注册需要的监听事件
+        EventBus.on('element.hover', function (eventObj) {
+          let element = eventObj ? eventObj.element : null;
+          that.elementHover(element);
+        });
+        EventBus.on('element.out', function (eventObj) {
+          let 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'));
+        // 展示信息
+        const activity = this.activityList.find((m) => m.key === element.id);
+        if (!activity) {
           return;
         }
-        if (item.sourceRef.id === activity.key) {
-          outgoing.push(item);
-        }
-      });
-      return outgoing;
-    },
-    initModelListeners() {
-      const EventBus = this.bpmnModeler.get("eventBus");
-      const that = this;
-      // 注册需要的监听事件
-      EventBus.on('element.hover', function(eventObj) {
-        let element = eventObj ? eventObj.element : null;
-        that.elementHover(element);
-      });
-      EventBus.on('element.out', function(eventObj) {
-        let 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"));
-      // 展示信息
-      const activity = this.activityList.find(m => m.key === element.id);
-      if (!activity) {
-        return;
-      }
-      if (!this.elementOverlayIds[element.id] && element.type !== "bpmn:Process") {
-        let html = `<div class="element-overlays">
+        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) {
-          html = `<p>发起人:${this.processInstance.startUser.nickname}</p>
+          if (element.type === 'bpmn:StartEvent' && this.processInstance) {
+            html = `<p>发起人:${this.processInstance.startUser.nickname}</p>
                   <p>部门:${this.processInstance.startUser.deptName}</p>
                   <p>创建时间:${this.processInstance.createTime}`;
-        } else if (element.type === 'bpmn:UserTask') {
-          // debugger
-          let task = this.taskList.find(m => m.id === activity.taskId); // 找到活动对应的 taskId
-          if (!task) {
-            return;
-          }
-          html = `<p>审批人:${task.assigneeUser.nickname}</p>
+          } else if (element.type === 'bpmn:UserTask') {
+            // debugger
+            let task = this.taskList.find((m) => m.id === activity.taskId); // 找到活动对应的 taskId
+            if (!task) {
+              return;
+            }
+            html = `<p>审批人:${task.assigneeUser.nickname}</p>
                   <p>部门:${task.assigneeUser.deptName}</p>
-                  <p>结果:${this.getDictValue('流程实例的结果', task.result)}</p>
+                  <p>结果:${this.getDictValue(
+                    '流程实例的结果',
+                    task.result
+                  )}</p>
                   <p>创建时间:${task.createTime}</p>`;
-          if (task.endTime) {
-            html += `<p>结束时间:${task.endTime}</p>`
-          }
-          if (task.reason) {
-            html += `<p>审批建议:${task.reason}</p>`
-          }
-        } else if (element.type === 'bpmn:ServiceTask' && this.processInstance) {
-          if(activity.startTime>0){
-            html = `<p>创建时间:${activity.startTime}</p>`;
-          }
-          if(activity.endTime>0){
-            html += `<p>结束时间:${activity.endTime}</p>`
-          }
-          console.log(html)
-        } else if (element.type === 'bpmn:EndEvent' && this.processInstance) {
-          html = `<p>结果:${this.getDictValue('流程实例的结果', this.processInstance.result)}</p>`;
-          if (this.processInstance.endTime) {
-            html += `<p>结束时间:${this.processInstance.endTime}</p>`
+            if (task.endTime) {
+              html += `<p>结束时间:${task.endTime}</p>`;
+            }
+            if (task.reason) {
+              html += `<p>审批建议:${task.reason}</p>`;
+            }
+          } else if (
+            element.type === 'bpmn:ServiceTask' &&
+            this.processInstance
+          ) {
+            if (activity.startTime > 0) {
+              html = `<p>创建时间:${activity.startTime}</p>`;
+            }
+            if (activity.endTime > 0) {
+              html += `<p>结束时间:${activity.endTime}</p>`;
+            }
+            console.log(html);
+          } else if (element.type === 'bpmn:EndEvent' && this.processInstance) {
+            html = `<p>结果:${this.getDictValue(
+              '流程实例的结果',
+              this.processInstance.result
+            )}</p>`;
+            if (this.processInstance.endTime) {
+              html += `<p>结束时间:${this.processInstance.endTime}</p>`;
+            }
           }
+          this.elementOverlayIds[element.id] = this.overlays.add(element, {
+            position: { left: 0, bottom: 0 },
+            html: `<div class="element-overlays">${html}</div>`
+          });
         }
-        this.elementOverlayIds[element.id] = this.overlays.add(element, {
-          position: { left: 0, bottom: 0 },
-          html: `<div class="element-overlays">${html}</div>`
-        });
+      },
+      // 流程图的元素被 out
+      elementOut(element) {
+        this.overlays.remove({ element });
+        this.elementOverlayIds[element.id] = null;
       }
-    },
-    // 流程图的元素被 out
-    elementOut(element) {
-      this.overlays.remove({ element });
-      this.elementOverlayIds[element.id] = null;
-    },
-  }
-};
+    }
+  };
 </script>
 
 <style>
-.bjs-powered-by{
-  display: none;
-}
-/** 处理中 */
-.highlight-todo.djs-connection > .djs-visual > path {
-  stroke: #1890ff !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
-.highlight-todo.djs-shape .djs-visual > :nth-child(1) {
-  fill: #1890ff !important;
-  stroke: #1890ff !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
+  .bjs-powered-by {
+    display: none;
+  }
+  /** 处理中 */
+  .highlight-todo.djs-connection > .djs-visual > path {
+    stroke: #1890ff !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
+  .highlight-todo.djs-shape .djs-visual > :nth-child(1) {
+    fill: #1890ff !important;
+    stroke: #1890ff !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
 
-:deep(.highlight-todo.djs-connection > .djs-visual > path) {
-  stroke: #1890ff !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-  marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
-}
-:deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
-  fill: #1890ff !important;
-  stroke: #1890ff !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
+  :deep(.highlight-todo.djs-connection > .djs-visual > path) {
+    stroke: #1890ff !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+    marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
+  }
+  :deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
+    fill: #1890ff !important;
+    stroke: #1890ff !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
 
-/** 通过 */
-.highlight.djs-shape .djs-visual > :nth-child(1) {
-  fill: green !important;
-  stroke: green !important;
-  fill-opacity: 0.2 !important;
-}
-.highlight.djs-shape .djs-visual > :nth-child(2) {
-  fill: green !important;
-}
-.highlight.djs-shape .djs-visual > path {
-  fill: green !important;
-  fill-opacity: 0.2 !important;
-  stroke: green !important;
-}
-.highlight.djs-connection > .djs-visual > path {
-  stroke: green !important;
-}
+  /** 通过 */
+  .highlight.djs-shape .djs-visual > :nth-child(1) {
+    fill: green !important;
+    stroke: green !important;
+    fill-opacity: 0.2 !important;
+  }
+  .highlight.djs-shape .djs-visual > :nth-child(2) {
+    fill: green !important;
+  }
+  .highlight.djs-shape .djs-visual > path {
+    fill: green !important;
+    fill-opacity: 0.2 !important;
+    stroke: green !important;
+  }
+  .highlight.djs-connection > .djs-visual > path {
+    stroke: green !important;
+  }
 
-.highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
-  fill: green !important; /* color elements as green */
-}
+  .highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
+    fill: green !important; /* color elements as green */
+  }
 
-:deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
-  fill: green !important;
-  stroke: green !important;
-  fill-opacity: 0.2 !important;
-}
-:deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
-  fill: green !important;
-}
-:deep(.highlight.djs-shape .djs-visual > path) {
-  fill: green !important;
-  fill-opacity: 0.2 !important;
-  stroke: green !important;
-}
-:deep(.highlight.djs-connection > .djs-visual > path) {
-  stroke: green !important;
-}
+  :deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
+    fill: green !important;
+    stroke: green !important;
+    fill-opacity: 0.2 !important;
+  }
+  :deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
+    fill: green !important;
+  }
+  :deep(.highlight.djs-shape .djs-visual > path) {
+    fill: green !important;
+    fill-opacity: 0.2 !important;
+    stroke: green !important;
+  }
+  :deep(.highlight.djs-connection > .djs-visual > path) {
+    stroke: green !important;
+  }
 
-/** 不通过 */
-.highlight-reject.djs-shape .djs-visual > :nth-child(1) {
-  fill: red !important;
-  stroke: red !important;
-  fill-opacity: 0.2 !important;
-}
-.highlight-reject.djs-shape .djs-visual > :nth-child(2) {
-  fill: red !important;
-}
-.highlight-reject.djs-shape .djs-visual > path {
-  fill: red !important;
-  fill-opacity: 0.2 !important;
-  stroke: red !important;
-}
-.highlight-reject.djs-connection > .djs-visual > path {
-  stroke: red !important;
-}
+  /** 不通过 */
+  .highlight-reject.djs-shape .djs-visual > :nth-child(1) {
+    fill: red !important;
+    stroke: red !important;
+    fill-opacity: 0.2 !important;
+  }
+  .highlight-reject.djs-shape .djs-visual > :nth-child(2) {
+    fill: red !important;
+  }
+  .highlight-reject.djs-shape .djs-visual > path {
+    fill: red !important;
+    fill-opacity: 0.2 !important;
+    stroke: red !important;
+  }
+  .highlight-reject.djs-connection > .djs-visual > path {
+    stroke: red !important;
+  }
 
-.highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {
-  fill: red !important; /* color elements as green */
-}
+  .highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {
+    fill: red !important; /* color elements as green */
+  }
 
-:deep(.highlight-reject.djs-shape .djs-visual > :nth-child(1)) {
-  fill: red !important;
-  stroke: red !important;
-  fill-opacity: 0.2 !important;
-}
-:deep(.highlight-reject.djs-shape .djs-visual > :nth-child(2)) {
-  fill: red !important;
-}
-:deep(.highlight-reject.djs-shape .djs-visual > path) {
-  fill: red !important;
-  fill-opacity: 0.2 !important;
-  stroke: red !important;
-}
-:deep(.highlight-reject.djs-connection > .djs-visual > path) {
-  stroke: red !important;
-}
+  :deep(.highlight-reject.djs-shape .djs-visual > :nth-child(1)) {
+    fill: red !important;
+    stroke: red !important;
+    fill-opacity: 0.2 !important;
+  }
+  :deep(.highlight-reject.djs-shape .djs-visual > :nth-child(2)) {
+    fill: red !important;
+  }
+  :deep(.highlight-reject.djs-shape .djs-visual > path) {
+    fill: red !important;
+    fill-opacity: 0.2 !important;
+    stroke: red !important;
+  }
+  :deep(.highlight-reject.djs-connection > .djs-visual > path) {
+    stroke: red !important;
+  }
 
-/** 已取消 */
-.highlight-cancel.djs-shape .djs-visual > :nth-child(1) {
-  fill: grey !important;
-  stroke: grey !important;
-  fill-opacity: 0.2 !important;
-}
-.highlight-cancel.djs-shape .djs-visual > :nth-child(2) {
-  fill: grey !important;
-}
-.highlight-cancel.djs-shape .djs-visual > path {
-  fill: grey !important;
-  fill-opacity: 0.2 !important;
-  stroke: grey !important;
-}
-.highlight-cancel.djs-connection > .djs-visual > path {
-  stroke: grey !important;
-}
+  /** 已取消 */
+  .highlight-cancel.djs-shape .djs-visual > :nth-child(1) {
+    fill: grey !important;
+    stroke: grey !important;
+    fill-opacity: 0.2 !important;
+  }
+  .highlight-cancel.djs-shape .djs-visual > :nth-child(2) {
+    fill: grey !important;
+  }
+  .highlight-cancel.djs-shape .djs-visual > path {
+    fill: grey !important;
+    fill-opacity: 0.2 !important;
+    stroke: grey !important;
+  }
+  .highlight-cancel.djs-connection > .djs-visual > path {
+    stroke: grey !important;
+  }
 
-.highlight-cancel:not(.djs-connection) .djs-visual > :nth-child(1) {
-  fill: grey !important; /* color elements as green */
-}
+  .highlight-cancel:not(.djs-connection) .djs-visual > :nth-child(1) {
+    fill: grey !important; /* color elements as green */
+  }
 
-:deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(1)) {
-  fill: grey !important;
-  stroke: grey !important;
-  fill-opacity: 0.2 !important;
-}
-:deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(2)) {
-  fill: grey !important;
-}
-:deep(.highlight-cancel.djs-shape .djs-visual > path) {
-  fill: grey !important;
-  fill-opacity: 0.2 !important;
-  stroke: grey !important;
-}
-:deep(.highlight-cancel.djs-connection > .djs-visual > path) {
-  stroke: grey !important;
-}
-/**驳回 */
-.highlight-back.djs-connection > .djs-visual > path {
-  stroke: #FFBA00 !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
+  :deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(1)) {
+    fill: grey !important;
+    stroke: grey !important;
+    fill-opacity: 0.2 !important;
+  }
+  :deep(.highlight-cancel.djs-shape .djs-visual > :nth-child(2)) {
+    fill: grey !important;
+  }
+  :deep(.highlight-cancel.djs-shape .djs-visual > path) {
+    fill: grey !important;
+    fill-opacity: 0.2 !important;
+    stroke: grey !important;
+  }
+  :deep(.highlight-cancel.djs-connection > .djs-visual > path) {
+    stroke: grey !important;
+  }
+  /**驳回 */
+  .highlight-back.djs-connection > .djs-visual > path {
+    stroke: #ffba00 !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
 
-.highlight-back.djs-shape .djs-visual > :nth-child(1) {
-  fill: #FFBA00 !important;
-  stroke: #FFBA00 !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
+  .highlight-back.djs-shape .djs-visual > :nth-child(1) {
+    fill: #ffba00 !important;
+    stroke: #ffba00 !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
 
-:deep(.highlight-back.djs-connection > .djs-visual > path) {
-  stroke: #FFBA00 !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-  marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
-}
+  :deep(.highlight-back.djs-connection > .djs-visual > path) {
+    stroke: #ffba00 !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+    marker-end: url(#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr);
+  }
 
-:deep(.highlight-back.djs-shape .djs-visual > :nth-child(1)) {
-  fill: #FFBA00 !important;
-  stroke: #FFBA00 !important;
-  stroke-dasharray: 4px !important;
-  fill-opacity: 0.2 !important;
-}
-.element-overlays {
-  box-sizing: border-box;
-  padding: 8px;
-  background: rgba(0, 0, 0, 0.6);
-  border-radius: 4px;
-  color: #fafafa;
-  width: 200px;
-}
+  :deep(.highlight-back.djs-shape .djs-visual > :nth-child(1)) {
+    fill: #ffba00 !important;
+    stroke: #ffba00 !important;
+    stroke-dasharray: 4px !important;
+    fill-opacity: 0.2 !important;
+  }
+  .element-overlays {
+    box-sizing: border-box;
+    padding: 8px;
+    background: rgba(0, 0, 0, 0.6);
+    border-radius: 4px;
+    color: #fafafa;
+    width: 200px;
+  }
 </style>

+ 1 - 1
src/components/processSubmitDialog/api.js

@@ -89,4 +89,4 @@ export async function getProduceTreeByCode(code) {
     return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
-}
+}

+ 2 - 2
src/components/selectReleaseRules/search.vue

@@ -31,10 +31,10 @@
             placeholder: '规则名称'
           },
           {
-            label: '记录表分类:',
+            label: '记录规则分类:',
             value: 'classify',
             type: 'select',
-            placeholder: '记录表分类',
+            placeholder: '记录规则分类',
             planList: this.typeList
           }
           //,

+ 2 - 1
src/enum/dict.js

@@ -38,7 +38,8 @@ export default {
   记录规则频率: 'record_rules_frequency',
   规则类型: 'rule_type',
   规则状态: 'rule_status',
-  规则周期: 'rule_cycle'
+  规则周期: 'rule_cycle',
+  流程实例的结果: 'bpm_process_instance_result'
 };
 export const numberList = ['date_method'];
 

+ 268 - 0
src/views/batchRecord/components/bpmList.vue

@@ -0,0 +1,268 @@
+<template>
+  <el-col :span="12">
+    <!-- 审批记录 -->
+    <el-card class="box-card" v-loading="tasksLoad">
+      <div slot="header" class="clearfix">
+        <span class="el-icon-picture-outline">审批记录</span>
+      </div>
+      <div class="block details-bpm-list">
+        <el-timeline>
+          <el-timeline-item
+            v-for="(item, index) in tasks"
+            :key="index"
+            :icon="getTimelineItemIcon(item)"
+            :type="getTimelineItemType(item)"
+          >
+            <p style="font-weight: 700">任务:{{ item.name }}</p>
+            <el-card :body-style="{ padding: '10px' }">
+              <label
+                v-if="item.assigneeUser"
+                style="font-weight: normal; margin-right: 30px"
+              >
+                审批人:{{ item.assigneeUser.nickname }}
+                <el-tag type="info" size="mini">{{
+                  item.assigneeUser.deptName
+                }}</el-tag>
+              </label>
+              <label style="font-weight: normal" v-if="item.createTime"
+                >创建时间:</label
+              >
+              <label style="color: #8a909c; font-weight: normal">{{
+                item.createTime
+              }}</label>
+              <label
+                v-if="item.endTime"
+                style="margin-left: 30px; font-weight: normal"
+                >审批时间:</label
+              >
+              <label
+                v-if="item.endTime"
+                style="color: #8a909c; font-weight: normal"
+              >
+                {{ item.endTime }}</label
+              >
+              <label
+                v-if="item.durationInMillis"
+                style="margin-left: 30px; font-weight: normal"
+                >耗时:</label
+              >
+              <label
+                v-if="item.durationInMillis"
+                style="color: #8a909c; font-weight: normal"
+              >
+                {{ getDateStar(item.durationInMillis) }}
+              </label>
+              <p v-if="item.reason">
+                <el-tag :type="getTimelineItemType(item)">{{
+                  item.reason
+                }}</el-tag>
+              </p>
+            </el-card>
+          </el-timeline-item>
+        </el-timeline>
+      </div>
+    </el-card>
+  </el-col>
+</template>
+
+<script>
+  import {
+    getProcessDefinitionBpmnXML,
+    getProcessInstance,
+    getActivityList,
+    getTaskListByProcessInstanceId
+  } from '@/api/produce/bom.js';
+  import store from '@/store';
+  // import { getProcessInstance } from '@/api/bpm/processInstance';
+  import { getDate } from '@/utils/dateUtils';
+  import dictMixins from '@/mixins/dictMixins';
+  // import { getTaskListByProcessInstanceId } from '@/api/bpm/task';
+  // import { getActivityList } from '@/api/bpm/activity';
+  // import Vue from 'vue';
+
+  // 流程实例的详情页,可用于审批
+  export default {
+    name: 'bpmList',
+    mixins: [dictMixins],
+    emits: ['setCurrenNode'],
+    components: {},
+    props: {
+      // 流程id
+      id: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        // 遮罩层
+        processInstanceLoading: true,
+        dialogVisible: false,
+
+        processInstance: {},
+
+        // BPMN 数据
+        bpmnXML: null,
+        bpmnControlForm: {
+          prefix: 'flowable'
+        },
+        activityList: [],
+
+        // 审批记录
+        tasksLoad: true,
+        tasks: []
+      };
+    },
+    created() {
+      // this.id = this.$route.query.id;
+      // if (!this.id) {
+      //   this.$message.error('未传递 id 参数,无法查看流程信息');
+      //   return;
+      // }
+      this.getDetail();
+    },
+    methods: {
+      /** 获得流程实例 */
+      getDetail() {
+        // 获得流程实例相关
+        this.processInstanceLoading = true;
+        getProcessInstance(this.id).then((response) => {
+          if (!response) {
+            this.$message.error('查询不到流程信息!');
+            return;
+          }
+          // 设置流程信息
+          this.processInstance = response;
+
+          // //将业务表单,注册为动态组件
+          // const path = this.processInstance.processDefinition.formCustomViewPath;
+          // Vue.component("async-biz-form-component", function (resolve) {
+          //   require([`@/views${path}`], resolve);
+          // });
+          // 加载流程图
+          getProcessDefinitionBpmnXML(
+            this.processInstance.processDefinition.id
+          ).then((response) => {
+            this.bpmnXML = response;
+          });
+          // 加载活动列表
+          getActivityList({
+            processInstanceId: this.processInstance.id
+          }).then((response) => {
+            console.log(response, 'response');
+            this.activityList = response;
+          });
+
+          // 取消加载中
+          this.processInstanceLoading = false;
+        });
+
+        // 获得流程任务列表(审批记录)
+        this.tasksLoad = true;
+        getTaskListByProcessInstanceId(this.id).then((response) => {
+          // 审批记录
+          this.tasks = [];
+          // 移除已取消的审批
+          response.forEach((task) => {
+            if (task.result !== 4) {
+              this.tasks.push(task);
+            }
+          });
+          // 排序,将未完成的排在前面,已完成的排在后面;
+          this.tasks.sort((a, b) => {
+            // 有已完成的情况,按照完成时间倒序
+            if (a.endTime && b.endTime) {
+              return b.endTime - a.endTime;
+            } else if (a.endTime) {
+              return 1;
+            } else if (b.endTime) {
+              return -1;
+              // 都是未完成,按照创建时间倒序
+            } else {
+              return b.createTime - a.createTime;
+            }
+          });
+
+          // 需要审核的记录
+          const userId = store.getters.userId;
+          this.tasks.forEach((task) => {
+            if (task.result !== 1 && task.result !== 6) {
+              // 只有待处理才需要
+              return;
+            }
+            if (!task.assigneeUser || task.assigneeUser.id !== userId) {
+              // 自己不是处理人
+              return;
+            }
+          });
+
+          const currenItem = this.tasks.find((i) => i.result == 1);
+          if (currenItem) {
+            // 当前处理中的节点
+            this.$emit('setCurrenNode', currenItem);
+          }
+
+          // 取消加载中
+          this.tasksLoad = false;
+        });
+      },
+      getDateStar(ms) {
+        return getDate(ms);
+      },
+      getTimelineItemIcon(item) {
+        if (item.result === 1) {
+          return 'el-icon-time';
+        }
+        if (item.result === 2) {
+          return 'el-icon-check';
+        }
+        if (item.result === 3) {
+          return 'el-icon-close';
+        }
+        if (item.result === 4) {
+          return 'el-icon-remove-outline';
+        }
+        if (item.result === 5) {
+          return 'el-icon-back';
+        }
+        return '';
+      },
+      getTimelineItemType(item) {
+        if (item.result === 1) {
+          return 'primary';
+        }
+        if (item.result === 2) {
+          return 'success';
+        }
+        if (item.result === 3) {
+          return 'danger';
+        }
+        if (item.result === 4) {
+          return 'info';
+        }
+        if (item.result === 5) {
+          return 'warning';
+        }
+        if (item.result === 6) {
+          return 'default';
+        }
+        return '';
+      }
+    }
+  };
+</script>
+
+<style lang="scss">
+  .my-process-designer {
+    height: calc(100vh - 200px);
+  }
+
+  .box-card {
+    width: 100%;
+    margin-bottom: 20px;
+  }
+
+  .details-bpm-list {
+    max-height: 120px;
+    overflow-y: auto;
+  }
+</style>

+ 141 - 0
src/views/batchRecord/components/bpmSubmit.vue

@@ -0,0 +1,141 @@
+<template>
+  <el-col :span="12">
+    <el-card v-loading="!taskDefinitionKey" class="box-card">
+      <div slot="header" class="clearfix">
+        <span class="el-icon-picture-outline">审批任务</span>
+      </div>
+      <el-form label-width="100px" ref="formRef" :model="form">
+        <el-form-item
+          label="审批建议"
+          style="margin-bottom: 20px"
+          :rules="{
+            required: true,
+            message: '请选择',
+            trigger: 'change'
+          }"
+        >
+          <el-input
+            type="textarea"
+            v-model="form.reason"
+            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(1)"
+          >通过
+        </el-button>
+
+        <el-button
+          icon="el-icon-circle-close"
+          type="danger"
+          size="mini"
+          @click="handleAudit(0)"
+          >驳回
+        </el-button>
+      </div>
+    </el-card>
+  </el-col>
+</template>
+<script>
+  import { approveTaskWithVariables } from '@/api/bpm/task';
+  import storageApi from '@/api/warehouseManagement';
+  export default {
+    data() {
+      return {
+        form: {}
+      };
+    },
+    props: {
+      businessId: {
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      taskDefinitionKey: {
+        default: ''
+      }
+    },
+    methods: {
+      handleAudit(status) {
+        if (!this.form.reason && status == 1) {
+          this.$message.warning(`请填写审批意见!`);
+          return;
+        }
+
+        this._approveTaskWithVariables(status);
+      },
+      async _approveTaskWithVariables(status) {
+        console.log(status);
+        if (status == 1) {
+          if (this.taskDefinitionKey === 'storage') {
+            const res = await storageApi.allot({ applyId: this.businessId });
+            if (res.data.code != '-1') {
+              const params = {
+                id: this.taskId,
+                reason: this.form.reason,
+                variables: { pass: true }
+              };
+              const data = await approveTaskWithVariables(params);
+              if (data.data.code != '-1') {
+                this.$emit('handleAudit', {
+                  status,
+                  title: '通过'
+                });
+              }
+            }
+          } else {
+            const params = {
+              id: this.taskId,
+              reason: this.form.reason,
+              variables: { pass: true }
+            };
+            const data = await approveTaskWithVariables(params);
+            if (data.data.code != '-1') {
+              this.$emit('handleAudit', {
+                status,
+                title: '通过'
+              });
+            }
+          }
+        } else {
+          if (this.taskDefinitionKey === 'outbound') {
+            const data = await storageApi.notAllotPass({
+              id: this.businessId,
+              reason: this.form.reason,
+              taskId: this.taskId
+            });
+            if (data.data.code != '-1') {
+              this.$emit('handleAudit', {
+                status,
+                title: '驳回'
+              });
+            }
+          } else {
+            const params = {
+              id: this.taskId,
+              reason: this.form.reason,
+              variables: { pass: false }
+            };
+            const data = await approveTaskWithVariables(params);
+            if (data.data.code != '-1') {
+              this.$emit('handleAudit', {
+                status,
+                title: '驳回'
+              });
+            }
+          }
+        }
+      }
+    }
+  };
+</script>

+ 138 - 77
src/views/batchRecord/components/detialsModal.vue

@@ -10,7 +10,12 @@
   >
     <div
       class="switch"
-      v-if="type == 'detail' && details && details.executeMethod == 2"
+      v-if="
+        details &&
+        details.executeMethod == 2 &&
+        details.approvalStatus != null &&
+        details.approvalStatus != 0
+      "
       :maxable="true"
       style="margin-bottom: 20px"
     >
@@ -28,7 +33,7 @@
       </div>
     </div>
     <el-form
-      v-if="details"
+      v-if="details && activeComp == 'main'"
       ref="formRef"
       :model="form"
       :rules="rules"
@@ -44,10 +49,11 @@
         </el-col>
         <el-col :span="8">
           <el-form-item label="工序名称">
-            <el-input :value="details.taskTypeName" disabled></el-input>
+            <el-input :value="details.produceTaskName" disabled></el-input>
           </el-form-item>
         </el-col>
-        <el-col :span="8"> </el-col>
+      </el-row>
+      <el-row style="margin-bottom: 20px">
         <el-col :span="8">
           <el-form-item label="产品编码">
             <el-input :value="details.productCode" disabled></el-input>
@@ -65,6 +71,8 @@
               disabled
             ></el-input> </el-form-item
         ></el-col>
+      </el-row>
+      <el-row style="margin-bottom: 20px">
         <el-col :span="8">
           <el-form-item label="规格">
             <el-input :value="details.specification" disabled></el-input>
@@ -83,72 +91,79 @@
       </el-row>
       <header-title title="基本信息"></header-title>
       <!-- 记录规则 -->
-      <el-row v-if="details.executeMethod == 2" style="margin-bottom: 20px">
-        <el-col :span="8">
-          <el-form-item label="记录规则名称">
-            <el-input :value="details.productModel" disabled></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="记录规则分类">
-            <DictSelection
-              dictName="记录规则类型"
-              clearable
-              v-model="details.recordRulesClassify"
-              disabled
-            >
-            </DictSelection>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="车间区域">
-            <el-input
-              :value="details.workshopArea"
-              disabled
-            ></el-input> </el-form-item
-        ></el-col>
-        <el-col :span="8">
-          <el-form-item label="检查完成时间">
-            <el-input
-              :value="details.checkFinishTime"
-              disabled
-            ></el-input> </el-form-item
-        ></el-col>
-        <el-col :span="8">
-          <el-form-item label="检查有效期">
-            <el-input
-              placeholder="请输入"
-              v-model="details.checkValidity"
-              type="text"
-              disabled
-            >
-              <template slot="append">
-                <div style="width: 40px; box-sizing: border-box">
-                  <el-form-item required>
-                    <DictSelection
-                      dictName="检查有效期单位"
-                      clearable
-                      v-model="details.checkValidityUnit"
-                      placeholder="单位"
-                      style="width: auto; box-sizing: border-box; height: 36px"
-                      disabled
-                    >
-                    </DictSelection>
-                  </el-form-item>
-                </div>
-              </template>
-            </el-input> </el-form-item
-        ></el-col>
-        <el-col :span="8">
-          <el-form-item label="结论">
-            <el-radio-group v-model="details.conclution" disabled>
-              <el-radio :label="1">合格</el-radio>
-              <el-radio :label="2">不合格</el-radio>
-            </el-radio-group>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8"> </el-col>
-      </el-row>
+      <template v-if="details.executeMethod == 2">
+        <el-row style="margin-bottom: 20px">
+          <el-col :span="8">
+            <el-form-item label="记录规则名称">
+              <el-input :value="details.ruleName" disabled></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="记录规则分类">
+              <DictSelection
+                dictName="记录规则类型"
+                clearable
+                v-model="details.recordRulesClassify"
+                disabled
+              >
+              </DictSelection>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="车间区域">
+              <el-input
+                :value="details.workshopArea"
+                disabled
+              ></el-input> </el-form-item
+          ></el-col>
+        </el-row>
+        <el-row style="margin-bottom: 20px">
+          <el-col :span="8">
+            <el-form-item label="检查完成时间">
+              <el-input
+                :value="details.checkFinishTime"
+                disabled
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :span="8">
+            <el-form-item label="检查有效期">
+              <el-input
+                placeholder="请输入"
+                v-model="details.checkValidity"
+                type="text"
+                disabled
+              >
+                <template slot="append">
+                  <div style="width: 40px; box-sizing: border-box">
+                    <el-form-item required>
+                      <DictSelection
+                        dictName="检查有效期单位"
+                        clearable
+                        v-model="details.checkValidityUnit"
+                        placeholder="单位"
+                        style="
+                          width: auto;
+                          box-sizing: border-box;
+                          height: 36px;
+                        "
+                        disabled
+                      >
+                      </DictSelection>
+                    </el-form-item>
+                  </div>
+                </template>
+              </el-input> </el-form-item
+          ></el-col>
+          <el-col :span="8">
+            <el-form-item label="结论">
+              <el-radio-group v-model="details.conclution" disabled>
+                <el-radio :label="1">合格</el-radio>
+                <el-radio :label="2">不合格</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </template>
 
       <header-title
         v-if="details.executeMethod == 2"
@@ -472,9 +487,41 @@
             </div>
           </el-tab-pane>
         </el-tabs>
+
+        <!--  -->
       </div>
     </el-form>
 
+    <bpmDetail
+      v-if="activeComp == 'bpm' && details && details.processInstanceId"
+      :id="details.processInstanceId"
+    >
+    </bpmDetail>
+
+    <!-- 底部审批 -->
+    <el-row
+      v-if="
+        details &&
+        visible &&
+        details.processInstanceId &&
+        details.approvalStatus == 0
+      "
+      :gutter="20"
+      style="margin-top: 40px"
+    >
+      <bpmSubmit
+        :id="details.processInstanceId"
+        :taskId="currenNode ? currenNode.id : ''"
+        :businessId="details.id"
+        :taskDefinitionKey="currenNode ? currenNode.taskDefinitionKey : ''"
+        @handleAudit="handleAudit"
+      ></bpmSubmit>
+      <bpmList
+        :id="details.processInstanceId"
+        @setCurrenNode="setCurrenNode"
+      ></bpmList>
+    </el-row>
+
     <template v-slot:footer>
       <el-button @click="handleClose">返回</el-button>
     </template>
@@ -486,15 +533,20 @@
   import { getById } from '@/api/producetaskrecordrulesrecord/index.js';
   import { getById as maintenanceGetById } from '@/api/maintenance/patrol_maintenance.js';
   import { getUserPage } from '@/api/system/organization';
+  import bpmDetail from '@/views/bpm/processInstance/detail.vue';
+  import bpmSubmit from './bpmSubmit.vue';
+  import bpmList from './bpmList.vue';
 
   export default {
     name: 'editModal',
     mixins: [dictMixins],
+    components: {
+      bpmDetail,
+      bpmSubmit,
+      bpmList
+    },
     data() {
-      const formBaseData = {
-        username: '',
-        email: ''
-      };
+      const formBaseData = {};
 
       return {
         visible: false,
@@ -521,16 +573,16 @@
         uerList: [],
         deviceList: [],
         // ruleInfo
-        ruleInfo: ''
+        ruleInfo: '',
+        currenNode: null
       };
     },
     methods: {
       // 外部调用,打开弹窗
       open(data, type) {
         this.type = type;
-        this.details = data;
         this.title = type == 'detail' ? '详情' : '审核';
-        console.log('data', data);
+        console.log('当前行数据', data);
         this.getDatails(data.id);
         if (data.executeMethod == 1) {
           // 查询事项规则信息
@@ -542,6 +594,7 @@
       },
       // 关闭时清理表单
       handleClose() {
+        this.currenNode = null;
         this.visible = false;
       },
       // 获取详情
@@ -601,6 +654,14 @@
             this.uerList = res.list;
           }
         } catch (error) {}
+      },
+      // currenNode
+      setCurrenNode(currenNode) {
+        this.currenNode = currenNode;
+      },
+      // 审核通过刷新数据
+      handleAudit() {
+        this.getDatails(this.details.id);
       }
     }
   };

+ 68 - 26
src/views/batchRecord/components/editModal.vue

@@ -225,16 +225,53 @@
     </div>
 
     <template v-slot:footer>
-      <el-button
-        type="primary"
-        @click="save"
-        :loading="butLoading"
-        :disabled="form.executeStatus != 0"
-        >保存</el-button
+      <template
+        v-if="
+          ($hasPermission('mes:producetaskrulerecord:tempsu') ||
+            $hasPermission('mes:producetaskrulerecord:tempsus')) &&
+          form.executeMethod == '1'
+        "
       >
-      <el-button type="primary" @click="submit" :loading="butLoading"
-        >执行</el-button
+        <el-button
+          v-if="$hasPermission('mes:producetaskrulerecord:tempsu')"
+          type="primary"
+          @click="save"
+          :loading="butLoading"
+          :disabled="form.executeStatus != 0"
+          >保存</el-button
+        >
+
+        <el-button
+          v-if="$hasPermission('mes:producetaskrulerecord:tempsus')"
+          type="primary"
+          @click="submit"
+          :loading="butLoading"
+          >执行</el-button
+        >
+      </template>
+      <template
+        v-if="
+          ($hasPermission('mes:producetaskrecordrulesrecord:saveorupdate') ||
+            $hasPermission('mes:producetaskrecordrulesrecord:sus')) &&
+          form.executeMethod == '2'
+        "
       >
+        <el-button
+          v-if="$hasPermission('mes:producetaskrecordrulesrecord:saveorupdate')"
+          type="primary"
+          @click="save"
+          :loading="butLoading"
+          :disabled="form.executeStatus != 0"
+          >保存</el-button
+        >
+        <el-button
+          v-if="$hasPermission('mes:producetaskrecordrulesrecord:sus')"
+          type="primary"
+          @click="submit"
+          :loading="butLoading"
+          >执行</el-button
+        >
+      </template>
       <el-button @click="handleClose" :loading="butLoading">取 消</el-button>
     </template>
 
@@ -375,13 +412,16 @@
             { required: true, message: '请选择规则', trigger: 'blur' }
           ],
           productCode: [
-            { required: true, message: '请输入产品编码', trigger: 'blur' }
+            { required: true, message: '请输入产品编码', trigger: 'blur' },
+            { required: true, message: '请输入产品编码', trigger: 'change' }
           ],
           productName: [
-            { required: true, message: '请输入产品名称', trigger: 'blur' }
+            { required: true, message: '请输入产品名称', trigger: 'blur' },
+            { required: true, message: '请输入产品编码', trigger: 'change' }
           ],
           formingNum: [
-            { required: true, message: '请输入要求生产数量', trigger: 'blur' }
+            { required: true, message: '请输入要求生产数量', trigger: 'blur' },
+            { required: true, message: '请输入产品编码', trigger: 'change' }
           ],
           produceTaskId: [
             { validator: validatepProduceTaskId, trigger: 'blur' }
@@ -440,6 +480,7 @@
       handleClose() {
         this.visible = false;
         this.form = JSON.parse(JSON.stringify(this.formBaseData));
+        this.produceTaskList = [];
         this.$refs.formRef && this.$refs.formRef.resetFields();
       },
       // 修改规则事项类型
@@ -556,22 +597,20 @@
           this.form.reportWorkType = this.reportWorkType;
           console.log('this.form', this.form);
 
-          if (!this.workOrderInfo) {
-            return this.$message.warning('工单信息不能为空');
-          }
-
           if (this.form.executeMethod == 1) {
             // 设备保养计划相关逻辑
             this.dialogTitle = '新增设备保养计划';
             this.$refs.programRulesDialogRef.init(
               this.form,
-              this.workOrderInfo,
-              {}
+              this.workOrderInfo ? this.workOrderInfo : this.form,
+              {
+                name: this.form.produceTaskName
+              }
             );
           } else {
             this.$refs.releaseRulesDialogRef.open(
               this.form,
-              this.workOrderInfo,
+              this.workOrderInfo ? this.workOrderInfo : this.form,
               {}
             );
           }
@@ -588,14 +627,17 @@
           try {
             this.butLoading = true;
             // 区分事项规则 和 记录规则
-            if (this.form.executeMethod == 1) {
-              const data = await tempSaveOrUpdate(this.form);
-              // 赋值返回的id
-              this.form.id = data;
-            } else {
-              const id = await saveOrUpdate(this.addForm);
-              this.addForm.id = id;
-            }
+            // if (this.form.executeMethod == 1) {
+            //   const data = await tempSaveOrUpdate(this.form);
+            //   // 赋值返回的id
+            //   this.form.id = data;
+            // } else {
+            //   const id = await tempSaveOrUpdate(this.form);
+            //   this.form.id = id;
+            // }
+            const id = await tempSaveOrUpdate(this.form);
+            this.form.id = id;
+
             this.$message.success('保存成功!');
             this.$emit('reload');
 

+ 28 - 17
src/views/batchRecord/components/list.vue

@@ -7,13 +7,20 @@
       :columns="columns"
       :datasource="datasource"
       cacheKey="batchRecordBefore"
-      :cache-key="'batchRecordTableRules-reportWorkType-' + reportWorkType"
+      :cache-key="cacheKeyUrl"
       autoAmendPage
+      :pageSize="20"
     >
       <!-- 操作列 -->
       <!-- 表头工具栏 -->
       <template v-slot:toolbar>
         <el-button
+          v-if="
+            $hasPermission('mes:producetaskrulerecord:tempsu') ||
+            $hasPermission('mes:producetaskrulerecord:tempsus') ||
+            $hasPermission('mes:producetaskrecordrulesrecord:saveorupdate') ||
+            $hasPermission('mes:producetaskrecordrulesrecord:sus')
+          "
           size="small"
           type="primary"
           icon="el-icon-plus"
@@ -53,15 +60,21 @@
           执行
         </el-link>
         <el-link
-          v-if="row.executeStatus == 2 && showBut"
+          v-if="
+            row.approvalStatus != null &&
+            (row.approvalStatus === 0 || row.approvalStatus === 3)
+          "
           type="primary"
           :underline="false"
-          @click="openApproval"
+          @click="openApproval(row)"
         >
           处理
         </el-link>
         <el-popconfirm
-          v-if="row.executeStatus == 0"
+          v-if="
+            row.executeStatus == 0 &&
+            $hasPermission('mes:producetaskrecordrulesrecord:logicdelete')
+          "
           title="确定要删除此用户吗?"
           class="ele-action"
           @confirm="deleteById(row)"
@@ -299,6 +312,9 @@
             ]
           }
         ];
+      },
+      cacheKeyUrl() {
+        return `mes-batchRecordTableRules-reportWorkType-${this.reportWorkType}`;
       }
     },
     created() {
@@ -323,8 +339,8 @@
         return producetaskrulerecordPage({
           ...where,
           ...order,
-          page,
-          limit,
+          pageNum: page,
+          size: limit,
           reportWorkType: this.reportWorkType
         });
       },
@@ -371,22 +387,17 @@
       // 执行
       async execute(row) {
         console.log('row', row);
-        const workOrderInfo = await getById(row.workOrderId);
+
+        const currentItem = { ...row, recordId: row.id };
 
         if (row.executeMethod == 1) {
           // 设备保养计划相关逻辑
-          this.$refs.programRulesDialogRef.init(
-            { ...row, recordId: row.id },
-            workOrderInfo,
-            {}
-          );
+          this.$refs.programRulesDialogRef.init(currentItem, currentItem, {
+            name: row.produceTaskName
+          });
           return;
         }
-        console.log('workOrderInfo', workOrderInfo);
-        this.$refs.releaseRulesDialogRef?.open(
-          { ...row, recordId: row.id },
-          workOrderInfo
-        );
+        this.$refs.releaseRulesDialogRef?.open(currentItem, currentItem);
       }
     }
   };

+ 149 - 0
src/views/batchRecord/components/tables/workOrderTable.vue

@@ -0,0 +1,149 @@
+<template>
+  <ele-pro-table
+    ref="table"
+    row-key="id"
+    :columns="columns"
+    :datasource="datasource"
+    :cache-key="cacheKeyUrl"
+    autoAmendPage
+  >
+  </ele-pro-table>
+</template>
+
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import tableColumnsMixin from '@/mixins/tableColumnsMixin';
+  import { batchRecordPage } from '@/api/workOrderList';
+
+  export default {
+    mixins: [dictMixins, tableColumnsMixin],
+    props: {
+      tableQuery: {
+        type: Object,
+        default: () => {
+          return {};
+        }
+      }
+    },
+    data() {
+      return {
+        columns: [
+          {
+            width: 50,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            label: '序号'
+          },
+          {
+            prop: 'code',
+            label: '生产工单号',
+            align: 'center',
+            minWidth: 110,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'scheduleStatus',
+            label: '工序进度',
+            align: 'center',
+            formatter: (row) => {
+              switch (row.scheduleStatus) {
+                case 10:
+                  return '待排产';
+                case 20:
+                  return '待发布';
+                case 30:
+                  return '发布失败';
+                case 40:
+                  return '待生产';
+                case 50:
+                  return '生产中';
+                case 60:
+                  return '已完成';
+                case 70:
+                  return '已延期';
+                case 80:
+                  return '待下达';
+                case 90:
+                  return '已暂停';
+                case 100:
+                  return '已终止';
+                case 110:
+                  return '已委外';
+                default:
+                  return '';
+              }
+            }
+          },
+          {
+            prop: 'planStartTime',
+            label: '计划开始时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'startTime',
+            label: '实际开始时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'planCompleteTime',
+            label: '工单状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 150,
+            formatter: (row) => {
+              switch (row.status) {
+                case 4:
+                  return '待生产';
+                case 5:
+                  return '生产中';
+                case 6:
+                  return '已完成';
+                case 7:
+                  return '已延期';
+                case 8:
+                  return '待下达';
+                case 9:
+                  return '暂停';
+                case 10:
+                  return '终止';
+
+                default:
+                  return '';
+              }
+            }
+          }
+        ],
+        cacheKeyUrl: 'mes-922194-work-order-table'
+      };
+    },
+    computed: {},
+    methods: {
+      // 刷新表格
+      reload(where = {}) {
+        this.$refs.table.reload({
+          where,
+          ...this.tableQuery
+        });
+      },
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        // 参数
+        const body = {
+          ...where,
+          ...order,
+          pageNum: page,
+          size: limit,
+          ...this.tableQuery
+        };
+        return batchRecordPage(body);
+      }
+    }
+  };
+</script>
+
+<style></style>

+ 172 - 83
src/views/batchRecord/index.vue

@@ -2,7 +2,7 @@
   <div class="ele-body">
     <el-card shadow="never">
       <ele-split-layout
-        width="460px"
+        width="500px"
         allow-collapse
         :right-style="{ overflow: 'hidden' }"
       >
@@ -10,24 +10,113 @@
           <div class="left-item">
             <div class="title">产品</div>
 
-            <el-input
-              placeholder="搜索"
-              :suffix-icon="productBody.param ? '' : 'el-icon-search'"
-              v-model="productBody.param"
-              @input="handleInput"
-              clearable
-            ></el-input>
+            <el-popover placement="right" width="400" trigger="click">
+              <div>
+                <el-form
+                  ref="productFormRef"
+                  :model="productBody"
+                  label-width="80px"
+                  class="productForm"
+                >
+                  <el-form-item label="关键字:">
+                    <el-input
+                      v-model="productBody.param"
+                      placeholder="产品编码、产品名称"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label="查询范围:">
+                    <el-date-picker
+                      style="width: 100%"
+                      v-model="productBody.createTimeStart"
+                      type="date"
+                      placeholder="选择日期"
+                      format="yyyy-MM-dd HH:mm:ss"
+                      value-format="yyyy-MM-dd HH:mm:ss"
+                    >
+                    </el-date-picker>
+                    <div style="margin-top: 10px">
+                      <el-date-picker
+                        style="width: 100%"
+                        v-model="productBody.createTimeEnd"
+                        type="date"
+                        placeholder="选择日期"
+                        format="yyyy-MM-dd HH:mm:ss"
+                        value-format="yyyy-MM-dd HH:mm:ss"
+                      >
+                      </el-date-picker>
+                    </div>
+                  </el-form-item>
+                  <el-form-item>
+                    <el-button
+                      type="primary"
+                      @click="getAllProductInWorkOrder"
+                      icon="el-icon-search"
+                      :loading="productButLoading"
+                      >查询</el-button
+                    >
+                    <el-button
+                      type="primary"
+                      @click="resetSubmit"
+                      icon="el-icon-refresh-left"
+                      :loading="productButLoading"
+                      >重置</el-button
+                    >
+                  </el-form-item>
+                </el-form>
+              </div>
+              <el-button slot="reference" type="primary" style="width: 100%"
+                >搜索</el-button
+              >
+            </el-popover>
 
             <div class="list-box">
               <div
                 class="list-item"
                 v-for="i in productList"
                 :key="i.productName + i.productCode"
-                :class="{ active: i.productName == tableQuery.param }"
+                :class="{ active: i.productCode == tableQuery.productCode }"
                 @click="changeProductName(i)"
               >
-                {{ i.productName }}
+                <!-- <el-popover
+                  placement="top-start"
+                  width="200"
+                  trigger="hover"
+                  :content="`产品编码:${i.productCode},产品名称:${i.productName}`"
+                >
+                  <template slot="reference">
+                    <div class="ele-elip" style="width: 100%">{{
+                      i.productCode
+                    }}</div>
+                    <div class="ele-elip" style="width: 100%">{{
+                      i.productName
+                    }}</div>
+                  </template>
+                </el-popover> -->
+                <div class="ele-elip" style="width: 100%">{{
+                  i.productCode
+                }}</div>
+                <div class="ele-elip" style="width: 100%">{{
+                  i.productName
+                }}</div>
               </div>
+              <div class="list-item"></div>
+              <div class="list-item"></div>
+              <div class="list-item"></div>
+              <div class="list-item"></div>
+            </div>
+
+            <div class="footer-box">
+              <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :current-page.sync="productBody.pageNum"
+                :page-size="20"
+                layout="sizes,pager"
+                :total="total"
+                :pager-count="5"
+                small
+              >
+              </el-pagination>
             </div>
           </div>
           <div class="left-item">
@@ -62,15 +151,11 @@
         <template v-slot:content>
           <div>
             <seek-page :seekList="seekList" @search="search"></seek-page>
-            <ele-pro-table
-              ref="table"
-              row-key="workOrderId"
-              :columns="columns"
-              :datasource="datasource"
-              cache-key="batch-record-list"
-              autoAmendPage
-            >
-            </ele-pro-table>
+            <workOrderTable
+              v-if="activeType == '生产工单'"
+              ref="tableRef"
+              :tableQuery="tableQuery"
+            ></workOrderTable>
           </div>
         </template>
       </ele-split-layout>
@@ -83,40 +168,14 @@
   import tableColumnsMixin from '@/mixins/tableColumnsMixin';
   import seekPage from '@/components/common/seekPage.vue';
   import { getAllProductInWorkOrder } from '@/api/produce/workOrder';
-  import { debounce } from '@/utils/util.js';
-  import { batchRecordPage } from '@/api/workOrderList';
+  import workOrderTable from './components/tables/workOrderTable.vue';
 
   export default {
-    components: { seekPage },
+    components: { seekPage, workOrderTable },
     name: 'batchRecord',
     mixins: [dictMixins, tableColumnsMixin],
     data() {
       return {
-        columns: [
-          {
-            width: 50,
-            type: 'index',
-            columnKey: 'index',
-            align: 'center',
-            label: '序号'
-          },
-          {
-            prop: 'workOrderName',
-            label: '单据名称'
-          },
-          {
-            prop: '',
-            label: '单据编码'
-          },
-          {
-            prop: 'status',
-            label: '单据状态'
-          },
-          {
-            prop: 'approveStatus',
-            label: '审核状态'
-          }
-        ],
         types: [
           {
             name: '生产工单'
@@ -151,16 +210,20 @@
         productBody: {
           param: '',
           pageNum: 1,
-          size: 999
+          size: 10,
+          // 创建开始时间和结束时间
+          createTimeStart: '',
+          createTimeEnd: ''
         },
+        productButLoading: false,
+        total: 0,
         // 批次号
         batchNos: [],
         // 产品列表
         productList: [],
         tableQuery: {
-          param: '',
-          batchNo: '',
-          type: ''
+          productCode: '',
+          batchNo: ''
         }
       };
     },
@@ -180,50 +243,37 @@
             placeholder: '请输入'
           }
         ];
-      },
-      /* 表格数据源 */
-      datasource({ page, limit, where, order }) {
-        return () => {
-          const body = { ...where, ...order, page, limit, ...this.tableQuery };
-
-          // 根据类型查询不同的api
-          switch (this.activeType) {
-            case '生产工单':
-              return batchRecordPage(body);
-
-            default:
-              return [];
-          }
-        };
       }
     },
     created() {
       this.getAllProductInWorkOrder();
     },
     methods: {
-      reload(where) {
-        this.$refs.table.reload({
-          where,
-          ...this.tableQuery
-        });
-      },
       // 刷新表格数据
+      reload() {
+        this.$refs.tableRef?.reload();
+      },
       search(where) {
-        this.reload(where);
+        this.$refs.tableRef?.reload(where);
       },
       // 获取产品和批次号
       async getAllProductInWorkOrder() {
-        const { list } = await getAllProductInWorkOrder(this.productBody);
-        this.productList = list;
-        console.log('this.productList', this.productList);
+        try {
+          this.productButLoading = true;
+          const { list, count } = await getAllProductInWorkOrder(
+            this.productBody
+          );
+          this.productList = list;
+          console.log('this.productList', this.productList);
+          this.productButLoading = false;
+          this.total = count;
+        } catch (error) {
+          this.productButLoading = false;
+        }
       },
-      // 搜索产品
-      handleInput: debounce(function (e) {
-        this.getAllProductInWorkOrder();
-      }, 500),
       // 选择产品
       changeProductName(i) {
-        this.tableQuery.param = i.productName;
+        this.tableQuery.productCode = i.productCode;
         // 设置批次号
         this.batchNos = i.batchNos;
         // 刷新表格
@@ -233,6 +283,20 @@
       changeActiveType(i) {
         this.activeType = i.name;
         this.reload();
+      },
+      resetSubmit() {
+        this.productBody.param = '';
+        this.productBody.createTimeStart = null;
+        this.productBody.createTimeEnd = null;
+        this.getAllProductInWorkOrder();
+      },
+      handleSizeChange(size) {
+        this.productBody.size = size;
+        this.getAllProductInWorkOrder();
+      },
+      handleCurrentChange(pageNum) {
+        this.productBody.pageNum = pageNum;
+        this.getAllProductInWorkOrder();
       }
     }
   };
@@ -245,8 +309,11 @@
     .left-item {
       flex: 1;
       border-right: 1px solid #ededed;
-      min-height: 80vh;
+      max-height: 78%;
       padding: 0 5px;
+      width: 33.3%;
+      position: relative;
+      box-sizing: border-box;
 
       .title {
         text-align: center;
@@ -263,7 +330,7 @@
         box-sizing: border-box;
 
         .list-item {
-          padding: 15px 10px;
+          padding: 10px 10px;
           border-bottom: 1px solid #ededed;
           font-size: 14px;
           cursor: pointer;
@@ -275,6 +342,28 @@
           color: #fff;
         }
       }
+
+      .footer-box {
+        width: 100%;
+        height: 70px;
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        z-index: 1;
+        background: #fff;
+        padding: 10px 0;
+
+        :deep(.el-pagination__sizes) {
+          display: block;
+          margin-bottom: 10px;
+        }
+      }
+    }
+  }
+
+  .productForm {
+    .el-form-item {
+      margin-bottom: 10px;
     }
   }
 </style>

+ 1 - 1
src/views/cqzb/index.vue

@@ -90,7 +90,7 @@
           },
           {
             prop: 'bfl',
-            label: '记录表分类',
+            label: '记录规则分类',
             align: 'center',
             showOverflowTooltip: true,
             minWidth: 110

+ 20 - 10
src/views/produce/components/prenatalExamination/programRulesDialog.vue

@@ -355,6 +355,7 @@
     },
     data() {
       const formData = {
+        id: null,
         code: '', // 计划配置单号
         name: '', // 计划配置名称
         autoOrder: 1, // 自动派单
@@ -430,7 +431,8 @@
         // 加载状态
         loading: false,
         // 提交状态
-        butLoading: false
+        butLoading: false,
+        produceTaskInfo: null
       };
     },
     computed: {
@@ -462,17 +464,17 @@
         this.deviceList = [];
         this.visible = false;
       },
-      // 初始化
-      async init(row, workOrderInfo) {
-        console.log('row, workOrderInfo', row, workOrderInfo);
+      // 初始化 事项、工单、工序信息
+      async init(row, workOrderInfo, produceTaskInfo) {
+        console.log('productionInfo', workOrderInfo);
+        console.log('workOrderInfo', row, workOrderInfo);
+        console.log('produceTaskInfo', produceTaskInfo);
+        this.produceTaskInfo = produceTaskInfo;
         this.productionInfo = row;
         this.workOrderInfo = workOrderInfo;
         this.visible = true;
 
-        if (
-          this.productionInfo.executeStatus &&
-          this.productionInfo.executeStatus != 0
-        ) {
+        if (this.productionInfo && this.productionInfo.eamPlanId) {
           // 执行中 已执行 获取基本信息
           this.getInfo();
         } else {
@@ -492,6 +494,10 @@
           // 类型转换
           this.addForm.urgent = this.addForm.urgent + '';
           this.addForm.executorId = data.executorId.split(',');
+          // 赋值id
+          this.addForm.id = this.productionInfo.id;
+          this.addForm.isTempRecord = data.isTempRecord;
+
           // 获取部门用户列表
           this.getUserList({ groupId: data.groupId });
           this.ruleInfo = data.ruleInfo;
@@ -636,9 +642,12 @@
 
             // 请求参数
             const body = {
+              id: this.addForm.id,
               planList: [
                 {
                   ...this.addForm,
+                  id: this.productionInfo.eamPlanId,
+                  planId: this.productionInfo.eamPlanId,
                   executorId: this.addForm.executorId.join(','),
                   planDeviceList: [
                     {
@@ -653,7 +662,7 @@
               produceRoutingName: this.workOrderInfo.produceRoutingName,
               produceTaskConfigId: this.productionInfo.produceTaskConfigId,
               produceTaskId: this.productionInfo.produceTaskId,
-              produceTaskName: this.productionInfo.produceTaskName,
+              produceTaskName: this.produceTaskInfo.name,
               reportWorkType: this.productionInfo.reportWorkType,
               ruleId: this.ruleInfo.id,
               ruleName: this.ruleInfo.name,
@@ -666,7 +675,7 @@
               productModel: this.workOrderInfo.productModel,
               productName: this.workOrderInfo.productName,
               specification: this.workOrderInfo.specification,
-              isTempRecord: 0,
+              isTempRecord: this.addForm.isTempRecord,
               itemType: this.productionInfo.itemType,
               deviceId: deviceInfo.id,
               deviceName: deviceInfo.name
@@ -674,6 +683,7 @@
 
             console.log('body', body);
 
+            // 批记录打开的统一这个接口,不区分是否临时记录
             if (this.isTempRecord) {
               await tempSaveOrUpdateAndSubmit(body);
             } else {

+ 14 - 5
src/views/produce/components/prenatalExamination/releaseRulesDialog.vue

@@ -22,7 +22,7 @@
           <el-form-item label="记录规则名称" required>
             <el-input
               v-model="addForm.ruleName"
-              size="small"
+
               placeholder="自动带出"
               disabled
             ></el-input>
@@ -46,7 +46,7 @@
           >
             <el-input
               v-model="addForm.deviceName"
-              size="small"
+
               placeholder="自动带出"
               disabled
             ></el-input>
@@ -54,11 +54,13 @@
           <el-form-item v-else label="车间区域" prop="workshopArea">
             <el-input
               v-model="addForm.workshopArea"
-              size="small"
+
               placeholder="请输入"
             ></el-input>
           </el-form-item>
         </el-col>
+      </el-row>
+      <el-row>
         <el-col :span="8">
           <el-form-item label="检查完成时间" required prop="checkFinishTime">
             <el-date-picker
@@ -403,6 +405,9 @@
           console.log('dat 缓存', data);
           this.$util.assignObject(this.addForm, data);
           this.addForm.recordRulesClassify += '';
+          if (this.addForm.details?.length == 0) {
+            this.getRuleList();
+          }
           this.loading = false;
         } catch (error) {
           this.loading = false;
@@ -544,7 +549,7 @@
           this.getRuleList();
           this.$message.success('缓存清空成功!');
           this.productionInfo.executeStatus = 0;
-          if (this.isTempRecord) {
+          if (this.addForm.isTempRecord) {
             this.handleBeforeClose();
           }
           this.$emit('reload');
@@ -556,7 +561,7 @@
   };
 </script>
 
-<style scoped>
+<style scoped lang="scss">
   .modal-body {
     padding: 16px;
     min-height: 100px;
@@ -567,4 +572,8 @@
     gap: 10px;
     justify-content: flex-end;
   }
+
+  .el-form-item .el-form-item {
+    margin-bottom: -5px;
+  }
 </style>

+ 6 - 0
src/views/produceOrder/index.vue

@@ -559,6 +559,12 @@
             align: 'center',
             showOverflowTooltip: true
           },
+          {
+            prop: 'specification',
+            label: '规格',
+            align: 'center',
+            showOverflowTooltip: true
+          },
           {
             prop: 'productionCodes',
             label: '生产编号',

+ 18 - 11
src/views/produceOrder/print.vue

@@ -10,33 +10,40 @@
         <div style="text-align: center; font-size: 16px; font-weight: bold; margin: 5px 0;">工艺流程卡</div>
         <table style="width: 100%; border-collapse: collapse; margin-bottom: 6px;">
           <tr>
-            <td rowspan="4" style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle; text-align: center; width: 100px; height: 120px;">
+            <td rowspan="5" style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle; text-align: center; width: 100px; height: 120px;">
               <img :src="card.qrLeft" alt="二维码" style="width: 90px; height: 90px;" />
             </td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">单号</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.code }}</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">单据日期</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.createDate }}</td>
-            <td rowspan="4" style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle; text-align: center; width: 100px; height: 120px;">
+            <td rowspan="5" style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle; text-align: center; width: 100px; height: 120px;">
               <img :src="card.qrRight" alt="二维码" style="width: 90px; height: 90px;" />
             </td>
           </tr>
           <tr>
-            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">编号</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">编码</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.productCode }}</td>
-            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">存货名称</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">名称</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.productName }}</td>
           </tr>
           <tr>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">图号</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.imgCode }}</td>
-            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">计划开始时间</td>
-            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.planStartTime }}</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">计量单位</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.unit }}</td>
+          </tr>
+          <tr>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">型号</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.model }}</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">规格</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.specification }}</td>
           </tr>
           <tr>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">计划开始时间</td>
+            <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.planStartTime }}</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">计划结束时间</td>
             <td style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;">{{ card.planCompleteTime }}</td>
-            <td colspan="2" style="border: 1px solid #000; padding: 3px 5px; vertical-align: middle;"></td>
           </tr>
         </table>
 
@@ -59,10 +66,10 @@
           <tbody>
             <tr v-for="(row, idx) in card.printTaskCarDetail" :key="idx">
               <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.taskName }}</td>
-              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.formingNum }}</td>
-              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.formedNum }}</td>
-              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.qualified }}</td>
-              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.noQualifiedSum }}</td>
+              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.formingNum || '' }}</td>
+              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.formedNum || '' }}</td>
+              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.qualified || '' }}</td>
+              <td style="border: 1px solid #000; padding: 3px; text-align: center;">{{ row.noQualifiedSum || '' }}</td>
               <td style="border: 1px solid #000; padding: 3px; text-align: center;"></td>
               <td style="border: 1px solid #000; padding: 3px; text-align: center;"></td>
               <td style="border: 1px solid #000; padding: 3px; text-align: center;"></td>

+ 2 - 2
vue.config.js

@@ -33,9 +33,9 @@ module.exports = {
       '/api': {
         // target: 'http://124.71.68.31:50001',
         // target: 'http://192.168.1.116:18086',
-        // target: 'http://192.168.1.251:18086',
+        target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.103:18086',192.168.1.116
-        target: 'http://192.168.1.125:18086',
+        // target: 'http://192.168.1.125:18086',
         // target: 'http://192.168.1.116:18086',
         // target: 'http://192.168.1.144:18086',
         // target: 'http://192.168.1.30:18086',