Parcourir la source

Merge branch '外箱包装功能修改'

lxf il y a 1 an
Parent
commit
c1c396bb2a

+ 85 - 15
src/views/group/order/management/detail.vue

@@ -311,6 +311,15 @@
             </el-collapse>
           </div>
         </template>
+        <template #package>
+          <div style="width: 100%; padding: 0 20px">
+            <el-form :model="formData.data">
+              <el-form-item>
+                <el-button type="primary" size="small" @click="clickViewPackaging()" v-preReClick>产品包装配置</el-button>
+              </el-form-item>
+            </el-form>
+          </div>
+        </template>
         <template #deliveryTime>
           <div style="width: 100%">
             <el-date-picker
@@ -329,13 +338,10 @@
                 定制加工费: ¥{{ moneyFormat(calculatedAmount("customProcessingFee"), 2) }}
               </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">代发费: ¥{{ moneyFormat(calculatedAmount("lssueFee"), 2) }}</span>
-              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">
-                快递包材费: ¥{{ moneyFormat(calculatedAmount("deliveryMaterialsFee"), 2) }}
-              </span>
+              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">快递包材费: ¥{{ moneyFormat(computeDeliveryMaterialsFee(), 2) }} </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包装人工费: ¥{{ moneyFormat(calculatedAmount("packingLabor"), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包材费: ¥{{ moneyFormat(calculatedPackagingMaterialCost(), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">管理费: ¥{{ moneyFormat(calculatedAmount("managementFee"), 2) }}</span>
-              <!-- <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">外箱包装费: ¥{{ moneyFormat(calculatedOuterBoxPackingFee(), 2) }}</span> -->
             </div>
             <div style="padding: 8px 0 0 0">
               <span style="font-weight: 700; color: red">订单总金额(含税): ¥{{ moneyFormat(calculatedTotalAmount(), 2) }}</span>
@@ -405,6 +411,38 @@
         <el-button type="primary" @click="submitChangePrice()" size="large" v-preReClick>提 交</el-button>
       </template>
     </el-dialog>
+    
+    <el-dialog title="包装配置" v-if="openViewPackaging" v-model="openViewPackaging" width="80%">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
+        <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+        <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+          <el-table-column label="品号" prop="code" width="160" />
+          <el-table-column label="品名" prop="name" min-width="220" />
+          <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+          <el-table-column label="数量" prop="quantity" width="120" />
+          <el-table-column label="销售小计" width="120">
+            <template #default="{ row }">
+              {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+        <div style="display: flex; width: 100%">
+          <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+          <div style="width: calc(100% - 80px)">
+            <el-image
+              fit="scale-down"
+              style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+              v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+              :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+              @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <el-button @click="openViewPackaging = false">关 闭</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -434,6 +472,8 @@ const formData = reactive({
     type: 1,
     orderSkuList: [],
     fileList: [],
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
   },
 });
 const formConfig = computed(() => {
@@ -448,6 +488,19 @@ const formConfig = computed(() => {
       prop: "orderSkuList",
       slotName: "orderSkuList",
     },
+    route.query && route.query.detailId
+      ? {
+          type: "title",
+          title: "产品包装配置",
+          label: "",
+        }
+      : {},
+    route.query && route.query.detailId
+      ? {
+          type: "slot",
+          slotName: "package",
+        }
+      : {},
     {
       type: "title",
       title: "类型",
@@ -643,6 +696,12 @@ const getOrderDetail = (parameter) => {
           } else {
             fileList.value = [];
           }
+          let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
+          if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
+            formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
+          } else {
+            formData.data.outerBoxSelfAdhesiveStickerFile = {};
+          }
         }
         for (let i = 0; i < formData.data.orderSkuList.length; i++) {
           if (fileObj[formData.data.orderSkuList[i].id] && fileObj[formData.data.orderSkuList[i].id].length > 0) {
@@ -734,7 +793,7 @@ const clickRefresh = (index, label) => {
   formData.data.productTotalAmount = calculatedAmount("unitPrice");
   formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
   formData.data.lssueFee = calculatedAmount("lssueFee");
-  formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+  formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
   formData.data.packingLabor = calculatedAmount("packingLabor");
   formData.data.managementFee = calculatedAmount("managementFee");
   formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
@@ -788,10 +847,9 @@ const submitChangePrice = () => {
         formData.data.productTotalAmount = calculatedAmount("unitPrice");
         formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
         formData.data.lssueFee = calculatedAmount("lssueFee");
-        formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+        formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
         formData.data.packingLabor = calculatedAmount("packingLabor");
         formData.data.managementFee = calculatedAmount("managementFee");
-        // formData.data.outerBoxPackingFee = calculatedOuterBoxPackingFee();
         formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
         formData.data.totalAmount = calculatedTotalAmount();
         if (fileList.value && fileList.value.length > 0) {
@@ -836,7 +894,7 @@ const submitChangePrice = () => {
         formData.data.productTotalAmount = calculatedAmount("unitPrice");
         formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
         formData.data.lssueFee = calculatedAmount("lssueFee");
-        formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+        formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
         formData.data.packingLabor = calculatedAmount("packingLabor");
         formData.data.managementFee = calculatedAmount("managementFee");
         formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
@@ -897,7 +955,7 @@ const clickBomPriceRefresh = (index, indexBOM, label) => {
   formData.data.productTotalAmount = calculatedAmount("unitPrice");
   formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
   formData.data.lssueFee = calculatedAmount("lssueFee");
-  formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+  formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
   formData.data.packingLabor = calculatedAmount("packingLabor");
   formData.data.managementFee = calculatedAmount("managementFee");
   formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
@@ -1000,10 +1058,9 @@ const calculatedTotalAmount = () => {
       (calculatedAmount("unitPrice") +
         calculatedAmount("customProcessingFee") +
         calculatedAmount("lssueFee") +
-        calculatedAmount("deliveryMaterialsFee") +
+        computeDeliveryMaterialsFee() +
         calculatedAmount("packingLabor") +
         calculatedAmount("managementFee") +
-        // calculatedOuterBoxPackingFee() +
         calculatedPackagingMaterialCost()) *
         100
     ) / 100
@@ -1027,17 +1084,30 @@ const onSuccessFile = (any, UploadFile) => {
 const onPreviewFile = (file) => {
   window.open(file.raw.fileUrl, "_blank");
 };
-const calculatedOuterBoxPackingFee = () => {
-  let money = 0;
+const computeDeliveryMaterialsFee = () => {
+  let money = calculatedAmount("deliveryMaterialsFee");
   if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
     for (let i = 0; i < formData.data.orderPackageBomList.length; i++) {
-      if (formData.data.orderPackageBomList[i].costPrice && formData.data.orderPackageBomList[i].quantity) {
-        money = Number(Math.round((money + formData.data.orderPackageBomList[i].costPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100);
+      if (formData.data.orderPackageBomList[i].internalSellingPrice && formData.data.orderPackageBomList[i].quantity) {
+        money = Number(
+          Math.round((money + formData.data.orderPackageBomList[i].internalSellingPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100
+        );
       }
     }
   }
   return money;
 };
+const openViewPackaging = ref(false);
+const clickViewPackaging = () => {
+  openViewPackaging.value = true;
+};
+const computePackagingMoney = (item, label) => {
+  let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
 </script>
 
 <style lang="scss" scoped>

+ 248 - 56
src/views/group/order/management/index.vue

@@ -59,26 +59,6 @@
       </template>
     </el-dialog>
 
-    <el-dialog title="修改税率" v-if="openChangeTaxRate" v-model="openChangeTaxRate" width="500" style="margin-top: 20vh !important">
-      <el-form :model="details.data" label-width="120px" ref="taxRate">
-        <el-form-item label="税率" prop="taxRate" :rules="[{ required: true, message: '请输入税率', trigger: 'blur' }]">
-          <el-input-number
-            onmousewheel="return false;"
-            v-model="details.data.taxRate"
-            placeholder="请输入税率"
-            style="width: 100%"
-            :controls="false"
-            :min="0"
-            :precision="2"
-            :max="100" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="openChangeTaxRate = false" size="large">取 消</el-button>
-        <el-button type="primary" @click="submitChangeTaxRate()" size="large" v-preReClick>确 定</el-button>
-      </template>
-    </el-dialog>
-
     <el-dialog title="售后类型" v-if="openAfterSale" v-model="openAfterSale" width="300px" style="margin-top: 20vh !important">
       <template #footer>
         <el-button type="primary" @click="applyForAfterSale(1)" size="large" v-preReClick>退 货</el-button>
@@ -89,6 +69,90 @@
     <el-dialog title="送货单" v-if="openDeliveryNote" v-model="openDeliveryNote" width="1000px">
       <DeliveryNote :rowData="rowData" @clickCancel="clickCancel"></DeliveryNote>
     </el-dialog>
+
+    <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden" v-loading="loadingPackage">
+        <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
+          <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+          <div style="margin-bottom: 10px">
+            <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
+          </div>
+          <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="品号" prop="code" width="160" />
+            <el-table-column label="品名" prop="name" min-width="220" />
+            <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+            <el-table-column label="数量" width="120">
+              <template #default="{ row, $index }">
+                <div class="shippingPackage">
+                  <el-form-item
+                    :prop="'orderPackageBomList.' + $index + '.quantity'"
+                    :rules="rulesShippingPackage.quantity"
+                    :inline-message="true"
+                    style="width: 100%">
+                    <el-input-number
+                      onmousewheel="return false;"
+                      v-model="row.quantity"
+                      placeholder="修正数量"
+                      style="width: 100%"
+                      :controls="false"
+                      :min="0"
+                      :precision="0" />
+                  </el-form-item>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="销售小计" width="120">
+              <template #default="{ row }">
+                {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="80">
+              <template #default="{ $index }">
+                <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+          <div style="display: flex; width: 100%">
+            <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+            <div style="width: calc(100% - 80px)">
+              <el-image
+                fit="scale-down"
+                style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+                v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+              <div style="display: flex">
+                <el-upload
+                  :show-file-list="false"
+                  action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                  :data="uploadAdhesiveData"
+                  :before-upload="uploadAdhesiveFile"
+                  :on-success="
+                    (response, uploadFile) => {
+                      return handleAdhesivePackagingSuccess(uploadFile);
+                    }
+                  "
+                  style="width: 100%">
+                  <el-button type="primary" text>上传文件</el-button>
+                </el-upload>
+              </div>
+            </div>
+          </div>
+        </el-form>
+      </div>
+      <template #footer>
+        <el-button @click="openShippingPackage = false" v-preReClick>取 消</el-button>
+        <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提 交</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
+      <SelectBOM :selectStatus="true" :expressStatus="true" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false">关 闭</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -97,6 +161,7 @@ import byTable from "/src/components/byTable/index";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { copyText } from "vue3-clipboard";
 import DeliveryNote from "/src/components/order/deliveryNote/index";
+import SelectBOM from "/src/views/group/BOM/management/index";
 
 const { proxy } = getCurrentInstance();
 const props = defineProps({
@@ -340,7 +405,7 @@ const config = computed(() => {
     {
       attrs: {
         label: "操作",
-        width: 200,
+        width: 180,
         align: "center",
         fixed: "right",
       },
@@ -359,6 +424,17 @@ const config = computed(() => {
                 },
               }
             : {},
+          {
+            attrs: {
+              label: "修改包装配置",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              clickChangePackaging(row);
+            },
+          },
           props.selectStatus
             ? {
                 attrs: {
@@ -423,19 +499,6 @@ const config = computed(() => {
                 },
               }
             : {},
-          !props.selectStatus && row.status && row.status != 0
-            ? {
-                attrs: {
-                  label: "税率",
-                  type: "primary",
-                  text: true,
-                },
-                el: "button",
-                click() {
-                  clickChangeTaxRate(row);
-                },
-              }
-            : {},
           !props.selectStatus && [0, 10, 20].includes(row.status) && proxy.useUserStore().user.userId === "1"
             ? {
                 attrs: {
@@ -647,28 +710,6 @@ const getLogsList = async (req) => {
     }, 200);
   });
 };
-const details = reactive({
-  data: {},
-});
-const openChangeTaxRate = ref(false);
-const clickChangeTaxRate = (item) => {
-  proxy.post("/orderInfo/detail", { id: item.id }).then((res) => {
-    details.data = res;
-    openChangeTaxRate.value = true;
-  });
-};
-const submitChangeTaxRate = () => {
-  proxy.$refs.taxRate.validate((valid) => {
-    if (valid) {
-      details.data.updateType = "21";
-      proxy.post("/orderInfo/edit", details.data).then(() => {
-        ElMessage({ message: "修改完成", type: "success" });
-        openChangeTaxRate.value = false;
-        getList();
-      });
-    }
-  });
-};
 const emit = defineEmits(["selectOrder"]);
 const clickSelect = (item) => {
   emit("selectOrder", item);
@@ -750,6 +791,152 @@ const deriveExcel = (row) => {
     })
     .catch(() => {});
 };
+const formData = reactive({
+  data: {
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
+  },
+});
+const rulesShippingPackage = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const openShippingPackage = ref(false);
+const loadingPackage = ref(false);
+const clickChangePackaging = (row) => {
+  loadingPackage.value = true;
+  openShippingPackage.value = true;
+  proxy.post("/orderInfo/detail", { id: row.id }).then(
+    (res) => {
+      formData.data = res;
+      proxy.post("/fileInfo/getList", { businessIdList: [formData.data.id] }).then((fileObj) => {
+        if (fileObj[formData.data.id] && fileObj[formData.data.id].length > 0) {
+          let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
+          if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
+            formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
+          } else {
+            formData.data.outerBoxSelfAdhesiveStickerFile = {};
+          }
+        }
+      });
+      loadingPackage.value = false;
+    },
+    (err) => {
+      console.log(err);
+      loadingPackage.value = false;
+    }
+  );
+};
+const computePackagingMoney = (item, label) => {
+  let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
+const clickPackagingDelete = (index) => {
+  formData.data.orderPackageBomList.splice(index, 1);
+};
+const openFile = (path) => {
+  window.open(path);
+};
+const uploadAdhesiveData = ref({});
+const uploadAdhesiveFile = async (file) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  uploadAdhesiveData.value = res.uploadBody;
+  file.id = res.id;
+  file.fileName = res.fileName;
+  file.fileUrl = res.fileUrl;
+  return true;
+};
+const handleAdhesivePackagingSuccess = (UploadFile) => {
+  formData.data.outerBoxSelfAdhesiveStickerFile = {
+    id: UploadFile.raw.id,
+    fileName: UploadFile.raw.fileName,
+    fileUrl: UploadFile.raw.fileUrl,
+  };
+};
+const clickSaveShippingPackage = () => {
+  proxy.$refs.shippingPackage.validate((valid) => {
+    if (valid) {
+      loadingPackage.value = true;
+      if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+        proxy
+          .post("/orderInfo/editOrderPackageBom", {
+            id: formData.data.id,
+            orderPackageBomList: formData.data.orderPackageBomList,
+            outerBoxSelfAdhesiveStickerFile: formData.data.outerBoxSelfAdhesiveStickerFile,
+          })
+          .then(
+            () => {
+              ElMessage({ message: "提交成功", type: "success" });
+              openShippingPackage.value = false;
+              getList();
+            },
+            (err) => {
+              console.log(err);
+              loadingPackage.value = false;
+            }
+          );
+      } else {
+        ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            proxy
+              .post("/orderInfo/editOrderPackageBom", {
+                id: formData.data.id,
+                orderPackageBomList: formData.data.orderPackageBomList,
+                outerBoxSelfAdhesiveStickerFile: formData.data.outerBoxSelfAdhesiveStickerFile,
+              })
+              .then(
+                () => {
+                  ElMessage({ message: "提交成功", type: "success" });
+                  openShippingPackage.value = false;
+                  getList();
+                },
+                (err) => {
+                  console.log(err);
+                  loadingPackage.value = false;
+                }
+              );
+          })
+          .catch(() => {});
+      }
+    }
+  });
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = () => {
+  openExpressPacking.value = true;
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+    let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递物流包材已添加");
+    }
+    formData.data.orderPackageBomList.push({
+      bomSpecId: data.id,
+      code: data.code,
+      name: data.name,
+      internalSellingPrice: data.internalSellingPrice,
+      quantity: undefined,
+    });
+  } else {
+    formData.data.orderPackageBomList = [
+      {
+        bomSpecId: data.id,
+        code: data.code,
+        name: data.name,
+        internalSellingPrice: data.internalSellingPrice,
+        quantity: undefined,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -765,4 +952,9 @@ const deriveExcel = (row) => {
   overflow-y: auto;
   overflow-x: hidden;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 249 - 1
src/views/production/schedule/order-inquiry/index.vue

@@ -29,12 +29,98 @@
     <el-dialog title="送货单" v-if="openDeliveryNote" v-model="openDeliveryNote" width="1000px">
       <DeliveryNote :rowData="rowData" @clickCancel="clickCancel"></DeliveryNote>
     </el-dialog>
+
+    <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden" v-loading="loadingPackage">
+        <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
+          <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+          <div style="margin-bottom: 10px">
+            <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
+          </div>
+          <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="品号" prop="code" width="160" />
+            <el-table-column label="品名" prop="name" min-width="220" />
+            <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+            <el-table-column label="数量" width="120">
+              <template #default="{ row, $index }">
+                <div class="shippingPackage">
+                  <el-form-item
+                    :prop="'orderPackageBomList.' + $index + '.quantity'"
+                    :rules="rulesShippingPackage.quantity"
+                    :inline-message="true"
+                    style="width: 100%">
+                    <el-input-number
+                      onmousewheel="return false;"
+                      v-model="row.quantity"
+                      placeholder="修正数量"
+                      style="width: 100%"
+                      :controls="false"
+                      :min="0"
+                      :precision="0" />
+                  </el-form-item>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="销售小计" width="120">
+              <template #default="{ row }">
+                {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="80">
+              <template #default="{ $index }">
+                <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+          <div style="display: flex; width: 100%">
+            <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+            <div style="width: calc(100% - 80px)">
+              <el-image
+                fit="scale-down"
+                style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+                v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+              <div style="display: flex">
+                <el-upload
+                  :show-file-list="false"
+                  action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                  :data="uploadAdhesiveData"
+                  :before-upload="uploadAdhesiveFile"
+                  :on-success="
+                    (response, uploadFile) => {
+                      return handleAdhesivePackagingSuccess(uploadFile);
+                    }
+                  "
+                  style="width: 100%">
+                  <el-button type="primary" text>上传文件</el-button>
+                </el-upload>
+              </div>
+            </div>
+          </div>
+        </el-form>
+      </div>
+      <template #footer>
+        <el-button @click="openShippingPackage = false" v-preReClick>取 消</el-button>
+        <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提 交</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
+      <SelectBOM :selectStatus="true" :expressStatus="true" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false">关 闭</el-button>
+      </template>
+    </el-dialog>
   </el-card>
 </template>
 
 <script setup>
 import byTable from "/src/components/byTable/index";
 import DeliveryNote from "/src/components/order/deliveryNote/index";
+import SelectBOM from "/src/views/group/BOM/management/index";
+import { ElMessage, ElMessageBox } from "element-plus";
 
 const { proxy } = getCurrentInstance();
 const departmentList = ref([{ dictKey: "0", dictValue: "胜德体育" }]);
@@ -159,12 +245,23 @@ const config = computed(() => {
     {
       attrs: {
         label: "操作",
-        width: 180,
+        width: 240,
         align: "center",
         fixed: "right",
       },
       renderHTML(row) {
         return [
+          {
+            attrs: {
+              label: "修改包装配置",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              clickChangePackaging(row);
+            },
+          },
           [40, 50].includes(row.status)
             ? {
                 attrs: {
@@ -327,6 +424,152 @@ const clickCancelHangUp = (row) => {
     })
     .catch(() => {});
 };
+const formData = reactive({
+  data: {
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
+  },
+});
+const rulesShippingPackage = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const openShippingPackage = ref(false);
+const loadingPackage = ref(false);
+const clickChangePackaging = (row) => {
+  loadingPackage.value = true;
+  openShippingPackage.value = true;
+  proxy.post("/orderInfo/detail", { id: row.id }).then(
+    (res) => {
+      formData.data = res;
+      proxy.post("/fileInfo/getList", { businessIdList: [formData.data.id] }).then((fileObj) => {
+        if (fileObj[formData.data.id] && fileObj[formData.data.id].length > 0) {
+          let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
+          if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
+            formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
+          } else {
+            formData.data.outerBoxSelfAdhesiveStickerFile = {};
+          }
+        }
+      });
+      loadingPackage.value = false;
+    },
+    (err) => {
+      console.log(err);
+      loadingPackage.value = false;
+    }
+  );
+};
+const computePackagingMoney = (item, label) => {
+  let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
+const clickPackagingDelete = (index) => {
+  formData.data.orderPackageBomList.splice(index, 1);
+};
+const openFile = (path) => {
+  window.open(path);
+};
+const uploadAdhesiveData = ref({});
+const uploadAdhesiveFile = async (file) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  uploadAdhesiveData.value = res.uploadBody;
+  file.id = res.id;
+  file.fileName = res.fileName;
+  file.fileUrl = res.fileUrl;
+  return true;
+};
+const handleAdhesivePackagingSuccess = (UploadFile) => {
+  formData.data.outerBoxSelfAdhesiveStickerFile = {
+    id: UploadFile.raw.id,
+    fileName: UploadFile.raw.fileName,
+    fileUrl: UploadFile.raw.fileUrl,
+  };
+};
+const clickSaveShippingPackage = () => {
+  proxy.$refs.shippingPackage.validate((valid) => {
+    if (valid) {
+      loadingPackage.value = true;
+      if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+        proxy
+          .post("/orderInfo/editOrderPackageBom", {
+            id: formData.data.id,
+            orderPackageBomList: formData.data.orderPackageBomList,
+            outerBoxSelfAdhesiveStickerFile: formData.data.outerBoxSelfAdhesiveStickerFile,
+          })
+          .then(
+            () => {
+              ElMessage({ message: "提交成功", type: "success" });
+              openShippingPackage.value = false;
+              getList();
+            },
+            (err) => {
+              console.log(err);
+              loadingPackage.value = false;
+            }
+          );
+      } else {
+        ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            proxy
+              .post("/orderInfo/editOrderPackageBom", {
+                id: formData.data.id,
+                orderPackageBomList: formData.data.orderPackageBomList,
+                outerBoxSelfAdhesiveStickerFile: formData.data.outerBoxSelfAdhesiveStickerFile,
+              })
+              .then(
+                () => {
+                  ElMessage({ message: "提交成功", type: "success" });
+                  openShippingPackage.value = false;
+                  getList();
+                },
+                (err) => {
+                  console.log(err);
+                  loadingPackage.value = false;
+                }
+              );
+          })
+          .catch(() => {});
+      }
+    }
+  });
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = () => {
+  openExpressPacking.value = true;
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+    let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递物流包材已添加");
+    }
+    formData.data.orderPackageBomList.push({
+      bomSpecId: data.id,
+      code: data.code,
+      name: data.name,
+      internalSellingPrice: data.internalSellingPrice,
+      quantity: undefined,
+    });
+  } else {
+    formData.data.orderPackageBomList = [
+      {
+        bomSpecId: data.id,
+        code: data.code,
+        name: data.name,
+        internalSellingPrice: data.internalSellingPrice,
+        quantity: undefined,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -334,4 +577,9 @@ const clickCancelHangUp = (row) => {
   margin-top: 10px !important;
   margin-bottom: 10px !important;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 311 - 22
src/views/subsidiary/order/management/add.vue

@@ -110,7 +110,7 @@
                                 :controls="false"
                                 :min="0"
                                 :precision="0"
-                                @change="changeQuantity(index)" />
+                                @change="changeQuantity(index, true)" />
                             </el-form-item>
                           </div>
                           <div style="line-height: 35px">
@@ -327,6 +327,15 @@
             </el-collapse>
           </div>
         </template>
+        <template #package>
+          <div style="width: 100%; padding: 0 20px">
+            <el-form :model="formData.data">
+              <el-form-item>
+                <el-button type="primary" size="small" @click="clickViewPackaging()" v-preReClick>产品包装配置</el-button>
+              </el-form-item>
+            </el-form>
+          </div>
+        </template>
         <template #deliveryTime>
           <div style="width: 100%">
             <el-date-picker
@@ -345,13 +354,10 @@
                 定制加工费: ¥{{ moneyFormat(calculatedAmount("customProcessingFee"), 2) }}
               </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">代发费: ¥{{ moneyFormat(calculatedAmount("lssueFee"), 2) }}</span>
-              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">
-                快递包材费: ¥{{ moneyFormat(calculatedAmount("deliveryMaterialsFee"), 2) }}
-              </span>
+              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">快递包材费: ¥{{ moneyFormat(computeDeliveryMaterialsFee(), 2) }} </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包装人工费: ¥{{ moneyFormat(calculatedAmount("packingLabor"), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包材费: ¥{{ moneyFormat(calculatedPackagingMaterialCost(), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">管理费: ¥{{ moneyFormat(calculatedAmount("managementFee"), 2) }}</span>
-              <!-- <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">外箱包装费: ¥{{ moneyFormat(calculatedOuterBoxPackingFee(), 2) }}</span> -->
             </div>
             <div style="padding: 8px 0 0 0">
               <span style="font-weight: 700; color: red">订单总金额(含税): ¥{{ moneyFormat(calculatedTotalAmount(), 2) }}</span>
@@ -385,7 +391,7 @@
         <el-button @click="clickCancel()" v-if="route.query && route.query.detailId" size="large">关 闭</el-button>
         <el-button @click="clickCancel()" v-if="!(route.query && route.query.detailId)" size="large">取 消</el-button>
         <el-button @click="submitForm('0')" v-if="!(route.query && route.query.detailId)" size="large" v-preReClick>暂 存</el-button>
-        <el-button type="primary" @click="submitForm('20')" v-if="!(route.query && route.query.detailId)" size="large" v-preReClick>提 交</el-button>
+        <el-button type="primary" @click="submitForm('20')" v-if="!(route.query && route.query.detailId)" size="large" v-preReClick>确认包装配置</el-button>
       </div>
     </el-card>
 
@@ -409,12 +415,128 @@
         <el-button @click="openDrawingFile = false" size="large">关 闭</el-button>
       </template>
     </el-dialog>
+
+    <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
+        <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
+          <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+          <div style="margin-bottom: 10px">
+            <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
+          </div>
+          <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="品号" prop="code" width="160" />
+            <el-table-column label="品名" prop="name" min-width="220" />
+            <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+            <el-table-column label="数量" width="120">
+              <template #default="{ row, $index }">
+                <div class="shippingPackage">
+                  <el-form-item
+                    :prop="'orderPackageBomList.' + $index + '.quantity'"
+                    :rules="rulesShippingPackage.quantity"
+                    :inline-message="true"
+                    style="width: 100%">
+                    <el-input-number
+                      onmousewheel="return false;"
+                      v-model="row.quantity"
+                      placeholder="修正数量"
+                      style="width: 100%"
+                      :controls="false"
+                      :min="0"
+                      :precision="0" />
+                  </el-form-item>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="销售小计" width="120">
+              <template #default="{ row }">
+                {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="80">
+              <template #default="{ $index }">
+                <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+          <div style="display: flex; width: 100%">
+            <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+            <div style="width: calc(100% - 80px)">
+              <el-image
+                fit="scale-down"
+                style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+                v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+              <div style="display: flex">
+                <el-upload
+                  :show-file-list="false"
+                  action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                  :data="uploadAdhesiveData"
+                  :before-upload="uploadAdhesiveFile"
+                  :on-success="
+                    (response, uploadFile) => {
+                      return handleAdhesivePackagingSuccess(uploadFile);
+                    }
+                  "
+                  style="width: 100%">
+                  <el-button type="primary" text>上传文件</el-button>
+                </el-upload>
+              </div>
+            </div>
+          </div>
+        </el-form>
+      </div>
+      <template #footer>
+        <el-button @click="openShippingPackage = false" v-preReClick>关 闭</el-button>
+        <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提交订单</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
+      <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="包装配置" v-if="openViewPackaging" v-model="openViewPackaging" width="80%">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
+        <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+        <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+          <el-table-column label="品号" prop="code" width="160" />
+          <el-table-column label="品名" prop="name" min-width="220" />
+          <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+          <el-table-column label="数量" prop="quantity" width="120" />
+          <el-table-column label="销售小计" width="120">
+            <template #default="{ row }">
+              {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+            </template>
+          </el-table-column>
+        </el-table>
+        <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+        <div style="display: flex; width: 100%">
+          <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+          <div style="width: calc(100% - 80px)">
+            <el-image
+              fit="scale-down"
+              style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+              v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+              :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+              @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <el-button @click="openViewPackaging = false">关 闭</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
 import byForm from "/src/components/byForm/index";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import Editor from "/src/components/Editor/index.vue";
 import { useRouter, useRoute } from "vue-router";
 import SelectProduct from "/src/views/group/product/management/index";
@@ -443,6 +565,8 @@ const formData = reactive({
     type: 1,
     orderSkuList: [],
     fileList: [],
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
   },
 });
 const formConfig = computed(() => {
@@ -457,6 +581,19 @@ const formConfig = computed(() => {
       prop: "orderSkuList",
       slotName: "orderSkuList",
     },
+    route.query && route.query.detailId
+      ? {
+          type: "title",
+          title: "产品包装配置",
+          label: "",
+        }
+      : {},
+    route.query && route.query.detailId
+      ? {
+          type: "slot",
+          slotName: "package",
+        }
+      : {},
     {
       type: "title",
       title: "类型",
@@ -628,10 +765,12 @@ const updatePackageRemark = (val, index) => {
 };
 const clickDelete = (index) => {
   formData.data.orderSkuList.splice(index, 1);
+  getShippingPackage();
 };
 const updateValue = (val) => {
   formData.data.remark = val;
 };
+const openShippingPackage = ref(false);
 const submitForm = (status) => {
   submit.value.handleSubmit(() => {
     if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
@@ -663,10 +802,9 @@ const submitForm = (status) => {
       formData.data.productTotalAmount = calculatedAmount("unitPrice");
       formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
       formData.data.lssueFee = calculatedAmount("lssueFee");
-      formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+      formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
       formData.data.packingLabor = calculatedAmount("packingLabor");
       formData.data.managementFee = calculatedAmount("managementFee");
-      // formData.data.outerBoxPackingFee = calculatedOuterBoxPackingFee();
       formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
       formData.data.totalAmount = calculatedTotalAmount();
       if (fileList.value && fileList.value.length > 0) {
@@ -686,14 +824,10 @@ const submitForm = (status) => {
         formData.data.fileList = [];
       }
       formData.data.status = status;
-      let type = "add";
-      if (formData.data.id && status == "20") {
-        proxy.post("/orderInfo/confirmation", formData.data).then(() => {
-          ElMessage({ message: "提交成功", type: "success" });
-          refreshStore().setRefresh("order");
-          clickCancel();
-        });
+      if (status == "20") {
+        openShippingPackage.value = true;
       } else {
+        let type = "add";
         if (formData.data.id) {
           type = "edit";
         }
@@ -776,6 +910,12 @@ const getOrderDetail = (parameter) => {
           } else {
             fileList.value = [];
           }
+          let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
+          if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
+            formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
+          } else {
+            formData.data.outerBoxSelfAdhesiveStickerFile = {};
+          }
         }
         for (let i = 0; i < formData.data.orderSkuList.length; i++) {
           if (fileObj[formData.data.orderSkuList[i].id] && fileObj[formData.data.orderSkuList[i].id].length > 0) {
@@ -910,7 +1050,7 @@ const selectPackingFittings = (data) => {
   }
   ElMessage({ message: "添加成功", type: "success" });
 };
-const changeQuantity = (index) => {
+const changeQuantity = (index, status) => {
   if (formData.data.orderSkuList[index].quantity) {
     proxy
       .post("/orderInfo/getSkuSpecPrice", { skuSpecId: formData.data.orderSkuList[index].skuSpecId, quantity: formData.data.orderSkuList[index].quantity })
@@ -927,6 +1067,9 @@ const changeQuantity = (index) => {
         formData.data.orderSkuList[index].managementFee = res.managementFee;
         formData.data.orderSkuList[index].unitPrice = res.unitPrice;
       });
+    if (status) {
+      getShippingPackage();
+    }
   }
 };
 const cellStyleName = ({ column, columnIndex }) => {
@@ -1039,10 +1182,9 @@ const calculatedTotalAmount = () => {
       (calculatedAmount("unitPrice") +
         calculatedAmount("customProcessingFee") +
         calculatedAmount("lssueFee") +
-        calculatedAmount("deliveryMaterialsFee") +
+        computeDeliveryMaterialsFee() +
         calculatedAmount("packingLabor") +
         calculatedAmount("managementFee") +
-        // calculatedOuterBoxPackingFee() +
         calculatedPackagingMaterialCost()) *
         100
     ) / 100
@@ -1082,17 +1224,159 @@ const handleAdhesiveSuccess = (UploadFile, index) => {
     fileUrl: UploadFile.raw.fileUrl,
   };
 };
-const calculatedOuterBoxPackingFee = () => {
+const formShippingPackage = reactive({
+  data: {
+    assemblyName: "",
+  },
+});
+const rulesShippingPackage = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const computePackagingMoney = (item, label) => {
   let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
+const clickPackagingDelete = (index) => {
+  formData.data.orderPackageBomList.splice(index, 1);
+};
+const handleAdhesivePackagingSuccess = (UploadFile) => {
+  formData.data.outerBoxSelfAdhesiveStickerFile = {
+    id: UploadFile.raw.id,
+    fileName: UploadFile.raw.fileName,
+    fileUrl: UploadFile.raw.fileUrl,
+  };
+};
+const clickSaveShippingPackage = () => {
+  proxy.$refs.shippingPackage.validate((valid) => {
+    if (valid) {
+      if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+        formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
+        formData.data.totalAmount = calculatedTotalAmount();
+        let type = "add";
+        if (formData.data.id && status == "20") {
+          proxy.post("/orderInfo/confirmation", formData.data).then(() => {
+            ElMessage({ message: "提交成功", type: "success" });
+            refreshStore().setRefresh("order");
+            clickCancel();
+          });
+        } else {
+          if (formData.data.id) {
+            type = "edit";
+          }
+          proxy.post("/orderInfo/" + type, formData.data).then(() => {
+            ElMessage({
+              message: type == "add" ? "添加成功" : "编辑成功",
+              type: "success",
+            });
+            refreshStore().setRefresh("order");
+            clickCancel();
+          });
+        }
+      } else {
+        ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
+            formData.data.totalAmount = calculatedTotalAmount();
+            let type = "add";
+            if (formData.data.id) {
+              type = "edit";
+            }
+            proxy.post("/orderInfo/" + type, formData.data).then(() => {
+              ElMessage({
+                message: type == "add" ? "添加成功" : "编辑成功",
+                type: "success",
+              });
+              refreshStore().setRefresh("order");
+              clickCancel();
+            });
+          })
+          .catch(() => {});
+      }
+    }
+  });
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = () => {
+  openExpressPacking.value = true;
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+    let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递物流包材已添加");
+    }
+    formData.data.orderPackageBomList.push({
+      bomSpecId: data.id,
+      code: data.code,
+      name: data.name,
+      internalSellingPrice: data.internalSellingPrice,
+      quantity: undefined,
+    });
+  } else {
+    formData.data.orderPackageBomList = [
+      {
+        bomSpecId: data.id,
+        code: data.code,
+        name: data.name,
+        internalSellingPrice: data.internalSellingPrice,
+        quantity: undefined,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
+const getShippingPackage = () => {
+  let skuSpecList = formData.data.orderSkuList.filter((item) => item.quantity && item.quantity > 0);
+  if (skuSpecList && skuSpecList.length > 0) {
+    skuSpecList = skuSpecList.map((item) => {
+      return {
+        skuSpecId: item.skuSpecId,
+        quantity: item.quantity,
+      };
+    });
+    proxy.post("/orderInfo/getSkuSpecPackageBomList", { skuSpecList: skuSpecList }).then((res) => {
+      if (res && res.length > 0) {
+        formData.data.orderPackageBomList = res.map((item) => {
+          return {
+            bomSpecId: item.bomSpecId,
+            code: item.bomSpecCode,
+            name: item.bomSpecName,
+            internalSellingPrice: item.internalSellingPrice,
+            quantity: item.quantity,
+          };
+        });
+      } else {
+        formData.data.orderPackageBomList = [];
+      }
+    });
+  } else {
+    formData.data.orderPackageBomList = [];
+  }
+};
+const computeDeliveryMaterialsFee = () => {
+  let money = calculatedAmount("deliveryMaterialsFee");
   if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
     for (let i = 0; i < formData.data.orderPackageBomList.length; i++) {
-      if (formData.data.orderPackageBomList[i].costPrice && formData.data.orderPackageBomList[i].quantity) {
-        money = Number(Math.round((money + formData.data.orderPackageBomList[i].costPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100);
+      if (formData.data.orderPackageBomList[i].internalSellingPrice && formData.data.orderPackageBomList[i].quantity) {
+        money = Number(
+          Math.round((money + formData.data.orderPackageBomList[i].internalSellingPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100
+        );
       }
     }
   }
   return money;
 };
+const openViewPackaging = ref(false);
+const clickViewPackaging = () => {
+  openViewPackaging.value = true;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -1118,4 +1402,9 @@ const calculatedOuterBoxPackingFee = () => {
 :deep(.vertical-align) {
   vertical-align: middle;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 196 - 19
src/views/subsidiary/order/management/design.vue

@@ -275,13 +275,10 @@
                 定制加工费: ¥{{ moneyFormat(calculatedAmount("customProcessingFee"), 2) }}
               </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">代发费: ¥{{ moneyFormat(calculatedAmount("lssueFee"), 2) }}</span>
-              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">
-                快递包材费: ¥{{ moneyFormat(calculatedAmount("deliveryMaterialsFee"), 2) }}
-              </span>
+              <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">快递包材费: ¥{{ moneyFormat(computeDeliveryMaterialsFee(), 2) }} </span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包装人工费: ¥{{ moneyFormat(calculatedAmount("packingLabor"), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">包材费: ¥{{ moneyFormat(calculatedPackagingMaterialCost(), 2) }}</span>
               <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">管理费: ¥{{ moneyFormat(calculatedAmount("managementFee"), 2) }}</span>
-              <!-- <span style="font-weight: 700; color: #6c88f1; margin-left: 40px">外箱包装费: ¥{{ moneyFormat(calculatedOuterBoxPackingFee(), 2) }}</span> -->
             </div>
             <div style="padding: 8px 0 0 0">
               <span style="font-weight: 700; color: red">订单总金额(含税): ¥{{ moneyFormat(calculatedTotalAmount(), 2) }}</span>
@@ -327,12 +324,96 @@
         <el-button @click="openPackingFittings = false" size="large">关 闭</el-button>
       </template>
     </el-dialog>
+
+    <el-dialog title="产品包装配置" v-if="openShippingPackage" v-model="openShippingPackage" width="80%" :close-on-press-escape="false" :show-close="false">
+      <div style="height: calc(100vh - 184px); overflow-y: auto; overflow-x: hidden">
+        <el-form :model="formData.data" :rules="rulesShippingPackage" ref="shippingPackage">
+          <div style="font-weight: 700; margin: 20px 0 10px 0">发货包装</div>
+          <div style="margin-bottom: 10px">
+            <el-button type="primary" size="small" @click="clickExpressPacking()">选择包材</el-button>
+          </div>
+          <el-table :data="formData.data.orderPackageBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="品号" prop="code" width="160" />
+            <el-table-column label="品名" prop="name" min-width="220" />
+            <el-table-column label="销售单价" prop="internalSellingPrice" width="100" />
+            <el-table-column label="数量" width="120">
+              <template #default="{ row, $index }">
+                <div class="shippingPackage">
+                  <el-form-item
+                    :prop="'orderPackageBomList.' + $index + '.quantity'"
+                    :rules="rulesShippingPackage.quantity"
+                    :inline-message="true"
+                    style="width: 100%">
+                    <el-input-number
+                      onmousewheel="return false;"
+                      v-model="row.quantity"
+                      placeholder="修正数量"
+                      style="width: 100%"
+                      :controls="false"
+                      :min="0"
+                      :precision="0" />
+                  </el-form-item>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="销售小计" width="120">
+              <template #default="{ row }">
+                {{ moneyFormat(computePackagingMoney(row, "internalSellingPrice"), 2) }}
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" width="80">
+              <template #default="{ $index }">
+                <el-button type="danger" @click="clickPackagingDelete($index)" text>删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div style="font-weight: 700; margin: 20px 0 10px 0">外箱不干胶图稿</div>
+          <div style="display: flex; width: 100%">
+            <div style="width: 80px; line-height: 32px">不干胶图片:</div>
+            <div style="width: calc(100% - 80px)">
+              <el-image
+                fit="scale-down"
+                style="width: 148px; height: 148px; margin-right: 10px; cursor: pointer"
+                v-if="formData.data.outerBoxSelfAdhesiveStickerFile && formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                :src="formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl"
+                @click="openFile(formData.data.outerBoxSelfAdhesiveStickerFile.fileUrl)" />
+              <div style="display: flex">
+                <el-upload
+                  :show-file-list="false"
+                  action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                  :data="uploadAdhesiveData"
+                  :before-upload="uploadAdhesiveFile"
+                  :on-success="
+                    (response, uploadFile) => {
+                      return handleAdhesivePackagingSuccess(uploadFile);
+                    }
+                  "
+                  style="width: 100%">
+                  <el-button type="primary" text>上传文件</el-button>
+                </el-upload>
+              </div>
+            </div>
+          </div>
+        </el-form>
+      </div>
+      <template #footer>
+        <el-button @click="openShippingPackage = false" v-preReClick>关 闭</el-button>
+        <el-button type="primary" @click="clickSaveShippingPackage" v-preReClick>提交订单</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="90%">
+      <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false">关 闭</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
 import byForm from "/src/components/byForm/index";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import { useRouter, useRoute } from "vue-router";
 import useTagsViewStore from "/src/store/modules/tagsView";
 import SelectPicture from "/src/components/select-picture/index.vue";
@@ -359,6 +440,8 @@ const formData = reactive({
     type: 1,
     orderSkuList: [],
     fileList: [],
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
   },
 });
 const formConfig = computed(() => {
@@ -511,6 +594,7 @@ const selectPic = (row) => {
 const openFile = (path) => {
   window.open(path);
 };
+const openShippingPackage = ref(false);
 const submitForm = (status) => {
   submit.value.handleSubmit(() => {
     if (formData.data.orderSkuList && formData.data.orderSkuList.length > 0) {
@@ -542,10 +626,9 @@ const submitForm = (status) => {
       formData.data.productTotalAmount = calculatedAmount("unitPrice");
       formData.data.customProcessingFee = calculatedAmount("customProcessingFee");
       formData.data.lssueFee = calculatedAmount("lssueFee");
-      formData.data.deliveryMaterialsFee = calculatedAmount("deliveryMaterialsFee");
+      formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
       formData.data.packingLabor = calculatedAmount("packingLabor");
       formData.data.managementFee = calculatedAmount("managementFee");
-      // formData.data.outerBoxPackingFee = calculatedOuterBoxPackingFee();
       formData.data.packagingMaterialCost = calculatedPackagingMaterialCost();
       formData.data.totalAmount = calculatedTotalAmount();
       if (fileList.value && fileList.value.length > 0) {
@@ -560,11 +643,7 @@ const submitForm = (status) => {
         formData.data.fileList = [];
       }
       formData.data.status = status;
-      proxy.post("/orderInfo/confirmation", formData.data).then(() => {
-        ElMessage({ message: "提交成功", type: "success" });
-        refreshStore().setRefresh("order");
-        clickCancel();
-      });
+      openShippingPackage.value = true;
     } else {
       return ElMessage("请添加产品");
     }
@@ -618,6 +697,12 @@ const getOrderDetail = (parameter) => {
           } else {
             fileList.value = [];
           }
+          let outerBoxSelfAdhesiveStickerFile = fileObj[formData.data.id].filter((item) => item.businessType == "1");
+          if (outerBoxSelfAdhesiveStickerFile && outerBoxSelfAdhesiveStickerFile.length > 0) {
+            formData.data.outerBoxSelfAdhesiveStickerFile = outerBoxSelfAdhesiveStickerFile[0];
+          } else {
+            formData.data.outerBoxSelfAdhesiveStickerFile = {};
+          }
         }
         for (let i = 0; i < formData.data.orderSkuList.length; i++) {
           if (fileObj[formData.data.orderSkuList[i].id] && fileObj[formData.data.orderSkuList[i].id].length > 0) {
@@ -670,7 +755,7 @@ const uploadFile = async (file) => {
 };
 const handleSuccess = (UploadFile, index) => {
   formData.data.orderSkuList[index].productionDocument = UploadFile.raw.fileUrl;
-  formData.data.orderSkuList[index].artworkLibraryId = '0';
+  formData.data.orderSkuList[index].artworkLibraryId = "0";
 };
 const uploadImgData = ref({});
 const uploadImgFile = async (file) => {
@@ -683,7 +768,7 @@ const uploadImgFile = async (file) => {
 };
 const handleImgSuccess = (UploadFile, index) => {
   formData.data.orderSkuList[index].blueprint = UploadFile.raw.fileUrl;
-  formData.data.orderSkuList[index].artworkLibraryId = '0';
+  formData.data.orderSkuList[index].artworkLibraryId = "0";
 };
 const computeQuantity = (index, indexSKU) => {
   let quantity = 0;
@@ -797,10 +882,9 @@ const calculatedTotalAmount = () => {
       (calculatedAmount("unitPrice") +
         calculatedAmount("customProcessingFee") +
         calculatedAmount("lssueFee") +
-        calculatedAmount("deliveryMaterialsFee") +
+        computeDeliveryMaterialsFee() +
         calculatedAmount("packingLabor") +
         calculatedAmount("managementFee") +
-        // calculatedOuterBoxPackingFee() +
         calculatedPackagingMaterialCost()) *
         100
     ) / 100
@@ -840,12 +924,100 @@ const handleAdhesiveSuccess = (UploadFile, index) => {
     fileUrl: UploadFile.raw.fileUrl,
   };
 };
-const calculatedOuterBoxPackingFee = () => {
+const formShippingPackage = reactive({
+  data: {
+    assemblyName: "",
+  },
+});
+const rulesShippingPackage = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const computePackagingMoney = (item, label) => {
   let money = 0;
+  if (item.quantity && item[label]) {
+    money = Number(Math.round(item.quantity * item[label] * 100) / 100);
+  }
+  return money;
+};
+const clickPackagingDelete = (index) => {
+  formData.data.orderPackageBomList.splice(index, 1);
+};
+const handleAdhesivePackagingSuccess = (UploadFile) => {
+  formData.data.outerBoxSelfAdhesiveStickerFile = {
+    id: UploadFile.raw.id,
+    fileName: UploadFile.raw.fileName,
+    fileUrl: UploadFile.raw.fileUrl,
+  };
+};
+const clickSaveShippingPackage = () => {
+  proxy.$refs.shippingPackage.validate((valid) => {
+    if (valid) {
+      if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+        formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
+        formData.data.totalAmount = calculatedTotalAmount();
+        proxy.post("/orderInfo/confirmation", formData.data).then(() => {
+          ElMessage({ message: "提交成功", type: "success" });
+          refreshStore().setRefresh("order");
+          clickCancel();
+        });
+      } else {
+        ElMessageBox.confirm("是否确认无产品发货包装", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            formData.data.deliveryMaterialsFee = computeDeliveryMaterialsFee();
+            formData.data.totalAmount = calculatedTotalAmount();
+            proxy.post("/orderInfo/confirmation", formData.data).then(() => {
+              ElMessage({ message: "提交成功", type: "success" });
+              refreshStore().setRefresh("order");
+              clickCancel();
+            });
+          })
+          .catch(() => {});
+      }
+    }
+  });
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = () => {
+  openExpressPacking.value = true;
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
+    let list = formData.data.orderPackageBomList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递物流包材已添加");
+    }
+    formData.data.orderPackageBomList.push({
+      bomSpecId: data.id,
+      code: data.code,
+      name: data.name,
+      internalSellingPrice: data.internalSellingPrice,
+      quantity: undefined,
+    });
+  } else {
+    formData.data.orderPackageBomList = [
+      {
+        bomSpecId: data.id,
+        code: data.code,
+        name: data.name,
+        internalSellingPrice: data.internalSellingPrice,
+        quantity: undefined,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
+const computeDeliveryMaterialsFee = () => {
+  let money = calculatedAmount("deliveryMaterialsFee");
   if (formData.data.orderPackageBomList && formData.data.orderPackageBomList.length > 0) {
     for (let i = 0; i < formData.data.orderPackageBomList.length; i++) {
-      if (formData.data.orderPackageBomList[i].costPrice && formData.data.orderPackageBomList[i].quantity) {
-        money = Number(Math.round((money + formData.data.orderPackageBomList[i].costPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100);
+      if (formData.data.orderPackageBomList[i].internalSellingPrice && formData.data.orderPackageBomList[i].quantity) {
+        money = Number(
+          Math.round((money + formData.data.orderPackageBomList[i].internalSellingPrice * formData.data.orderPackageBomList[i].quantity) * 100) / 100
+        );
       }
     }
   }
@@ -873,4 +1045,9 @@ const calculatedOuterBoxPackingFee = () => {
 :deep(.el-table__cell) {
   vertical-align: top;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>