heshaofeng
7 天以前 ca3e4977395bc02c5d147dffdff7381333fdfbca
ÏîÄ¿´úÂë/WIDESEA_WMSClient/src/extension/stock/stockView.js
@@ -1,12 +1,10 @@
//此js文件是用来自定义扩展业务代码,可以扩展一些自定义页面或者重新配置生成的代码
import { el } from "element-plus/es/locales.mjs";
import { createVNode, render, h, reactive } from 'vue';
import { ElDialog, ElForm, ElFormItem, ElSelect, ElOption, ElButton, ElMessage, ElLoading } from 'element-plus';
import gridHeader from './extend/CrossAreaRelocationDialog.vue'
let extension = {
  components: {
    //查询界面扩展组件
    gridHeader: '',
    gridHeader: gridHeader,
    gridBody: '',
    gridFooter: '',
    //新建、编辑弹出框扩展组件
@@ -36,48 +34,48 @@
      //   }
      // }
      this.columns.forEach(column => {
        if (column.field == 'materielCode') {
          column.formatter = (row) => {
            var str = '';
            var list = row.materielCode.split(',');
            for (let index = 0; index < list.length; index++) {
              str += list[index] + '<br>';
            }
            return str = list[0] == "" ? "空箱" : str;
          }
        }
        if (column.field == 'batchNo') {
          column.formatter = (row) => {
            var str = '';
            var list = row.batchNo.split(',');
            for (let index = 0; index < list.length; index++) {
              str += list[index] + '<br>';
            }
            return str = list[0] == "" ? "无" : str;
          }
        }
        if (column.field == 'materielInfo') {
          const today = new Date()
          column.formatter = (row) => {
            if (row.details.length > 0) {
              const today = new Date();
              const closestDate = row.details
                .map(x => {
                  const date = new Date(x.effectiveDate);
                  const diffInDays = Math.ceil(Math.abs((today - date) / (1000 * 60 * 60 * 24)));
                  return { date, diffInDays };
                })
                .reduce((closest, current) => (current.diffInDays < closest.diffInDays ? current : closest))
                .date;
        // if (column.field == 'materielCode') {
        //   column.formatter = (row) => {
        //     var str = '';
        //     var list = row.materielCode.split(',');
        //     for (let index = 0; index < list.length; index++) {
        //       str += list[index] + '<br>';
        //     }
        //     return str = list[0] == "" ? "空箱" : str;
        //   }
        // }
        // if (column.field == 'batchNo') {
        //   column.formatter = (row) => {
        //     var str = '';
        //     var list = row.batchNo.split(',');
        //     for (let index = 0; index < list.length; index++) {
        //       str += list[index] + '<br>';
        //     }
        //     return str = list[0] == "" ? "无" : str;
        //   }
        // }
        // if (column.field == 'materielInfo') {
        //   const today = new Date()
        //   column.formatter = (row) => {
        //     if (row.details.length > 0) {
        //       const today = new Date();
        //       const closestDate = row.details
        //         .map(x => {
        //           const date = new Date(x.effectiveDate);
        //           const diffInDays = Math.ceil(Math.abs((today - date) / (1000 * 60 * 60 * 24)));
        //           return { date, diffInDays };
        //         })
        //         .reduce((closest, current) => (current.diffInDays < closest.diffInDays ? current : closest))
        //         .date;
              const daysSinceClosest = Math.ceil(Math.abs((today - closestDate) / (1000 * 60 * 60 * 24)));
              return '<span style="color: #F56C6C">' + daysSinceClosest + "天" + '</span>';
            } else {
              return '<span style="color: #F56C6C">' + "无保质期" + '</span>';
            }
        //       const daysSinceClosest = Math.ceil(Math.abs((today - closestDate) / (1000 * 60 * 60 * 24)));
        //       return '<span style="color: #F56C6C">' + daysSinceClosest + "天" + '</span>';
        //     } else {
        //       return '<span style="color: #F56C6C">' + "无保质期" + '</span>';
        //     }
          }
        }
        //   }
        // }
        if (column.field == 'sumStock') {
          column.formatter = (row) => {
            if (row.details.length > 0) {
@@ -93,7 +91,261 @@
          }
        }
        if (column.field === 'orderStatistics') {
          column.formatter = (row) => {
            // æ ¡éªŒdetails是否存在且有数据
            if (row.details && row.details.length > 0) {
              // æŒ‰barcode + supplyCode + BatchNo ç»„合维度分组统计stockQuantity总和,并记录单位(取第一个非空单位)
              const groupSumMap = row.details.reduce((acc, item) => {
                // èŽ·å–åˆ†ç»„å…³é”®å­—æ®µï¼Œä¸ºç©ºæ—¶èµ‹äºˆé»˜è®¤å€¼
                const supplyCode = item.supplyCode || '未知供应商编码';
                const batchNo = item.batchNo || '未知批次号';
                const materielCode = item.materielCode || '未知物料'; // ä¿ç•™åŽŸæœ‰ç‰©æ–™ç¼–ç 
                const quantity = Number(item.stockQuantity) || 0;
                const unit = item.unit || ''; // èŽ·å–å•ä½ï¼Œæ— åˆ™ä¸ºç©º
                // ç»„合分组键(可根据需要调整显示格式)
                const groupKey = `${supplyCode}|${batchNo}|${materielCode}`;
                // ç´¯åŠ æ•°é‡ï¼Œä¿ç•™ç¬¬ä¸€ä¸ªéžç©ºå•ä½
                acc[groupKey] = {
                  total: (acc[groupKey]?.total || 0) + quantity,
                  unit: acc[groupKey]?.unit || unit,
                  supplyCode,
                  batchNo,
                  materielCode
                };
                return acc;
              }, {});
              // æ¯ä¸ªåˆ†ç»„项生成独立div,跨行显示(包含所有分组维度和单位)
              const displayItems = Object.entries(groupSumMap).map(([_, data]) => {
                // å¤„理单位显示:有单位则加空格显示,无则不显示
                const unitText = data.unit ? ` ${data.unit}` : '';
                // ç»„装显示文本(可根据需求调整字段显示顺序和格式)
                return `<div style="line-height: 1.5; white-space: normal; margin-bottom: 4px;">
                  ä¾›åº”商编码:${data.supplyCode} | æ‰¹æ¬¡å·ï¼š${data.batchNo} | ç‰©æ–™ç¼–码:${data.materielCode}:${data.total}${unitText}
        </div>`;
              });
              const displayContent = displayItems.join('');
              return `<div style="color: #716cf5ff; white-space: normal; word-break: break-all;">${displayContent}</div>`;
            } else {
              return '<span style="color: #F56C6C">空箱</span>';
            }
          };
        }
        if (column.field == 'stockOrderNo') {
          column.formatter = (row) => {
            // æœ‰æ˜Žç»†æ•°æ®æ—¶å¤„理
            if (row.details && row.details.length > 0) {
              // æå–所有非空的orderNO并去重
              const uniqueOrderNOs = [...new Set(
                row.details.map(item => item.orderNo).filter(no => no) // è¿‡æ»¤ç©ºå•据号
              )];
              // æœ‰æœ‰æ•ˆå•据号则换行显示,否则显示默认文本
              if (uniqueOrderNOs.length > 0) {
                return `<span style="color: #F56C6C">${uniqueOrderNOs.join('<br>')}</span>`;
              } else {
                return '<span style="color: #F56C6C">暂无单据</span>';
              }
            } else {
              // æ— æ˜Žç»†æ•°æ®æ—¶æ˜¾ç¤ºé»˜è®¤æ–‡æœ¬
              return '<span style="color: #F56C6C">暂无单据</span>';
            }
          }
        }
      })
      let SelectTake = this.buttons.find(x => x.value == 'SelectStockTake');
      if (SelectTake) {
        // æ”¹ä¸ºç®­å¤´å‡½æ•°ç¡®ä¿this指向Vue组件实例
        SelectTake.onClick = async () => {
          // èŽ·å–é€‰ä¸­æ•°æ®ï¼ˆä¸ŽåŽŸé€»è¾‘ä¸€è‡´ï¼Œç¡®ä¿æ˜¯æ•°ç»„æ ¼å¼ï¼‰
          let stockViews = this.$refs.table.getSelected();
          // æ•°æ®æ ¡éªŒï¼šè‡³å°‘选择一条数据
          if (stockViews.length === 0) return ElMessage.error("请选择需要操作的数据!");
          // ç«™å°é€‰é¡¹ï¼ˆå¯æ ¹æ®å®žé™…业务调整选项值)
          const stationOptions = [
            { label: "站台2", value: "2-1" },
            { label: "站台3", value: "3-1" },
            { label: "站台4", value: "4-1" },
          ];
          // åˆ›å»ºå¼¹çª—挂载节点
          const mountNode = document.createElement("div");
          document.body.appendChild(mountNode);
          // è¡¨å•数据(绑定选中的站台)
          const formData = reactive({
            outStation: stationOptions[0].value, // é»˜è®¤é€‰ä¸­ç¬¬ä¸€ä¸ªç«™å°
          });
          // åˆ›å»ºå¼¹çª—VNode
          const vnode = createVNode(
            ElDialog,
            {
              title: "库存操作 - é€‰æ‹©å‡ºåº“站台",
              width: "500px",
              modelValue: true,
              appendToBody: true,
              "onUpdate:modelValue": (isVisible) => {
                if (!isVisible) {
                  render(null, mountNode);
                  document.body.removeChild(mountNode);
                }
              },
              style: {
                padding: "20px 0",
                borderRadius: "8px",
              },
            },
            {
              default: () =>
                h(
                  ElForm,
                  {
                    model: formData,
                    rules: {
                      outStation: [
                        { required: true, message: "请选择出库站台", trigger: "change" },
                      ],
                    },
                    ref: "stockTakeForm", // è¡¨å•ref标识
                    labelWidth: "100px",
                    style: {
                      padding: "0 30px",
                    },
                  },
                  [
                    // ç«™å°é€‰æ‹©ä¸‹æ‹‰æ¡†
                    h(ElFormItem, {
                      label: "出库站台",
                      prop: "outStation",
                      style: { marginBottom: "24px" },
                    }, [
                      h(ElSelect, {
                        placeholder: "请选择出库站台",
                        modelValue: formData.outStation,
                        "onUpdate:modelValue": (val) => {
                          formData.outStation = val;
                        },
                        style: {
                          width: "100%",
                          height: "40px",
                          borderRadius: "4px",
                          borderColor: "#dcdfe6",
                        },
                      }, stationOptions.map((station) =>
                        h(ElOption, { label: station.label, value: station.value })
                      )),
                    ]),
                    // åº•部按钮区域
                    h("div", {
                      style: {
                        textAlign: "right",
                        marginTop: "8px",
                        paddingRight: "4px",
                      },
                    }, [
                      // å–消按钮
                      h(ElButton, {
                        type: "text",
                        onClick: () => {
                          render(null, mountNode);
                          document.body.removeChild(mountNode);
                          ElMessage.info("取消库存操作");
                        },
                        style: { marginRight: "8px", color: "#606266" },
                      }, "取消"),
                      // ç¡®å®šæŒ‰é’®
                      h(ElButton, {
                        type: "primary",
                        onClick: async () => {
                          // ç¡®ä¿è¡¨å•ref已挂载
                          await this.$nextTick();
                          const formRef = vnode.component.refs.stockTakeForm;
                          if (!formRef) {
                            ElMessage.error("表单初始化失败,请重试");
                            return;
                          }
                          // è¡¨å•验证
                          try {
                            await formRef.validate();
                          } catch (err) {
                            return;
                          }
                          const requestBody = stockViews;
                          const outStation = formData.outStation;
                          try {
                            const url = `api/Task/TakeOutbound?outStation=${encodeURIComponent(outStation)}`;
                            const x = await this.http.post(
                              url, // å¸¦æŸ¥è¯¢å‚æ•°çš„URL
                              requestBody, // è¯·æ±‚体:stockViews数组
                              "数据处理中"
                            );
                            if (!x.status) {
                              ElMessage.error(x.message || "库存操作失败");
                              return;
                            }
                            ElMessage.success("操作成功");
                            this.refresh(); // åŽŸåˆ·æ–°é€»è¾‘ä¿ç•™
                          } catch (error) {
                            console.error("库存接口请求失败:", error);
                            ElMessage.error("请求失败,请稍后重试");
                          } finally {
                            // æ— è®ºæˆåŠŸå¤±è´¥ï¼Œå…³é—­å¼¹çª—
                            render(null, mountNode);
                            document.body.removeChild(mountNode);
                          }
                        },
                        style: { borderRadius: "4px", padding: "8px 20px" },
                      }, "确定操作"),
                    ]),
                  ]),
            }
          );
          // ç»‘定app上下文(确保弹窗内组件正常工作)
          vnode.appContext = this.$.appContext;
          render(vnode, mountNode);
        };
      }
      let SelectTakeArea = this.buttons.find(x => x.value == 'SelectStockAreaOut');
      if (SelectTakeArea) {
        SelectTakeArea.onClick = function () {
          let stockViews = this.$refs.table.getSelected();
          this.http
            .post("api/Task/AreaOutbound",stockViews, "数据处理中")
            .then((x) => {
              if (!x.status) return this.$message.error(x.message);
              this.$message.success("操作成功");
              this.refresh();
            });
        }
      }
      var SelectStockAreaIn = this.buttons.find(x => x.value == "SelectStockAreaIn");
      if (SelectStockAreaIn != null) {
        SelectStockAreaIn.onClick = () => {
          let rows = this.$refs.table.getSelected();
          if (rows.length == 0) {
              return this.$message.error("请先选择需要移库的数据!");
            }
          this.$refs.gridHeader.open();
        }
      }
    },
    onInited() {
      //框架初始化配置后