Procházet zdrojové kódy

Merge branch 'master' into 对账单-导出货物交接单

lxf před 1 rokem
rodič
revize
96b8f83707
40 změnil soubory, kde provedl 2291 přidání a 451 odebrání
  1. 65 91
      src/components/byTable/ElementsMapping.vue
  2. 2 1
      src/components/byTable/index.vue
  3. 5 4
      src/components/makeProduct/modification/index.vue
  4. 5 4
      src/components/makeProduct/modification/subsidiary.vue
  5. 1 1
      src/router/index.js
  6. 3 39
      src/views/group/data-board/daily-board/index.vue
  7. 5 4
      src/views/group/data-board/material-control-purchasing/index.vue
  8. 11 2
      src/views/group/data-board/material-in-transit/index.vue
  9. 11 2
      src/views/group/data-board/sku-quoted-price/index.vue
  10. 19 4
      src/views/group/data-board/turnover-rate/index.vue
  11. 11 2
      src/views/group/finance/check-bill/printBOM.vue
  12. 11 2
      src/views/group/finance/check-bill/printSKU.vue
  13. 1 10
      src/views/group/finance/purchase-warehousing/index.vue
  14. 11 2
      src/views/group/finance/sales-return/index.vue
  15. 1 10
      src/views/group/finance/sales-revenue-cost/index.vue
  16. 1 10
      src/views/group/finance/summary/index.vue
  17. 11 2
      src/views/group/finance/summary/printBOM.vue
  18. 11 2
      src/views/group/finance/summary/printSKU.vue
  19. 5 4
      src/views/group/limits-authority/role/index.vue
  20. 88 17
      src/views/group/order/management/detail.vue
  21. 289 58
      src/views/group/order/management/index.vue
  22. 17 3
      src/views/group/purchase/supplier/index.vue
  23. 120 51
      src/views/production/operation/batching/index.vue
  24. 288 0
      src/views/production/operation/lose-the-delivery/index.vue
  25. 1 1
      src/views/production/operation/production-error/index.vue
  26. 314 0
      src/views/production/operation/supplementary-order/index.vue
  27. 249 1
      src/views/production/schedule/order-inquiry/index.vue
  28. 5 4
      src/views/production/schedule/production-order/index.vue
  29. 103 47
      src/views/production/schedule/production-work-order/index.vue
  30. 5 4
      src/views/production/shipment/print-order/index.vue
  31. 11 1
      src/views/production/warehouse/check/index.vue
  32. 14 4
      src/views/production/warehouse/finished-parts-storage/index.vue
  33. 11 2
      src/views/production/warehouse/flow-record/index.vue
  34. 21 3
      src/views/production/warehouse/inventory/index.vue
  35. 13 2
      src/views/production/warehouse/outbound/index.vue
  36. 13 2
      src/views/production/warehouse/putInStorage/index.vue
  37. 1 10
      src/views/subsidiary/finance/summary/index.vue
  38. 321 23
      src/views/subsidiary/order/management/add.vue
  39. 206 20
      src/views/subsidiary/order/management/design.vue
  40. 11 2
      src/views/subsidiary/warehouse/inventory/index.vue

+ 65 - 91
src/components/byTable/ElementsMapping.vue

@@ -1,20 +1,16 @@
 <template>
   <div>
-    
-    <el-button v-for="(i,index) in getCellList"  @click="i.click()" :key="index" v-bind="i.attrs" v-show="index < 2">{{ i.attrs.label }}</el-button>
+    <el-button v-for="(i, index) in getCellList" @click="i.click()" :key="index" v-bind="i.attrs" v-show="index < btnNum - 1">
+      {{ i.attrs.label }}
+    </el-button>
     <el-dropdown>
       <span class="el-dropdown-link">
         <span class="more-btn">更多</span>
-        
       </span>
       <template #dropdown>
         <el-dropdown-menu>
-          <el-dropdown-item 
-            :class="index > 1 ? '' : 'dn'" 
-            @click="i.click()" v-for="(i,index) in getCellList" 
-            
-            :key="index" >
-            <span :style="i.attrs.type == 'danger' ? 'color:red' : 'color:#409eff'">{{ i.attrs.label}}</span>
+          <el-dropdown-item :class="index > btnNum - 2 ? '' : 'dn'" @click="i.click()" v-for="(i, index) in getCellList" :key="index">
+            <span :style="i.attrs.type == 'danger' ? 'color:red' : 'color:#409eff'">{{ i.attrs.label }}</span>
           </el-dropdown-item>
         </el-dropdown-menu>
       </template>
@@ -22,121 +18,99 @@
   </div>
 </template>
 <script>
-import {
-  defineComponent,
-  getCurrentInstance,
-  computed,
-  ref,
-  h,
-  withDirectives,
-  resolveDirective,
-  resolveComponent
-} from 'vue'
+import { defineComponent, getCurrentInstance, computed, ref, h, withDirectives, resolveDirective, resolveComponent } from "vue";
 export default defineComponent({
   props: {
     parent: {
       type: Object,
-      default () {
-        return {}
-      }
+      default() {
+        return {};
+      },
     },
     row: {
       type: Object,
-      default () {
-        return {}
-      }
+      default() {
+        return {};
+      },
     },
     cellList: {
       type: Array,
-      default () {
-        return []
-      }
-    }
+      default() {
+        return [];
+      },
+    },
+    btnNum: {
+      type: Number,
+      default() {
+        return 3;
+      },
+    },
   },
-  setup (props) {
-    const { proxy } = getCurrentInstance()
-    
-    proxy.$.components = props.parent.$options.components
-    proxy.$.directives = props.parent.$options.directives
+  setup(props) {
+    const { proxy } = getCurrentInstance();
+    proxy.$.components = props.parent.$options.components;
+    proxy.$.directives = props.parent.$options.directives;
     const elementsMapping = ref({
-      button: 'el-button'
-    })
+      button: "el-button",
+    });
     const getCellList = computed(() => {
-      return props.cellList.filter((cell) => cell && Object.keys(cell).length)
-    })
+      return props.cellList.filter((cell) => cell && Object.keys(cell).length);
+    });
     const getAttrsValue = (item) => {
       if (!item.attrs) {
-        item.attrs = {}
+        item.attrs = {};
       }
-      const {
-        class: className = null,
-        style = null,
-        directives = null,
-        ...attrs
-      } = item.attrs
+      const { class: className = null, style = null, directives = null, ...attrs } = item.attrs;
       return {
         class: className,
         style,
         directives,
-        props: attrs
-      }
-    }
-    if(getCellList.value.length > 3) {
+        props: attrs,
+      };
+    };
+    if (getCellList.value.length > props.btnNum) {
       return {
-        getCellList
-      }
+        getCellList,
+      };
     }
     return () => {
       return h(
-        'div',
+        "div",
         getCellList.value.map((cellItem) => {
-          const comp = resolveComponent(
-            elementsMapping.value[cellItem.el] ||
-            cellItem.el
-          )
-          const attributes = getAttrsValue(cellItem)
-          const { label, ...others } = attributes.props
-          const { directives } = attributes
-          let onClick
+          const comp = resolveComponent(elementsMapping.value[cellItem.el] || cellItem.el);
+          const attributes = getAttrsValue(cellItem);
+          const { label, ...others } = attributes.props;
+          const { directives } = attributes;
+          let onClick;
           if (cellItem.click) {
-            onClick = cellItem.click.bind(props.parent, props.row)
+            onClick = cellItem.click.bind(props.parent, props.row);
           }
-          let resultVNode = h(
-            comp,
-            {
-              onClick,
-              innerHTML: label,
-              ...others
-            }
-          )
+          let resultVNode = h(comp, {
+            onClick,
+            innerHTML: label,
+            ...others,
+          });
           if (directives) {
-            resultVNode = withDirectives(
-              resultVNode,
-              [
-                ...directives.map((directiveItem) => {
-                  return [
-                    resolveDirective(directiveItem.name),
-                    directiveItem.value,
-                    directiveItem.arg
-                  ]
-                })
-              ]
-            )
+            resultVNode = withDirectives(resultVNode, [
+              ...directives.map((directiveItem) => {
+                return [resolveDirective(directiveItem.name), directiveItem.value, directiveItem.arg];
+              }),
+            ]);
           }
-          return resultVNode
+          return resultVNode;
         })
-      )
-    }
-  }
-})
+      );
+    };
+  },
+});
 </script>
 <style>
-.more-btn{
+.more-btn {
   line-height: 34px;
   font-size: 14px;
-  color:#FF9315;
+  color: #ff9315;
 }
-.dn{
-  display: none!important;
+.dn {
+  display: none !important;
 }
-</style>
+</style>

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

@@ -145,7 +145,8 @@
                   ($event) => {
                     handleNativeClick(getAttrsValue(item), $event, item);
                   }
-                " />
+                "
+                :key="scope.row.id" />
             </div>
             <div v-else>
               {{ getValue(scope, item) }}

+ 5 - 4
src/components/makeProduct/modification/index.vue

@@ -123,7 +123,12 @@ const searchConfig = computed(() => {
 const config = computed(() => {
   return [];
 });
+const selectData = ref([]);
+const handleBOM = () => {
+  openBOM.value = true;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -152,10 +157,6 @@ const handleSizeChange = (val) => {
   getList({ pageNum: 1, pageSize: val });
 };
 const openBOM = ref(false);
-const selectData = ref([]);
-const handleBOM = () => {
-  openBOM.value = true;
-};
 const selectBOM = (item) => {
   selectData.value = [item];
   ElMessage({ message: "选择完成", type: "success" });

+ 5 - 4
src/components/makeProduct/modification/subsidiary.vue

@@ -139,7 +139,12 @@ const searchConfig = computed(() => {
 const config = computed(() => {
   return [];
 });
+const selectData = ref([]);
+const handleBOM = () => {
+  openBOM.value = true;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -168,10 +173,6 @@ const handleSizeChange = (val) => {
   getList({ pageNum: 1, pageSize: val });
 };
 const openBOM = ref(false);
-const selectData = ref([]);
-const handleBOM = () => {
-  openBOM.value = true;
-};
 const selectBOM = (item) => {
   selectData.value = [item];
   ElMessage({ message: "选择完成", type: "success" });

+ 1 - 1
src/router/index.js

@@ -209,7 +209,7 @@ export const constantRoutes = [
     children: [
       {
         path: "/outbound/packing-materials/add",
-        name: "add-outbound",
+        name: "add-packing-outbound",
         component: () => import(/* webpackChunkName: "page" */ "@/views/production/warehouse/outbound/packing-materials/add.vue"),
         props: true,
         meta: { title: "包材出库" },

+ 3 - 39
src/views/group/data-board/daily-board/index.vue

@@ -12,6 +12,9 @@
             value-format="YYYY-MM-DD"
             @change="changeTime" />
         </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="changeTime()" size="small" v-preReClick>刷新</el-button>
+        </el-form-item>
       </el-form>
     </el-card>
     <el-row :gutter="10" style="padding-top: 10px">
@@ -299,45 +302,6 @@
         </el-card>
       </el-col>
     </el-row>
-    <!-- <div style="padding-top: 10px">
-      <el-card v-loading="bottomCenter">
-        <div class="cardTitle">MES今日自建订单数据</div>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <div class="firstRowBoard">
-              <span style="font-size: 16px !important">自建订单总数(单)</span>
-              <span style="font-weight: 700; font-size: 20px !important">{{ BCData.sumOrderCount }}</span>
-            </div>
-          </el-col>
-          <el-col :span="8">
-            <div class="firstRowBoard">
-              <span style="font-size: 16px !important">自建订单BOM总数(个)</span>
-              <span style="font-weight: 700; font-size: 20px !important">{{ BCData.sumBomCount }}</span>
-            </div>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20" v-if="BCData.outStorageBomList && BCData.outStorageBomList.length > 0">
-          <el-col :span="8" style="margin-top: 20px" v-for="(item, index) in BCData.outStorageBomList" :key="index">
-            <el-row :gutter="2">
-              <el-col :span="8">
-                <div style="background-color: #eeeeee; padding: 20px">BOM编号</div>
-              </el-col>
-              <el-col :span="16">
-                <div style="background-color: #eeeeee; padding: 20px">{{ item.bomSpecCode }}</div>
-              </el-col>
-            </el-row>
-            <el-row :gutter="2" style="margin-top: 2px">
-              <el-col :span="8">
-                <div style="background-color: #eeeeee; padding: 20px">数量</div>
-              </el-col>
-              <el-col :span="16">
-                <div style="background-color: #eeeeee; padding: 20px">{{ item.quantity }}</div>
-              </el-col>
-            </el-row>
-          </el-col>
-        </el-row>
-      </el-card>
-    </div> -->
   </div>
 </template>
 

+ 5 - 4
src/views/group/data-board/material-control-purchasing/index.vue

@@ -231,7 +231,12 @@ const config = computed(() => {
     },
   ];
 });
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -264,10 +269,6 @@ getList();
 const clickReset = () => {
   getList("", true);
 };
-const selectData = ref([]);
-const selectRow = (data) => {
-  selectData.value = data;
-};
 const cellClassName = ({ columnIndex, row }) => {
   if (columnIndex === 3 && row.inventoryQuantity < row.safetyInventoryQuantity) {
     return "colorDim";

+ 11 - 2
src/views/group/data-board/material-in-transit/index.vue

@@ -30,7 +30,7 @@
 <script setup>
 import byTable from "/src/components/byTable/index";
 import moment from "moment";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 
 const { proxy } = getCurrentInstance();
 const sourceList = ref({
@@ -155,7 +155,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/purchaseInTransitBom/export", sourceList.value.pagination).then((res) => {
-        proxy.downloadFile(res, "在途物料-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "在途物料-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 11 - 2
src/views/group/data-board/sku-quoted-price/index.vue

@@ -38,7 +38,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -193,7 +193,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/skuSpecQuotationBoard/exportExcel", sourceList.value.pagination).then((res) => {
-        proxy.downloadFile(res, "SKU报价看板-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "SKU报价看板-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 19 - 4
src/views/group/data-board/turnover-rate/index.vue

@@ -75,7 +75,7 @@
 <script setup>
 import byTable from "/src/components/byTable/index";
 import { nextTick } from "vue";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -87,11 +87,17 @@ const sourceList = ref({
     width: "",
     height: "",
     chromatophore: "",
+    bomSpecName: "",
   },
 });
 const searchConfig = computed(() => {
   return [
     {
+      type: "input",
+      prop: "bomSpecName",
+      label: "BOM品名",
+    },
+    {
       type: "select",
       prop: "width",
       dictKey: "width_size",
@@ -236,10 +242,19 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/turnoverRateBoard/exportExcel", { bomClassify: activeName.value, ...sourceList.value.pagination }).then((res) => {
-        if (activeName.value == "1") {
-          proxy.downloadFile(res, "周转率-裸垫-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
         } else {
-          proxy.downloadFile(res, "周转率-裸砖-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          if (activeName.value == "1") {
+            proxy.downloadFile(res, "周转率-裸垫-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          } else {
+            proxy.downloadFile(res, "周转率-裸砖-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          }
         }
       });
     })

+ 11 - 2
src/views/group/finance/check-bill/printBOM.vue

@@ -192,8 +192,17 @@ const deriveExcel = () => {
   loading.value = true;
   proxy.getFile("/statementOfAccount/exportDocumentByBom", { id: props.rowData.id, orderClassify: props.tabValues.tabsCard }).then(
     (res) => {
-      proxy.downloadFile(res, "BOM对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
-      loading.value = false;
+      if (res.type === "application/json") {
+        const fileReader = new FileReader();
+        fileReader.onloadend = () => {
+          const jsonData = JSON.parse(fileReader.result);
+          ElMessage({ message: jsonData.msg, type: "error" });
+        };
+        fileReader.readAsText(res);
+      } else {
+        proxy.downloadFile(res, "BOM对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        loading.value = false;
+      }
     },
     (err) => {
       console.log(err);

+ 11 - 2
src/views/group/finance/check-bill/printSKU.vue

@@ -179,8 +179,17 @@ const deriveExcel = () => {
   loading.value = true;
   proxy.getFile("/statementOfAccount/exportDocumentBySku", { id: props.rowData.id, orderClassify: props.tabValues.tabsCard }).then(
     (res) => {
-      proxy.downloadFile(res, "SKU对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
-      loading.value = false;
+      if (res.type === "application/json") {
+        const fileReader = new FileReader();
+        fileReader.onloadend = () => {
+          const jsonData = JSON.parse(fileReader.result);
+          ElMessage({ message: jsonData.msg, type: "error" });
+        };
+        fileReader.readAsText(res);
+      } else {
+        proxy.downloadFile(res, "SKU对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        loading.value = false;
+      }
     },
     (err) => {
       console.log(err);

+ 1 - 10
src/views/group/finance/purchase-warehousing/index.vue

@@ -191,16 +191,7 @@ const getList = async (req, status) => {
   }
   loading.value = true;
   proxy.post("/purchaseWarehousing/page", sourceList.value.pagination).then((res) => {
-    if (res.rows && res.rows.length > 0) {
-      sourceList.value.data = res.rows.map((item) => {
-        return {
-          ...item,
-          isCheck: true,
-        };
-      });
-    } else {
-      sourceList.value.data = [];
-    }
+    sourceList.value.data = res.rows;
     sourceList.value.pagination.total = res.total;
     setTimeout(() => {
       loading.value = false;

+ 11 - 2
src/views/group/finance/sales-return/index.vue

@@ -22,7 +22,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -198,7 +198,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.getFile("/orderExchangeDetail/excelExport", sourceList.value.pagination).then((res) => {
-        proxy.downloadFile(res, "销售退货明细表-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "销售退货明细表-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 1 - 10
src/views/group/finance/sales-revenue-cost/index.vue

@@ -292,16 +292,7 @@ const getList = async (req, status) => {
   }
   loading.value = true;
   proxy.post("/statementOfAccountMerge/salesRevenueCostPage", sourceList.value.pagination).then((res) => {
-    if (res.rows && res.rows.length > 0) {
-      sourceList.value.data = res.rows.map((item) => {
-        return {
-          ...item,
-          isCheck: true,
-        };
-      });
-    } else {
-      sourceList.value.data = [];
-    }
+    sourceList.value.data = res.rows;
     sourceList.value.pagination.total = res.total;
     setTimeout(() => {
       loading.value = false;

+ 1 - 10
src/views/group/finance/summary/index.vue

@@ -206,16 +206,7 @@ const getList = async (req, status) => {
   }
   loading.value = true;
   proxy.post("/statementOfAccountMerge/page", sourceList.value.pagination).then((res) => {
-    if (res.rows && res.rows.length > 0) {
-      sourceList.value.data = res.rows.map((item) => {
-        return {
-          ...item,
-          isCheck: true,
-        };
-      });
-    } else {
-      sourceList.value.data = [];
-    }
+    sourceList.value.data = res.rows;
     sourceList.value.pagination.total = res.total;
     setTimeout(() => {
       loading.value = false;

+ 11 - 2
src/views/group/finance/summary/printBOM.vue

@@ -199,8 +199,17 @@ const deriveExcel = () => {
     })
     .then(
       (res) => {
-        proxy.downloadFile(res, "BOM对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
-        loading.value = false;
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "BOM对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          loading.value = false;
+        }
       },
       (err) => {
         console.log(err);

+ 11 - 2
src/views/group/finance/summary/printSKU.vue

@@ -186,8 +186,17 @@ const deriveExcel = () => {
     })
     .then(
       (res) => {
-        proxy.downloadFile(res, "SKU对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
-        loading.value = false;
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "SKU对账单-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          loading.value = false;
+        }
       },
       (err) => {
         console.log(err);

+ 5 - 4
src/views/group/limits-authority/role/index.vue

@@ -144,7 +144,12 @@ const config = computed(() => {
     },
   ];
 });
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -233,10 +238,6 @@ const submitForm = () => {
     });
   });
 };
-const selectData = ref([]);
-const selectRow = (data) => {
-  selectData.value = data;
-};
 const treeData = ref([]);
 const getSubset = (list, data) => {
   for (let i = 0; i < list.length; i++) {

+ 88 - 17
src/views/group/order/management/detail.vue

@@ -101,7 +101,7 @@
                           <div style="line-height: 35px">
                             <span style="color: black; font-weight: 700">快递包材费: </span>
                             <span>{{ item.deliveryMaterialsFee }}</span>
-                            <el-tooltip content="修改快递包材费" placement="top" effect="light">
+                            <el-tooltip content="修改快递包材费" placement="top" effect="light" v-if="userStatus">
                               <el-icon
                                 style="margin-left: 10px; transform: translateY(2px); color: #409eff; cursor: pointer"
                                 @click="clickChangePrice(item, index, 'deliveryMaterialsFee', '快递包材费')"
@@ -109,7 +109,7 @@
                                 <EditPen />
                               </el-icon>
                             </el-tooltip>
-                            <el-tooltip content="清零" placement="top" effect="light">
+                            <el-tooltip content="清零" placement="top" effect="light" v-if="userStatus">
                               <el-icon
                                 style="margin-left: 10px; transform: translateY(2px); color: #409eff; cursor: pointer"
                                 @click="clickRefresh(index, 'deliveryMaterialsFee')"
@@ -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>
@@ -396,7 +402,7 @@
             style="width: 100%"
             :controls="false"
             :min="0"
-            :precision="2"
+            :precision="labelPrice === 'deliveryMaterialsFee' ? 3 : 2"
             :disabled="(!changePrice.data.customProcessingType || changePrice.data.customProcessingType === '-1') && labelPrice === 'customProcessingFee'" />
         </el-form-item>
       </el-form>
@@ -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>
 
@@ -415,6 +453,7 @@ import { useRouter, useRoute } from "vue-router";
 import useTagsViewStore from "/src/store/modules/tagsView";
 
 const { proxy } = getCurrentInstance();
+const userStatus = ref(proxy.useUserStore().user.userId === "1");
 const router = useRouter();
 const route = useRoute();
 const submit = ref(null);
@@ -434,6 +473,8 @@ const formData = reactive({
     type: 1,
     orderSkuList: [],
     fileList: [],
+    orderPackageBomList: [],
+    outerBoxSelfAdhesiveStickerFile: {},
   },
 });
 const formConfig = computed(() => {
@@ -448,6 +489,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 +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) {
@@ -734,7 +794,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 +848,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 +895,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 +956,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 +1059,9 @@ const calculatedTotalAmount = () => {
       (calculatedAmount("unitPrice") +
         calculatedAmount("customProcessingFee") +
         calculatedAmount("lssueFee") +
-        calculatedAmount("deliveryMaterialsFee") +
+        computeDeliveryMaterialsFee() +
         calculatedAmount("packingLabor") +
         calculatedAmount("managementFee") +
-        // calculatedOuterBoxPackingFee() +
         calculatedPackagingMaterialCost()) *
         100
     ) / 100
@@ -1027,17 +1085,30 @@ const onSuccessFile = (any, UploadFile) => {
 const onPreviewFile = (file) => {
   window.open(file.raw.fileUrl, "_blank");
 };
-const calculatedOuterBoxPackingFee = () => {
+const computeDeliveryMaterialsFee = () => {
   let money = 0;
   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>

+ 289 - 58
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,105 @@
     <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-dialog title="删除并退料入库" v-if="openDelete" v-model="openDelete" width="1000px">
+      <div v-loading="loadingDelete">
+        <el-table :data="deleteList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+          <el-table-column label="BOM品号" prop="bomSpecCode" width="140" />
+          <el-table-column label="BOM品名" prop="bomSpecName" min-width="220" />
+          <el-table-column label="仓库名称" prop="warehouseName" width="100" />
+          <el-table-column label="出库数量" prop="outQuantity" width="100" />
+        </el-table>
+      </div>
+      <template #footer>
+        <el-button @click="openDelete = false" size="large" v-preReClick>取 消</el-button>
+        <el-button type="primary" @click="submitDelete()" size="large" v-preReClick>确认删除</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -97,6 +176,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 +420,7 @@ const config = computed(() => {
     {
       attrs: {
         label: "操作",
-        width: 200,
+        width: 220,
         align: "center",
         fixed: "right",
       },
@@ -359,6 +439,17 @@ const config = computed(() => {
                 },
               }
             : {},
+          {
+            attrs: {
+              label: "修改包装配置",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              clickChangePackaging(row);
+            },
+          },
           props.selectStatus
             ? {
                 attrs: {
@@ -423,19 +514,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: {
@@ -535,15 +613,30 @@ const clickDelete = (row) => {
     })
     .catch(() => {});
 };
+const openDelete = ref(false);
+const loadingDelete = ref(false);
+const deleteList = ref([]);
+const deleteRow = ref({});
 const clickDeleteTwo = (row) => {
+  deleteList.value = [];
+  loadingDelete.value = true;
+  openDelete.value = true;
+  deleteRow.value = row;
+  proxy.post("/orderInfo/returnBomList", { id: row.id }).then((res) => {
+    deleteList.value = res;
+    loadingDelete.value = false;
+  });
+};
+const submitDelete = () => {
   ElMessageBox.confirm("你是否确认此操作", "提示", {
     confirmButtonText: "确定",
     cancelButtonText: "取消",
     type: "warning",
   })
     .then(() => {
-      proxy.post("/orderInfo/deleteAndStore", { id: row.id }).then(() => {
+      proxy.post("/orderInfo/deleteAndStore", { id: deleteRow.value.id }).then(() => {
         ElMessage({ message: "删除成功", type: "success" });
+        openDelete.value = false;
         getList();
       });
     })
@@ -647,28 +740,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);
@@ -736,11 +807,166 @@ const deriveExcel = (row) => {
   })
     .then(() => {
       proxy.postFile("/orderInfo/orderExportExcel", { id: row.id }).then((res) => {
-        proxy.downloadFile(res, row.code + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, row.code + ".xlsx");
+        }
       });
     })
     .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>
@@ -756,4 +982,9 @@ const deriveExcel = (row) => {
   overflow-y: auto;
   overflow-x: hidden;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 17 - 3
src/views/group/purchase/supplier/index.vue

@@ -136,6 +136,14 @@ const config = computed(() => {
       attrs: {
         label: "供应商名称",
         prop: "name",
+        'min-width': 240,
+      },
+    },
+    {
+      attrs: {
+        label: "E10供应商编号",
+        prop: "code",
+        width: 140,
       },
     },
     {
@@ -163,14 +171,14 @@ const config = computed(() => {
       attrs: {
         label: "城市",
         prop: "city",
-        width: 140,
+        width: 160,
       },
     },
     {
       attrs: {
         label: "地址",
         prop: "detailedAddress",
-        width: 240,
+        'min-width': 240,
       },
     },
     {
@@ -236,7 +244,7 @@ const openDialog = ref(false);
 const submit = ref(null);
 const formOption = reactive({
   inline: true,
-  labelWidth: "100px",
+  labelWidth: "120px",
   itemWidth: 100,
   rules: [],
   labelPosition: "right",
@@ -259,6 +267,12 @@ const formConfig = computed(() => {
     },
     {
       type: "input",
+      prop: "code",
+      label: "E10供应商编号",
+      itemType: "text",
+    },
+    {
+      type: "input",
       prop: "companyTelephone",
       label: "公司电话",
       itemType: "text",

+ 120 - 51
src/views/production/operation/batching/index.vue

@@ -71,40 +71,48 @@
       </el-tabs>
     </el-card>
 
-    <el-dialog title="打印" v-if="openPrint" v-model="openPrint" width="1000px">
-      <div style="height: calc(100vh - 174px); overflow-y: auto; overflow-x: hidden">
-        <div class="printBomList" id="printMe">
-          <div class="t">生产备料单</div>
-          <div class="time" style="text-align: right">
-            {{ printTime }}
+    <el-dialog title="打印" v-if="openPrint" v-model="openPrint" width="1200px">
+      <div v-loading="loadingPrint">
+        <div style="height: calc(100vh - 174px); overflow-y: auto; overflow-x: hidden">
+          <div class="printBomList" id="printMe">
+            <div class="t">生产备料单</div>
+            <div class="time" style="text-align: right">
+              {{ printTime }}
+            </div>
+            <table border="1" cellspacing="0" class="table">
+              <thead>
+                <tr>
+                  <td style="width: 40px; text-align: center">编号</td>
+                  <td style="width: 120px">图稿类型</td>
+                  <td style="width: 100px">规格</td>
+                  <td style="width: 120px">颜色</td>
+                  <td style="width: 110px">BOM品号</td>
+                  <td>图稿名称</td>
+                  <td style="width: 120px">SKU品号</td>
+                  <td style="width: 80px; text-align: center">数量小计</td>
+                  <td style="width: 80px; text-align: center">数量总计</td>
+                </tr>
+              </thead>
+              <tbody v-if="formData && formData.length > 0">
+                <tr v-for="(item, index) in formData" :key="index">
+                  <td style="text-align: center">{{ item.index }}</td>
+                  <td>{{ dictKeyValue(item.machinedPanel, useUserStore().allDict["charge_item"]) }}</td>
+                  <td :rowspan="item.specIndex" v-if="item.specStatus">{{ item.spec }}</td>
+                  <td :rowspan="item.colourIndex" v-if="item.colourStatus">{{ item.colour }}</td>
+                  <td :rowspan="item.bomIndex" v-if="item.bomStatus">{{ item.bomSpecCode }}</td>
+                  <td>{{ item.artworkName }}</td>
+                  <td>{{ item.skuSpecCode }}</td>
+                  <td style="text-align: center">{{ item.quantity }}</td>
+                  <td :rowspan="item.bomIndex" v-if="item.bomStatus" style="text-align: center">{{ item.totalQuantity }}</td>
+                </tr>
+              </tbody>
+            </table>
           </div>
-          <table border="1" cellspacing="0" class="table">
-            <thead>
-              <tr>
-                <td style="width: 6%; text-align: center">编号</td>
-                <td style="width: 18%">物料品号</td>
-                <td style="width: 38%">物料品名</td>
-                <td style="width: 18%">SKU品号</td>
-                <td style="width: 10%; text-align: center">数量小计</td>
-                <td style="width: 10%; text-align: center">数量总计</td>
-              </tr>
-            </thead>
-            <tbody v-for="(item, index) in sourceList.data" :key="index">
-              <tr v-for="(itemSKU, indexSKU) in item.skuInfoList" :key="indexSKU">
-                <td :rowspan="item.skuInfoList.length" v-if="indexSKU === 0" style="text-align: center">{{ index + 1 }}</td>
-                <td :rowspan="item.skuInfoList.length" v-if="indexSKU === 0">{{ item.bomSpecCode }}</td>
-                <td :rowspan="item.skuInfoList.length" v-if="indexSKU === 0">{{ item.bomSpecName }}</td>
-                <td>{{ itemSKU.skuSpecCode }}</td>
-                <td style="text-align: center">{{ itemSKU.quantity }}</td>
-                <td :rowspan="item.skuInfoList.length" v-if="indexSKU === 0" style="text-align: center">{{ item.totalQuantity }}</td>
-              </tr>
-            </tbody>
-          </table>
         </div>
-      </div>
-      <div style="text-align: center; margin: 10px">
-        <el-button @click="openPrint = false" size="large">取消</el-button>
-        <el-button type="primary" v-print="printObj" size="large">打印</el-button>
+        <div style="text-align: center; margin: 10px">
+          <el-button @click="openPrint = false" size="large">取消</el-button>
+          <el-button type="primary" v-print="printObj" size="large">打印</el-button>
+        </div>
       </div>
     </el-dialog>
 
@@ -229,12 +237,6 @@ const searchConfigTwo = computed(() => {
 const config = computed(() => {
   return [
     {
-      type: "selection",
-      attrs: {
-        checkAtt: "isCheck",
-      },
-    },
-    {
       attrs: {
         label: "BOM品号",
         prop: "bomSpecCode",
@@ -356,18 +358,7 @@ const getList = async (req, status) => {
   }
   loading.value = true;
   proxy.post("/stockPreparation/uncompletedList", sourceList.value.pagination).then((res) => {
-    if (res && res.length > 0) {
-      sourceList.value.data = Object.freeze(
-        res.map((item) => {
-          return {
-            ...item,
-            isCheck: false,
-          };
-        })
-      );
-    } else {
-      sourceList.value.data = res;
-    }
+    sourceList.value.data = res;
     setTimeout(() => {
       loading.value = false;
     }, 200);
@@ -425,9 +416,86 @@ const openFile = (path) => {
 };
 const openPrint = ref(false);
 const printTime = ref("");
+const formData = ref([]);
+const loadingPrint = ref(false);
 const outExcel = () => {
+  formData.value = [];
   printTime.value = moment().format("yyyy-MM-DD HH:mm:ss");
+  loadingPrint.value = true;
   openPrint.value = true;
+  proxy.post("/stockPreparation/printUncompletedList", sourceList.value.pagination).then((res) => {
+    if (res && res.length > 0) {
+      for (let i = 0; i < res.length; i++) {
+        if (res[i].colourGroupingInfoList && res[i].colourGroupingInfoList.length > 0) {
+          res[i].specIndex = 0;
+          for (let j = 0; j < res[i].colourGroupingInfoList.length; j++) {
+            res[i].colourGroupingInfoList[j].colourIndex = 0;
+            let colourGroupingInfoList = res[i].colourGroupingInfoList[j];
+            if (colourGroupingInfoList.uncompletedVoList && colourGroupingInfoList.uncompletedVoList.length > 0) {
+              for (let x = 0; x < colourGroupingInfoList.uncompletedVoList.length; x++) {
+                res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex = 0;
+                let uncompletedVoList = colourGroupingInfoList.uncompletedVoList[x];
+                if (uncompletedVoList.skuInfoList && uncompletedVoList.skuInfoList.length > 0) {
+                  for (let y = 0; y < uncompletedVoList.skuInfoList.length; y++) {
+                    res[i].specIndex++;
+                    res[i].colourGroupingInfoList[j].colourIndex++;
+                    res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex++;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    let list = [];
+    if (res && res.length > 0) {
+      let index = 0;
+      for (let i = 0; i < res.length; i++) {
+        if (res[i].colourGroupingInfoList && res[i].colourGroupingInfoList.length > 0) {
+          let specStatus = true;
+          for (let j = 0; j < res[i].colourGroupingInfoList.length; j++) {
+            let colourStatus = true;
+            let colourGroupingInfoList = res[i].colourGroupingInfoList[j];
+            if (colourGroupingInfoList.uncompletedVoList && colourGroupingInfoList.uncompletedVoList.length > 0) {
+              for (let x = 0; x < colourGroupingInfoList.uncompletedVoList.length; x++) {
+                let bomStatus = true;
+                let uncompletedVoList = colourGroupingInfoList.uncompletedVoList[x];
+                if (uncompletedVoList.skuInfoList && uncompletedVoList.skuInfoList.length > 0) {
+                  for (let y = 0; y < uncompletedVoList.skuInfoList.length; y++) {
+                    let skuInfoList = uncompletedVoList.skuInfoList[y];
+                    index++;
+                    list.push({
+                      index: index,
+                      spec: res[i].spec,
+                      colour: colourGroupingInfoList.colour,
+                      bomSpecCode: uncompletedVoList.bomSpecCode,
+                      artworkName: skuInfoList.artworkName,
+                      skuSpecCode: skuInfoList.skuSpecCode,
+                      machinedPanel: skuInfoList.machinedPanel,
+                      quantity: skuInfoList.quantity,
+                      totalQuantity: uncompletedVoList.totalQuantity,
+                      specStatus: specStatus,
+                      specIndex: res[i].specIndex,
+                      colourStatus: colourStatus,
+                      colourIndex: res[i].colourGroupingInfoList[j].colourIndex,
+                      bomStatus: bomStatus,
+                      bomIndex: res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex,
+                    });
+                    specStatus = false;
+                    colourStatus = false;
+                    bomStatus = false;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    formData.value = Object.freeze(list);
+    loadingPrint.value = false;
+  });
 };
 const printObj = ref({
   id: "printMe",
@@ -453,6 +521,7 @@ const clickCancel = (status) => {
 }
 .printBomList {
   width: 100%;
+  font-size: 12px !important;
   .t {
     text-align: center;
     font-size: 26px;
@@ -465,7 +534,7 @@ const clickCancel = (status) => {
   .table {
     width: 100%;
     td {
-      padding: 10px;
+      padding: 4px;
     }
   }
 }

+ 288 - 0
src/views/production/operation/lose-the-delivery/index.vue

@@ -0,0 +1,288 @@
+<template>
+  <el-card class="box-card">
+    <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+      <template #orderId>
+        <div style="width: 100%">
+          <el-select-v2
+            v-model="formData.data.orderId"
+            :options="productionOrder"
+            placeholder="请选择订单号"
+            @change="changeOrder()"
+            style="width: 100%"
+            filterable />
+        </div>
+      </template>
+      <template #productionExceedReceiveSkuList>
+        <div style="width: 100%">
+          <el-table :data="formData.data.productionExceedReceiveSkuList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="SKU品号" prop="code" width="160" />
+            <el-table-column label="SKU品名" prop="name" min-width="220" />
+            <el-table-column label="丢件SKU" width="200">
+              <template #default="{ row, $index }">
+                <el-button
+                  v-if="!row.exceptionSkuSpecId"
+                  type="primary"
+                  size="small"
+                  @click="handleOpen($index)"
+                  style="margin: 5px 0; background-color: #43b214; border-color: #43b214">
+                  选择SKU
+                </el-button>
+                <div style="width: 100%; display: flex; align-items: center" v-else>
+                  <el-icon style="font-size: 16px; cursor: pointer" @click="clickRemove($index)"><Remove /></el-icon>
+                  <span>{{ row.exceptionSkuSpecCode }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="订单数量" prop="orderQuantity" width="120" />
+            <el-table-column label="超领数量" width="160">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'productionExceedReceiveSkuList.' + $index + '.quantity'" :inline-message="true" style="width: 100%" @change="queryBOM">
+                  <el-input-number
+                    onmousewheel="return false;"
+                    v-model="row.quantity"
+                    placeholder="超领数量"
+                    style="width: 100%"
+                    :controls="false"
+                    :min="0"
+                    :precision="0"
+                    :max="row.orderQuantity" />
+                </el-form-item>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </template>
+      <template #productionExceedReceiveBomList>
+        <div style="width: 100%">
+          <el-table :data="formData.data.productionExceedReceiveBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="BOM品号" prop="bomSpecCode" width="160" />
+            <el-table-column label="BOM品名" prop="bomSpecName" min-width="220" />
+            <el-table-column label="仓库" prop="warehouseName" width="160" />
+            <el-table-column label="库存数量" prop="inventoryQuantity" width="120" />
+            <el-table-column label="出库数量" prop="outQuantity" width="120" />
+          </el-table>
+        </div>
+      </template>
+    </byForm>
+    <div style="text-align: center; margin: 10px">
+      <el-button @click="clickCancel()" size="large">重 置</el-button>
+      <el-button type="primary" @click="submitForm()" size="large" v-preReClick>提 交</el-button>
+    </div>
+
+    <el-dialog title="选择SKU" v-if="openSKU" v-model="openSKU" width="84%">
+      <SelectProduct :selectStatus="true" :type="'null'" @selectProduct="selectProduct"></SelectProduct>
+      <template #footer>
+        <el-button @click="openSKU = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+  </el-card>
+</template>
+
+<script setup>
+import byForm from "/src/components/byForm/index";
+import { ElMessage } from "element-plus";
+import SelectProduct from "/src/views/group/product/management/index";
+
+const { proxy } = getCurrentInstance();
+const productionOrder = ref([]);
+const typeList = ref([
+  {
+    dictKey: 1,
+    dictValue: "制作损坏",
+  },
+  {
+    dictKey: 2,
+    dictValue: "裸垫质量不良",
+  },
+  {
+    dictKey: 3,
+    dictValue: "生产错误",
+  },
+  {
+    dictKey: 4,
+    dictValue: "丢件",
+  },
+]);
+const getDemandData = () => {
+  proxy.post("/productionOrder/page", { pageNum: 1, pageSize: 9999, status: "30" }).then((res) => {
+    if (res.rows && res.rows.length > 0) {
+      productionOrder.value = productionOrder.value.concat(
+        res.rows.map((item) => {
+          if (item.wlnCode) {
+            return {
+              value: item.orderId,
+              label: item.code + " (" + item.wlnCode + ")",
+            };
+          } else {
+            return {
+              value: item.orderId,
+              label: item.code,
+            };
+          }
+        })
+      );
+    }
+  });
+};
+getDemandData();
+const submit = ref(null);
+const formOption = reactive({
+  inline: true,
+  labelWidth: "120px",
+  itemWidth: 100,
+  rules: [],
+  labelPosition: "right",
+});
+const formData = reactive({
+  data: {
+    orderId: "",
+    type: 4,
+    productionExceedReceiveSkuList: [],
+    productionExceedReceiveBomList: [],
+  },
+});
+const formConfig = computed(() => {
+  return [
+    {
+      type: "slot",
+      label: "订单号",
+      slotName: "orderId",
+      prop: "orderId",
+      itemWidth: 51,
+    },
+    {
+      type: "select",
+      label: "超领原因",
+      prop: "type",
+      data: typeList.value,
+      itemWidth: 51,
+      disabled: true,
+    },
+    {
+      type: "input",
+      label: "责任人",
+      prop: "responsible",
+      itemWidth: 51,
+    },
+    {
+      type: "slot",
+      slotName: "productionExceedReceiveSkuList",
+      label: "订单商品",
+    },
+    {
+      type: "slot",
+      slotName: "productionExceedReceiveBomList",
+      label: "BOM明细",
+    },
+  ];
+});
+const rules = ref({
+  orderId: [{ required: true, message: "请选择订单号", trigger: "change" }],
+  type: [{ required: true, message: "请选择超领原因", trigger: "change" }],
+  responsible: [{ required: true, message: "请输入责任人", trigger: "blur" }],
+});
+const submitForm = () => {
+  submit.value.handleSubmit(() => {
+    if (formData.data.productionExceedReceiveSkuList && formData.data.productionExceedReceiveSkuList.length > 0) {
+      let list = formData.data.productionExceedReceiveSkuList.filter((item) => item.quantity > 0);
+      if (list && list.length > 0) {
+        proxy.post("/productionExceedReceive/replenishExceedReceive", formData.data).then(() => {
+          ElMessage({ message: "操作完成", type: "success" });
+          clickCancel();
+        });
+      } else {
+        return ElMessage("请输入超领数量");
+      }
+    } else {
+      return ElMessage("请添加订单商品");
+    }
+  });
+};
+const clickCancel = () => {
+  formData.data = {
+    type: 4,
+    productionExceedReceiveSkuList: [],
+    productionExceedReceiveBomList: [],
+  };
+  submit.value.resetFields();
+};
+const changeOrder = () => {
+  if (formData.data.orderId) {
+    proxy.post("/productionExceedReceive/getOrderSkuList", { id: formData.data.orderId }).then((res) => {
+      if (res && res.length > 0) {
+        formData.data.productionExceedReceiveSkuList = res.map((item) => {
+          return {
+            name: item.name,
+            code: item.code,
+            orderQuantity: item.quantity,
+            orderSkuId: item.id,
+            skuSpecId: item.skuSpecId,
+            exceptionSkuSpecId: "",
+            exceptionSkuSpecCode: "",
+            quantity: 0,
+            warehouseId: "",
+          };
+        });
+      } else {
+        formData.data.productionExceedReceiveSkuList = [];
+      }
+    });
+  } else {
+    formData.data.productionExceedReceiveSkuList = [];
+  }
+  formData.data.productionExceedReceiveBomList = [];
+};
+const rowIndex = ref(null);
+const openSKU = ref(false);
+const handleOpen = (index) => {
+  rowIndex.value = index;
+  openSKU.value = true;
+};
+const clickRemove = (index) => {
+  formData.data.productionExceedReceiveSkuList[index].exceptionSkuSpecId = "";
+  formData.data.productionExceedReceiveSkuList[index].exceptionSkuSpecCode = "";
+};
+const selectProduct = (item) => {
+  if (item.id) {
+    formData.data.productionExceedReceiveSkuList[rowIndex.value].exceptionSkuSpecId = item.id;
+    formData.data.productionExceedReceiveSkuList[rowIndex.value].exceptionSkuSpecCode = item.code;
+    ElMessage({ message: "选择完成", type: "success" });
+    openSKU.value = false;
+  }
+};
+const queryBOM = () => {
+  let list = formData.data.productionExceedReceiveSkuList.filter((item) => item.quantity > 0);
+  if (list && list.length > 0) {
+    proxy
+      .post("/productionExceedReceive/getSkuSpecMaterialList", {
+        skuSpecList: list.map((item) => {
+          return {
+            skuSpecId: item.skuSpecId,
+            quantity: item.quantity,
+          };
+        }),
+      })
+      .then(
+        (res) => {
+          formData.data.productionExceedReceiveBomList = res;
+        },
+        (err) => {
+          console.log(err);
+          formData.data.productionExceedReceiveBomList = [];
+        }
+      );
+  } else {
+    formData.data.productionExceedReceiveBomList = [];
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-input-number .el-input__inner) {
+  text-align: left;
+}
+:deep(.el-dialog) {
+  margin-top: 10px !important;
+  margin-bottom: 10px !important;
+}
+</style>

+ 1 - 1
src/views/production/operation/production-error/index.vue

@@ -241,7 +241,7 @@ const changeOrder = () => {
             name: item.name,
             code: item.code,
             orderQuantity: item.quantity,
-            orderSkuId: item.skuId,
+            orderSkuId: item.id,
             skuSpecId: item.skuSpecId,
             exceptionSkuSpecId: "",
             exceptionSkuSpecCode: "",

+ 314 - 0
src/views/production/operation/supplementary-order/index.vue

@@ -0,0 +1,314 @@
+<template>
+  <el-card class="box-card">
+    <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+      <template #orderId>
+        <div style="width: 100%">
+          <el-select-v2
+            v-model="formData.data.orderId"
+            :options="productionOrder"
+            placeholder="请选择订单号"
+            @change="changeOrder()"
+            style="width: 100%"
+            filterable />
+        </div>
+      </template>
+      <template #productionExceedReceiveSkuList>
+        <div style="width: 100%">
+          <el-table :data="formData.data.productionExceedReceiveSkuList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="SKU品号" prop="code" width="160" />
+            <el-table-column label="SKU品名" prop="name" min-width="220" />
+            <el-table-column label="补单SKU" width="200">
+              <template #default="{ row, $index }">
+                <el-button
+                  v-if="!row.exceptionSkuSpecId"
+                  type="primary"
+                  size="small"
+                  @click="handleOpen($index)"
+                  style="margin: 5px 0; background-color: #43b214; border-color: #43b214">
+                  选择SKU
+                </el-button>
+                <div style="width: 100%; display: flex; align-items: center" v-else>
+                  <el-icon style="font-size: 16px; cursor: pointer" @click="clickRemove($index)"><Remove /></el-icon>
+                  <span>{{ row.exceptionSkuSpecCode }}</span>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="仓库" width="160">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'productionExceedReceiveSkuList.' + $index + '.warehouseId'" style="width: 100%">
+                  <el-select v-model="row.warehouseId" placeholder="请选择仓库" clearable style="width: 100%">
+                    <el-option v-for="item in warehouseList" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                  </el-select>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column label="订单数量" prop="orderQuantity" width="120" />
+            <el-table-column label="超领数量" width="160">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'productionExceedReceiveSkuList.' + $index + '.quantity'" :inline-message="true" style="width: 100%" @change="queryBOM">
+                  <el-input-number
+                    onmousewheel="return false;"
+                    v-model="row.quantity"
+                    placeholder="超领数量"
+                    style="width: 100%"
+                    :controls="false"
+                    :min="0"
+                    :precision="0"
+                    :max="row.orderQuantity" />
+                </el-form-item>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </template>
+      <template #productionExceedReceiveBomList>
+        <div style="width: 100%">
+          <el-table :data="formData.data.productionExceedReceiveBomList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+            <el-table-column label="BOM品号" prop="bomSpecCode" width="160" />
+            <el-table-column label="BOM品名" prop="bomSpecName" min-width="220" />
+            <el-table-column label="仓库" prop="warehouseName" width="160" />
+            <el-table-column label="库存数量" prop="inventoryQuantity" width="120" />
+            <el-table-column label="出库数量" prop="outQuantity" width="120" />
+          </el-table>
+        </div>
+      </template>
+    </byForm>
+    <div style="text-align: center; margin: 10px">
+      <el-button @click="clickCancel()" size="large">重 置</el-button>
+      <el-button type="primary" @click="submitForm()" size="large" v-preReClick>提 交</el-button>
+    </div>
+
+    <el-dialog title="选择SKU" v-if="openSKU" v-model="openSKU" width="84%">
+      <SelectProduct :selectStatus="true" :type="'null'" @selectProduct="selectProduct"></SelectProduct>
+      <template #footer>
+        <el-button @click="openSKU = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+  </el-card>
+</template>
+
+<script setup>
+import byForm from "/src/components/byForm/index";
+import { ElMessage } from "element-plus";
+import SelectProduct from "/src/views/group/product/management/index";
+
+const { proxy } = getCurrentInstance();
+const productionOrder = ref([]);
+const warehouseList = ref([]);
+const typeList = ref([
+  {
+    dictKey: 1,
+    dictValue: "制作损坏",
+  },
+  {
+    dictKey: 2,
+    dictValue: "裸垫质量不良",
+  },
+  {
+    dictKey: 3,
+    dictValue: "生产错误",
+  },
+  {
+    dictKey: 4,
+    dictValue: "丢件",
+  },
+  {
+    dictKey: 5,
+    dictValue: "补单",
+  },
+]);
+const getDemandData = () => {
+  proxy.post("/productionOrder/page", { pageNum: 1, pageSize: 9999, status: "30" }).then((res) => {
+    if (res.rows && res.rows.length > 0) {
+      productionOrder.value = productionOrder.value.concat(
+        res.rows.map((item) => {
+          if (item.wlnCode) {
+            return {
+              value: item.orderId,
+              label: item.code + " (" + item.wlnCode + ")",
+            };
+          } else {
+            return {
+              value: item.orderId,
+              label: item.code,
+            };
+          }
+        })
+      );
+    }
+  });
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    if (res.rows && res.rows.length > 0) {
+      warehouseList.value = res.rows
+        .filter((item) => ["1", "5"].includes(item.type))
+        .map((item) => {
+          return {
+            dictKey: item.id,
+            dictValue: item.name,
+          };
+        });
+    }
+  });
+};
+getDemandData();
+const submit = ref(null);
+const formOption = reactive({
+  inline: true,
+  labelWidth: "120px",
+  itemWidth: 100,
+  rules: [],
+  labelPosition: "right",
+});
+const formData = reactive({
+  data: {
+    orderId: "",
+    type: 5,
+    productionExceedReceiveSkuList: [],
+    productionExceedReceiveBomList: [],
+  },
+});
+const formConfig = computed(() => {
+  return [
+    {
+      type: "slot",
+      label: "订单号",
+      slotName: "orderId",
+      prop: "orderId",
+      itemWidth: 51,
+    },
+    {
+      type: "select",
+      label: "超领原因",
+      prop: "type",
+      data: typeList.value,
+      itemWidth: 51,
+      disabled: true,
+    },
+    {
+      type: "input",
+      label: "责任人",
+      prop: "responsible",
+      itemWidth: 51,
+    },
+    {
+      type: "slot",
+      slotName: "productionExceedReceiveSkuList",
+      label: "订单商品",
+    },
+    {
+      type: "slot",
+      slotName: "productionExceedReceiveBomList",
+      label: "BOM明细",
+    },
+  ];
+});
+const rules = ref({
+  orderId: [{ required: true, message: "请选择订单号", trigger: "change" }],
+  type: [{ required: true, message: "请选择超领原因", trigger: "change" }],
+  responsible: [{ required: true, message: "请输入责任人", trigger: "blur" }],
+});
+const submitForm = () => {
+  submit.value.handleSubmit(() => {
+    if (formData.data.productionExceedReceiveSkuList && formData.data.productionExceedReceiveSkuList.length > 0) {
+      let list = formData.data.productionExceedReceiveSkuList.filter((item) => item.quantity > 0);
+      if (list && list.length > 0) {
+        proxy.post("/productionExceedReceive/replenishExceedReceive", formData.data).then(() => {
+          ElMessage({ message: "操作完成", type: "success" });
+          clickCancel();
+        });
+      } else {
+        return ElMessage("请输入超领数量");
+      }
+    } else {
+      return ElMessage("请添加订单商品");
+    }
+  });
+};
+const clickCancel = () => {
+  formData.data = {
+    type: 5,
+    productionExceedReceiveSkuList: [],
+    productionExceedReceiveBomList: [],
+  };
+  submit.value.resetFields();
+};
+const changeOrder = () => {
+  if (formData.data.orderId) {
+    proxy.post("/productionExceedReceive/getOrderSkuList", { id: formData.data.orderId }).then((res) => {
+      if (res && res.length > 0) {
+        formData.data.productionExceedReceiveSkuList = res.map((item) => {
+          return {
+            name: item.name,
+            code: item.code,
+            orderQuantity: item.quantity,
+            orderSkuId: item.id,
+            skuSpecId: item.skuSpecId,
+            exceptionSkuSpecId: "",
+            exceptionSkuSpecCode: "",
+            quantity: 0,
+            warehouseId: "",
+          };
+        });
+      } else {
+        formData.data.productionExceedReceiveSkuList = [];
+      }
+    });
+  } else {
+    formData.data.productionExceedReceiveSkuList = [];
+  }
+  formData.data.productionExceedReceiveBomList = [];
+};
+const rowIndex = ref(null);
+const openSKU = ref(false);
+const handleOpen = (index) => {
+  rowIndex.value = index;
+  openSKU.value = true;
+};
+const clickRemove = (index) => {
+  formData.data.productionExceedReceiveSkuList[index].exceptionSkuSpecId = "";
+  formData.data.productionExceedReceiveSkuList[index].exceptionSkuSpecCode = "";
+};
+const selectProduct = (item) => {
+  if (item.id) {
+    formData.data.productionExceedReceiveSkuList[rowIndex.value].exceptionSkuSpecId = item.id;
+    formData.data.productionExceedReceiveSkuList[rowIndex.value].exceptionSkuSpecCode = item.code;
+    ElMessage({ message: "选择完成", type: "success" });
+    openSKU.value = false;
+  }
+};
+const queryBOM = () => {
+  let list = formData.data.productionExceedReceiveSkuList.filter((item) => item.quantity > 0);
+  if (list && list.length > 0) {
+    proxy
+      .post("/productionExceedReceive/getSkuSpecMaterialList", {
+        skuSpecList: list.map((item) => {
+          return {
+            skuSpecId: item.skuSpecId,
+            quantity: item.quantity,
+          };
+        }),
+      })
+      .then(
+        (res) => {
+          formData.data.productionExceedReceiveBomList = res;
+        },
+        (err) => {
+          console.log(err);
+          formData.data.productionExceedReceiveBomList = [];
+        }
+      );
+  } else {
+    formData.data.productionExceedReceiveBomList = [];
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep(.el-input-number .el-input__inner) {
+  text-align: left;
+}
+:deep(.el-dialog) {
+  margin-top: 10px !important;
+  margin-bottom: 10px !important;
+}
+</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: 220,
         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>

+ 5 - 4
src/views/production/schedule/production-order/index.vue

@@ -327,7 +327,12 @@ const getDemandData = () => {
   });
 };
 getDemandData();
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -359,10 +364,6 @@ getList();
 const clickReset = () => {
   getList({ status: 30 }, true);
 };
-const selectData = ref([]);
-const selectRow = (data) => {
-  selectData.value = data;
-};
 const clickCode = (row) => {
   proxy.$router.replace({
     path: "/addOrder",

+ 103 - 47
src/views/production/schedule/production-work-order/index.vue

@@ -16,10 +16,14 @@
           text: '打印生产面单',
           action: () => clickSelectPrint(),
         },
+        {
+          text: '合并工单',
+          disabled: selectData.length < 2,
+          action: () => clickMerge(),
+        },
       ]"
       @get-list="getList"
-      @clickReset="clickReset"
-      @changeRadioGroup="changeRadioGroup">
+      @clickReset="clickReset">
       <template #code="{ item }">
         <div>
           <a style="color: #409eff; cursor: pointer; word-break: break-all" @click="clickCode(item)">{{ item.code }}</a>
@@ -62,12 +66,37 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { getNearDays } from "/src/utils/util";
 import QRCode from "qrcodejs2-fix";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import CycleBarcode from "/src/components/CycleBarcode";
 
 const { proxy } = getCurrentInstance();
+const statusList = ref([
+  {
+    dictKey: 0,
+    dictValue: "待投产",
+  },
+  {
+    dictKey: 1,
+    dictValue: "已扫描",
+  },
+  {
+    dictKey: 2,
+    dictValue: "生产中",
+  },
+  {
+    dictKey: 3,
+    dictValue: "生产完成",
+  },
+  {
+    dictKey: 4,
+    dictValue: "生产异常",
+  },
+  {
+    dictKey: 5,
+    dictValue: "重新排单",
+  },
+]);
 const sourceList = ref({
   data: [],
   pagination: {
@@ -81,9 +110,7 @@ const sourceList = ref({
     bomSpecCode: "",
     bomSpecName: "",
     productionWorkOrderCode: "",
-    beginTime: "",
-    endTime: "",
-    type: 3,
+    status: [0, 4],
   },
 });
 const loading = ref(false);
@@ -125,28 +152,11 @@ const searchConfig = computed(() => {
       label: "工单号",
     },
     {
-      type: "radio-group",
-      prop: "type",
-      label: "交期",
-      data: [
-        {
-          dictKey: 1,
-          dictValue: "近3天",
-        },
-        {
-          dictKey: 3,
-          dictValue: "近7天",
-        },
-        {
-          dictKey: 15,
-          dictValue: "近31天",
-        },
-      ],
-    },
-    {
-      type: "date",
-      propList: ["beginTime", "endTime"],
-      label: "日期",
+      type: "select",
+      prop: "status",
+      label: "生产状态",
+      data: statusList.value,
+      multiple: true,
     },
   ];
 });
@@ -214,9 +224,7 @@ const config = computed(() => {
         width: 80,
       },
       render(val) {
-        if (val == 0) {
-          return "待投产";
-        }
+        return proxy.dictKeyValue(val, statusList.value);
       },
     },
     {
@@ -253,14 +261,17 @@ const config = computed(() => {
     },
   ];
 });
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
       pageSize: sourceList.value.pagination.pageSize,
-      type: 3,
-      beginTime: getNearDays(3).beginTime,
-      endTime: getNearDays(3).endTime,
+      status: [0, 4],
     };
   } else {
     sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
@@ -269,10 +280,17 @@ const getList = async (req, status) => {
   proxy.post("/productionWorkOrder/page", sourceList.value.pagination).then((res) => {
     if (res.rows && res.rows.length > 0) {
       sourceList.value.data = res.rows.map((item) => {
-        return {
-          ...item,
-          isCheck: true,
-        };
+        if (item.status == 0 && !item.type) {
+          return {
+            ...item,
+            isCheck: true,
+          };
+        } else {
+          return {
+            ...item,
+            isCheck: false,
+          };
+        }
       });
     } else {
       sourceList.value.data = [];
@@ -283,13 +301,10 @@ const getList = async (req, status) => {
     }, 200);
   });
 };
-getList({ beginTime: getNearDays(3).beginTime, endTime: getNearDays(3).endTime });
+getList();
 const clickReset = () => {
   getList("", true);
 };
-const changeRadioGroup = () => {
-  getList({ beginTime: getNearDays(sourceList.value.pagination.type).beginTime, endTime: getNearDays(sourceList.value.pagination.type).endTime });
-};
 const clickCode = (row) => {
   proxy.$router.replace({
     path: "/addOrder",
@@ -307,10 +322,6 @@ const printObj = ref({
   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 selectData = ref([]);
-const selectRow = (data) => {
-  selectData.value = data;
-};
 const QRcodeList = ref([]);
 const clickPrint = (list) => {
   QRcodeList.value = list;
@@ -340,6 +351,48 @@ const clickSelectPrint = () => {
     return ElMessage("请选择需要打印的工单");
   }
 };
+const clickMerge = () => {
+  ElMessageBox.confirm("你是否确认此操作", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(() => {
+      proxy
+        .post(
+          "/productionWorkOrder/combined",
+          selectData.value.map((item) => item.id)
+        )
+        .then(() => {
+          ElMessage({ message: "操作成功", type: "success" });
+          getList();
+        });
+    })
+    .catch(() => {});
+};
+watch(selectData, (newVal) => {
+  if (newVal && newVal.length > 0) {
+    sourceList.value.data.forEach((x) => {
+      if (x.status == 0 && !x.type) {
+        if (x.bomSpecCode === newVal[0].bomSpecCode && x.skuSpecCode === newVal[0].skuSpecCode) {
+          x.isCheck = true;
+        } else {
+          x.isCheck = false;
+        }
+      } else {
+        x.isCheck = false;
+      }
+    });
+  } else {
+    sourceList.value.data.forEach((x) => {
+      if (x.status == 0 && !x.type) {
+        x.isCheck = true;
+      } else {
+        x.isCheck = false;
+      }
+    });
+  }
+});
 </script>
 
 <style lang="scss" scoped>
@@ -375,4 +428,7 @@ const clickSelectPrint = () => {
     }
   }
 }
+:deep(.el-table__header-wrapper .el-checkbox) {
+  display: none;
+}
 </style>

+ 5 - 4
src/views/production/shipment/print-order/index.vue

@@ -454,7 +454,12 @@ const getDemandData = () => {
   });
 };
 getDemandData();
+const selectData = ref([]);
+const selectRow = (data) => {
+  selectData.value = data;
+};
 const getList = async (req, status) => {
+  selectData.value = [];
   if (status) {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
@@ -485,10 +490,6 @@ getList();
 const clickReset = () => {
   getList("", true);
 };
-const selectData = ref([]);
-const selectRow = (data) => {
-  selectData.value = data;
-};
 const clickCode = (row) => {
   proxy.$router.replace({
     path: "/order-detail",

+ 11 - 1
src/views/production/warehouse/check/index.vue

@@ -68,6 +68,7 @@
 <script setup>
 import byTable from "/src/components/byTable/index";
 import moment from "moment";
+import { ElMessage } from "element-plus";
 
 const { proxy } = getCurrentInstance();
 const activeName = ref("first");
@@ -438,7 +439,16 @@ const clickSubmit = () => {
   proxy.$refs.derive.validate((valid) => {
     if (valid) {
       proxy.postFile("/check/inventoryExportExcel", { id: formData.data.warehouseId }).then((res) => {
-        proxy.downloadFile(res, "盘点-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "盘点-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     }
   });

+ 14 - 4
src/views/production/warehouse/finished-parts-storage/index.vue

@@ -294,10 +294,20 @@ const giveawayServerLog = (params) => {
   formFile.append("file", file);
   proxy.postUploadAndDownloadFile("/inventoryFinishedOrder/erpExcelExport", formFile).then(
     (res) => {
-      ElMessage({ message: "操作成功", type: "success" });
-      proxy.downloadFile(res, "成品库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
-      loadingGiveaway.value = false;
-      openGiveaway.value = false;
+      if (res.type === "application/json") {
+        const fileReader = new FileReader();
+        fileReader.onloadend = () => {
+          const jsonData = JSON.parse(fileReader.result);
+          ElMessage({ message: jsonData.msg, type: "error" });
+          loadingGiveaway.value = false;
+        };
+        fileReader.readAsText(res);
+      } else {
+        ElMessage({ message: "操作成功", type: "success" });
+        proxy.downloadFile(res, "成品库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        loadingGiveaway.value = false;
+        openGiveaway.value = false;
+      }
     },
     (err) => {
       console.log(err);

+ 11 - 2
src/views/production/warehouse/flow-record/index.vue

@@ -21,7 +21,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -253,7 +253,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/inOutStorageBom/exportExcelSummary", sourceList.value.pagination).then((res) => {
-        proxy.downloadFile(res, "出入库流水-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "出入库流水-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 21 - 3
src/views/production/warehouse/inventory/index.vue

@@ -55,7 +55,7 @@
 import byTable from "/src/components/byTable/index";
 import { useRoute } from "vue-router";
 import useTagsViewStore from "/src/store/modules/tagsView";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -391,11 +391,29 @@ const deriveExcel = () => {
     .then(() => {
       if (route.query && route.query.backupDate) {
         proxy.getFile("/inventory/exportBackExcel", sourceList.value.pagination).then((res) => {
-          proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          if (res.type === "application/json") {
+            const fileReader = new FileReader();
+            fileReader.onloadend = () => {
+              const jsonData = JSON.parse(fileReader.result);
+              ElMessage({ message: jsonData.msg, type: "error" });
+            };
+            fileReader.readAsText(res);
+          } else {
+            proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          }
         });
       } else {
         proxy.getFile("/inventory/exportExcel", sourceList.value.pagination).then((res) => {
-          proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          if (res.type === "application/json") {
+            const fileReader = new FileReader();
+            fileReader.onloadend = () => {
+              const jsonData = JSON.parse(fileReader.result);
+              ElMessage({ message: jsonData.msg, type: "error" });
+            };
+            fileReader.readAsText(res);
+          } else {
+            proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+          }
         });
       }
     })

+ 13 - 2
src/views/production/warehouse/outbound/index.vue

@@ -62,7 +62,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -352,6 +352,7 @@ const getList = async (req, status) => {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
       pageSize: sourceList.value.pagination.pageSize,
+      type: "0",
     };
   } else {
     sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
@@ -374,6 +375,7 @@ const getListTwo = async (req, status) => {
     sourceListTwo.value.pagination = {
       pageNum: sourceListTwo.value.pagination.pageNum,
       pageSize: sourceListTwo.value.pagination.pageSize,
+      type: "0",
     };
   } else {
     sourceListTwo.value.pagination = { ...sourceListTwo.value.pagination, ...req };
@@ -450,7 +452,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/inOutStorageBom/exportExcel", sourceListTwo.value.pagination).then((res) => {
-        proxy.downloadFile(res, "出库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "出库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 13 - 2
src/views/production/warehouse/putInStorage/index.vue

@@ -58,7 +58,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -347,6 +347,7 @@ const getList = async (req, status) => {
     sourceList.value.pagination = {
       pageNum: sourceList.value.pagination.pageNum,
       pageSize: sourceList.value.pagination.pageSize,
+      type: "1",
     };
   } else {
     sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
@@ -369,6 +370,7 @@ const getListTwo = async (req, status) => {
     sourceListTwo.value.pagination = {
       pageNum: sourceListTwo.value.pagination.pageNum,
       pageSize: sourceListTwo.value.pagination.pageSize,
+      type: "1",
     };
   } else {
     sourceListTwo.value.pagination = { ...sourceListTwo.value.pagination, ...req };
@@ -437,7 +439,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.postFile("/inOutStorageBom/exportExcel", sourceListTwo.value.pagination).then((res) => {
-        proxy.downloadFile(res, "入库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "入库明细-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});

+ 1 - 10
src/views/subsidiary/finance/summary/index.vue

@@ -172,16 +172,7 @@ const getList = async (req, status) => {
   }
   loading.value = true;
   proxy.post("/statementOfAccountMerge/page", sourceList.value.pagination).then((res) => {
-    if (res.rows && res.rows.length > 0) {
-      sourceList.value.data = res.rows.map((item) => {
-        return {
-          ...item,
-          isCheck: true,
-        };
-      });
-    } else {
-      sourceList.value.data = [];
-    }
+    sourceList.value.data = res.rows;
     sourceList.value.pagination.total = res.total;
     setTimeout(() => {
       loading.value = false;

+ 321 - 23
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">
@@ -123,7 +123,7 @@
                           </div>
                           <div style="line-height: 35px">
                             <span style="color: black; font-weight: 700">快递包材费: </span>
-                            <span>{{ item.deliveryMaterialsFee }}</span>
+                            <span>{{ computeSingleDeliveryMaterialsFee(index) }}</span>
                           </div>
                           <div style="line-height: 35px">
                             <span style="color: black; font-weight: 700">包装人工费: </span>
@@ -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,168 @@ const handleAdhesiveSuccess = (UploadFile, index) => {
     fileUrl: UploadFile.raw.fileUrl,
   };
 };
-const calculatedOuterBoxPackingFee = () => {
+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 = 0;
   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 computeSingleDeliveryMaterialsFee = (index) => {
+  let money = computeDeliveryMaterialsFee();
+  let list = formData.data.orderSkuList.filter((item) => item.quantity > 0);
+  let num = 0;
+  let singlePrice = 0;
+  if (list && list.length > 0) {
+    for (let i = 0; i < list.length; i++) {
+      num = Number(Math.round(num + list[i].quantity));
+    }
+    singlePrice = Number(Math.ceil((money / num) * 1000) / 1000);
+  }
+  formData.data.orderSkuList[index].deliveryMaterialsFee = singlePrice;
+  return formData.data.orderSkuList[index].deliveryMaterialsFee;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -1118,4 +1411,9 @@ const calculatedOuterBoxPackingFee = () => {
 :deep(.vertical-align) {
   vertical-align: middle;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 206 - 20
src/views/subsidiary/order/management/design.vue

@@ -61,7 +61,7 @@
                           </div>
                           <div style="line-height: 35px">
                             <span style="color: black; font-weight: 700">快递包材费: </span>
-                            <span>{{ item.deliveryMaterialsFee }}</span>
+                            <span>{{ computeSingleDeliveryMaterialsFee(index) }}</span>
                           </div>
                           <div style="line-height: 35px">
                             <span style="color: black; font-weight: 700">包装人工费: </span>
@@ -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,17 +924,114 @@ const handleAdhesiveSuccess = (UploadFile, index) => {
     fileUrl: UploadFile.raw.fileUrl,
   };
 };
-const calculatedOuterBoxPackingFee = () => {
+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 = 0;
   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 computeSingleDeliveryMaterialsFee = (index) => {
+  let money = computeDeliveryMaterialsFee();
+  let list = formData.data.orderSkuList.filter((item) => item.quantity > 0);
+  let num = 0;
+  let singlePrice = 0;
+  if (list && list.length > 0) {
+    for (let i = 0; i < list.length; i++) {
+      num = Number(Math.round(num + list[i].quantity));
+    }
+    singlePrice = Number(Math.ceil((money / num) * 1000) / 1000);
+  }
+  formData.data.orderSkuList[index].deliveryMaterialsFee = singlePrice;
+  return formData.data.orderSkuList[index].deliveryMaterialsFee;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -873,4 +1054,9 @@ const calculatedOuterBoxPackingFee = () => {
 :deep(.el-table__cell) {
   vertical-align: top;
 }
+.shippingPackage {
+  .el-form-item {
+    margin-bottom: 0;
+  }
+}
 </style>

+ 11 - 2
src/views/subsidiary/warehouse/inventory/index.vue

@@ -53,7 +53,7 @@
 
 <script setup>
 import byTable from "/src/components/byTable/index";
-import { ElMessageBox } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import moment from "moment";
 
 const { proxy } = getCurrentInstance();
@@ -313,7 +313,16 @@ const deriveExcel = () => {
   })
     .then(() => {
       proxy.getFile("/inventory/exportExcel", sourceList.value.pagination).then((res) => {
-        proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        if (res.type === "application/json") {
+          const fileReader = new FileReader();
+          fileReader.onloadend = () => {
+            const jsonData = JSON.parse(fileReader.result);
+            ElMessage({ message: jsonData.msg, type: "error" });
+          };
+          fileReader.readAsText(res);
+        } else {
+          proxy.downloadFile(res, "库存-" + moment().format("yyyy-MM-DD") + ".xlsx");
+        }
       });
     })
     .catch(() => {});