Răsfoiți Sursa

生产排程、以及待建产品需求

cz 1 an în urmă
părinte
comite
f1700593cf

+ 6 - 1
src/components/byTable/index.vue

@@ -229,6 +229,11 @@ export default defineComponent({
     //   type: Number,
     //   required: false,
     // },
+    otherHeight: {
+      type: Number,
+      default: 0,
+    },
+
     tableBorder: {
       type: Boolean,
       required: false,
@@ -309,7 +314,7 @@ export default defineComponent({
       // } else {
       //   tableHeight.value = 550;
       // }
-      tableHeight.value = window.innerHeight - 229;
+      tableHeight.value = window.innerHeight - 229 - props.otherHeight;
       if (props.hidePagination) {
         tableHeight.value += 42;
       }

+ 13 - 9
src/components/headerBar/header-bar.vue

@@ -135,23 +135,23 @@
         <notice v-model="noticeTableModal" @changeNum="(e) => (badgeNum = e)" @openNotice="noticeTableModal = true"></notice>
         <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
           <div class="dropdown-box" style="color:#fff">
-            {{ userData }}
+            {{ getUserData() }}
           </div>
           <template #dropdown>
             <el-dropdown-menu>
+              <el-dropdown-item v-for="company in useUserStore().user.companyList" :key="company.deptId" @click="changeCompany(company)">
+                <span :style="{color:company.deptId==useUserStore().user.companyId?'#409EFF':''}">{{company.deptName }}</span>
+              </el-dropdown-item>
               <router-link to="/user/profile">
-                <el-dropdown-item>{{
+                <el-dropdown-item divided>{{
                   $t("header.personalCenter")
                 }}</el-dropdown-item>
               </router-link>
-              <el-dropdown-item divided v-for="company in useUserStore().user.companyList" :key="company.deptId"
-                                @click="changeCompany(company.deptId)">
-                <span :style="{color:company.deptId==useUserStore().user.companyId?'#409EFF':''}">{{company.deptName }}</span>
-              </el-dropdown-item>
+
               <!-- <el-dropdown-item command="setLayout">
                 <span>{{ $t("header.layoutSettings") }}</span>
               </el-dropdown-item> -->
-              <el-dropdown-item divided command="logout">
+              <el-dropdown-item command="logout">
                 <span>{{ $t("header.logout") }}</span>
               </el-dropdown-item>
             </el-dropdown-menu>
@@ -641,14 +641,14 @@ function handleCommand(command) {
   }
 }
 
-function changeCompany(val) {
+function changeCompany(company) {
+  let { deptId: val, deptName } = company;
   if (!val) {
     return;
   }
   if (proxy.useUserStore().user.companyId == val) {
     return;
   }
-  proxy.useUserStore().setCurrentCompany(val);
   proxy
     .msgConfirm()
     .then((res) => {
@@ -657,6 +657,7 @@ function changeCompany(val) {
           companyId: val,
         })
         .then((res) => {
+          proxy.useUserStore().setCurrentCompany(val, deptName);
           proxy.msgTip("操作成功", 1);
           setTimeout(() => {
             window.location.reload();
@@ -739,6 +740,9 @@ function calcAutoListChidren() {
   autoListChidrenNum.value = Math.floor((getBrowserWidth() - 616) / 120);
 }
 
+const getUserData = () => {
+  return userData.value + `(${proxy.useUserStore().currentCompanyName})`;
+};
 //一维数组转tree
 const jobData = ref({});
 onMounted(() => {

+ 62 - 8
src/components/process/SF/ContractChange.vue

@@ -8,6 +8,29 @@
             " @click="clickCopy(1)">复制合同</el-button>
         </div>
       </template>
+      <template #ofCompanyId>
+        <div style="width: 100%">
+          <el-form-item label="业务公司" class="margin-b-0 wid100" required>
+            <el-row style="width: 100%">
+              <el-col :span="12">
+                <el-form-item prop="ofCompanyId" label="" label-width="0px" class="margin-b-0 wid100">
+                  <el-tree-select v-model="formData.data.ofCompanyId" :data="useUserStore().allDict['tree_company_data']" style="width: 100%"
+                                  placeholder="公司" default-expand-all
+                                  :props="{ value:  'deptId', label:  'deptName', children: 'children', disabled: 'disabled' }"
+                                  @change="handleOfCompanyIdChange" :disabled="useUserStore().currentCompany==useUserStore().user.companyId" />
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item prop="deptId" label="" label-width="0px" class="margin-b-0 wid100">
+                  <el-tree-select v-model="formData.data.deptId" :data="deptData" style="width: 100%" placeholder="部门" default-expand-all
+                                  :props="{ value:  'deptId', label:  'deptName', children: 'children', disabled: 'disabled' }" />
+                </el-form-item>
+              </el-col>
+
+            </el-row>
+          </el-form-item>
+        </div>
+      </template>
       <template #seller>
         <div style="width: 100%">
           <el-form-item prop="sellCorporationId" label="卖方信息" class="wid100">
@@ -468,6 +491,7 @@ const countryData = ref([]);
 const provinceData = ref([]);
 const cityData = ref([]);
 const treeData = ref([]);
+const deptData = ref([]);
 const openProductCompany = ref(false);
 const copyType = ref(1);
 const copyContract = ref(false);
@@ -529,13 +553,19 @@ const formConfig = computed(() => {
       disabled: true,
       isShow: formData.data.code ? true : false,
     },
+    // {
+    //   type: "treeSelect",
+    //   prop: "ofCompanyId",
+    //   label: "业务公司",
+    //   data: proxy.useUserStore().allDict["tree_company_data"],
+    //   propsTreeLabel: "deptName",
+    //   propsTreeValue: "deptId",
+    //   itemWidth: 50,
+    // },
     {
-      type: "treeSelect",
-      prop: "ofCompanyId",
-      label: "业务公司",
-      data: proxy.useUserStore().allDict["tree_company_data"],
-      propsTreeLabel: "deptName",
-      propsTreeValue: "deptId",
+      type: "slot",
+      slotName: "ofCompanyId",
+      label: "",
       itemWidth: 50,
     },
     {
@@ -886,6 +916,7 @@ const rules = ref({
   ofCompanyId: [
     { required: true, message: "请选择业务公司", trigger: "change" },
   ],
+  deptId: [{ required: true, message: "请选择业务部门", trigger: "change" }],
   companyId: [{ required: true, message: "请选择生产公司", trigger: "change" }],
   contractType: [
     { required: true, message: "请选择订单类型", trigger: "change" },
@@ -1044,6 +1075,23 @@ const getCityData = (id, type, isChange) => {
 getDict();
 getCityData("0");
 
+const handleOfCompanyIdChange = (val) => {
+  if (val) {
+    proxy
+      .get("/tenantDept/list", {
+        pageNum: 1,
+        pageSize: 9999,
+        keyword: "",
+        parentId: val,
+        tenantId: proxy.useUserStore().user.tenantId,
+        type: 2,
+      })
+      .then((res) => {
+        deptData.value = proxy.handleTree(res.data, "deptId");
+      });
+  }
+};
+
 const sellCorporationIdChange = (val) => {
   if (val) {
     proxy.post("/corporation/detail", { id: val }).then((res) => {
@@ -1812,8 +1860,14 @@ const getPriceSheetData = (id) => {
 // 是否能编辑修改产品列表
 const isEditList = ref(true);
 onMounted(() => {
-  if (currencyData.value && currencyData.value.length > 0) {
-    formData.data.currency = currencyData.value[0].dictKey;
+  if (
+    proxy.useUserStore().currentCompany == proxy.useUserStore().user.companyId
+  ) {
+    formData.data.ofCompanyId = proxy.useUserStore().user.companyId;
+    handleOfCompanyIdChange(formData.data.ofCompanyId);
+    // setTimeout(() => {
+    //   formData.data.deptId = proxy.useUserStore().user.deptId;
+    // }, 1500);
   }
   formOption.disabled = judgeStatus();
   // 报价转销售订单

+ 0 - 1
src/directive/permission/hasPermi.js

@@ -12,7 +12,6 @@
      } = binding
      const all_permission = "*:*:*";
      const permissions = useUserStore().permissions
-     console.log(permissions, value, 'ssaa');
      if (value && value instanceof Array && value.length > 0) {
        const permissionFlag = value
 

+ 6 - 2
src/store/modules/user.js

@@ -21,7 +21,9 @@ const useUserStore = defineStore(
       permissions: [],
       user: {},
       allDict: {},
-      currentCompany: ""
+      currentCompany: "",
+      currentCompanyName: "",
+
     }),
     actions: {
       // 登录
@@ -57,6 +59,7 @@ const useUserStore = defineStore(
             this.name = user.userName
             this.user = user
             this.currentCompany = user.companyId
+            this.currentCompanyName = user.companyName
             this.avatar = avatar;
             resolve(res)
           }).catch(error => {
@@ -78,8 +81,9 @@ const useUserStore = defineStore(
         });
       },
       // 当前的公司
-      setCurrentCompany(val) {
+      setCurrentCompany(val, name) {
         this.currentCompany = val
+        this.currentCompanyName = name
       },
       // 退出系统
       logOut() {

+ 46 - 35
src/views/EHSD/productLibrary/companyProduct/index.vue

@@ -110,7 +110,6 @@
                   </el-col>
                 </el-row>
               </el-form-item>
-
             </div>
           </template>
 
@@ -990,7 +989,29 @@ const treeChange = (e) => {
     getList({ productClassifyId: e.id });
   }
 };
-
+const productCustomInfoListData = ref([
+  {
+    type: 1,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 2,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 3,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+]);
 const openModal = () => {
   dialogVisible.value = true;
   modalType.value = "add";
@@ -1003,29 +1024,7 @@ const openModal = () => {
     isCustomized: 0,
     packAsk: [],
     productBomDetailList: [],
-    productCustomInfoList: [
-      {
-        type: 1,
-        isCheck: 0,
-        isCheckBox: false,
-        fileList: [],
-        remark: "",
-      },
-      {
-        type: 2,
-        isCheck: 0,
-        isCheckBox: false,
-        fileList: [],
-        remark: "",
-      },
-      {
-        type: 3,
-        isCheck: 0,
-        isCheckBox: false,
-        fileList: [],
-        remark: "",
-      },
-    ],
+    productCustomInfoList: productCustomInfoListData.value,
   };
   // if (currencyData.value && currencyData.value.length > 0) {
   //   formData.data.currency = currencyData.value[0].dictKey;
@@ -1110,16 +1109,6 @@ const getDtl = (row) => {
       formData.data.productCustomInfoList &&
       formData.data.productCustomInfoList.length > 0
     ) {
-      // let productCustomInfoIds = formData.data.productCustomInfoList.map(
-      //   (x) => x.id
-      // );
-      // proxy.getFileData({
-      //   businessIdList: productCustomInfoIds,
-      //   data: formData.data.productCustomInfoList,
-      //   att: "id",
-      //   businessType: "0",
-      //   fileAtt: "fileList",
-      // });
       formData.data.productCustomInfoList.forEach((x) => {
         x.isCheckBox = x.isCheck == 1;
         if (!x.fileList) {
@@ -1133,6 +1122,28 @@ const getDtl = (row) => {
         }
       });
     }
+    // let list = [];
+    // for (let i = 0; i < productCustomInfoListData.value.length; i++) {
+    //   const iele = productCustomInfoListData.value[i];
+    //   let current = formData.data.productCustomInfoList.find(
+    //     (x) => x.type == iele.type
+    //   );
+    //   if (current) {
+    //     list.push({
+    //       ...iele,
+    //       ...current,
+    //       isCheckBox: current.isCheck == 1,
+    //       fileList: current.fileList.map((x) => ({
+    //         ...x,
+    //         url: x.fileUrl,
+    //         name: x.fileName,
+    //       })),
+    //     });
+    //   } else {
+    //     list.push(iele);
+    //   }
+    // }
+    // formData.data.productCustomInfoList = list;
     if (formData.data.packAsk) {
       formData.data.packAsk = formData.data.packAsk.split(",");
     }

+ 1255 - 0
src/views/EHSD/productLibrary/waitCreateProduct/index.vue

@@ -0,0 +1,1255 @@
+<template>
+  <div class="pageIndexClass">
+
+    <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row
+             :selectConfig="selectConfig" :action-list="[]" @get-list="getList">
+      <template #name="{ item }">
+        <div>
+          <span class="el-click">{{ item.name }}</span>
+        </div>
+      </template>
+
+      <template #size="{ item }">
+        <div v-if="item.productLength && item.productWidth && item.productHeight">
+          <span>{{ item.productLength }}</span>*
+          <span>{{ item.productWidth }}</span>*
+          <span>{{ item.productHeight }}</span>
+        </div>
+        <div v-else></div>
+      </template>
+      <template #price="{ item }">
+        <div v-if="item.price">
+          <span> {{ moneyFormat(item.price ,2)}}</span>
+        </div>
+        <div v-else></div>
+      </template>
+    </byTable>
+
+    <el-dialog :title="modalType == 'add' ? '添加产品' : '编辑产品'" v-model="dialogVisible" width="80%" destroy-on-close>
+      <div class="public_height_dialog">
+        <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
+          <template #nameEnglish>
+            <div style="width: 100%">
+              <el-input v-model="formData.data.nameEnglish" placeholder="请输入" onkeyup="value=value.replace(/[^\x00-\xff]/g, '')"></el-input>
+            </div>
+          </template>
+          <template #productionFile>
+            <div style="width: 100%">
+              <span style="color:#409eff;cursor:pointer" @click="handleClickUpload('prodFilePath',true)"
+                    v-if="!formData.data.prodFilePath">点击上传</span>
+              <span style="color:#409eff;cursor:pointer" @click="handleClickUpload('prodFilePath',false)" v-else>点击查看</span>
+            </div>
+          </template>
+          <template #productionFileOne>
+            <div style="width: 100%">
+              <el-button type="primary" plain @click="handleClickUpload('prodImgPath',true)" v-if="!formData.data.prodImgPath">点击上传</el-button>
+              <el-button type="primary" plain @click="handleClickUpload('prodImgPath',false)" v-else>点击查看</el-button>
+            </div>
+          </template>
+
+          <template #color>
+            <div style="width: 100%">
+              <el-form-item label="颜色" class="margin-b-0 wid100">
+                <el-row style="width: 100%">
+                  <el-col :span="12">
+                    <el-form-item prop="color" label-width="0px" class="margin-b-0 wid100">
+                      <el-input v-model="formData.data.color" placeholder="颜色" />
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="12">
+                    <el-form-item prop="colorCardCode" label-width="0px" class="margin-b-0 wid100">
+                      <el-input v-model="formData.data.colorCardCode" placeholder="色卡号" />
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </el-form-item>
+            </div>
+          </template>
+          <template #size>
+            <div style="width: 100%">
+              <el-form-item label="尺寸" class="margin-b-0 wid100" required>
+                <el-row>
+                  <el-col :span="8">
+                    <el-form-item prop="length" label-width="0px" class="margin-b-0 wid100">
+                      <el-input-number v-model="formData.data['length']" placeholder="长 (cm)" style="width: 100%" :precision="2" :controls="false"
+                                       :min="0" onmousewheel="return false;" />
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="8">
+                    <el-form-item prop="width" label-width="0px" class="margin-b-0 wid100">
+                      <el-input-number v-model="formData.data.width" placeholder="宽 (cm)" style="width: 100%" :precision="2" :controls="false"
+                                       :min="0" onmousewheel="return false;" />
+                    </el-form-item>
+                  </el-col>
+                  <el-col :span="8">
+                    <el-form-item prop="height" label-width="0px" class="margin-b-0 wid100">
+                      <el-input-number v-model="formData.data.height" placeholder="高 (cm)" style="width: 100%" :precision="2" :controls="false"
+                                       :min="0" onmousewheel="return false;" />
+                    </el-form-item>
+                  </el-col>
+                </el-row>
+              </el-form-item>
+            </div>
+          </template>
+
+          <template #materialDetail>
+            <div style="width: 100%;padding-left:15px">
+              <el-button type="primary" @click="clickOpenSelectMaterial(1)" plain>选择包材/配件/辅材</el-button>
+              <el-table :data="formData.data.productBomDetailList" style="width: 100%; margin-top: 16px">
+                <el-table-column prop="productName" label="物料名称" min-width="130" />
+                <el-table-column prop="productCode" label="物料编码" width="150" />
+                <el-table-column label="数量" width="150">
+                  <template #default="{ row, $index }">
+                    <div style="width: 100%">
+                      <el-form-item :prop="'productBomDetailList.' + $index + '.quantity'" :rules="rules.quantity" :inline-message="true"
+                                    class="margin-b-0 wid100">
+                        <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="请输入" style="width: 100%" :precision="0"
+                                         :controls="false" :min="1" />
+                      </el-form-item>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" width="60" align="center" fixed="right">
+                  <template #default="{ $index }">
+                    <el-button type="primary" link @click="handleRemove($index,1)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </template>
+
+          <template #technology>
+            <div style="width:100%">
+              <div class="small-title">
+                ① 工艺线路
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item prop="technologyId" label="工艺产线" class="wid100">
+                    <el-select v-model="formData.data.technologyId" placeholder="请选择" style="width:100%">
+                      <el-option v-for="item in technologyData" :key="item.id" :label="item.name" :value="item.id" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ② LOGO
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item label="LOGO尺寸" class="wid100">
+                    <el-row>
+                      <el-col :span="8">
+                        <el-form-item prop="logoLength" label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.data.logoLength" placeholder="长 (cm)" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item prop="logoWidth" label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.data.logoWidth" placeholder="宽 (cm)" style="width: 100%" :precision="2" :controls="false"
+                                           :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item prop="logoHeight" label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.data.logoHeight" placeholder="高 (cm)" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item prop="colorCount" label="几色印刷" class="wid100">
+                    <el-input-number v-model="formData.data.colorCount" placeholder="请输入" style="width: 100%" :precision="0" :controls="false"
+                                     :min="1" onmousewheel="return false;" />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ③ 折叠
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item prop="isFold" label="是否折叠" class="wid100">
+                    <el-select v-model="formData.data.isFold" placeholder="请选择" style="width:100%">
+                      <el-option :label="'否'" :value="0" />
+                      <el-option :label="'是'" :value="1" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item prop="foldWay" label="折叠数" class="wid100" v-if="formData.data.isFold==1">
+                    <el-select v-model="formData.data.foldWay" placeholder="请选择" style="width:100%">
+                      <el-option v-for="item in foldWayData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ④ 包装要求
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item prop="packAsk" label="包装要求" class="wid100">
+                    <el-select v-model="formData.data.packAsk" placeholder="请选择" style="width:100%" multiple>
+                      <el-option v-for="item in packAskData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ⑤ 是否定制
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item prop="isCustomized" label="是否定制" class="wid100">
+                    <el-select v-model="formData.data.isCustomized" placeholder="请选择" style="width:100%">
+                      <el-option :label="'否'" :value="0" />
+                      <el-option :label="'是'" :value="1" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-row style="width:100%">
+                <el-form-item prop="technologyId" label="定制内容" class="wid100" v-if="formData.data.isCustomized==1">
+                  <table style="width:100%" border class="table">
+                    <tr>
+                      <td style="width:20%">
+                      </td>
+                      <td style="width:40%">附件</td>
+                      <td style="width:40%">备注</td>
+                    </tr>
+                    <tr v-for="(row,index) in formData.data.productCustomInfoList" :key="index">
+                      <td>
+                        <el-checkbox v-model="row.isCheckBox" label="" /> <span style="position:relative;top:-2px"> {{getLabel(row.type)}}</span>
+                      </td>
+                      <td>
+                        <el-upload :file-list="row.fileList" :action="uploadUrl" :data="uploadData" :limit="1" :list-type="'text'"
+                                   :before-upload="(file)=>handleBeforeUploadOne(file,index)" :on-success="()=>handleSuccessOne(index)"
+                                   :on-remove="(file)=>handleRemoveFile(file,index)" :on-preview="onPreviewFile"
+                                   :on-exceed="()=>msgTip(`上传文件数量不可大于1`, 2)">
+                          <el-button text type="primary">上传附件</el-button>
+                        </el-upload>
+                      </td>
+                      <td>
+                        <el-form-item :prop="'productCustomInfoList.' + index + '.remark'" :rules="row.isCheckBox?rules.remark:''"
+                                      class="margin-b-0 wid100">
+                          <el-input v-model="row.remark" placeholder="请输入备注" />
+                        </el-form-item>
+                      </td>
+                    </tr>
+                  </table>
+                </el-form-item>
+              </el-row>
+            </div>
+          </template>
+
+        </byForm>
+      </div>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="defualt" v-debounce>取 消</el-button>
+        <el-button type="primary" @click="submitForm()" size="defualt" v-debounce>确 定</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog :title="'物料选择'" v-model="openSelectMaterial" width="90%" destroy-on-close>
+      <SelectMaterial :isNeRawMaterial="'1'" @selectMaterial="selectMaterial"></SelectMaterial>
+      <template #footer>
+        <el-button @click="bomDialog = false" size="defualt" v-debounce>取 消</el-button>
+      </template>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
+import treeList from "@/components/product/treeList";
+import SelectMaterial from "@/components/product/SelectMaterial.vue";
+import { getToken } from "@/utils/auth";
+const { proxy } = getCurrentInstance();
+const actionUrl = import.meta.env.VITE_APP_BASE_API;
+const loading = ref(false);
+const submitLoading = ref(false);
+const treeData = ref([]);
+const treeDataOne = ref([]);
+const treeListData = ref([]);
+const technologyData = ref([]);
+const companyData = ref([]);
+const currencyData = computed(
+  () => proxy.useUserStore().allDict["account_currency"]
+);
+const packAskData = computed(() => proxy.useUserStore().allDict["pack_ask"]);
+const foldWayData = computed(() => proxy.useUserStore().allDict["fold_way"]);
+
+const headers = ref({ Authorization: "Bearer " + getToken() });
+const uploadData = ref({});
+const tableHeight = ref(0);
+const getTableHeight = () => {
+  tableHeight.value = window.innerHeight - 245;
+};
+getTableHeight();
+window.addEventListener("resize", () => {
+  getTableHeight();
+});
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 3,
+    pageNum: 1,
+    pageSize: 10,
+    type: "",
+    productClassifyId: "",
+    keyword: "",
+    definition: "1",
+    companyId: "",
+  },
+});
+const dialogVisible = ref(false);
+const openExcelDialog = ref(false);
+const excelLoading = ref(false);
+const modalType = ref("add");
+const rules = ref({
+  companyId: [{ required: true, message: "请选择归属公司", trigger: "change" }],
+  productClassifyId: [
+    { required: true, message: "请选择产品分类", trigger: "change" },
+  ],
+  name: [{ required: true, message: "请输入产品名称", trigger: "blur" }],
+  customCode: [{ required: true, message: "请输入产品编号", trigger: "blur" }],
+  length: [{ required: true, message: "请输入长 (cm)", trigger: "blur" }],
+  width: [{ required: true, message: "请输入宽 (cm)", trigger: "blur" }],
+  height: [{ required: true, message: "请输入高 (cm)", trigger: "blur" }],
+  technologyId: [
+    { required: true, message: "请选择生产工艺", trigger: "change" },
+  ],
+  rawMaterialId: [
+    { required: true, message: "请选择原材料", trigger: "change" },
+  ],
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+  remark: [{ required: true, message: "请输入备注", trigger: "blur" }],
+});
+const props = defineProps({
+  selectStatus: Boolean,
+});
+const selectConfig = computed(() => [
+  {
+    label: "业务公司",
+    prop: "companyId",
+    data: companyData.value,
+  },
+]);
+const config = computed(() => {
+  return [
+    // {
+    //   attrs: {
+    //     label: "图片",
+    //     slot: "pic",
+    //     align: "center",
+    //     width: 80,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "业务公司",
+    //     prop: "companyName",
+    //     width: 150,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "产品分类",
+    //     prop: "classifyName",
+    //     "min-width": 200,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "产品编码",
+    //     prop: "customCode",
+    //     width: 180,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "产品名称",
+    //     prop: "productName",
+    //     "min-width": 200,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "产品英文名",
+    //     prop: "nameEnglish",
+    //     "min-width": 120,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "产品规格",
+    //     prop: "spec",
+    //     width: 120,
+    //   },
+    // },
+    {
+      attrs: {
+        label: "原材料",
+        prop: "rawMaterialName",
+        // "min-width": 300,
+      },
+    },
+    {
+      attrs: {
+        label: "颜色",
+        prop: "productColor",
+        // width: 160,
+      },
+    },
+    {
+      attrs: {
+        label: "色卡号",
+        prop: "colorCardCode",
+        // width: 160,
+      },
+    },
+    {
+      attrs: {
+        label: "尺寸 (cm)",
+        slot: "size",
+        // width: 130,
+      },
+    },
+    {
+      attrs: {
+        label: "净重",
+        prop: "netWeight",
+        // width: 100,
+      },
+      render(val) {
+        if (val) {
+          return val + " kg";
+        }
+      },
+    },
+    // {
+    //   attrs: {
+    //     label: "销售价",
+    //     prop: "price",
+    //     width: 100,
+    //   },
+    //   render(val) {
+    //     return proxy.moneyFormat(val, 2);
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "海关编码",
+    //     prop: "hsCode",
+    //     width: 100,
+    //   },
+    // },
+    // {
+    //   attrs: {
+    //     label: "原材料编码",
+    //     prop: "rawMaterialCode",
+    //     width: 120,
+    //   },
+    // },
+
+    {
+      attrs: {
+        label: "操作",
+        width: "100",
+        align: "center",
+        fixed: "right",
+      },
+      renderHTML(row) {
+        return [
+          //  {
+          //     attrs: {
+          //       label: "选择",
+          //       type: "primary",
+          //       text: true,
+          //     },
+          //     el: "button",
+          //     click() {
+          //       clickSelect(row);
+          //     },
+          //   }
+          // {
+          //   attrs: {
+          //     label: "BOM",
+          //     type: "primary",
+          //     text: true,
+          //   },
+          //   el: "button",
+          //   click() {
+          //     bomSetting(row);
+          //   },
+          // },
+          {
+            attrs: {
+              label: "创建产品",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              getDtl(row);
+            },
+          },
+          // {
+          //   attrs: {
+          //     label: "删除",
+          //     type: "danger",
+          //     text: true,
+          //   },
+          //   el: "button",
+          //   click() {
+          //     proxy
+          //       .msgConfirm()
+          //       .then((res) => {
+          //         proxy
+          //           .post("/productInfo/delete", {
+          //             id: row.id,
+          //           })
+          //           .then((res) => {
+          //             proxy.msgTip("删除成功", 1);
+          //             getList();
+          //           });
+          //       })
+          //       .catch((err) => {});
+          //   },
+          // },
+        ];
+      },
+    },
+  ];
+});
+
+const getPriceData = () => {
+  if (
+    formData.data["length"] &&
+    formData.data.width &&
+    formData.data.technologyId &&
+    formData.data.rawMaterialId
+  ) {
+    proxy
+      .post("/productInfo/getProductPrice", {
+        id: formData.data.id || "",
+        length: formData.data["length"],
+        width: formData.data.width,
+        technologyId: formData.data.technologyId,
+        rawMaterialId: formData.data.rawMaterialId,
+      })
+      .then((res) => {
+        formData.data.price = res.price;
+      });
+  }
+};
+
+const formData = reactive({
+  data: {},
+  bomData: {},
+});
+const formOption = reactive({
+  disabled: false,
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+});
+const formDom = ref(null);
+const formConfig = computed(() => {
+  return [
+    {
+      type: "title1",
+      title: "基本信息",
+    },
+    {
+      type: "treeSelect",
+      prop: "companyId",
+      label: "业务公司",
+      data: treeDataOne.value,
+      propsTreeLabel: "deptName",
+      propsTreeValue: "deptId",
+      itemWidth: 50,
+    },
+    {
+      type: "treeSelect",
+      prop: "productClassifyId",
+      label: "产品分类",
+      data: treeData.value,
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "input",
+      prop: "name",
+      label: "产品名称",
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "slot",
+      slotName: "nameEnglish",
+      label: "英文名",
+      itemWidth: 50,
+    },
+    {
+      type: "input",
+      prop: "customCode",
+      label: "产品编号",
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "number",
+      prop: "price",
+      label: "销售价",
+      precision: 2,
+      min: 0.01,
+      controls: false,
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "uploadImg",
+      // listType: "picture-card",
+      // limit: 1,
+      // accept: ".gif, .jpeg, .jpg, .png",
+      prop: "fileList",
+      imgProp: "imageUrl",
+      label: "产品缩略图",
+      itemWidth: 50,
+    },
+    {
+      type: "input",
+      prop: "hsCode",
+      label: "海关编码",
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "slot",
+      slotName: "productionFileOne",
+      label: "产品原图",
+      itemWidth: 100,
+    },
+    {
+      type: "upload",
+      listType: "text",
+      accept: "",
+      limit: 1,
+      prop: "prodFileList",
+      label: "生产文件",
+    },
+    // {
+    //   type: "slot",
+    //   slotName: "productionFile",
+    //   label: "生产文件",
+    //   itemWidth: 100,
+    // },
+    {
+      type: "title1",
+      title: "主材",
+    },
+    {
+      type: "select",
+      prop: "rawMaterialId",
+      label: "原材料",
+      itemWidth: 50,
+      data: rawMaterialData.value,
+      filterable: true,
+      disabled: false,
+      fn: (val) => {
+        // let current = rawMaterialData.value.find((x) => x.value == val);
+        // if (current) {
+        //   formData.data.price = Number(
+        //     parseFloat(
+        //       current["length"] * current.width * current.price
+        //     ).toFixed(2)
+        //   );
+        // }
+        // getPriceData();
+      },
+    },
+
+    // {
+    //   type: "selectInput",
+    //   prop: "price",
+    //   selectProp: "currency",
+    //   label: "销售价",
+    //   itemWidth: 50,
+    //   disabledSelect: true,
+    //   data: currencyData.value,
+    //   disabled: true,
+    // },
+    // {
+    //   type: "select",
+    //   prop: "technologyId",
+    //   label: "生产工艺",
+    //   itemWidth: 50,
+    //   data: technologyData.value,
+    //   filterable: true,
+    //   disabled: false,
+    //   fn: () => {
+    //     // getPriceData();
+    //   },
+    // },
+    // {
+    //   type: "input",
+    //   prop: "spec",
+    //   label: "规格型号",
+    //   itemWidth: 50,
+    //   disabled: false,
+    // },
+    {
+      type: "slot",
+      slotName: "color",
+      prop: "",
+      label: "",
+      itemWidth: 50,
+      disabled: false,
+    },
+    {
+      type: "slot",
+      slotName: "size",
+      prop: "",
+      label: "",
+      itemWidth: 50,
+      disabled: false,
+    },
+    // {
+    //   type: "select",
+    //   prop: "innerPackMethod",
+    //   label: "内包装方式",
+    //   required: true,
+    //   itemWidth: 50,
+    //   multiple: true,
+    //   data: innerMethon.value,
+    //   filterable: true,
+    //   placeholder: "内包装方式",
+    //   style: {
+    //     width: "100%",
+    //   },
+    //   disabled: false,
+    // },
+    // {
+    //   type: "select",
+    //   prop: "outerPackMethod",
+    //   label: "外包装方式",
+    //   required: true,
+    //   itemWidth: 50,
+    //   multiple: true,
+    //   data: outsideMethon.value,
+    //   filterable: true,
+    //   placeholder: "外包装方式",
+    //   style: {
+    //     width: "100%",
+    //   },
+    //   disabled: false,
+    // },
+    {
+      type: "number",
+      prop: "netWeight",
+      label: "净重(kg)",
+      precision: 2,
+      min: 0,
+      controls: false,
+      itemWidth: 50,
+    },
+    // {
+    //   type: "input",
+    //   itemType: "textarea",
+    //   prop: "remark",
+    //   label: "备注",
+    //   itemWidth: 100,
+    // },
+    {
+      type: "title1",
+      title: "辅材",
+    },
+    {
+      type: "slot",
+      slotName: "materialDetail",
+    },
+    {
+      type: "title1",
+      title: "附加工艺要求",
+    },
+    {
+      type: "slot",
+      slotName: "technology",
+    },
+  ];
+});
+
+const getList = (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy
+    .post(
+      "/extQuotationProduct/waitCreateProductPage",
+      sourceList.value.pagination
+    )
+    .then(
+      (res) => {
+        sourceList.value.data = res.rows;
+        sourceList.value.pagination.total = res.total;
+        setTimeout(() => {
+          loading.value = false;
+        }, 200);
+      },
+      (err) => {
+        loading.value = false;
+      }
+    );
+};
+
+const getDict = () => {
+  proxy
+    .get("/tenantDept/list", {
+      pageNum: 1,
+      pageSize: 9999,
+      keyword: "",
+      tenantId: proxy.useUserStore().user.tenantId,
+      type: 0,
+    })
+    .then((res) => {
+      companyData.value = res.data.map((x) => ({
+        ...x,
+        label: x.deptName,
+        value: x.deptId,
+      }));
+      treeDataOne.value = proxy.handleTree(res.data, "deptId");
+    });
+};
+getDict();
+const getTreeList = () => {
+  proxy
+    .post("/productClassify/tree", { parentId: "", name: "", definition: "1" })
+    .then((message) => {
+      treeListData.value = [
+        {
+          id: "",
+          label: "全部",
+          parentId: "",
+          children: message,
+        },
+      ];
+      treeData.value = message;
+    });
+};
+getTreeList();
+const treeChange = (e) => {
+  if (e.id != undefined) {
+    sourceList.value.pagination.productClassifyId = e.id;
+    getList({ productClassifyId: e.id });
+  }
+};
+const productCustomInfoListData = ref([
+  {
+    type: 1,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 2,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 3,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+]);
+const openModal = () => {
+  dialogVisible.value = true;
+  modalType.value = "add";
+  formData.data = {
+    definition: "1",
+    fileList: [],
+    currency: "",
+    prodFileList: [],
+    isFold: 0,
+    isCustomized: 0,
+    packAsk: [],
+    productBomDetailList: [],
+    productCustomInfoList: productCustomInfoListData.value,
+  };
+  // if (currencyData.value && currencyData.value.length > 0) {
+  //   formData.data.currency = currencyData.value[0].dictKey;
+  // }
+};
+
+const openExcel = () => {
+  openExcelDialog.value = true;
+};
+
+const submitForm = () => {
+  formDom.value.handleSubmit((valid) => {
+    if (!formData.data.fileList.length > 0) {
+      return proxy.msgTip("请上传图片", 2);
+    }
+    // if(!formData.data.productBomDetailList.length>0){
+
+    // }
+    // formData.data.fileList = formData.data.fileList.map((x) => ({
+    //   id: x.id,
+    //   fileName: x.fileName,
+    //   fileUrl: x.fileUrl,
+    // }));
+    for (let i = 0; i < formData.data.productCustomInfoList.length; i++) {
+      const ele = formData.data.productCustomInfoList[i];
+      ele.isCheck = ele.isCheckBox ? 1 : 0;
+      if (ele.isCheckBox) {
+        if (!(ele.fileList && ele.fileList.length > 0)) {
+          return proxy.msgTip(`请上传${getLabel(ele.type)}附件`, 2);
+        }
+      }
+    }
+
+    if (formData.data.packAsk && formData.data.packAsk.length > 0) {
+      formData.data.packAsk = formData.data.packAsk.join(",");
+    }
+    submitLoading.value = true;
+    proxy.post("/extQuotationProduct/createProduct", formData.data).then(
+      (res) => {
+        proxy.msgTip("操作成功", 1);
+        dialogVisible.value = false;
+        submitLoading.value = false;
+        getList();
+      },
+      (err) => {
+        submitLoading.value = false;
+        if (formData.data.packAsk) {
+          formData.data.packAsk = formData.data.packAsk.split(",");
+        }
+      }
+    );
+  });
+};
+
+const getTechnologyData = () => {
+  proxy.post("/technology/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    technologyData.value = res.rows;
+  });
+};
+const getDtl = (row) => {
+  modalType.value = "add";
+  formData.data = {
+    definition: "1",
+    extQuotationProductId: row.id,
+    ...row,
+    companyId: "",
+    productClassifyId: "",
+    name: "",
+    customCode: row.productCode,
+    nameEnglish: "",
+    price: null,
+    imageUrl: "",
+    fileList: [],
+    hsCode: "",
+    prodFileList: [],
+    prodImgPath: "",
+    color: row.productColor,
+    length: row.productLength,
+    width: row.productWidth,
+    height: row.productHeight,
+    productBomDetailList:
+      row.quotationProductBomList.filter((x) => x.type == 2) || [],
+    productCustomInfoList: row.quotationProductCustomInfoList || [],
+  };
+  if (
+    formData.data.productCustomInfoList &&
+    formData.data.productCustomInfoList.length > 0
+  ) {
+    formData.data.productCustomInfoList.forEach((x) => {
+      x.isCheckBox = x.isCheck == 1;
+      if (!x.fileList) {
+        x.fileList = [];
+      } else {
+        x.fileList = x.fileList.map((x) => ({
+          ...x,
+          url: x.fileUrl,
+          name: x.fileName,
+        }));
+      }
+    });
+  }
+  if (formData.data.packAsk) {
+    formData.data.packAsk = formData.data.packAsk.split(",");
+  } else {
+    formData.data.packAsk = [];
+  }
+  delete formData.data.id;
+  // proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
+  //   formData.data = res;
+  //   formData.data.productBomDetailList =
+  //     formData.data.productBomDetailList.filter((x) => x.type == 2);
+
+  //   if (
+  //     formData.data.productCustomInfoList &&
+  //     formData.data.productCustomInfoList.length > 0
+  //   ) {
+  //     formData.data.productCustomInfoList.forEach((x) => {
+  //       x.isCheckBox = x.isCheck == 1;
+  //       if (!x.fileList) {
+  //         x.fileList = [];
+  //       } else {
+  //         x.fileList = x.fileList.map((x) => ({
+  //           ...x,
+  //           url: x.fileUrl,
+  //           name: x.fileName,
+  //         }));
+  //       }
+  //     });
+  //   }
+  //   // let list = [];
+  //   // for (let i = 0; i < productCustomInfoListData.value.length; i++) {
+  //   //   const iele = productCustomInfoListData.value[i];
+  //   //   let current = formData.data.productCustomInfoList.find(
+  //   //     (x) => x.type == iele.type
+  //   //   );
+  //   //   if (current) {
+  //   //     list.push({
+  //   //       ...iele,
+  //   //       ...current,
+  //   //       isCheckBox: current.isCheck == 1,
+  //   //       fileList: current.fileList.map((x) => ({
+  //   //         ...x,
+  //   //         url: x.fileUrl,
+  //   //         name: x.fileName,
+  //   //       })),
+  //   //     });
+  //   //   } else {
+  //   //     list.push(iele);
+  //   //   }
+  //   // }
+  //   // formData.data.productCustomInfoList = list;
+  //   if (formData.data.packAsk) {
+  //     formData.data.packAsk = formData.data.packAsk.split(",");
+  //   }
+  //   formData.data.fileList = row.fileList.map((x) => ({
+  //     ...x,
+  //     url: x.fileUrl,
+  //     name: x.fileName,
+  //   }));
+  //   if (formData.data.fileList.length > 0) {
+  //     formData.data.imageUrl = formData.data.fileList[0].fileUrl;
+  //   }
+
+  //   proxy
+  //     .post("/fileInfo/getList", { businessIdList: [row.id] })
+  //     .then((fileObj) => {
+  //       if (fileObj[row.id] && fileObj[row.id].length > 0) {
+  //         formData.data.prodFileList = fileObj[row.id]
+  //           .filter((x) => x.businessType == "2")
+  //           .map((item) => {
+  //             return {
+  //               ...item,
+  //               name: item.fileName,
+  //               url: item.fileUrl,
+  //             };
+  //           });
+  //       } else {
+  //         formData.data.prodFileList = [];
+  //       }
+  //     });
+
+  //   dialogVisible.value = true;
+  // });
+  dialogVisible.value = true;
+};
+const rawMaterialData = ref([]);
+const getRawMaterialData = () => {
+  proxy.post("/productInfo/page", { productClassifyId: 100 }).then((res) => {
+    rawMaterialData.value = res.rows.map((x) => ({
+      ...x,
+      label:
+        x.name +
+        "," +
+        x.customCode +
+        "," +
+        `${x["length"]}*${x.width}*${x.height}(cm)` +
+        "," +
+        x.color,
+      value: x.id,
+    }));
+  });
+};
+getRawMaterialData();
+
+const openSelectMaterial = ref(false);
+const openType = ref(-1);
+const clickOpenSelectMaterial = (type) => {
+  openType.value = type;
+  openSelectMaterial.value = true;
+};
+const selectMaterial = (row) => {
+  if (openType.value == 1) {
+    let flag = formData.data.productBomDetailList.some(
+      (x) => x.materialId == row.id
+    );
+    if (!flag) {
+      formData.data.productBomDetailList.push({
+        type: 2,
+        materialName: row.name,
+        materialCode: row.customCode,
+        materialId: row.id,
+        quantity: null,
+      });
+      proxy.msgTip("选择成功");
+    } else {
+      proxy.msgTip("该物料已选择", 2);
+    }
+  } else {
+    let flag = formData.bomData.productBomDetailList.some(
+      (x) => x.materialId == row.id
+    );
+    if (!flag) {
+      formData.bomData.productBomDetailList.push({
+        type: 2,
+        materialName: row.name,
+        materialCode: row.customCode,
+        materialId: row.id,
+        quantity: null,
+      });
+      proxy.msgTip("选择成功");
+    } else {
+      proxy.msgTip("该物料已选择", 2);
+    }
+  }
+};
+const handleRemove = (index, type) => {
+  if (type == 1) {
+    formData.data.productBomDetailList.splice(index, 1);
+  } else {
+    formData.bomData.productBomDetailList.splice(index, 1);
+  }
+};
+
+getTechnologyData();
+getList();
+
+const handleBeforeUploadOne = async (file, index) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  file.id = res.id;
+  file.fileUrl = res.fileUrl;
+  uploadData.value = res.uploadBody;
+  formData.data.productCustomInfoList[index].fileData = res;
+  return true;
+};
+
+const handleSuccessOne = (index) => {
+  if (
+    formData.data.productCustomInfoList[index].fileData &&
+    formData.data.productCustomInfoList[index].fileData.fileUrl
+  ) {
+    let file = formData.data.productCustomInfoList[index].fileData;
+    formData.data.productCustomInfoList[index].fileList.push({
+      id: file.id,
+      fileName: file.fileName,
+      name: file.fileName,
+      url: file.fileUrl,
+      fileUrl: file.fileUrl,
+    });
+    formData.data.productCustomInfoList[index].fileData = {};
+  }
+};
+
+const handleRemoveFile = (file, index) => {
+  let sonIndex = formData.data.productCustomInfoList[index].fileList.findIndex(
+    (x) => x.id == file.id || x.id == file.raw.id
+  );
+  if (sonIndex > -1) {
+    formData.data.productCustomInfoList[index].fileList.splice(sonIndex, 1);
+  }
+};
+
+const onPreviewFile = (file) => {
+  if (file && file.fileUrl) {
+    window.open(file.fileUrl, "_blank");
+  } else {
+    window.open(file.raw.fileUrl, "_blank");
+  }
+};
+let obj = {
+  1: "定制刀模",
+  2: "定制纹路",
+  3: "定制模具",
+};
+const getLabel = (type) => {
+  return obj[type];
+};
+
+const handleClickUpload = async (att, flag) => {
+  let res = null;
+  let path = "";
+  if (flag) {
+    proxy.msgTip("请稍后", 2);
+    res = await proxy.post("/fileService/createTempFolder");
+    if (res && res.path) {
+      formData.data[att] = res.path;
+      path = res.path;
+    }
+  } else {
+    path = formData.data[att];
+  }
+  let a = document.createElement("a");
+  a.href = "printer://" + "ftp://121.37.194.75/" + path + "/";
+  a.style.display = "none";
+  document.body.appendChild(a);
+  a.click();
+  document.body.removeChild(a);
+};
+</script>
+
+<style lang="scss" scoped>
+.box {
+  padding: 10px;
+  display: flex;
+  justify-content: space-between;
+  .tree {
+    width: 300px;
+  }
+  .content {
+    width: calc(100% - 310px);
+  }
+}
+.pic {
+  object-fit: contain;
+  width: 50px;
+  height: 50px;
+  cursor: pointer;
+  vertical-align: middle;
+}
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+
+  td {
+    text-align: center;
+    padding: 2px 4px;
+    // padding: 5px 10px;
+  }
+}
+.small-title {
+  padding-left: 15px;
+  margin-bottom: 10px;
+  color: #3366ff;
+  font-size: 14px;
+}
+:deep(.el-checkbox) {
+  margin-right: 0px;
+}
+</style>

+ 629 - 91
src/views/EHSD/saleContract/priceSheetEHSD/index.vue

@@ -106,7 +106,7 @@
                 <el-option v-for="item in customerList" :key="item.value" :label="item.label" :value="item.value" />
               </el-select>
             </el-form-item>
-            <el-row style="width: 100%">
+            <!-- <el-row style="width: 100%">
               <el-col :span="12">
                 <el-form-item label="地址" class="wid100 margin-b-0">
                   <el-row style="padding-right:5px;width:100%">
@@ -146,15 +146,17 @@
                   </el-input>
                 </el-form-item>
               </el-col>
-            </el-row>
+            </el-row> -->
           </div>
         </template>
 
         <template #commodity>
           <div style="width: 100%;padding-left:25px">
+            <el-button type="warning" @click="clickPushProduct" plain style="margin-bottom: 16px" v-if="!isDetail"
+                       :disabled="!formData.data.companyId">定制</el-button>
             <el-button type="primary" @click="openProductCompany = true" plain style="margin-bottom: 16px" v-if="!isDetail"
-                       :disabled="!formData.data.companyId">产品库</el-button>
-            <el-table :data="formData.data.quotationProductList" style="width: 100%;" default-expand-all>
+                       :disabled="!formData.data.companyId">选择产品库</el-button>
+            <!-- <el-table :data="formData.data.quotationProductList" style="width: 100%;" default-expand-all>
               <el-table-column type="expand" width="50" align="center">
                 <template #default="scope">
                   <div style="padding-left:50px">
@@ -179,35 +181,6 @@
                           </div>
                         </template>
                       </el-table-column>
-                      <!-- <el-table-column label="数量" width="110">
-                        <template #default="{ row, $index }">
-                          <div style="width: 100%">
-                            <el-form-item :prop="'quotationProductList.' + scope.$index + '.quotationProductBomList.' + $index + '.quantity'"
-                                          :rules="rules.quantity" :inline-message="true" class="margin-b-0 wid100">
-                              <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="请输入" style="width: 100%"
-                                               :precision="0" :controls="false" :min="1" v-if="row.type==2" @change="changeQuantity()" />
-                              <span v-else>{{row.quantity}}</span>
-                            </el-form-item>
-                          </div>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="allQuantity" label="总量" width="80" />
-                      <el-table-column label="单价" width="110">
-                        <template #default="{ row, $index }">
-                          <div style="width: 100%">
-                            <span v-if="row.price">¥ {{row.price}}</span>
-                            <span v-else>待报价</span>
-                          </div>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="amount" label="小计" width="110">
-                        <template #default="{ row, $index }">
-                          <div style="width: 100%">
-                            <span v-if="row.amount">¥ {{row.amount}}</span>
-                            <span v-else>一</span>
-                          </div>
-                        </template>
-                      </el-table-column> -->
                       <el-table-column label="备注" width="180">
                         <template #default="{ row, $index }">
                           <div style="width: 100%">
@@ -280,7 +253,255 @@
                   <el-button type="primary" link @click="handleRemove($index)">删除</el-button>
                 </template>
               </el-table-column>
-            </el-table>
+            </el-table> -->
+
+            <el-collapse v-model="activeNames">
+              <el-collapse-item :name="index" v-for="(product,index) in formData.data.quotationProductList" :key="index">
+                <template #title>
+                  <!-- <TitleInfo :content="'主材'"></TitleInfo> -->
+                  <div style="font-size:14px;font-weight:700;padding-left:25px;width:300px">
+                    产品编码:{{product.productCode}}
+                  </div>
+                  <el-form-item label="数量" class="margin-b-0" style="width:300px !important;" :prop="'quotationProductList.' +index + '.quantity'"
+                                :rules="rules.quantity" :inline-message="true" @click.stop>
+                    <el-input-number v-model="product.quantity" placeholder="请输入" style="width: 100%" :precision="0" :controls="false" :min="1"
+                                     onmousewheel="return false;" />
+                  </el-form-item>
+                </template>
+                <div style="width:100%">
+                  <div style="margin:10px 0">
+                    <TitleInfo :content="'主材'"></TitleInfo>
+                  </div>
+                  <div style="width: 100%;padding-left:15px">
+                    <el-row>
+                      <el-col :span="12">
+                        <el-form-item :prop="'quotationProductList.' +index + '.rawMaterialId'" :rules="rules.rawMaterialId" :inline-message="true"
+                                      label="原材料" class="wid100">
+                          <el-select v-model="product.rawMaterialId" placeholder="请选择" style="width:100%">
+                            <el-option v-for="item in rawMaterialData" :key="item.value" :label="item.label" :value="item.value" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="12">
+                        <el-form-item label="颜色" class="margin-b-0 wid100">
+                          <el-row style="width: 100%">
+                            <el-col :span="12">
+                              <el-form-item prop="productColor" label-width="0px" class="margin-b-0 wid100">
+                                <el-input v-model="product.productColor" placeholder="颜色" />
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                              <el-form-item prop="colorCardCode" label-width="0px" class="margin-b-0 wid100">
+                                <el-input v-model="product.colorCardCode" placeholder="色卡号" />
+                              </el-form-item>
+                            </el-col>
+                          </el-row>
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <el-row>
+                      <el-col :span="12">
+                        <el-form-item label="尺寸" class="margin-b-0 wid100" required>
+                          <el-row style="width:100%">
+                            <el-col :span="8">
+                              <el-form-item :prop="'quotationProductList.' +index + '.productLength'" :rules="rules.productLength"
+                                            :inline-message="true" label-width="0px" class="margin-b-0 wid100">
+                                <el-input-number v-model="product.productLength" placeholder="长 (cm)" style="width: 100%" :precision="2"
+                                                 :controls="false" :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="8">
+                              <el-form-item :prop="'quotationProductList.' +index + '.productWidth'" :rules="rules.productWidth"
+                                            :inline-message="true" label-width="0px" class="margin-b-0 wid100">
+                                <el-input-number v-model="product.productWidth" placeholder="宽 (cm)" style="width: 100%" :precision="2"
+                                                 :controls="false" :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="8">
+                              <el-form-item :prop="'quotationProductList.' +index + '.productHeight'" :rules="rules.productHeight"
+                                            :inline-message="true" label-width="0px" class="margin-b-0 wid100">
+                                <el-input-number v-model="product.productHeight" placeholder="高 (cm)" style="width: 100%" :precision="2"
+                                                 :controls="false" :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                          </el-row>
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="12">
+                        <el-form-item label="净重(kg)" prop="netWeight" class="margin-b-0 wid100">
+                          <el-input-number v-model="product.netWeight" placeholder="请输入" style="width: 100%" :precision="2" :controls="false" :min="0"
+                                           onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+
+                    </el-row>
+                  </div>
+
+                  <div style="margin:10px 0">
+                    <TitleInfo :content="'辅材'"></TitleInfo>
+                  </div>
+                  <div style="width: 100%;padding-left:15px">
+                    <el-button type="primary" @click="handleClickSelectMaterial(index)" plain>选择包材/配件/辅材</el-button>
+                    <el-table :data="product.quotationProductBomList" style="width: 100%; margin-top: 16px">
+                      <el-table-column prop="materialName" label="物料名称" min-width="130" />
+                      <el-table-column prop="materialCode" label="物料编码" width="150" />
+                      <el-table-column label="数量" width="150">
+                        <template #default="{ row, $index }">
+                          <div style="width: 100%">
+                            <el-form-item :prop="'quotationProductList.' + index + '.quotationProductBomList.' + $index + '.quantity'"
+                                          :rules="rules.quantity" :inline-message="true" class="margin-b-0 wid100">
+                              <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="请输入" style="width: 100%"
+                                               :precision="0" :controls="false" :min="1" />
+                            </el-form-item>
+                          </div>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="操作" width="60" align="center" fixed="right">
+                        <template #default="{ $index }">
+                          <el-button type="primary" link @click="handleRemoveBom(index,$index)">删除</el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table>
+                  </div>
+
+                  <div style="margin:10px 0">
+                    <TitleInfo :content="'附加工艺要求'"></TitleInfo>
+                  </div>
+
+                  <div style="width:100%;padding-left:15px">
+                    <div class="small-title">
+                      ① 工艺线路
+                    </div>
+                    <el-row style="width:100%">
+                      <el-col :span="12">
+                        <el-form-item label="工艺产线" class="wid100" :prop="'quotationProductList.' + index + '.technologyId'"
+                                      :rules="rules.technologyId" :inline-message="true">
+                          <el-select v-model="product.technologyId" placeholder="请选择" style="width:100%">
+                            <el-option v-for="item in technologyData" :key="item.id" :label="item.name" :value="item.id" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <div class="small-title">
+                      ② LOGO
+                    </div>
+                    <el-row style="width:100%">
+                      <el-col :span="12">
+                        <el-form-item label="LOGO尺寸" class="wid100">
+                          <el-row>
+                            <el-col :span="8">
+                              <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoLength'"
+                                            :rules="rules.logoLength" :inline-message="true">
+                                <el-input-number v-model="product.logoLength" placeholder="长 (cm)" style="width: 100%" :precision="2"
+                                                 :controls="false" :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="8">
+                              <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoWidth'"
+                                            :rules="rules.logoWidth" :inline-message="true">
+                                <el-input-number v-model="product.logoWidth" placeholder="宽 (cm)" style="width: 100%" :precision="2" :controls="false"
+                                                 :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                            <el-col :span="8">
+                              <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoHeight'"
+                                            :rules="rules.logoHeight" :inline-message="true">
+                                <el-input-number v-model="product.logoHeight" placeholder="高 (cm)" style="width: 100%" :precision="2"
+                                                 :controls="false" :min="0" onmousewheel="return false;" />
+                              </el-form-item>
+                            </el-col>
+                          </el-row>
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="12">
+                        <el-form-item label="几色印刷" class="wid100">
+                          <el-input-number v-model="product.colorCount" placeholder="请输入" style="width: 100%" :precision="0" :controls="false"
+                                           :min="1" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <div class="small-title">
+                      ③ 折叠
+                    </div>
+                    <el-row style="width:100%">
+                      <el-col :span="12">
+                        <el-form-item label="是否折叠" class="wid100">
+                          <el-select v-model="product.isFold" placeholder="请选择" style="width:100%">
+                            <el-option :label="'否'" :value="0" />
+                            <el-option :label="'是'" :value="1" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="12">
+                        <el-form-item label="折叠数" class="wid100" v-if="product.isFold==1">
+                          <el-select v-model="product.foldWay" placeholder="请选择" style="width:100%">
+                            <el-option v-for="item in foldWayData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <div class="small-title">
+                      ④ 包装要求
+                    </div>
+                    <el-row style="width:100%">
+                      <el-col :span="12">
+                        <el-form-item label="包装要求" class="wid100">
+                          <el-select v-model="product.packAsk" placeholder="请选择" style="width:100%" multiple>
+                            <el-option v-for="item in packAskData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <div class="small-title">
+                      ⑤ 是否定制
+                    </div>
+                    <el-row style="width:100%">
+                      <el-col :span="12">
+                        <el-form-item prop="isCustomized" label="是否定制" class="wid100">
+                          <el-select v-model="product.isCustomized" placeholder="请选择" style="width:100%">
+                            <el-option :label="'否'" :value="0" />
+                            <el-option :label="'是'" :value="1" />
+                          </el-select>
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                    <el-row style="width:100%">
+                      <el-form-item label="定制内容" class="wid100" v-if="product.isCustomized==1">
+                        <table style="width:100%" border class="table">
+                          <tr>
+                            <td style="width:20%">
+                            </td>
+                            <td style="width:40%">附件</td>
+                            <td style="width:40%">备注</td>
+                          </tr>
+                          <tr v-for="(row,sonIndex) in product.quotationProductCustomInfoList" :key="sonIndex">
+                            <td>
+                              <el-checkbox v-model="row.isCheckBox" label="" /> <span style="position:relative;top:-2px">
+                                {{getLabelOne(row.type)}}</span>
+                            </td>
+                            <td>
+                              <el-upload :file-list="row.fileList" :action="uploadUrl" :data="uploadData" :limit="1" :list-type="'text'"
+                                         :before-upload="(file)=>handleBeforeUploadOne(file,index,sonIndex)"
+                                         :on-success="()=>handleSuccessOne(index,sonIndex)" :on-remove="(file)=>handleRemoveFile(file,index,sonIndex)"
+                                         :on-preview="onPreviewFile" :on-exceed="()=>msgTip(`上传文件数量不可大于1`, 2)">
+                                <el-button text type="primary">上传附件</el-button>
+                              </el-upload>
+                            </td>
+                            <td>
+                              <el-form-item :prop="'quotationProductList.' + index + '.quotationProductCustomInfoList.' + sonIndex + '.remark'"
+                                            :rules="row.isCheckBox?rules.remark:''" :inline-message="true" class="margin-b-0 wid100">
+                                <el-input v-model="row.remark" placeholder="请输入备注" />
+                              </el-form-item>
+                            </td>
+                          </tr>
+                        </table>
+                      </el-form-item>
+                    </el-row>
+                  </div>
+                </div>
+              </el-collapse-item>
+
+            </el-collapse>
           </div>
         </template>
       </byForm>
@@ -598,6 +819,9 @@ import * as echarts from "echarts";
 import PriceSheetDetailList from "@/views/EHSD/saleContract/PriceSheetDetailList";
 
 const { proxy } = getCurrentInstance();
+const uploadData = ref({});
+const packAskData = computed(() => proxy.useUserStore().allDict["pack_ask"]);
+const foldWayData = computed(() => proxy.useUserStore().allDict["fold_way"]);
 const companyId = ref("");
 const accountList = ref([]);
 const corporationList = ref([]);
@@ -750,7 +974,7 @@ const config = computed(() => {
       attrs: {
         label: "客户名称",
         prop: "buyCorporationName",
-        "min-width": 150,
+        "min-width": 170,
       },
     },
     {
@@ -851,6 +1075,28 @@ const getList = async (req) => {
 };
 getDict();
 getList();
+const rawMaterialData = ref([]);
+const technologyData = ref([]);
+const getRawMaterialData = () => {
+  proxy.post("/productInfo/page", { productClassifyId: 100 }).then((res) => {
+    rawMaterialData.value = res.rows.map((x) => ({
+      ...x,
+      label:
+        x.name +
+        "," +
+        x.customCode +
+        "," +
+        `${x["length"]}*${x.width}*${x.height}(cm)` +
+        "," +
+        x.color,
+      value: x.id,
+    }));
+  });
+  proxy.post("/technology/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    technologyData.value = res.rows;
+  });
+};
+getRawMaterialData();
 const openAddDialog = ref(false);
 const submitLoading = ref(false);
 const modalType = ref("add");
@@ -1106,20 +1352,20 @@ const formConfig = computed(() => {
       label: "",
       itemWidth: 100,
     },
-    {
-      type: "input",
-      itemType: "text",
-      label: "联系人",
-      prop: "buyContactName",
-      itemWidth: 50,
-    },
-    {
-      type: "input",
-      itemType: "text",
-      label: "联系人电话",
-      prop: "buyContactNumber",
-      itemWidth: 50,
-    },
+    // {
+    //   type: "input",
+    //   itemType: "text",
+    //   label: "联系人",
+    //   prop: "buyContactName",
+    //   itemWidth: 50,
+    // },
+    // {
+    //   type: "input",
+    //   itemType: "text",
+    //   label: "联系人电话",
+    //   prop: "buyContactNumber",
+    //   itemWidth: 50,
+    // },
     {
       type: "title1",
       title: "商品信息",
@@ -1143,7 +1389,7 @@ const formConfig = computed(() => {
   ];
 });
 const rules = ref({
-  type: [{ required: true, message: "请选择报价类型", trigger: "change" }],
+  // type: [{ required: true, message: "请选择报价类型", trigger: "change" }],
   ofCompanyId: [
     { required: true, message: "请选择业务公司", trigger: "change" },
   ],
@@ -1152,6 +1398,22 @@ const rules = ref({
     { required: true, message: "请选择客户公司", trigger: "change" },
   ],
   quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+  productLength: [
+    { required: true, message: "请输入长 (cm)", trigger: "blur" },
+  ],
+  productWidth: [
+    { required: true, message: "请输入宽 (cm)", trigger: "blur" },
+  ],
+  productHeight: [
+    { required: true, message: "请输入高 (cm)", trigger: "blur" },
+  ],
+  rawMaterialId: [
+    { required: true, message: "请选择原材料", trigger: "change" },
+  ],
+  technologyId: [
+    { required: true, message: "请选择工艺产线", trigger: "change" },
+  ],
+  remark: [{ required: true, message: "请输入备注", trigger: "blur" }],
 });
 
 const getCityData = (id, type, isChange = false) => {
@@ -1240,31 +1502,58 @@ const handlePerson = (item) => {
   }
 };
 const quotationProductBomList = ref([]);
-const selectProduct = (goods) => {
-  if (goods && goods.id) {
-    let fileUrl = "";
-    if (goods.fileList && goods.fileList.length > 0) {
-      fileUrl = goods.fileList[0].fileUrl;
-    }
-    proxy.post("/productBomInfo/detail", { id: goods.id }).then((res) => {
-      if (res.productBomDetailList && res.productBomDetailList.length > 0) {
-        quotationProductBomList.value = res.productBomDetailList.map((x) => ({
-          fileUrl: "",
-          materialId: x.materialId,
-          productName: x.materialName,
-          productCode: x.materialCode,
-          productLength: x["materialLength"],
-          productWidth: x.materialWidth,
-          productHeight: x.materialHeight,
-          quantity: x.quantity || null,
-          allQuantity: "",
-          price: null,
-          amount: "",
-          fileList: [],
-          type: x.type,
-        }));
+const productCustomInfoListData = ref([
+  {
+    type: 1,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 2,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+  {
+    type: 3,
+    isCheck: 0,
+    isCheckBox: false,
+    fileList: [],
+    remark: "",
+  },
+]);
+const selectProduct = (row) => {
+  if (row && row.id) {
+    proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
+      let goods = res;
+      if (goods.productBomDetailList && goods.productBomDetailList.length > 0) {
+        let quotationProductCustomInfoList = goods.productCustomInfoList.map(
+          (x) => {
+            if (x.fileList) {
+              x.fileList = x.fileList.map((y) => ({
+                ...y,
+                url: y.fileUrl,
+                name: y.fileName,
+              }));
+            } else {
+              x.fileList = [];
+            }
+            x.isCheckBox = x.isCheck == 1;
+            delete x.id;
+            return x;
+          }
+        );
+        if (goods.isCustomized == 0) {
+          quotationProductCustomInfoList = productCustomInfoListData.value;
+        }
+        let packAsk = goods.packAsk;
+        if (packAsk) {
+          packAsk = packAsk.split(",");
+        }
         formData.data.quotationProductList.push({
-          fileUrl: fileUrl,
           productId: goods.id,
           productName: goods.name,
           productCode: goods.customCode,
@@ -1272,21 +1561,26 @@ const selectProduct = (goods) => {
           productWidth: goods.width,
           productHeight: goods.height,
           productColor: goods.color,
+          colorCardCode: goods.colorCardCode,
+          netWeight: goods.netWeight,
           quantity: null,
           price: null,
           amount: "",
           fileList: [],
-          quotationProductBomList: quotationProductBomList.value,
+          rawMaterialId: goods.rawMaterialId,
+          technologyId: goods.technologyId,
+          logoLength: goods.logoLength,
+          logoWidth: goods.logoWidth,
+          logoHeight: goods.logoHeight,
+          colorCount: goods.colorCount,
+          isFold: goods.isFold || 0,
+          foldWay: goods.foldWay,
+          packAsk: packAsk,
+          isCustomized: goods.isCustomized || 0,
+          quotationProductBomList: goods.productBomDetailList,
+          quotationProductCustomInfoList: quotationProductCustomInfoList,
         });
         proxy.msgTip("添加成功", 1);
-        let ids = quotationProductBomList.value.map((x) => x.materialId);
-        proxy.getFile(
-          ids,
-          quotationProductBomList.value,
-          "materialId",
-          "fileList",
-          "fileUrl"
-        );
       } else {
         return proxy.msgTip("该产品未配置BOM", 2);
       }
@@ -1295,12 +1589,105 @@ const selectProduct = (goods) => {
     return proxy.msgTip("选择错误", 2);
   }
 };
+const clickPushProduct = () => {
+  let quotationProductCustomInfoList = productCustomInfoListData.value;
+  formData.data.quotationProductList.push({
+    productId: "",
+    productName: "",
+    productCode: "",
+    productLength: null,
+    productWidth: null,
+    productHeight: null,
+    productColor: "",
+    colorCardCode: "",
+    netWeight: null,
+    quantity: null,
+    price: null,
+    amount: "",
+    fileList: [],
+    rawMaterialId: "",
+    technologyId: "",
+    logoLength: null,
+    logoWidth: null,
+    logoHeight: null,
+    colorCount: null,
+    isFold: 0,
+    foldWay: "",
+    packAsk: [],
+    isCustomized: 0,
+    quotationProductBomList: [],
+    quotationProductCustomInfoList: quotationProductCustomInfoList,
+  });
+  proxy.msgTip("添加成功", 1);
+};
+// const selectProduct = (goods) => {
+//   if (goods && goods.id) {
+//     let fileUrl = "";
+//     if (goods.fileList && goods.fileList.length > 0) {
+//       fileUrl = goods.fileList[0].fileUrl;
+//     }
+//     proxy.post("/productBomInfo/detail", { id: goods.id }).then((res) => {
+//       if (res.productBomDetailList && res.productBomDetailList.length > 0) {
+//         quotationProductBomList.value = res.productBomDetailList.map((x) => ({
+//           fileUrl: "",
+//           materialId: x.materialId,
+//           productName: x.materialName,
+//           productCode: x.materialCode,
+//           productLength: x["materialLength"],
+//           productWidth: x.materialWidth,
+//           productHeight: x.materialHeight,
+//           quantity: x.quantity || null,
+//           allQuantity: "",
+//           price: null,
+//           amount: "",
+//           fileList: [],
+//           type: x.type,
+//         }));
+//         formData.data.quotationProductList.push({
+//           fileUrl: fileUrl,
+//           productId: goods.id,
+//           productName: goods.name,
+//           productCode: goods.customCode,
+//           productLength: goods["length"],
+//           productWidth: goods.width,
+//           productHeight: goods.height,
+//           productColor: goods.color,
+//           quantity: null,
+//           price: null,
+//           amount: "",
+//           fileList: [],
+//           quotationProductBomList: quotationProductBomList.value,
+//         });
+//         proxy.msgTip("添加成功", 1);
+//         let ids = quotationProductBomList.value.map((x) => x.materialId);
+//         proxy.getFile(
+//           ids,
+//           quotationProductBomList.value,
+//           "materialId",
+//           "fileList",
+//           "fileUrl"
+//         );
+//       } else {
+//         return proxy.msgTip("该产品未配置BOM", 2);
+//       }
+//     });
+//   } else {
+//     return proxy.msgTip("选择错误", 2);
+//   }
+// };
 
 const handleClickSelectMaterial = (index) => {
   indexValue.value = index;
   openSelectMaterial.value = true;
 };
 
+const handleRemoveBom = (index, sonIndex) => {
+  formData.data.quotationProductList[index].quotationProductBomList.splice(
+    sonIndex,
+    1
+  );
+};
+
 const selectMaterial = (goods) => {
   let flag = formData.data.quotationProductList[
     indexValue.value
@@ -1315,11 +1702,11 @@ const selectMaterial = (goods) => {
     ].quotationProductBomList.push({
       fileUrl: fileUrl,
       materialId: goods.id,
-      productName: goods.name,
-      productCode: goods.customCode,
-      productLength: goods["length"],
-      productWidth: goods.width,
-      productHeight: goods.height,
+      materialName: goods.name,
+      materialCode: goods.customCode,
+      // productLength: goods["length"],
+      // productWidth: goods.width,
+      // productHeight: goods.height,
       quantity: null,
       price: null,
       amount: "",
@@ -1332,6 +1719,37 @@ const selectMaterial = (goods) => {
   }
 };
 
+// const selectMaterial = (goods) => {
+//   let flag = formData.data.quotationProductList[
+//     indexValue.value
+//   ].quotationProductBomList.some((x) => x.materialId == goods.id);
+//   if (!flag) {
+//     let fileUrl = "";
+//     if (goods.fileList && goods.fileList.length > 0) {
+//       fileUrl = goods.fileList[0].fileUrl;
+//     }
+//     formData.data.quotationProductList[
+//       indexValue.value
+//     ].quotationProductBomList.push({
+//       fileUrl: fileUrl,
+//       materialId: goods.id,
+//       productName: goods.name,
+//       productCode: goods.customCode,
+//       productLength: goods["length"],
+//       productWidth: goods.width,
+//       productHeight: goods.height,
+//       quantity: null,
+//       price: null,
+//       amount: "",
+//       fileList: [],
+//       type: 2,
+//     });
+//     proxy.msgTip("选择成功");
+//   } else {
+//     proxy.msgTip("该物料已选择", 2);
+//   }
+// };
+
 const onPicture = (path) => {
   window.open(path, "_blank");
 };
@@ -1413,10 +1831,46 @@ const handleSubmit = (type) => {
       formData.data.quotationProductList &&
       formData.data.quotationProductList.length > 0
     ) {
+      let data = proxy.deepClone(formData.data);
+      for (let i = 0; i < data.quotationProductList.length; i++) {
+        const iele = data.quotationProductList[i];
+        if (
+          !(
+            iele.quotationProductBomList &&
+            iele.quotationProductBomList.length > 0
+          )
+        ) {
+          return proxy.msgTip("请添加辅材", 2);
+        }
+        iele.quotationProductBomList.push({
+          materialId: iele.rawMaterialId,
+          type: 1,
+        });
+        if (iele.packAsk) {
+          iele.packAsk = iele.packAsk.join(",");
+        }
+        if (
+          iele.quotationProductCustomInfoList &&
+          iele.quotationProductCustomInfoList.length > 0
+        ) {
+          for (let j = 0; j < iele.quotationProductCustomInfoList.length; j++) {
+            let jele = iele.quotationProductCustomInfoList[j];
+            jele.isCheck = jele.isCheckBox ? 1 : 0;
+            if (jele.isCheckBox) {
+              if (!(jele.fileList && jele.fileList.length > 0)) {
+                return proxy.msgTip(
+                  `请上传第${i + 1}条数据的${getLabel(jele.type)}附件`,
+                  2
+                );
+              }
+            }
+          }
+        }
+      }
       submitLoading.value = true;
-      formData.data.status = type;
+      data.status = type;
       if (isChange.value) {
-        proxy.post("/saleQuotation/change", formData.data).then(
+        proxy.post("/saleQuotation/change", data).then(
           (res) => {
             proxy.msgTip("操作成功", 1);
             openAddDialog.value = false;
@@ -1429,7 +1883,7 @@ const handleSubmit = (type) => {
           }
         );
       } else {
-        proxy.post("/saleQuotation/" + modalType.value, formData.data).then(
+        proxy.post("/saleQuotation/" + modalType.value, data).then(
           (res) => {
             proxy.msgTip("操作成功", 1);
             openAddDialog.value = false;
@@ -1998,6 +2452,70 @@ const changeForeignQuantity = () => {
     formData.data.amount = parseFloat(money).toFixed(2);
   }
 };
+
+const activeNames = ref([]);
+
+let obj = {
+  1: "定制刀模",
+  2: "定制纹路",
+  3: "定制模具",
+};
+const getLabelOne = (type) => {
+  return obj[type];
+};
+
+const handleBeforeUploadOne = async (file, index, sonIndex) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  file.id = res.id;
+  file.fileUrl = res.fileUrl;
+  uploadData.value = res.uploadBody;
+  formData.data.quotationProductList[index].quotationProductCustomInfoList[
+    sonIndex
+  ].fileData = res;
+  return true;
+};
+
+const handleSuccessOne = (index, sonIndex) => {
+  if (
+    formData.data.quotationProductList[index].quotationProductCustomInfoList[
+      sonIndex
+    ].fileData &&
+    formData.data.quotationProductList[index].quotationProductCustomInfoList[
+      sonIndex
+    ].fileData.fileUrl
+  ) {
+    let file =
+      formData.data.quotationProductList[index].quotationProductCustomInfoList[
+        sonIndex
+      ].fileData;
+    formData.data.quotationProductList[index].quotationProductCustomInfoList[
+      sonIndex
+    ].fileList.push({
+      id: file.id,
+      fileName: file.fileName,
+      name: file.fileName,
+      url: file.fileUrl,
+      fileUrl: file.fileUrl,
+    });
+    formData.data.quotationProductList[index].quotationProductCustomInfoList[
+      sonIndex
+    ].fileData = {};
+  }
+};
+
+const handleRemoveFile = (file, index, sonIndex) => {
+  formData.data.quotationProductList[index].quotationProductCustomInfoList[
+    sonIndex
+  ].fileList.splice(sonIndex, 1);
+};
+
+const onPreviewFile = (file) => {
+  if (file && file.fileUrl) {
+    window.open(file.fileUrl, "_blank");
+  } else {
+    window.open(file.raw.fileUrl, "_blank");
+  }
+};
 </script>
 
 <style lang="scss" scoped>
@@ -2028,5 +2546,25 @@ const changeForeignQuantity = () => {
 :deep(.bom-table .el-table__body-wrapper .el-table__body .el-table__row) {
   background: #f4f4f5 !important;
 }
+
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+
+  td {
+    text-align: center;
+    padding: 2px 4px;
+    // padding: 5px 10px;
+  }
+}
+.small-title {
+  padding-left: 15px;
+  margin-bottom: 10px;
+  color: #3366ff;
+  font-size: 14px;
+}
+:deep(.el-checkbox) {
+  margin-right: 0px;
+}
 </style>
 

+ 407 - 29
src/views/EHSD/saleContract/priceSheetEstimate/index.vue

@@ -60,10 +60,11 @@
         <div class="left">
           <el-card style="width:100%;margin-bottom:15px" v-for="(item,index) in quotationProductList" :key="index">
             <div style="text-align:right">
+              <el-button plain type="primary" @click="handleLookDetail(item,index)">查看</el-button>
               <el-button plain type="primary" @click="handleReportPrice(item,index)">报价</el-button>
             </div>
             <el-table :data="[item]" style="width: 100%;">
-              <el-table-column type="expand" width="50" align="center">
+              <!-- <el-table-column type="expand" width="50" align="center">
                 <template #default="scope">
                   <div>
                     <div style="margin-bottom:10px;">
@@ -87,33 +88,12 @@
                           </div>
                         </template>
                       </el-table-column>
-                      <!-- <el-table-column prop="quantity" label="数量" width="80">
-                      </el-table-column>
-                      <el-table-column prop="allQuantity" label="总量" width="80" />
-                      <el-table-column label="单价" width="110">
-                        <template #default="{ row, $index }">
-                          <div style="width: 100%">
-                            <el-form-item :prop="'quotationProductList.' + scope.$index + '.quotationProductBomList.' + $index + '.price'"
-                                          :rules="rules.price" :inline-message="true" class="margin-b-0 wid100">
-                              <el-input-number onmousewheel="return false;" v-model="row.price" placeholder="请输入" style="width: 100%" :precision="2"
-                                               :controls="false" :min="0" @change="totalAmount()" />
-                            </el-form-item>
-                          </div>
-                        </template>
-                      </el-table-column>
-                      <el-table-column prop="amount" label="小计" width="110">
-                        <template #default="{ row, $index }">
-                          <div style="width: 100%">
-                            ¥ {{row.amount}}
-                          </div>
-                        </template>
-                      </el-table-column> -->
                       <el-table-column label="备注" width="180" prop="remark">
                       </el-table-column>
                     </el-table>
                   </div>
                 </template>
-              </el-table-column>
+              </el-table-column> -->
               <el-table-column label="图片" width="80">
                 <template #default="{ row }">
                   <div v-if="row.fileUrl">
@@ -169,12 +149,15 @@
                       <th style="width:10%">
                         类型
                       </th>
-                      <th style="width:18%">
+                      <th style="width:15%">
                         编码
                       </th>
-                      <th style="width:20%">
+                      <th style="width:15%">
                         名称
                       </th>
+                      <th style="width:8%" class="align-right">
+                        一出几
+                      </th>
                       <th style="width:16%" class="align-right">
                         模具
                       </th>
@@ -199,9 +182,17 @@
                         <td>{{row.code}}</td>
                         <td>{{row.name}}</td>
                         <td class="align-right">
+                          <el-form-item label-width="0px" class="margin-b-0" :prop="'quotationEstimateList.' + index + '.cavityNum'"
+                                        :rules="rules.cavityNum" :inline-message="true">
+                            <el-input-number onmousewheel="return false;" v-model="row.cavityNum" placeholder="一出几" style="width: 100%" :precision="0"
+                                             :controls="false" :min="1" @change="(val)=>changeCavityNum(val,index)" />
+                          </el-form-item>
+                        </td>
+                        <td class="align-right">
                           <el-form-item label-width="0px" class="margin-b-0" :prop="'quotationEstimateList.' + index + '.moldId'"
                                         :rules="rules.moldId" :inline-message="true">
-                            <el-select v-model="row.moldId" filterable placeholder="请选择模具" style="width: 100%" @change="changeTotalAmount()">
+                            <el-select v-model="row.moldId" filterable placeholder="请选择模具" style="width: 100%"
+                                       @change="(val)=>changeMoldId(val,index)">
                               <el-option v-for="item in moldData" :key="item.id" :label="item.moldName" :value="item.id" />
                             </el-select>
                           </el-form-item>
@@ -241,6 +232,9 @@
                           -
                         </td>
                         <td class="align-right">
+                          -
+                        </td>
+                        <td class="align-right">
                           <el-form-item label-width="0px" class="margin-b-0" :prop="'quotationEstimateList.' + index + '.quantity'"
                                         :rules="rules.quantity" :inline-message="true">
                             <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="数量" style="width: 100%" :precision="0"
@@ -278,6 +272,9 @@
                           -
                         </td>
                         <td class="align-right">
+                          -
+                        </td>
+                        <td class="align-right">
                           {{row.quantity}}
                         </td>
                         <td class="align-right">
@@ -297,7 +294,7 @@
                     </template>
 
                     <tr>
-                      <td colspan="7">
+                      <td colspan="8">
                         合计
                       </td>
                       <td class="align-right">
@@ -425,6 +422,246 @@
       </template> -->
     </el-dialog>
 
+    <el-dialog v-if="detailDialog" v-model="detailDialog" :title="formData.detailsData.productCode+`(${formData.detailsData.productName})产品详情`"
+               width="60%" append-to-body>
+      <byForm :formConfig="detailsFormConfig" :formOption="detailsFormOption" v-model="formData.detailsData">
+        <template #detail>
+          <div style="width:100%">
+            <div style="margin:10px 0">
+              <TitleInfo :content="'主材'"></TitleInfo>
+            </div>
+            <div style="width: 100%;padding-left:15px">
+              <el-row>
+                <el-col :span="12">
+                  <el-form-item label="原材料" class="wid100">
+                    <el-select v-model="formData.detailsData.rawMaterialId" placeholder=" " style="width:100%">
+                      <el-option v-for="item in rawMaterialData" :key="item.value" :label="item.label" :value="item.value" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="颜色" class="margin-b-0 wid100">
+                    <el-row style="width: 100%">
+                      <el-col :span="12">
+                        <el-form-item prop="productColor" label-width="0px" class="margin-b-0 wid100">
+                          <el-input v-model="formData.detailsData.productColor" placeholder="" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="12">
+                        <el-form-item prop="colorCardCode" label-width="0px" class="margin-b-0 wid100">
+                          <el-input v-model="formData.detailsData.colorCardCode" placeholder="" />
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-row>
+                <el-col :span="12">
+                  <el-form-item label="尺寸" class="margin-b-0 wid100" required>
+                    <el-row style="width:100%">
+                      <el-col :span="8">
+                        <el-form-item :prop="'quotationProductList.' +index + '.productLength'" :rules="rules.productLength" :inline-message="true"
+                                      label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.detailsData.productLength" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item :prop="'quotationProductList.' +index + '.productWidth'" :rules="rules.productWidth" :inline-message="true"
+                                      label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.detailsData.productWidth" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item :prop="'quotationProductList.' +index + '.productHeight'" :rules="rules.productHeight" :inline-message="true"
+                                      label-width="0px" class="margin-b-0 wid100">
+                          <el-input-number v-model="formData.detailsData.productHeight" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="净重(kg)" prop="netWeight" class="margin-b-0 wid100">
+                    <el-input-number v-model="formData.detailsData.netWeight" placeholder="" style="width: 100%" :precision="2" :controls="false"
+                                     :min="0" onmousewheel="return false;" />
+                  </el-form-item>
+                </el-col>
+
+              </el-row>
+            </div>
+
+            <div style="margin:10px 0">
+              <TitleInfo :content="'辅材'"></TitleInfo>
+            </div>
+            <div style="width: 100%;padding-left:15px">
+              <!-- <el-button type="primary" @click="handleClickSelectMaterial(index)" plain>选择包材/配件/辅材</el-button> -->
+              <el-table :data="formData.detailsData.quotationProductBomList" style="width: 100%;">
+                <el-table-column prop="productName" label="物料名称" min-width="130" />
+                <el-table-column prop="productCode" label="物料编码" width="150" />
+                <el-table-column label="数量" width="150">
+                  <template #default="{ row, $index }">
+                    <div style="width: 100%">
+                      <el-form-item :prop="'quotationProductList.' + index + '.quotationProductBomList.' + $index + '.quantity'"
+                                    :rules="rules.quantity" :inline-message="true" class="margin-b-0 wid100">
+                        <el-input-number onmousewheel="return false;" v-model="row.quantity" placeholder="" style="width: 100%" :precision="0"
+                                         :controls="false" :min="1" />
+                      </el-form-item>
+                    </div>
+                  </template>
+                </el-table-column>
+                <!-- <el-table-column label="操作" width="60" align="center" fixed="right">
+                  <template #default="{ $index }">
+                    <el-button type="primary" link @click="handleRemoveBom(index,$index)">删除</el-button>
+                  </template>
+                </el-table-column> -->
+              </el-table>
+            </div>
+
+            <div style="margin:10px 0">
+              <TitleInfo :content="'附加工艺要求'"></TitleInfo>
+            </div>
+
+            <div style="width:100%;padding-left:15px">
+              <div class="small-title">
+                ① 工艺线路
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item label="工艺产线" class="wid100" :prop="'quotationProductList.' +index + '.technologyId'" :rules="rules.technologyId"
+                                :inline-message="true">
+                    <el-select v-model="formData.detailsData.technologyId" placeholder="请选择" style="width:100%">
+                      <el-option v-for="item in technologyData" :key="item.id" :label="item.name" :value="item.id" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ② LOGO
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item label="LOGO尺寸" class="wid100">
+                    <el-row style="width:100%">
+                      <el-col :span="8">
+                        <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoLength'"
+                                      :rules="rules.logoLength" :inline-message="true">
+                          <el-input-number v-model="formData.detailsData.logoLength" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoWidth'"
+                                      :rules="rules.logoWidth" :inline-message="true">
+                          <el-input-number v-model="formData.detailsData.logoWidth" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                      <el-col :span="8">
+                        <el-form-item label-width="0px" class="margin-b-0 wid100" :prop="'quotationProductList.' +index + '.logoHeight'"
+                                      :rules="rules.logoHeight" :inline-message="true">
+                          <el-input-number v-model="formData.detailsData.logoHeight" placeholder="" style="width: 100%" :precision="2"
+                                           :controls="false" :min="0" onmousewheel="return false;" />
+                        </el-form-item>
+                      </el-col>
+                    </el-row>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="几色印刷" class="wid100">
+                    <el-input-number v-model="formData.detailsData.colorCount" placeholder="" style="width: 100%" :precision="0" :controls="false"
+                                     :min="1" onmousewheel="return false;" />
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ③ 折叠
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item label="是否折叠" class="wid100">
+                    <el-select v-model="formData.detailsData.isFold" placeholder="" style="width:100%">
+                      <el-option :label="'否'" :value="0" />
+                      <el-option :label="'是'" :value="1" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="折叠数" class="wid100" v-if="formData.detailsData.isFold==1">
+                    <el-select v-model="formData.detailsData.foldWay" placeholder="" style="width:100%">
+                      <el-option v-for="item in foldWayData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ④ 包装要求
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item label="包装要求" class="wid100">
+                    <el-select v-model="formData.detailsData.packAsk" placeholder="" style="width:100%" multiple>
+                      <el-option v-for="item in packAskData" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <div class="small-title">
+                ⑤ 是否定制
+              </div>
+              <el-row style="width:100%">
+                <el-col :span="12">
+                  <el-form-item prop="isCustomized" label="是否定制" class="wid100">
+                    <el-select v-model="formData.detailsData.isCustomized" placeholder="" style="width:100%">
+                      <el-option :label="'否'" :value="0" />
+                      <el-option :label="'是'" :value="1" />
+                    </el-select>
+                  </el-form-item>
+                </el-col>
+              </el-row>
+              <el-row style="width:100%">
+                <el-form-item prop="technologyId" label="定制内容" class="wid100" v-if="formData.detailsData.isCustomized==1">
+                  <table style="width:100%" border class="table">
+                    <tr>
+                      <td style="width:20%">
+                      </td>
+                      <td style="width:40%">附件</td>
+                      <td style="width:40%">备注</td>
+                    </tr>
+                    <tr v-for="(row,sonIndex) in formData.detailsData.quotationProductCustomInfoList" :key="sonIndex">
+                      <td>
+                        <el-checkbox v-model="row.isCheckBox" label="" /> <span style="position:relative;top:-2px">
+                          {{getLabelOne(row.type)}}</span>
+                      </td>
+                      <td>
+                        <div v-for="file in row.fileList" :key="file.id" class="el-click" @click="openImg(file.fileUrl)">
+                          {{file.fileName}}
+                        </div>
+                      </td>
+                      <td>
+                        <el-form-item :prop="'quotationProductList.' + index + '.quotationProductCustomInfoList.' + sonIndex + '.remark'"
+                                      :rules="row.isCheckBox?rules.remark:''" :inline-message="true" class="margin-b-0 wid100">
+                          <el-input v-model="row.remark" placeholder="" />
+                        </el-form-item>
+                      </td>
+                    </tr>
+                  </table>
+                </el-form-item>
+              </el-row>
+            </div>
+          </div>
+        </template>
+
+      </byForm>
+      <template #footer>
+        <el-button @click="detailDialog = false" size="default" v-debounce>关 闭</el-button>
+
+      </template>
+    </el-dialog>
+
     <el-dialog :title="'物料选择'" v-model="openSelectMaterial" width="90%" destroy-on-close>
       <SelectMaterial :isNeRawMaterial="'1'" @selectMaterial="selectMaterial"></SelectMaterial>
       <template #footer>
@@ -446,6 +683,8 @@ import * as echarts from "echarts";
 import SelectMaterial from "@/components/product/SelectMaterial.vue";
 import QuotationPDF from "@/components/PDF/quotationPDF.vue";
 const { proxy } = getCurrentInstance();
+const packAskData = computed(() => proxy.useUserStore().allDict["pack_ask"]);
+const foldWayData = computed(() => proxy.useUserStore().allDict["fold_way"]);
 const sourceList = ref({
   data: [],
   pagination: {
@@ -640,10 +879,33 @@ const getList = async (req) => {
   });
 };
 getList();
+const rawMaterialData = ref([]);
+const technologyData = ref([]);
+const getRawMaterialData = () => {
+  proxy.post("/productInfo/page", { productClassifyId: 100 }).then((res) => {
+    rawMaterialData.value = res.rows.map((x) => ({
+      ...x,
+      label:
+        x.name +
+        "," +
+        x.customCode +
+        "," +
+        `${x["length"]}*${x.width}*${x.height}(cm)` +
+        "," +
+        x.color,
+      value: x.id,
+    }));
+  });
+  proxy.post("/technology/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    technologyData.value = res.rows;
+  });
+};
+getRawMaterialData();
 const formDom = ref(null);
 const submitLoading = ref(false);
 const formData = reactive({
   data: {},
+  detailsData: {},
 });
 const formOption = reactive({
   inline: true,
@@ -1069,6 +1331,7 @@ const getDict = () => {
     .then((res) => {
       moldData.value = res.rows.map((x) => ({
         ...x,
+        area: Number(parseFloat(x.moldLength * x.moldWidth).toFixed(2)),
         moldName:
           x.moldName + `(${x.moldLength}*${x.moldWidth}*${x.moldHeight})`,
       }));
@@ -1077,7 +1340,9 @@ const getDict = () => {
 getDict();
 
 let currentIndex = ref(-1);
+const currentProduct = ref({});
 const handleReportPrice = (item, index) => {
+  currentProduct.value = item;
   currentIndex.value = index;
   submitLoading.value = true;
   formData.data = {
@@ -1185,6 +1450,95 @@ const handlePrint = (row) => {
   openPrint.value = true;
   rowData.value = row;
 };
+
+const changeCavityNum = (val, index) => {
+  let { productLength, productWidth } = currentProduct.value;
+  if (val) {
+    // 计算商品的总面积
+    let areaOne = (productLength + 2) * val * ((productWidth + 2) * 1);
+    let areaTwo = (productLength + 2) * 1 * ((productWidth + 2) * val);
+    // 过滤出模具面积 >= 商品的总面积
+    let filterData = moldData.value.filter(
+      (x) => x.area >= areaOne || x.area >= areaTwo
+    );
+    // 取出面积最小的模具
+    if (filterData && filterData.length > 0) {
+      let sortList = filterData.sort((a, b) => a.area - b.area);
+      formData.data.quotationEstimateList[index].moldId = sortList[0].id;
+    } else {
+      formData.data.quotationEstimateList[index].moldId = "";
+      return proxy.msgTip("未找到合适的模具", 2);
+    }
+  }
+};
+
+const changeMoldId = (val, index) => {
+  let { productLength, productWidth } = currentProduct.value;
+  //  一出几
+  let cavityNum = formData.data.quotationEstimateList[index].cavityNum;
+  // 计算商品的总面积
+
+  if (val && cavityNum) {
+    let areaOne = (productLength + 2) * cavityNum * ((productWidth + 2) * 1);
+    let areaTwo = (productLength + 2) * 1 * ((productWidth + 2) * cavityNum);
+    let mold = moldData.value.find((x) => x.id == val);
+    if (mold) {
+      if (mold.area >= areaOne || mold.area >= areaTwo) {
+      } else {
+        proxy.msgTip(`该模具不能一出${cavityNum}`, 2);
+      }
+    }
+    changeTotalAmount();
+  }
+};
+
+const detailDialog = ref(false);
+const detailsFormOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  disabled: true,
+});
+const detailsFormConfig = computed(() => {
+  return [
+    {
+      type: "slot",
+      slotName: "detail",
+      label: "",
+    },
+  ];
+});
+const handleLookDetail = (item) => {
+  let obj = proxy.deepClone(item);
+  if (obj.packAsk) {
+    obj.packAsk = obj.packAsk.split(",");
+  }
+  obj.quotationProductCustomInfoList.forEach((x) => {
+    if (x.fileList) {
+      x.fileList = x.fileList.map((y) => ({
+        ...y,
+        url: y.fileUrl,
+        name: y.fileName,
+      }));
+    } else {
+      x.fileList = [];
+    }
+    x.isCheckBox = x.isCheck == 1;
+  });
+  obj.quotationProductBomList = obj.quotationProductBomList.filter(
+    (x) => x.type == 2
+  );
+  formData.detailsData = obj;
+  detailDialog.value = true;
+};
+let obj = {
+  1: "定制刀模",
+  2: "定制纹路",
+  3: "定制模具",
+};
+const getLabelOne = (type) => {
+  return obj[type];
+};
 </script>
 
 <style lang="scss" scoped>
@@ -1242,7 +1596,31 @@ const handlePrint = (row) => {
   }
 }
 
-::v-deep(.el-input-number .el-input__inner) {
-  text-align: right;
+::v-deep(.box .el-input-number .el-input__inner) {
+  text-align: right !important;
+}
+::v-deep(.box .el-input-number.is-without-controls .el-input__wrapper) {
+  padding-left: 10px;
+  padding-right: 10px;
+}
+
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+
+  td {
+    text-align: center;
+    padding: 2px 4px;
+    // padding: 5px 10px;
+  }
+}
+.small-title {
+  padding-left: 15px;
+  margin-bottom: 10px;
+  color: #3366ff;
+  font-size: 14px;
+}
+:deep(.el-checkbox) {
+  margin-right: 0px;
 }
 </style>

+ 23 - 3
src/views/EHSD/saleContract/priceSheetForeign/index.vue

@@ -94,8 +94,12 @@
       <template #btn="{item}">
         <div style="width: 100%">
           <div>
-            <el-button type="primary" text v-debounce v-if="item.status !=88" @click="handleGenerate(item,false)">生成订单</el-button>
-            <el-button type="primary" text v-debounce v-if="item.status !=88" @click="handleGenerate(item,true)">生成样品单</el-button>
+            <el-button type="primary" text v-debounce v-if="item.status !=88 && item.createProductStatus==0"
+                       @click="handleGenerateProduct(item)">生成待建产品</el-button>
+            <el-button type="primary" text v-debounce v-if="item.status !=88 && item.createProductStatus==2"
+                       @click="handleGenerate(item,false)">生成订单</el-button>
+            <el-button type="primary" text v-debounce v-if="item.status !=88 && item.createProductStatus==2"
+                       @click="handleGenerate(item,true)">生成样品单</el-button>
             <!-- <el-button type="primary" text v-debounce v-if="item.status !=88" @click="getDtl(item)">调价</el-button> -->
             <el-button type="danger" text v-debounce v-if="item.status !=0 && item.status !=88" @click="handleRepeal(item)">作废</el-button>
           </div>
@@ -409,7 +413,7 @@ const config = computed(() => {
       attrs: {
         label: "客户名称",
         prop: "buyCorporationName",
-        "min-width": 150,
+        "min-width": 170,
       },
     },
     {
@@ -796,6 +800,22 @@ const leftRowData = ref({});
 const changeLeftData = (i) => {
   leftRowData.value = i;
 };
+
+const handleGenerateProduct = (row) => {
+  proxy
+    .msgConfirm()
+    .then((res) => {
+      proxy
+        .post("/extQuotation/waitProduct", {
+          id: row.id,
+        })
+        .then((res) => {
+          proxy.msgTip("操作成功", 1);
+          getList();
+        });
+    })
+    .catch((err) => {});
+};
 </script>
 
 <style lang="scss" scoped>

Fișier diff suprimat deoarece este prea mare
+ 717 - 158
src/views/MES/processScheduling/index.vue


+ 1 - 1
src/views/MES/productionTask/index.vue

@@ -577,7 +577,7 @@ const config = ref([
     attrs: {
       label: "产品颜色",
       prop: "productColor",
-      width: 80,
+      width: 160,
     },
   },
   {

+ 1143 - 0
src/views/MES/productionTask/selectProductionTask.vue

@@ -0,0 +1,1143 @@
+<template>
+  <div class="pageIndexClass">
+    <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row
+             :selectConfig="selectConfig" :action-list="[ 
+              
+        ]" :table-events="{
+          //element talbe事件都能传
+          select: selectRow,
+       'select-all':selectRow
+        }" @get-list="getList">
+
+      <template #orderCode="{ item }">
+        <div style="width: 100%" class="el-click" @click="lookDetails(item)">
+          {{item.orderCode}}
+        </div>
+      </template>
+
+      <template #pic="{ item }">
+        <div v-if="item.fileList &&item.fileList.length > 0">
+          <img :src="item.fileList[0].fileUrl" class="pic" @click="handleClickFile(item.fileList[0])" />
+        </div>
+        <div v-else></div>
+      </template>
+
+      <template #picOne="{ item }">
+        <div v-if="item.fileListOne &&item.fileListOne.length > 0">
+          <img :src="item.fileListOne[0].fileUrl" class="pic" @click="handleClickFile(item.fileListOne[0])" />
+        </div>
+        <div v-else></div>
+      </template>
+
+      <template #size="{ item }">
+        <div v-if="item.productLength && item.productWidth && item.productHeight">
+          <span>{{ item.productLength }}</span>*
+          <span>{{ item.productWidth }}</span>*
+          <span>{{ item.productHeight }}</span>
+        </div>
+      </template>
+
+      <template #isOverdue="{item}">
+        <div style="width: 100%">
+          <span class="red" v-if="item.isOverdue=='1'"> 逾期 </span>
+          <span v-else> 未逾期 </span>
+        </div>
+      </template>
+
+      <template #progress="{item}">
+        <div style="width: 100%">
+          <el-progress type="circle" :percentage="(Number(item.finishQuantity) / Number(item.quantity))*100" width="60"
+                       :status="(Number(item.finishQuantity) / Number(item.quantity))*100 == 100 ? 'success' : ''" />
+        </div>
+      </template>
+
+      <template #prodTag="{ item }">
+        <div style="width: 100%">
+          <el-popover placement="top-start" :width="300" trigger="hover">
+            <div>
+              备注:{{item.prodRemark}}
+            </div>
+            <template #reference>
+              <div style="width:100%;display:inline-block">
+                <el-tag style="margin-right: 8px" type="success" v-for="(tag, index) in item.prodTags" :key="index">
+                  {{ dictKeyValue(tag, contractTag) }}
+                </el-tag>
+              </div>
+            </template>
+          </el-popover>
+        </div>
+      </template>
+
+      <template v-for="(slotItem, index) in processesData" v-slot:[slotItem.id]="{ item }" :key="slotItem.id">
+        <div style="width:100%">
+          <span v-if="isShowCotent(slotItem,item)" style="font-weight:700;min-width:50px;line-height:18px;display:inline-block"
+                :class="showCotentQuantity(slotItem,item)">
+            {{showCotent(slotItem,item)}}
+          </span>
+          <div v-else class="no-bk">
+            -
+          </div>
+        </div>
+      </template>
+    </byTable>
+
+    <el-dialog :title="'打印任务单'" v-model="dialogVisible" width="840px" destroy-on-close :before-close="beforeClose">
+      <div style="height:calc(100vh - 280px);overflow:auto;padding: 0 10px">
+        <div id="pdfDom" style="width:100%">
+          <!-- <div style="font-size:20px;text-align:center">
+            {{printData.name}}
+          </div> -->
+          <div v-for="item in printList" :key="item.id" style="margin-bottom:20px">
+            <div style="font-size:32px;font-weight:700;color:#000;text-align:center">
+              生产任务单
+            </div>
+            <div style="float:right;margin: 20px 0px 5px 0;">
+              {{printTime}}
+            </div>
+            <table class="table" border>
+              <tr>
+                <td style="width:25%">
+                  <div :ref="item.id">
+                  </div>
+                </td>
+                <td style="width:75%">
+                  <div style="display:flex;margin-bottom:10px">
+                    <div style="width:50%">
+                      <div class="top-title">
+                        订单号
+                      </div>
+                      <div>
+                        {{item.orderCode}}
+                      </div>
+                    </div>
+                    <div style="width:50%">
+                      <div class="top-title">
+                        交期
+                      </div>
+                      <div v-if="item.deliveryPeriod">
+                        {{item.deliveryPeriod.substr(0,10)}}
+                      </div>
+                    </div>
+                  </div>
+                  <div style="display:flex;margin-bottom:10px">
+                    <div style="width:50%">
+                      <div class="top-title">
+                        产品编码
+                      </div>
+                      <div>
+                        {{item.productCode}}
+                      </div>
+                    </div>
+                    <div style="width:50%">
+                      <div class="top-title">
+                        生产数量
+                      </div>
+                      <div>
+                        {{item.quantity}}
+                      </div>
+                    </div>
+                  </div>
+                  <div style="margin-bottom:10px">
+                    <div class="top-title">
+                      产品名称
+                    </div>
+                    <div>
+                      {{item.productName}}
+                    </div>
+                  </div>
+                  <div style="margin-bottom:10px">
+                    <div class="top-title">
+                      产品尺寸(cm)
+                    </div>
+                    <div>
+                      {{item.productLength}} * {{item.productWidth}} * {{item.productHeight}}
+                    </div>
+                  </div>
+                </td>
+              </tr>
+              <tr>
+                <td style="text-align:center" rowspan="4">
+                  <div>
+                    <div style="font-weight:700">产品图</div>
+                    <img v-if="item.fileList &&item.fileList.length > 0" class="bigImg" :src="item.fileList[0].fileUrl" alt="">
+                  </div>
+                  <div style="margin-top:20px">
+                    <div style="font-weight:700">设计图</div>
+                    <img v-if="item.fileListOne &&item.fileListOne.length > 0" class="bigImg" :src="item.fileListOne[0].fileUrl" alt="">
+                  </div>
+                </td>
+                <td style="height:60px;vertical-align:top">
+                  <div>
+                    <div class="top-title">
+                      产品备注
+                    </div>
+                    <div>
+                      {{item.productRemark}}
+                    </div>
+                  </div>
+                </td>
+              </tr>
+              <tr>
+                <td style="height:60px;vertical-align:top">
+                  <div class="top-title">
+                    生产工序
+                  </div>
+                  <div>
+                    <!-- <el-checkbox v-for="proess in item.productionTaskProgressList" :key="proess.processesId" :label="proess.progressName"
+                                 size="small" /> -->
+                    <span v-for="(proess,index) in item.productionTaskProgressList" :key="proess.processesId">{{proess.progressName}} <span
+                            v-if="index<item.productionTaskProgressList.length-1"> > </span> </span>
+                  </div>
+                </td>
+              </tr>
+              <tr>
+                <td style="height:107px">
+                  <div style="margin-bottom:10px">
+                    <div class="top-title">
+                      原材料编码
+                    </div>
+                    <div>
+                      {{item.rawMaterialCode}}
+                    </div>
+                  </div>
+                  <div>
+                    <div class="top-title">
+                      原材料名称
+                    </div>
+                    <div>
+                      {{item.rawMaterialName}}
+                    </div>
+                  </div>
+                </td>
+              </tr>
+              <tr>
+                <td style="vertical-align:top">
+                  <div class="top-title">BOM</div>
+                  <div>
+                    <table border class="table son">
+                      <tr>
+                        <td style="width:85%">名称</td>
+                        <!-- <td style="width:15%">单价</td> -->
+                        <td style="width:15%">数量</td>
+                      </tr>
+                      <tr v-for="son in item.contractProductBomList" :key="son.id">
+                        <td>
+                          <div>
+                            {{son.productCode}}
+                          </div>
+                          <div>
+                            {{son.productName}}
+                          </div>
+                        </td>
+                        <!-- <td>{{son.price}}</td> -->
+                        <td>{{son.quantity}}</td>
+                      </tr>
+                    </table>
+                  </div>
+                </td>
+              </tr>
+
+            </table>
+            <div style="page-break-after: always"></div>
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="defualt">取 消</el-button>
+        <el-button type="primary" v-print="printObj" size="defualt">打 印</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="备注" v-model="remarkDialog" width="500" destroy-on-close v-if="remarkDialog">
+      <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
+      </byForm>
+      <template #footer>
+        <el-button @click="remarkDialog = false" size="defualt" v-debounce>取 消</el-button>
+        <el-button type="primary" @click="submitForm()" size="defualt" v-debounce>
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="记录查看" v-model="recordDialog" width="70%" destroy-on-close v-if="recordDialog">
+      <byForm :formConfig="recordFormConfig" :formOption="recordFormOption" v-model="formData.recordData">
+        <template #detail1>
+          <div style="width:100%">
+            <el-table :data="formData.recordData.purchaseProductList">
+              <el-table-column label="商品图片" width="80">
+                <template #default="{ row }">
+                  <div v-if="row.fileUrl">
+                    <img :src="row.fileUrl" class="pic" @click="openImg(row.fileUrl)" />
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="productCode" label="商品编码" width="160" />
+              <el-table-column prop="productName" label="商品名称" min-width="130" />
+              <el-table-column label="尺寸 (cm)" width="140">
+                <template #default="{ row, $index }">
+                  <div style="width: 100%">
+                    {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="颜色" prop="productColor" width="160" />
+              <el-table-column label="采购数量" prop="quantity" width="100" />
+            </el-table>
+          </div>
+        </template>
+        <template #detail2>
+          <div style="width:100%">
+            <el-table :data="formData.recordData.stockJournalDetailsList">
+              <el-table-column label="类型" width="100" :formatter="(row) => row.opType=='1'?'入库':'出库'" />
+              <el-table-column label="商品图片" width="80">
+                <template #default="{ row }">
+                  <div v-if="row.fileUrl">
+                    <img :src="row.fileUrl" class="pic" @click="openImg(row.fileUrl)" />
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="productCode" label="商品编码" width="160" />
+              <el-table-column prop="productName" label="商品名称" min-width="130" />
+              <el-table-column label="尺寸 (cm)" width="140">
+                <template #default="{ row, $index }">
+                  <div style="width: 100%">
+                    {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="颜色" prop="productColor" width="160" />
+              <el-table-column label="数量" prop="quantity" width="100" />
+            </el-table>
+          </div>
+        </template>
+      </byForm>
+      <!-- <template #footer>
+        <el-button @click="recordDialog = false" size="defualt" v-debounce>关闭</el-button>
+      </template> -->
+    </el-dialog>
+  </div>
+
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
+import QRCode from "qrcodejs2-fix";
+import moment from "moment";
+
+const { proxy } = getCurrentInstance();
+const contractTag = computed(
+  () => proxy.useUserStore().allDict["contract_prod_tag"]
+);
+const companyData = ref([]);
+const loading = ref(false);
+const submitLoading = ref(false);
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 3,
+    pageNum: 1,
+    pageSize: 10,
+    keyword: "",
+    produceStatus: "",
+    staDeliveryPeriod: "",
+    endDeliveryPeriod: "",
+    beginTime: "",
+    endTime: "",
+    isOverdue: "",
+  },
+});
+const treeData = ref([]);
+const dialogVisible = ref(false);
+const remarkDialog = ref(false);
+
+const modalType = ref("add");
+const statusData = ref([
+  {
+    label: "未开始",
+    value: "0",
+  },
+  {
+    label: "生产中",
+    value: "1",
+  },
+  {
+    label: "生产完成",
+    value: "2",
+  },
+  {
+    label: "出库中",
+    value: "5",
+  },
+  {
+    label: "已出库",
+    value: "10",
+  },
+]);
+
+const isOverdueData = ref([
+  {
+    label: "是",
+    value: "1",
+  },
+  {
+    label: "否",
+    value: "0",
+  },
+]);
+
+const contractTypeData = ref([
+  {
+    dictKey: "3",
+    dictValue: "打样订单",
+  },
+  {
+    dictKey: "2",
+    dictValue: "内销订单",
+  },
+  {
+    dictKey: "1",
+    dictValue: "外贸订单(退税)",
+  },
+  {
+    dictKey: "4",
+    dictValue: "外贸订单(不退税)",
+  },
+]);
+
+const selectConfig = computed(() => [
+  {
+    label: "业务公司",
+    prop: "contractCompanyId",
+    data: companyData.value,
+    isFilter: false,
+  },
+  {
+    label: "工厂",
+    prop: "companyId",
+    data: companyData.value,
+  },
+  {
+    label: "生产状态",
+    prop: "produceStatus",
+    data: statusData.value,
+  },
+  {
+    label: "是否逾期",
+    prop: "isOverdue",
+    data: isOverdueData.value,
+  },
+  {
+    type: "time",
+    label: "交期",
+    placeholder: "开始日期",
+    prop: "staDeliveryPeriod",
+    placeholderOne: "结束日期",
+    propOne: "endDeliveryPeriod",
+  },
+  {
+    type: "time",
+    label: "下单日期",
+    placeholder: "开始日期",
+    prop: "beginTime",
+    placeholderOne: "结束日期",
+    propOne: "endTime",
+  },
+]);
+const config = ref([
+  // {
+  //   type: "selection",
+  //   attrs: {
+  //     checkAtt: "isCheck",
+  //     width: 60,
+  //   },
+  // },
+  // {
+  //   attrs: {
+  //     label: "操作",
+  //     width: "160",
+  //     align: "left",
+  //     // fixed: "right",
+  //   },
+  //   renderHTML(row) {
+  //     return [
+  //       {
+  //         attrs: {
+  //           label: "打印任务单",
+  //           type: "primary",
+  //           text: true,
+  //         },
+  //         el: "button",
+  //         click() {
+  //           printQrCode(row);
+  //         },
+  //       },
+  //       {
+  //         attrs: {
+  //           label: "备注",
+  //           type: "primary",
+  //           text: true,
+  //         },
+  //         el: "button",
+  //         click() {
+  //           openRemark(row);
+  //         },
+  //       },
+  //     ];
+  //   },
+  // },
+  {
+    attrs: {
+      label: "业务公司",
+      prop: "contractCompanyName",
+      width: 110,
+    },
+  },
+  {
+    attrs: {
+      label: "是否逾期",
+      slot: "isOverdue",
+      width: 80,
+      fixed: "left",
+    },
+  },
+  {
+    attrs: {
+      label: "订单类型",
+      prop: "contractType",
+      width: 110,
+    },
+    render(val) {
+      return proxy.dictKeyValue(val, contractTypeData.value);
+    },
+  },
+  {
+    attrs: {
+      label: "工厂",
+      prop: "companyName",
+      width: 100,
+      // align: "center",
+    },
+  },
+  {
+    attrs: {
+      label: "业务员",
+      prop: "saleUserName",
+      width: 100,
+      // align: "center",
+    },
+  },
+  {
+    attrs: {
+      label: "订单号",
+      slot: "orderCode",
+      width: 130,
+    },
+  },
+  {
+    attrs: {
+      label: "产品图片",
+      slot: "pic",
+      width: 80,
+    },
+  },
+  {
+    attrs: {
+      label: "设计图",
+      slot: "picOne",
+      width: 80,
+    },
+  },
+  {
+    attrs: {
+      label: "产品编码",
+      prop: "productCode",
+      width: 130,
+    },
+  },
+  {
+    attrs: {
+      label: "产品名称",
+      prop: "productName",
+      "min-width": 200,
+    },
+  },
+  {
+    attrs: {
+      label: "产品尺寸 (cm)",
+      slot: "size",
+      width: 160,
+    },
+  },
+  {
+    attrs: {
+      label: "产品颜色",
+      prop: "productColor",
+      width: 160,
+    },
+  },
+  {
+    attrs: {
+      label: "生产件数",
+      prop: "quantity",
+      width: 100,
+    },
+  },
+  {
+    attrs: {
+      label: "完成进度",
+      slot: "progress",
+      width: 90,
+    },
+  },
+  {
+    attrs: {
+      label: "已完成",
+      prop: "finishQuantity",
+      width: 100,
+    },
+  },
+  {
+    attrs: {
+      label: "未完成",
+      prop: "incomplete",
+      width: 100,
+    },
+  },
+  {
+    attrs: {
+      label: "生产状态",
+      prop: "produceStatus",
+      width: 100,
+    },
+    render(val) {
+      return proxy.dictValueLabel(val, statusData.value);
+    },
+  },
+  {
+    attrs: {
+      label: "生产指示",
+      slot: "prodTag",
+      "min-width": 220,
+    },
+  },
+  {
+    attrs: {
+      label: "下单时间",
+      prop: "orderCreateTime",
+      width: 160,
+    },
+  },
+  {
+    attrs: {
+      label: "交期",
+      prop: "deliveryPeriod",
+      width: 100,
+    },
+    render(val) {
+      if (val) {
+        return val.slice(0, 10);
+      }
+      return "";
+    },
+  },
+  // {
+  //   attrs: {
+  //     label: "投产时间",
+  //     prop: "produceTime",
+  //     width: 160,
+  //   },
+  // },
+  {
+    attrs: {
+      label: "完成时间",
+      prop: "finishTime",
+      width: 160,
+    },
+  },
+
+  {
+    attrs: {
+      label: "生产用时",
+      prop: "usageTime",
+      width: 100,
+    },
+  },
+  {
+    attrs: {
+      label: "备注",
+      prop: "remark",
+      "min-width": 200,
+    },
+  },
+  {
+    attrs: {
+      label: "操作",
+      width: "80",
+      align: "center",
+      fixed: "right",
+    },
+    // 渲染 el-button,一般用在最后一列。
+    renderHTML(row) {
+      return [
+        {
+          attrs: {
+            label: "选择",
+            type: "primary",
+            text: true,
+          },
+          el: "button",
+          click() {
+            selectTask(row);
+          },
+        },
+      ];
+    },
+  },
+]);
+const formData = reactive({
+  data: {},
+  recordData: {},
+});
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+});
+const formDom = ref(null);
+const formConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "remark",
+      itemType: "textarea",
+      label: "备注",
+      itemWidth: 100,
+      disabled: false,
+    },
+  ];
+});
+const rules = ref({
+  remark: [{ required: true, message: "请输入备注", trigger: "blur" }],
+});
+
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy
+    .post("/produceOrderDetail/schedulingTaskPage", sourceList.value.pagination)
+    .then((res) => {
+      res.rows.forEach((x) => {
+        if (x.prodTag) {
+          x.prodTags = x.prodTag.split(",");
+        } else {
+          x.prodTags = [];
+        }
+        x.incomplete = x.quantity - x.finishQuantity;
+      });
+      sourceList.value.data = res.rows.map((x) => ({ ...x, isCheck: true }));
+      sourceList.value.pagination.total = res.total;
+      setTimeout(() => {
+        loading.value = false;
+      }, 200);
+      const productIdList = res.rows.map((x) => x.productId);
+      // 请求文件数据并回显
+      if (productIdList.length > 0) {
+        // proxy.getFile(productIdList, sourceList.value.data, "productId");
+        proxy
+          .post("/fileInfo/getList", { businessIdList: productIdList })
+          .then((fileObj) => {
+            for (let i = 0; i < sourceList.value.data.length; i++) {
+              const ele = sourceList.value.data[i];
+              for (const key in fileObj) {
+                if (
+                  ele.productId == key &&
+                  fileObj[ele.productId] &&
+                  fileObj[ele.productId].length > 0
+                ) {
+                  ele.fileList = fileObj[ele.productId].filter(
+                    (x) => x.businessType == "0"
+                  );
+                }
+              }
+            }
+          });
+      }
+
+      const productIdListOne = res.rows.map((x) => x.contractDetailId);
+      // 请求文件数据并回显
+      if (productIdListOne.length > 0) {
+        proxy
+          .post("/fileInfo/getList", { businessIdList: productIdListOne })
+          .then((fileObj) => {
+            for (let i = 0; i < sourceList.value.data.length; i++) {
+              const ele = sourceList.value.data[i];
+              for (const key in fileObj) {
+                if (
+                  ele.contractDetailId == key &&
+                  fileObj[ele.contractDetailId] &&
+                  fileObj[ele.contractDetailId].length > 0
+                ) {
+                  ele.fileListOne = fileObj[ele.contractDetailId].filter(
+                    (x) => x.businessType == "0"
+                  );
+                }
+              }
+            }
+          });
+        // proxy.getFile(
+        //   productIdListOne,
+        //   sourceList.value.data,
+        //   "contractDetailId",
+        //   "fileListOne"
+        // );
+      }
+    });
+};
+
+const printList = ref([]);
+
+const selectIds = ref([]);
+const selectRow = (data) => {
+  selectIds.value = data.map((x) => x.id);
+};
+const printTime = ref("");
+const openModal = () => {
+  proxy.msgTip("请稍后", 2);
+  proxy
+    .post("/produceOrderDetail/detailByIds", { taskIds: selectIds.value })
+    .then((res) => {
+      printList.value = res;
+      for (let i = 0; i < printList.value.length; i++) {
+        const iele = printList.value[i];
+        for (let j = 0; j < sourceList.value.data.length; j++) {
+          const jele = sourceList.value.data[j];
+          if (iele.id == jele.id) {
+            iele.fileList = jele.fileList;
+            iele.fileListOne = jele.fileListOne;
+            break;
+          }
+        }
+      }
+      printTime.value = moment().format("yyyy-MM-DD HH:mm:ss");
+      dialogVisible.value = true;
+      nextTick(() => {
+        for (let i = 0; i < printList.value.length; i++) {
+          const row = printList.value[i];
+          proxy.$refs[row.id][0].innerHTML = ""; //清除二维码方法一
+          new QRCode(proxy.$refs[row.id][0], {
+            text: row.id,
+            width: 200,
+            height: 200,
+            colorDark: "#000000",
+            colorLight: "#ffffff",
+            correctLevel: QRCode.CorrectLevel.H,
+          });
+        }
+      });
+    });
+};
+
+const submitForm = () => {
+  formDom.value.handleSubmit((valid) => {
+    submitLoading.value = true;
+    proxy.post("/produceOrderDetail/editRemark", formData.data).then(
+      (res) => {
+        proxy.msgTip("操作成功", 1);
+        remarkDialog.value = false;
+        submitLoading.value = false;
+        getList();
+      },
+      (err) => {
+        submitLoading.value = false;
+      }
+    );
+  });
+};
+
+const getDtl = (row) => {
+  modalType.value = "edit";
+  proxy.post("/shopInfo/detail", { id: row.id }).then((res) => {
+    formData.data = res;
+    dialogVisible.value = true;
+  });
+};
+const processesData = ref([]);
+const getProcesses = () => {
+  proxy
+    .post("/productionProcesses/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      // for (let i = 0; i < res.rows.length; i++) {
+      //   const ele = res.rows[i];
+      //   let attrs = {
+      //     label: `[ ${ele.name} ]`,
+      //     slot: ele.id,
+      //     isNeedHeaderSlot: false,
+      //     width: 70,
+      //     align: "center",
+      //     fixed: "right",
+      //   };
+      //   config.value.push({
+      //     attrs,
+      //   });
+      // }
+
+      // config.value.push({
+      //   attrs: {
+      //     label: "操作",
+      //     width: "160",
+      //     align: "center",
+      //     fixed: "right",
+      //   },
+      //   renderHTML(row) {
+      //     return [
+      //       {
+      //         attrs: {
+      //           label: "打印任务单",
+      //           type: "primary",
+      //           text: true,
+      //         },
+      //         el: "button",
+      //         click() {
+      //           printQrCode(row);
+      //         },
+      //       },
+      //       {
+      //         attrs: {
+      //           label: "备注",
+      //           type: "primary",
+      //           text: true,
+      //         },
+      //         el: "button",
+      //         click() {
+      //           openRemark(row);
+      //         },
+      //       },
+      //     ];
+      //   },
+      // });
+      processesData.value = res.rows;
+    });
+};
+getProcesses();
+getList();
+const printType = ref(false);
+
+const printQrCode = (row) => {
+  printType.value = true;
+  selectIds.value = [row.id];
+  openModal();
+};
+const beforeClose = () => {
+  if (printType.value) {
+    selectIds.value = [];
+  }
+  dialogVisible.value = false;
+};
+const printObj = ref({
+  id: "pdfDom",
+  popTitle: "",
+  extraCss:
+    "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
+  extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
+});
+
+const handleClickFile = (file) => {
+  window.open(file.fileUrl, "_blank");
+};
+
+const isShowCotent = (slot, item) => {
+  if (item && item.productionTaskProgressList) {
+    return item.productionTaskProgressList.some(
+      (x) => x.processesId == slot.id
+    );
+  } else {
+    return false;
+  }
+};
+const showCotent = (slot, item) => {
+  if (item && item.productionTaskProgressList) {
+    const current = item.productionTaskProgressList.find(
+      (x) => x.processesId == slot.id
+    );
+    if (current) {
+      return current.finishQuantity;
+    }
+  } else {
+    return false;
+  }
+};
+
+const showCotentQuantity = (slot, item) => {
+  if (item && item.productionTaskProgressList) {
+    const current = item.productionTaskProgressList.find(
+      (x) => x.processesId == slot.id
+    );
+    if (current && Number(current.finishQuantity) > 0) {
+      if (Number(current.finishQuantity) >= item.quantity) {
+        return "tag-active";
+      } else if (Number(current.finishQuantity) < item.quantity) {
+        return "tag-active-1";
+      }
+    }
+  }
+};
+
+const getDict = () => {
+  proxy
+    .get("/tenantDept/list", {
+      pageNum: 1,
+      pageSize: 9999,
+      keyword: "",
+      tenantId: proxy.useUserStore().user.tenantId,
+      type: 0,
+    })
+    .then((res) => {
+      companyData.value = res.data.map((x) => ({
+        ...x,
+        label: x.deptName,
+        value: x.deptId,
+      }));
+      // treeData.value = proxy.handleTree(res.data, "deptId");
+    });
+};
+getDict();
+
+const openRemark = (row) => {
+  formData.data = {
+    id: row.id,
+    remark: row.remark,
+  };
+  remarkDialog.value = true;
+};
+const recordDialog = ref(false);
+const recordFormOption = reactive({
+  inline: true,
+  labelWidth: 40,
+  itemWidth: 100,
+});
+const recordFormConfig = computed(() => {
+  return [
+    {
+      type: "title1",
+      title: "采购记录",
+    },
+    {
+      type: "slot",
+      slotName: "detail1",
+      label: " ",
+    },
+    {
+      type: "title1",
+      title: "出入库流水记录",
+    },
+    {
+      type: "slot",
+      slotName: "detail2",
+      label: " ",
+    },
+  ];
+});
+const lookDetails = (item) => {
+  recordDialog.value = true;
+  proxy
+    .post("/produceOrder/detail", {
+      id: item.produceOrderId,
+    })
+    .then((res) => {
+      console.log(res, "aaa");
+      formData.recordData = res;
+      if (
+        formData.recordData.purchaseProductList &&
+        formData.recordData.purchaseProductList.length > 0
+      ) {
+        let productIds = formData.recordData.purchaseProductList.map(
+          (x) => x.productId
+        );
+        proxy.getFileData({
+          businessIdList: productIds,
+          data: formData.recordData.purchaseProductList,
+          att: "productId",
+          businessType: "0",
+          fileAtt: "fileList",
+          filePathAtt: "fileUrl",
+        });
+      }
+      if (
+        formData.recordData.stockJournalDetailsList &&
+        formData.recordData.stockJournalDetailsList.length > 0
+      ) {
+        let productIds = formData.recordData.stockJournalDetailsList.map(
+          (x) => x.productId
+        );
+        proxy.getFileData({
+          businessIdList: productIds,
+          data: formData.recordData.stockJournalDetailsList,
+          att: "productId",
+          businessType: "0",
+          fileAtt: "fileList",
+          filePathAtt: "fileUrl",
+        });
+      }
+    });
+};
+
+const selectTask = (row) => {
+  proxy.$emit("selectTask", row);
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-progress__text) {
+  font-size: 14px !important;
+}
+.content {
+  padding: 20px;
+}
+.pic {
+  object-fit: contain;
+  width: 50px;
+  height: 50px;
+  cursor: pointer;
+  vertical-align: middle;
+}
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  td {
+    text-align: left;
+    padding: 10px;
+    font-size: 13px;
+    // padding: 5px 10px;
+    .top-title {
+      font-weight: 700;
+      margin-bottom: 5px;
+    }
+    .bigImg {
+      object-fit: contain;
+      width: 160px;
+      height: 320px;
+      cursor: pointer;
+      margin-top: 10px;
+      vertical-align: middle;
+    }
+  }
+}
+.son {
+  td {
+    text-align: left;
+    padding: 5px !important;
+  }
+}
+.no-bk {
+  // background: #f3f3f3;
+  // height: 50px;
+}
+.red {
+  background: red;
+  border-radius: 2px;
+  padding: 4px;
+  color: #fff;
+}
+</style>

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff