Browse Source

需求流程

yusheng 2 years ago
parent
commit
b32eee80e8
33 changed files with 2624 additions and 353 deletions
  1. 79 0
      src/api/bpm/components/purchasingManage/inquiryManage.js
  2. 35 0
      src/api/bpm/components/purchasingManage/purchaseNeedManage.js
  3. 57 0
      src/api/bpm/components/purchasingManage/purchaseOrder.js
  4. 26 0
      src/api/bpm/components/purchasingManage/purchasePlanManage.js
  5. 71 0
      src/api/bpm/components/purchasingManage/purchaseorderreceive.js
  6. 61 0
      src/api/bpm/components/purchasingManage/returnGoods.js
  7. 60 0
      src/components/CommomSelect/dept-select.vue
  8. 73 0
      src/components/CommomSelect/person-select.vue
  9. 3 1
      src/enum/dict.js
  10. 5 5
      src/views/bpm/handleTask/components/businessOpportunity/addOpportunityDialog.vue
  11. 26 14
      src/views/bpm/handleTask/components/businessOpportunity/opportunityDetailDialog.vue
  12. 15 7
      src/views/bpm/handleTask/components/businessOpportunity/submit.vue
  13. 11 2
      src/views/bpm/handleTask/components/contact/submit.vue
  14. 1 1
      src/views/bpm/handleTask/components/contractBook/addDialog.vue
  15. 22 1
      src/views/bpm/handleTask/components/contractBook/detailDialog.vue
  16. 28 1
      src/views/bpm/handleTask/components/contractBook/inventoryTable.vue
  17. 10 1
      src/views/bpm/handleTask/components/contractBook/submit.vue
  18. 306 0
      src/views/bpm/handleTask/components/purchaseNeedManage/addDialog.vue
  19. 244 0
      src/views/bpm/handleTask/components/purchaseNeedManage/detailDialog.vue
  20. 517 0
      src/views/bpm/handleTask/components/purchaseNeedManage/inventoryTable.vue
  21. 155 0
      src/views/bpm/handleTask/components/purchaseNeedManage/submit.vue
  22. 265 0
      src/views/bpm/handleTask/components/purchasePlanManage/detailDialog.vue
  23. 168 0
      src/views/bpm/handleTask/components/purchasePlanManage/submit.vue
  24. 4 0
      src/views/bpm/handleTask/components/quotation/addDialog.vue
  25. 20 3
      src/views/bpm/handleTask/components/quotation/detailDialog.vue
  26. 45 13
      src/views/bpm/handleTask/components/quotation/inventoryTable.vue
  27. 224 208
      src/views/bpm/handleTask/components/quotation/product-list.vue
  28. 23 7
      src/views/bpm/handleTask/components/quotation/submit.vue
  29. 7 42
      src/views/bpm/handleTask/components/saleOrder/accountstatement/submit.vue
  30. 32 7
      src/views/bpm/handleTask/components/saleOrder/inventoryTable.vue
  31. 13 2
      src/views/bpm/handleTask/components/saleOrder/invoice/submit.vue
  32. 6 33
      src/views/bpm/handleTask/components/saleOrder/returnGoods/submit.vue
  33. 12 5
      src/views/bpm/handleTask/components/saleOrder/submit.vue

+ 79 - 0
src/api/bpm/components/purchasingManage/inquiryManage.js

@@ -0,0 +1,79 @@
+import request from '@/utils/request';
+
+
+/**
+ * 获取信息列表
+ */
+export async function getTableList(params) {
+  const res = await request.get(`/eom/purchaseinquiry/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取信息详情
+ */
+export async function getpurchaseinquiry(id) {
+  const res = await request.get(`/eom/purchaseinquiry/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新信息
+ */
+export async function UpdateInformation(data) {
+  const res = await request.put(`/eom/purchaseinquiry/update`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 新增信息
+ */
+export async function addPurchaseinquiry(data) {
+  const res = await request.post(`/eom/purchaseinquiry/save`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 删除
+ */
+export async function deleteInformation(data) {
+  const res = await request.delete('/eom/purchaseinquiry/delete', { data });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+/**
+ * 设置中标单位
+ */
+export async function chooseWinner(data) {
+  const res = await request.post(`/eom/purchaseinquiry/chooseWinner`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取生成合同的数据
+ */
+export async function generateContract(data) {
+  const res = await request.post(`/eom/purchaseinquiry/generateContract`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+

+ 35 - 0
src/api/bpm/components/purchasingManage/purchaseNeedManage.js

@@ -0,0 +1,35 @@
+import request from '@/utils/request';
+
+
+/**
+ * 获取信息列表
+ */
+export async function getTableList(params) {
+  const res = await request.get(`/eom/purchaserequirement/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取信息详情
+ */
+export async function getDetail(id) {
+  const res = await request.get(`/eom/purchaserequirement/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新信息
+ */
+export async function UpdateInformation(data) {
+  const res = await request.put(`/eom/purchaserequirement/update`, data);
+  return res.data
+}
+
+
+

+ 57 - 0
src/api/bpm/components/purchasingManage/purchaseOrder.js

@@ -0,0 +1,57 @@
+import request from '@/utils/request';
+import { download } from '@/utils/file';
+/**
+ * 获取信息列表
+ */
+export async function getTableList(params) {
+  const res = await request.get(`/eom/purchaseorder/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取信息详情
+ */
+export async function getpurchaseorderDetail(id) {
+  const res = await request.get(`/eom/purchaseorder/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新信息
+ */
+export async function UpdateInformation(data) {
+  const res = await request.put(`/eom/purchaseorder/update`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 新增信息
+ */
+export async function addInformation(data) {
+  const res = await request.post(`/eom/purchaseorder/save`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 删除
+ */
+export async function deleteInformation(data) {
+  const res = await request.delete('/eom/purchaseorder/delete', { data });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+

+ 26 - 0
src/api/bpm/components/purchasingManage/purchasePlanManage.js

@@ -0,0 +1,26 @@
+import request from '@/utils/request';
+
+
+
+/**
+ * 获取信息详情
+ */
+export async function getplanDetail(id) {
+  const res = await request.get(`/eom/purchaseplan/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+/**
+ * 新增信息
+ */
+export async function assign(data) {
+  const res = await request.post(`/bpm/purchasePlanApprove/assign`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 71 - 0
src/api/bpm/components/purchasingManage/purchaseorderreceive.js

@@ -0,0 +1,71 @@
+import request from '@/utils/request';
+import { download } from '@/utils/file';
+/**
+ * 获取信息列表
+ */
+export async function getReceiveTableList(params) {
+  const res = await request.get(`/eom/purchaseorderreceive/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取信息详情
+ */
+export async function getReceiveSaleOrderrecordDetail(id) {
+  const res = await request.get(`/eom/purchaseorderreceive/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新信息
+ */
+export async function UpdateReceiveInformation(data) {
+  const res = await request.put(`/eom/purchaseorderreceive/update`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 新增信息
+ */
+export async function addReceiveInformation(data) {
+  const res = await request.post(`/eom/purchaseorderreceive/save`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 删除
+ */
+export async function deleteReceiveInformation(data) {
+  const res = await request.delete('/eom/purchaseorderreceive/delete', { data });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+
+
+
+// /**
+//  * 通过销售发货获取发货清单
+//  */
+// export async function getProductListByRecordId(recordId) {
+//     const res = await request.get(`/eom/purchaseorderreceive/getProductListByRecordId/${recordId}`, {});
+//     if (res.data.code == 0) {
+//       return res.data.data;
+//     }
+//     return Promise.reject(new Error(res.data.message));
+//   }

+ 61 - 0
src/api/bpm/components/purchasingManage/returnGoods.js

@@ -0,0 +1,61 @@
+import request from '@/utils/request';
+import { download } from '@/utils/file';
+/**
+ * 获取信息列表
+ */
+export async function getReturnTableList(params) {
+  const res = await request.get(`/eom/purchaseorderreturn/page`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 获取信息详情
+ */
+export async function getReturnSaleOrderrecordDetail(id) {
+  const res = await request.get(`/eom/purchaseorderreturn/getById/${id}`, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 更新信息
+ */
+export async function UpdateReturnInformation(data) {
+  const res = await request.put(`/eom/purchaseorderreturn/update`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 新增信息
+ */
+export async function addReturnInformation(data) {
+  const res = await request.post(`/eom/purchaseorderreturn/save`, data);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+/**
+ * 删除
+ */
+export async function deleteReturnInformation(data) {
+  const res = await request.delete('/eom/purchaseorderreturn/delete', { data });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+
+
+

+ 60 - 0
src/components/CommomSelect/dept-select.vue

@@ -0,0 +1,60 @@
+<!-- 部门树形选择下拉框 -->
+<template>
+  <ele-tree-select
+    clearable
+    :value="value || ''"
+    :data="treeData"
+    label-key="name"
+    value-key="id"
+    default-expand-all
+    ref="treeSelect"
+    :placeholder="placeholder"
+    @input="updateValue"
+    @change="changeChoose"
+  />
+</template>
+
+<script>
+  import { listOrganizations } from '@/api/system/organization';
+  export default {
+    props: {
+      // 选中的数据(v-model)
+      value: [Number, String],
+      // 提示信息
+      placeholder: {
+        type: String,
+        default: '请选择'
+      }
+    },
+    data () {
+      return {
+        treeData: []
+      };
+    },
+    created () {
+      this.getData();
+    },
+    methods: {
+      async getData (params = {}) {
+        const data = await listOrganizations(params);
+        this.treeData = this.$util.toTreeData({
+          data: data || [],
+          idField: 'id',
+          parentIdField: 'parentId'
+        });
+      },
+      /* 更新选中数据 */
+      updateValue (value) {
+        this.$emit('input', value);
+      },
+
+      changeChoose (val) {
+        this.$emit(
+          'changeGroup',
+          val,
+          this.$refs.treeSelect.getNodeByValue(val)
+        );
+      }
+    }
+  };
+</script>

+ 73 - 0
src/components/CommomSelect/person-select.vue

@@ -0,0 +1,73 @@
+<template>
+  <el-select
+    v-model="selectVal"
+    filterable
+    style="width: 100%"
+    v-bind="$attrs"
+    v-on="$listeners"
+    clearable
+  >
+    <el-option
+      v-for="item in dictList"
+      :key="item.id"
+      :value="item.id"
+      :label="item.name"
+    ></el-option>
+  </el-select>
+</template>
+
+<script>
+  import { getUserPage } from '@/api/system/organization';
+  export default {
+    model: {
+      prop: 'value',
+      event: 'updateVal'
+    },
+    props: {
+      value: {
+        type: [String, Number, Array],
+        default: ''
+      },
+      init: {
+        type: Boolean,
+        default: true
+      }
+    },
+    data () {
+      return {
+        dictList: []
+      };
+    },
+    computed: {
+      selectVal: {
+        set (val) {
+          this.$emit(
+            'selfChange',
+            val,
+            this.dictList.find((i) => i.id === val)
+          );
+          this.$emit('updateVal', val);
+        },
+        get () {
+          return this.value;
+        }
+      }
+    },
+    created () {
+      if (this.init) {
+        this.getList();
+      }
+    },
+    methods: {
+      async getList (params) {
+        let data = { pageNum: 1, size: -1 };
+        // 如果传了参数就是获取巡点检人员数据
+        if (params) {
+          data = Object.assign(data, params);
+        }
+        const res = await getUserPage(data);
+        this.dictList = res.list;
+      }
+    }
+  };
+</script>

+ 3 - 1
src/enum/dict.js

@@ -50,7 +50,9 @@ export default {
   商机来源: 'business_opport_code',
   合同类型: 'contract_type',
   销售类型: 'sale_type',
-  退货类型: 'sale_return_type'
+  退货类型: 'sale_return_type',
+  需求来源类型:'requirement_source_type',
+
 };
 
 export const numberList = [

+ 5 - 5
src/views/bpm/handleTask/components/businessOpportunity/addOpportunityDialog.vue

@@ -12,7 +12,7 @@
     >
       <el-row>
         <el-col :span="8">
-          <el-form-item label="选择客户" prop="contactName">
+          <el-form-item label="选择客户" prop="contactName" style="height: 58px;">
             <el-input
               placeholder="请选择"
               v-model="form.contactName"
@@ -22,7 +22,7 @@
           </el-form-item>
         </el-col>
         <el-col :span="8">
-          <el-form-item label="	商机名称" prop="name">
+          <el-form-item label="	商机名称" prop="name" style="height: 58px;">
             <el-input
               placeholder="请输入"
               v-model="form.name"
@@ -41,7 +41,7 @@
           </el-form-item>
         </el-col>
         <el-col :span="8">
-          <el-form-item label="商机来源" prop="sourceCode">
+          <el-form-item label="商机来源" prop="sourceCode" style="height: 58px;">
             <DictSelection
               dictName="商机来源"
               clearable
@@ -76,7 +76,7 @@
             ></el-date-picker>
           </el-form-item>
         </el-col>
-        <el-col :span="8">
+        <!-- <el-col :span="8">
           <el-form-item label="商机阶段" prop="stageCode">
             <DictSelection
               dictName="商机阶段"
@@ -85,7 +85,7 @@
             >
             </DictSelection>
           </el-form-item>
-        </el-col>
+        </el-col> -->
         <el-col :span="8">
           <el-form-item prop="files" label="附件">
             <fileUpload

+ 26 - 14
src/views/bpm/handleTask/components/businessOpportunity/opportunityDetailDialog.vue

@@ -1,10 +1,6 @@
 <template>
   <div>
-    <el-card
-      shadow="never"
-      header="基本信息"
-      body-style="padding: 22px 20px 0 0;"
-    >
+    <headerTitle title="基本信息"></headerTitle>
       <el-form
         label-width="120px"
         ref="form"
@@ -75,13 +71,10 @@
           </el-col>
         </el-row>
       </el-form>
-    </el-card>
+   
+
+      <headerTitle title="产品清单"></headerTitle>
 
-    <el-card
-      shadow="never"
-      header="产品清单"
-      body-style="padding: 22px 20px 0 20px;"
-    >
       <inventoryTable
         :taskDefinitionKey="taskDefinitionKey"
         ref="inventoryTable"
@@ -114,9 +107,21 @@
             >
           </div>
         </template>
+        <template v-slot:customerReqFiles="{ row }">
+          <div v-if="row.customerReqFiles && row.customerReqFiles?.length">
+            <el-link
+              v-for="link in row.customerReqFiles"
+              :key="link.id"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(link)"
+            >
+              {{ link.name }}</el-link
+            >
+          </div>
+        </template>
       </ele-pro-table>
-    </el-card>
-    <el-card
+    <!-- <el-card
       shadow="never"
       header="竞品对手"
       body-style="padding: 22px 20px 0 20px;"
@@ -143,7 +148,7 @@
         row-key="id"
       >
       </ele-pro-table>
-    </el-card>
+    </el-card> -->
   </div>
 </template>
 
@@ -330,6 +335,13 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 240,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles',
+           
+          },
           {
             width: 120,
             prop: 'technicalAnswerName',

+ 15 - 7
src/views/bpm/handleTask/components/businessOpportunity/submit.vue

@@ -26,7 +26,16 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -154,9 +163,7 @@
         //技术员修改
         if (this.taskDefinitionKey === 'technicianApprove' && status === 1) {
           let data = await this.getTableValue();
-          if (!arr) {
-            return;
-          }
+
           let arr = data.map((item) => {
             return {
               id: item.id,
@@ -166,9 +173,10 @@
               technicalParams: item.technicalParams
             };
           });
-          try {
-            await updateTech(arr);
-          } catch (error) {}
+          if (!arr) {
+            return;
+          }
+          await updateTech(arr);
         }
         //销售员补充
         if (this.taskDefinitionKey === 'salesmanApprove' && status === 1) {

+ 11 - 2
src/views/bpm/handleTask/components/contact/submit.vue

@@ -1,7 +1,16 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px">
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="reason"
@@ -71,7 +80,7 @@
           status,
           taskId: this.taskId
         }).then((res) => {
-          this.$emit('handleAudit', {status});
+          this.$emit('handleAudit', { status });
         });
 
         // this.dialogVisible = false;

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

@@ -358,7 +358,7 @@
         :contractStartDate="this.form.contractStartDate"
       ></inventoryTable>
       <headerTitle
-        :title="form.type == '2' ? '付款清单' : '收款清单'"
+        :title="form.type == '2' ? '付款方式' : '收款方式'"
         style="margin-top: 30px"
       ></headerTitle>
       <paymentList ref="paymentListTable" />

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

@@ -210,10 +210,23 @@
           >
         </div>
       </template>
+      <template v-slot:customerReqFiles="{ row }">
+          <div v-if="row.customerReqFiles && row.customerReqFiles?.length">
+            <el-link
+              v-for="link in row.customerReqFiles"
+              :key="link.id"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(link)"
+            >
+              {{ link.name }}</el-link
+            >
+          </div>
+        </template>
     </ele-pro-table>
 
     <headerTitle
-      :title="form.type == '2' ? '付款清单' : '收款清单'"
+      :title="form.type == '2' ? '付款方式' : '收款方式'"
       style="margin-top: 30px"
     ></headerTitle>
     <ele-pro-table
@@ -389,6 +402,14 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 240,
+            prop: 'customerReqFiles',
+            label: '技术图纸',
+            slot: 'customerReqFiles',
+            
+          },
+          
           {
             width: 120,
             prop: 'technicalAnswerName',

+ 28 - 1
src/views/bpm/handleTask/components/contractBook/inventoryTable.vue

@@ -274,6 +274,25 @@
           />
         </el-form-item>
       </template>
+      <template v-slot:customerReqFiles="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.customerReqFiles'"
+          :rules="{
+            required: false,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <fileUpload
+            v-model="scope.row.customerReqFiles"
+            module="main"
+            :showLib="false"
+            :limit="5"
+          />
+        </el-form-item>
+      </template>
+
       <template v-slot:deliveryDeadline="scope">
         <el-form-item
           :prop="'datasource.' + scope.$index + '.deliveryDeadline'"
@@ -325,7 +344,7 @@
   </el-form>
 </template>
 <script>
-  import {  numberReg } from 'ele-admin';
+  import { numberReg } from 'ele-admin';
   import productList from '@/views/bpm/handleTask/components/quotation/product-list.vue';
   import dictMixins from '@/mixins/dictMixins';
   import fileUpload from '@/components/upload/fileUpload';
@@ -463,6 +482,12 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 220,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles'
+          },
           {
             width: 130,
             prop: 'technicalAnswerName',
@@ -594,6 +619,7 @@
           v.technicalDrawings = v.technicalDrawings
             ? v.technicalDrawings
             : null;
+          v.customerReqFiles = v.customerReqFiles || null;
         });
         return comitDatasource;
       },
@@ -648,6 +674,7 @@
           this.form.datasource = data.productList;
           this.allPrice = data.contractVO.totalPrice;
           this.discountTotalPrice = data.contractVO.discountTotalPrice;
+          this.discountInput(data.contractVO.discountTotalPrice);
         }
       },
       //选择产品

+ 10 - 1
src/views/bpm/handleTask/components/contractBook/submit.vue

@@ -1,7 +1,16 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="form.reason"

+ 306 - 0
src/views/bpm/handleTask/components/purchaseNeedManage/addDialog.vue

@@ -0,0 +1,306 @@
+<template>
+  <div>
+    <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+      <headerTitle title="基本信息"></headerTitle>
+      <el-row>
+        <el-col :span="12">
+          <el-form-item
+            label="需求来源类型"
+            prop="sourceType"
+            style="margin-bottom: 22px"
+          >
+            <DictSelection
+              dictName="需求来源类型"
+              clearable
+              v-model="form.sourceType"
+              valueName="dictValue"
+            >
+            </DictSelection>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item
+            label="需求部门"
+            prop="requireDeptId"
+            style="margin-bottom: 22px"
+          >
+            <ele-tree-select
+              clearable
+              :data="groupTreeData"
+              v-model="form.requireDeptId"
+              valueKey="id"
+              labelKey="name"
+              placeholder="请选择"
+              @change="change_principalDep"
+              default-expand-all
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12"    style="height: 58px;">
+          <el-form-item
+            label="需求人"
+            prop="requireUserId"
+            style="margin-bottom: 0px;"
+            
+          >
+            <personSelect
+              ref="directorRef"
+              v-model="form.requireUserId"
+              @selfChange="salesmanChange"
+              :init="false"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="remark" label="是否接受拆单" label-width="120px">
+            <el-select
+              v-model="form.acceptUnpack"
+              placeholder="请选择"
+              clearable
+              style="width: 100%"
+            >
+              <el-option
+                v-for="item in acceptUnpackList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="用途" prop="useTo">
+            <el-input
+              type="textarea"
+              resize="none"
+              v-model="form.useTo"
+              :rows="2"
+              placeholder="请输入"
+              size="small"
+              maxlength="200"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="remark" label="备注">
+            <el-input
+              type="textarea"
+              resize="none"
+              v-model="form.remark"
+              :rows="2"
+              placeholder="请输入"
+              size="small"
+              maxlength="200"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="files" label="附件">
+            <fileUpload
+              v-model="form.files"
+              module="main"
+              :showLib="false"
+              :limit="1"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <headerTitle title="需求清单"></headerTitle>
+    <inventoryTable
+      ref="inventoryTable"
+      :delDetailIds="delDetailIds"
+    ></inventoryTable>
+  </div>
+</template>
+
+<script>
+  import inventoryTable from './inventoryTable.vue';
+  import fileUpload from '@/components/upload/fileUpload';
+  import dictMixins from '@/mixins/dictMixins';
+  import personSelect from '@/components/CommomSelect/person-select.vue';
+  import { getDetail } from '@/api/bpm/components/purchasingManage/purchaseNeedManage';
+  import { copyObj } from '@/utils/util';
+  import { listOrganizations } from '@/api/system/organization';
+
+  export default {
+    props: {
+      businessId: {
+        default: ''
+      }
+    },
+    mixins: [dictMixins],
+    components: {
+      fileUpload,
+      inventoryTable,
+      personSelect
+    },
+    data() {
+      let formDef = {
+        id: '',
+        receiveDate: null,
+        remark: null,
+        requireDeptId: '',
+        requireUserId: '',
+        sourceCode: '',
+        sourceId: '',
+        sourceType: '',
+        files: [],
+        acceptUnpack: 1
+      };
+
+      return {
+        visible: false,
+        title: '',
+        delDetailIds: [],
+        formDef,
+        form: copyObj(formDef),
+        acceptUnpackList: [
+          {
+            label: '接受',
+            value: 1
+          },
+          {
+            label: '不接受',
+            value: 0
+          }
+        ],
+        rules: {
+          requireDeptId: [
+            { required: true, message: '请选择需求部门', trigger: 'change' }
+          ],
+          requireUserId: [
+            { required: true, message: '请选择需求人', trigger: 'change' }
+          ],
+          useTo: [{ required: true, message: '请输入用途', trigger: 'change' }],
+          sourceType: [
+            { required: true, message: '请选择需求来源类型', trigger: 'change' }
+          ]
+        },
+        // 提交状态
+        loading: false,
+        // 是否是修改
+        isUpdate: false,
+
+        // 组织机构树形结构数据
+        groupTreeData: [],
+        // 组织机构平铺数据
+        groupData: []
+      };
+    },
+    async created() {
+      await this.getGroupAll();
+      await this.getDetailData(this.businessId);
+    },
+
+    methods: {
+      // 获取公司数据
+      getGroupAll() {
+        listOrganizations().then((list) => {
+          this.groupData = list;
+          this.groupTreeData = this.$util.toTreeData({
+            data: list,
+            idField: 'id',
+            parentIdField: 'parentId'
+          });
+        });
+      },
+
+      // 选择负责人部门
+      change_principalDep(id) {
+        const info = this.groupData.find((e) => e.id == id);
+        this.form.requireDeptName = info.name;
+        this.form.requireUserId = '';
+        this.form.requireUserName = '';
+        // 根据部门获取人员
+        this.$nextTick(() => {});
+        this.getrequireUser(id);
+      },
+      // //选择需求来源类型
+      // chaengSource(data) {
+      //   this.form.sourceType = data?.dictValue;
+      // },
+      getrequireUser(groupId) {
+        if (groupId) {
+          this.$refs.directorRef.getList({ groupId });
+        }
+      },
+      salesmanChange(val, info) {
+        this.form.requireUserName = info.name;
+      },
+      //获取详情
+      async getDetailData(id) {
+        this.loading = true;
+        const data = await getDetail(id);
+        this.loading = false;
+        this.getrequireUser(data.requireDeptId);
+
+        if (data) {
+          this.$nextTick(() => {
+            this.form = data;
+            // if (data.files !== '') {
+            //   this.$set(this.form, 'files', data?.files);
+            // }
+            // 根据部门获取人员
+
+            this.$refs.inventoryTable &&
+              this.$refs.inventoryTable.putTableValue(data.detailList);
+          });
+        }
+      },
+
+      getValidate() {
+        return Promise.all([
+          new Promise((resolve, reject) => {
+            this.$refs.form.validate((valid) => {
+              if (!valid) {
+                reject(false);
+              } else {
+                resolve(true);
+              }
+            });
+          }),
+          new Promise((resolve, reject) => {
+            this.$refs.inventoryTable.validateForm((valid) => {
+              if (!valid) {
+                reject(false);
+              } else {
+                resolve(true);
+              }
+            });
+          })
+        ]);
+      },
+      async getTableValue() {
+        try {
+          await this.getValidate();
+          // 表单验证通过,执行保存操作
+          this.loading = true;
+
+          if (this.$refs.inventoryTable.getTableValue().length == 0) {
+            this.$message.warning('需求清单不能为空');
+            return;
+          }
+          this.form.files = this.form.files || [];
+          let commitData = Object.assign({}, this.form, {
+            detailList: this.$refs.inventoryTable.getTableValue()
+          });
+          return commitData;
+        } catch (error) {
+          console.log(error);
+          // 表单验证未通过,不执行保存操作
+        }
+      },
+
+    }
+  };
+</script>
+<style scoped lang="scss">
+  .TotalAmount {
+    font-size: 16px;
+    padding-right: 30px;
+  }
+</style>

+ 244 - 0
src/views/bpm/handleTask/components/purchaseNeedManage/detailDialog.vue

@@ -0,0 +1,244 @@
+<template>
+  <div>
+    <el-form ref="form" :model="form" label-width="120px">
+      <headerTitle title="基本信息">
+        <!-- <el-button
+                  size="small"
+                  type="primary"
+                  icon="el-icon-s-grid"
+                  class="ele-btn-icon"
+                  @click="exportTable"
+                >
+                 导出
+                </el-button> -->
+      </headerTitle>
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="需求来源类型:" prop="contactTel">
+            {{ form.sourceType }}
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="需求部门:" prop="requireDeptName">
+            {{ detailData.requireDeptName }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="需求人:" prop="requireUserName">
+            {{ form.requireUserName }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="remark" label="是否接受拆单">
+            {{
+              form.acceptUnpack === 1
+                ? '接受'
+                : form.cceptUnpack === 1
+                ? '不接受'
+                : ''
+            }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="用途:" prop="useTo">
+            {{ form.useTo }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="完成日期:" prop="finishDate">
+            {{ form.finishDate }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="remark" label="备注:">
+            {{ form.remark }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="askFile" label="附件:">
+            <el-link
+              v-if="form.files && form.files !== ''"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(form.files)"
+            >
+              {{ form.files.name }}</el-link
+            >
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <headerTitle title="需求清单"></headerTitle>
+    <ele-pro-table
+      ref="table"
+      :needPage="false"
+      :columns="columns"
+      :toolkit="[]"
+      :datasource="detailData.detailList"
+      row-key="id"
+    >
+      <template v-slot:files="{ row }">
+        <div v-if="row.files && row.files?.length">
+          <el-link
+            v-for="link in row.files"
+            :key="link.id"
+            type="primary"
+            :underline="false"
+            @click="downloadFile(link)"
+          >
+            {{ link.name }}</el-link
+          >
+        </div>
+      </template>
+    </ele-pro-table>
+  </div>
+</template>
+
+<script>
+  import { getDetail } from '@/api/bpm/components/purchasingManage/purchaseNeedManage';
+  import { getFile } from '@/api/system/file';
+  import dictMixins from '@/mixins/dictMixins';
+
+  export default {
+    props: {
+      businessId: {
+        default: ''
+      }
+    },
+    mixins: [dictMixins],
+ 
+    data() {
+      return {
+        visible: false,
+        title: '详情',
+        row: {},
+        form: {},
+        detailData: {},
+        columns: [
+          {
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            width: 150,
+            prop: 'productCategoryName',
+            label: '分类',
+            slot: 'productCategoryName'
+          },
+          {
+            width: 140,
+            prop: 'productCode',
+            label: '编码',
+            slot: 'productCode'
+          },
+          {
+            width: 240,
+            prop: 'productName',
+            label: '名称',
+            slot: 'productName'
+          },
+          {
+            width: 150,
+            prop: 'productBrand',
+            label: '牌号',
+            slot: 'productBrand'
+          },
+          {
+            width: 80,
+            prop: 'totalCount',
+            label: '数量',
+            slot: 'totalCount'
+          },
+          {
+            width: 100,
+            prop: 'measuringUnit',
+            label: '单位',
+            slot: 'measuringUnit'
+          },
+          {
+            width: 130,
+            prop: 'modelType',
+            label: '型号',
+            slot: 'modelType'
+          },
+          {
+            width: 120,
+            prop: 'specification',
+            label: '规格',
+            slot: 'specification'
+          },
+          {
+            width: 130,
+            prop: 'brand',
+            label: '品牌',
+            slot: 'brand'
+          },
+          {
+            width: 170,
+            prop: 'expectReceiveDate',
+            label: '到货日期',
+            slot: 'expectReceiveDate'
+          },
+          {
+            width: 140,
+            prop: 'files',
+            label: '附件',
+            slot: 'files'
+          },
+          {
+            width: 220,
+            prop: 'remark',
+            label: '备注',
+            slot: 'remark'
+          }
+        ]
+      };
+    },
+    created() {
+      this.getDetailData(this.businessId);
+    },
+    methods: {
+      downloadFile(file) {
+        getFile({ objectName: file.storePath }, file.name);
+      },
+      async getDetailData(id) {
+        this.loading = true;
+        const data = await getDetail(id);
+        this.loading = false;
+        if (data) {
+          this.form = data;
+
+          this.detailData = data;
+          if (data.files && data.files.length > 0) {
+            this.form.files = data.files[0];
+          } else {
+            this.form.files = null;
+          }
+        }
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  .ele-dialog-form {
+    .el-form-item {
+      margin-bottom: 10px;
+    }
+  }
+
+  .headbox {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .amount {
+      font-size: 14px;
+      font-weight: bold;
+    }
+  }
+</style>

+ 517 - 0
src/views/bpm/handleTask/components/purchaseNeedManage/inventoryTable.vue

@@ -0,0 +1,517 @@
+<template>
+  <el-form ref="form" :model="form" :rules="rules">
+    <ele-pro-table
+      ref="table"
+      :needPage="false"
+      :columns="columns"
+      :toolkit="[]"
+      :datasource="form.datasource"
+      cache-key="systemRoleTable17"
+      class="time-form"
+    >
+      <!-- 表头工具栏 -->
+      <template v-slot:toolbar>
+        <div class="headbox">
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-plus"
+            class="ele-btn-icon"
+            @click="handlAdd"
+          >
+            新增
+          </el-button>
+        </div>
+      </template>
+      <template v-slot:productName="{ row, $index }">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + $index + '.productName'"
+          :rules="{
+            required: true,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <el-input
+            v-model="row.productName"
+            placeholder="请输入"
+            style="width: 60%; margin-right: 10px"
+            :disabled="!!row.productCode"
+          ></el-input>
+          <el-button
+            size="small"
+            type="primary"
+            @click.native="handParent(row, $index)"
+            >选择</el-button
+          >
+        </el-form-item>
+      </template>
+      <template v-slot:productCode="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.productCode'"
+          :rules="{
+            required: !!scope.row.productCode ? true : false,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <el-input v-model="scope.row.productCode" disabled></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:productCategoryName="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.productCategoryName'"
+          :rules="{
+            required: !!scope.row.productCode ? true : false,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <el-input v-model="scope.row.productCategoryName" disabled></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:totalCount="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.totalCount'"
+          :rules="{
+            required: true,
+            pattern: numberReg,
+            message: '请输入数字',
+            trigger: 'blur'
+          }"
+        >
+          <el-input
+            v-model="scope.row.totalCount"
+            placeholder="请输入"
+          ></el-input>
+        </el-form-item>
+      </template>
+
+      <template v-slot:productBrand="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.productBrand'"
+        >
+          <el-input
+            v-model="scope.row.productBrand"
+            :disabled="!!scope.row.productCode"
+          ></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:brand="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.brand'"
+        >
+          <el-input v-model="scope.row.brand"></el-input>
+        </el-form-item>
+      </template>
+
+      <template v-slot:modelType="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.modelType'"
+        >
+          <el-input
+            v-model="scope.row.modelType"
+            :disabled="!!scope.row.productCode"
+          ></el-input>
+        </el-form-item>
+      </template>
+
+      <template v-slot:specification="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.specification'"
+        >
+          <el-input
+            v-model="scope.row.specification"
+            :disabled="!!scope.row.productCode"
+          ></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:measuringUnit="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.measuringUnit'"
+        >
+          <el-input
+            v-model="scope.row.measuringUnit"
+            placeholder="请输入"
+            disabled
+          ></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:remark="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.remark'"
+        >
+          <el-input
+            v-model="scope.row.remark"
+            type="textarea"
+            placeholder="请输入"
+          ></el-input>
+        </el-form-item>
+      </template>
+
+      <template v-slot:technicalAnswerName="{ row, $index }">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + $index + '.technicalAnswerName'"
+          :rules="{
+            required: false,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <el-input
+            v-model="row.technicalAnswerName"
+            placeholder="请输入"
+            @click.native="handHead(row, $index)"
+          ></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:technicalParams="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.technicalParams'"
+          :rules="{
+            required: false,
+            message: '请输入',
+            trigger: 'change'
+          }"
+        >
+          <el-input
+            type="textarea"
+            v-model="scope.row.technicalParams"
+            placeholder="请输入"
+          ></el-input>
+        </el-form-item>
+      </template>
+      <template v-slot:files="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.files'"
+        >
+          <fileUpload
+            v-model="scope.row.files"
+            module="main"
+            :showLib="false"
+            :limit="5"
+          />
+        </el-form-item>
+      </template>
+      <template v-slot:expectReceiveDate="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.expectReceiveDate'"
+          :rules="{
+            required: true,
+            message: '请选择日期',
+            trigger: 'blur'
+          }"
+        >
+          <el-date-picker
+            style="width: 100%"
+            clearable
+            v-model="scope.row.expectReceiveDate"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择日期"
+          >
+          </el-date-picker>
+        </el-form-item>
+      </template>
+
+      <!-- 操作列 -->
+      <template v-slot:action="scope">
+        <el-popconfirm
+          class="ele-action"
+          title="确定要删除吗?"
+          @confirm="remove(scope.$index)"
+        >
+          <template v-slot:reference>
+            <el-link type="danger" :underline="false" icon="el-icon-delete">
+              删除
+            </el-link>
+          </template>
+        </el-popconfirm>
+      </template>
+    </ele-pro-table>
+    <product-list
+      ref="productListRef"
+      :isSole="true"
+      @changeParent="changeParent"
+    ></product-list>
+    <head-list ref="headRef" @changeParent="changeAnswer"></head-list>
+  </el-form>
+</template>
+<script>
+  import { numberReg } from 'ele-admin';
+  import productList from '@/views/bpm/handleTask/components/quotation/product-list.vue';
+  import dictMixins from '@/mixins/dictMixins';
+  import fileUpload from '@/components/upload/fileUpload';
+  import headList from '@/components/headList';
+  export default {
+    mixins: [dictMixins],
+    components: {
+      productList,
+      fileUpload,
+      headList
+    },
+    data() {
+      const defaultForm = {
+        key: null,
+        endTime: '',
+        isFirst: 0,
+        name: ''
+      };
+      return {
+        numberReg,
+        defaultForm,
+        form: {
+          datasource: []
+        },
+        rules: {},
+        columns: [
+          {
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            width: 150,
+            prop: 'productCategoryName',
+            label: '分类',
+            slot: 'productCategoryName'
+          },
+          {
+            width: 140,
+            prop: 'productCode',
+            label: '编码',
+            slot: 'productCode'
+          },
+          {
+            width: 240,
+            prop: 'productName',
+            label: '名称',
+            slot: 'productName'
+          },
+          {
+            width: 150,
+            prop: 'productBrand',
+            label: '牌号',
+            slot: 'productBrand'
+          },
+          {
+            width: 80,
+            prop: 'totalCount',
+            label: '数量',
+            slot: 'totalCount'
+          },
+          {
+            width: 100,
+            prop: 'measuringUnit',
+            label: '单位',
+            slot: 'measuringUnit'
+          },
+          {
+            width: 130,
+            prop: 'modelType',
+            label: '型号',
+            slot: 'modelType'
+          },
+
+          {
+            width: 120,
+            prop: 'specification',
+            label: '规格',
+            slot: 'specification'
+          },
+          {
+            width: 130,
+            prop: 'brand',
+            label: '品牌',
+            slot: 'brand'
+          },
+          {
+            width: 170,
+            prop: 'expectReceiveDate',
+            label: '到货日期',
+            slot: 'expectReceiveDate'
+          },
+          {
+            width: 140,
+            prop: 'files',
+            label: '附件',
+            slot: 'files'
+          },
+
+          {
+            width: 220,
+            prop: 'remark',
+            label: '备注',
+            slot: 'remark'
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 120,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            fixed: 'right',
+            showOverflowTooltip: true
+          }
+        ]
+      };
+    },
+
+    methods: {
+      // 返回列表数据
+      getTableValue() {
+        let comitDatasource = this.form.datasource;
+        if (comitDatasource.length === 0) return [];
+        comitDatasource.forEach((v) => {
+          v.totalPrice = (v.totalCount * v.singlePrice)?.toFixed(2) || 0;
+          v.files = v.files || null;
+        });
+        return comitDatasource;
+      },
+      //修改回显
+      putTableValue(data) {
+        if (data && data?.length) {
+          this.form.datasource = data;
+        }
+      },
+      //选择产品
+      handParent(row, index) {
+        // let item = {
+        //   id: row.productCode
+        // };
+        this.$refs.productListRef.open(this.form.datasource, index);
+      },
+      //选择技术人回调
+      changeAnswer(obj, idx) {
+        this.$set(this.form.datasource[idx], 'technicalAnswerId', obj.id);
+        this.$set(this.form.datasource[idx], 'technicalAnswerName', obj.name);
+      },
+      handHead(row, index) {
+        let item = {
+          id: row.technicalAnswerId
+        };
+        this.$refs.headRef.open(item, index);
+      },
+      //选择产品回调
+      changeParent(obj, idx) {
+        // if (
+        //   obj.code &&
+        //   this.form.datasource
+        //     .map((item) => item.productCode)
+        //     .includes(obj.code)
+        // ) {
+        //   this.$message.warning('不能选择重复的产品');
+        //   return;
+        // }
+        this.$set(this.form.datasource[idx], 'id', obj.id);
+        this.$set(this.form.datasource[idx], 'categoryName', obj.name);
+        this.$set(
+          this.form.datasource[idx],
+          'productCategoryId',
+          obj.categoryLevelId
+        );
+        this.$set(this.form.datasource[idx], 'productBrand', obj.brandNum);
+        this.$set(
+          this.form.datasource[idx],
+          'productCategoryName',
+          obj.categoryLevelPath
+        );
+        this.$set(this.form.datasource[idx], 'productCode', obj.code);
+        this.$set(this.form.datasource[idx], 'productName', obj.name);
+        this.$set(this.form.datasource[idx], 'modelType', obj.modelType);
+        this.$set(
+          this.form.datasource[idx],
+          'measuringUnit',
+          obj.measuringUnit
+        );
+        this.$set(
+          this.form.datasource[idx],
+          'specification',
+          obj.specification
+        );
+        this.$set(this.form.datasource[idx], 'remark', '');
+      },
+      remove(i) {
+        this.form.datasource.splice(i, 1);
+        this.setSort();
+      },
+      // 清空表格
+      restTable() {
+        this.form.datasource = [];
+      },
+      // 重新排序
+      setSort() {
+        this.form.datasource.forEach((n, index) => {
+          n.key = index + 1;
+        });
+      },
+      // 添加
+      handlAdd() {
+        let item = JSON.parse(JSON.stringify(this.defaultForm));
+        item.key = this.form.datasource.length + 1;
+        this.form.datasource.push(item);
+      },
+
+      validateForm(callback) {
+        //开始表单校验
+        this.$refs.form.validate((valid) => {
+          callback(valid);
+        });
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .headbox {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .amount {
+      font-size: 14px;
+      font-weight: bold;
+    }
+  }
+  .time-form .el-form-item {
+    margin-bottom: 0 !important;
+  }
+
+  ::v-deep .period {
+    display: flex;
+    .borderleftnone {
+      .el-input--medium .el-input__inner {
+        border-top-right-radius: 0;
+        border-bottom-right-radius: 0;
+      }
+    }
+    .borderrightnone {
+      .el-input--medium .el-input__inner {
+        border-top-left-radius: 0;
+        border-bottom-left-radius: 0;
+      }
+    }
+  }
+
+  ::v-deep .time-form tbody > tr:hover > td {
+    background-color: transparent !important;
+  }
+  ::v-deep .time-form .el-table tr {
+    background-color: #ffffff;
+  }
+</style>

+ 155 - 0
src/views/bpm/handleTask/components/purchaseNeedManage/submit.vue

@@ -0,0 +1,155 @@
+<template>
+  <el-col :span="16" :offset="6">
+    <el-form label-width="100px" ref="formRef" :model="form">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
+        <el-input
+          type="textarea"
+          v-model="form.reason"
+          placeholder="请输入审批建议"
+        />
+      </el-form-item>
+    </el-form>
+    <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+      <el-button
+        icon="el-icon-edit-outline"
+        type="success"
+        size="mini"
+        @click="handleAudit(1)"
+        >通过
+      </el-button>
+
+      <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleAudit(0)"
+        v-if="!['starter'].includes(taskDefinitionKey)"
+        >驳回
+      </el-button>
+
+      <!-- <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleBackList"
+        >退回
+      </el-button> -->
+      <!-- <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleAudit(0)"
+        v-if="taskDefinitionKey != 'productionSupervisorApprove1'"
+        >不通过
+      </el-button>
+      <el-button
+        icon="el-icon-edit-outline"
+        type="primary"
+        size="mini"
+        v-if="taskDefinitionKey != 'productionSupervisorApprove1'"
+        @click="handleUpdateAssignee"
+        >转办
+      </el-button> -->
+    </div>
+  </el-col>
+</template>
+
+<script>
+  import { UpdateInformation } from '@/api/bpm/components/purchasingManage/purchaseNeedManage';
+  import { approveTaskWithVariables } from '@/api/bpm/task';
+
+  // 流程实例的详情页,可用于审批
+  export default {
+    name: '',
+    components: {
+      //   Parser
+    },
+    props: {
+      businessId: {
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      taskDefinitionKey: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        form: {
+          reason: ''
+        }
+      };
+    },
+    created() {},
+    methods: {
+      /** 处理转办审批人 */
+      handleUpdateAssignee() {
+        this.$emit('handleUpdateAssignee');
+      },
+      /** 退回 */
+      handleBackList() {
+        this.$emit('handleBackList');
+      },
+
+      async handleAudit(status) {
+        //发起人
+        if (this.taskDefinitionKey === 'starter') {
+          let arr = await this.getTableValue();
+          if (!arr) {
+            return;
+          }
+          let data = await UpdateInformation(arr);
+          if (data.code != '0') {
+            return;
+          }
+        }
+        this._approveTaskWithVariables(status);
+      },
+      async _approveTaskWithVariables(status) {
+        let variables = {
+          pass: !!status
+        };
+
+        approveTaskWithVariables({
+          id: this.taskId,
+          reason: this.form.reason,
+          variables
+        }).then((res) => {
+          if (res.data.code != '-1') {
+            this.$emit('handleAudit', {
+              status,
+              title: status === 0 ? '驳回' : ''
+            });
+          }
+        });
+      },
+
+      getTableValue() {
+        return new Promise((resolve, reject) => {
+          this.$emit('getTableValue', async (data) => {
+            resolve(await data);
+          });
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss"></style>

+ 265 - 0
src/views/bpm/handleTask/components/purchasePlanManage/detailDialog.vue

@@ -0,0 +1,265 @@
+<template>
+  <div>
+    <el-form ref="form" :model="form" label-width="120px">
+      <headerTitle title="基本信息">
+        <!-- <el-button
+                  size="small"
+                  type="primary"
+                  icon="el-icon-s-grid"
+                  class="ele-btn-icon"
+                  @click="exportTable"
+                >
+                 导出
+                </el-button> -->
+      </headerTitle>
+      <el-row>
+        <el-col :span="12" style="height: 40px">
+          <el-form-item label="采购需求:" prop="requirementCode">
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="openDetail(form)"
+            >
+              {{ form.requirementCode }}
+            </el-link>
+            <!-- {{ form.requirementCode }} -->
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="负责人:" prop="responsibleName">
+            {{ detailData.responsibleName }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="需求来源类型:" prop="contactTel">
+            {{ form.sourceType }}
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item label="需求部门:" prop="requireDeptName">
+            {{ detailData.requireDeptName }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="需求人:" prop="requireUserName">
+            {{ form.requireUserName }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="remark" label="是否接受拆单:">
+            {{
+              form.acceptUnpack === 1
+                ? '接受'
+                : form.acceptUnpack === 1
+                ? '不接受'
+                : ''
+            }}
+          </el-form-item>
+        </el-col>
+        <!-- <el-col :span="12">
+          <el-form-item
+            label="用途"
+            prop="requireUserName"
+            style="margin-bottom: 22px"
+          >
+            {{ form.requireUserName }}
+          </el-form-item>
+        </el-col> -->
+        <el-col :span="12">
+          <el-form-item label="完结日期:" prop="receiveDate">
+            {{ form.receiveDate }}
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="12">
+          <el-form-item prop="remark" label="备注:">
+            {{ form.remark }}
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item prop="askFile" label="附件:">
+            <el-link
+              v-if="form.files && form.files !== ''"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(form.files)"
+            >
+              {{ form.files.name }}</el-link
+            >
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <headerTitle title="计划清单" style="margin-top: 15px"></headerTitle>
+    <ele-pro-table
+      ref="table"
+      :needPage="false"
+      :columns="columns"
+      :toolkit="[]"
+      :datasource="detailData.detailList"
+      row-key="id"
+    >
+    </ele-pro-table>
+  </div>
+</template>
+
+<script>
+  import { getplanDetail } from '@/api/bpm/components/purchasingManage/purchasePlanManage';
+
+  import { getFile } from '@/api/system/file';
+  import dictMixins from '@/mixins/dictMixins';
+  import { copyObj } from '@/utils/util';
+
+  export default {
+    mixins: [dictMixins],
+    components: {},
+    props: {
+      businessId: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        visible: false,
+        detailId: '',
+        title: '详情',
+        row: {},
+        form: {},
+        detailData: {},
+        columns: [
+          {
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
+          },
+          {
+            width: 150,
+            prop: 'productCategoryName',
+            label: '分类',
+            slot: 'productCategoryName'
+          },
+          {
+            width: 140,
+            prop: 'productCode',
+            label: '编码',
+            slot: 'productCode'
+          },
+          {
+            width: 240,
+            prop: 'productName',
+            label: '名称',
+            slot: 'productName'
+          },
+
+          {
+            width: 150,
+            prop: 'productBrand',
+            label: '牌号',
+            slot: 'productBrand'
+          },
+          {
+            width: 80,
+            prop: 'totalCount',
+            label: '数量',
+            slot: 'totalCount'
+          },
+          {
+            width: 100,
+            prop: 'measuringUnit',
+            label: '单位',
+            slot: 'measuringUnit'
+          },
+          {
+            width: 130,
+            prop: 'modelType',
+            label: '型号',
+            slot: 'modelType'
+          },
+
+          {
+            width: 120,
+            prop: 'specification',
+            label: '规格',
+            slot: 'specification'
+          },
+          // {
+          //   width: 130,
+          //   prop: 'modelType',
+          //   label: '品牌',
+          //   slot: 'modelType'
+          // },
+          {
+            width: 170,
+            prop: 'receiveDate',
+            label: '到货日期',
+            slot: 'receiveDate'
+          },
+          {
+            width: 140,
+            prop: 'files',
+            label: '附件',
+            slot: 'files'
+          },
+          {
+            width: 220,
+            prop: 'remark',
+            label: '备注',
+            slot: 'remark'
+          }
+        ]
+      };
+    },
+    created() {
+      this.getPlanData(this.businessId);
+    },
+    methods: {
+      downloadFile(file) {
+        getFile({ objectName: file.storePath }, file.name);
+      },
+      async getPlanData(id) {
+        this.loading = true;
+        const data = await getplanDetail(id);
+        this.loading = false;
+        if (data) {
+          this.detailData = data;
+          this.form = data;
+
+          if (data.files && data.files.length > 0) {
+            this.form.files = data.files[0];
+          } else {
+            this.form.files = null;
+          }
+        }
+      },
+
+      //查看详情
+      openDetail(row) {
+        console.log(row);
+        this.$refs.contactDetailDialogRef.open(row);
+      }
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  .ele-dialog-form {
+    .el-form-item {
+      margin-bottom: 10px;
+    }
+  }
+
+  .headbox {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .amount {
+      font-size: 14px;
+      font-weight: bold;
+    }
+  }
+</style>

+ 168 - 0
src/views/bpm/handleTask/components/purchasePlanManage/submit.vue

@@ -0,0 +1,168 @@
+<template>
+  <el-col :span="16" :offset="6">
+    <el-form label-width="100px" ref="formRef" :model="form">
+      <el-form-item
+        label="负责人"
+        prop="userId"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
+        <el-select
+          v-model="form.userId"
+          clearable
+          style="width: 100%"
+          :filterable="true"
+        >
+          <el-option
+            v-for="item in userOptions"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
+        <el-input
+          type="textarea"
+          v-model="form.reason"
+          placeholder="请输入审批建议"
+        />
+      </el-form-item>
+    </el-form>
+    <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+      <el-button
+        icon="el-icon-edit-outline"
+        type="success"
+        size="mini"
+        @click="handleAudit(1)"
+        >通过
+      </el-button>
+      <!-- <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleAudit(0)"
+        >驳回
+      </el-button> -->
+
+      <!-- <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleBackList"
+        >退回
+      </el-button> -->
+      <!-- <el-button
+        icon="el-icon-circle-close"
+        type="danger"
+        size="mini"
+        @click="handleAudit(0)"
+        v-if="taskDefinitionKey != 'productionSupervisorApprove1'"
+        >不通过
+      </el-button>
+      <el-button
+        icon="el-icon-edit-outline"
+        type="primary"
+        size="mini"
+        v-if="taskDefinitionKey != 'productionSupervisorApprove1'"
+        @click="handleUpdateAssignee"
+        >转办
+      </el-button> -->
+    </div>
+  </el-col>
+</template>
+
+<script>
+  import { approveTaskWithVariables } from '@/api/bpm/task';
+  import { listAllUserBind } from '@/api/system/organization';
+  import { assign } from '@/api/bpm/components/purchasingManage/purchasePlanManage';
+
+  // 流程实例的详情页,可用于审批
+  export default {
+    name: '',
+    components: {
+      //   Parser
+    },
+    props: {
+      businessId: {
+        default: ''
+      },
+      taskId: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      id: {
+        default: ''
+      },
+      taskDefinitionKey: {
+        default: ''
+      }
+    },
+    data() {
+      return {
+        form: {
+          userId: '',
+          reason: ''
+        },
+        userOptions: []
+      };
+    },
+    created() {
+      this.userOptions = [];
+      listAllUserBind().then((data) => {
+        this.userOptions.push(...data);
+      });
+    },
+    methods: {
+      /** 处理转办审批人 */
+      handleUpdateAssignee() {
+        this.$emit('handleUpdateAssignee');
+      },
+      /** 退回 */
+      handleBackList() {
+        this.$emit('handleBackList');
+      },
+
+      async handleAudit(status) {
+        //生产主管审批选择技术员
+        if (this.taskDefinitionKey === 'deptLeaderAssign') {
+          if (!this.form.userId) {
+            this.$message.warning(`请选择负责人!`);
+            return;
+          }
+          let userInfo = this.userOptions.find(
+            (item) => item.id == this.form.userId
+          );
+          await assign({
+            userId: userInfo.id,
+            userName: userInfo.name,
+            id: this.taskId,
+            reason: this.form.reason,
+            businessId:this.businessId
+          });
+          this.$emit('handleAudit', {
+            status,
+            title: status === 0 ? '驳回' : ''
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss"></style>

+ 4 - 0
src/views/bpm/handleTask/components/quotation/addDialog.vue

@@ -253,6 +253,7 @@
     getDetail
   } from '@/api/bpm/components/saleManage/quotation';
   import { copyObj } from '@/utils/util';
+  import { getFile } from '@/api/system/file';
 
   export default {
     mixins: [dictMixins],
@@ -442,6 +443,9 @@
         };
         this.$refs.headRef.open(item);
       },
+      downloadFile(file) {
+        getFile({ objectName: file.storePath }, file.name);
+      },
       //选择报价方人回调
       changePersonel(obj) {
         this.$set(this.form, 'quoteLinkId', obj.id);

+ 20 - 3
src/views/bpm/handleTask/components/quotation/detailDialog.vue

@@ -187,6 +187,19 @@
           >
         </div>
       </template>
+      <template v-slot:customerReqFiles="{ row }">
+          <div v-if="row.customerReqFiles && row.customerReqFiles?.length">
+            <el-link
+              v-for="link in row.customerReqFiles"
+              :key="link.id"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(link)"
+            >
+              {{ link.name }}</el-link
+            >
+          </div>
+        </template>
     </ele-pro-table>
   </div>
   <!-- </ele-modal> -->
@@ -315,6 +328,12 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 240,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles'
+          },
           {
             width: 120,
             prop: 'technicalAnswerName',
@@ -332,9 +351,7 @@
             prop: 'technicalDrawings',
             label: '技术图纸',
             slot: 'technicalDrawings',
-            formatter: (_row, _column, cellValue) => {
-              return _row.guaranteePeriod + _row.guaranteePeriodUnitName;
-            }
+           
           },
           {
             width: 220,

+ 45 - 13
src/views/bpm/handleTask/components/quotation/inventoryTable.vue

@@ -172,11 +172,12 @@
       <template v-slot:measuringUnit="scope">
         <el-form-item
           style="margin-bottom: 20px"
-          :prop="'datasource.' + scope.$index + '.measuringUnit'" 
+          :prop="'datasource.' + scope.$index + '.measuringUnit'"
         >
           <el-input
             :disabled="taskDefinitionKey == 'technicianApprove'"
-            v-model="scope.row.measuringUnit" disabled
+            v-model="scope.row.measuringUnit"
+            disabled
             placeholder="请输入"
           ></el-input>
         </el-form-item>
@@ -205,8 +206,11 @@
             trigger: 'change'
           }"
         >
-          
-          <el-input v-model="scope.row.singlePrice" placeholder="请输入" :disabled="taskDefinitionKey == 'technicianApprove'">
+          <el-input
+            v-model="scope.row.singlePrice"
+            placeholder="请输入"
+            :disabled="taskDefinitionKey == 'technicianApprove'"
+          >
             <template slot="append">元</template>
           </el-input>
         </el-form-item>
@@ -249,11 +253,6 @@
         <el-form-item
           style="margin-bottom: 20px"
           :prop="'datasource.' + scope.$index + '.technicalDrawings'"
-          :rules="{
-            required: false,
-            message: '请输入',
-            trigger: 'change'
-          }"
         >
           <fileUpload
             v-model="scope.row.technicalDrawings"
@@ -264,6 +263,30 @@
         </el-form-item>
       </template>
 
+      <template v-slot:customerReqFiles="scope">
+        <el-form-item
+          style="margin-bottom: 20px"
+          :prop="'datasource.' + scope.$index + '.customerReqFiles'"
+        >
+          <div v-if="row.customerReqFiles && row.customerReqFiles?.length&&taskDefinitionKey != 'technicianApprove'">
+            <el-link
+              v-for="link in row.customerReqFiles"
+              :key="link.id"
+              type="primary"
+              :underline="false"
+              @click="downloadFile(link)"
+            >
+              {{ link.name }}</el-link
+            >
+          </div>
+          <fileUpload
+            v-model="scope.row.customerReqFiles"
+            module="main"
+            :showLib="false"
+            :limit="5"
+          />
+        </el-form-item>
+      </template>
       <template v-slot:workHour="scope">
         {{ getHour(scope.row) }}
       </template>
@@ -413,6 +436,12 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 220,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles'
+          },
           {
             width: 130,
             prop: 'technicalAnswerName',
@@ -467,6 +496,7 @@
             v.guaranteePeriodUnitCode
           );
           v.technicalDrawings = v.technicalDrawings || null;
+          v.customerReqFiles = v.customerReqFiles || null;
         });
         return comitDatasource;
       },
@@ -488,10 +518,12 @@
       //修改回显
       putTableValue(data) {
         if (data && data?.length) {
-          data.forEach(item=>{
-            item['technicalAnswerId']=item['technicalAnswerId']||this.$store.state.user.info.userId
-            item['technicalAnswerName']=item['technicalAnswerName']||this.$store.state.user.info.name
-          })
+          data.forEach((item) => {
+            item['technicalAnswerId'] =
+              item['technicalAnswerId'] || this.$store.state.user.info.userId;
+            item['technicalAnswerName'] =
+              item['technicalAnswerName'] || this.$store.state.user.info.name;
+          });
           this.form.datasource = data;
         }
       },

+ 224 - 208
src/views/bpm/handleTask/components/quotation/product-list.vue

@@ -1,242 +1,258 @@
 <template>
-    <el-dialog title="选择产品" :visible.sync="visible" :before-close="handleClose" :close-on-click-modal="false"  top="5vh"
-        :close-on-press-escape="false" append-to-body width="80%">
-        <el-card shadow="never">
-            <searchProduct @search="reload"></searchProduct>
-            <ele-split-layout width="244px" allow-collapse :right-style="{ overflow: 'hidden' }">
-                <div class="ele-border-lighter split-layout-right-content">
-                    <productTree @handleNodeClick="handleNodeClick" :isFirstRefreshTable="false" ref="treeList" />
-                </div>
-                <!-- 表格 -->
-                <template v-slot:content>
-                    <ele-pro-table ref="table" :columns="columns" :datasource="datasource" row-key="id"
-                        height="calc(100vh - 350px)" class="dict-table" @cell-click="cellClick">
-                        <!-- 表头工具栏 -->
-                        <template v-slot:action="{ row }">
-                            <el-radio class="radio" v-model="radio" :label="row.code"><i></i></el-radio>
-                        </template>
-                    </ele-pro-table>
-                </template>
-            </ele-split-layout>
-
-
-
-
-
-
-
-        </el-card>
-
-        <div class="btns">
-            <el-button type="primary" size="small" @click="selected">选择</el-button>
-            <el-button size="small" @click="handleClose">关闭</el-button>
+  <el-dialog
+    title="选择产品"
+    :visible.sync="visible"
+    :before-close="handleClose"
+    :close-on-click-modal="false"
+    top="5vh"
+    :close-on-press-escape="false"
+    append-to-body
+    width="80%"
+  >
+    <el-card shadow="never">
+      <searchProduct @search="reload"></searchProduct>
+      <ele-split-layout
+        width="244px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div class="ele-border-lighter split-layout-right-content">
+          <productTree
+            @handleNodeClick="handleNodeClick"
+            :isFirstRefreshTable="false"
+            ref="treeList"
+          />
         </div>
-
-    </el-dialog>
+        <!-- 表格 -->
+        <template v-slot:content>
+          <ele-pro-table
+            ref="table"
+            :columns="columns"
+            :datasource="datasource"
+            row-key="id"
+            height="calc(100vh - 350px)"
+            class="dict-table"
+            @cell-click="cellClick"
+          >
+            <!-- 表头工具栏 -->
+            <template v-slot:action="{ row }">
+              <el-radio class="radio" v-model="radio" :label="row.code"
+                ><i></i
+              ></el-radio>
+            </template>
+          </ele-pro-table>
+        </template>
+      </ele-split-layout>
+    </el-card>
+
+    <div class="btns">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </el-dialog>
 </template>
-  
-<script>
 
-import { getProductList } from '@/api/bpm/components/saleManage/contact';
-import searchProduct from './searchProduct.vue';
-import productTree from '@/components/productTree';
-export default {
+<script>
+  import { getProductList } from '@/api/bpm/components/saleManage/contact';
+  import searchProduct from './searchProduct.vue';
+  import productTree from '@/components/productTree';
+  export default {
     components: {
-        productTree,
-        searchProduct
+      productTree,
+      searchProduct
     },
- 
-    data() {
-        return {
-            visible: false,
-            currentIndex:null,
-             columns: [
-
-                {
-                    action: 'action',
-                    slot: 'action',
-                    align: 'center',
-                    label: '选择'
-                },
-                {
-          columnKey: 'index',
-          type: 'index',
-          width: 50,
-          align: 'center',
-          showOverflowTooltip: true,
-          label: '序号'
-        },
-        {
-          prop: 'code',
-          label: '编码',
-          align: 'center',
-          showOverflowTooltip: true,
-          minWidth: 110
-        },
-        {
-          prop: 'name',
-          label: '名称',
-          align: 'center',
-          showOverflowTooltip: true,
-          minWidth: 110
-        },
-
-        {
-          prop: 'brandNum',
-          align: 'center',
-          label: '牌号',
-          showOverflowTooltip: true
-        },
-        {
-          prop: 'modelType',
-          label: '型号',
-          align: 'center',
-          showOverflowTooltip: true
-        },
-        {
-          prop: 'specification',
-          label: '规格',
-          align: 'center',
-          showOverflowTooltip: true
-        },
-        {
-          prop: 'measuringUnit',
-          label: '计量单位',
-          showOverflowTooltip: true,
-          minWidth: 90
-        },
-
-        {
-          prop: 'weightUnit',
-          label: '重量单位',
-          showOverflowTooltip: true,
-          minWidth: 90
-        },
-
-        {
-          prop: 'roughWeight',
-          label: '毛重',
-          showOverflowTooltip: true,
-          minWidth: 90
-        },
-
-        {
-          prop: 'netWeight',
-          label: '净重',
-          showOverflowTooltip: true,
-          minWidth: 90
-        },
-
-
-        {
-          prop: 'packingUnit',
-          align: 'center',
-          label: '包装单位',
-          showOverflowTooltip: true
-        },
-        {
-          prop: 'categoryLevelPath',
-          label: '分类',
-          align: 'center',
-          showOverflowTooltip: true
-        }  ],
-
-            radio: null,
-        }
+    props: {
+      isSole: {
+        default: () => false,
+        type: Boolean
+      }
     },
 
-    watch: {
-
+    data() {
+      return {
+        visible: false,
+        columns: [
+          {
+            action: 'action',
+            slot: 'action',
+            align: 'center',
+            label: '选择'
+          },
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 50,
+            align: 'center',
+            showOverflowTooltip: true,
+            label: '序号'
+          },
+          {
+            prop: 'code',
+            label: '编码',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'name',
+            label: '名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            prop: 'brandNum',
+            align: 'center',
+            label: '牌号',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'modelType',
+            label: '型号',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'specification',
+            label: '规格',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'measuringUnit',
+            label: '计量单位',
+            showOverflowTooltip: true,
+            minWidth: 90
+          },
+
+          {
+            prop: 'weightUnit',
+            label: '重量单位',
+            showOverflowTooltip: true,
+            minWidth: 90
+          },
+
+          {
+            prop: 'roughWeight',
+            label: '毛重',
+            showOverflowTooltip: true,
+            minWidth: 90
+          },
+
+          {
+            prop: 'netWeight',
+            label: '净重',
+            showOverflowTooltip: true,
+            minWidth: 90
+          },
+
+          {
+            prop: 'packingUnit',
+            align: 'center',
+            label: '包装单位',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryLevelPath',
+            label: '分类',
+            align: 'center',
+            showOverflowTooltip: true
+          }
+        ],
+        data: [],
+        radio: null
+      };
     },
-    methods: {
-        open(item,currentIndex) {
-            this.currentIndex = currentIndex
-            if (item&&item.id) {
-                this.radio = item.id
-            }
-           
-            this.visible = true
-        },
-
-
-        /* 表格数据源 */
-        datasource({ page, limit, where, order }) {
-            return getProductList({
-                pageNum: page,
-                size: limit,
-                categoryLevelId:9,
-                ...where
-            });
-        },
-
-
-        /* 刷新表格 */
-        reload(where) {
-            this.$refs.table.reload({ pageNum: 1, where: where  });
-        },
-
-        handleNodeClick(data, node) {
-            this.curNodeData = data;
-            this.reload({ categoryLevelId: data.id });
-        },
-
-
-        // 单击获取id
-        cellClick(row) {
-            this.current = row
-            this.radio = row.id
-        },
-        handleClose() {
-            this.visible = false
-            this.current = null
-            this.radio = ''
-        },
-
-        selected() {
-            if (!this.current) {
-                return this.$message.warning('请至少选择一条数据')
-            }
-            this.$emit('changeParent', this.current,this.currentIndex)
-            this.handleClose()
-        },
-
-
 
+    watch: {},
+    methods: {
+      open(item, data = []) {
+        this.data = data;
+        if (item && item.id) {
+          this.radio = item.id;
+        }
 
+        this.visible = true;
+      },
+
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        return getProductList({
+          pageNum: page,
+          size: limit,
+          categoryLevelId: 9,
+          ...where
+        });
+      },
+
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ pageNum: 1, where: where });
+      },
+
+      handleNodeClick(data, node) {
+        this.curNodeData = data;
+        this.reload({ categoryLevelId: data.id });
+      },
+
+      // 单击获取id
+      cellClick(row) {
+        this.current = row;
+        this.radio = row.id;
+      },
+      handleClose() {
+        this.visible = false;
+        this.current = null;
+        this.radio = '';
+      },
+
+      selected() {
+        if (!this.current) {
+          return this.$message.warning('请至少选择一条数据');
+        }
 
+        if (
+          this.isSole &&
+          this.data.map((item) => item.productCode).includes(this.current.code)
+        ) {
+          return this.$message.error('选择的产品已经存在列表了');
+        }
+        this.$emit('changeParent', this.current);
+        this.handleClose();
+      }
     }
-}
+  };
 </script>
-  
+
 <style lang="scss" scoped>
-.tree_col {
+  .tree_col {
     border: 1px solid #eee;
     padding: 10px 0;
     box-sizing: border-box;
     height: 500px;
     overflow: auto;
-}
+  }
 
-.table_col {
+  .table_col {
     padding-left: 10px;
 
     ::v-deep .el-table th.el-table__cell {
-        background: #f2f2f2;
+      background: #f2f2f2;
     }
-}
+  }
 
-.pagination {
+  .pagination {
     text-align: right;
     padding: 10px 0;
-}
+  }
 
-.btns {
+  .btns {
     text-align: center;
     padding: 10px 0;
-}
+  }
 
-.topsearch {
+  .topsearch {
     margin-bottom: 15px;
-}
+  }
 </style>
-  

+ 23 - 7
src/views/bpm/handleTask/components/quotation/submit.vue

@@ -1,7 +1,7 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
-      <el-form-item
+      <!-- <el-form-item
         label="技术员"
         prop="technicianId"
         style="margin-bottom: 20px"
@@ -25,8 +25,17 @@
             :value="item.id"
           />
         </el-select>
-      </el-form-item>
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      </el-form-item> -->
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -47,7 +56,7 @@
         type="success"
         size="mini"
         v-if="taskDefinitionKey === 'productionSupervisorApprove1'"
-        @click="handleAudit(0, 'zp')"
+        @click="head"
         >指派技术员
       </el-button>
       <el-button
@@ -87,6 +96,7 @@
         >转办
       </el-button> -->
     </div>
+    <head-list ref="headRef" @changeParent="changePersonel"></head-list>
   </el-col>
 </template>
 
@@ -97,12 +107,12 @@
   } from '@/api/bpm/components/saleManage/quotation';
   import { approveTaskWithVariables } from '@/api/bpm/task';
   import { listAllUserBind } from '@/api/system/organization';
-
+  import headList from '@/components/headList';
   // 流程实例的详情页,可用于审批
   export default {
     name: '',
     components: {
-      //   Parser
+      headList
     },
     props: {
       businessId: {
@@ -145,7 +155,13 @@
       handleBackList() {
         this.$emit('handleBackList');
       },
-
+      head() {
+        this.$refs.headRef.open();
+      },
+      changePersonel(data) {
+        this.form.technicianId = data.id;
+        this.handleAudit(1, 'zp');
+      },
       async handleAudit(status, type) {
         //生产主管审批选择技术员
         if (this.taskDefinitionKey === 'productionSupervisorApprove1') {

+ 7 - 42
src/views/bpm/handleTask/components/saleOrder/accountstatement/submit.vue

@@ -1,32 +1,16 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
-      <!-- <el-form-item
-        label="生产主管"
-        prop="productionSupervisorId"
+      <el-form-item
+        label="审批建议"
+        prop="reason"
         style="margin-bottom: 20px"
         :rules="{
           required: true,
           message: '请选择',
           trigger: 'change'
         }"
-        v-if="taskDefinitionKey == 'deptLeaderApprove'"
       >
-        <el-select
-          v-model="form.productionSupervisorId"
-          clearable
-          style="width: 100%"
-          :filterable="true"
-        >
-          <el-option
-            v-for="item in userOptions"
-            :key="item.id"
-            :label="item.name"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item> -->
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -114,14 +98,11 @@
       return {
         form: {
           technicianId: '',
-          reason: '',
-          productionSupervisorId: ''
-        },
+          reason: ''
+        }
       };
     },
-    created() {
-   
-    },
+    created() {},
     methods: {
       /** 处理转办审批人 */
       handleUpdateAssignee() {
@@ -143,10 +124,7 @@
           if (!arr) {
             return;
           }
-          if (
-            this.taskDefinitionKey === 'uploadReceipt' &&
-            arr.replied === 0
-          ) {
+          if (this.taskDefinitionKey === 'uploadReceipt' && arr.replied === 0) {
             this.$message.error('回执附件不能为空');
             return;
           }
@@ -156,19 +134,6 @@
           }
         }
 
-        // if (this.taskDefinitionKey === 'deptLeaderApprove') {
-        //   if (!this.form.productionSupervisorId) {
-        //     this.$message.error('请选择生产主管!');
-        //     return;
-        //   }
-        // }
-        // if (this.taskDefinitionKey === 'productionSupervisorApprove') {
-        //   let arr = await this.getTableValue();
-        //   let ids = arr.productList.map((item) => item.warehouseId);
-        //   let data = await getWarehouseListByIds(ids || []);
-
-        //   storemanIds = data.map((item) => item.ownerId);
-        // }
         this._approveTaskWithVariables(status);
       },
       async _approveTaskWithVariables(status) {

+ 32 - 7
src/views/bpm/handleTask/components/saleOrder/inventoryTable.vue

@@ -11,7 +11,7 @@
       >
       </ele-pro-table>
     </template> -->
-    <template >
+    <template>
       <ele-pro-table
         ref="table"
         :needPage="false"
@@ -268,6 +268,19 @@
             />
           </el-form-item>
         </template>
+        <template v-slot:customerReqFiles="scope">
+          <el-form-item
+            style="margin-bottom: 20px"
+            :prop="'datasource.' + scope.$index + '.customerReqFiles'"
+          >
+            <fileUpload
+              v-model="scope.row.customerReqFiles"
+              module="main"
+              :showLib="false"
+              :limit="5"
+            />
+          </el-form-item>
+        </template>
         <template v-slot:guaranteePeriodDeadline="scope">
           <el-form-item
             :prop="'datasource.' + scope.$index + '.guaranteePeriodDeadline'"
@@ -467,6 +480,12 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 240,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles'
+          },
           {
             width: 120,
             prop: 'technicalAnswerName',
@@ -508,8 +527,7 @@
             prop: 'productName',
             label: '名称',
             slot: 'productName',
-            headerSlot:'headerProductName'
-
+            headerSlot: 'headerProductName'
           },
           {
             width: 120,
@@ -547,8 +565,7 @@
             prop: 'totalCount',
             label: '数量',
             slot: 'totalCount',
-            headerSlot:'headerTotalCount'
-
+            headerSlot: 'headerTotalCount'
           },
           {
             width: 80,
@@ -561,8 +578,7 @@
             prop: 'singlePrice',
             label: '单价',
             slot: 'singlePrice',
-            headerSlot:'headerSinglePrice'
-
+            headerSlot: 'headerSinglePrice'
           },
           {
             width: 120,
@@ -600,6 +616,12 @@
           //   label: '',
           //   slot: 'guaranteePeriodUnitCode'
           // },
+          {
+            width: 240,
+            prop: 'customerReqFiles',
+            label: '客户需求',
+            slot: 'customerReqFiles'
+          },
           {
             width: 130,
             prop: 'technicalAnswerName',
@@ -659,6 +681,9 @@
           v.technicalDrawings = Array.isArray(v.technicalDrawings)
             ? v.technicalDrawings
             : [];
+          v.customerReqFiles = Array.isArray(v.customerReqFiles)
+            ? v.customerReqFiles
+            : [];
         });
         return comitDatasource;
       },

+ 13 - 2
src/views/bpm/handleTask/components/saleOrder/invoice/submit.vue

@@ -1,7 +1,16 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -22,7 +31,9 @@
         type="danger"
         size="mini"
         @click="handleAudit(0)"
-        v-if="['deptLeaderApprove','storemanApprove'].includes(taskDefinitionKey)"
+        v-if="
+          ['deptLeaderApprove', 'storemanApprove'].includes(taskDefinitionKey)
+        "
         >驳回
       </el-button>
 

+ 6 - 33
src/views/bpm/handleTask/components/saleOrder/returnGoods/submit.vue

@@ -2,31 +2,15 @@
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
       <el-form-item
-        label="生产主管"
-        prop="productionSupervisorId"
+        label="审批建议"
+        prop="reason"
         style="margin-bottom: 20px"
         :rules="{
           required: true,
           message: '请选择',
           trigger: 'change'
         }"
-        v-if="taskDefinitionKey == 'deptLeaderApprove'"
       >
-        <el-select
-          v-model="form.productionSupervisorId"
-          clearable
-          style="width: 100%"
-          :filterable="true"
-        >
-          <el-option
-            v-for="item in userOptions"
-            :key="item.id"
-            :label="item.name"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -42,7 +26,7 @@
         @click="handleAudit(1)"
         >通过
       </el-button>
-      <el-button
+      <!-- <el-button
         icon="el-icon-circle-close"
         type="danger"
         size="mini"
@@ -53,7 +37,7 @@
           )
         "
         >驳回
-      </el-button>
+      </el-button> -->
 
       <!-- <el-button
         icon="el-icon-circle-close"
@@ -117,8 +101,7 @@
       return {
         form: {
           technicianId: '',
-          reason: '',
-          productionSupervisorId: ''
+          reason: ''
         },
         userOptions: []
       };
@@ -163,17 +146,11 @@
           }
         }
 
-        if (this.taskDefinitionKey === 'deptLeaderApprove') {
-          if (!this.form.productionSupervisorId) {
-            this.$message.error('请选择生产主管!');
-            return;
-          }
-        }
         if (this.taskDefinitionKey === 'productionSupervisorApprove') {
           let arr = await this.getTableValue();
           let ids = arr.productList.map((item) => item.warehouseId);
           let data = await getWarehouseListByIds(ids || []);
-      
+
           storemanIds = data.map((item) => item.ownerId);
         }
         this._approveTaskWithVariables(
@@ -190,10 +167,6 @@
         if (storemanIds) {
           variables['storemanIds'] = storemanIds;
         }
-        if (this.form.productionSupervisorId) {
-          variables['productionSupervisorId'] =
-            this.form.productionSupervisorId;
-        }
 
         approveTaskWithVariables({
           id: this.taskId,

+ 12 - 5
src/views/bpm/handleTask/components/saleOrder/submit.vue

@@ -1,7 +1,16 @@
 <template>
   <el-col :span="16" :offset="6">
     <el-form label-width="100px" ref="formRef" :model="form">
-      <el-form-item label="审批建议" prop="reason" style="margin-bottom: 20px">
+      <el-form-item
+        label="审批建议"
+        prop="reason"
+        style="margin-bottom: 20px"
+        :rules="{
+          required: true,
+          message: '请选择',
+          trigger: 'change'
+        }"
+      >
         <el-input
           type="textarea"
           v-model="form.reason"
@@ -85,12 +94,10 @@
         form: {
           technicianId: '',
           reason: ''
-        },
+        }
       };
     },
-    created() {
-     
-    },
+    created() {},
     methods: {
       /** 处理转办审批人 */
       handleUpdateAssignee() {