Переглянути джерело

Merge branch 'master' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-wt

liujt 1 рік тому
батько
коміт
a9a371109d

+ 16 - 1
src/BIZComponents/inventoryTableDetails.vue

@@ -148,6 +148,11 @@
             unitIdKey: 'saleUnitId'
           };
         }
+      },
+      //是否显示生产要求
+      isProductionRequirements: {
+        type: Boolean,
+        default: false
       }
     },
     data() {
@@ -511,9 +516,19 @@
           {
             minWidth: 160,
             prop: 'productionCodes',
-            label: '生产编码',
+            label: '生产编号',
             align: 'center'
           },
+          this.isProductionRequirements
+            ? {
+                minWidth: 280,
+                prop: 'productionRequirements',
+                label: '生产要求',
+                align: 'center'
+              }
+            : {
+                width: 1
+              },
           {
             minWidth: 240,
             prop: 'taskName',

+ 1 - 0
src/BIZComponents/processSubmitDialog/components/SHGDListDialog.vue

@@ -232,6 +232,7 @@ export default {
       const params = {
         pageNum: page,
         size: limit,
+        isDispatch:'0',
         ...where
       };
       return getSalesWorkOrder(params).finally(() => {

+ 611 - 598
src/BIZComponents/processSubmitDialog/processSubmitDialog.vue

@@ -400,7 +400,7 @@
       ref="parentRef"
       @changeParent="handleConcatConfirm"
     ></parentList>
-    
+
     <SHGDListDialog
       ref="SHGDListDialogRef"
       @changeParent="getSHGDData"
@@ -408,645 +408,658 @@
   </ele-modal>
 </template>
 <script>
-import {
-  getModelPage,
-  getProcessDefinitionBpmnXML,
-  getProcessDefinitionInfo,
-  getTaskAssignRuleList,
-  listAllUserBind,
-  listSimpleUserGroups,
-  processInstanceCreateAPI
-} from './api';
-import { treeClassifyCodeEnum } from '@/enum/dict';
-import { listRoles } from '@/api/system/role';
-import { listOrganizations } from '@/api/system/organization';
-import dictMixins from '@/mixins/dictMixins';
-import { getByCode } from '@/api/system/dictionary-data';
-import { getGroupUserTree, getProduceTreeByCode } from '@/api/main';
-import visibilityRangeDialog from './visibilityRangeDialog.vue';
-import { getModel } from '@/api/bpm/model';
-import { getProcessDefinitionList } from '@/api/bpm/definition';
-import { getToken } from '@/utils/token-util';
-import { mapGetters } from 'vuex';
-import staffSelection from '@/components/staffSelection/staffSelection.vue';
-import { topLevel1, topLevel2, topLevel3 } from '@/enum/dict';
-import dayjs from 'dayjs';
-import parentList from './components/parentList.vue';
-import { number } from 'echarts';
-import { del } from 'vue';
-import businessComponent from './components/businessComponent.vue';
-import useSealComponent from './components/useSealComponent.vue';
-import useQualificationComponent from './components/useQualificationComponent.vue';
-import productSpecificationComponent from './components/productSpecificationComponent.vue';
-import eventComponent from './components/eventComponent.vue';
-import reissueComponent from './components/reissueComponent.vue';
-import SHGDListDialog from './components/SHGDListDialog.vue';
-export default {
-  name: 'processSubmitDialog',
-  components: {
-    visibilityRangeDialog,
-    staffSelection,
-    parentList,
-    businessComponent,
-    useSealComponent,
-    useQualificationComponent,
-    productSpecificationComponent,
-    eventComponent,
-    reissueComponent,
-    SHGDListDialog
-  },
-  mixins: [dictMixins],
-  props: {
-    processSubmitDialogFlag: {
-      type: Boolean,
-      default: false
-    }
-  },
-  watch: {
-    filterText(val) {
-      this.$refs.tree.filter(val);
-    }
-  },
-  data() {
-    return {
-      visibilityRangeDialogFlag: false,
-      isRight: false,
-      jsonData: {},
-      form: {
-        LCFL: '',
-        FQLC: '',
-        processDefinitionId: '',
-        name: '',
-        businessId: '',
-        noticeScope: [],
-        formJson: {},
-        valueJson: {},
-        businessKey: ''
-      },
-      title: '',
-      active: 0,
-      bpmnXML: null,
-      filterText: null,
-      treeList: [],
-      treeData: [],
-      defaultProps: {
-        children: 'children',
-        label: 'name'
-      },
-      LCFLList: [],
-      processList: [],
-      datasource: [],
-      roleOptions: [],
-      deptOptions: [],
-      deptTreeOptions: [],
-      postOptions: [],
-      userOptions: [],
-      userGroupOptions: [],
-      dictList: {},
-      rules: {},
-      editForm: {
-        start: '',
-        end: '',
-        days: ''
-      },
-      componentRef: [
-        'blank_business_component',
-        'blank_use_seal',
-        'blank_use_qualification',
-        'blank_product_specification',
-        'blank_event_component',
-        'blank_reissue_component'
-      ]
-    };
-  },
-  computed: {
-    ...mapGetters(['user']),
-    modelWidth() {
-      let width =
-        this.jsonData.config?.platform && this.jsonData.config.platform === 'pc'
-          ? 1100
-          : 450;
-      if (this.isRight) {
-        return width + 350 + 'px';
-      } else {
-        return width + 'px';
-      }
-    }
-  },
-  async created() {
-    let typeObj = await getProduceTreeByCode(
-      treeClassifyCodeEnum['PROCESSTYPE']
-    );
-    //  await this.getTreeData();
-    this.LCFLList = typeObj[0].children;
-
-    // 获得角色列表
-    this.roleOptions = [];
-    listRoles({
-      current: 1,
-      size: 9999
-    }).then((data) => {
-      this.roleOptions.push(...data.list);
-    });
-    // 获得部门列表
-    this.deptOptions = [];
-    this.deptTreeOptions = [];
-    listOrganizations().then((data) => {
-      this.deptOptions.push(...data);
-      this.deptTreeOptions.push(...this.handleTree(data, 'id'));
-    });
-    // 获得岗位列表 暂无岗位概念
-    this.postOptions = [];
-    /*listSimplePosts().then(response => {
-this.postOptions.push(...response.data);
-});*/
-    // 获得用户列表
-    this.userOptions = [];
-    listAllUserBind().then((data) => {
-      this.userOptions.push(...data);
-    });
-    // 获得用户组列表
-    this.userGroupOptions = [];
-    listSimpleUserGroups().then((response) => {
-      this.userGroupOptions.push(...response);
-    });
+  import {
+    getModelPage,
+    getProcessDefinitionBpmnXML,
+    getProcessDefinitionInfo,
+    getTaskAssignRuleList,
+    listAllUserBind,
+    listSimpleUserGroups,
+    processInstanceCreateAPI
+  } from './api';
+  import { treeClassifyCodeEnum } from '@/enum/dict';
+  import { listRoles } from '@/api/system/role';
+  import { listOrganizations } from '@/api/system/organization';
+  import dictMixins from '@/mixins/dictMixins';
+  import { getByCode } from '@/api/system/dictionary-data';
+  import { getGroupUserTree, getProduceTreeByCode } from '@/api/main';
+  import visibilityRangeDialog from './visibilityRangeDialog.vue';
+  import { getModel } from '@/api/bpm/model';
+  import { getProcessDefinitionList } from '@/api/bpm/definition';
+  import { getToken } from '@/utils/token-util';
+  import { mapGetters } from 'vuex';
+  import staffSelection from '@/components/staffSelection/staffSelection.vue';
+  import { topLevel1, topLevel2, topLevel3 } from '@/enum/dict';
+  import dayjs from 'dayjs';
+  import parentList from './components/parentList.vue';
+  import { number } from 'echarts';
+  import { del } from 'vue';
+  import businessComponent from './components/businessComponent.vue';
+  import useSealComponent from './components/useSealComponent.vue';
+  import useQualificationComponent from './components/useQualificationComponent.vue';
+  import productSpecificationComponent from './components/productSpecificationComponent.vue';
+  import eventComponent from './components/eventComponent.vue';
+  import reissueComponent from './components/reissueComponent.vue';
+  import SHGDListDialog from './components/SHGDListDialog.vue';
+  import { parameterGetByCode } from '@/api/main/index.js';
 
-    //this.dictEnum['工作流任务分配自定义脚本']
-    await this.getDictList(this.dictEnum['工作流任务分配自定义脚本']);
-    await this.getDictList(this.dictEnum['工种类型']);
-  },
-  mounted() {
-    //this.isRight = false
-  },
-  methods: {
-    async addNewRow(key) {
-      console.log(key);
-      let data = await this.$refs.generateForm.getData(false);
-      data[key].push({
-        price: '',
-        remark: ''
-      });
-      this.$refs.generateForm.setData({
-        key: data[key]
-      });
+  export default {
+    name: 'processSubmitDialog',
+    components: {
+      visibilityRangeDialog,
+      staffSelection,
+      parentList,
+      businessComponent,
+      useSealComponent,
+      useQualificationComponent,
+      productSpecificationComponent,
+      eventComponent,
+      reissueComponent,
+      SHGDListDialog
     },
-    async delNewRow(key, index) {
-      let data = await this.$refs.generateForm.getData(false);
-      data[key] = data[key].filter((item, index1) => index1 != index);
-      this.$refs.generateForm.setData({
-        [key]: data[key]
-      });
-      this.changePrice(data[key]);
+    mixins: [dictMixins],
+    props: {
+      processSubmitDialogFlag: {
+        type: Boolean,
+        default: false
+      }
     },
-    changePrice(data) {
-      let num = 0;
-      data.forEach((item) => {
-        num += Number(item.price);
-      });
-      this.$refs.generateForm.setData({
-        input_jd9ouzyh: num
-      });
+    watch: {
+      filterText(val) {
+        this.$refs.tree.filter(val);
+      }
     },
-
-    // 获取组件的中文名称,用于错误提示
-    getComponentName(componentKey) {
-      const nameMap = {
-        blank_business_component: '差旅交通',
-        blank_use_seal: '印章使用',
-        blank_use_qualification: '资质使用',
-        blank_product_specification: '产品规格',
-        blank_event_component: '事件',
-        blank_reissue_component: '补发信息'
+    data() {
+      return {
+        visibilityRangeDialogFlag: false,
+        isRight: false,
+        jsonData: {},
+        form: {
+          LCFL: '',
+          FQLC: '',
+          processDefinitionId: '',
+          name: '',
+          businessId: '',
+          noticeScope: [],
+          formJson: {},
+          valueJson: {},
+          businessKey: ''
+        },
+        title: '',
+        active: 0,
+        bpmnXML: null,
+        filterText: null,
+        treeList: [],
+        treeData: [],
+        defaultProps: {
+          children: 'children',
+          label: 'name'
+        },
+        LCFLList: [],
+        processList: [],
+        datasource: [],
+        roleOptions: [],
+        deptOptions: [],
+        deptTreeOptions: [],
+        postOptions: [],
+        userOptions: [],
+        userGroupOptions: [],
+        dictList: {},
+        rules: {},
+        editForm: {
+          start: '',
+          end: '',
+          days: ''
+        },
+        componentRef: [
+          'blank_business_component',
+          'blank_use_seal',
+          'blank_use_qualification',
+          'blank_product_specification',
+          'blank_event_component',
+          'blank_reissue_component'
+        ]
       };
-      return nameMap[componentKey] || componentKey;
     },
+    computed: {
+      ...mapGetters(['user']),
+      modelWidth() {
+        let width =
+          this.jsonData.config?.platform &&
+          this.jsonData.config.platform === 'pc'
+            ? 1100
+            : 450;
+        if (this.isRight) {
+          return width + 350 + 'px';
+        } else {
+          return width + 'px';
+        }
+      }
+    },
+    async created() {
+      let typeObj = await getProduceTreeByCode(
+        treeClassifyCodeEnum['PROCESSTYPE']
+      );
+      //  await this.getTreeData();
+      this.LCFLList = typeObj[0].children;
 
-    async addContact(type) {
-      console.log(type);
-      let data = await this.$refs.generateForm.getData(false);
-      console.log('data', data);
-      data[type] = {
-        id: '',
-        name: ''
-      };
-      this.$refs.generateForm.setData({
-        type: data[type]
+      // 获得角色列表
+      this.roleOptions = [];
+      listRoles({
+        current: 1,
+        size: 9999
+      }).then((data) => {
+        this.roleOptions.push(...data.list);
       });
-      let item = {
-        id: data[type].id
-      };
-      this.$refs.parentRef.open(item);
+      // 获得部门列表
+      this.deptOptions = [];
+      this.deptTreeOptions = [];
+      listOrganizations().then((data) => {
+        this.deptOptions.push(...data);
+        this.deptTreeOptions.push(...this.handleTree(data, 'id'));
+      });
+      // 获得岗位列表 暂无岗位概念
+      this.postOptions = [];
+      /*listSimplePosts().then(response => {
+this.postOptions.push(...response.data);
+});*/
+      // 获得用户列表
+      this.userOptions = [];
+      listAllUserBind().then((data) => {
+        this.userOptions.push(...data);
+      });
+      // 获得用户组列表
+      this.userGroupOptions = [];
+      listSimpleUserGroups().then((response) => {
+        this.userGroupOptions.push(...response);
+      });
+
+      //this.dictEnum['工作流任务分配自定义脚本']
+      await this.getDictList(this.dictEnum['工作流任务分配自定义脚本']);
+      await this.getDictList(this.dictEnum['工种类型']);
     },
-    
-    async addWorkOrder(type) {
-      
-      this.$refs.SHGDListDialogRef.open();
+    mounted() {
+      //this.isRight = false
     },
-    getSHGDData(workOrder) {
-      if (!workOrder?.code) {
-        this.$message.warning('选中的工单缺少编码,请重新选择');
-        return;
-      }
-      this.$refs.generateForm.getData(false).then((currentFormData) => {
-        currentFormData.manage_workorder = {
-          code: workOrder.code,
-          id: workOrder.id || '',
-          name: workOrder.name || ''
-        };
+    methods: {
+      async addNewRow(key) {
+        console.log(key);
+        let data = await this.$refs.generateForm.getData(false);
+        data[key].push({
+          price: '',
+          remark: ''
+        });
         this.$refs.generateForm.setData({
-          manage_workorder: currentFormData.manage_workorder
+          key: data[key]
         });
-        this.form.valueJson.manage_workorder = currentFormData.manage_workorder;
-      });
-    },
-    async handleConcatConfirm(item) {
-      console.log('选择的客户', item);
+      },
+      async delNewRow(key, index) {
+        let data = await this.$refs.generateForm.getData(false);
+        data[key] = data[key].filter((item, index1) => index1 != index);
+        this.$refs.generateForm.setData({
+          [key]: data[key]
+        });
+        this.changePrice(data[key]);
+      },
+      changePrice(data) {
+        let num = 0;
+        data.forEach((item) => {
+          num += Number(item.price);
+        });
+        this.$refs.generateForm.setData({
+          input_jd9ouzyh: num
+        });
+      },
 
-      let data = await this.$refs.generateForm.getData(false);
-      data['eom_contact'] = {
-        id: item.id,
-        name: item.name
-      };
-      this.$refs.generateForm.setData({
-        eom_contact: data['eom_contact']
-      });
-      console.log('data~~~~', data);
-    },
-    async init(row = {}) {
-      this.title = row.name; //'新建' + row.name + '单';
-      this.form = _.cloneDeep(row);
-      this.form.formId = row.id;
-      this.$set(this.form, 'noticeScope', []);
-      this.$set(this.form, 'LCFL', '');
-      this.$set(this.form, 'FQLC', '');
-      this.$set(this.form, 'name', '');
-      this.$set(this.form, 'key', '');
-      this.$set(this.form, 'valueJson', {});
-      this.jsonData = JSON.parse(this.form.formJson.makingJson);
-      console.log('jsonData', this.jsonData);
+      // 获取组件的中文名称,用于错误提示
+      getComponentName(componentKey) {
+        const nameMap = {
+          blank_business_component: '差旅交通',
+          blank_use_seal: '印章使用',
+          blank_use_qualification: '资质使用',
+          blank_product_specification: '产品规格',
+          blank_event_component: '事件',
+          blank_reissue_component: '补发信息'
+        };
+        return nameMap[componentKey] || componentKey;
+      },
 
-      this.jsonData.config.dataSource &&
-        this.jsonData.config.dataSource.forEach((item) => {
-          item.headers = {
-            Authorization: getToken()
-          };
-          // item.url = item.url && item.url.replace('/api', this.APIUrl);
+      async addContact(type) {
+        console.log(type);
+        let data = await this.$refs.generateForm.getData(false);
+        console.log('data', data);
+        data[type] = {
+          id: '',
+          name: ''
+        };
+        this.$refs.generateForm.setData({
+          type: data[type]
         });
-      this.jsonData.list.forEach((item) => {
-        if (item.type == 'deptAndUserCascader') {
+        let item = {
+          id: data[type].id
+        };
+        this.$refs.parentRef.open(item);
+      },
+
+      async addWorkOrder(type) {
+        this.$refs.SHGDListDialogRef.open();
+      },
+      getSHGDData(workOrder) {
+        if (!workOrder?.code) {
+          this.$message.warning('选中的工单缺少编码,请重新选择');
+          return;
         }
-        if (item.type == 'deptCascader') {
-          if (item.options.isDefaultLoginUser) {
-            this.form.valueJson[item.model] = this.user.info.groupIdList;
+        this.$refs.generateForm.getData(false).then((currentFormData) => {
+          currentFormData.manage_workorder = {
+            code: workOrder.code,
+            id: workOrder.id || '',
+            name: workOrder.name || ''
+          };
+          this.$refs.generateForm.setData({
+            manage_workorder: currentFormData.manage_workorder
+          });
+          this.form.valueJson.manage_workorder =
+            currentFormData.manage_workorder;
+        });
+      },
+      async handleConcatConfirm(item) {
+        console.log('选择的客户', item);
+
+        let data = await this.$refs.generateForm.getData(false);
+        data['eom_contact'] = {
+          id: item.id,
+          name: item.name
+        };
+        this.$refs.generateForm.setData({
+          eom_contact: data['eom_contact']
+        });
+        console.log('data~~~~', data);
+      },
+      async init(row = {}) {
+        this.title = row.name; //'新建' + row.name + '单';
+        this.form = _.cloneDeep(row);
+        this.form.formId = row.id;
+        this.$set(this.form, 'noticeScope', []);
+        this.$set(this.form, 'LCFL', '');
+        this.$set(this.form, 'FQLC', '');
+        this.$set(this.form, 'name', '');
+        this.$set(this.form, 'key', '');
+        this.$set(this.form, 'valueJson', {});
+        this.jsonData = JSON.parse(this.form.formJson.makingJson);
+        console.log('jsonData', this.jsonData);
+
+        this.jsonData.config.dataSource &&
+          this.jsonData.config.dataSource.forEach((item) => {
+            item.headers = {
+              Authorization: getToken()
+            };
+            // item.url = item.url && item.url.replace('/api', this.APIUrl);
+          });
+        this.jsonData.list.forEach((item) => {
+          if (item.type == 'deptAndUserCascader') {
           }
-        }
-        if (item.type == 'userSelect') {
-          if (item.options.isDefaultLoginUser) {
-            this.form.valueJson[item.model] = this.user.info.userId;
+          if (item.type == 'deptCascader') {
+            if (item.options.isDefaultLoginUser) {
+              this.form.valueJson[item.model] = this.user.info.groupIdList;
+            }
           }
-        }
-        if (item.type == 'imgupload') {
-          // this.form.valueJson[item.model].length &&
-          //   this.form.valueJson[item.model].forEach((item) => {
-          //     //item.objectUrl = this.APIUrl +'/kd-aiot' + item.storePath
-          //     // item.objectUrl = item.url;
-          //     // console.log(item);
-          //   });
-        }
-      });
-      await this.getProcessDefinitionBpmnXMLInfo(this.form.processModelId);
-      await this.getTaskAssignRuleListInfo({
-        modelId: this.form.processModelId,
-        processDefinitionId: this.form.processDefinitionId
-      });
-      await this.getDefaultInfo(row.processModelId);
-    },
-    async getDefaultInfo(businessKey) {
-      let info = await getModel(businessKey);
-      //let info = await getProcessDefinitionInfo({ id: businessKey });
-      this.form.LCFL = info?.category;
-      this.form.FQLC = info?.id;
-      this.form.name = this.title;
-      this.form.key = info?.key;
-      if (this.form.LCFL) await this.getProcessList(this.form.LCFL);
-    },
-    async getProcessList(val) {
-      let params = {
-        pageNo: 1,
-        pageSize: 999,
-        processTypeId: val
-      };
-      const { list } = await getModelPage(params);
-      this.processList = list.filter((item) => item.processDefinition);
-    },
-    async getProcessDefinitionBpmnXML(val) {
-      this.bpmnXML = await getProcessDefinitionBpmnXML(val);
-    },
-    async getProcessDefinitionBpmnXMLInfo(val) {
-      // 加载流程图
-      let res = await getModel(val);
-      this.bpmnXML = res.bpmnXml;
-    },
-    async getTaskAssignRuleListInfo(find) {
-      this.datasource = await getTaskAssignRuleList({
-        modelId: find.modelId,
-        processDefinitionId: find.processDefinitionId
-      });
-    },
-    handleEditDataScope() {
-      this.$refs.staffSelection.open(this.form.noticeScope);
-      // this.visibilityRangeDialogFlag = true;
-      // this.$nextTick(() => {
-      //   this.$refs.visibilityRangeDialogRef.init(this.form);
-      // });
-    },
-    getTreeList(list) {
-      list.forEach((item) => {
-        item.type = 1;
-      });
-      this.form.noticeScope = list;
-    },
-    handleCloseTag(index) {
-      this.form.noticeScope.splice(index, 1);
-    },
-    getAssignRuleOptionName(row, option) {
-      if (row.type == 10) {
-        for (const roleOption of this.roleOptions) {
-          if (roleOption.id === option) {
-            return roleOption.name;
+          if (item.type == 'userSelect') {
+            if (item.options.isDefaultLoginUser) {
+              this.form.valueJson[item.model] = this.user.info.userId;
+            }
           }
-        }
-      } else if (row.type === 20 || row.type === 21) {
-        for (const deptOption of this.deptOptions) {
-          if (deptOption.id === option) {
-            return deptOption.name;
+          if (item.type == 'imgupload') {
+            // this.form.valueJson[item.model].length &&
+            //   this.form.valueJson[item.model].forEach((item) => {
+            //     //item.objectUrl = this.APIUrl +'/kd-aiot' + item.storePath
+            //     // item.objectUrl = item.url;
+            //     // console.log(item);
+            //   });
           }
-        }
-      } else if (row.type === 22) {
-        option = option + ''; // 转换成 string
-        return this.getDictV(this.dictEnum['工种类型'], option);
-      } else if (row.type === 30 || row.type === 31 || row.type === 32) {
-        for (const userOption of this.userOptions) {
-          if (userOption.id === option) {
-            return userOption.nickname || userOption.name;
+        });
+        await this.getProcessDefinitionBpmnXMLInfo(this.form.processModelId);
+        await this.getTaskAssignRuleListInfo({
+          modelId: this.form.processModelId,
+          processDefinitionId: this.form.processDefinitionId
+        });
+        await this.getDefaultInfo(row.processModelId);
+      },
+      async getDefaultInfo(businessKey) {
+        let info = await getModel(businessKey);
+        //let info = await getProcessDefinitionInfo({ id: businessKey });
+        parameterGetByCode({
+          code: 'wt_collaborative_bpm'
+        }).then((res) => {
+          if (!res.value||res.value=='1') {
+            this.form.FQLC = info?.id;
+            this.form.name = this.title;
+            this.form.key = info?.key;
           }
-        }
-      } else if (row.type === 40) {
-        for (const userGroupOption of this.userGroupOptions) {
-          if (userGroupOption.id === option) {
-            return userGroupOption.name;
+        });
+        this.form.LCFL = info?.category;
+
+        if (this.form.LCFL) await this.getProcessList(this.form.LCFL);
+      },
+      async getProcessList(val) {
+        let params = {
+          pageNo: 1,
+          pageSize: 999,
+          processTypeId: val
+        };
+        const { list } = await getModelPage(params);
+        this.processList = list.filter((item) => item.processDefinition);
+      },
+      async getProcessDefinitionBpmnXML(val) {
+        this.bpmnXML = await getProcessDefinitionBpmnXML(val);
+      },
+      async getProcessDefinitionBpmnXMLInfo(val) {
+        // 加载流程图
+        let res = await getModel(val);
+        this.bpmnXML = res.bpmnXml;
+      },
+      async getTaskAssignRuleListInfo(find) {
+        this.datasource = await getTaskAssignRuleList({
+          modelId: find.modelId,
+          processDefinitionId: find.processDefinitionId
+        });
+      },
+      handleEditDataScope() {
+        this.$refs.staffSelection.open(this.form.noticeScope);
+        // this.visibilityRangeDialogFlag = true;
+        // this.$nextTick(() => {
+        //   this.$refs.visibilityRangeDialogRef.init(this.form);
+        // });
+      },
+      getTreeList(list) {
+        list.forEach((item) => {
+          item.type = 1;
+        });
+        this.form.noticeScope = list;
+      },
+      handleCloseTag(index) {
+        this.form.noticeScope.splice(index, 1);
+      },
+      getAssignRuleOptionName(row, option) {
+        if (row.type == 10) {
+          for (const roleOption of this.roleOptions) {
+            if (roleOption.id === option) {
+              return roleOption.name;
+            }
           }
+        } else if (row.type === 20 || row.type === 21) {
+          for (const deptOption of this.deptOptions) {
+            if (deptOption.id === option) {
+              return deptOption.name;
+            }
+          }
+        } else if (row.type === 22) {
+          option = option + ''; // 转换成 string
+          return this.getDictV(this.dictEnum['工种类型'], option);
+        } else if (row.type === 30 || row.type === 31 || row.type === 32) {
+          for (const userOption of this.userOptions) {
+            if (userOption.id === option) {
+              return userOption.nickname || userOption.name;
+            }
+          }
+        } else if (row.type === 40) {
+          for (const userGroupOption of this.userGroupOptions) {
+            if (userGroupOption.id === option) {
+              return userGroupOption.name;
+            }
+          }
+        } else if (row.type === 50) {
+          option = option + ''; // 转换成 string
+          return this.getDictV(
+            this.dictEnum['工作流任务分配自定义脚本'],
+            option
+          );
+        } else if (row.type === 60) {
+          return row.variableName;
+        } else if (row.type === 70) {
+          let data = JSON.parse(row.variableName);
+          if (data.direction == 1) {
+            return topLevel2.find((item) => item.value == data.topLevel)?.label;
+          } else {
+            return topLevel1.find((item) => item.value == data.topLevel)?.label;
+          }
+        } else if (row.type === 80) {
+          let data = JSON.parse(row.variableName);
+          return topLevel3.find((item) => item.value == data.topLevel)?.label;
         }
-      } else if (row.type === 50) {
-        option = option + ''; // 转换成 string
-        return this.getDictV(this.dictEnum['工作流任务分配自定义脚本'], option);
-      } else if (row.type === 60) {
-        return row.variableName;
-      } else if (row.type === 70) {
-        let data = JSON.parse(row.variableName);
-        if (data.direction == 1) {
-          return topLevel2.find((item) => item.value == data.topLevel)?.label;
-        } else {
-          return topLevel1.find((item) => item.value == data.topLevel)?.label;
-        }
-      } else if (row.type === 80) {
-        let data = JSON.parse(row.variableName);
-        return topLevel3.find((item) => item.value == data.topLevel)?.label;
-      }
-      return '未知(' + option + ')';
-    },
-    async getTreeData() {
-      this.treeData = await getGroupUserTree();
-    },
-    filterNode(value, data) {
-      if (!value) return true;
-      return data.name.indexOf(value) !== -1;
-    },
-    /**
-     * 构造树型结构数据
-     * @param {*} data 数据源
-     * @param {*} id id字段 默认 'id'
-     * @param {*} parentId 父节点字段 默认 'parentId'
-     * @param {*} children 孩子节点字段 默认 'children'
-     * @param {*} rootId 根Id 默认 0
-     */
-    handleTree(data, id, parentId, children, rootId) {
-      id = id || 'id';
-      parentId = parentId || 'parentId';
-      children = children || 'children';
-      rootId =
-        rootId ||
-        Math.min.apply(
-          Math,
-          data.map((item) => {
-            return item[parentId];
-          })
-        ) ||
-        0;
-      //对源数据深度克隆
-      const cloneData = JSON.parse(JSON.stringify(data));
-      //循环所有项
-      const treeData = cloneData.filter((father) => {
-        let branchArr = cloneData.filter((child) => {
-          //返回每一项的子级数组
-          return father[id] == child[parentId];
+        return '未知(' + option + ')';
+      },
+      async getTreeData() {
+        this.treeData = await getGroupUserTree();
+      },
+      filterNode(value, data) {
+        if (!value) return true;
+        return data.name.indexOf(value) !== -1;
+      },
+      /**
+       * 构造树型结构数据
+       * @param {*} data 数据源
+       * @param {*} id id字段 默认 'id'
+       * @param {*} parentId 父节点字段 默认 'parentId'
+       * @param {*} children 孩子节点字段 默认 'children'
+       * @param {*} rootId 根Id 默认 0
+       */
+      handleTree(data, id, parentId, children, rootId) {
+        id = id || 'id';
+        parentId = parentId || 'parentId';
+        children = children || 'children';
+        rootId =
+          rootId ||
+          Math.min.apply(
+            Math,
+            data.map((item) => {
+              return item[parentId];
+            })
+          ) ||
+          0;
+        //对源数据深度克隆
+        const cloneData = JSON.parse(JSON.stringify(data));
+        //循环所有项
+        const treeData = cloneData.filter((father) => {
+          let branchArr = cloneData.filter((child) => {
+            //返回每一项的子级数组
+            return father[id] == child[parentId];
+          });
+          branchArr.length > 0 ? (father.children = branchArr) : '';
+          //返回第一层
+          return father[parentId] == rootId;
         });
-        branchArr.length > 0 ? (father.children = branchArr) : '';
-        //返回第一层
-        return father[parentId] == rootId;
-      });
-      return treeData !== '' ? treeData : data;
-    },
-    getDictV(code, val) {
-      if (!this.dictList[code]) return '';
-      return this.dictList[code].find((item) => item.value == val)?.label;
-    },
-    async getDictList(code) {
-      let { data: res } = await getByCode(code);
-      this.dictList[code] = res.map((item) => {
-        let values = Object.keys(item);
-        return {
-          value: values[0],
-          label: item[values[0]]
-        };
-      });
-    },
-    generateFormValid(validate = true) {
-      return this.$refs.generateForm.getData(validate).then((data) => {
-        return data;
-      });
-    },
-    handleTreeChange() {
-      this.$nextTick(() => {
-        this.form.noticeScope =
-          this.$refs.treeSelect.$refs.tree.getCheckedNodes();
-        console.log(this.form.noticeScope);
-      });
-    },
-    async changeLCFL(val) {
-      this.bpmnXML = null;
-      this.form.processDefinitionId = null;
-      this.form.FQLC = null;
-      await this.getProcessList(val);
-    },
-    async changeFQLC(val) {
-      if (!val) return;
-      let find = this.processList.find((item) => item.id === val) || {};
-      this.form.name = find.name;
-      this.form.key = find.key;
-      this.form.processDefinitionId = find.processDefinition.id;
-      this.form.processModelId = val;
-      await this.getProcessDefinitionBpmnXML(find.processDefinition.id);
-      await this.getTaskAssignRuleListInfo({
-        modelId: find.id,
-        processDefinitionId: find.processDefinition.id
-      });
-    },
-    async submit() {
-      // console.log('this.form~~~', this.$refs.businessComponentRef.form);
+        return treeData !== '' ? treeData : data;
+      },
+      getDictV(code, val) {
+        if (!this.dictList[code]) return '';
+        return this.dictList[code].find((item) => item.value == val)?.label;
+      },
+      async getDictList(code) {
+        let { data: res } = await getByCode(code);
+        this.dictList[code] = res.map((item) => {
+          let values = Object.keys(item);
+          return {
+            value: values[0],
+            label: item[values[0]]
+          };
+        });
+      },
+      generateFormValid(validate = true) {
+        return this.$refs.generateForm.getData(validate).then((data) => {
+          return data;
+        });
+      },
+      handleTreeChange() {
+        this.$nextTick(() => {
+          this.form.noticeScope =
+            this.$refs.treeSelect.$refs.tree.getCheckedNodes();
+          console.log(this.form.noticeScope);
+        });
+      },
+      async changeLCFL(val) {
+        this.bpmnXML = null;
+        this.form.processDefinitionId = null;
+        this.form.FQLC = null;
+        await this.getProcessList(val);
+      },
+      async changeFQLC(val) {
+        if (!val) return;
+        let find = this.processList.find((item) => item.id === val) || {};
+        this.form.name = find.name;
+        this.form.key = find.key;
+        this.form.processDefinitionId = find.processDefinition.id;
+        this.form.processModelId = val;
+        await this.getProcessDefinitionBpmnXML(find.processDefinition.id);
+        await this.getTaskAssignRuleListInfo({
+          modelId: find.id,
+          processDefinitionId: find.processDefinition.id
+        });
+      },
+      async submit() {
+        // console.log('this.form~~~', this.$refs.businessComponentRef.form);
 
-      // const businessComponentForm = this.$refs.businessComponentRef.form;
-      let data = await this.$refs.generateForm.getData(false);
-      // data['blank_business_component'] = businessComponentForm.blank_business_component;
-      // this.$refs.generateForm.setData({
-      //   'blank_business_component': data['blank_business_component']
-      // });
-      // 获取所有组件的引用
-      let validArr = [];
-      // 过滤出存在于componentRef中的键
-      Object.keys(data).forEach((key) => {
-        if (this.componentRef.includes(key)) {
-          validArr.push(key);
-        }
-      });
+        // const businessComponentForm = this.$refs.businessComponentRef.form;
+        let data = await this.$refs.generateForm.getData(false);
+        // data['blank_business_component'] = businessComponentForm.blank_business_component;
+        // this.$refs.generateForm.setData({
+        //   'blank_business_component': data['blank_business_component']
+        // });
+        // 获取所有组件的引用
+        let validArr = [];
+        // 过滤出存在于componentRef中的键
+        Object.keys(data).forEach((key) => {
+          if (this.componentRef.includes(key)) {
+            validArr.push(key);
+          }
+        });
 
-      // 检查每个组件的数据是否为空数组
-      let emptyComponents = [];
-      validArr.forEach((item) => {
-        // 检查data[item]是否存在且为数组,并且长度为0
-        if (Array.isArray(data[item]) && data[item].length === 0) {
-          emptyComponents.push(item);
-        }
-      });
+        // 检查每个组件的数据是否为空数组
+        let emptyComponents = [];
+        validArr.forEach((item) => {
+          // 检查data[item]是否存在且为数组,并且长度为0
+          if (Array.isArray(data[item]) && data[item].length === 0) {
+            emptyComponents.push(item);
+          }
+        });
 
-      // 如果有未填写的组件,显示提示信息
-      if (emptyComponents.length > 0) {
-        // this.$message.warning(`请填写完整信息:${emptyComponents.map(comp => this.getComponentName(comp)).join('、')}`);
-        this.$message.warning(`请填写完整信息`);
-        return false;
-      }
+        // 如果有未填写的组件,显示提示信息
+        if (emptyComponents.length > 0) {
+          // this.$message.warning(`请填写完整信息:${emptyComponents.map(comp => this.getComponentName(comp)).join('、')}`);
+          this.$message.warning(`请填写完整信息`);
+          return false;
+        }
 
-      // 使用Promise.all并行校验所有组件
-      // try {
-      //   await Promise.all(validArr.map(key => {
-      //     if (this.$refs[key] && typeof this.$refs[key].validateForm === 'function') {
-      //       return this.$refs[key].validateForm();
-      //     }
-      //     return Promise.resolve(true); // 如果组件不存在或没有validateForm方法,默认通过
-      //   }));
-      //   console.log('所有组件校验通过');
-      // } catch (error) {
-      //   console.error('表单校验失败:', error);
-      //   this.$message.error('表单校验失败,请检查必填项');
-      //   return false; // 任一组件校验失败则整体失败
-      // }
-      // console.log('data~~~~', data);
-      this.form.valueJson = await this.generateFormValid();
-      this.form.processType = '1';
-      console.log('formformformform', this.form);
-      await processInstanceCreateAPI({
-        ...this.form,
-        variables: { ...this.form.valueJson }
-      });
-      this.$message('提交审核成功');
-      this.$emit('reload');
-      this.cancel();
-    },
-    cancel() {
-      this.$emit('update:processSubmitDialogFlag', false);
-    },
-    getDays(start, end) {
-      const startDay = dayjs(start);
-      const endDay = dayjs(end);
-      const diffInMilliseconds = endDay.diff(startDay);
+        // 使用Promise.all并行校验所有组件
+        // try {
+        //   await Promise.all(validArr.map(key => {
+        //     if (this.$refs[key] && typeof this.$refs[key].validateForm === 'function') {
+        //       return this.$refs[key].validateForm();
+        //     }
+        //     return Promise.resolve(true); // 如果组件不存在或没有validateForm方法,默认通过
+        //   }));
+        //   console.log('所有组件校验通过');
+        // } catch (error) {
+        //   console.error('表单校验失败:', error);
+        //   this.$message.error('表单校验失败,请检查必填项');
+        //   return false; // 任一组件校验失败则整体失败
+        // }
+        // console.log('data~~~~', data);
+        this.form.valueJson = await this.generateFormValid();
+        this.form.processType = '1';
+        console.log('formformformform', this.form);
+        await processInstanceCreateAPI({
+          ...this.form,
+          variables: { ...this.form.valueJson }
+        });
+        this.$message('提交审核成功');
+        this.$emit('reload');
+        this.cancel();
+      },
+      cancel() {
+        this.$emit('update:processSubmitDialogFlag', false);
+      },
+      getDays(start, end) {
+        const startDay = dayjs(start);
+        const endDay = dayjs(end);
+        const diffInMilliseconds = endDay.diff(startDay);
 
-      // 计算天数
-      const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
-      // 计算剩余小时数
-      const hours = Math.floor(
-        (diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
-      );
-      // 计算剩余分钟数
-      const minutes = Math.floor(
-        (diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60)
-      );
-      // 计算剩余秒数
-      const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000);
+        // 计算天数
+        const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
+        // 计算剩余小时数
+        const hours = Math.floor(
+          (diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
+        );
+        // 计算剩余分钟数
+        const minutes = Math.floor(
+          (diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60)
+        );
+        // 计算剩余秒数
+        const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000);
 
-      let result = '';
-      if (days > 0) result += `${days} 天 `;
-      if (hours > 0) result += `${hours} 小时 `;
-      if (minutes > 0) result += `${minutes} 分钟 `;
-      if (seconds > 0) result += `${seconds} 秒`;
-      return result.trim();
+        let result = '';
+        if (days > 0) result += `${days} 天 `;
+        if (hours > 0) result += `${hours} 小时 `;
+        if (minutes > 0) result += `${minutes} 分钟 `;
+        if (seconds > 0) result += `${seconds} 秒`;
+        return result.trim();
+      }
     }
-  }
-};
+  };
 </script>
 <style scoped lang="scss">
-.box {
-  display: flex;
-  height: 450px;
+  .box {
+    display: flex;
+    height: 450px;
 
-  .left-box {
-    width: 55%;
-    border-right: 1px solid #e2e4e7;
-    padding-right: 15px;
-    height: 100%;
+    .left-box {
+      width: 55%;
+      border-right: 1px solid #e2e4e7;
+      padding-right: 15px;
+      height: 100%;
 
-    .el-tree {
-      height: 85%;
-      overflow-y: auto;
+      .el-tree {
+        height: 85%;
+        overflow-y: auto;
+      }
     }
-  }
 
-  .right-box {
-    flex: 1;
-    padding-left: 20px;
-    height: 100%;
+    .right-box {
+      flex: 1;
+      padding-left: 20px;
+      height: 100%;
 
-    .right-box-item {
-      margin-top: 5px;
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
+      .right-box-item {
+        margin-top: 5px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+      }
     }
   }
-}
 
-.form-box {
-  // max-height: 500px;
-  min-width: 400px;
-  overflow: auto;
-  background: #4298fd0d;
-}
-::v-deep .el-dialog {
-  min-width: 400px;
-  .el-dialog__header {
-    background: #1890ffd6;
+  .form-box {
+    // max-height: 500px;
+    min-width: 400px;
+    overflow: auto;
+    background: #4298fd0d;
   }
-  .el-dialog__title,
-  .el-dialog__close {
-    color: #ffffff;
+  ::v-deep .el-dialog {
+    min-width: 400px;
+    .el-dialog__header {
+      background: #1890ffd6;
+    }
+    .el-dialog__title,
+    .el-dialog__close {
+      color: #ffffff;
+    }
   }
-}
-.blank_adopzrdd {
-  display: flex;
-  align-items: center;
-  > span {
-    display: inline-block;
-    width: 80px;
+  .blank_adopzrdd {
+    display: flex;
+    align-items: center;
+    > span {
+      display: inline-block;
+      width: 80px;
+    }
+    margin-bottom: 10px;
   }
-  margin-bottom: 10px;
-}
 </style>

+ 20 - 0
src/api/afterSales/index.js

@@ -42,4 +42,24 @@ export async function salesrealcostinfo(id) {
     return res.data.data;
   }
   return Promise.reject(new Error(res.data.message));
+}
+//售后服务 售后需求详情
+
+export async function getSalesDemandById(id) {
+  const res = await request.get(`/eom/afterSalesDemand/getById/${id}`);
+  if (res.data.code === "0") { 
+    return res.data; 
+  }
+  return Promise.reject(new Error(res.data.message || "获取售后需求详情失败"));
+}
+
+/**
+ * 获取客户信息详情
+ */
+export async function contactDetail(id) {
+  const res = await request.get(`/eom/contact/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
 }

+ 198 - 145
src/views/bpm/collaborative/detail.vue

@@ -35,7 +35,10 @@
           ref="generateForm"
         >
           <template v-slot:blank_adopzrdd="scope">
-            <div v-for="(item, index) in scope.model.blank_adopzrdd" :key="index">
+            <div
+              v-for="(item, index) in scope.model.blank_adopzrdd"
+              :key="index"
+            >
               <div class="blank_adopzrdd">
                 <span>{{ index + 1 }}报销事项:</span>
                 <el-input
@@ -55,45 +58,89 @@
             </div>
           </template>
           <!-- 客户名称 -->
-            <template v-slot:eom_contact="scope">
-              <div class="eom_contact">
-                <el-input
-                    v-model="scope.model.eom_contact.name"
-                    style="width: 100%"
-                  ></el-input>
-              </div>
-            </template>
-
-            <!-- 差旅 -->
-            <template v-slot:blank_business_component="scope">
-              <businessComponent  ref="blank_business_component" id="blank_business_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></businessComponent>
-            </template>
+          <template v-slot:eom_contact="scope">
+            <div class="eom_contact">
+              <el-input
+                v-model="scope.model.eom_contact.name"
+                style="width: 100%"
+              ></el-input>
+            </div>
+          </template>
 
-            <!-- 印章使用 -->
-            <template v-slot:blank_use_seal="scope">
-              <useSealComponent  ref="blank_use_seal" id="blank_use_seal" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></useSealComponent>
-            </template>
+          <!-- 关联工单 -->
+          <template v-slot:manage_workorder="scope">
+            <div class="manage_workorder">
+              <el-input
+                v-model="scope.model.manage_workorder.code"
+                style="width: 100%"
+              ></el-input>
+            </div>
+          </template>
+          <!-- 差旅 -->
+          <template v-slot:blank_business_component="scope">
+            <businessComponent
+              ref="blank_business_component"
+              id="blank_business_component"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></businessComponent>
+          </template>
 
-            <!-- 资质使用 -->
-            <template v-slot:blank_use_qualification="scope">
-              <useQualificationComponent  ref="blank_use_qualification" id="blank_use_qualification" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></useQualificationComponent>
-            </template>
+          <!-- 印章使用 -->
+          <template v-slot:blank_use_seal="scope">
+            <useSealComponent
+              ref="blank_use_seal"
+              id="blank_use_seal"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></useSealComponent>
+          </template>
 
-            <!-- 产品规格 -->
-            <template v-slot:blank_product_specification="scope">
-              <productSpecificationComponent  ref="blank_product_specification" id="blank_product_specification" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></productSpecificationComponent>
-            </template>
+          <!-- 资质使用 -->
+          <template v-slot:blank_use_qualification="scope">
+            <useQualificationComponent
+              ref="blank_use_qualification"
+              id="blank_use_qualification"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></useQualificationComponent>
+          </template>
 
-            <!-- 事件 -->
-            <template v-slot:blank_event_component="scope">
-              <eventComponent  ref="blank_event_component" id="blank_event_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></eventComponent>
-            </template>
+          <!-- 产品规格 -->
+          <template v-slot:blank_product_specification="scope">
+            <productSpecificationComponent
+              ref="blank_product_specification"
+              id="blank_product_specification"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></productSpecificationComponent>
+          </template>
 
-            <!-- 补发 -->
-            <template v-slot:blank_reissue_component="scope">
-              <reissueComponent  ref="blank_reissue_component" id="blank_reissue_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></reissueComponent>
-            </template>
+          <!-- 事件 -->
+          <template v-slot:blank_event_component="scope">
+            <eventComponent
+              ref="blank_event_component"
+              id="blank_event_component"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></eventComponent>
+          </template>
 
+          <!-- 补发 -->
+          <template v-slot:blank_reissue_component="scope">
+            <reissueComponent
+              ref="blank_reissue_component"
+              id="blank_reissue_component"
+              :generateForm="$refs.generateForm"
+              :info="scope.model"
+              :view="view"
+            ></reissueComponent>
+          </template>
         </fm-generate-form>
       </div>
       <div
@@ -118,14 +165,10 @@
         <span style="writing-mode: vertical-rl">选择流程</span>
       </div>
       <div style="flex: 1" v-if="isRight">
-        <Detail
-          :view="true"
-          :id="form.id"
-          ref="formDetailDialogRef"
-        ></Detail>
+        <Detail :view="true" :id="form.id" ref="formDetailDialogRef"></Detail>
       </div>
     </div>
-    
+
     <outgoingDetails
       v-if="outgoingData.id"
       :business-id="outgoingData.id"
@@ -137,121 +180,131 @@
   </ele-modal>
 </template>
 <script>
-  import dictMixins from '@/mixins/dictMixins';
-  import { getToken } from '@/utils/token-util';
-  import outgoingDetails from '@/views/bpm/outgoingManagement/details.vue';
-  import storageApi from '@/api/warehouseManagement';
-
-  // 流程组件  需要在三个地方使用,审批流程,详情,提交流程
-  import businessComponent from '@/BIZComponents/processSubmitDialog/components/businessComponent.vue';
-  import useSealComponent from '@/BIZComponents/processSubmitDialog/components/useSealComponent.vue';
-  import useQualificationComponent from '@/BIZComponents/processSubmitDialog/components/useQualificationComponent.vue';
-  import productSpecificationComponent from '@/BIZComponents/processSubmitDialog/components/productSpecificationComponent.vue';
-  import eventComponent from '@/BIZComponents/processSubmitDialog/components/eventComponent.vue';
-  import reissueComponent from '@/BIZComponents/processSubmitDialog/components/reissueComponent.vue';
-  import Detail from '@/views/bpm/processInstance/detailNew.vue';
+import dictMixins from '@/mixins/dictMixins';
+import { getToken } from '@/utils/token-util';
+import outgoingDetails from '@/views/bpm/outgoingManagement/details.vue';
+import storageApi from '@/api/warehouseManagement';
 
-  
+// 流程组件  需要在三个地方使用,审批流程,详情,提交流程
+import businessComponent from '@/BIZComponents/processSubmitDialog/components/businessComponent.vue';
+import useSealComponent from '@/BIZComponents/processSubmitDialog/components/useSealComponent.vue';
+import useQualificationComponent from '@/BIZComponents/processSubmitDialog/components/useQualificationComponent.vue';
+import productSpecificationComponent from '@/BIZComponents/processSubmitDialog/components/productSpecificationComponent.vue';
+import eventComponent from '@/BIZComponents/processSubmitDialog/components/eventComponent.vue';
+import reissueComponent from '@/BIZComponents/processSubmitDialog/components/reissueComponent.vue';
+import Detail from '@/views/bpm/processInstance/detailNew.vue';
 
-  export default {
-    name: 'formDetailDialog',
-    components: {outgoingDetails, businessComponent, useSealComponent, useQualificationComponent, productSpecificationComponent, eventComponent, reissueComponent, Detail},
-    props: {
-      formDetailDialogFlag: {
-        type: Boolean,
-        default: false
-      },
-      view: {
-        type: Boolean,
-        default: false
-      },
+export default {
+  name: 'formDetailDialog',
+  components: {
+    outgoingDetails,
+    businessComponent,
+    useSealComponent,
+    useQualificationComponent,
+    productSpecificationComponent,
+    eventComponent,
+    reissueComponent,
+    Detail
+  },
+  props: {
+    formDetailDialogFlag: {
+      type: Boolean,
+      default: false
     },
-    mixins: [dictMixins],
-    data() {
-      return {
-        form: {},
-        jsonData: {},
-        outgoingData:{},
-        isRight: false,
-      };
-    },
-    computed: {
-      // modelWidth() {
-      //   return (this.outgoingData?.id || this.jsonData.config?.platform && this.jsonData.config.platform === 'pc') ? '80%' : '400px';
-      // }
-      modelWidth() {
-        let width = this.jsonData.config?.platform && this.jsonData.config.platform === 'pc' ? 1100 : 450;
-        if(this.isRight) {
-          return width + 750 + 'px'
-        } else {
-          return width + 'px'
-        }
+    view: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mixins: [dictMixins],
+  data() {
+    return {
+      form: {},
+      jsonData: {},
+      outgoingData: {},
+      isRight: false
+    };
+  },
+  computed: {
+    // modelWidth() {
+    //   return (this.outgoingData?.id || this.jsonData.config?.platform && this.jsonData.config.platform === 'pc') ? '80%' : '400px';
+    // }
+    modelWidth() {
+      let width =
+        this.jsonData.config?.platform && this.jsonData.config.platform === 'pc'
+          ? 1100
+          : 450;
+      if (this.isRight) {
+        return width + 750 + 'px';
+      } else {
+        return width + 'px';
+      }
+    }
+  },
+  methods: {
+    open(row) {
+      this.form = _.cloneDeep(row);
+      if (this.form.id) {
+        storageApi.getInfoBySourceBizNo(this.form.id).then((res) => {
+          this.outgoingData = res;
+        });
       }
+      this.jsonData = JSON.parse(this.form.formJson.makingJson);
+      this.jsonData.config.dataSource &&
+        this.jsonData.config.dataSource.forEach((item) => {
+          item.headers = {
+            Authorization: getToken()
+          };
+          // item.url = item.url && item.url.replace('/api', this.APIUrl);
+        });
     },
-    methods: {
-       open(row) {
-        this.form = _.cloneDeep(row);
-        if(this.form.id){
-          storageApi.getInfoBySourceBizNo(this.form.id).then(res=>{
-          this.outgoingData=res
-        })
-        }
-        this.jsonData = JSON.parse(this.form.formJson.makingJson);
-        this.jsonData.config.dataSource &&
-          this.jsonData.config.dataSource.forEach((item) => {
-            item.headers = {
-              Authorization: getToken()
-            };
-            // item.url = item.url && item.url.replace('/api', this.APIUrl);
-          });
-      },
-      getTimelineItemType(result) {
-        if (result === '通过') {
-          return 'success';
-        }
-        if (result === '不通过') {
-          return 'danger';
-        }
-        if (result === '取消') {
-          return 'info';
-        }
-        if (result === '处理中') {
-          return 'warning';
-        }
-
-        return '';
-      },
-      cancel() {
-        this.$emit('update:formDetailDialogFlag', false);
+    getTimelineItemType(result) {
+      if (result === '通过') {
+        return 'success';
+      }
+      if (result === '不通过') {
+        return 'danger';
+      }
+      if (result === '取消') {
+        return 'info';
+      }
+      if (result === '处理中') {
+        return 'warning';
       }
+
+      return '';
+    },
+    cancel() {
+      this.$emit('update:formDetailDialogFlag', false);
     }
-  };
+  }
+};
 </script>
 <style scoped lang="scss">
-  .eleModalBox {
-    height: 100%;
-    min-width: 300px;
-    overflow: auto;
-  }
+.eleModalBox {
+  height: 100%;
+  min-width: 300px;
+  overflow: auto;
+}
 
-  .form-box {
-    // max-height: 500px;
-    min-width: 400px;
-    overflow: auto;
-    background: #4298fd0d;
-  }
+.form-box {
+  // max-height: 500px;
+  min-width: 400px;
+  overflow: auto;
+  background: #4298fd0d;
+}
 
-  ::v-deep .el-dialog__header {
-    display: flex;
-    justify-content: space-between;
-  }
-  .blank_adopzrdd {
-    display: flex;
-    align-items: center;
-    > span {
-      display: inline-block;
-      width: 80px;
-    }
-    margin-bottom: 10px;
+::v-deep .el-dialog__header {
+  display: flex;
+  justify-content: space-between;
+}
+.blank_adopzrdd {
+  display: flex;
+  align-items: center;
+  > span {
+    display: inline-block;
+    width: 80px;
   }
+  margin-bottom: 10px;
+}
 </style>

+ 1 - 0
src/views/bpm/handleTask/components/contractBook/detailDialog.vue

@@ -169,6 +169,7 @@
       :pricingWay="form.pricingWay"
       :isChangeCount="false"
       :isArrivalWay="true"
+      :isProductionRequirements="form.type == '1'"
       :countObj="{
         countKey: 'contractCount',
         unitKey: 'contractUnit',

+ 1 - 0
src/views/bpm/handleTask/components/saleOrder/detailDialog.vue

@@ -206,6 +206,7 @@
         :isCustomerMark="true"
         :isDiscountTotalPrice="true"
         :isArrivalWay="true"
+        :isProductionRequirements="true"
       ></inventoryTabledetail>
       <headerTitle title="类型清单" v-if="form.needProduce == 4"></headerTitle>
 

+ 7 - 2
src/views/bpm/handleTask/components/saleOrder/invoice/detailDialog.vue

@@ -259,7 +259,6 @@
       };
     },
     computed: {
-
       columns() {
         let columnsVersion = this.columnsVersion;
         return [
@@ -339,6 +338,12 @@
             label: '生产编号',
             align: 'center'
           },
+          {
+            minWidth: 280,
+            prop: 'productionRequirements',
+            label: '生产要求',
+            align: 'center'
+          },
           {
             width: 120,
             prop: 'imgCode',
@@ -427,7 +432,7 @@
             align: 'center'
           },
 
-           this.$store.state.user.info.clientEnvironmentId== '4'
+          this.$store.state.user.info.clientEnvironmentId == '4'
             ? {
                 width: 120,
                 prop: 'blockCount',

+ 1145 - 0
src/views/bpm/handleTask/components/salesServiceManagement/demand/salesServiceDialog.vue

@@ -0,0 +1,1145 @@
+<template>
+  <el-form
+    ref="form"
+    :model="form"
+    :rules="rules"
+    label-width="130px"
+    class="create-form"
+  >
+    <!-- 标题区域 -->
+    <headerTitle
+      title="基本信息"
+      style="margin-top: 8px"
+      v-if="isPurchaseNeed"
+    ></headerTitle>
+    <headerTitle
+      title="需求信息"
+      style="margin-top: 8px"
+      v-if="!isPurchaseNeed"
+    ></headerTitle>
+
+    <!-- 基本信息表单区域 -->
+    <el-row :gutter="24" v-if="source != '报工信息'">
+      <el-col :span="6">
+        <el-form-item label="需求编码:">
+          <el-input v-model="form.code" disabled />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="关联类型:">
+          <el-select
+            style="width: 100%"
+            v-model="form.associationType"
+            placeholder="请选择"
+            disabled
+          >
+            <el-option
+              v-for="item in associationTypeList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="需求名称:">
+          <el-select
+            style="width: 100%"
+            v-model="form.name"
+            filterable
+            allow-create
+            default-first-option
+            placeholder="请选择需求名称"
+            disabled
+          >
+            <el-option
+              v-for="item in demandList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="客户名称:">
+          <el-input
+            v-model="form.contractInfo.contactName"
+            readonly
+            disabled
+            placeholder="请选择"
+          />
+        </el-form-item>
+      </el-col>
+
+      <!-- 关联类型对应的订单展示 -->
+      <el-col :span="6" v-if="form.associationType == '1'">
+        <el-form-item label="发货单:">
+          <el-input
+            v-model="form.orderCode"
+            readonly
+            disabled
+            placeholder="请选择"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6" v-if="form.associationType == '2'">
+        <el-form-item label="销售订单:">
+          <el-input
+            v-model="form.orderCode"
+            readonly
+            disabled
+            placeholder="请选择"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6" v-if="form.associationType == '3'">
+        <el-form-item label="产品:">
+          <el-input
+            v-model="form.orderCode"
+            readonly
+            disabled
+            placeholder="请选择"
+          />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="6">
+        <el-form-item label="客户编码:">
+          <el-input v-model="form.contractInfo.code" readonly disabled />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="客户代号:">
+          <el-input v-model="form.contractInfo.serialNo" readonly disabled />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="业务员:">
+          <el-select
+            style="width: 100%"
+            v-model="form.salespersonId"
+            placeholder="请选择业务员"
+            filterable
+            clearable
+            disabled
+          >
+            <el-option
+              v-for="item in userList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="报修地址:">
+          <el-input v-model="form.contactAddress" readonly disabled />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="6">
+        <el-form-item label="故障等级:">
+          <DictSelection
+            dictName="故障等级"
+            disabled
+            v-model="form.faultLevel"
+          ></DictSelection>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="期望解决时间:">
+          <el-date-picker
+            disabled
+            style="width: 100%"
+            v-model="form.expectedTime"
+            type="date"
+            :picker-options="pickerOptions"
+            placeholder="选择日期时间"
+          ></el-date-picker>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="售后类型:">
+          <el-select
+            style="width: 100%"
+            v-model="form.aftertype"
+            placeholder="请选择"
+            disabled
+          >
+            <el-option
+              v-for="item in aftertypeList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="是否收费:">
+          <el-select
+            style="width: 100%"
+            v-model="form.charge"
+            placeholder="请选择"
+            disabled
+          >
+            <el-option
+              v-for="item in chargeList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="6">
+        <el-form-item label="是否带配件:">
+          <el-select
+            style="width: 100%"
+            v-model="form.part"
+            placeholder="请选择"
+            disabled
+          >
+            <el-option
+              v-for="item in partList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="是否派车:">
+          <el-select
+            style="width: 100%"
+            v-model="form.car"
+            placeholder="请选择是否派车"
+            disabled
+          >
+            <el-option
+              v-for="item in carList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6" v-if="form.car == '1'">
+        <el-form-item label="派车类型:">
+          <el-select
+            style="width: 100%"
+            v-model="form.pietype"
+            placeholder="请选择"
+            disabled
+          >
+            <el-option
+              v-for="item in pietypeList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="是否外包:">
+          <el-select
+            style="width: 100%"
+            v-model="form.isOutsource"
+            placeholder="请选择是否外包"
+            disabled
+          >
+            <el-option
+              v-for="item in outsourceList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="6" v-if="form.isOutsource == '1'">
+        <el-form-item label="供应商名称:">
+          <el-input
+            v-model="form.supplierName"
+            placeholder="请选择供应商名称"
+            readonly
+            disabled
+          ></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="是否生成采购订单:">
+          <el-select
+            style="width: 100%"
+            v-model="form.isCreatePurchaseOrder"
+            placeholder="请选择是否生成采购订单"
+            disabled
+          >
+            <el-option
+              v-for="item in isCreatePurchaseOrderList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="涉及事业部门:">
+          <ele-tree-select
+            v-model="form.involveDeptId"
+            :data="deptTreeData"
+            label-key="name"
+            value-key="id"
+            clearable
+            default-expand-all
+            placeholder="请选择"
+            disabled
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="6">
+        <el-form-item label="备注说明:" class="remark-input">
+          <el-input
+            v-model="form.remark"
+            type="textarea"
+            rows="2"
+            placeholder="请输入备注信息(选填)"
+            readonly
+            disabled
+          ></el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <!-- 售后方案区域 -->
+    <headerTitle
+      title="售后方案"
+      style="margin-top: 10px"
+      v-if="isPurchaseNeed"
+    ></headerTitle>
+    <spareParts
+      ref="sparePartsRef"
+      type="view"
+      :source="source"
+      obtain="售后"
+      :is-after-sales="true"
+      v-if="isPurchaseNeed"
+    />
+
+    <!-- 售后对象/故障信息区域 -->
+    <div class="after_sales_target" v-if="salesShow">
+      <headerTitle
+        title="售后对象"
+        style="margin-top: 10px"
+        v-if="isPurchaseNeed"
+      ></headerTitle>
+      <ele-pro-table
+        ref="tableRef3"
+        :columns="columnsDetail"
+        :datasource="form.tableList"
+        :need-page="false"
+        :toolbar="false"
+        maxHeight="300px"
+        row-key="id"
+        default-expand-all
+      >
+        <template v-slot:measureQuantity="{ row }">
+          <el-input
+            v-model="row.measureQuantity"
+            type="number"
+            :min="1"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:batchNo="{ row }">
+          <el-input
+            v-model="row.batchNo"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:barcodes="{ row }">
+          <el-input
+            v-model="row.barcodes"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:shipmentDate="{ row }">
+          <el-date-picker
+            v-model="row.shipmentDate"
+            type="datetime"
+            placeholder="选择结束时间"
+            format="yyyy-MM-dd HH:mm:ss"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            disabled
+          ></el-date-picker>
+        </template>
+
+        <template v-slot:expand="{ row, $index }">
+          <div
+            style="
+              width: calc(100% - 55px);
+              min-height: 60px;
+              margin-left: 55px;
+            "
+            v-if="row.faultDetails && row.faultDetails.length > 0"
+          >
+            <ele-pro-table
+              :columns="faultList"
+              :datasource="row.faultDetails || []"
+              :need-page="false"
+              maxHeight="300px"
+              class="el-form-box"
+              :toolkit="[]"
+            >
+              <template v-slot:type="{ row }">
+                <el-select
+                  v-model="row.type"
+                  disabled
+                  :placeholder="
+                    form.aftertype === '3' ? '请选择质量类型' : '请选择故障类型'
+                  "
+                >
+                  <el-option
+                    v-for="item in form.aftertype === '3'
+                      ? qualityTypeOptions
+                      : typeOptions"
+                    :key="item.value"
+                    :label="item.label"
+                    :value="item.value"
+                  ></el-option>
+                </el-select>
+              </template>
+              <template v-slot:faultPhenomenon="{ row }">
+                <el-input
+                  v-model="row.faultPhenomenon"
+                  placeholder="请输入"
+                  disabled
+                ></el-input>
+              </template>
+              <template v-slot:faultReason="{ row }">
+                <el-input
+                  v-model="row.faultReason"
+                  placeholder="请输入"
+                  disabled
+                ></el-input>
+              </template>
+              <template v-slot:maintenanceProcess="{ row }">
+                <el-input
+                  v-model="row.maintenanceProcess"
+                  placeholder="请输入"
+                  disabled
+                ></el-input>
+              </template>
+              <template v-slot:attachments="{ row }">
+                <fileMain v-model="row.attachments" type="view"></fileMain>
+              </template>
+
+              <template v-slot:headerType="{ column }">
+                <span>{{
+                  form.aftertype === '3' ? '质量类型' : column.label
+                }}</span>
+              </template>
+              <template v-slot:headerPhenomenon="{ column }">
+                <span>{{
+                  form.aftertype === '3' ? '质量问题反馈' : column.label
+                }}</span>
+              </template>
+              <template v-slot:headerMaintenance="{ column }">
+                <span>{{
+                  form.aftertype === '3' ? '质量处理方式' : column.label
+                }}</span>
+              </template>
+              <template v-slot:headerFaultReason="{ column }">
+                <span>{{
+                  form.aftertype === '3' ? '质量问题分析' : column.label
+                }}</span>
+              </template>
+            </ele-pro-table>
+          </div>
+        </template>
+
+        <template v-slot:useLocation="{ row }">
+          <el-input v-model="row.useLocation" disabled></el-input>
+        </template>
+      </ele-pro-table>
+    </div>
+
+    <div class="fault_infor" v-else>
+      <headerTitle
+        title="故障信息"
+        style="margin-top: 10px"
+        v-if="form.aftertype !== '3'"
+      ></headerTitle>
+      <headerTitle
+        title="质量反馈信息"
+        style="margin-top: 10px"
+        v-if="form.aftertype === '3'"
+      ></headerTitle>
+
+      <ele-pro-table
+        :columns="faultList"
+        :datasource="form.faultDetailList"
+        :need-page="false"
+        maxHeight="300px"
+        class="el-form-box"
+        :toolkit="[]"
+      >
+        <template v-slot:type="{ row }">
+          <el-select
+            v-model="row.type"
+            disabled
+            :placeholder="
+              form.aftertype === '3' ? '请选择质量类型' : '请选择故障类型'
+            "
+          >
+            <el-option
+              v-for="item in form.aftertype === '3'
+                ? qualityTypeOptions
+                : typeOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </template>
+        <template v-slot:faultPhenomenon="{ row }">
+          <el-input
+            v-model="row.faultPhenomenon"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:faultReason="{ row }">
+          <el-input
+            v-model="row.faultReason"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:maintenanceProcess="{ row }">
+          <el-input
+            v-model="row.maintenanceProcess"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </template>
+        <template v-slot:attachments="{ row }">
+          <fileMain v-model="row.attachments" type="view"></fileMain>
+        </template>
+
+        <template v-slot:headerType="{ column }">
+          <span>{{ form.aftertype === '3' ? '质量类型' : column.label }}</span>
+        </template>
+        <template v-slot:headerPhenomenon="{ column }">
+          <span>{{
+            form.aftertype === '3' ? '质量问题反馈' : column.label
+          }}</span>
+        </template>
+        <template v-slot:headerMaintenance="{ column }">
+          <span>{{
+            form.aftertype === '3' ? '质量处理方式' : column.label
+          }}</span>
+        </template>
+        <template v-slot:headerFaultReason="{ column }">
+          <span>{{
+            form.aftertype === '3' ? '质量问题分析' : column.label
+          }}</span>
+        </template>
+      </ele-pro-table>
+    </div>
+
+    <!-- 联系人信息区域 -->
+    <headerTitle
+      title="联系人信息"
+      style="margin-top: 10px"
+      v-if="isPurchaseNeed"
+    ></headerTitle>
+    <ele-pro-table
+      :style="{ marginTop: isPurchaseNeed ? 0 : '10px' }"
+      ref="table"
+      :columns="bankColumns"
+      :datasource="form.contactInfoVOS"
+      :toolkit="[]"
+      class="el-form-box"
+      :need-page="false"
+      v-if="source != '报工信息'"
+    >
+      <template v-slot:contactName="{ row }">
+        <el-input
+          v-model="row.contactName"
+          placeholder="请输入"
+          disabled
+          maxlength="50"
+        ></el-input>
+      </template>
+      <template v-slot:contactPhone="{ row }">
+        <el-input
+          v-model="row.contactPhone"
+          placeholder="请输入"
+          disabled
+        ></el-input>
+      </template>
+      <template v-slot:post="{ row }">
+        <el-input v-model="row.post" placeholder="请输入" disabled></el-input>
+      </template>
+      <template v-slot:telephone="{ row }">
+        <el-input
+          v-model="row.telephone"
+          placeholder="请输入"
+          disabled
+        ></el-input>
+      </template>
+      <template v-slot:email="{ row }">
+        <el-input v-model="row.email" placeholder="请输入" disabled></el-input>
+      </template>
+      <template v-slot:wechat="{ row }">
+        <el-input v-model="row.wechat" placeholder="请输入" disabled></el-input>
+      </template>
+      <template v-slot:deptName="{ row }">
+        <el-input
+          v-model="row.deptName"
+          placeholder="请输入"
+          disabled
+        ></el-input>
+      </template>
+      <template v-slot:remark="{ row }">
+        <el-input v-model="row.remark" placeholder="请输入" disabled></el-input>
+      </template>
+    </ele-pro-table>
+  </el-form>
+</template>
+
+<script>
+import fileMain from '@/components/addDoc/index.vue';
+import dictMixins from '@/mixins/dictMixins';
+import { mapGetters } from 'vuex';
+import spareParts from './sparePartsList.vue';
+import { getByCode } from '@/api/system/dictionary-data';
+import { listOrganizations } from '@/api/system/organization';
+import { getUserPage } from '@/api/system/organization';
+import { getSalesDemandById, contactDetail } from '@/api/afterSales/index';
+
+export default {
+  mixins: [dictMixins],
+  components: {
+    fileMain,
+    spareParts
+  },
+  computed: {
+    ...mapGetters(['getDictValue']),
+    sxtValueLabelMap() {
+      return this.sxtList.reduce((map, item) => {
+        map[item.value] = item.label;
+        return map;
+      }, {});
+    },
+    salesShow() {
+      if (this.form.associationType === '1') return true;
+      if (this.form.tableList.length > 0) return true;
+      if (this.form.associationType === '2' && !this.isOrder) return true;
+      return false;
+    },
+    bankColumns() {
+      return [
+        {
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center'
+        },
+        {
+          label: '姓名',
+          prop: 'contactName',
+          slot: 'contactName',
+          align: 'center'
+        },
+        {
+          label: '手机',
+          prop: 'contactPhone',
+          slot: 'contactPhone',
+          align: 'center'
+        },
+        {
+          label: '电话',
+          prop: 'telephone',
+          slot: 'telephone',
+          align: 'center'
+        },
+        {
+          label: '微信号',
+          prop: 'wechat',
+          slot: 'wechat',
+          align: 'center'
+        },
+        {
+          label: '邮箱',
+          prop: 'email',
+          slot: 'email',
+          align: 'center'
+        },
+        {
+          label: '部门',
+          prop: 'deptName',
+          slot: 'deptName',
+          align: 'center'
+        },
+        {
+          label: '职务',
+          prop: 'post',
+          slot: 'post',
+          align: 'center'
+        },
+        {
+          label: '备注',
+          prop: 'remark',
+          slot: 'remark',
+          align: 'center'
+        }
+      ];
+    },
+    columnsDetail() {
+      return [
+        {
+          columnKey: 'index',
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          width: 45,
+          type: 'expand',
+          columnKey: 'expand',
+          align: 'center',
+          slot: 'expand'
+        },
+        {
+          prop: 'productCategoryName',
+          label: '类型',
+          align: 'center',
+          showOverflowTooltip: true,
+          width: 200
+        },
+        {
+          prop: 'categoryCode',
+          label: '编码',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'categoryName',
+          label: '名称',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'categoryModel',
+          label: '型号',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          slot: 'batchNo',
+          prop: 'batchNo',
+          label: '批次号',
+          align: 'center',
+          minWidth: 135
+        },
+        {
+          slot: 'barcodes',
+          prop: 'barcodes',
+          label: '发货条码',
+          align: 'center',
+          minWidth: 135
+        },
+        {
+          slot: 'shipmentDate',
+          prop: 'shipmentDate',
+          label: '发货时间',
+          align: 'center',
+          minWidth: 180
+        },
+        {
+          prop: 'guaranteePeriodDeadline',
+          label: '有效期',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'warrantyStatus',
+          label: '质保状态',
+          align: 'center',
+          showOverflowTooltip: true,
+          formatter: (_row) =>
+            _row.warrantyStatus === 1 ? '有效期外' : '有效期内'
+        },
+        {
+          slot: 'measureQuantity',
+          prop: 'measureQuantity',
+          label: '计量数量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'singlePrice',
+          label: '单价(元)',
+          align: 'center',
+          showOverflowTooltip: true
+        }
+      ];
+    },
+    faultList() {
+      const isQualityScene = this.form.aftertype === '3';
+      return [
+        {
+          type: 'index',
+          label: '序号',
+          align: 'center',
+          width: 60
+        },
+        {
+          prop: 'type',
+          slot: 'type',
+          label: isQualityScene ? '质量类型' : '故障类型',
+          align: 'center',
+          headerSlot: 'headerType',
+          showOverflowTooltip: true,
+          width: 120
+        },
+        {
+          prop: 'faultPhenomenon',
+          slot: 'faultPhenomenon',
+          headerSlot: 'headerPhenomenon',
+          label: isQualityScene ? '质量问题反馈' : '故障现象',
+          align: 'center',
+          minWidth: 240
+        },
+        {
+          prop: 'faultReason',
+          slot: 'faultReason',
+          headerSlot: 'headerFaultReason',
+          label: isQualityScene ? '质量问题分析' : '故障原因',
+          align: 'center',
+          minWidth: 340
+        },
+        {
+          prop: 'maintenanceProcess',
+          slot: 'maintenanceProcess',
+          headerSlot: 'headerMaintenance',
+          label: isQualityScene ? '质量处理方式' : '维修过程',
+          align: 'center',
+          width: 340
+        },
+        {
+          prop: 'imageUrl',
+          slot: 'imageUrl',
+          label: '查看拍照',
+          align: 'center',
+          width: 120
+        }
+      ];
+    },
+    tableOperate() {
+      return false;
+    },
+    faultOperate() {
+      return () => false;
+    },
+    change_permission() {
+      return true;
+    },
+    fileStr() {
+      return 'view';
+    },
+    imageUrleng() {
+      return (row) => (row.imageUrl ? row.imageUrl.length : 0);
+    }
+  },
+  props: {
+    businessId: {
+      default: '',
+      required: true
+    },
+    isPurchaseNeed: {
+      default: true,
+      type: Boolean
+    },
+    source: {
+      default: '',
+      type: String
+    },
+    demandList: {
+      type: Array,
+      default: () => []
+    }
+  },
+  watch: {
+    demandList: {
+      handler(val) {
+        this.demandList = val;
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  data() {
+    return {
+      userList: [],
+      pickerOptions: {
+        disabledDate(time) {
+          return time.getTime() < new Date().setHours(0, 0, 0, 0);
+        }
+      },
+      detailList: [],
+      chargeList: [
+        { label: '是', value: '1' },
+        { label: '否', value: '0' }
+      ],
+      partList: [
+        { label: '是', value: '1' },
+        { label: '否', value: '0' }
+      ],
+      carList: [
+        { label: '是', value: '1' },
+        { label: '否', value: '0' }
+      ],
+      typeOptions: [
+        { label: '维修', value: '1' },
+        { label: '保养', value: '2' },
+        { label: '安装', value: '3' }
+      ],
+      qualityTypeOptions: [],
+      outsourceList: [
+        { label: '是', value: '1' },
+        { label: '否', value: '0' }
+      ],
+      isCreatePurchaseOrderList: [
+        { label: '是', value: '1' },
+        { label: '否', value: '0' }
+      ],
+      sxtList: [
+        { label: '自制件', value: '1' },
+        { label: '采购件', value: '2' },
+        { label: '外协件', value: '3' },
+        { label: '受托件', value: '4' }
+      ],
+      form: {
+        contractInfo: {},
+        tableList: [],
+        contactInfoVOS: [],
+        faultDetailList: [],
+        associationType: '1',
+        aftertype: '',
+        salespersonName: '',
+        salespersonId: '',
+        charge: '',
+        part: '',
+        car: '',
+        pietype: '',
+        isOutsource: '0',
+        isCreatePurchaseOrder: '0',
+        supplierName: '',
+        supplierId: '',
+        supplierCode: '',
+        involveDeptId: '',
+        involveDeptName: '',
+        remark: ''
+      },
+      rules: {},
+      associationTypeList: [
+        { value: '1', label: '发货单' },
+        { value: '2', label: '销售订单' },
+        { value: '3', label: '客户' }
+      ],
+      isOrder: false,
+      aftertypeList: [],
+      pietypeList: [],
+      deptTreeData: []
+    };
+  },
+  async created() {
+    // 独立加载每个字典,单独捕获错误,不阻塞整体流程
+    await this.loadDict('after_sales_type', 'aftertypeList', '售后类型');
+    await this.loadDict('pie_car_type', 'pietypeList', '派车类型');
+    await this.loadDict('after_sale_quality_type', 'qualityTypeOptions', '质量类型');
+    
+    // 其他初始化操作
+    await this.getUserList().catch(err => {
+      this.$message.error(`获取用户列表失败:${err.message}`);
+    });
+    await this.getDeptTreeData().catch(err => {
+      this.$message.error(`获取部门数据失败:${err.message}`);
+    });
+  },
+  mounted() {
+    this.getDetail(this.businessId);
+  },
+  methods: {
+    async getDetail(id) {
+      try {
+        const res = await getSalesDemandById(id);
+        if (!res || res.code !== '0' || !res.data) {
+          this.$message.error('获取详情失败:接口返回异常');
+          return;
+        }
+        this.init(res.data);
+      } catch (err) {
+        this.$message.error(`获取详情失败:${err.message}`);
+      }
+    },
+    /**
+     * 通用字典加载方法(核心修改:兼容数组/对象两种数据格式)
+     * @param {String} dictCode - 字典编码(如pie_car_type)
+     * @param {String} targetKey - 存储字典的data属性名(如pietypeList)
+     * @param {String} dictName - 字典名称(用于错误提示)
+     */
+    async loadDict(dictCode, targetKey, dictName) {
+      try {
+        const res = await getByCode(dictCode);
+        // 1. 基础校验:接口是否返回成功且有数据
+        if (res.code !== '0' || !res.data) { // 注意:接口返回code是字符串"0",需匹配类型
+          throw new Error(`接口返回异常(code: ${res.code},data: ${res.data ? '存在' : '不存在'})`);
+        }
+
+        // 2. 核心修改:兼容数组/对象两种格式的data
+        let dictItems = [];
+        if (Array.isArray(res.data)) {
+          // 格式1:data是数组(如[{ "1": "工时" }, { "2": "零配件" }])
+          dictItems = res.data;
+        } else {
+          // 格式2:data是对象(如{ "1": "工时", "2": "零配件" })
+          dictItems = Object.values(res.data);
+        }
+
+        // 3. 解析字典数据:提取键值对,确保value为字符串
+        const dictData = dictItems.map(el => {
+          // 每个el是单个键值对对象(如{ "1": "工时" })
+          const key = Object.keys(el)[0];
+          const value = Object.values(el)[0];
+          return { 
+            label: value || '', // 防止label为空
+            value: String(key)  // 强制转为字符串,与表单value类型匹配
+          };
+        });
+
+        // 4. 赋值到目标变量
+        this[targetKey] = dictData;
+        console.log(`【${dictName}】字典加载成功:`, dictData); // 可选:调试用
+      } catch (err) {
+        // 单独提示某个字典失败,不影响其他功能
+        this.$message.warning(`获取${dictName}字典失败:${err.message}`);
+        // 赋值空数组,避免渲染报错
+        this[targetKey] = [];
+      }
+    },
+    async getDeptTreeData() {
+      const deptRes = await listOrganizations();
+      this.deptTreeData = this.$util.toTreeData({
+        data: deptRes || [],
+        idField: 'id',
+        parentIdField: 'parentId'
+      });
+    },
+    async getUserList() {
+      const res = await getUserPage({ pageNum: 1, pageSize: -1 });
+      this.userList = res?.list || [];
+    },
+    init(res) {
+      const productDetail = res.productDetail || [];
+      this.$set(this.form, 'tableList', productDetail);
+      this.$set(this.form, 'orderCode', res.orderCode);
+      this.$set(this.form, 'orderId', res.orderId);
+      this.$set(this.form, 'contactInfoVOS', res.contactInfoVOS || []);
+      this.$set(this.form, 'name', res.name);
+      this.$set(this.form, 'faultLevel', res.faultLevel ? String(res.faultLevel) : '');
+      this.$set(this.form, 'code', res.code);
+      this.$set(this.form, 'expectedTime', res.expectedTime);
+      this.$set(this.form, 'contactAddress', res.contactAddress || '');
+
+      this.contactDetail(res.contactId, 'init');
+      this.form.associationType = res.associationType ? String(res.associationType) : '1';
+      this.$set(this.form, 'faultDetailList', res.faultDetailList || []);
+      this.isOrder = res.faultDetailList?.length > 0;
+
+      this.$set(this.form, 'aftertype', res.afterSalesType ? String(res.afterSalesType) : '');
+      this.$set(this.form, 'charge', res.isFee !== undefined ? String(res.isFee) : '');
+      this.$set(this.form, 'part', res.isWithAccessories !== undefined ? String(res.isWithAccessories) : '');
+      this.$set(this.form, 'car', res.isPieCar !== undefined ? String(res.isPieCar) : '');
+      this.$set(this.form, 'pietype', res.pieCarType ? String(res.pieCarType) : '');
+      this.$set(this.form, 'salespersonName', res.salespersonName || '');
+      this.$set(this.form, 'salespersonId', res.salespersonId || '');
+      this.$set(this.form, 'isOutsource', res.isOutsource !== undefined ? String(res.isOutsource) : '0');
+      this.$set(this.form, 'isCreatePurchaseOrder', res.isCreatePurchaseOrder !== undefined ? String(res.isCreatePurchaseOrder) : '0');
+      this.$set(this.form, 'remark', res.remark || '');
+      this.$set(this.form, 'involveDeptId', res.involveDeptId ?? '');
+      this.$set(this.form, 'involveDeptName', res.involveDeptName ?? '');
+      this.$set(this.form, 'supplierId', res.supplierId ?? '');
+      this.$set(this.form, 'supplierName', res.supplierName ?? '');
+      this.$set(this.form, 'supplierCode', res.supplierCode ?? '');
+      this.$set(this, 'detailList', res.costListVOS || []);
+
+      this.$nextTick(() => {
+        if (this.$refs.sparePartsRef && this.detailList.length > 0) {
+          this.$refs.sparePartsRef.setTableValue(this.detailList);
+        }
+      });
+    },
+    async contactDetail(id, type) {
+      if (!id) {
+        this.contractInfo = {};
+        return;
+      }
+      try {
+        const { base, other } = await contactDetail(id);
+        base.contactName = base.name;
+        const addressName = `${other.addressName || ''}${other.address || ''}`;
+        this.$set(this.form, 'contractInfo', base);
+        if (type !== 'init') {
+          this.$set(this.form, 'contactAddress', addressName);
+        }
+      } catch (err) {
+        this.$message.error(`获取客户详情失败:${err.message}`);
+      }
+    },
+    getValue() {
+      return this.form;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+:deep(.el-table__body .el-form-item__content) {
+  margin-left: 0px !important;
+}
+:deep(.el-table__body .el-form-item) {
+  margin-bottom: 0px !important;
+}
+.reserve {
+  margin-left: 16px;
+  color: #e6a23c;
+}
+:deep(.el-row) {
+  display: flex;
+  flex-wrap: wrap;
+}
+:deep(.remark-input .el-textarea__inner) {
+  color: #f56c6c !important;
+}
+:deep(.remark-input .el-textarea.is-disabled .el-textarea__inner) {
+  color: #f56c6c !important;
+}
+</style>

+ 474 - 0
src/views/bpm/handleTask/components/salesServiceManagement/demand/sparePartsList.vue

@@ -0,0 +1,474 @@
+<template>
+  <div class="ele-body">
+    <el-form ref="form" :model="form" label-width="100px" class="create-form">
+      <ele-pro-table
+        ref="tableRef2"
+        :columns="columnsDetail"
+        :datasource="form.tableList"
+        tool-class="ele-toolbar-form"
+        :initLoad="false"
+        :need-page="false"
+        height="300px"
+      >
+        <!-- 工具栏:仅保留合计显示,隐藏添加按钮 -->
+        <template v-slot:toolbar>
+          <div class="toobar toobar_r">
+            <span class="total_price">总计: {{ totalPrice }} (元)</span>
+          </div>
+        </template>
+
+        <!-- 项目类型:禁用下拉 -->
+        <template v-slot:typeId="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.typeId'"
+          >
+            <el-select
+              v-model="scope.row.typeId"
+              placeholder="请选择"
+              class="w100"
+              disabled
+            >
+              <el-option
+                v-for="item in typeIdList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </template>
+
+        <!-- 费用类别:禁用下拉 -->
+        <template v-slot:feeType="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.feeType'"
+          >
+            <el-select
+              v-model="scope.row.feeType"
+              placeholder="请选择"
+              class="w100"
+              disabled
+            >
+              <el-option
+                v-for="item in feeTypeList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+        </template>
+
+        <!-- 编码:纯文本展示 -->
+        <template v-slot:code="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.code'"
+          >
+            <span>{{ scope.row.code || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 名称:纯文本展示(隐藏选择按钮) -->
+        <template v-slot:name="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.name'"
+          >
+            <span>{{ scope.row.name || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 型号:纯文本展示 -->
+        <template v-slot:categoryModel="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.categoryModel'"
+          >
+            <span>{{ scope.row.categoryModel || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 规格:纯文本展示 -->
+        <template v-slot:specification="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.specification'"
+          >
+            <span>{{ scope.row.specification || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 详细内容:纯文本展示 -->
+        <template v-slot:content="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.content'"
+          >
+            <span>{{ scope.row.content || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 数量:纯文本展示 -->
+        <template v-slot:totalCount="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.totalCount'"
+          >
+            <span>{{ scope.row.totalCount || '0' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 单位:纯文本展示 -->
+        <template v-slot:measureUnit="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.measureUnit'"
+          >
+            <span>{{ scope.row.measureUnit || '-' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 单价:纯文本展示 -->
+        <template v-slot:singlePrice="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.singlePrice'"
+          >
+            <span>{{ scope.row.singlePrice || '0' }}</span>
+          </el-form-item>
+        </template>
+
+        <!-- 仓库:纯文本展示(显示仓库名称,隐藏下拉) -->
+        <template v-slot:warehouseId="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'tableList.' + scope.$index + '.warehouseId'"
+          >
+            <span>{{ scope.row.warehouseName || '-' }}</span>
+          </el-form-item>
+        </template>
+
+      </ele-pro-table>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { getWarehouseOutStock, getIdWarehouseList } from '@/api/afterSales/index';
+import { getByCode } from '@/api/system/dictionary-data';
+
+export default {
+  components: {},
+  props: {
+    source: {
+      default: '',
+      type: String
+    },
+    detailList: {
+      type: Array,
+      default: () => []
+    },
+    obtain: {
+      type: String,
+      default: '主数据'
+    },
+    hideFeeType: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      form: {
+        tableList: [] // 展示用数据列表
+      },
+      totalPrice: 0, // 合计金额(保留展示)
+      typeIdList: [], // 项目类型字典(核心修复点)
+      feeTypeList: [ // 费用类别字典(硬编码,已适配字符串value)
+        { label: '收入', value: '1' },
+        { label: '支出', value: '2' }
+      ]
+    };
+  },
+  created() {
+    // 初始化项目类型字典(修复后)
+    if (this.source !== '配件回收') { // 配件回收场景固定字典,无需请求
+      this.getLevelCode('after_sales_project');
+    }
+  },
+  computed: {
+    // 表格列配置:隐藏操作列,调整展示逻辑
+    columnsDetail() {
+      return [
+        {
+          columnKey: 'index',
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'typeId',
+          label: '项目',
+          align: 'center',
+          width: 120,
+          slot: 'typeId',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'code',
+          label: '编码',
+          align: 'center',
+          slot: 'code',
+          minWidth: 150,
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'feeType',
+          label: '费用类别',
+          align: 'center',
+          slot: 'feeType',
+          minWidth: 150,
+          showOverflowTooltip: true,
+          show: !this.hideFeeType // 保留原隐藏逻辑
+        },
+        {
+          prop: 'name',
+          label: '名称',
+          align: 'center',
+          minWidth: 250,
+          slot: 'name',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'categoryModel',
+          label: '型号',
+          width: 150,
+          align: 'center',
+          slot: 'categoryModel',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'specification',
+          width: 150,
+          label: '规格',
+          slot: 'specification',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'content',
+          minWidth: 300,
+          slot: 'content',
+          label: '详细内容',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'warehouseId',
+          minWidth: 170,
+          slot: 'warehouseId',
+          label: '仓库',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'warehouseNum',
+          minWidth: 100,
+          label: '库存',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'totalCount',
+          slot: 'totalCount',
+          width: 100,
+          label: '数量',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'measureUnit',
+          width: 120,
+          slot: 'measureUnit',
+          label: '单位',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'singlePrice',
+          slot: 'singlePrice',
+          width: 120,
+          label: '单价(元)',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        {
+          prop: 'settlementPrice',
+          width: 80,
+          label: '合计(元)',
+          align: 'center',
+          showOverflowTooltip: true
+        },
+        // 完全隐藏操作列
+        {
+          columnKey: 'action',
+          label: '操作',
+          width: 150,
+          align: 'center',
+          resizable: false,
+          slot: 'action',
+          fixed: 'right',
+          showOverflowTooltip: true,
+          show: false
+        }
+      ];
+    },
+    // 以下计算属性均返回固定值,确保操作元素不显示、组件禁用
+    chooseShow() {
+      return () => false; // 隐藏"选择"按钮
+    },
+    buttonJud() {
+      return false; // 隐藏"添加"按钮
+    },
+    schemeOperate() {
+      return () => false; // 隐藏"删除"按钮
+    },
+    schemeTableTool() {
+      return () => true; // 所有表格组件禁用
+    },
+    inputOperate() {
+      return () => true; // 所有输入组件禁用
+    }
+  },
+  watch: {
+    // 监听传入的详情数据,格式化后渲染(修复:类型Id转字符串)
+    detailList: {
+      handler(newVal) {
+        const formattedList = newVal.map((item) => ({
+          ...item,
+          feeType: (item.feeType || '1').toString(), // 费用类别转字符串
+          typeId: (item.typeId || '').toString(), // 项目类型转字符串(核心修复)
+          warehouseName: item.warehouseName || '', // 确保仓库名称有值
+          settlementPrice: item.settlementPrice || (Number(item.totalCount) * Number(item.singlePrice) || 0) // 补全合计金额(修复数字计算)
+        }));
+        this.form.tableList = formattedList;
+        this.calculatePrice(); // 计算合计
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    // 配件回收场景:固定项目类型为"零配件"(确保value是字符串)
+    if (this.source === '配件回收') {
+      this.typeIdList = [{ label: '零配件', value: '2' }];
+      // 触发一次数据格式化(防止watch未覆盖)
+      if (this.detailList.length > 0) {
+        this.watch.detailList.handler(this.detailList);
+      }
+    }
+  },
+  methods: {
+    // 初始化项目类型字典(核心修复:兼容接口格式+类型匹配)
+    async getLevelCode(code) {
+      try {
+        const res = await getByCode(code);
+        // 修复1:接口code是字符串"0",而非数字0
+        if (res.code !== '0' || !res.data) {
+          throw new Error(`接口返回异常(code: ${res.code})`);
+        }
+
+        // 修复2:兼容接口返回的"数组"或"对象"格式
+        let dictItems = [];
+        if (Array.isArray(res.data)) {
+          dictItems = res.data; // 格式1:[{ "1": "工时" }, { "2": "零配件" }]
+        } else {
+          dictItems = Object.values(res.data); // 格式2:{ "1": "工时", "2": "零配件" }
+        }
+
+        // 修复3:解析为label-value格式,确保value是字符串
+        this.typeIdList = dictItems.map(el => {
+          const key = Object.keys(el)[0];
+          const value = Object.values(el)[0];
+          return {
+            label: value || '', // 防止空label
+            value: String(key) // 强制转为字符串,与表单typeId匹配
+          };
+        });
+
+        console.log('项目类型字典加载成功:', this.typeIdList); // 调试用
+      } catch (err) {
+        this.$message.error(`获取项目类型字典失败:${err.message}`);
+        this.typeIdList = []; // 避免渲染报错
+      }
+    },
+    // 计算合计金额(修复:确保数字类型计算)
+    calculatePrice() {
+      this.totalPrice = this.form.tableList.reduce((total, item) => {
+        return total + (Number(item.settlementPrice) || 0); // 转为数字计算
+      }, 0);
+    },
+    // 接收外部数据并格式化(修复:项目类型转字符串)
+    async setTableValue(val) {
+      const tableList = JSON.parse(JSON.stringify(val));
+      for (const item of tableList) {
+        // 格式化基础字段(确保类型匹配)
+        item.feeType = (item.feeType || '1').toString();
+        item.typeId = (item.typeId || '').toString(); // 项目类型转字符串
+        item.categoryCode = item.categoryCode || item.code;
+        item.categoryName = item.categoryName || item.name;
+        item.settlementPrice = item.settlementPrice || (Number(item.totalCount) * Number(item.singlePrice) || 0);
+        
+        // 补充仓库数据(仅用于展示)
+        if (item.typeId === '2' && item.categoryId) {
+          try {
+            item.warehouseList = await getIdWarehouseList({ categoryId: item.categoryId });
+            if (item.warehouseId) {
+              item.warehouseNum = await getWarehouseOutStock({
+                warehouseId: item.warehouseId,
+                code: item.code
+              });
+            }
+          } catch (err) {
+            console.error('获取仓库数据失败:', err);
+            item.warehouseList = [];
+            item.warehouseNum = 0;
+          }
+        }
+      }
+      this.form.tableList = tableList;
+      this.calculatePrice(); // 重新计算合计
+    },
+    // 获取当前展示数据(保留用于外部获取数据)
+    getTableValue() {
+      return this.form.tableList;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+:deep(.el-table__body .el-form-item__content) {
+  margin-left: 0px !important;
+}
+:deep(.el-table__body .el-form-item) {
+  margin-bottom: 0px !important;
+}
+.total_price {
+  margin-left: 24px;
+}
+.toobar {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding-right: 16px;
+}
+.toobar_r {
+  justify-content: flex-end;
+}
+</style>

+ 224 - 172
src/views/bpm/handleTask/formParser/formParserDialog.vue

@@ -35,48 +35,91 @@
               style="width: calc(100% - 80px)"
             ></el-input>
           </div>
-
         </div>
       </template>
       <!-- 客户名称 -->
-            <template v-slot:eom_contact="scope">
-              <div class="eom_contact">
-                <el-input
-                    v-model="scope.model.eom_contact.name"
-                    style="width: 100%"
-                  ></el-input>
-              </div>
-            </template>
-
-            <!-- 差旅 -->
-            <template v-slot:blank_business_component="scope">
-              <businessComponent  ref="blank_business_component" id="blank_business_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></businessComponent>
-            </template>
+      <template v-slot:eom_contact="scope">
+        <div class="eom_contact">
+          <el-input
+            v-model="scope.model.eom_contact.name"
+            style="width: 100%"
+          ></el-input>
+        </div>
+      </template>
+      <!-- 关联工单 -->
+      <template v-slot:manage_workorder="scope">
+        <div class="manage_workorder">
+          <el-input
+            v-model="scope.model.manage_workorder.code"
+            style="width: 100%"
+          ></el-input>
+        </div>
+      </template>
+      <!-- 差旅 -->
+      <template v-slot:blank_business_component="scope">
+        <businessComponent
+          ref="blank_business_component"
+          id="blank_business_component"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></businessComponent>
+      </template>
 
-            <!-- 印章使用 -->
-            <template v-slot:blank_use_seal="scope">
-              <useSealComponent  ref="blank_use_seal" id="blank_use_seal" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></useSealComponent>
-            </template>
+      <!-- 印章使用 -->
+      <template v-slot:blank_use_seal="scope">
+        <useSealComponent
+          ref="blank_use_seal"
+          id="blank_use_seal"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></useSealComponent>
+      </template>
 
-            <!-- 资质使用 -->
-            <template v-slot:blank_use_qualification="scope">
-              <useQualificationComponent  ref="blank_use_qualification" id="blank_use_qualification" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></useQualificationComponent>
-            </template>
+      <!-- 资质使用 -->
+      <template v-slot:blank_use_qualification="scope">
+        <useQualificationComponent
+          ref="blank_use_qualification"
+          id="blank_use_qualification"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></useQualificationComponent>
+      </template>
 
-            <!-- 产品规格 -->
-            <template v-slot:blank_product_specification="scope">
-              <productSpecificationComponent  ref="blank_product_specification" id="blank_product_specification" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></productSpecificationComponent>
-            </template>
+      <!-- 产品规格 -->
+      <template v-slot:blank_product_specification="scope">
+        <productSpecificationComponent
+          ref="blank_product_specification"
+          id="blank_product_specification"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></productSpecificationComponent>
+      </template>
 
-            <!-- 事件 -->
-            <template v-slot:blank_event_component="scope">
-              <eventComponent  ref="blank_event_component" id="blank_event_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></eventComponent>
-            </template>
+      <!-- 事件 -->
+      <template v-slot:blank_event_component="scope">
+        <eventComponent
+          ref="blank_event_component"
+          id="blank_event_component"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></eventComponent>
+      </template>
 
-            <!-- 补发 -->
-            <template v-slot:blank_reissue_component="scope">
-              <reissueComponent  ref="blank_reissue_component" id="blank_reissue_component" :generateForm="$refs.generateForm" :info="scope.model" :view="view"></reissueComponent>
-            </template>
+      <!-- 补发 -->
+      <template v-slot:blank_reissue_component="scope">
+        <reissueComponent
+          ref="blank_reissue_component"
+          id="blank_reissue_component"
+          :generateForm="$refs.generateForm"
+          :info="scope.model"
+          :view="view"
+        ></reissueComponent>
+      </template>
     </fm-generate-form>
 
     <outboundXTBG
@@ -144,165 +187,174 @@
   </ele-modal>
 </template>
 <script>
-  import Parser from '@/components/FormGenerator/components/parser/Parser.vue';
-  import outboundXTBG from '@/views/bpm/outgoingManagement/outboundXTBG.vue';
-  import {
-    approveTaskWithVariables,
-    cancelTask,
-    rejectTask
-  } from '@/api/bpm/task';
-  import { getToken } from '@/utils/token-util';
-  import storageApi from '@/api/warehouseManagement';
+import Parser from '@/components/FormGenerator/components/parser/Parser.vue';
+import outboundXTBG from '@/views/bpm/outgoingManagement/outboundXTBG.vue';
+import {
+  approveTaskWithVariables,
+  cancelTask,
+  rejectTask
+} from '@/api/bpm/task';
+import { getToken } from '@/utils/token-util';
+import storageApi from '@/api/warehouseManagement';
 
-  import businessComponent from '@/BIZComponents/processSubmitDialog/components/businessComponent.vue';
-  import useSealComponent from '@/BIZComponents/processSubmitDialog/components/useSealComponent.vue';
-  import useQualificationComponent from '@/BIZComponents/processSubmitDialog/components/useQualificationComponent.vue';
-  import productSpecificationComponent from '@/BIZComponents/processSubmitDialog/components/productSpecificationComponent.vue';
-  import eventComponent from '@/BIZComponents/processSubmitDialog/components/eventComponent.vue';
-  import reissueComponent from '@/BIZComponents/processSubmitDialog/components/reissueComponent.vue';
+import businessComponent from '@/BIZComponents/processSubmitDialog/components/businessComponent.vue';
+import useSealComponent from '@/BIZComponents/processSubmitDialog/components/useSealComponent.vue';
+import useQualificationComponent from '@/BIZComponents/processSubmitDialog/components/useQualificationComponent.vue';
+import productSpecificationComponent from '@/BIZComponents/processSubmitDialog/components/productSpecificationComponent.vue';
+import eventComponent from '@/BIZComponents/processSubmitDialog/components/eventComponent.vue';
+import reissueComponent from '@/BIZComponents/processSubmitDialog/components/reissueComponent.vue';
 
-  export default {
-    name: 'formParserDialog',
-    components: { Parser, outboundXTBG },
-    components: {businessComponent, useSealComponent, useQualificationComponent, productSpecificationComponent, eventComponent, reissueComponent},
-    props: {
-      businessId: {
-        default: ''
-      },
-      formParserDialogFlag: {
-        type: Boolean,
-        default: false
-      }
+export default {
+  name: 'formParserDialog',
+  components: { Parser, outboundXTBG },
+  components: {
+    businessComponent,
+    useSealComponent,
+    useQualificationComponent,
+    productSpecificationComponent,
+    eventComponent,
+    reissueComponent
+  },
+  props: {
+    businessId: {
+      default: ''
     },
-    data() {
-      return {
-        form: {},
-        index: '',
-        jsonData: {},
-        width: '30%',
-        isSaveLoading: false
-      };
+    formParserDialogFlag: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      form: {},
+      index: '',
+      jsonData: {},
+      width: '30%',
+      isSaveLoading: false
+    };
+  },
+  modelWidth() {
+    let width =
+      this.jsonData.config?.platform && this.jsonData.config.platform === 'pc'
+        ? 1100
+        : 450;
+    if (this.form?.taskDefinitionKey == 'CGYSP') {
+      return (width = '70%');
+    }
+    return width + 'px';
+  },
+  methods: {
+    open(row) {
+      this.form = _.cloneDeep(row);
+      console.log(this.form.taskDefinitionKey, 'this.form.taskDefinitionKey');
+
+      this.jsonData = JSON.parse(this.form.formJson.makingJson);
+      this.jsonData.config.dataSource &&
+        this.jsonData.config.dataSource.forEach((item) => {
+          item.headers = {
+            Authorization: getToken()
+          };
+          // item.url = item.url && item.url.replace('/api', this.APIUrl);
+        });
     },
-    modelWidth() {
-      let width = this.jsonData.config?.platform && this.jsonData.config.platform === 'pc' ? 1100 : 450;
-      if (this.form?.taskDefinitionKey == 'CGYSP') {
-        return width = '70%';
-      }
-      return width + 'px'
+    cancel() {
+      this.$emit('update:formParserDialogFlag', false);
+    },
+    async handleAudit(status) {
+      await this._approveTaskWithVariables(status);
     },
-    methods: {
-      open(row) {
-        this.form = _.cloneDeep(row);
-        console.log(this.form.taskDefinitionKey, 'this.form.taskDefinitionKey');
-        
-        this.jsonData = JSON.parse(this.form.formJson.makingJson);
-        this.jsonData.config.dataSource &&
-          this.jsonData.config.dataSource.forEach((item) => {
-            item.headers = {
-              Authorization: getToken()
-            };
-            // item.url = item.url && item.url.replace('/api', this.APIUrl);
-          });
-      },
-      cancel() {
-        this.$emit('update:formParserDialogFlag', false);
-      },
-      async handleAudit(status) {
-        await this._approveTaskWithVariables(status);
-      },
-
-      async storemanApprove(status) {
-        let storageData = await this.$refs.outboundXTBGRef.getReturnStorage();
-        console.log(storageData);
-
-        // 出库来源isSkip 0-正常  1-外部(外部跳过内部审核流程)
-        storageData.isSkip = 1;
-        storageData.isMes = 1;
-        try {
-          this.isSaveLoading = true;
-          await storageApi.outStorage(storageData);
-          approveTaskWithVariables({
-            id: this.form.id,
-            reason: this.form.reason,
-            businessId: this.businessId,
-            variables: {
-              pass: true
-            }
-          }).then((res) => {
-            if (res.data.code != '-1') {
-       
-              this.$message.success(`出库成功!`);
-              this.$emit('reload');
-              this.cancel();
-            }
-            this.isSaveLoading = false;
-          });
-        } catch (error) {
-          this.isSaveLoading = false;
-          console.error('出库失败:', error);
-        }
-      },
 
-      async _approveTaskWithVariables(status) {
-        let variables = {
-          pass: !!status
-        };
-        let API = !!status ? approveTaskWithVariables : rejectTask;
+    async storemanApprove(status) {
+      let storageData = await this.$refs.outboundXTBGRef.getReturnStorage();
+      console.log(storageData);
 
-        API({
+      // 出库来源isSkip 0-正常  1-外部(外部跳过内部审核流程)
+      storageData.isSkip = 1;
+      storageData.isMes = 1;
+      try {
+        this.isSaveLoading = true;
+        await storageApi.outStorage(storageData);
+        approveTaskWithVariables({
           id: this.form.id,
           reason: this.form.reason,
           businessId: this.businessId,
-          variables
+          variables: {
+            pass: true
+          }
         }).then((res) => {
           if (res.data.code != '-1') {
-            let params = {
-              status,
-              title: status === 0 ? '驳回' : ''
-            };
-            this.$message.success(`审批${params.title}成功!`);
+            this.$message.success(`出库成功!`);
             this.$emit('reload');
             this.cancel();
           }
+          this.isSaveLoading = false;
         });
-      },
+      } catch (error) {
+        this.isSaveLoading = false;
+        console.error('出库失败:', error);
+      }
+    },
 
-      //更多
-      handleCommand(command) {
-        if (command === 'cancel') {
-          this.$confirm('是否确认作废?', {
-            type: 'warning',
-            cancelButtonText: '取消',
-            confirmButtonText: '确定'
-          })
-            .then(() => {
-              cancelTask({
-                taskId: this.form.id,
-                id: this.form.processInstance.id,
-                reason: this.form.reason
-              })
-                .then(() => {
-                  this.$emit('reload');
-                  this.cancel();
-                })
-                .catch(() => {
-                  this.$message.error('流程作废失败');
-                });
-            })
-            .catch(() => {});
+    async _approveTaskWithVariables(status) {
+      let variables = {
+        pass: !!status
+      };
+      let API = !!status ? approveTaskWithVariables : rejectTask;
+
+      API({
+        id: this.form.id,
+        reason: this.form.reason,
+        businessId: this.businessId,
+        variables
+      }).then((res) => {
+        if (res.data.code != '-1') {
+          let params = {
+            status,
+            title: status === 0 ? '驳回' : ''
+          };
+          this.$message.success(`审批${params.title}成功!`);
+          this.$emit('reload');
+          this.cancel();
         }
+      });
+    },
+
+    //更多
+    handleCommand(command) {
+      if (command === 'cancel') {
+        this.$confirm('是否确认作废?', {
+          type: 'warning',
+          cancelButtonText: '取消',
+          confirmButtonText: '确定'
+        })
+          .then(() => {
+            cancelTask({
+              taskId: this.form.id,
+              id: this.form.processInstance.id,
+              reason: this.form.reason
+            })
+              .then(() => {
+                this.$emit('reload');
+                this.cancel();
+              })
+              .catch(() => {
+                this.$message.error('流程作废失败');
+              });
+          })
+          .catch(() => {});
       }
     }
-  };
+  }
+};
 </script>
 <style scoped lang="scss">
-  .blank_adopzrdd {
-    display: flex;
-    align-items: center;
-    > span {
-      display: inline-block;
-      width: 80px;
-    }
-    margin-bottom: 10px;
+.blank_adopzrdd {
+  display: flex;
+  align-items: center;
+  > span {
+    display: inline-block;
+    width: 80px;
   }
+  margin-bottom: 10px;
+}
 </style>

+ 7 - 0
src/views/bpm/stockManagement/details.vue

@@ -245,6 +245,13 @@
               :show-overflow-tooltip="true"
             >
             </el-table-column>
+             <el-table-column
+                label="生产要求"
+                align="center"
+                width="200"
+                prop="productionRequirements"
+                :show-overflow-tooltip="true"
+              ></el-table-column>
             <el-table-column label="机型" prop="modelKey" width="200">
             </el-table-column>
             <el-table-column label="颜色" prop="colorKey" width="200">

+ 11 - 2
src/views/bpm/stockManagement/storage.vue

@@ -120,7 +120,7 @@
               ></el-input>
             </el-form-item>
           </el-col>
-          <el-col :span="6">
+          <!-- <el-col :span="6">
             <el-form-item label="生产要求" prop="productionRequirements">
               <el-input
                 v-model="formData.productionRequirements"
@@ -131,7 +131,7 @@
                 disabled
               ></el-input>
             </el-form-item>
-          </el-col>
+          </el-col> -->
         </el-row>
       </el-form>
       <div class="inbound_details">
@@ -461,6 +461,13 @@
                   <template slot="append"> </template>
                 </template>
               </el-table-column>
+             <el-table-column
+                label="生产要求"
+                align="center"
+                width="200"
+                prop="productionRequirements"
+                :show-overflow-tooltip="true"
+              ></el-table-column>
               <el-table-column label="机型" prop="modelKey" width="300">
                 <template slot-scope="{ row, $index }">
                   <DictSelection
@@ -1681,6 +1688,7 @@
                 batchNo: batchNo, // 批次号
                 supplierListOptions: supplierList[item.id], // 供应商列表
                 supplierId: this.form.supplierId, // 供应商id
+                productionRequirements:filtersItem.productionRequirements,//生产要求
                 supplierCode:
                   this.bizType == 2 || this.bizType == 7
                     ? filtersItem.supplierMark
@@ -1932,6 +1940,7 @@
                   this.detailList.find((val) => val.categoryCode == item.code)
                     ?.supplierName || item.supplierName, // 供应商名称
                 approvalNumber: item.approvalNumber, // 批准文号
+                 productionRequirements:this.form.productionRequirements,
                 packingSpecification: item.packingSpecification, // 包装规格
                 packingSpecificationOption: newSpecificationOption[index], // 包装规格选项
                 packingSpecificationLabel: packingSpecificationLabel, // 包装规格显示

+ 1 - 0
src/views/bpm/todo/index.vue

@@ -291,6 +291,7 @@
       /** 处理审批按钮 */
 
       handleAudit(type, row) {
+        console.log(type,row)
         // return
 
         if (type == 'audit') {

+ 1 - 1
vue.config.js

@@ -40,7 +40,7 @@ module.exports = {
         // target: 'http://192.168.1.105:18086',
 
         // target: 'http://192.168.1.251:18186',
-        target: 'http://192.168.1.125:18086',
+        target: 'http://192.168.1.251:18086',
         // target: 'http://192.168.1.125:18086',
 
         // target: 'http://192.168.1.3:18086',