Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/enum/dict.js
Z 1 год назад
Родитель
Сommit
f880e74df0

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

@@ -0,0 +1,78 @@
+import request from '@/utils/request';
+
+/**
+ * aps计划工单
+ */
+export async function getList (data) {
+  const res = await request.post('/aps/productionplan/page', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 工单发布
+ */
+export async function getDeviceList ({ productionId }) {
+  const res = await request.get(
+    `/aps/batchingworkorder/getDeviceList/${productionId}`
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 生产计划添加工单列表
+export async function getPlanDeviceList ({ produceVersionId }) {
+  const res = await request.get(`/aps/workorder/getDeviceList/${produceVersionId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+// 选择工艺路线
+export async function routeList(params) {
+  const res = await request.get('/main/producerouting/page', { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+}
+// 工序
+export async function getProduceTaskList(params) {
+  const res = await request.post('/main/producerouting/taskinstance/page',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));
+}

+ 52 - 0
src/api/changeManagement/notice.js

@@ -0,0 +1,52 @@
+import request from '@/utils/request';
+
+/**
+ * 列表
+ */
+export async function getNoticeList (data) {
+  const res = await request.post('/main/change_notice/page', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//新建/修改
+export async function noticeSave(data) {
+  const res = await request.post('/main/change_notice/' + (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 remove(data) {
+  const res = await request.delete('/main/change_notice/delete', { data });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 提交
+ */
+ export async function submit (data) {
+  const res = await request.post('/bpm/change_notice/submit', data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 详情
+ */
+ export async function noticeDetails(id) {
+  const res = await request.get(`/main/change_notice/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+

+ 51 - 0
src/api/changeManagement/question.js

@@ -0,0 +1,51 @@
+import request from '@/utils/request';
+
+/**
+ * 列表
+ */
+export async function getQuestionList (data) {
+  const res = await request.post('/main/problem_report/page', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//新建/修改
+export async function questionSave(data) {
+  const res = await request.post('/main/problem_report/' + (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 remove(data) {
+  const res = await request.delete('/main/problem_report/delete', { data });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 提交
+ */
+ export async function submit (data) {
+  const res = await request.post('/bpm/problem_report/submit', data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 详情
+ */
+ export async function questionDetails(id) {
+  const res = await request.get(`/main/problem_report/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 51 - 0
src/api/changeManagement/request.js

@@ -0,0 +1,51 @@
+import request from '@/utils/request';
+
+/**
+ * 列表
+ */
+export async function getRequestList(data) {
+  const res = await request.post('/main/change_request/page', data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//新建/修改
+export async function requestSave(data) {
+  const res = await request.post('/main/change_request/' + (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 remove(data) {
+  const res = await request.delete('/main/change_request/delete', { data });
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 提交
+ */
+export async function submit(data) {
+  const res = await request.post('/bpm/change_request/submit', data);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 详情
+ */
+export async function requestDetails(id) {
+  const res = await request.get(`/main/change_request/getById/${id}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 8 - 0
src/api/system/user/index.js

@@ -221,3 +221,11 @@ export async function checkExistence (field, value, id) {
   }
   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));
+}

+ 1 - 1
src/components/Dict/DictSelection.vue

@@ -25,7 +25,7 @@
     },
     props: {
       value: {
-        type: [String, Number],
+        type: [String, Number,Array],
         default: ''
       },
       dictName: {

+ 197 - 190
src/components/upload/fileUpload.vue

@@ -11,9 +11,12 @@
       :before-upload="beforeUpload"
       :file-list="fileList"
       :show-file-list="!showLib"
+      :disabled="disabled"
     >
       <slot>
-        <el-button type="primary" icon="el-icon-plus">点击上传</el-button>
+        <el-button :disabled="disabled" type="primary" icon="el-icon-plus"
+          >点击上传</el-button
+        >
       </slot>
     </el-upload>
     <el-button type="primary" class="lib" @click="handleOpenLib" v-if="showLib"
@@ -69,209 +72,213 @@
 </template>
 
 <script>
-  import {
-    uploadFile,
-    removeFile,
-    getFileList,
-    getFile
-  } from '@/api/system/file/index.js';
-  import { getImageUrl, getImagePath } from '@/utils/file';
-  export default {
-    props: {
-      value: {
-        type: Array,
-        default: () => []
-      },
-      // 所属模块
-      module: {
-        type: String,
-        required: true
-      },
-      // 文档库
-      showLib: {
-        type: Boolean,
-        default: false
-      },
-      // 限制数量
-      limit: {
-        type: Number,
-        default: -1
-      },
-      // 限制大小 mb
-      size: {
-        type: Number,
-        default: 10
-      }
+import {
+  uploadFile,
+  removeFile,
+  getFileList,
+  getFile
+} from '@/api/system/file/index.js';
+import { getImageUrl, getImagePath } from '@/utils/file';
+export default {
+  props: {
+    value: {
+      type: Array,
+      default: () => []
     },
-    data () {
-      return {
-        documentVisible: false,
-        selectItem: null,
-        documentForm: {
-          name: ''
-        },
-        columns: [
-          {
-            label: '序号',
-            type: 'index',
-            width: 55,
-            align: 'center'
-          },
-          {
-            label: '文档名称',
-            prop: 'name',
-            minWidth: '180',
-            showOverflowTooltip: true
-          },
-          {
-            label: '文档类型',
-            prop: 'type'
-          },
-          {
-            label: '系统'
-          },
-          {
-            label: '储存路径',
-            prop: 'storePath',
-            minWidth: '180',
-            showOverflowTooltip: true
-          },
-          {
-            label: '模块名',
-            prop: 'module'
-          },
-          {
-            label: '上传时间',
-            prop: 'createTime'
-          }
-        ]
-      };
+    // 所属模块
+    module: {
+      type: String,
+      required: true
     },
-    computed: {
-      fileList: {
-        set (val) {
-          // console.log(val);
-          this.$emit(
-            'input',
-            val.map((item) => ({
-              ...item,
-              url: getImagePath(item.url)
-            }))
-          );
-        },
-        get () {
-          // console.log(this.value, 2);
-          const arr =
-            (this.value &&
-              this.value.map((item) => ({
-                ...item,
-                url: getImageUrl(item.url)
-              }))) ||
-            [];
-          return arr;
-        }
-      }
+    // 文档库
+    showLib: {
+      type: Boolean,
+      default: false
     },
-
-    methods: {
-      //点击查看图片
-      handleItem(file){
-        console.log(file,'5555')
-       getFile({ objectName: file.storePath }, file.name);
-      },
-      delFileList () {
-        this.$emit('input', []);
-      },
-      handleOpenLib () {
-        this.documentVisible = true;
-        this.$nextTick(() => {
-          this.reload();
-        });
-      },
-      //图文档勾选
-      submitDocument () {
-        this.$emit('input', [
-          { url: this.selectItem.storePath, ...this.selectItem }
-        ]);
-        this.documentVisible = false;
-      },
-      datasource ({ page, limit }) {
-        return getFileList({
-          ...this.documentForm,
-          pageNum: page,
-          size: limit
-        });
-      },
-      reload () {
-        this.$refs.table.reload();
+    // 限制数量
+    limit: {
+      type: Number,
+      default: -1
+    },
+    // 限制大小 mb
+    size: {
+      type: Number,
+      default: 10
+    },
+    disabled: {
+      default: false,
+      type: Boolean
+    }
+  },
+  data() {
+    return {
+      documentVisible: false,
+      selectItem: null,
+      documentForm: {
+        name: ''
       },
-      beforeRemove (file) {
-        if (file.id) {
-          return removeFile({
-            fileId: file.id
-          }).then(() => {
-            return true;
-          });
-        } else {
-          return true;
+      columns: [
+        {
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center'
+        },
+        {
+          label: '文档名称',
+          prop: 'name',
+          minWidth: '180',
+          showOverflowTooltip: true
+        },
+        {
+          label: '文档类型',
+          prop: 'type'
+        },
+        {
+          label: '系统'
+        },
+        {
+          label: '储存路径',
+          prop: 'storePath',
+          minWidth: '180',
+          showOverflowTooltip: true
+        },
+        {
+          label: '模块名',
+          prop: 'module'
+        },
+        {
+          label: '上传时间',
+          prop: 'createTime'
         }
+      ]
+    };
+  },
+  computed: {
+    fileList: {
+      set(val) {
+        // console.log(val);
+        this.$emit(
+          'input',
+          val.map((item) => ({
+            ...item,
+            url: getImagePath(item.url)
+          }))
+        );
       },
-      handleRemove (file, fileList) {
-        this.fileList = fileList;
-      },
-      beforeUpload (file) {
-        if (file.size / 1024 / 1024 > this.size) {
-          this.$message.error(`大小不能超过 ${this.size}MB`);
-          return false;
-        }
+      get() {
+        // console.log(this.value, 2);
+        const arr =
+          (this.value &&
+            this.value.map((item) => ({
+              ...item,
+              url: getImageUrl(item.url)
+            }))) ||
+          [];
+        return arr;
+      }
+    }
+  },
 
-        if (this.limit > 0 && this.fileList.length === this.limit) {
-          this.$message.error(`最多上传 ${this.limit}个文件`);
-          return false;
-        }
-        return uploadFile({
-          module: this.module,
-          multiPartFile: file
-        }).then((res) => {
-          if (res.data) {
-            this.$emit('input', [
-              ...(this.value || []),
-              { ...file, url: res.data.storePath, ...res.data }
-            ]);
-          }
-          return res.data;
+  methods: {
+    //点击查看图片
+    handleItem(file) {
+      console.log(file, '5555');
+      getFile({ objectName: file.storePath }, file.name);
+    },
+    delFileList() {
+      this.$emit('input', []);
+    },
+    handleOpenLib() {
+      this.documentVisible = true;
+      this.$nextTick(() => {
+        this.reload();
+      });
+    },
+    //图文档勾选
+    submitDocument() {
+      this.$emit('input', [
+        { url: this.selectItem.storePath, ...this.selectItem }
+      ]);
+      this.documentVisible = false;
+    },
+    datasource({ page, limit }) {
+      return getFileList({
+        ...this.documentForm,
+        pageNum: page,
+        size: limit
+      });
+    },
+    reload() {
+      this.$refs.table.reload();
+    },
+    beforeRemove(file) {
+      if (file.id) {
+        return removeFile({
+          fileId: file.id
+        }).then(() => {
+          return true;
         });
-      },
-      handlRequest () {
-        return Promise.resolve();
+      } else {
+        return true;
       }
+    },
+    handleRemove(file, fileList) {
+      this.fileList = fileList;
+    },
+    beforeUpload(file) {
+      if (file.size / 1024 / 1024 > this.size) {
+        this.$message.error(`大小不能超过 ${this.size}MB`);
+        return false;
+      }
+
+      if (this.limit > 0 && this.fileList.length === this.limit) {
+        this.$message.error(`最多上传 ${this.limit}个文件`);
+        return false;
+      }
+      return uploadFile({
+        module: this.module,
+        multiPartFile: file
+      }).then((res) => {
+        if (res.data) {
+          this.$emit('input', [
+            ...(this.value || []),
+            { ...file, url: res.data.storePath, ...res.data }
+          ]);
+        }
+        return res.data;
+      });
+    },
+    handlRequest() {
+      return Promise.resolve();
     }
-  };
+  }
+};
 </script>
 
 <style lang="scss" scoped>
-  .upload-file {
-    display: flex;
-    justify-content: flex-start;
-    align-items: center;
+.upload-file {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
 
-    .lib {
-      margin-left: 12px;
-    }
+  .lib {
+    margin-left: 12px;
+  }
 
-    .imgs-box {
-      margin-left: 10px;
-      flex: 1;
-    }
-    .imgs-box .imgs-p {
-      height: 30px;
-      background: #f0f3f3;
-      line-height: 30px;
-      min-width: 480px;
-      margin-bottom: 5px;
-      padding: 0 10px;
-      display: flex;
-      justify-content: space-between;
-    }
+  .imgs-box {
+    margin-left: 10px;
+    flex: 1;
+  }
+  .imgs-box .imgs-p {
+    height: 30px;
+    background: #f0f3f3;
+    line-height: 30px;
+    min-width: 480px;
+    margin-bottom: 5px;
+    padding: 0 10px;
+    display: flex;
+    justify-content: space-between;
   }
+}
 </style>

+ 2 - 1
src/enum/dict.js

@@ -29,7 +29,8 @@ export default {
   交付物流程类型: 'pro_files_approve_type',
   预算单位: 'pro_projects_budget_unit',
   体积单位: 'volume_unit',
-
+  问题类型: 'question_type',
+  变更类型: 'change_type',
 };
 
 export const numberList = [

+ 104 - 0
src/views/changeManagement/components/EquipmentDialog.vue

@@ -0,0 +1,104 @@
+<template>
+  <el-dialog
+    title="关联变更"
+    :visible.sync="equipmentdialog"
+    :before-close="handleClose"
+    :close-on-click-modal="true"
+    :close-on-press-escape="false"
+    append-to-body
+    width="60%"
+  >
+    <div>
+      <tableLIst ref="tableLIstRef"></tableLIst>
+    </div>
+
+    <div>
+      <ele-pro-table
+        ref="table"
+        :columns="questionColumns"
+        :datasource="tableList"
+        :selection.sync="selection"
+        row-key="id"
+        height="20vh"
+        :needPage="false"
+      >
+        <template v-slot:category="{ row }">
+          <span v-for="item in row.category.split(',')" :key="item">
+            {{ getDictValue('问题类型', item) }}</span
+          >
+        </template>
+        <template v-slot:type="{ row }">
+        <span>{{ getDictValue('变更类型', row.type + '') }}</span>
+      </template>
+        <template v-slot:toolbar>
+          <el-button type="primary" size="small" @click="add">添加</el-button>
+          <el-button size="small" @click="del">移除</el-button></template
+        >
+      </ele-pro-table>
+    </div>
+    <template v-slot:footer>
+      <el-button type="primary" size="small" @click="selected">确认</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+import tableLIst from './tableLIst.vue';
+import { questionColumns } from './data.js';
+import dictMixins from '@/mixins/dictMixins';
+
+export default {
+  components: { tableLIst },
+  mixins: [dictMixins],
+
+  data() {
+    return {
+      questionColumns: questionColumns.filter(
+        (item) => item.columnKey != 'action'&&item.prop != 'objType'
+      ),
+      equipmentdialog: false,
+      tableList: [],
+      selection: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    open(data) {
+      this.tableList = JSON.parse(JSON.stringify(data));
+      this.equipmentdialog = true;
+    },
+
+    reload() {
+      this.$refs.equiTable.reload();
+    },
+    handleClose() {
+      this.equipmentdialog = false;
+    },
+    reset() {
+      this.reload();
+    },
+    add() {
+      if (this.$refs.tableLIstRef.getValue().length == 0) {
+        return;
+      }
+      let ids = this.tableList.map((item) => item.id);
+      let getValue = this.$refs.tableLIstRef
+        .getValue()
+        .filter((item) => !ids.includes(item.id)); //去重
+      this.tableList.push(...getValue);
+    },
+    del() {
+      let ids = this.selection.map((item) => item.id);
+      this.tableList = this.tableList.filter((item) => !ids.includes(item.id));
+    },
+    // 选择
+    selected() {
+      this.$emit('choose', JSON.parse(JSON.stringify(this.tableList)));
+      this.handleClose();
+    }
+  }
+};
+</script>
+

+ 174 - 0
src/views/changeManagement/components/changeInfo.vue

@@ -0,0 +1,174 @@
+<template>
+  <el-form
+    ref="form"
+    :model="form"
+    :rules="rules"
+    label-width="100px"
+    class="create-form"
+  >
+    <el-row :gutter="15">
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="名称:" prop="name">
+          <el-input v-model="form.name" :disabled="disabled" />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="编码:" prop="code">
+          <el-input v-model="form.code" disabled />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="类型:" prop="type">
+          <DictSelection
+            dictName="变更类型"
+            v-model="form.type"
+            :disabled="disabled"
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="类别:" prop="category">
+          <DictSelection
+            multiple
+            dictName="问题类型"
+            v-model="form.category"
+            :disabled="disabled"
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="变更原因:">
+          <el-input
+            v-model="form.changeReason"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="可行性分析:">
+          <el-input
+            v-model="form.feasibilityAnalysis"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="描述:">
+          <el-input
+            v-model="form.problemDescription"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item
+          label="接收人"
+          prop="recipientId"
+          style="margin-bottom: 20px"
+        >
+          <el-select
+            v-model="form.recipientId"
+            clearable
+            style="width: 100%"
+            :filterable="true"
+            :disabled="disabled"
+          >
+            <el-option
+              v-for="item in userOptions"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+              @click.native="userChange(item)"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item prop="accessory" label="相关文档">
+          <fileUpload
+            v-model="form.accessory"
+            module="main"
+            :limit="5"
+            :disabled="disabled"
+            :showLib="false"
+          />
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+import fileUpload from '@/components/upload/fileUpload';
+import { listAllUserBind } from '@/api/system/user/index';
+import { infoForm } from './data.js';
+
+export default {
+  components: { fileUpload },
+  data() {
+    return {
+      userOptions: [],
+      form: { ...infoForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      }
+    };
+  },
+  props: {
+    disabled: {
+      type: Boolean,
+      default:false
+    }
+  },
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {
+    this.userOptions = [];
+    listAllUserBind().then((data) => {
+      this.userOptions.push(...data);
+    });
+  },
+  methods: {
+    cancel() {
+      this.form = { ...infoForm() };
+    },
+    open(row) {
+      if (row) {
+        this.form = row;
+      }
+    },
+    setValue(data) {
+      this.form = JSON.parse(JSON.stringify(data));
+    },
+    userChange(item) {
+      this.form.recipientName = item.name;
+    },
+    /* 保存编辑 */
+    async getValue() {
+      const valid = await this.validateFn();
+      this.form.objType = '2';
+      return valid ? JSON.parse(JSON.stringify(this.form)) : '';
+    },
+    validateFn() {
+      return new Promise((resolve, reject) => {
+        this.$refs.form.validate((valid) => {
+          resolve(valid);
+        });
+      });
+    }
+  }
+};
+</script>

+ 404 - 0
src/views/changeManagement/components/create.vue

@@ -0,0 +1,404 @@
+<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
+      v-show="activeComp == 'main'"
+      ref="form"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+      class="create-form"
+    >
+      <el-steps :active="active" align-center style="margin-bottom: 10px">
+        <el-step title="基本信息"> </el-step>
+        <el-step title="关联变更"></el-step>
+        <el-step title="问题对象"></el-step>
+        <el-step title="影响对象"></el-step>
+        <el-step title="参考对象"></el-step>
+      </el-steps>
+
+      <el-row :gutter="15" v-show="active == 0">
+        <questionInfo
+          ref="info"
+          v-if="pageType == 1"
+          :disabled="type == 'detail'"
+        />
+        <changeInfo
+          ref="info"
+          v-if="pageType == 2"
+          :disabled="type == 'detail'"
+        />
+        <noticeInfo
+          ref="info"
+          v-if="pageType == 3"
+          :disabled="type == 'detail'"
+        />
+      </el-row>
+      <el-row :gutter="15" v-show="active == 1">
+        <ele-pro-table
+          ref="table"
+          :columns="questionColumns"
+          :datasource="this.form.relationObjList"
+          height="20vh"
+          :selection.sync="selection"
+          :needPage="false"
+        >
+          <template v-slot:category="{ row }">
+            <span v-for="item in row.category.split(',')" :key="item">
+              {{ getDictValue('问题类型', item) }}</span
+            >
+          </template>
+          <template v-slot:type="{ row }">
+            <span>{{ getDictValue('变更类型', row.type + '') }}</span>
+          </template>
+          <template v-slot:toolbar>
+            <el-button
+              size="small"
+              v-if="type != 'detail'"
+              @click="del('selection', 'relationObjList')"
+              >移除</el-button
+            ></template
+          >
+        </ele-pro-table>
+        <div
+          class="add-product"
+          v-if="type != 'detail'"
+          @click="addEquipment('EquipmentDialogRef', 'relationObjList')"
+        >
+          <i class="el-icon-circle-plus-outline"></i>
+        </div>
+      </el-row>
+      <el-row :gutter="15" v-show="active == 2">
+        <ele-pro-table
+          ref="table"
+          :columns="objColumns"
+          :datasource="this.form.problemObjList"
+          height="20vh"
+          :selection.sync="objSelection"
+          :needPage="false"
+        >
+          <template v-slot:toolbar>
+            <el-button
+              size="small"
+              v-if="type != 'detail'"
+              @click="del('objSelection', 'problemObjList')"
+              >移除</el-button
+            ></template
+          >
+        </ele-pro-table>
+        <div
+          class="add-product"
+          v-if="type != 'detail'"
+          @click="addEquipment('objEquipmentDialogRef', 'problemObjList')"
+        >
+          <i class="el-icon-circle-plus-outline"></i>
+        </div>
+      </el-row>
+      <el-row :gutter="15" v-show="active == 3">
+        <ele-pro-table
+          ref="table"
+          :columns="objColumns"
+          :datasource="this.form.influenceObjList"
+          height="20vh"
+          :selection.sync="influenceSelection"
+          :needPage="false"
+        >
+          <template v-slot:toolbar>
+            <el-button
+              size="small"
+              v-if="type != 'detail'"
+              @click="del('influenceSelection', 'influenceObjList')"
+              >移除</el-button
+            ></template
+          >
+        </ele-pro-table>
+        <div
+          class="add-product"
+          v-if="type != 'detail'"
+          @click="addEquipment('objEquipmentDialogRef', 'influenceObjList')"
+        >
+          <i class="el-icon-circle-plus-outline"></i>
+        </div>
+      </el-row>
+      <el-row :gutter="15" v-show="active == 4">
+        <ele-pro-table
+          ref="table"
+          :columns="objColumns"
+          :datasource="this.form.referenceObjList"
+          height="20vh"
+          :selection.sync="referenceSelection"
+          :needPage="false"
+        >
+          <template v-slot:toolbar>
+            <el-button
+              v-if="type != 'detail'"
+              size="small"
+              @click="del('referenceSelection', 'referenceObjList')"
+              >移除</el-button
+            ></template
+          >
+        </ele-pro-table>
+        <div
+          v-if="type != 'detail'"
+          class="add-product"
+          @click="addEquipment('objEquipmentDialogRef', 'referenceObjList')"
+        >
+          <i class="el-icon-circle-plus-outline"></i>
+        </div>
+      </el-row>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="prev" :disabled="active == 0">上一步</el-button>
+      <el-button @click="next" :disabled="active == 4">下一步</el-button>
+      <el-button
+        type="primary"
+        @click="save"
+        :loading="loading"
+        v-if="type != 'detail'"
+      >
+        确定
+      </el-button>
+      <el-button @click="cancel">取消</el-button>
+    </template>
+    <bpmDetail v-if="activeComp==='bpm'&&form.processInstanceId" :id="form.processInstanceId"></bpmDetail>
+
+    <EquipmentDialog ref="EquipmentDialogRef" @choose="choose" />
+    <objEquipmentDialog ref="objEquipmentDialogRef" @choose="choose" />
+  </ele-modal>
+</template>
+
+<script>
+import questionInfo from './questionInfo';
+import changeInfo from './changeInfo';
+import noticeInfo from './noticeInfo';
+
+import EquipmentDialog from './EquipmentDialog';
+import objEquipmentDialog from './objEquipmentDialog';
+import dictMixins from '@/mixins/dictMixins';
+import bpmDetail from '@/views/bpm/processInstance/detail.vue';
+
+import { questionColumns, objColumns } from './data.js';
+import { questionSave,questionDetails } from '@/api/changeManagement/question';
+import { requestSave,requestDetails } from '@/api/changeManagement/request';
+import { noticeSave, noticeDetails } from '@/api/changeManagement/notice';
+
+import fileUpload from '@/components/upload/fileUpload';
+import { listAllUserBind } from '@/api/system/user/index';
+const defaultForm = function () {
+  return {
+    relationObjList: [],
+    problemObjList: [],
+    influenceObjList: [],
+    referenceObjList: []
+  };
+};
+export default {
+  mixins: [dictMixins],
+
+  components: {
+    fileUpload,
+    bpmDetail,
+    // workOrder,
+    // produceOrder,
+    questionInfo,
+    // productionPlan,
+    EquipmentDialog,
+    objEquipmentDialog,
+    changeInfo,
+    noticeInfo
+  },
+  data() {
+    //关联对象类型 objType 1:生产计划 2:生产订单 3:生产工单
+    //关联变更类型 objType 1:问题报告 2:变更申请 3:变更通知
+    return {
+      activeComp: 'main',
+      tabOptions: [
+        { key: 'main', name: '详情' },
+        { key: 'bpm', name: '流程详情' }
+      ],
+      questionColumns: questionColumns
+        .map((item) => {
+          if (item.columnKey == 'selection') {
+            return {
+              columnKey: 'selection',
+              type: 'selection',
+              width: 45,
+              align: 'center',
+              fixed: 'left'
+            };
+          } else {
+            return item;
+          }
+        })
+        .filter((item) => item.columnKey != 'action'),
+      objColumns,
+      visible: false,
+      loading: false,
+      active: 0,
+      activeList: '',
+      userOptions: [],
+      form: { ...defaultForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      },
+      type: '',
+      pageType: '1',
+      title: '创建',
+      selection: [],
+      influenceSelection: [],
+      objSelection: [],
+      referenceSelection: []
+    };
+  },
+
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {
+    this.userOptions = [];
+    listAllUserBind().then((data) => {
+      this.userOptions.push(...data);
+    });
+  },
+  methods: {
+    del(selection, list) {
+      let ids = this[selection].map((item) => item.id);
+      this.form[list] = this.form[list].filter(
+        (item) => !ids.includes(item.id)
+      );
+    },
+    async next() {
+      let infoData = await this.$refs.info.getValue();
+      if (!infoData) {
+        return;
+      }
+      this.active++;
+    },
+    prev() {
+      this.active--;
+    },
+    addEquipment(ref, list) {
+      this.activeList = list;
+      this.$refs[ref].open(this.form[list]);
+    },
+    open(type, row, pageType) {
+      this.pageType = pageType;
+      this.visible = true;
+      (this.activeComp = 'main'), (this.type = type);
+      if (type != 'add') {
+        this.form = JSON.parse(JSON.stringify(row));
+        this.form.category = this.form.category.split(',');
+        this.form.type = this.form.type + '';
+        this.$nextTick(() => {
+          this.$refs.info.setValue(this.form);
+        });
+      }
+      this.title = type == 'add' ? '新增' : type == 'edit' ? '修改' : '详情';
+    },
+
+    cancel() {
+      this.active = 0;
+      this.$refs.info?.cancel();
+      this.form = { ...defaultForm() };
+      this.visible = false;
+    },
+    choose(data) {
+      this.form[this.activeList] = data;
+
+      if (this.active == 1) {
+        this.getChangeData();
+      }
+    },
+    getChangeData() {
+      ['problemObjList', 'influenceObjList', 'referenceObjList'].forEach(
+        (key) => {
+          this.form[key] = [];
+        }
+      );
+      //获取关联数据
+      this.form.relationObjList.forEach(async (item) => {
+        let api =
+          item.objType == 1
+            ? questionDetails
+            : item.objType == 2
+            ? requestDetails
+            : noticeDetails;
+        const data = await api(item.id);
+        ['problemObjList', 'influenceObjList', 'referenceObjList'].forEach(
+          (key) => {
+            this.form[key].push(...data[key]);
+          }
+        );
+      });
+    },
+    /* 保存编辑 */
+    async save() {
+      // let data = JSON.parse(JSON.stringify(this.form));
+      let infoData = await this.$refs.info.getValue();
+      if (!infoData) {
+        return;
+      }
+      infoData.category = infoData.category.toString();
+      Object.assign(infoData, {
+        relationObjList: this.form.relationObjList,
+        problemObjList: this.form.problemObjList,
+        influenceObjList: this.form.influenceObjList,
+        referenceObjList: this.form.referenceObjList
+      });
+      this.loading = true;
+
+      let api =
+        this.pageType == 1
+          ? questionSave
+          : this.pageType == 2
+          ? requestSave
+          : noticeSave;
+      api(infoData)
+        .then((res) => {
+          this.loading = false;
+          this.$message.success('成功');
+          this.cancel();
+          this.$emit('refresh');
+        })
+        .catch((e) => {
+          this.loading = false;
+        });
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.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>

+ 405 - 0
src/views/changeManagement/components/data.js

@@ -0,0 +1,405 @@
+export const infoForm = function () {
+    return {
+        "name": "",
+        "problemSourceId": '',  //问题来源
+        "problemSourceCode": "",
+        "problemDescription": "",
+        "accessory": [
+
+        ],//附件
+        "approvalStatus": '', //审批状态
+        "reportUserId": '',  //提出人id
+        "reportUserName": "",
+        "recipientId": '',  //接收人人id
+        "recipientName": "",
+        "status": '',  //状态
+        "processInstanceId": "",  //流程实例id
+        "type": '',  //类型
+        "category": [], //类别
+        "objType": '',  //对象类型
+        changeReason: '',
+        "changeContent": "",
+        "createUserName": ""
+    };
+};
+
+export const questionColumns = [
+    {
+        columnKey: 'selection',
+        type: 'selection',
+        width: 45,
+        align: 'center',
+
+        fixed: 'left', selectable: (row, index) => {
+            return row.approvalStatus == 0;  // 这里是让 id < 3 的禁用,根据自己业务修改
+        },
+    },
+    {
+        columnKey: 'index',
+        label: '序号',
+        type: 'index',
+        width: 55,
+        align: 'center',
+        showOverflowTooltip: true,
+        fixed: 'left'
+    },
+    {
+        prop: 'objType',
+        label: '对象类型',
+        align: 'center',
+        showOverflowTooltip: true,
+        width: 80,
+        fixed: 'left',
+        formatter: (row, column, cellValue) => {
+            return cellValue == 1 ? '问题报告' : cellValue == 2 ? '变更申请' : cellValue == 3 ? '变更通知' : ''
+        }
+
+    },
+    {
+        prop: 'code',
+        label: '编码',
+        align: 'center',
+        slot: 'code',
+        fixed: 'left',
+        minWidth: 180,
+        showOverflowTooltip: true,
+
+    },
+    {
+        prop: 'name',
+        label: '名称',
+        align: 'center',
+        minWidth: 150,
+        showOverflowTooltip: true,
+
+    },
+    {
+        prop: 'problemDescription',
+        label: '问题描述',
+        align: 'center',
+        minWidth: 160,
+        showOverflowTooltip: true,
+    },
+    {
+        prop: 'type',
+        label: '类型',
+        align: 'center',
+        slot: 'type',
+        minWidth: 120,
+        showOverflowTooltip: true,
+    },
+    {
+        prop: 'category',
+        label: '类别',
+        align: 'center',
+        slot: 'category',
+        minWidth: 180,
+        showOverflowTooltip: true,
+    },
+    {
+        prop: 'departmentName',
+        label: '提出部门',
+        align: 'center',
+        minWidth: 130,
+        showOverflowTooltip: true,
+    },
+    {
+        prop: 'reportUserName',
+        label: '提出人',
+        align: 'center',
+        showOverflowTooltip: true,
+        minWidth: 110,
+    },
+    {
+        prop: 'createTime',
+        showOverflowTooltip: true,
+        minWidth: 160,
+        label: '提出时间',
+        align: 'center'
+    },
+
+    {
+        prop: 'recipientName',
+        label: '接收人',
+        showOverflowTooltip: true,
+        minWidth: 120,
+        align: 'center'
+    },
+    {
+        prop: 'approvalStatus',
+        label: '状态',
+        minWidth: 80,
+        align: 'center',
+        slot: 'approvalStatus', formatter: (row, column, cellValue) => {
+            return cellValue == 0 ? '草稿' : cellValue == 1 ? '审核中' : cellValue == 2 ? '审核通过' : ''
+        }
+    },
+    {
+        columnKey: 'action',
+        label: '操作',
+        width: 240,
+        align: 'center',
+        resizable: false,
+        fixed: 'right',
+        slot: 'action',
+        showOverflowTooltip: true
+    }
+];
+export const requestColumns = [
+    {
+        columnKey: 'selection',
+        type: 'selection',
+        width: 45,
+        align: 'center',
+        fixed: 'left', selectable: (row, index) => {
+            return row.approvalStatus == 0;  // 这里是让 id < 3 的禁用,根据自己业务修改
+        },
+    },
+    {
+        columnKey: 'index',
+        label: '序号',
+        type: 'index',
+        width: 55,
+        align: 'center',
+        showOverflowTooltip: true,
+        fixed: 'left'
+    },
+
+    {
+        prop: 'code',
+        label: '编码',
+        align: 'center',
+        slot: 'code',
+
+    },
+    {
+        prop: 'name',
+        label: '名称',
+        align: 'center'
+    },
+    {
+        prop: 'changeReason',
+        label: '变更原因',
+        align: 'center'
+    },
+    {
+        prop: 'feasibilityAnalysis',
+        label: '可行性分析',
+        align: 'center'
+    },
+    {
+        prop: 'type',
+        label: '类型',
+        align: 'center',
+        slot: 'type'
+    },
+    {
+        prop: 'category',
+        label: '类别',
+        align: 'center',
+        slot: 'category'
+    },
+    {
+        prop: 'recipientName',
+        label: '接收人',
+        align: 'center'
+    },
+    {
+        prop: 'problemDescription',
+        label: '描述',
+        align: 'center'
+    },
+    {
+        prop: 'departmentName',
+        label: '申请部门',
+        align: 'center',
+    },
+    {
+        prop: 'reportUserName',
+        label: '申请人',
+        align: 'center'
+    },
+    {
+        prop: 'createTime',
+        label: '提出时间',
+        align: 'center'
+    },
+
+
+    {
+        prop: 'approvalStatus',
+        label: '状态',
+        align: 'center',
+        slot: 'approvalStatus', formatter: (row, column, cellValue) => {
+            return cellValue == 0 ? '草稿' : cellValue == 1 ? '审核中' : cellValue == 2 ? '审核通过' : ''
+        }
+    },
+
+    {
+        columnKey: 'action',
+        label: '操作',
+        width: 240,
+        align: 'center',
+        resizable: false,
+        fixed: 'right',
+        slot: 'action',
+        showOverflowTooltip: true
+    }
+];
+export const noticeColumns = [
+    {
+        columnKey: 'selection',
+        type: 'selection',
+        width: 45,
+        align: 'center',
+        fixed: 'left',
+        selectable: (row, index) => {
+            return row.approvalStatus == 0;  // 这里是让 id < 3 的禁用,根据自己业务修改
+        },
+    },
+    {
+        columnKey: 'index',
+        label: '序号',
+        type: 'index',
+        width: 55,
+        align: 'center',
+        showOverflowTooltip: true,
+        fixed: 'left'
+    },
+
+    {
+        prop: 'code',
+        label: '编码',
+        align: 'center',
+        slot: 'code',
+
+    },
+    {
+        prop: 'name',
+        label: '名称',
+        align: 'center'
+    },
+    {
+        prop: 'changeReason',
+        label: '变更原因',
+        align: 'center'
+    },
+    {
+        prop: 'changeContent',
+        label: '变更内容',
+        align: 'center'
+    },
+    {
+        prop: 'type',
+        label: '类型',
+        align: 'center',
+        slot: 'type'
+    },
+    {
+        prop: 'category',
+        label: '类别',
+        align: 'center',
+        slot: 'category'
+    },
+    {
+        prop: 'recipientName',
+        label: '通知人员',
+        align: 'center'
+    },
+    {
+        prop: 'problemDescription',
+        label: '描述',
+        align: 'center'
+    },
+    {
+        prop: 'createTime',
+        label: '创建时间',
+        align: 'center'
+    },
+    {
+        prop: 'createUserName',
+        label: '创建人',
+        align: 'center'
+    },
+
+
+    {
+        prop: 'approvalStatus',
+        label: '状态',
+        align: 'center',
+        slot: 'approvalStatus',
+        formatter: (row, column, cellValue) => {
+            return cellValue == 0 ? '草稿' : cellValue == 1 ? '审核中' : cellValue == 2 ? '审核通过' : ''
+        }
+    },
+
+    {
+        columnKey: 'action',
+        label: '操作',
+        width: 240,
+        align: 'center',
+        resizable: false,
+        fixed: 'right',
+        slot: 'action',
+        showOverflowTooltip: true
+    }
+];
+export const objColumns = [
+    {
+        columnKey: 'selection',
+        type: 'selection',
+        width: 45,
+        align: 'center',
+        fixed: 'left'
+    },
+    {
+        columnKey: 'index',
+        label: '序号',
+        type: 'index',
+        width: 55,
+        align: 'center',
+        showOverflowTooltip: true,
+        fixed: 'left'
+    },
+    {
+        prop: 'objType',
+        label: '对象类型',
+        align: 'center',
+        formatter: (row, column, cellValue) => {
+            return cellValue == 1 ? '生产计划' : cellValue == 2 ? '生产订单' : cellValue == 3 ? '生产工单' : ''
+        }
+
+    },
+    {
+        prop: 'code',
+        label: '编码',
+        align: 'center',
+        slot: 'code',
+
+    },
+    {
+        prop: 'name',
+        label: '名称',
+        align: 'center'
+    },
+
+    {
+        prop: 'status',
+        label: '状态',
+        align: 'center',
+    }
+    ,
+
+    {
+        prop: 'createUserName',
+        label: '创建人',
+        align: 'center',
+    }
+    ,
+
+    {
+        prop: 'createTime',
+        label: '创建时间',
+        align: 'center',
+    }
+];

+ 176 - 0
src/views/changeManagement/components/noticeInfo.vue

@@ -0,0 +1,176 @@
+<template>
+  <el-form
+    ref="form"
+    :model="form"
+    :rules="rules"
+    label-width="100px"
+    class="create-form"
+  >
+    <el-row :gutter="15">
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="名称:" prop="name">
+          <el-input v-model="form.name" :disabled="disabled" />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="编码:" prop="code">
+          <el-input v-model="form.code" disabled />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="类型:" prop="type">
+          <DictSelection
+            dictName="变更类型"
+            v-model="form.type"
+            :disabled="disabled" 
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="类别:" prop="category">
+          <DictSelection
+            multiple
+            dictName="问题类型"
+            v-model="form.category"
+            :disabled="disabled" 
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="变更原因:">
+          <el-input
+            v-model="form.changeReason"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled" 
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="变更内容:">
+          <el-input
+            v-model="form.changeContent"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled" 
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="描述:">
+          <el-input
+            v-model="form.problemDescription"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled" 
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item
+          label="通知人员"
+          prop="recipientId"
+          style="margin-bottom: 20px"
+        >
+          <el-select
+            v-model="form.recipientId"
+            clearable
+            style="width: 100%"
+            :disabled="disabled" 
+            :filterable="true"
+          >
+            <el-option
+              v-for="item in userOptions"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+              @click.native="userChange(item)"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item prop="accessory" label="相关文档">
+          <fileUpload
+            v-model="form.accessory"
+            module="main"
+            :limit="5"
+            :disabled="disabled" 
+            :showLib="false"
+          />
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+import fileUpload from '@/components/upload/fileUpload';
+import { listAllUserBind } from '@/api/system/user/index';
+import { infoForm } from './data.js';
+
+export default {
+  components: { fileUpload },
+  data() {
+    return {
+      userOptions: [],
+      form: { ...infoForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      }
+    };
+  },
+  props: {
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {
+    this.userOptions = [];
+    listAllUserBind().then((data) => {
+      this.userOptions.push(...data);
+    });
+  },
+  methods: {
+    cancel() {
+      this.form = { ...infoForm() };
+    },
+    setValue(data) {
+      this.form = JSON.parse(JSON.stringify(data));
+    },
+    open(row) {
+      if (row) {
+        this.form = row;
+      }
+    },
+    userChange(item) {
+      this.form.recipientName = item.name;
+    },
+    /* 保存编辑 */
+    async getValue() {
+      const valid = await this.validateFn();
+      this.form.objType = '3';
+      return valid ? JSON.parse(JSON.stringify(this.form)) : '';
+    },
+    validateFn() {
+      return new Promise((resolve, reject) => {
+        this.$refs.form.validate((valid) => {
+          resolve(valid);
+        });
+      });
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 252 - 0
src/views/changeManagement/components/objEquipmentDialog.vue

@@ -0,0 +1,252 @@
+<template>
+  <el-dialog
+    title="问题对象"
+    :visible.sync="equipmentdialog"
+    :before-close="handleClose"
+    :close-on-click-modal="true"
+    :close-on-press-escape="false"
+    append-to-body
+    width="60%"
+  >
+    <el-row>
+      <el-col :span="6">
+        <el-form
+          label-width="90px"
+          style="padding: 10px"
+          class="ele-form-search"
+          @keyup.enter.native="search"
+          @submit.native.prevent
+        >
+          <el-row>
+            <el-col :span="24">
+              <el-form-item label="批号:">
+                <el-input
+                  v-model="where.batchNo"
+                  placeholder="请输入"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="编号:">
+                <el-input v-model="where.code" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="名称:">
+                <el-input v-model="where.name" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="产品编码:">
+                <el-input
+                  v-model="where.productCode"
+                  placeholder="请输入"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+
+            <el-col :span="24">
+              <el-form-item label="产品名称:">
+                <el-input
+                  v-model="where.productName"
+                  placeholder="请输入"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="牌号:">
+                <el-input
+                  v-model="where.brandNo"
+                  placeholder="请输入"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="型号:">
+                <el-input v-model="where.model" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <el-form-item label="规格:">
+                <el-input v-model="where.specification" placeholder="请输入"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="24">
+              <div class="ele-form-actions" style="display:flex;justify-content: end;margin-top: 15px;" >
+                <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-col>
+          </el-row> </el-form
+      ></el-col>
+      <el-col :span="18"
+        ><div>
+          <div class="switch">
+            <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>
+        </div>
+        <productionPlan
+          v-if="activeComp == 'productionPlan'"
+          ref="productionPlan"
+        />
+        <workOrder v-if="activeComp == 'workOrder'" ref="workOrder" />
+        <produceOrder v-if="activeComp == 'produceOrder'" ref="produceOrder" />
+        <div>
+          <ele-pro-table
+            ref="table"
+            :columns="objColumns"
+            :datasource="tableList"
+            :selection.sync="selection"
+            row-key="id"
+            height="20vh"
+            :needPage="false"
+          >
+            <template v-slot:toolbar>
+              <el-button type="primary" size="small" @click="add"
+                >添加</el-button
+              >
+              <el-button size="small" @click="del">移除</el-button></template
+            >
+          </ele-pro-table>
+        </div></el-col
+      >
+    </el-row>
+
+    <template v-slot:footer>
+      <el-button type="primary" size="small" @click="selected">确认</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+// 默认表单数据
+const defaultWhere = {
+  code: '',
+  name: '',
+  productCode: '',
+  productName: '',
+  brandNo: '',
+  model: '',
+  batchNo:"",
+  specification:''
+};
+import { objColumns } from './data.js';
+import dictMixins from '@/mixins/dictMixins';
+import productionPlan from './productionPlan';
+import workOrder from './workOrder';
+import produceOrder from './produceOrder';
+export default {
+  components: { productionPlan, workOrder, produceOrder },
+  mixins: [dictMixins],
+
+  data() {
+    return {
+      activeComp: 'productionPlan',
+      where: {...defaultWhere},
+      tabOptions: [
+        { key: 'productionPlan', name: '生产计划' },
+        { key: 'workOrder', name: '生产订单' },
+        { key: 'produceOrder', name: '生产工单' }
+      ],
+      objColumns: objColumns,
+      equipmentdialog: false,
+      tableList: [],
+      selection: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    open(data) {
+      this.tableList = (data && JSON.parse(JSON.stringify(data))) || [];
+      this.equipmentdialog = true;
+    },
+
+    reload() {
+      this.$refs.equiTable.reload();
+    },
+    handleClose() {
+      this.equipmentdialog = false;
+    },
+    reset() {
+      this.reload();
+    },
+    add() {
+      const planStatus = [
+        { label: '待发布', value: '2' },
+        { label: '发布失败', value: '3' },
+        { label: '待生产', value: '4' },
+        { label: '生产中', value: '5' },
+        { label: '已完成', value: '6' },
+        { label: '已延期', value: '7' },
+        { label: '待下达', value: '8' }
+      ];
+      if (this.$refs[this.activeComp].getValue().length == 0) {
+        return;
+      }
+      let ids = this.tableList.map((item) => item.id);
+      let getValue = this.$refs[this.activeComp]
+        .getValue()
+        .filter((item) => !ids.includes(item.id)); //去重
+      getValue.forEach((element) => {
+        element.status = planStatus.find(
+          (item) => item.value == element.status
+        ).label;
+      });
+      this.tableList.push(...getValue);
+    },
+    del() {
+      let ids = this.selection.map((item) => item.id);
+      this.tableList = this.tableList.filter((item) => !ids.includes(item.id));
+    },
+    // 选择
+    selected() {
+      this.$emit('choose', JSON.parse(JSON.stringify(this.tableList)));
+      this.handleClose();
+    },
+    /* 搜索 */
+    search() {
+      this.$refs[this.activeComp].reload(this.where)
+    },
+    /*  重置 */
+    reset() {
+      this.where = { ...defaultWhere };
+      this.search();
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+:deep(.el-row) {
+  margin-bottom: 20px;
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+</style>
+
+

+ 163 - 0
src/views/changeManagement/components/order-search.vue

@@ -0,0 +1,163 @@
+<!-- 搜索表单 -->
+<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="类型:">
+            <DictSelection
+              dictName="异常类型"
+              clearable
+              v-model="where.type"
+            ></DictSelection>
+        </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.name"
+            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%" clearable>
+            <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.createTimeUserName"
+            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 = {
+      type: '',
+      name:'',
+      code:'',
+      status: '',
+      createTime: [],
+      deptIds:'',
+    };
+    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>

+ 233 - 0
src/views/changeManagement/components/produceOrder.vue

@@ -0,0 +1,233 @@
+<template>
+  <ele-pro-table
+    ref="equiTable"
+    :columns="columns"
+    :datasource="datasource"
+    :selection.sync="selection"
+    :current.sync="current"
+    highlight-current-row
+    row-key="id"
+    height="20vh"
+  >
+  </ele-pro-table>
+</template>
+
+<script>
+import { produceOrder } from '@/api/aps/index.js';
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 1 //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',
+          showOverflowTooltip: true,
+          minWidth: 180,
+          fixed: 'left'
+        },
+
+        {
+          prop: 'productionPlanCode',
+          label: '计划编号',
+          align: 'center',
+          minWidth: 180
+        },
+        {
+          prop: 'planType',
+          label: '计划类型',
+          align: 'center',
+          minWidth: 110,
+          showOverflowTooltip: true,
+
+          formatter: (row) => {
+            const obj = this.planType.find((i) => i.value == row.planType);
+            return obj && obj.label;
+          }
+        },
+        {
+          prop: 'produceRoutingName',
+          label: '工艺路线',
+          showOverflowTooltip: true,
+          align: 'center',
+          minWidth: 120
+        },
+        {
+          prop: 'productCode',
+          minWidth: 180,
+          label: '产品编号',
+          showOverflowTooltip: true,
+          align: 'center'
+        },
+        {
+          prop: 'productName',
+          label: '产品名称',
+          showOverflowTooltip: true,
+          minWidth: 150,
+
+          align: 'center'
+        },
+        {
+          prop: 'brandNo',
+          label: '牌号',
+          showOverflowTooltip: true,
+          minWidth: 100,
+
+          align: 'center'
+        },
+        {
+          prop: 'specification',
+          label: '规格',
+          showOverflowTooltip: true,
+          minWidth: 130,
+
+          align: 'center'
+        },
+        {
+          prop: 'model',
+          label: '型号',
+          minWidth: 130,
+          showOverflowTooltip: true,
+
+          align: 'center'
+        },
+        {
+          prop: 'batchNo',
+          label: '批号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'priority',
+          label: '优先级',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 90,
+          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',
+          minWidth: 110,
+
+          showOverflowTooltip: true
+        }
+      ],
+      categoryLevelId: null,
+      code: null,
+      selection: [],
+      ids: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    datasource({ page, where, limit }) {
+      return produceOrder({
+        ...where,
+        pageNum: page,
+        size: limit
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() =>
+        this.$refs.equiTable.reload({ page: 1, limit: 10, where })
+      );
+    },
+    // 选择
+    getValue() {
+      this.selection.forEach((item) => {
+        item['objType'] = 3;
+      });
+      return JSON.parse(JSON.stringify(this.selection));
+    }
+  }
+};
+</script>

+ 200 - 0
src/views/changeManagement/components/productionPlan.vue

@@ -0,0 +1,200 @@
+<template>
+  <ele-pro-table
+    ref="equiTable"
+    :columns="columns"
+    :datasource="datasource"
+    :selection.sync="selection"
+    :current.sync="current"
+    highlight-current-row
+    row-key="id"
+    height="20vh"
+  >
+  </ele-pro-table>
+</template>
+
+<script>
+import { getList } from '@/api/aps/index.js';
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 1 //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,
+          fixed: 'left'
+        },
+        {
+          prop: 'productCode',
+          label: '产品编码',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 180
+        },
+        {
+          prop: 'productName',
+          label: '产品名称',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 150
+        },
+
+        {
+          prop: 'brandNo',
+          label: '牌号',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 80
+        },
+        {
+          prop: 'batchNo',
+          label: '批号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'model',
+          label: '型号',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 100
+        },
+
+        {
+          prop: 'priority',
+          label: '优先级',
+          align: 'center',
+          minWidth: 90,
+          showOverflowTooltip: true,
+          sortable: 'custom'
+        },
+
+        {
+          prop: 'productNum',
+          label: '计划数量',
+          showOverflowTooltip: true,
+          align: 'center',
+          minWidth: 90
+        },
+        {
+          prop: 'productWeight',
+          label: '计划重量',
+          minWidth: 90,
+
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'requiredFormingNum',
+          label: '要求生产数量',
+          minWidth: 120,
+
+          align: 'center',
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'newSumOrderWeight',
+          label: '要求生产重量',
+          minWidth: 120,
+
+          align: 'center',
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'reqMoldTime',
+          label: '要求生产日期',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 120
+        },
+
+        {
+          prop: 'orderType',
+          label: '计划类型',
+          align: 'center',
+          minWidth: 80,
+          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
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() =>
+        this.$refs.equiTable.reload({ page: 1, limit: 10, where })
+      );
+    },
+    // 选择
+    getValue() {
+      this.selection.forEach((item) => {
+        item['objType'] = 1;
+      });
+      return JSON.parse(JSON.stringify(this.selection));
+    }
+  }
+};
+</script>
+

+ 149 - 0
src/views/changeManagement/components/questionInfo.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-form
+    ref="form"
+    :model="form"
+    :rules="rules"
+    label-width="100px"
+    class="create-form"
+  >
+    <el-row :gutter="15">
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="名称:" prop="name">
+          <el-input v-model="form.name"  :disabled="disabled" />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="编码:" prop="code">
+          <el-input v-model="form.code" disabled />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="问题描述:">
+          <el-input
+            v-model="form.problemDescription"
+            type="textarea"
+            :rows="2"
+            :disabled="disabled" 
+          />
+        </el-form-item>
+      </el-col>
+      <el-col v-bind="styleResponsive ? { lg: 24, md: 24 } : { span: 24 }">
+        <el-form-item label="类别:" prop="category">
+          <DictSelection
+            multiple
+            dictName="问题类型"
+            v-model="form.category"
+            :disabled="disabled" 
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="24">
+        <el-form-item
+          label="接收人"
+          prop="recipientId"
+          style="margin-bottom: 20px"
+        >
+          <el-select
+            v-model="form.recipientId"
+            clearable
+            style="width: 100%"
+            :filterable="true"
+            :disabled="disabled" 
+          >
+            <el-option
+              v-for="item in userOptions"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+              @click.native="userChange(item)"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item prop="accessory" label="相关文档">
+          <fileUpload
+            v-model="form.accessory"
+            module="main"
+            :limit="5"
+            :disabled="disabled" 
+            :showLib="false"
+          />
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+
+<script>
+import fileUpload from '@/components/upload/fileUpload';
+import { listAllUserBind } from '@/api/system/user/index';
+import { infoForm } from './data.js';
+
+export default {
+  components: { fileUpload },
+  data() {
+    return {
+
+      userOptions: [],
+      form: { ...infoForm() },
+      // 表单验证规则
+      rules: {
+        type: [{ required: true, message: '请选择', trigger: 'change' }],
+        name: [{ required: true, message: '请选择', trigger: 'change' }],
+        relationType: [{ required: true, message: '请选择', trigger: 'change' }]
+      },
+
+    
+    };
+  },
+  props: {
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  computed: {
+    // 是否开启响应式布局
+    styleResponsive() {
+      return this.$store.state.theme.styleResponsive;
+    }
+  },
+  created() {
+    this.userOptions = [];
+    listAllUserBind().then((data) => {
+      this.userOptions.push(...data);
+    });
+  },
+  methods: {
+    cancel() {
+      this.form = { ...infoForm() };
+    },
+    open(row) {
+      if (row) {
+        this.form = row;
+      }
+    },
+    userChange(item) {
+      this.form.recipientName = item.name;
+    },
+    setValue(data){
+      this.form=JSON.parse(JSON.stringify(data))
+    },
+    /* 保存编辑 */
+    async getValue() {
+      const valid = await this.validateFn()
+      this.form.objType='1'
+      return valid?JSON.parse(JSON.stringify(this.form)):''
+    },
+    validateFn() {
+      return new Promise((resolve, reject) => {
+        this.$refs.form.validate(valid=>{
+          resolve(valid)
+      });
+      })
+    }
+  }
+};
+</script>

+ 126 - 0
src/views/changeManagement/components/tableLIst.vue

@@ -0,0 +1,126 @@
+<template>
+  <div>
+    <div class="switch">
+      <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>
+    <!-- <order-search @search="reload" ref="searchRef" v-if="type==1"> </order-search> -->
+    <ele-pro-table
+      ref="table"
+      :columns="columns"
+      :datasource="datasource"
+      :selection.sync="selection"
+      row-key="id"
+      height="20vh"
+    >
+      <template v-slot:category="{ row }">
+        <span v-for="item in row.category.split(',')" :key="item">
+          {{ getDictValue('问题类型', item) }}</span
+        >
+      </template>
+      <template v-slot:type="{ row }">
+        <span>{{ getDictValue('变更类型', row.type + '') }}</span>
+      </template>
+    </ele-pro-table>
+  </div>
+</template>
+  
+  <script>
+// import OrderSearch from '../components/order-search.vue';
+import dictMixins from '@/mixins/dictMixins';
+import { questionColumns, requestColumns, noticeColumns } from './data.js';
+import { getQuestionList } from '@/api/changeManagement/question';
+import { getRequestList } from '@/api/changeManagement/request';
+import { getNoticeList } from '@/api/changeManagement/notice';
+export default {
+  components: {},
+
+  mixins: [dictMixins],
+  data() {
+    return {
+      activeComp: 'question',
+      tabOptions: [
+        { key: 'question', name: '问题报告' },
+        { key: 'request', name: '变更申请' },
+        { key: 'notice', name: '变更通知' }
+      ],
+      loading: false,
+      selection: []
+    };
+  },
+  computed: {
+    // 表格列配置
+    columns() {
+      return (
+        this.activeComp == 'question'
+          ? questionColumns
+          : this.activeComp == 'request'
+          ? requestColumns
+          : noticeColumns
+      ).map((item) => {
+          if (item.columnKey == 'selection') {
+            return {
+              columnKey: 'selection',
+              type: 'selection',
+              width: 45,
+              align: 'center',
+              fixed: 'left'
+            };
+          } else {
+            return item;
+          }
+        })
+        .filter((item) => item.columnKey != 'action' && item.prop != 'objType');
+    }
+  },
+  watch: {
+    activeComp() {
+      this.$nextTick(() => {
+        this.$refs.table.reload({ page: 1 });
+      });
+    }
+  },
+  created() {
+    this.requestDict('问题类型');
+  },
+  filters: {},
+  methods: {
+    /* 表格数据源 */
+    datasource({ page, limit, where }) {
+      let api =
+        this.activeComp == 'question'
+          ? getQuestionList
+          : this.activeComp == 'request'
+          ? getRequestList
+          : getNoticeList;
+      return api({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+    },
+    getValue() {
+      this.selection.forEach((item) => {
+        item['objType'] =
+          this.activeComp == 'question'
+            ? 1
+            : this.activeComp == 'request'
+            ? 2
+            : 3;
+      });
+      return JSON.parse(JSON.stringify(this.selection));
+    }
+  }
+};
+</script>
+  

+ 211 - 0
src/views/changeManagement/components/workOrder.vue

@@ -0,0 +1,211 @@
+<template>
+  <ele-pro-table
+    ref="equiTable"
+    :columns="columns"
+    :datasource="datasource"
+    :selection.sync="selection"
+    :current.sync="current"
+    highlight-current-row
+    row-key="id"
+    height="20vh"
+  >
+  </ele-pro-table>
+</template>
+
+<script>
+import { workOrder } from '@/api/aps/index.js';
+
+export default {
+  components: {},
+  props: {
+    selectList: Array,
+    type: {
+      default: 1 //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: 180,
+          prop: 'code',
+          showOverflowTooltip: true,
+          fixed: 'left'
+        },
+        {
+          prop: 'productionPlanCode',
+          label: '计划编号',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 180
+        },
+        {
+          prop: 'produceRoutingName',
+          label: '工艺路线',
+          minWidth: 130,
+          showOverflowTooltip: true,
+
+          align: 'center'
+        },
+        {
+          prop: 'productCode',
+          label: '产品编码',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 180
+        },
+        {
+          prop: 'productName',
+          label: '产品名称',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 120
+        },
+        {
+          prop: 'brandNo',
+          label: '牌号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'batchNo',
+          label: '批号',
+          align: 'center',
+          minWidth: 100,
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'model',
+          label: '型号',
+          minWidth: 120,
+          showOverflowTooltip: true,
+
+          align: 'center'
+        },
+
+        {
+          prop: 'priority',
+          label: '优先级',
+          align: 'center',
+          minWidth: 90,
+          showOverflowTooltip: true,
+          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',
+          minWidth: 110,
+
+          showOverflowTooltip: true
+        },
+
+        {
+          prop: 'simpleName',
+          label: '客户简称',
+          align: 'center',
+          minWidth: 120,
+
+          showOverflowTooltip: true
+        }
+      ],
+      categoryLevelId: null,
+      code: null,
+      selection: []
+    };
+  },
+
+  watch: {},
+  methods: {
+    datasource({ page, where, limit }) {
+      return workOrder({
+        ...where,
+        pageNum: page,
+        size: limit
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() =>
+        this.$refs.equiTable.reload({ page: 1, limit: 10, where })
+      );
+    },
+    // 选择
+    getValue() {
+      this.selection.forEach((item) => {
+        item['objType'] = 2;
+      });
+      return JSON.parse(JSON.stringify(this.selection));
+    }
+  }
+};
+</script>
+

+ 105 - 0
src/views/changeManagement/index.vue

@@ -0,0 +1,105 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never">
+      <div class="switch">
+        <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>
+      <div class="main">
+        <div v-if="activeComp == 'question'">
+          <question ></question>
+        </div>
+        <div v-if="activeComp == 'request'">
+          <request ></request>
+        </div>
+        <div v-if="activeComp == 'notice'">
+          <notice ></notice>
+        </div>
+        <!-- <div v-if="activeComp == 'entrustedReceive'">
+          <entrustedReceive></entrustedReceive>
+        </div>
+        <div v-if="activeComp == 'returnorder'" class="returnorder">
+          <return-goods></return-goods>
+        </div>
+     -->
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+import question from './question/index.vue';
+import request from './request/index.vue';
+import notice from './notice/index.vue';
+
+import dictMixins from '@/mixins/dictMixins';
+
+export default {
+  mixins: [dictMixins],
+
+  components: {
+    question,request,notice
+  },
+  data() {
+    return {
+      activeComp: 'question',
+      tabOptions: [
+        { key: 'question', name: '问题报告' },
+        { key: 'request', name: '变更申请' },
+        { key: 'notice', name: '变更通知' }
+      ]
+    };
+  },
+  computed: {},
+  created() {
+    this.requestDict('问题类型');
+    this.requestDict('变更类型');
+  },
+  methods: {}
+};
+</script>
+
+<style lang="scss" scoped>
+:deep .el-card__body {
+  padding: 0;
+}
+
+:deep(.el-link--inner) {
+  margin-left: 0px !important;
+}
+
+.sys-organization-list {
+  height: calc(100vh - 264px);
+  box-sizing: border-box;
+  border-width: 1px;
+  border-style: solid;
+  overflow: auto;
+}
+
+.sys-organization-list :deep(.el-tree-node__content) {
+  height: 40px;
+
+  & > .el-tree-node__expand-icon {
+    margin-left: 10px;
+  }
+}
+
+.el-dropdown-link {
+  cursor: pointer;
+  color: var(--color-primary-5);
+}
+
+.el-icon-arrow-down {
+  font-size: 12px;
+}
+</style>

+ 162 - 0
src/views/changeManagement/notice/index.vue

@@ -0,0 +1,162 @@
+<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"
+        height="calc(100vh - 480px)"
+      >
+        <template v-slot:category="{ row }">
+          <span v-for="item in row.category.split(',')" :key="item">
+            {{ getDictValue('问题类型', item) }}</span
+          >
+        </template>
+        <template v-slot:type="{ row }">
+          <span>{{ getDictValue('变更类型', row.type + '') }}</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>
+
+        </template>
+
+        <template v-slot:action="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-truck"
+            @click="open('edit', row)"
+            v-if="row.approvalStatus==0"
+
+          >
+            编辑
+          </el-link>
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除吗?"
+            v-if="row.approvalStatus==0"
+            @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"
+            @click="submit(row.id)"
+            v-if="row.approvalStatus==0"
+
+          >
+            提交
+          </el-link>
+        </template>
+      </ele-pro-table>
+    </el-card>
+    <Create ref="create" @refresh="reload" />
+  </div>
+</template>
+  
+  <script>
+import OrderSearch from '../components/order-search.vue';
+import dictMixins from '@/mixins/dictMixins';
+import Create from '../components/create.vue';
+import { noticeColumns } from '../components/data.js';
+
+import { getNoticeList, remove,submit } from '@/api/changeManagement/notice';
+
+export default {
+  components: {
+    OrderSearch,
+    Create
+  },
+
+  mixins: [dictMixins],
+  data() {
+    return {
+      loading: false,
+      selection: []
+    };
+  },
+  computed: {
+    // 表格列配置
+    columns() {
+      return noticeColumns;
+    }
+  },
+  created() {},
+  filters: {},
+  methods: {
+    /* 表格数据源 */
+    datasource({ page, limit, where }) {
+      return getNoticeList({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+    },
+    open(type, row) {
+      this.$refs.create.open(type, row, 3);
+    },
+    remove(id) {
+      let ids = id || this.selection.map((item) => item.id);
+      remove(ids).then((res) => {
+        this.$message.success('删除' + res.message);
+
+        this.reload();
+      });
+    },
+
+    submit(id) {
+      submit({ businessId: id }).then((res) => {
+        this.$message.success('提交' + res.message);
+        this.reload();
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() => {
+        this.$refs.table.reload({ page: 1, where });
+      });
+    }
+  }
+};
+</script>
+  

+ 170 - 0
src/views/changeManagement/question/index.vue

@@ -0,0 +1,170 @@
+<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"
+        height="calc(100vh - 480px)"
+      >
+        <template v-slot:category="{ row }">
+          <span v-for="item in row.category.split(',')" :key="item">
+            {{ getDictValue('问题类型', item) }}</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-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"
+
+            @click="open('edit', row)"
+          >
+            编辑
+          </el-link>
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除吗?"
+            v-if="row.approvalStatus==0"
+
+            @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==0"
+
+            @click="submit(row.id)"
+          >
+            提交
+          </el-link>
+        </template>
+      </ele-pro-table>
+    </el-card>
+    <Create ref="create" @refresh="reload" />
+  </div>
+</template>
+  
+  <script>
+import OrderSearch from '../components/order-search.vue';
+import dictMixins from '@/mixins/dictMixins';
+import Create from '../components/create.vue';
+import { questionColumns } from '../components/data.js';
+
+import { getQuestionList, remove ,submit} from '@/api/changeManagement/question';
+
+export default {
+  components: {
+    OrderSearch,
+    Create
+  },
+
+  mixins: [dictMixins],
+  data() {
+    return {
+      loading: false,
+      selection: []
+    };
+  },
+  computed: {
+    // 表格列配置
+    columns() {
+      return questionColumns.filter(
+        (item) => !['objType', 'type'].includes(item.prop)
+      );
+    }
+  },
+  created() {},
+  methods: {
+    /* 表格数据源 */
+    datasource({ page, limit, where }) {
+      return getQuestionList({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+    },
+    open(type, row) {
+      this.$refs.create.open(type, row, 1);
+    },
+    remove(id) {
+      let ids = id || this.selection.map((item) => item.id);
+      remove(ids).then((res) => {
+        this.$message.success('删除' + res.message);
+        this.reload();
+      });
+    },
+
+    submit(id) {
+      submit({ businessId: id }).then((res) => {
+        this.$message.success('提交' + res.message);
+        this.reload();
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() => {
+        this.$refs.table.reload({ page: 1, where });
+      });
+    }
+  }
+};
+</script>
+  

+ 162 - 0
src/views/changeManagement/request/index.vue

@@ -0,0 +1,162 @@
+<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"
+        height="calc(100vh - 480px)"
+      >
+        <template v-slot:category="{ row }">
+          <span v-for="item in row.category.split(',')" :key="item">
+            {{ getDictValue('问题类型', item) }}</span
+          >
+        </template>
+        <template v-slot:type="{ row }">
+          <span>{{ getDictValue('变更类型', row.type + '') }}</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>
+        </template>
+
+        <template v-slot:action="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            icon="el-icon-truck"
+            v-if="row.approvalStatus==0"
+
+            @click="open('edit', row)"
+          >
+            编辑
+          </el-link>
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除吗?"
+            v-if="row.approvalStatus==0"
+            
+            @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"
+            @click="submit(row.id)"
+            v-if="row.approvalStatus==0"
+
+          >
+            提交
+          </el-link>
+        </template>
+      </ele-pro-table>
+    </el-card>
+    <Create ref="create" @refresh="reload" />
+  </div>
+</template>
+  
+  <script>
+import OrderSearch from '../components/order-search.vue';
+import dictMixins from '@/mixins/dictMixins';
+import Create from '../components/create.vue';
+import { requestColumns } from '../components/data.js';
+import { getRequestList, remove,submit } from '@/api/changeManagement/request';
+
+export default {
+  components: {
+    OrderSearch,
+    Create
+  },
+
+  mixins: [dictMixins],
+  data() {
+    return {
+      loading: false,
+      selection: []
+    };
+  },
+  computed: {
+    // 表格列配置
+    columns() {
+      return requestColumns;
+    }
+  },
+  created() {},
+  methods: {
+    /* 表格数据源 */
+    datasource({ page, limit, where }) {
+      return getRequestList({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+    },
+    open(type, row) {
+      this.$refs.create.open(type, row, 2);
+    },
+    remove(id) {
+      let ids = id || this.selection.map((item) => item.id);
+      remove(ids).then((res) => {
+        this.$message.success('删除' + res.message);
+
+        this.reload();
+      });
+    },
+
+    submit(id) {
+      submit({
+        businessId:id,
+      }).then((res) => {
+        this.$message.success('提交' + res.message);
+        this.reload();
+      });
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$nextTick(() => {
+        this.$refs.table.reload({ page: 1, where });
+      });
+    }
+  }
+};
+</script>
+