张诺
6 小时以前 b07dcaaddf964f5ca45ea204c6037d8d62c6b4ad
feat(产品结构): 新增按BOM添加功能并优化产品结构管理

- 新增按BOM添加功能,支持选择父项产品并添加其BOM结构
- 优化产品结构详情页,调整按钮顺序和文案,增加"按BOM添加"按钮
- 修改规格字段为图纸编号,新增规格型号字段显示
- 完善导入功能,增加错误文件下载处理
- 调整产品结构列表页按钮顺序和字段显示
- 新增产品结构记录接口用于生产订单领料
- 优化产品接口,新增分页查询和模板下载
- 移除项目详情路由配置
已添加1个文件
已修改6个文件
485 ■■■■ 文件已修改
src/api/basicData/product.js 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productStructure.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productStructureRecord.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/Detail/index.vue 326 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/StructureEdit.vue 47 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productStructure/index.vue 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/basicData/product.js
@@ -1,6 +1,14 @@
// äº§å“ç»´æŠ¤é¡µé¢æŽ¥å£
import request from '@/utils/request'
// äº§å“åˆ—表查询
export function productListPage(query) {
    return request({
        url: '/basic/product/listPage',
        method: 'get',
        params: query
    })
}
// äº§å“æ ‘查询
export function productTreeList(query) {
    return request({
@@ -56,12 +64,11 @@
        params: query
    })
}
//  ä¸‹è½½äº§å“å¯¼å…¥æ¨¡æ¿
export function downloadProductModelImportTemplate() {
// ä¸‹è½½äº§å“å¯¼å…¥æ¨¡æ¿
export function downloadTemplate() {
    return request({
        url: '/basic/product/export',
        url: '/basic/product/downloadTemplate',
        method: 'get',
        responseType: 'blob'
    })
}
}
src/api/productionManagement/productStructure.js
@@ -9,6 +9,14 @@
  });
}
// æ ¹æ®BOM ID查询父项产品
export function listByBomIdIsParent(bomId) {
  return request({
    url: "/productStructure/listBybomIdIsParent/" + bomId,
    method: "get",
  });
}
export function add(data) {
  return request({
    url: "/productStructure",
src/api/productionManagement/productStructureRecord.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
// ç”Ÿäº§è®¢å•领料记录接口
import request from "@/utils/request";
// æ ¹æ®è®¢å•ID查询物料清单(领料数据)
export function listPage(query) {
  return request({
    url: "/productStructureRecord/listPage",
    method: "get",
    params: query,
  });
}
// é¢†æ–™æäº¤
export function pick(data) {
  return request({
    url: "/productStructureRecord/pick",
    method: "post",
    data: data,
  });
}
src/router/index.js
@@ -106,19 +106,6 @@
      },
    ],
  },
  {
    path: "/projectManagement/Management/detail",
    component: Layout,
    hidden: true,
    children: [
      {
        path: ":id",
        component: () => import("@/views/projectManagement/Management/projectDetail.vue"),
        name: "ProjectManagementDetail",
        meta: { title: "项目详情", activeMenu: "/projectManagement/Management" },
      },
    ],
  },
];
// åŠ¨æ€è·¯ç”±ï¼ŒåŸºäºŽç”¨æˆ·æƒé™åŠ¨æ€åŽ»åŠ è½½
src/views/productionManagement/productStructure/Detail/index.vue
@@ -2,16 +2,21 @@
  <div class="app-container">
    <PageHeader content="产品结构详情">
      <template #right-button>
        <el-button v-if="dataValue.isEdit && !isOrderPage"
                   @click="cancelEdit">取消
        </el-button>
        <el-button v-if="!dataValue.isEdit && !isOrderPage"
                   type="primary"
                   @click="dataValue.isEdit = true">编辑
        </el-button>
        <el-button v-if="dataValue.isEdit && !isOrderPage"
                   type="primary"
                   @click="cancelEdit">取消
                   @click="dataValue.isEdit = true">点击进行修改
        </el-button>
        <el-button v-if="!isOrderPage"
                   type="primary"
                   @click="openBomAddDialog"
                   :disabled="!dataValue.isEdit">
          <el-icon><Document /></el-icon> æŒ‰BOM添加
        </el-button>
        <el-button v-if="!isOrderPage"
                   type="success"
                   :loading="dataValue.loading"
                   @click="submit"
                   :disabled="!dataValue.isEdit">确认
@@ -34,30 +39,30 @@
                      style="width: 100%">
              <el-table-column prop="productName"
                               label="产品" />
              <el-table-column prop="model"
                               label="规格">
                <template #default="{ row, $index }">
                  <el-form-item v-if="dataValue.isEdit"
                                :rules="[{ required: true, message: '请选择规格', trigger: ['blur','change'] }]"
                                style="margin: 0">
                    <el-select v-model="row.model"
                               placeholder="请选择规格"
                               clearable
                               :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
                               style="width: 100%"
                               @visible-change="(v) => { if (v) openDialog(row.tempId) }">
                      <el-option v-if="row.model"
                                 :label="row.model"
                                 :value="row.model" />
                    </el-select>
                  </el-form-item>
                </template>
              </el-table-column>
                            <el-table-column prop="model"
                                                             label="图纸编号">
                                <template #default="{ row, $index }">
                                    <el-form-item v-if="dataValue.isEdit"
                                                            :rules="[{ required: true, message: '请选择规格', trigger: ['blur','change'] }]"
                                                            style="margin: 0">
                                        <el-select v-model="row.model"
                                                             placeholder="请选择规格"
                                                             clearable
                                                             :disabled="!dataValue.isEdit || dataValue.dataList.some(item => (item as any).tempId === row.tempId)"
                                                             style="width: 100%"
                                                             @visible-change="(v) => { if (v) openDialog(row.tempId) }">
                                            <el-option v-if="row.model"
                                                                 :label="row.model"
                                                                 :value="row.model" />
                                        </el-select>
                                    </el-form-item>
                                </template>
                            </el-table-column>
              <el-table-column prop="processName"
                               label="消耗工序">
                               label="工序">
                <template #default="{ row, $index }">
                  <el-form-item v-if="dataValue.isEdit"
                                :rules="dataValue.dataList.some(item => (item as any).tempId === row.tempId) ? [] : [{ required: true, message: '请选择消耗工序', trigger: 'change' }]"
                                :rules="dataValue.dataList.some(item => (item as any).tempId === row.tempId) ? [] : [{ required: true, message: '请选工序', trigger: 'change' }]"
                                style="margin: 0">
                    <el-select v-model="row.processId"
                               placeholder="请选择"
@@ -74,10 +79,10 @@
                </template>
              </el-table-column>
              <el-table-column prop="unitQuantity"
                               label="单位产出所需数量">
                               label="单位用量">
                <template #default="{ row, $index }">
                  <el-form-item v-if="dataValue.isEdit"
                                :rules="[{ required: true, message: '请输入单位产出所需数量', trigger: ['blur','change'] }]"
                                :rules="[{ required: true, message: '请输入单位用量', trigger: ['blur','change'] }]"
                                style="margin: 0">
                    <el-input-number v-model="row.unitQuantity"
                                     :min="0"
@@ -139,16 +144,43 @@
          </el-form>
        </template>
      </el-table-column>
      <el-table-column label="BOM编号"
      <el-table-column v-if="!isOrderPage"
                       label="BOM编号"
                       prop="bomNo" />
      <el-table-column label="产品名称"
                       prop="productName" />
      <el-table-column label="规格型号"
                       prop="model" />
            <el-table-column label="图纸编号"
                                                         prop="model" />
    </el-table>
    <product-select-dialog v-if="dataValue.showProductDialog"
                           v-model:model-value="dataValue.showProductDialog"
                           @confirm="handleProduct" />
    <!-- æŒ‰BOM添加弹窗 -->
    <el-dialog v-model="bomAddDialogVisible" title="按BOM添加" width="500px" @close="closeBomAddDialog">
      <el-form ref="bomAddFormRef" :model="bomAddForm" :rules="bomAddRules" label-width="100px">
        <el-form-item label="父项产品" prop="parentProductId">
          <el-select v-model="bomAddForm.parentProductId" placeholder="请选择" clearable filterable
            style="width: 100%" @change="handleBomParentProductChange">
            <el-option v-for="item in parentProductOptions" :key="item.id"
              :label="`${item.model || item.productCode || item.id} | ${item.productName}`"
              :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="用量系数" prop="coefficient" style="margin-top: 20px;">
          <el-input-number v-model="bomAddForm.coefficient" :min="0.01" :precision="2" :step="1"
            controls-position="right" style="width: 100%" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitBomAdd">确定</el-button>
        <el-button @click="closeBomAddDialog">取消</el-button>
      </template>
    </el-dialog>
    <!-- é«˜çº§é€‰æ‹©äº§å“å¼¹çª— -->
    <product-select-dialog v-if="showAdvancedProductDialog" v-model:model-value="showAdvancedProductDialog"
      @confirm="handleAdvancedProductSelect" />
  </div>
</template>
@@ -161,11 +193,14 @@
    reactive,
    ref,
  } from "vue";
  import { queryList, add } from "@/api/productionManagement/productStructure.js";
  import { queryList, add, listByBomIdIsParent } from "@/api/productionManagement/productStructure.js";
  import { listProcessBom } from "@/api/productionManagement/productionOrder.js";
  import { list } from "@/api/productionManagement/productionProcess";
  import { productListPage } from "@/api/basicData/product.js";
  import { listPage as listBomPage } from "@/api/productionManagement/productBom.js";
  import { ElMessage } from "element-plus";
  import { useRoute, useRouter } from "vue-router";
  import { Search, Document } from '@element-plus/icons-vue'
  defineComponent({
    name: "StructureEdit",
@@ -192,6 +227,7 @@
  // ä»Žè·¯ç”±å‚数获取产品信息
  const routeBomNo = computed(() => route.query.bomNo || "");
  const routeProductName = computed(() => route.query.productName || "");
  const routeDrawingNumber = computed(() => route.query.drawingNumber || "");
  const routeProductModelName = computed(
    () => route.query.productModelName || ""
  );
@@ -212,9 +248,26 @@
    isEdit: false,
  });
  // æŒ‰BOM添加相关
  const bomAddDialogVisible = ref(false);
  const bomAddFormRef = ref();
  const parentProductOptions = ref([]);
  const selectedBomProduct = ref(null);
  const selectedBomTreeData = ref([]); // ä¿å­˜é€‰ä¸­äº§å“æ—¶èŽ·å–çš„BOM树数据
  const showAdvancedProductDialog = ref(false);
  const bomAddForm = reactive({
    parentProductId: undefined,
    coefficient:1
  });
  const bomAddRules = {
    parentProductId: [{ required: true, message: "请选择父项产品", trigger: "change" }],
    coefficient: [{ required: true, message: "请输入用量系数", trigger: "blur" }]
  };
  const tableData = reactive([
    {
      productName: "",
      drawingNumber: "",
      model: "",
      bomNo: "",
    },
@@ -293,6 +346,7 @@
    dataValue.dataList.map(item => {
      if (item.tempId === dataValue.currentRowName) {
        item.productName = productData.productName;
        item.drawingNumber = productData.drawingNumber || "";
        item.model = productData.model;
        item.productModelId = productData.id;
        item.unit = productData.unit || "";
@@ -305,6 +359,7 @@
  const childItem = (item: any, tempId: any, productData: any) => {
    if (item.tempId === tempId) {
      item.productName = productData.productName;
      item.drawingNumber = productData.drawingNumber || "";
      item.model = productData.model;
      item.productModelId = productData.id;
      item.unit = productData.unit || "";
@@ -332,13 +387,8 @@
        isValid = false;
        return;
      }
      if (!isTopLevel && !item.processId) {
        ElMessage.error("请选择消耗工序");
        isValid = false;
        return;
      }
      if (!item.unitQuantity) {
        ElMessage.error("请输入单位产出所需数量");
        ElMessage.error("请输入单位用量");
        isValid = false;
        return;
      }
@@ -503,9 +553,155 @@
    fetchData();
  };
  // èŽ·å–çˆ¶é¡¹äº§å“åˆ—è¡¨
  const getParentProductList = async () => {
    try {
      const { data } = await listBomPage({ current: 1, size: 1000 });
      parentProductOptions.value = data?.records || [];
    } catch (error) {
      console.error("获取父项产品列表失败:", error);
      parentProductOptions.value = [];
    }
  };
  // æ‰“开按BOM添加弹窗
  const openBomAddDialog = () => {
    bomAddDialogVisible.value = true;
    bomAddForm.parentProductId = undefined;
    bomAddForm.coefficient = 1;
    selectedBomProduct.value = null;
    getParentProductList();
  };
  // å…³é—­æŒ‰BOM添加弹窗
  const closeBomAddDialog = () => {
    bomAddDialogVisible.value = false;
    bomAddFormRef.value?.resetFields();
    selectedBomProduct.value = null;
  };
  // æ‰“开高级选择
  const openAdvancedSelect = () => {
    showAdvancedProductDialog.value = true;
  };
  // çˆ¶é¡¹äº§å“å˜æ›´
  const handleBomParentProductChange = async (val) => {
    if (val) {
      const product = parentProductOptions.value.find(item => item.id === val);
      selectedBomProduct.value = product || null;
      console.log(val)
      // ç›´æŽ¥ç”¨é€‰ä¸­çš„ BOM ID è°ƒç”¨ listByBomIdIsParent
      const { data: treeData } = await listByBomIdIsParent(val);
      selectedBomTreeData.value = treeData || [];
      // å°†äºŒçº§æ ‘中的产品添加到父项产品选项(从第二级开始)
      const addTreeToOptions = (items: any[]) => {
        items.forEach((item: any) => {
          // è·³è¿‡ç¬¬ä¸€çº§ï¼Œåªæ·»åŠ ç¬¬äºŒçº§åŠä»¥ä¸‹çš„äº§å“
          if (item.children && item.children.length > 0) {
            item.children.forEach((child: any) => {
              const exists = parentProductOptions.value.some(opt => opt.id === child.id);
              if (!exists) {
                parentProductOptions.value.push({
                  id: child.id,
                  productName: child.productName,
                  model: child.model,
                  productCode: child.model,
                  spec: child.drawingNumber,
                  drawingNumber: child.drawingNumber,
                  stockQuantity: child.stockQuantity || 0
                });
              }
              // é€’归添加子项
              if (child.children && child.children.length > 0) {
                addTreeToOptions([child]);
              }
            });
          }
        });
      };
      if (selectedBomTreeData.value.length > 0) {
        addTreeToOptions(selectedBomTreeData.value);
      }
    } else {
      selectedBomProduct.value = null;
      selectedBomTreeData.value = [];
    }
  };
  // æäº¤æŒ‰BOM添加
  const submitBomAdd = () => {
    bomAddFormRef.value.validate(async (valid) => {
      if (!valid) return;
      const product = parentProductOptions.value.find(item => item.id === bomAddForm.parentProductId);
      if (!product) {
        ElMessage.error("未找到选中的产品");
        return;
      }
      try {
        // ä½¿ç”¨é€‰æ‹©äº§å“æ—¶ä¿å­˜çš„BOM树数据
        const bomItems = selectedBomTreeData.value || [];
        if (bomItems.length === 0) {
          ElMessage.warning("该产品没有BOM信息");
          return;
        }
        // åˆ—表的第一级已经存在,把BOM数据作为第一级的子项(第二级)添加
        if (dataValue.dataList.length > 0) {
          const firstLevelItem = dataValue.dataList[0];
          // æŠŠBOM数据添加到第一级的children中
          const addBomItemsRecursively = (items: any[], parentItem: any) => {
            items.forEach((item: any) => {
              const newItem: any = {
                parentId: item.parentId || "",
                parentTempId: parentItem.tempId || "",
                productName: item.productName || "",
                productId: item.productId || item.productModelId || "",
                model: item.model || "",
                productModelId: item.productModelId || "",
                drawingNumber: item.drawingNumber || "",
                processId: item.processId || "",
                processName: item.processName || "",
                unitQuantity: (item.unitQuantity || 0) * bomAddForm.coefficient,
                demandedQuantity: (item.demandedQuantity || 0) * bomAddForm.coefficient,
                unit: item.unit || "",
                children: [],
                tempId: new Date().getTime() + Math.random(),
              };
              // æ·»åŠ åˆ°çˆ¶é¡¹çš„children
              if (!parentItem.children) {
                parentItem.children = [];
              }
              parentItem.children.push(newItem);
              // é€’归处理子项
              if (item.children && item.children.length > 0) {
                addBomItemsRecursively(item.children, newItem);
              }
            });
          };
          addBomItemsRecursively(bomItems, firstLevelItem);
        }
        ElMessage.success("添加成功");
        closeBomAddDialog();
      } catch (error) {
        console.error("按BOM添加失败:", error);
        ElMessage.error("添加失败");
      }
    });
  };
  onMounted(async () => {
    // ä»Žè·¯ç”±å‚数回显数据
    tableData[0].productName = routeProductName.value as string;
    tableData[0].drawingNumber = routeDrawingNumber.value as string;
    tableData[0].model = routeProductModelName.value as string;
    tableData[0].bomNo = routeBomNo.value as string;
@@ -518,4 +714,56 @@
    await fetchProcessOptions();
    await fetchData();
  });
</script>
</script>
<style scoped>
.selected-product-info {
  background-color: #f5f7fa;
  border-radius: 4px;
  padding: 16px;
  margin: 10px 0;
  position: relative;
}
.product-info-row {
  display: flex;
  margin-bottom: 8px;
  font-size: 14px;
}
.product-info-row:last-child {
  margin-bottom: 0;
}
.info-label {
  color: #909399;
  width: 70px;
  flex-shrink: 0;
}
.info-value {
  color: #303133;
  flex: 1;
}
.stock-info-box {
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  text-align: center;
}
.stock-number {
  font-size: 28px;
  font-weight: bold;
  color: #303133;
  line-height: 1;
  margin-bottom: 4px;
}
.stock-label {
  font-size: 12px;
  color: #909399;
}
</style>
src/views/productionManagement/productStructure/StructureEdit.vue
@@ -35,27 +35,30 @@
              <el-table-column prop="productName"
                               label="产品"
                               width="150" />
              <el-table-column prop="model"
                               label="规格"
                               width="150">
                <template #default="{ row, $index }">
                  <el-form-item v-if="dataValue.isEdit"
                                :prop="`dataList.${$index}.model`"
                                :rules="[{ required: true, message: '请选择规格', trigger: ['blur','change'] }]"
                                style="margin: 0">
                    <el-select v-model="row.model"
                               placeholder="请选择产品"
                               clearable
                               :disabled="!dataValue.isEdit"
                               style="width: 100%"
                               @visible-change="(v) => { if (v) openDialog($index) }">
                      <el-option v-if="row.model"
                                 :label="row.model"
                                 :value="row.model" />
                    </el-select>
                  </el-form-item>
                </template>
              </el-table-column>
                            <el-table-column prop="model"
                                                             label="图纸编号"
                                                             width="150">
                                <template #default="{ row, $index }">
                                    <el-form-item v-if="dataValue.isEdit"
                                                                :prop="`dataList.${$index}.model`"
                                                                :rules="[{ required: true, message: '请选择图纸编号', trigger: ['blur','change'] }]"
                                                                style="margin: 0">
                                        <el-select v-model="row.model"
                                                             placeholder="请选择产品"
                                                             clearable
                                                             :disabled="!dataValue.isEdit"
                                                             style="width: 100%"
                                                             @visible-change="(v) => { if (v) openDialog($index) }">
                                            <el-option v-if="row.model"
                                                                 :label="row.model"
                                                                 :value="row.model" />
                                        </el-select>
                                    </el-form-item>
                                </template>
                            </el-table-column>
              <el-table-column prop="drawingNumber"
                               label="规格型号"
                               width="150" />
              <el-table-column prop="processId"
                               label="消耗工序"
                               width="150">
@@ -156,7 +159,7 @@
      </el-table-column>
      <el-table-column label="产品编码" prop="productCode" />
      <el-table-column label="产品名称" prop="productName" />
      <el-table-column label="规格型号" prop="model" />
      <el-table-column label="图纸编号" prop="model" />
      <el-table-column label="单位" prop="unit" />
    </el-table>
src/views/productionManagement/productStructure/index.vue
@@ -1,11 +1,11 @@
<template>
  <div class="app-container">
    <div style="text-align: right; margin-bottom: 10px;">
      <el-button type="primary" @click="handleAdd">新增</el-button>
      <el-button type="info" plain icon="Upload" @click="handleImport"
        v-hasPermi="['product:bom:import']">导入</el-button>
      <el-button type="warning" plain icon="Download" @click="handleExport" :disabled="selectedRows.length !== 1"
        v-hasPermi="['product:bom:export']">导出</el-button>
      <el-button type="primary" @click="handleAdd">新增</el-button>
      <el-button type="danger" plain @click="handleBatchDelete" :disabled="selectedRows.length === 0">删除</el-button>
    </div>
    <PIMTable rowKey="id" :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true"
@@ -34,8 +34,8 @@
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="handleSubmit">确定</el-button>
        <el-button @click="closeDialog">取消</el-button>
        <el-button type="primary" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>
@@ -45,7 +45,7 @@
    <!-- BOM导入对话框 -->
    <ImportDialog ref="uploadRef" v-model="upload.open" :title="upload.title" :action="upload.url"
      :headers="upload.headers" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress"
      :on-success="handleFileSuccess" :show-download-template="true" @confirm="submitFileForm"
      :on-success="handleFileSuccess" :on-error="handleFileError" :show-download-template="true" @confirm="submitFileForm"
      @download-template="handleDownloadTemplate" @close="handleImportClose" />
  </div>
</template>
@@ -77,11 +77,11 @@
    minWidth: 160
  },
  {
    label: "规格型号",
    prop: "productModelName",
    minWidth: 140
  },
    {
        label: "图纸编号",
        prop: "productModelName",
        minWidth: 140
    },
  {
    label: "版本号",
    prop: "version",
@@ -334,7 +334,7 @@
};
//  æ–‡ä»¶ä¸Šä¼ æˆåŠŸå¤„ç†
const handleFileSuccess = (response, file, fileList) => {
const handleFileSuccess = (response, file) => {
  upload.open = false;
  upload.isUploading = false;
  proxy.$refs["uploadRef"].clearFiles();
@@ -342,13 +342,42 @@
    proxy.$modal.msgSuccess(response.msg || "导入成功");
    getList();
  } else {
    proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
    proxy.$modal.msgError(response.msg || "导入失败");
  }
};
// æäº¤ä¸Šä¼ æ–‡ä»¶
// æ–‡ä»¶ä¸Šä¼ å¤±è´¥å¤„理 - åŽç«¯è¿”回错误文件流
const handleFileError = (error, file) => {
  upload.open = false;
  upload.isUploading = false;
  proxy.$refs["uploadRef"].clearFiles();
  // error å¯èƒ½æ˜¯ Blob å¯¹è±¡ï¼ˆåŽç«¯è¿”回的错误文件)
  if (error instanceof Blob) {
    // ä¸‹è½½é”™è¯¯æ–‡ä»¶
    const blob = error;
    const downloadElement = document.createElement('a');
    const href = window.URL.createObjectURL(blob);
    downloadElement.href = href;
    downloadElement.download = "导入错误数据.xlsx";
    document.body.appendChild(downloadElement);
    downloadElement.click();
    document.body.removeChild(downloadElement);
    window.URL.revokeObjectURL(href);
    proxy.$modal.msgError("导入失败,请查看下载的错误文件");
  } else if (error && error.msg) {
    // åŽç«¯è¿”回的错误信息
    proxy.$modal.msgError(error.msg);
  } else {
    // æ™®é€šé”™è¯¯
    proxy.$modal.msgError("导入失败");
  }
};
// æäº¤ä¸Šä¼ æ–‡ä»¶ - çŽ°åœ¨ç”± ImportDialog å†…部处理
const submitFileForm = () => {
  proxy.$refs["uploadRef"].submit();
  // ImportDialog çš„ handleConfirm ä¼šè°ƒç”¨ uploadRef.value.submit()
  // è¿™é‡Œä¸éœ€è¦é¢å¤–操作
};
//  å¯¼å‡ºæŒ‰é’®æ“ä½œ
@@ -420,6 +449,7 @@
    path: '/productionManagement/productStructureDetail',
    query: {
      id: row.id,
      drawingNumber: row.drawingNumber || "",
      bomNo: row.bomNo || '',
      productName: row.productName || '',
      productModelName: row.productModelName || ''