2213980799@qq.com пре 1 година
родитељ
комит
26fc835624

+ 31 - 0
src/api/aps/index.js

@@ -44,4 +44,35 @@ export async function getProduceTaskList(params) {
   if (res.data.code == 0) {
     return res.data.data;
   }
+}
+
+
+/**
+ * 生产订单
+ */
+ export async function workOrder(params) {
+  const res = await request.post('/aps/workorder/page', params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 生产工单
+ */
+ export async function produceOrder (params) {
+  const res = await request.post('/mes/workorder/page', params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 获取计划详情
+export async function getUpdateInfoById(id) {
+  const res = await request.get(`/aps/productionplan/getUpdateInfoById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
 }

+ 56 - 49
src/api/bpm/index.js

@@ -1,59 +1,66 @@
 import request from '@/utils/request'
 
 export async function getProcessDefinitionBpmnXML(id) {
-    const res = await request({
-      url: '/bpm/process-definition/get-bpmn-xml?id=' + id,
-      method: 'get'
-    })
-    if (res.data.code == 0) {
-      return res.data.data;
-    }
-    return Promise.reject(new Error(res.data.message));
+  const res = await request({
+    url: '/bpm/process-definition/get-bpmn-xml?id=' + id,
+    method: 'get'
+  })
+  if (res.data.code == 0) {
+    return res.data.data;
   }
-  
-
-  export async function getProcessInstance(id) {
-
-    const res= await request({
-      url: '/bpm/process-instance/get?id=' + id,
-      method: 'get',
-    })
-  
-    if (res.data.code == 0) {
-      return res.data.data;
-    }
-    return Promise.reject(new Error(res.data.message));
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+export async function getProcessInstance(id) {
+
+  const res = await request({
+    url: '/bpm/process-instance/get?id=' + id,
+    method: 'get',
+  })
+
+  if (res.data.code == 0) {
+    return res.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));
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+
+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 async function getActivityList(query) {
 
-    const res= await request({
-      url: '/bpm/activity/list',
-      method: 'get',
-      params: query
-    })
-  
-    if (res.data.code == 0) {
-      return res.data.data;
-    }
-    return Promise.reject(new Error(res.data.message));
+  const res = await request({
+    url: '/bpm/activity/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 listAllUserBind() {
+  const res = await request.get('/main/user/listAllUserBind');
+  if (res.data.code == 0) {
+    return res.data.data;
   }
-  
+  return Promise.reject(new Error(res.data.message));
+}

+ 46 - 0
src/api/exceptionManagement/index.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request';
+
+
+/**
+ * 异常列表
+ */
+export async function getList(data) {
+  const res = await request.post('/mes/exception_management/page', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//新建/修改
+export async function save(data) {
+  const res = await request.post('/mes/exception_management/' + (data.id ? 'update' : 'add'), data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//处置
+export async function dispose(data) {
+  const res = await request.post('mes/exception_management_detail/dispose', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 删除
+export async function remove(data) {
+  const res = await request.delete('/mes/exception_management/remove' ,{data});
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//提交
+export async function submit(data) {
+  const res = await request.post('/bpm/exception/submit', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 7 - 1
src/components/upload/fileUpload.vue

@@ -11,9 +11,11 @@
       :before-upload="beforeUpload"
       :file-list="fileList"
       :show-file-list="!showLib"
+      :disabled="disabled"
+
     >
       <slot>
-        <el-button type="primary" icon="el-icon-plus" size="mini">点击上传</el-button>
+        <el-button :disabled="disabled" type="primary" icon="el-icon-plus" size="mini">点击上传</el-button>
       </slot>
     </el-upload>
     <el-button type="primary" class="lib" @click="handleOpenLib" v-if="showLib"
@@ -101,6 +103,10 @@
       size: {
         type: Number,
         default: 10
+      },
+      disabled:{
+        default:false,
+        type:Boolean
       }
     },
     data () {

+ 2 - 0
src/enum/dict.js

@@ -19,5 +19,7 @@ export default {
   订单类型: 'order_type',
   不合格品原因:'unqualified_products_reason',
   订单计划类型: 'plan_type',
+  异常类型: 'Exception_type',
+
 };
 export const numberList = ['date_method'];

+ 274 - 0
src/views/bpm/processInstance/detail.vue

@@ -0,0 +1,274 @@
+<template>
+
+    <div class="app-container" style="padding: 15px">
+      <!-- 审批记录 -->
+      <el-card class="box-card" v-loading="tasksLoad">
+        <div slot="header" class="clearfix">
+          <span class="el-icon-picture-outline">审批记录</span>
+        </div>
+        <el-col :span="16" :offset="4">
+          <div class="block">
+            <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-col>
+      </el-card>
+
+      <!-- 高亮流程图 -->
+      <el-card class="box-card" v-loading="processInstanceLoading">
+        <div slot="header" class="clearfix">
+          <span class="el-icon-picture-outline">流程图</span>
+        </div>
+        <my-process-viewer
+          key="designer"
+          v-model="bpmnXML"
+          v-bind="bpmnControlForm"
+          :activityData="activityList"
+          :processInstanceData="processInstance"
+          :taskData="tasks"
+        />
+      </el-card>
+    </div>
+
+</template>
+
+<script>
+  import {
+    getProcessDefinitionBpmnXML,
+    getProcessInstance,
+    getTaskListByProcessInstanceId,
+    getActivityList
+  } from '@/api/bpm/index';
+  import store from '@/store';
+  import { getDate } from '@/utils/dateUtils';
+  import dictMixins from '@/mixins/dictMixins';
+  // import Vue from 'vue';
+
+  // 流程实例的详情页,可用于审批
+  export default {
+    name: 'ProcessInstanceDetail',
+    mixins: [dictMixins],
+    props: {
+      id: {
+        default: ''
+      }
+    },
+    components: {},
+    data() {
+      return {
+        // 遮罩层
+        processInstanceLoading: true,
+        dialogVisible: false,
+
+        // 流程实例
+        // id: undefined, // 流程实例的编号
+        processInstance: {},
+
+        // BPMN 数据
+        bpmnXML: null,
+        bpmnControlForm: {
+          prefix: 'flowable'
+        },
+        activityList: [],
+
+        // 审批记录
+        tasksLoad: true,
+        tasks: []
+      };
+    },
+    created() {
+
+      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;
+            }
+          });
+
+          // 取消加载中
+          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 '';
+      },
+      handleClose() {
+        this.dialogVisible = false;
+      }
+    }
+  };
+</script>
+
+<style lang="scss">
+  .my-process-designer {
+    height: calc(100vh - 200px);
+  }
+
+  .box-card {
+    width: 100%;
+    margin-bottom: 20px;
+  }
+</style>

+ 386 - 0
src/views/exceptionManagement/components/create.vue

@@ -0,0 +1,386 @@
+<template>
+  <ele-modal :visible.sync="visible" :title="title" width="45vw" append-to-body>
+    <div class="switch" v-if="type=='detail'">
+      <div class="switch_left">
+        <ul>
+          <li
+            v-for="item in tabOptions"
+            :key="item.key"
+            :class="{ active: activeComp == item.key }"
+            @click="activeComp = item.key"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+    </div>
+    <el-form
+      ref="form"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+      class="create-form"
+      v-if="activeComp=='main'"
+    >
+      <headerTitle title="基本信息" style="margin-top: 15px"></headerTitle>
+
+      <el-row :gutter="15">
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="类型:" prop="type">
+            <DictSelection
+              dictName="异常类型"
+              v-model="form.type"
+              :disabled="type == 'detail'"
+            ></DictSelection>
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 24 } : { span: 8 }">
+          <el-form-item label="编码:" prop="code">
+            <el-input v-model="form.code" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 16, md: 24 } : { span: 16 }">
+          <el-form-item label="名称:" prop="name">
+            <el-input v-model="form.name" :disabled="type == 'detail'" />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 16, md: 24 } : { span: 16 }">
+          <el-form-item label="异常描述:">
+            <el-input
+              v-model="form.describes"
+              type="textarea"
+              :rows="2"
+              :disabled="type == 'detail'"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 16, md: 24 } : { span: 16 }">
+          <el-form-item label="关联:" prop="relationType">
+            <el-select
+              :disabled="type == 'detail'"
+              v-model="form.relationType"
+              placeholder="请选择"
+              style="width: 100%"
+              clearable
+              @input="addProduct"
+            >
+              <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="16">
+          <el-form-item prop="accessory" label="上传附件">
+            <fileUpload
+              v-model="form.accessory"
+              module="main"
+              :limit="5"
+              :disabled="type == 'detail'"
+              :showLib="false"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <headerTitle
+        v-if="form.relationJson.code"
+        style="margin-top: 15px"
+        :title="getTitle() + '信息'"
+      ></headerTitle>
+      <el-row :gutter="15" v-if="form.relationJson.code">
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item :label="'生产' + getTitle() + '号'">
+            <el-input v-model="form.relationJson.code" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="计划编号">
+            <el-input v-model="form.relationJson.productionPlanCode" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="计划类型">
+            <el-input v-model="form.relationJson.planTypeName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="工艺路线">
+            <el-input v-model="form.relationJson.produceRoutingName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="工序">
+            <el-input v-model="form.relationJson.produceVersionName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="产品编码">
+            <el-input v-model="form.relationJson.productCode" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="产品名称">
+            <el-input v-model="form.relationJson.productName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="牌号">
+            <el-input v-model="form.relationJson.brandNo" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="型号">
+            <el-input v-model="form.relationJson.model" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="批号">
+            <el-input v-model="form.relationJson.batchNo" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="要求生产数量">
+            <el-input v-model="form.relationJson.requiredFormingNum" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="要求生产重量">
+            <el-input v-model="form.relationJson.sumOrderWeight" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="计划开始时间">
+            <el-input v-model="form.relationJson.reqMoldTime" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="已生产数量">
+            <el-input v-model="form.relationJson.formedNum" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="已生产重量">
+            <el-input v-model="form.relationJson.formedWeight" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="计划结束时间">
+            <el-input v-model="form.relationJson.deliveryTime" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="状态">
+            <el-input v-model="form.relationJson.status" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="班组">
+            <el-input v-model="form.relationJson.teamName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="优先级">
+            <el-input v-model="form.relationJson.priority" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="创建人">
+            <el-input v-model="form.relationJson.createUserName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="创建时间">
+            <el-input v-model="form.relationJson.createTime" disabled />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="cancel">取消</el-button>
+      <el-button
+        type="primary"
+        @click="save"
+        :loading="loading"
+        v-if="type != 'detail'"
+      >
+        确定
+      </el-button>
+    </template>
+    <detail  v-if="activeComp === 'bpm' && form.processInstanceId"
+      :id="form.processInstanceId"></detail>
+    <productionPlan ref="productionPlanRef" @choose="choose" />
+    <workOrder ref="workOrderRef" @choose="choose" />
+    <produceOrder ref="produceOrderRef" @choose="choose" />
+  </ele-modal>
+</template>
+
+<script>
+import { save } from '@/api/exceptionManagement/index';
+import { transitionData } from './transition';
+import productionPlan from './productionPlan';
+import workOrder from './workOrder';
+import produceOrder from './produceOrder';
+import fileUpload from '@/components/upload/fileUpload';
+import detail from '@/views/bpm/processInstance/detail.vue';
+const defaultForm = function () {
+  return {
+    accessory: [],
+    images: [],
+    code: '',
+    type: '',
+    relationType: '', //关联类型 1 计划 2订单 3工单
+    relationId: '', //关联id
+    relationCode: '',
+    exceptionDetermine: '', //异常判定
+    exceptionDispose: '', //异常处置
+    approvalStatus: '', //审批状态
+    approvalOpinion: '', //审批意见
+    exceptionClose: '', //异常关闭 0否 1 是
+    createUserName: '', //创建人名称
+    id: '',
+    describes: '',
+    createTime: '',
+    relationJson: [],
+    approvalProcess:[]
+  };
+};
+export default {
+  components: { fileUpload, productionPlan, workOrder, produceOrder, detail },
+  data() {
+    return {
+      visible: false,
+      loading: false,
+      activeComp: 'main',
+      tabOptions: [
+        { key: 'main', name: '异常详情' },
+        { key: 'bpm', name: '流程详情' }
+      ],
+      form: { ...defaultForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      },
+      type: '',
+      title: '创建',
+      options: [
+        { label: '生产计划', value: 1 },
+        { label: '生产订单', value: 2 },
+        { label: '生产工单', value: 3 }
+      ],
+      planType: [
+        { label: '所有计划类型', value: null },
+        { label: '内销计划', value: '1' },
+        { label: '外销计划', value: '2' },
+        { label: '预制计划', value: '3' }
+      ]
+    };
+  },
+
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {},
+  methods: {
+    getTitle() {
+      return this.form.relationType == 1
+        ? '计划'
+        : this.form.relationType == 2
+        ? '订单'
+        : '工单';
+    },
+    open(type, row) {
+      this.visible = true;
+      
+      this.activeComp= 'main',
+      this.type = type;
+      if (type != 'add') {
+        this.form = JSON.parse(JSON.stringify(row));
+        this.form.relationJson = this.form.relationJson[0];
+        this.form.type = this.form.type + '';
+      }
+      this.title = type == 'add' ? '新增' : type == 'edit' ? '修改' : '详情';
+    },
+
+    addProduct() {
+      if (this.form.relationType == 1) {
+        this.$refs.productionPlanRef.open();
+      } else if (this.form.relationType == 2) {
+        this.$refs.workOrderRef.open();
+      } else if (this.form.relationType == 3) {
+        this.$refs.produceOrderRef.open();
+      }
+    },
+    cancel() {
+      this.form = { ...defaultForm() };
+      this.visible = false;
+    },
+    choose(data) {
+      this.form.relationJson = JSON.parse(
+        JSON.stringify(transitionData(data, this.form.relationType))
+      );
+      this.form.relationId = data.relationId;
+      this.form.relationCode = data.code;
+    },
+
+    /* 保存编辑 */
+    save() {
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return false;
+        }
+        if (!this.form.relationJson.code) {
+          this.$message.error('请选择' + this.getTitle());
+          return;
+        }
+        // for (let key in this.form) {
+        //   if (key.includes('create')) {
+        //     this.form[key] = '';
+        //   }
+        // }
+        this.loading = true;
+        let data = JSON.parse(JSON.stringify(this.form));
+        data.relationJson = [data.relationJson];
+        save(data)
+          .then((res) => {
+            this.loading = false;
+            this.$message.success('成功');
+            this.cancel();
+            this.$emit('refresh');
+          })
+          .catch((e) => {
+            this.loading = false;
+          });
+      });
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.basic-details-title {
+  margin: 10px 0;
+}
+
+.add-product {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  font-size: 30px;
+  color: #1890ff;
+  margin: 10px 0;
+  cursor: pointer;
+}
+
+.create-form .el-form-item {
+  margin-bottom: 15px !important;
+}
+</style>

+ 213 - 0
src/views/exceptionManagement/components/dispose.vue

@@ -0,0 +1,213 @@
+<template>
+  <ele-modal :visible.sync="visible" title="处置" width="45vw" append-to-body>
+    <el-form
+      ref="form"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+      class="create-form"
+    >
+      <headerTitle title="基本信息" style="margin-top: 15px"></headerTitle>
+      <el-row :gutter="15">
+        <el-col v-bind="styleResponsive ? { lg: 9, md: 12 } : { span: 9 }">
+          <el-form-item label="类型:" prop="type">
+            <DictSelection
+              dictName="异常类型"
+              v-model="form.type"
+              disabled
+            ></DictSelection>
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 9, md: 24 } : { span: 9 }">
+          <el-form-item label="编码:" prop="code">
+            <el-input v-model="form.code" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 18, md: 24 } : { span: 16 }">
+          <el-form-item label="名称:" prop="name">
+            <el-input v-model="form.name" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 18, md: 24 } : { span: 16 }">
+          <el-form-item label="异常描述:">
+            <el-input
+              v-model="form.describes"
+              type="textarea"
+              :rows="2"
+              disabled
+            />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 9, md: 24 } : { span: 9 }">
+          <el-form-item label="创建人:" prop="createUserName">
+            <el-input v-model="form.createUserName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 9, md: 24 } : { span: 9 }">
+          <el-form-item label="创建时间:" prop="createTime">
+            <el-input v-model="form.createTime" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="18">
+          <el-form-item prop="accessory" label="附件">
+            <fileUpload
+              v-model="form.accessory"
+              module="main"
+              :limit="5"
+              disabled
+              :showLib="false"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <headerTitle v-if="form.approvalProcess.length>0" title="异常判定结果" style="margin-top: 15px"></headerTitle>
+      <el-row :gutter="15" v-for="(item,index) in form.approvalProcess" :key="index">
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="审核人:" >
+            <el-input v-value="item.auditor" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="异常判定:" >
+            <el-input v-value="item.exceptionDetermine" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col v-if="item.exceptionDispose" v-bind="styleResponsive ? { lg: 8, md: 12 } : { span: 8 }">
+          <el-form-item label="异常处置:" >
+            <el-input v-value="item.exceptionDispose" disabled />
+          </el-form-item> </el-col
+      ></el-row>
+      <el-row :gutter="15">
+      <headerTitle title="异常处置" style="margin-top: 15px"></headerTitle>
+
+        <footBtn />
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="cancel">取消</el-button>
+      <el-button
+        type="primary"
+        @click="save"
+        :loading="loading"
+      
+      >
+        确定
+      </el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script>
+import fileUpload from '@/components/upload/fileUpload';
+import footBtn from './footBtn';
+const defaultForm = function () {
+  return {
+    accessory: [],
+    images: [],
+    code: '',
+    type: '',
+    relationType: '', //关联类型 1 计划 2订单 3工单
+    relationId: '', //关联id
+    relationCode: '',
+    exceptionDetermine: '', //异常判定
+    exceptionDispose: '', //异常处置
+    approvalStatus: '', //审批状态
+    approvalOpinion: '', //审批意见
+    exceptionClose: '', //异常关闭 0否 1 是
+    createUserName: '', //创建人名称
+    id: '',
+    describes: '',
+    createTime: '',
+    relationJson: [],
+    approvalProcess: []
+  };
+};
+export default {
+  components: { fileUpload, footBtn},
+  data() {
+    return {
+      visible: false,
+      loading: false,
+
+      form: { ...defaultForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      },
+
+    };
+  },
+
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {},
+  methods: {
+    open( row) {
+      this.visible = true;
+        console.log(row,'row')
+      this.form = JSON.parse(JSON.stringify(row));
+      this.form.relationJson = this.form.relationJson[0];
+      this.form.type = this.form.type + '';
+    },
+
+   
+    cancel() {
+      this.form = { ...defaultForm() };
+      this.visible = false;
+    },
+   
+    /* 保存编辑 */
+    save() {
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return false;
+        }
+        if (!this.form.relationJson.code) {
+          this.$message.error('请选择' + this.getTitle());
+          return;
+        }
+
+        this.loading = true;
+        let data = JSON.parse(JSON.stringify(this.form));
+        data.relationJson = [data.relationJson];
+        save(data)
+          .then((res) => {
+            this.loading = false;
+            this.$message.success('成功');
+            this.cancel();
+            this.$emit('refresh');
+          })
+          .catch((e) => {
+            this.loading = false;
+          });
+      });
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.basic-details-title {
+  margin: 10px 0;
+}
+
+.add-product {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  font-size: 30px;
+  color: #1890ff;
+  margin: 10px 0;
+  cursor: pointer;
+}
+
+.create-form .el-form-item {
+  margin-bottom: 15px !important;
+}
+</style>

+ 95 - 0
src/views/exceptionManagement/components/footBtn.vue

@@ -0,0 +1,95 @@
+<template>
+    <div class="foot_box">
+      <div v-for="(item, index) in btnList" :key="index" class="btn" :style="{'background': item.bjColor}" @click="footClick(item.type)">
+        <img src="../../../assets/Frame.png" class="Frame">
+        {{ item.name }}
+      </div>
+    </div>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+          btnList: [
+          {
+                name: '退料',
+                type: 'job',
+                bjColor: '#157A2C'
+            },
+            {
+                name: '变更',
+                type: '',
+                bjColor: '#3490DE'
+            },
+            
+            {
+                name: '不合格品处置',
+                type: '',
+                bjColor: '#39D9AC'
+            },
+            {
+                name: '补料',
+                type: '',
+                bjColor: '#6639A6'
+            },
+            {
+                name: '报修',
+                type: '',
+                bjColor: '#858585'
+            },
+            {
+                name: '报损',
+                type: '',
+                bjColor: '#FF4D4F'
+            },
+           
+
+          ]
+        };
+    },
+    created() {
+
+    },
+    methods: {
+        footClick(type) {
+            this.$emit('footBtn', type);
+        }
+    }
+};
+</script>
+
+<style lang="scss" scoped>
+.foot_box{
+    // min-width: 1280px;
+    width: 100%;
+    height: 80px;
+    padding: 0 16px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 20px;
+}
+
+.btn{
+    height: 80px;
+    width: calc(100% / 6);
+    margin: 0 10px;
+    color: #fff;
+    font-weight: 800;
+    font-size: 20px;
+    border-radius: 4px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+
+    .Frame{
+        width: 26px;
+        height: 26px;
+    }
+
+}
+
+</style>

+ 168 - 0
src/views/exceptionManagement/components/order-search.vue

@@ -0,0 +1,168 @@
+<!-- 搜索表单 -->
+<template>
+  <el-form
+    label-width="90px"
+    class="ele-form-search"
+    @keyup.enter.native="search"
+    @submit.native.prevent
+  >
+    <el-row :gutter="15">
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="类型:">
+          <el-input
+            clearable
+            v-model="where.workOrderCode"
+            placeholder="请输入"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="编码:">
+          <el-input
+            clearable
+            v-model="where.code"
+            placeholder="请输入"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="名称:">
+          <el-input
+            clearable
+            v-model="where.code"
+            placeholder="请输入"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="关联信息:">
+          <el-input
+            clearable
+            v-model="where.code"
+            placeholder="请输入"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="状态:">
+
+          <el-select v-model="where.status" style="width:100%">
+            <el-option
+              v-for="item in statusList"
+              :key="item.code"
+              :value="item.code"
+              :label="item.name"
+
+            ></el-option>
+          </el-select>
+        </el-form-item>
+
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="创建人:">
+          <el-input
+            clearable
+            v-model="where.reviewerName"
+            placeholder="请输入"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="创建时间:">
+          <el-date-picker
+            class="w100"
+            style="width: 100%"
+            v-model="where.createTime"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            :default-time="['00:00:00', '23:59:59']"
+          >
+          </el-date-picker>
+        </el-form-item>
+      </el-col>
+ 
+   
+      <el-col v-bind="styleResponsive ? { lg: 6, md: 12 } : { span: 6 }">
+        <el-form-item label="组织机构:">
+          <auth-selection data-type="Array" v-model="where.deptIds" style="width: 100%"></auth-selection>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item>
+          <div style="display:flex;justify-content: end;">
+            <el-button
+            type="primary"
+            icon="el-icon-search"
+            class="ele-btn-icon"
+            @click="search"
+          >
+            查询
+          </el-button>
+          <el-button @click="reset" icon="el-icon-refresh-left" type="primary"
+            >重置</el-button
+          >
+          </div>
+         
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+export default {
+  props: [],
+  data() {
+    // 默认表单数据
+    const defaultWhere = {
+      productName: '',
+      status: '',
+      createTime: []
+    };
+    return {
+      // 表单数据
+      where: { ...defaultWhere },
+      statusList: [
+        {name:'待处理',code:0},
+        {name:'处理中',code:1},
+        {name:'已处理',code:2},
+      ],
+    };
+  },
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  watch: {},
+  created() {},
+  methods: {
+    /* 搜索 */
+    search() {
+      const where = { ...this.where };
+      if (where.createTime?.length) {
+        where.startTime = where.createTime[0];
+        where.endTime = where.createTime[1];
+      }
+      delete where.createTime;
+      this.$emit('search', where);
+    },
+    /*  重置 */
+    reset() {
+      this.where = { ...this.defaultWhere };
+      this.search();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.ele-form-actions {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+}
+</style>

+ 266 - 0
src/views/exceptionManagement/components/produceOrder.vue

@@ -0,0 +1,266 @@
+<template>
+  <el-dialog
+    :visible.sync="equipmentdialog"
+    :before-close="handleClose"
+    :close-on-click-modal="true"
+    :close-on-press-escape="false"
+    append-to-body
+    width="70%"
+    title="生产工单"
+  >
+    <div>
+      <el-row>
+        <el-col :span="24" class="table_col" v-if="equipmentdialog">
+          <ele-pro-table
+            ref="equiTable"
+            :columns="columns"
+            :datasource="datasource"
+            :selection.sync="selection"
+            :current.sync="current"
+            highlight-current-row
+            row-key="id"
+            height="50vh"
+            @done="onDone"
+          >
+          </ele-pro-table>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="btns">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { produceOrder } from '@/api/aps/index.js';
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 2 //1多选 2单选
+    }
+  },
+  data() {
+    return {
+      planType: [
+        { label: '所有计划类型', value: null },
+        { label: '内销计划', value: '1' },
+        { label: '外销计划', value: '2' },
+        { label: '预制计划', value: '3' }
+      ],
+      equipmentdialog: false,
+      current: null,
+      columns: [
+        {
+          width: 45,
+          type: 'selection',
+          columnKey: 'selection',
+          align: 'center',
+          reserveSelection: true,
+          show: this.type == 1
+        },
+        {
+          label: '生产工单号',
+          align: 'center',
+          prop: 'code',
+
+          minWidth: 110
+        },
+
+        {
+          prop: 'productionPlanCode',
+          label: '计划编号',
+          align: 'center',
+          minWidth: 110
+        },
+        {
+          prop: 'planType',
+          label: '计划类型',
+          align: 'center',
+          formatter: (row) => {
+            const obj = this.planType.find((i) => i.value == row.planType);
+            return obj && obj.label;
+          }
+        },
+        {
+          prop: 'produceRoutingName',
+          label: '工艺路线',
+          align: 'center'
+        },
+        {
+          prop: 'productCode',
+          label: '产品编号',
+          align: 'center'
+        },
+        {
+          prop: 'productName',
+          label: '产品名称',
+          align: 'center'
+        },
+        {
+          prop: 'brandNo',
+          label: '牌号',
+          align: 'center'
+        },
+        {
+          prop: 'specification',
+          label: '规格',
+          align: 'center'
+        },
+        {
+          prop: 'model',
+          label: '型号',
+          align: 'center'
+        },
+        {
+          prop: 'batchNo',
+          label: '批号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'priority',
+          label: '优先级',
+          align: 'center',
+          minWidth: 120,
+          sortable: 'custom'
+        },
+
+        {
+          prop: 'formingNum',
+          label: '要求生产数量',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'formingWeight',
+          label: '要求生产重量',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'formedNum',
+          label: '已生产数量',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'formedWeight',
+          label: '已生产重量',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'planStartTime',
+          label: '计划开始时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'planCompleteTime',
+          label: '计划结束时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+        {
+          prop: 'startTime',
+          label: '实际开始时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+
+        {
+          prop: 'createTime',
+          label: '创建时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+
+        {
+          prop: 'teamName',
+          label: '班组',
+          align: 'center',
+          showOverflowTooltip: true
+        }
+      ],
+      categoryLevelId: null,
+      code: null,
+      selection: [],
+      ids: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    datasource({ page, where, limit }) {
+      return produceOrder({
+        ...where,
+        pageNum: page,
+        size: limit
+      });
+    },
+    open(ids) {
+      this.equipmentdialog = true;
+    },
+    onDone() {
+      this.$nextTick(() => {
+        this.$refs.equiTable.setSelectedRowKeys(this.ids);
+      });
+    },
+    handleClose() {
+      this.equipmentdialog = false;
+      this.$refs.equiTable.clearSelection();
+    },
+    // 选择
+    selected() {
+      let data =
+        this.type == 1
+          ? JSON.parse(JSON.stringify(this.selection))
+          : JSON.parse(JSON.stringify(this.current));
+      this.$emit('choose', data);
+      this.handleClose();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.tree_col {
+  border: 1px solid #eee;
+  padding: 10px 0;
+  box-sizing: border-box;
+  max-height: 530px;
+  overflow: auto;
+}
+.table_col {
+  padding-left: 10px;
+  ::v-deep .el-table th.el-table__cell {
+    background: #f2f2f2;
+  }
+}
+.pagination {
+  text-align: right;
+  padding: 10px 0;
+}
+.btns {
+  text-align: center;
+  padding: 10px 0;
+}
+.topsearch {
+  margin-bottom: 15px;
+}
+</style>

+ 241 - 0
src/views/exceptionManagement/components/productionPlan.vue

@@ -0,0 +1,241 @@
+<template>
+  <el-dialog
+    :visible.sync="equipmentdialog"
+    :before-close="handleClose"
+    :close-on-click-modal="true"
+    :close-on-press-escape="false"
+    append-to-body
+    width="70%"
+    title="生产计划"
+  >
+    <div>
+      <el-row>
+        <el-col :span="24" class="table_col" v-if="equipmentdialog">
+          <ele-pro-table
+            ref="equiTable"
+            :columns="columns"
+            :datasource="datasource"
+            :selection.sync="selection"
+            :current.sync="current"
+            highlight-current-row
+            row-key="id"
+            height="50vh"
+            @done="onDone"
+          >
+          </ele-pro-table>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="btns">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getList, getUpdateInfoById } from '@/api/aps/index.js';
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 2 //1多选 2单选
+    }
+  },
+  data() {
+    return {
+      equipmentdialog: false,
+      current: null,
+      planType: [
+        { label: '所有计划类型', value: null },
+        { label: '内销计划', value: '1' },
+        { label: '外销计划', value: '2' },
+        { label: '预制计划', value: '3' }
+      ],
+      columns: [
+        {
+          width: 45,
+          type: 'selection',
+          columnKey: 'selection',
+          align: 'center',
+          reserveSelection: true,
+          show: this.type == 1
+        },
+        {
+          columnKey: 'index',
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center',
+          showOverflowTooltip: true,
+          fixed: 'left'
+        },
+        {
+          prop: 'code',
+          label: '计划编号',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 180
+        },
+        {
+          prop: 'productCode',
+          label: '产品编码',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 140
+        },
+        {
+          prop: 'productName',
+          label: '产品名称',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 140
+        },
+
+        {
+          prop: 'brandNo',
+          label: '牌号',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'batchNo',
+          label: '批号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'model',
+          label: '型号',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'priority',
+          label: '优先级',
+          align: 'center',
+          minWidth: 120,
+          sortable: 'custom'
+        },
+
+        {
+          prop: 'productNum',
+          label: '计划数量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'productWeight',
+          label: '计划重量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'requiredFormingNum',
+          label: '要求生产数量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'newSumOrderWeight',
+          label: '要求生产重量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'reqMoldTime',
+          label: '要求生产日期',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        },
+
+        {
+          prop: 'orderType',
+          label: '计划类型',
+          align: 'center',
+          showOverflowTooltip: true,
+          formatter: (row) => {
+            const obj = this.planType.find((i) => i.value == row.planType);
+            return obj && obj.label;
+          }
+        },
+        {
+          prop: 'createTime',
+          label: '创建时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 110
+        }
+      ],
+      categoryLevelId: null,
+      code: null,
+      selection: [],
+      ids: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    datasource({ page, where, limit }) {
+      return getList({
+        ...where,
+        pageNum: page,
+        size: limit
+      });
+    },
+    open(ids) {
+      this.equipmentdialog = true;
+    },
+    onDone() {
+      this.$nextTick(() => {
+        this.$refs.equiTable.setSelectedRowKeys(this.ids);
+      });
+    },
+    handleClose() {
+      this.equipmentdialog = false;
+      this.$refs.equiTable.clearSelection();
+    },
+    // 选择
+    async selected() {
+      let data = await getUpdateInfoById(this.current.id);
+      
+      this.$emit('choose', data);
+      this.handleClose();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.tree_col {
+  border: 1px solid #eee;
+  padding: 10px 0;
+  box-sizing: border-box;
+  max-height: 530px;
+  overflow: auto;
+}
+.table_col {
+  padding-left: 10px;
+  ::v-deep .el-table th.el-table__cell {
+    background: #f2f2f2;
+  }
+}
+.pagination {
+  text-align: right;
+  padding: 10px 0;
+}
+.btns {
+  text-align: center;
+  padding: 10px 0;
+}
+.topsearch {
+  margin-bottom: 15px;
+}
+</style>

+ 48 - 0
src/views/exceptionManagement/components/transition.js

@@ -0,0 +1,48 @@
+const planType = [
+    { label: '所有计划类型', value: null },
+    { label: '内销计划', value: '1' },
+    { label: '外销计划', value: '2' },
+    { label: '预制计划', value: '3' }
+]
+const planStatus = [
+    { label: '待发布', value: '2' },
+    { label: '发布失败', value: '3' },
+    { label: '待生产', value: '4' },
+    { label: '生产中', value: '5' },
+    { label: '已完成', value: '6' },
+    { label: '已延期', value: '7' },
+    { label: '待下达', value: '8' },
+]
+
+
+export function transitionData(data,type) {
+    return {
+        code: data.code,//编码
+        productionPlanCode: data.productionPlanCode||data.code,//编码
+        planTypeName: data.planType&&planType.find((i) => i.value == data.planType).label,//计划类型
+        planType: data.planType,//计划类型
+        model: data.model,//型号
+        relationId: data.id,//关联id
+        productCode: data.productCode,//产品编码
+        productName: data.productName,//产品名称
+        specifications: data.specifications,//规格
+        requiredFormingNum: type==1?data.salesOrders[0]?.requiredFormingNum:(data.formingNum+' '+data.unit),//要求生产数量
+        sumOrderWeight: type==1?(data.sumOrderWeight+data.weightUnit):(data.formingWeight+' '+(data.newWeightUnit||data.weightUnit)),//要求生产重量
+        formedNum:data.formedNum&&(data.formedNum+' '+data.unit),//以生产数量
+        formedWeight:data.formedWeight&&(data.formedWeight+' '+data.weightUnit),//以生产数量
+        batchNo: data.batchNo,//批号
+        brandNo: data.brandNo,//牌号
+        priority: type==1?data.salesOrders[0]?.priority:data.priority,//优先级
+        produceRoutingId: data.produceRoutingId,//工艺id
+        produceRoutingName: data.produceRoutingName,//工艺名称
+        produceVersionId:data.produceVersionId,//工序id
+        produceVersionName: data.produceVersionName,//工序
+        status: planStatus.find((i) => i.value == (type==1?data.salesOrders[0]?.status:data.status)).label,//状态
+        createTime: data.createTime,//
+        createUserName: '',//创建人
+        deliveryTime:type==1?data.salesOrders[0]?.deliveryTime:data.planCompleteTime,//计划结束时间
+        reqMoldTime:type==1?data.salesOrders[0]?.reqMoldTime:data.planStartTime,//计划开始时间
+        teamName:data.teamName,//班组
+        teamId:data.teamId//班组
+    }
+}

+ 254 - 0
src/views/exceptionManagement/components/workOrder.vue

@@ -0,0 +1,254 @@
+<template>
+  <el-dialog
+    :visible.sync="equipmentdialog"
+    :before-close="handleClose"
+    :close-on-click-modal="true"
+    :close-on-press-escape="false"
+    append-to-body
+    width="70%"
+    title="生产订单"
+  >
+    <div>
+      <el-row>
+        <el-col :span="24" class="table_col" v-if="equipmentdialog">
+          <ele-pro-table
+            ref="equiTable"
+            :columns="columns"
+            :datasource="datasource"
+            :selection.sync="selection"
+            :current.sync="current"
+            highlight-current-row
+            
+            row-key="id"
+            height="50vh"
+            @done="onDone"
+          >
+          </ele-pro-table>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="btns">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { workOrder} from '@/api/aps/index.js';
+
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 2//1多选 2单选
+    }
+  },
+  data() {
+    return {
+      equipmentdialog: false,
+      current: null,
+      planType: [
+        { label: '所有计划类型', value: null },
+        { label: '内销计划', value: '1' },
+        { label: '外销计划', value: '2' },
+        { label: '预制计划', value: '3' }
+      ],
+      columns: [
+        {
+          width: 45,
+          type: 'selection',
+          columnKey: 'selection',
+          align: 'center',
+          reserveSelection: true,
+          show:this.type==1
+        },
+        {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            label: '生产订单号',
+            align: 'center',
+            minWidth: 110,
+            prop: 'code',
+
+          },
+          {
+            prop: 'productionPlanCode',
+            label: '计划编号',
+            align: 'center'
+          },
+          {
+            prop: 'produceRoutingName',
+            label: '工艺路线',
+            align: 'center'
+          },
+          {
+            prop: 'productCode',
+            label: '产品编码',
+            align: 'center'
+          },
+          {
+            prop: 'productName',
+            label: '产品名称',
+            align: 'center'
+          },
+          {
+            prop: 'brandNo',
+            label: '牌号',
+            align: 'center'
+          },
+
+          {
+            prop: 'batchNo',
+            label: '批号',
+            align: 'center',
+            minWidth: 100,
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'model',
+            label: '型号',
+            align: 'center'
+          },
+ 
+
+          {
+            prop: 'priority',
+            label: '优先级',
+            align: 'center',
+            minWidth: 120,
+            sortable: 'custom'
+          },
+
+          {
+            prop: 'formingNum',
+            label: '要求生产数量',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'formingWeight',
+            label: '要求生产重量',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110,
+          },
+          {
+            prop: 'planStartTime',
+            label: '计划开始时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            prop: 'planCompleteTime',
+            label: '计划结束时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+      
+
+          {
+            prop: 'serialNo',
+            label: '客户代号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+
+          {
+            prop: 'simpleName',
+            label: '客户简称',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+
+      ],
+      categoryLevelId: null,
+      code: null,
+      selection: [],
+      ids:[]
+    };
+  },
+
+  watch: {},
+  methods: {
+    datasource({ page, where, limit }) {
+      return workOrder({
+        ...where,
+        pageNum: page,
+        size: limit
+      });
+    },
+    open(ids) {
+    
+      this.equipmentdialog = true;
+
+    
+    },
+    onDone(){
+      this.$nextTick(() => {
+        this.$refs.equiTable.setSelectedRowKeys(this.ids);
+      });
+    },
+    handleClose() {
+      this.equipmentdialog = false;
+      this.$refs.equiTable.clearSelection();
+    },
+    // 选择
+    selected() {
+      let data=this.type==1?JSON.parse(JSON.stringify(this.selection)):JSON.parse(JSON.stringify(this.current))
+      data['productNumber']=data.formingNum
+
+      this.$emit('choose', data);
+      this.handleClose();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.tree_col {
+  border: 1px solid #eee;
+  padding: 10px 0;
+  box-sizing: border-box;
+  max-height: 530px;
+  overflow: auto;
+}
+.table_col {
+  padding-left: 10px;
+  ::v-deep .el-table th.el-table__cell {
+    background: #f2f2f2;
+  }
+}
+.pagination {
+  text-align: right;
+  padding: 10px 0;
+}
+.btns {
+  text-align: center;
+  padding: 10px 0;
+}
+.topsearch {
+  margin-bottom: 15px;
+}
+</style>

+ 362 - 0
src/views/exceptionManagement/exceptionList/index.vue

@@ -0,0 +1,362 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading">
+      <order-search @search="reload" ref="searchRef"> </order-search>
+      <ele-pro-table
+        ref="table"
+        :columns="columns"
+        :datasource="datasource"
+        :selection.sync="selection"
+        row-key="id"
+      >
+        <template v-slot:type="{ row }">
+          <span> {{ getDictValue('异常类型', row.type + '') }}</span>
+        </template>
+        <template v-slot:approvalStatus="{ row }">
+          <span
+            :style="{
+              color:
+                row.approvalStatus == 1
+                  ? '#409EFF'
+                  : row.approvalStatus == 2
+                  ? '#67C23A'
+                  : row.approvalStatus == 3
+                  ? '#F56C6C'
+                  : ''
+            }"
+          >
+            {{
+              row.approvalStatus == 1
+                ? '审核中'
+                : row.approvalStatus == 2
+                ? '通过'
+                : row.approvalStatus == 3
+                ? '不通过'
+                : '草稿'
+            }}
+          </span>
+        </template>
+        <template v-slot:code="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            @click="open('detail', row)"
+          >
+            {{ row.code }}
+          </el-link>
+        </template>
+        <!-- 操作列 -->
+        <!-- 表头工具栏 -->
+        <template v-slot:toolbar>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-plus"
+            class="ele-btn-icon"
+            @click="open('add')"
+          >
+            新建
+          </el-button>
+          <el-button
+            size="small"
+            type="danger"
+            icon="el-icon-delete"
+            class="ele-btn-icon"
+            @click="remove()"
+            plain
+            :disabled="selection.length == 0"
+          >
+            删除
+          </el-button>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-upload2"
+            class="ele-btn-icon"
+            plain
+          >
+            导出
+          </el-button>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-download"
+            class="ele-btn-icon"
+            plain
+          >
+            导入
+          </el-button>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-circle-plus-outline"
+            class="ele-btn-icon"
+            plain
+            :disabled="selection.length == 0"
+          >
+            处置
+          </el-button>
+        </template>
+
+        <template v-slot:action="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-truck"
+            v-if="row.approvalStatus == 0 || row.approvalStatus == 3"
+            @click="open('edit', row)"
+          >
+            编辑
+          </el-link>
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除吗?"
+            v-if="row.approvalStatus == 0 || row.approvalStatus == 3"
+            @confirm="remove([row.id])"
+          >
+            <template v-slot:reference>
+              <el-link type="danger" :underline="false" icon="el-icon-delete">
+                删除
+              </el-link>
+            </template>
+          </el-popconfirm>
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-circle-plus-outline"
+            v-if="row.approvalStatus == 2"
+            @click="dispose(row)"
+          >
+            处置
+          </el-link>
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-circle-plus-outline"
+            v-if="row.approvalStatus == 0 || row.approvalStatus == 3"
+            @click="submit(row.id)"
+          >
+            提交
+          </el-link>
+        </template>
+      </ele-pro-table>
+    </el-card>
+    <Create ref="create" @refresh="reload" />
+    <dispose ref="dispose" @refresh="reload" />
+    
+    <ele-modal :visible.sync="visible" width="20vw" append-to-body>
+      <el-form ref="form" label-width="100px" class="create-form">
+        <el-form-item
+          label="审核人"
+          prop="qualityInspector"
+          style="margin-bottom: 20px"
+        >
+          <el-select
+            v-model="qualityInspector"
+            clearable
+            style="width: 100%"
+            :filterable="true"
+          >
+            <el-option
+              v-for="item in userOptions"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template v-slot:footer>
+        <el-button @click="visible = false">取消</el-button>
+        <el-button type="primary" @click="submit()"> 确定 </el-button>
+      </template></ele-modal
+    >
+  </div>
+</template>
+  
+  <script>
+import OrderSearch from '../components/order-search.vue';
+import dictMixins from '@/mixins/dictMixins';
+import Create from '../components/create';
+import dispose from '../components/dispose';
+
+import { getList, remove,submit } from '@/api/exceptionManagement/index';
+import { listAllUserBind } from '@/api/bpm/index';
+
+export default {
+  components: {
+    OrderSearch,
+    Create,dispose
+  },
+  mixins: [dictMixins],
+  data() {
+    return {
+      visible: false,
+      loading: false,
+      releasParams: {
+        teamId: '',
+        id: ''
+      },
+      selection:[],
+      userOptions: [],
+      viewId: '',
+      qualityInspector: ''
+    };
+  },
+  computed: {
+    // 表格列配置
+    columns() {
+      return [
+        {
+          columnKey: 'selection',
+          type: 'selection',
+          width: 45,
+          align: 'center',
+          fixed: 'left'
+        },
+        {
+          columnKey: 'index',
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center',
+          showOverflowTooltip: true,
+          fixed: 'left'
+        },
+        {
+          prop: 'type',
+          label: '类型',
+          align: 'center',
+          slot: 'type'
+        },
+        {
+          prop: 'code',
+          label: '编码',
+          align: 'center',
+          slot: 'code'
+        },
+        {
+          prop: 'name',
+          label: '名称',
+          align: 'center'
+        },
+        {
+          prop: 'describes',
+          label: '异常描述',
+          align: 'center'
+        },
+        {
+          prop: 'relationType',
+          label: '关联类型',
+          align: 'center',
+          formatter: (row, column, cellValue) => {
+            return cellValue == 1
+              ? '生产计划'
+              : cellValue == 2
+              ? '生产订单'
+              : '生产工单';
+          }
+        },
+        {
+          prop: 'relationCode',
+          label: '关联编码',
+          align: 'center'
+        },
+        {
+          prop: 'a',
+          label: '关联名称',
+          align: 'center'
+        },
+
+        {
+          prop: 'createUserName',
+          label: '创建人',
+          align: 'center'
+        },
+
+        {
+          prop: 'createTime',
+          label: '创建时间',
+          align: 'center'
+        },
+
+        {
+          prop: 'approvalStatus',
+          label: '状态',
+          align: 'center',
+          slot: 'approvalStatus'
+        },
+
+        {
+          columnKey: 'action',
+          label: '操作',
+          width: 240,
+          align: 'center',
+          resizable: false,
+          fixed: 'right',
+          slot: 'action',
+          showOverflowTooltip: true
+        }
+      ];
+    }
+  },
+  created() {
+    this.requestDict('异常类型');
+    this.userOptions = [];
+    listAllUserBind().then((data) => {
+      this.userOptions.push(...data);
+    });
+  },
+  filters: {},
+  methods: {
+    //处置
+    dispose(row) {
+      this.$refs.dispose.open(row);
+    },
+    /* 表格数据源 */
+    datasource({ page, limit, where }) {
+      return getList({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+    },
+    open(type, row) {
+      this.$refs.create.open(type, row);
+    },
+    remove(id) {
+      let ids = id || this.selection.map((item) => item.id);
+      remove(ids).then((res) => {
+        this.$message.success('删除' + res);
+        this.reload();
+      });
+    },
+    
+    submit(id) {
+      if(id){
+        this.visible=true
+        this.viewId=id
+        return;
+      }
+      if (!this.qualityInspector) {
+        this.$message.error('审核人不能为空');
+        return;
+      }
+      submit({businessId: this.viewId,approvalUserId:this.qualityInspector}).then((res) => {
+        this.$message.success('提交' + message);
+        this.reload();
+        this.visible=false
+      });
+      
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() => {
+        this.$refs.table.reload({ page: 1, where });
+      });
+    }
+  }
+};
+</script>
+  
+  <style lang="scss" scoped></style>

+ 1 - 1
vue.config.js

@@ -32,7 +32,7 @@ module.exports = {
       // 当我们的本地的请求 有/api的时候,就会代理我们的请求地址向另外一个服务器发出请求
       '/api': {
         // target: 'http://124.71.68.31:50001',
-        target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.107:18086',
         // target: 'http://192.168.1.107:18086',
 
         changeOrigin: true, // 只有这个值为true的情况下 才表示开启跨域