zhangwencui
2026-04-24 664bba7725ee0dcdcb29bb218a81f78f3f7aefc4
修改
已修改8个文件
227 ■■■■■ 文件已修改
src/api/productionManagement/processRoute.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/processRouteItem.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productProcessRoute.js 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ProcessParamListDialog.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/processRoute/processRouteItem/index.vue 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/index.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/processRoute.js
@@ -12,7 +12,7 @@
export function add(data) {
  return request({
    url: "/technologyRouting",
    url: "/technologyRouting/addTechRoute",
    method: "post",
    data: data,
  });
@@ -34,7 +34,7 @@
export function update(data) {
  return request({
    url: "/technologyRouting",
    url: "/technologyRouting/editTechRoute",
    method: "put",
    data: data,
  });
src/api/productionManagement/processRouteItem.js
@@ -82,3 +82,11 @@
    data: data,
  });
}
// 按工艺路线工序同步工序参数-生产订单
export function syncProcessParamItemOrder(data) {
  return request({
    url: "/productionOrderRoutingOperationParam/sync",
    method: "post",
    data: data,
  });
}
src/api/productionManagement/productProcessRoute.js
@@ -4,7 +4,7 @@
// 列表查询
export function findProductProcessRouteItemList(query) {
  return request({
    url: "/productProcessRoute/list",
    url: "/productionOrderRouting/list",
    method: "get",
    params: query,
  });
@@ -12,7 +12,7 @@
export function addOrUpdateProductProcessRouteItem(data) {
  return request({
    url: "/productProcessRoute/updateRouteItem",
    url: "/productionOrderRouting/updateRouteItem",
    method: "post",
    data: data,
  });
@@ -21,7 +21,7 @@
// 生产订单下:新增工艺路线项目
export function addRouteItem(data) {
  return request({
    url: "/productProcessRoute/addRouteItem",
    url: "/productionOrderRouting/addRouteItem",
    method: "post",
    data,
  });
@@ -30,7 +30,7 @@
// 获取生产订单关联的工艺路线主信息
export function listMain(orderId) {
  return request({
    url: "/productProcessRoute/listMain",
    url: "/productionOrderRouting/listMain",
    method: "get",
    params: { orderId },
  });
@@ -39,7 +39,7 @@
// 删除工艺路线项目(路由后拼接 id)
export function deleteRouteItem(id) {
  return request({
    url: `/productProcessRoute/deleteRouteItem/${id}`,
    url: `/productionOrderRouting/deleteRouteItem/${id}`,
    method: "delete",
  });
}
@@ -47,7 +47,7 @@
// 生产订单下:排序工艺路线项目
export function sortRouteItem(data) {
  return request({
    url: "/productProcessRoute/sortRouteItem",
    url: "/productionOrderRouting/sortRouteItem",
    method: "post",
    data,
  });
@@ -55,7 +55,7 @@
// 获取工序参数列表-生产订单
export function findProcessParamListOrder(query) {
  return request({
    url: `/productionOrderRouteItemParam/list`,
    url: `/productionOrderRoutingOperationParam/list`,
    method: "get",
    params: query,
  });
@@ -63,7 +63,7 @@
// 工艺路线参数新增-生产订单
export function addProcessRouteItemParamOrder(data) {
  return request({
    url: "/productionOrderRouteItemParam/add",
    url: "/productionOrderRoutingOperationParam",
    method: "post",
    data: data,
  });
@@ -71,7 +71,7 @@
// 工艺路线参数修改-生产订单
export function editProcessRouteItemParamOrder(data) {
  return request({
    url: "/productionOrderRouteItemParam/update",
    url: "/productionOrderRoutingOperationParam",
    method: "put",
    data: data,
  });
@@ -79,7 +79,7 @@
// 工艺路线参数删除-生产订单
export function delProcessRouteItemParamOrder(id) {
  return request({
    url: `/productionOrderRouteItemParam/delete/${id}`,
    url: `/productionOrderRoutingOperationParam/${id}`,
    method: "delete",
  });
}
src/components/ProcessParamListDialog.vue
@@ -374,10 +374,8 @@
    // 调用API新增参数
    if (props.pageType === "order") {
      addProcessRouteItemParamOrder({
        orderId: Number(props.orderId),
        // processId: props.process.id,
        routeItemId: props.process.id,
        // routeItemId: Number(props.routeId),
        productionOrderId: Number(props.orderId),
        technologyRoutingOperationParamId: props.process.id,
        paramId: selectedParam.value.id,
        standardValue: selectedParam.value.standardValue || "",
        isRequired: selectedParam.value.isRequired || 0,
@@ -428,8 +426,6 @@
        if (props.pageType === "order") {
          editProcessRouteItemParamOrder({
            id: editParamForm.value.id,
            // routeItemId: props.process.id,
            // paramId: editParamForm.value.paramId,
            standardValue: editParamForm.value.standardValue || "",
            isRequired: editParamForm.value.isRequired || 0,
          })
src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -232,7 +232,7 @@
              style="width: 100%">
      <el-table-column type="expand">
        <template #default>
          <el-form ref="form"
          <el-form ref="bomFormRef"
                   :model="bomDataValue">
            <el-table :data="bomDataValue.dataList"
                      row-key="tempId"
@@ -356,7 +356,7 @@
                       prop="model" />
    </el-table>
    <ProductSelectDialog v-if="bomDataValue.showProductDialog"
                         v-model:model-value="bomDataValue.showProductDialog"
                         v-model="bomDataValue.showProductDialog"
                         :single="true"
                         @confirm="handleBomProduct" />
    <!-- 新增/编辑弹窗 -->
@@ -385,8 +385,8 @@
                      prop="productModelId">
          <el-button type="primary"
                     @click="showProductSelectDialog = true">
            {{ form.productName && form.model
              ? `${form.productName} - ${form.model}`
            {{ form.productName
              ? (form.model ? `${form.productName} - ${form.model}` : form.productName)
              : '选择产品' }}
          </el-button>
        </el-form-item>
@@ -401,13 +401,13 @@
                      prop="isQuality">
          <el-switch v-model="form.isQuality"
                     :active-value="true"
                     inactive-value="false" />
                     :inactive-value="false" />
        </el-form-item>
        <el-form-item label="是否生产"
                      prop="isProduction">
          <el-switch v-model="form.isProduction"
                     :active-value="true"
                     inactive-value="false" />
                     :inactive-value="false" />
        </el-form-item>
      </el-form>
      <template #footer>
@@ -454,7 +454,10 @@
    batchDeleteProcessRouteItem,
    getProcessParamList,
  } from "@/api/productionManagement/processRouteItem.js";
  import { syncProcessParamItem } from "@/api/productionManagement/processRouteItem.js";
  import {
    syncProcessParamItem,
    syncProcessParamItemOrder,
  } from "@/api/productionManagement/processRouteItem.js";
  import {
    findProductProcessRouteItemList,
    deleteRouteItem,
@@ -469,6 +472,7 @@
    queryList,
    addBomDetail,
  } from "@/api/productionManagement/productStructure.js";
  import { useRoute } from "vue-router";
  import { ElMessageBox, ElMessage } from "element-plus";
  import Sortable from "sortablejs";
@@ -485,6 +489,7 @@
  const dialogVisible = ref(false);
  const operationType = ref("add"); // add | edit
  const formRef = ref(null);
  const bomFormRef = ref(null);
  const submitLoading = ref(false);
  const cardsContainer = ref(null);
  const tableRef = ref(null);
@@ -542,6 +547,19 @@
      type: "warning",
    })
      .then(() => {
        if (pageType.value === "order") {
          syncProcessParamItemOrder({
            replaceExisting: true,
            technologyRoutingOperationId: currentProcess.value.id,
          }).then(res => {
            if (res.code === 200) {
              ElMessage.success("同步成功");
              refreshParamList();
            } else {
              ElMessage.error(res.msg || "同步失败");
            }
          });
        } else {
        syncProcessParamItem({
          replaceExisting: true,
          technologyRoutingOperationId: currentProcess.value.id,
@@ -553,6 +571,7 @@
            ElMessage.error(res.msg || "同步失败");
          }
        });
        }
      })
      .catch(() => {});
  };
@@ -670,15 +689,20 @@
  // 产品选择
  const handleProductSelect = products => {
    console.log(products, "===products===");
    if (products && products.length > 0) {
      const product = products[0];
      form.value.productModelId = product.id;
      form.value.productName = product.productName;
      form.value.model = product.model;
      form.value.unit = product.unit || "";
      console.log(product, "product");
      form.value = {
        ...form.value,
        productModelId: product.id,
        productName: product.productName,
        model: product.model,
        unit: product.unit || "",
      };
      showProductSelectDialog.value = false;
      // 触发表单验证
      formRef.value?.validateField("productModelId");
      // formRef.value?.validateField("productModelId");
    }
  };
@@ -773,6 +797,8 @@
      productName: "",
      model: "",
      unit: "",
      isQuality: false,
      isProduction: false,
    };
    formRef.value?.resetFields();
  };
@@ -788,7 +814,7 @@
    currentProcess.value = row;
    const query = {
      technologyRoutingOperationId: row.id,
      orderId: orderId.value,
      productionOrderId: orderId.value,
    };
    const apiPromise =
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -1,91 +1,108 @@
<template>
  <div>
    <el-dialog v-model="dialogVisible" title="领料台账" width="1200px" @close="handleClose">
    <el-dialog v-model="dialogVisible"
               title="领料台账"
               width="1200px"
               @close="handleClose">
      <div class="material-toolbar">
        <el-button type="primary" @click="handleAddMaterialRow">新增</el-button>
        <el-button type="primary"
                   @click="handleAddMaterialRow">新增</el-button>
      </div>
      <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId">
        <el-table-column label="工序名称" min-width="180">
      <el-table v-loading="materialTableLoading"
                :data="materialTableData"
                border
                row-key="tempId">
        <el-table-column label="工序名称"
                         min-width="180">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.processName || "-" }}</span>
            <el-select
              v-else
            <el-select v-else
              v-model="row.processName"
              placeholder="请选择工序"
              clearable
              filterable
              style="width: 100%;"
              @change="val => handleProcessNameChange(row, val)"
            >
              <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.name" />
                       @change="val => handleProcessNameChange(row, val)">
              <el-option v-for="item in processOptions"
                         :key="item.id"
                         :label="item.name"
                         :value="item.name" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="原料名称" min-width="160">
        <el-table-column label="原料名称"
                         min-width="160">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.materialName || "-" }}</span>
            <el-button v-else type="primary" link @click="openMaterialProductSelect(row)">
            <el-button v-else
                       type="primary"
                       link
                       @click="openMaterialProductSelect(row)">
              {{ row.materialName || "选择原料" }}
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="原料型号" min-width="180">
        <el-table-column label="原料型号"
                         min-width="180">
          <template #default="{ row }">
            {{ row.materialModel || "-" }}
          </template>
        </el-table-column>
        <el-table-column label="需求数量" min-width="120">
        <el-table-column label="需求数量"
                         min-width="120">
          <template #default="{ row }">
            <span v-if="row.bom === true">{{ row.requiredQty ?? "-" }}</span>
            <el-input-number
              v-else
            <el-input-number v-else
              v-model="row.requiredQty"
              :min="0"
              :precision="3"
              :step="1"
              controls-position="right"
              style="width: 100%;"
              @change="val => handleRequiredQtyChange(row, val)"
            />
                             @change="val => handleRequiredQtyChange(row, val)" />
          </template>
        </el-table-column>
        <el-table-column label="计量单位" width="120">
        <el-table-column label="计量单位"
                         width="120">
          <template #default="{ row }">
            {{ row.unit || "-" }}
          </template>
        </el-table-column>
        <el-table-column label="领用数量" min-width="120">
        <el-table-column label="领用数量"
                         min-width="120">
          <template #default="{ row }">
            <el-input-number
              v-model="row.pickQty"
            <el-input-number v-model="row.pickQty"
              :min="0"
              :precision="3"
              :step="1"
              controls-position="right"
              style="width: 100%;"
            />
                             style="width: 100%;" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="90" fixed="right">
        <el-table-column label="操作"
                         width="90"
                         fixed="right">
          <template #default="{ $index, row }">
            <el-button v-if="row.bom !== true" type="danger" link @click="handleDeleteMaterialRow($index)">删除</el-button>
            <el-button v-if="row.bom !== true"
                       type="danger"
                       link
                       @click="handleDeleteMaterialRow($index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">保存</el-button>
          <el-button type="primary"
                     :loading="materialSaving"
                     @click="handleMaterialSave">保存</el-button>
          <el-button @click="dialogVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <ProductSelectDialog
      v-model="materialProductDialogVisible"
    <ProductSelectDialog v-model="materialProductDialogVisible"
      @confirm="handleMaterialProductConfirm"
      single
      request-url="/stockInventory/rawMaterials"
    />
                         single />
    <!-- request-url="/stockInventory/rawMaterials" -->
  </div>
</template>
@@ -136,8 +153,12 @@
const getProcessOptions = async () => {
  if (!props.orderRow?.id) return;
  const res = await findProductProcessRouteItemList({ orderId: props.orderRow.id });
  const routeList = Array.isArray(res?.data) ? res.data : res?.data?.records || [];
    const res = await findProductProcessRouteItemList({
      orderId: props.orderRow.id,
    });
    const routeList = Array.isArray(res?.data)
      ? res.data
      : res?.data?.records || [];
  const processMap = new Map();
  routeList.forEach(item => {
    const processId = item.processId;
@@ -160,7 +181,9 @@
  materialTableData.value = [];
  await getProcessOptions();
  try {
    const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id });
      const detailRes = await listMaterialPickingDetail({
        orderId: props.orderRow.id,
      });
    const detailList = Array.isArray(detailRes?.data)
      ? detailRes.data
      : detailRes?.data?.records || [];
@@ -168,7 +191,9 @@
      materialTableData.value = detailList.map(item => createMaterialRow(item));
      return;
    }
    const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id });
      const ledgerRes = await listMaterialPickingLedger({
        orderId: props.orderRow.id,
      });
    const ledgerList = Array.isArray(ledgerRes?.data)
      ? ledgerRes.data
      : ledgerRes?.data?.records || [];
@@ -214,7 +239,9 @@
};
const openMaterialProductSelect = row => {
  currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId);
    currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(
      item => item.tempId === row.tempId
    );
  materialProductDialogVisible.value = true;
};
@@ -224,8 +251,10 @@
  if (index < 0 || !materialTableData.value[index]) return;
  const product = products[0];
  const row = materialTableData.value[index];
  row.materialModelId = product.materialModelId || product.modelId || product.id;
  row.materialName = product.materialName || product.productName || product.name || "";
    row.materialModelId =
      product.materialModelId || product.modelId || product.id;
    row.materialName =
      product.materialName || product.productName || product.name || "";
  row.materialModel = product.materialModel || product.model || "";
  row.unit = product.unit || product.measureUnit || "";
  currentMaterialSelectRowIndex.value = -1;
src/views/productionManagement/productionOrder/index.vue
@@ -28,7 +28,7 @@
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="产品名称:">
          <el-input v-model="searchForm.productCategory"
          <el-input v-model="searchForm.productName"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
@@ -36,7 +36,7 @@
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="规格:">
          <el-input v-model="searchForm.specificationModel"
          <el-input v-model="searchForm.model"
                    placeholder="请输入"
                    clearable
                    prefix-icon="Search"
@@ -269,8 +269,8 @@
      customerName: "",
      salesContractNo: "",
      projectName: "",
      productCategory: "",
      specificationModel: "",
      productName: "",
      model: "",
    },
  });
  const { searchForm } = toRefs(data);
@@ -429,9 +429,9 @@
          id: data.id,
          bomId: data.bomId,
          processRouteCode: data.processRouteCode || "",
          productName: data.productName || "",
          model: data.model || "",
          bomNo: data.bomNo || "",
          productName: row.productName || "",
          model: row.model || "",
          bomNo: row.bomNo || "",
          description: data.description || "",
          orderId,
          type: "order",
@@ -449,8 +449,8 @@
      query: {
        id: row.id,
        bomNo: row.bomNo || "",
        productName: row.productCategory || "",
        productModelName: row.specificationModel || "",
        productName: row.productName || "",
        productModelName: row.model || "",
        orderId: row.id,
        type: "order",
      },
src/views/productionPlan/productionPlan/index.vue
@@ -343,7 +343,7 @@
    },
    {
      label: "已下发数量",
      prop: "assignedQuantity",
      prop: "quantityIssued",
      width: "120px",
      className: "spec-cell",
      // formatData: (cell, row) => (cell ? `${cell}${row.unit || "方"}` : 0),
@@ -618,9 +618,9 @@
        };
      }
      summary[category].totalAssignedQuantity += Number(
        (
          Number(row.qtyRequired || 0) - Number(row.assignedQuantity || 0)
        ).toFixed(4)
        (Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0)).toFixed(
          4
        )
      );
    });
@@ -668,7 +668,7 @@
  // 判断行是否可选择
  const isSelectable = row => {
    // 计算剩余数量
    const remainingQty = (row.qtyRequired || 0) - (row.assignedQuantity || 0);
    const remainingQty = (row.qtyRequired || 0) - (row.quantityIssued || 0);
    // 如果剩余数量小于等于0,禁止选择
    if (remainingQty <= 0) {
      return false;