gaoluyang
2026-05-18 da57fbd8e7fa021614fb32502fb1520ea4e34e1e
src/views/productionPlan/productionPlan/index.vue
@@ -13,6 +13,14 @@
                    style="width: 160px;"
                    @keyup.enter="handleQuery" />
        </el-form-item>
<!--        <el-form-item label="销售合同号:"-->
<!--                      prop="salesContractNo">-->
<!--          <el-input v-model="searchForm.salesContractNo"-->
<!--                    placeholder="请输入"-->
<!--                    clearable-->
<!--                    style="width: 160px;"-->
<!--                    @keyup.enter="handleQuery" />-->
<!--        </el-form-item>-->
        <el-form-item label="需求日期范围:"
                      prop="dateRange">
          <el-date-picker v-model="searchForm.dateRange"
@@ -88,6 +96,13 @@
        <template #qtyRequired="{ row }">
          {{ row.qtyRequired || '-' }}<span style="color:rgba(12, 46, 40, 0.76)"> {{ row.unit || '方' }}</span>
        </template>
        <template #salesContractNo="{ row }">
          <el-button type="primary"
                     text
                     link
                     @click="showDetail(row)">{{ row.salesContractNo }}
          </el-button>
        </template>
      </PIMTable>
    </div>
    <!-- 合并下发弹窗 -->
@@ -95,7 +110,7 @@
               destroy-on-close
               title="合并下发"
               width="600px">
      <el-form :model="mergeForm"
      <el-form :model="mergeForm" :rules="mergeFormRules"
               label-width="120px">
        <el-row :gutter="20">
          <el-col :span="10">
@@ -124,12 +139,24 @@
                           @change="onBlur"
                           style="width: 100%" />
        </el-form-item>
        <el-form-item label="车间" prop="workshopId" required>
          <el-select v-model="mergeForm.workshopId"
                     placeholder="请选择车间"
                     clearable
                     filterable
                     style="width: 100%">
            <el-option v-for="item in workshopOptions"
                       :key="item.id"
                       :label="item.name"
                       :value="item.id" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="isShowNewModal = false">取消</el-button>
          <el-button type="primary"
                     @click="handleMergeSubmit">确定下发</el-button>
          <el-button @click="isShowNewModal = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -221,9 +248,9 @@
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary"
                     @click="handleSubmit">确定</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
@@ -238,6 +265,7 @@
    toRefs,
    getCurrentInstance,
    computed,
    watch,
  } from "vue";
  import { useRouter } from "vue-router";
  import dayjs from "dayjs";
@@ -251,8 +279,10 @@
    productionPlanUpdate,
    productionPlanDelete,
    productionPlanCombine,
    exportProductionPlan,
  } from "@/api/productionPlan/productionPlan.js";
  import { productTreeList, modelListPage } from "@/api/basicData/product.js";
  import { workshopPage } from "@/api/basicData/workshop.js";
  import PIMTable from "./components/PIMTable.vue";
  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
@@ -264,11 +294,6 @@
    return Promise.resolve({ code: 200, msg: "同步成功" });
  };
  const exportProductionPlan = () => {
    console.log("Mock exportProductionPlan called");
    return Promise.resolve();
  };
  // const productionPlanCombine = payload => {
  //   console.log("Mock productionPlanCombine called with:", payload);
  //   return Promise.resolve({ code: 200, msg: "合并下发成功" });
@@ -278,45 +303,49 @@
    {
      label: "主生产计划号",
      prop: "mpsNo",
      width: "150px",
      minWidth: "150px",
      align: "center",
    },
    {
      label: "来源",
      prop: "source",
      width: "150px",
      dataType: "tag",
      formatType: params => {
        return params == "销售" ? "primary" : "info";
      },
      formatData: params => {
        return params == "销售" ? "销售" : "内部";
      },
    },
    // {
    //   label: "来源",
    //   prop: "source",
    //   width: "150px",
    //   dataType: "tag",
    //   formatType: params => {
    //     return params == "销售" ? "primary" : "info";
    //   },
    //   formatData: params => {
    //     return params == "销售" ? "销售" : "内部";
    //   },
    // },
    {
      label: "产品名称",
      prop: "productName",
      width: "200px",
      minWidth: "200px",
      dataType: "tag",
      formatType: params => {
        return "primary";
      },
      align: "center",
    },
    {
      label: "产品规格",
      prop: "model",
      width: "150px",
      minWidth: "150px",
      className: "spec-cell",
      align: "center",
    },
    {
      label: "单位",
      prop: "unit",
      width: "100px",
      align: "center",
    },
    {
      label: "所需数量",
      prop: "qtyRequired",
      width: "150px",
      align: "right",
      minWidth: "150px",
      align: "center",
      dataType: "slot",
      slot: "qtyRequired",
      className: "volume-cell",
@@ -343,32 +372,54 @@
        };
        return statusMap[cell] || "";
      },
      align: "center",
    },
    {
      label: "已下发数量",
      prop: "quantityIssued",
      width: "120px",
      minWidth: "120px",
      className: "spec-cell",
      align: "center",
      // formatData: (cell, row) => (cell ? `${cell}${row.unit || "方"}` : 0),
    },
    {
      label: "需求日期",
      prop: "requiredDate",
      width: "160px",
      minWidth: "160px",
      className: "date-cell",
      formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
      align: "center",
    },
    {
      label: "承诺日期",
      prop: "promisedDeliveryDate",
      width: "160px",
      minWidth: "160px",
      className: "date-cell",
      formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
      align: "center",
    },
    // {
    //   label: "销售合同号",
    //   prop: "salesContractNo",
    //   width: "200px",
    //   dataType: "slot",
    //   slot: "salesContractNo",
    // },
    // {
    //   label: "客户名称",
    //   prop: "customerName",
    //   width: "150px",
    // },
    // {
    //   label: "项目名称",
    //   prop: "projectName",
    //   width: "150px",
    // },
    {
      label: "备注",
      width: "150px",
      minWidth: "150px",
      prop: "remark",
      align: "center",
    },
    {
      dataType: "action",
@@ -382,7 +433,7 @@
          type: "primary",
          link: true,
          showHide: row => {
            return row.status == 0;
            return row.status == 0 && row.source != "销售";
          },
          clickFun: row => {
            handleEdit(row);
@@ -398,12 +449,13 @@
            mergeForm.productName = row.productName || "";
            mergeForm.model = row.model || "";
            mergeForm.totalAssignedQuantity =
              Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
                Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
            mergeForm.planCompleteTime = row.requiredDate || "";
            mergeForm.productId = row.productId || "";
            mergeForm.ids = [row.id];
            mergeForm.workshopId = row.workshopId ?? undefined;
            sumAssignedQuantity.value =
              Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
                Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
            isShowNewModal.value = true;
          },
        },
@@ -430,6 +482,12 @@
  });
  const selectedRows = ref([]);
  const mergeFormRules = {
    workshopId: [
      { required: true, message: '请选择车间', trigger: 'change' }
    ]
  }
  // 产品类别汇总统计数据
  const categorySummary = ref([]);
  // 产品类别汇总弹窗控制
@@ -444,6 +502,44 @@
    totalAssignedQuantity: 0,
    planCompleteTime: "",
    productId: "",
    workshopId: undefined,
    ids: [],
  });
  const workshopOptions = ref([]);
  function parseWorkshopPagePayload(res) {
    const payload = res?.data;
    if (!payload) {
      return { records: [], total: 0 };
    }
    if (Array.isArray(payload)) {
      return { records: payload, total: payload.length };
    }
    const records = payload.records ?? payload.list ?? payload.rows ?? [];
    const total = Number(payload.total ?? payload.totalCount ?? 0);
    return { records: Array.isArray(records) ? records : [], total };
  }
  const fetchWorkshopOptions = () => {
    workshopPage({
      name: "",
      principal: "",
      contactPhone: "",
      current: 1,
      size: 999,
    }).then(res => {
      if (res.code === 200) {
        const { records } = parseWorkshopPagePayload(res);
        workshopOptions.value = records;
      }
    });
  };
  watch(isShowNewModal, val => {
    if (val) {
      fetchWorkshopOptions();
    }
  });
  // 导入相关
@@ -568,6 +664,7 @@
  const data = reactive({
    searchForm: {
      mpsNo: "",
      salesContractNo: "",
      productName: "",
      model: "",
      status: "",
@@ -596,6 +693,7 @@
    }
    Object.assign(searchForm.value, {
      mpsNo: "",
      salesContractNo: "",
      productName: "",
      model: "",
      status: "",
@@ -716,9 +814,18 @@
    mergeForm.planCompleteTime = firstRow.requiredDate || "";
    mergeForm.productId = firstRow.productId || "";
    mergeForm.ids = selectedRows.value.map(row => row.id);
    mergeForm.workshopId = firstRow.workshopId ?? undefined;
    // 打开弹窗
    isShowNewModal.value = true;
  };
  const showDetail = row => {
    router.push({
      path: "/salesManagement/salesLedger",
      query: {
        salesContractNo: row.salesContractNo,
      },
    });
  };
  // 处理合并下发提交
@@ -727,6 +834,10 @@
      ElMessage.warning("请输入生产数量");
      return;
    }
    if(!mergeForm.workshopId){
      ElMessage.warning("请选择车间");
      return;
    }
    console.log(sumAssignedQuantity.value, "sumAssignedQuantity");
    // 验证totalAssignedQuantity不能大于总方数