src/views/basicData/product/ProductSelectDialog.vue
@@ -8,14 +8,14 @@ :model="query" class="mb-2 search-form"> <el-form-item label="产品名称"> <el-input v-model="query.materialName" <el-input v-model="query.productName" size="small" placeholder="输入产品名称" clearable @keyup.enter="onSearch" /> </el-form-item> <el-form-item label="规格"> <el-input v-model="query.specification" <el-input v-model="query.model" size="small" placeholder="输入规格" clearable @@ -42,7 +42,7 @@ :data="tableData" height="420" highlight-current-row row-key="skuId" row-key="id" @selection-change="handleSelectionChange" @select="handleSelect"> <el-table-column type="selection" @@ -50,16 +50,16 @@ <el-table-column type="index" label="序号" width="60" /> <el-table-column prop="materialName" <el-table-column prop="productName" label="产品名称" min-width="160" /> <el-table-column prop="materialCode" label="物料编码" min-width="200" /> <el-table-column prop="specification" <el-table-column prop="model" label="规格" min-width="200" /> <el-table-column prop="baseUnit" <el-table-column prop="unit" label="单位" min-width="160" /> </el-table> @@ -90,11 +90,11 @@ import { modelListPage } from "@/api/basicData/newProduct"; export type ProductRow = { skuId: number; specification: string; id: number; model: string; materialCode: string; baseUnit?: string; materialName?: string; unit?: string; productName?: string; }; const props = defineProps<{ @@ -110,9 +110,9 @@ }); const query = reactive({ specification: "", model: "", materialCode: "", materialName: "", productName: "", }); const page = reactive({ @@ -157,7 +157,7 @@ nextTick(() => { if (tableRef.value) { tableData.value.forEach(item => { if (item.skuId !== row.skuId) { if (item.id !== row.id) { tableRef.value.toggleRowSelection(item, false); } }); @@ -173,9 +173,9 @@ } function onReset() { query.specification = ""; query.model = ""; query.materialCode = ""; query.materialName = ""; query.productName = ""; page.pageNum = 1; loadData(); } @@ -205,9 +205,9 @@ try { multipleSelection.value = []; // 翻页/搜索后清空选择更符合预期 const res: any = await modelListPage({ specification: query.specification.trim(), model: query.model.trim(), materialCode: query.materialCode.trim(), materialName: query.materialName.trim(), productName: query.productName.trim(), type: 1, current: page.pageNum, size: page.pageSize, src/views/basicData/product/index.vue
@@ -84,7 +84,7 @@ </el-button> <ImportExcel :product-id="currentId" @uploadSuccess="getModelList" /> <el-input v-model="specification" <el-input v-model="model" placeholder="规格型号" style="width: 150px" clearable @@ -121,8 +121,8 @@ <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="产品名称:" prop="materialName"> <el-input v-model="form.materialName" prop="productName"> <el-input v-model="form.productName" placeholder="请输入产品名称" maxlength="20" show-word-limit @@ -168,8 +168,8 @@ <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="基本单位:" prop="baseUnit"> <el-input v-model="form.baseUnit" prop="unit"> <el-input v-model="form.unit" placeholder="请输入基本单位" clearable @keydown.enter.prevent /> @@ -210,8 +210,8 @@ <el-row> <el-col :span="24"> <el-form-item label="规格型号:" prop="specification"> <el-input v-model="modelForm.specification" prop="model"> <el-input v-model="modelForm.model" placeholder="请输入规格型号" clearable @keydown.enter.prevent /> @@ -327,7 +327,7 @@ const expandedKeys = ref([]); const inventoryCategoryList = ref([]); const materialTypeList = ref([]); const specification = ref(""); const model = ref(""); const materialCode = ref(""); const getloadData = () => { @@ -374,11 +374,11 @@ const tableColumn = ref([ { label: "规格型号", prop: "materialName", prop: "productName", }, { label: "规格", prop: "specification", prop: "model", }, { label: "物料编码", @@ -386,7 +386,7 @@ }, { label: "单位", prop: "baseUnit", prop: "unit", }, { dataType: "action", @@ -417,28 +417,28 @@ form: { materialTypeId: null, inventoryCategoryId: null, materialName: "", baseUnit: "", productName: "", unit: "", remark: "", }, rules: { materialName: [ productName: [ { required: true, message: "请输入", trigger: "blur" }, { max: 20, message: "产品名称不能超过20个字符", trigger: "blur" }, ], inventoryCategoryId: [ { required: true, message: "请选择", trigger: "change" }, ], baseUnit: [{ required: true, message: "请输入", trigger: "blur" }], unit: [{ required: true, message: "请输入", trigger: "blur" }], }, modelForm: { specification: "", model: "", supplyType: "", materialCode: "", id: null, }, modelRules: { specification: [{ required: true, message: "请输入", trigger: "blur" }], model: [{ required: true, message: "请输入", trigger: "blur" }], supplyType: [{ required: true, message: "请选择", trigger: "change" }], materialCode: [{ required: true, message: "请输入", trigger: "blur" }], }, @@ -494,7 +494,7 @@ treeLoad.value = true; // 调用 productTreeListQuery 接口进行搜索 productTreeListQuery({ materialName: search.value }) productTreeListQuery({ productName: search.value }) .then(res => { // 处理返回的数据 const newList = []; @@ -505,11 +505,11 @@ item.children = (category.materialList || []).map(item => ({ id: item.id, isLeaf: true, label: item.materialName, label: item.productName, inventoryCategoryId: item.inventoryCategoryId, materialTypeId: item.materialTypeId, remark: item.remark, baseUnit: item.baseUnit, unit: item.unit, })); break; } @@ -522,11 +522,11 @@ // children: (category.materialList || []).map(item => ({ // id: item.id, // isLeaf: true, // label: item.materialName, // label: item.productName, // inventoryCategoryId: item.inventoryCategoryId, // materialTypeId: item.materialTypeId, // remark: item.remark, // baseUnit: item.baseUnit, // unit: item.unit, // })), // }; // newList.push(categoryNode); @@ -546,18 +546,18 @@ productDia.value = true; // 重置表单 form.value = { materialName: "", productName: "", inventoryCategoryId: null, baseUnit: "", unit: "", remark: "", materialTypeId: null, }; console.log(data); if (type === "edit" && data) { // 编辑模式,回填数据 form.value.materialName = data.label || ""; form.value.productName = data.label || ""; form.value.inventoryCategoryId = data.inventoryCategoryId || null; form.value.baseUnit = data.baseUnit || ""; form.value.unit = data.unit || ""; form.value.remark = data.remark || ""; form.value.materialTypeId = data.materialTypeId || null; form.value.id = data.id || null; @@ -586,16 +586,16 @@ modelOperationType.value = type; modelDia.value = true; // 重置所有字段 modelForm.value.specification = ""; modelForm.value.model = ""; modelForm.value.supplyType = ""; modelForm.value.id = null; modelForm.value.materialCode = null; if (type === "edit" && data) { // 编辑模式,回填数据 modelForm.value.specification = data.specification || ""; modelForm.value.model = data.model || ""; modelForm.value.supplyType = data.supplyType || ""; modelForm.value.id = data.skuId || null; modelForm.value.id = data.id || null; modelForm.value.materialCode = data.materialCode || null; } }; @@ -607,8 +607,8 @@ // const params = { // materialTypeId: null, // inventoryCategoryId: form.value.inventoryCategoryId, // materialName: form.value.materialName, // baseUnit: form.value.baseUnit, // productName: form.value.productName, // unit: form.value.unit, // remark: form.value.remark, // }; @@ -743,11 +743,11 @@ const children = materialList.map(item => ({ id: item.id, isLeaf: true, label: item.materialName, label: item.productName, inventoryCategoryId: item.inventoryCategoryId, materialTypeId: item.materialTypeId, remark: item.remark, baseUnit: item.baseUnit, unit: item.unit, })); // 更新节点的子节点 val.children = children; @@ -775,8 +775,8 @@ if (valid) { // 构建提交参数 const params = { materialId: currentId.value, specification: modelForm.value.specification, productId: currentId.value, model: modelForm.value.model, materialCode: modelForm.value.materialCode, supplyType: modelForm.value.supplyType, }; @@ -821,10 +821,10 @@ } tableLoading.value = true; modelListPage({ materialId: currentId.value, productId: currentId.value, current: page.current, size: page.size, specification: specification.value, model: model.value, materialCode: materialCode.value, }).then(res => { console.log("res", res); @@ -837,7 +837,7 @@ const handleDelete = () => { let ids = []; if (selectedRows.value.length > 0) { ids = selectedRows.value.map(item => item.skuId); ids = selectedRows.value.map(item => item.id); } else { proxy.$modal.msgWarning("请选择数据"); return; src/views/inventoryManagement/stockManagement/New.vue
@@ -131,12 +131,12 @@ const handleProductSelect = async products => { if (products && products.length > 0) { const product = products[0]; formState.value.productId = product.skuId; formState.value.productName = product.materialName; formState.value.productModelName = product.specification; formState.value.productId = product.id; formState.value.productName = product.productName; formState.value.productModelName = product.model; formState.value.productModelId = product.skuId; formState.value.unit = product.baseUnit; formState.value.productModelId = product.id; formState.value.unit = product.unit; showProductSelectDialog.value = false; // 触发表单验证更新 proxy.$refs["formRef"]?.validateField("productModelId"); src/views/inventoryManagement/stockManagement/Subtract.vue
@@ -143,11 +143,11 @@ if (products && products.length > 0) { const product = products[0]; console.log(product); formState.value.productId = product.skuId; formState.value.productName = product.materialName; formState.value.productModelName = product.specification; formState.value.productModelId = product.skuId; formState.value.unit = product.baseUnit; formState.value.productId = product.id; formState.value.productName = product.productName; formState.value.productModelName = product.model; formState.value.productModelId = product.id; formState.value.unit = product.unit; showProductSelectDialog.value = false; // 触发表单验证更新 proxy.$refs["formRef"]?.validateField("productModelId"); src/views/productionManagement/processRoute/index.vue
@@ -783,7 +783,7 @@ const product = products[0]; // 先查询BOM列表(必选) try { const res = await getByModel(product.skuId); const res = await getByModel(product.id); // 处理返回的BOM数据:可能是数组、对象或包含data字段 let bomList = []; if (Array.isArray(res)) { @@ -795,9 +795,9 @@ } if (bomList.length > 0) { routeForm.productModelId = product.skuId; routeForm.productName = product.materialName; routeForm.productModelName = product.specification; routeForm.productModelId = product.id; routeForm.productName = product.productName; routeForm.productModelName = product.model; routeForm.bomId = undefined; // 重置BOM选择 bomOptions.value = bomList; showProductSelectDialog.value = false; src/views/productionManagement/productStructure/Detail/index.vue
@@ -148,6 +148,7 @@ </el-table> <product-select-dialog v-if="dataValue.showProductDialog" v-model:model-value="dataValue.showProductDialog" single @confirm="handleProduct" /> </div> </template> @@ -326,6 +327,7 @@ // 校验函数 const validateItem = (item: any, isTopLevel = false) => { console.log(item, "item"); // 校验当前项的必填字段 if (!item.model) { ElMessage.error("请选择规格"); src/views/productionManagement/productStructure/StructureEdit.vue
@@ -19,13 +19,10 @@ @click="cancelEdit" style="margin-bottom: 10px">取消 </el-button> <el-table :data="tableData" <el-table :data="tableData" border :preserve-expanded-content="false" style="width: 100%" > style="width: 100%"> <el-table-column type="expand"> <template #default="props"> <el-form ref="form" @@ -154,14 +151,18 @@ </el-form> </template> </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="unit" /> <el-table-column label="产品编码" prop="productCode" /> <el-table-column label="产品名称" prop="productName" /> <el-table-column label="规格型号" prop="model" /> <el-table-column label="单位" prop="unit" /> </el-table> <product-select-dialog v-if="dataValue.showProductDialog" v-model:model-value="dataValue.showProductDialog" single @confirm="handleProduct" /> <template #footer> <div class="dialog-footer"> @@ -236,8 +237,8 @@ model: props.record.model, unit: props.record.unit, productCode: props.record.productCode, } ] }, ]; const openDialog = index => { dataValue.currentRowIndex = index; src/views/productionManagement/productStructure/index.vue
@@ -336,9 +336,9 @@ const handleProductSelect = products => { if (products && products.length > 0) { const product = products[0]; form.value.productModelId = product.skuId; form.value.productName = product.materialName; form.value.productModelName = product.specification; form.value.productModelId = product.id; form.value.productName = product.productName; form.value.productModelName = product.model; } showProductSelectDialog.value = false; }; src/views/productionManagement/productionOrder/New.vue
@@ -130,13 +130,13 @@ const handleProductSelect = async products => { if (products && products.length > 0) { const product = products[0]; formState.value.productId = product.skuId; formState.value.productName = product.materialName; formState.value.productModelName = product.specification; formState.value.productModelId = product.skuId; formState.value.unit = product.baseUnit; formState.value.productId = product.id; formState.value.productName = product.productName; formState.value.productModelName = product.model; formState.value.productModelId = product.id; formState.value.unit = product.unit; showProductSelectDialog.value = false; fetchRouteOptions(product.skuId); fetchRouteOptions(product.id); // 触发表单验证更新 proxy.$refs["formRef"]?.validateField("productModelId"); } src/views/productionPlan/productionPlan/index.vue
@@ -18,7 +18,7 @@ @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="产品规格:"> <el-input v-model="searchForm.specification" <el-input v-model="searchForm.model" placeholder="请输入" clearable style="width: 160px;" @@ -102,7 +102,7 @@ <el-row :gutter="20"> <el-col :span="10"> <el-form-item label="产品规格"> <div class="info-display">{{ mergeForm.specification || '-' }}</div> <div class="info-display">{{ mergeForm.model || '-' }}</div> </el-form-item> </el-col> <el-col :span="10"> @@ -251,9 +251,9 @@ filterable placeholder="请选择"> <el-option v-for="item in specificationOptions" :key="item.skuId" :label="item.specification" :value="item.skuId" /> :key="item.id" :label="item.model" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="块数" @@ -398,7 +398,7 @@ }, { label: "产品规格", prop: "specification", prop: "model", width: "150px", className: "spec-cell", }, @@ -549,7 +549,7 @@ mergeForm.ids = [row.id]; mergeForm.materialCode = row.materialCode; mergeForm.productName = row.productName || ""; mergeForm.specification = row.specification || ""; mergeForm.model = row.model || ""; mergeForm.length = row.length || 0; mergeForm.width = row.width || 0; mergeForm.height = row.height || 0; @@ -591,7 +591,7 @@ const mergeForm = reactive({ materialCode: "", productName: "", specification: "", model: "", length: 0, width: 0, height: 0, @@ -632,7 +632,7 @@ productMaterialId: undefined, productMaterialSkuId: undefined, productName: "", specification: "", model: "", materialCode: "", quantity: 0, volume: 0, @@ -699,7 +699,7 @@ if (item.materialList && item.materialList.length > 0) { newItem.children = item.materialList.map(material => ({ value: material.id, // 使用material的id作为value label: material.materialName, // 使用materialName作为label label: material.productName, // 使用materialName作为label })); } @@ -712,28 +712,26 @@ fetchSpecificationOptions(value); }; const fetchSpecificationOptions = materialId => { const fetchSpecificationOptions = productId => { specificationOptions.value = []; if (materialId) { modelListPage({ materialId: materialId, size: -1, current: -1 }).then( res => { if (productId) { modelListPage({ productId: productId, size: -1, current: -1 }).then(res => { specificationOptions.value = res.data.records; } ); }); } }; const handleChangeSpecification = value => { form.materialCode = undefined; const selectedModel = specificationOptions.value.find( item => item.skuId === value item => item.id === value ); if (selectedModel) { form.materialCode = selectedModel.materialCode; // 解析规格字符串获取长宽高 const specification = selectedModel.specification; if (specification) { const dimensions = specification.match(/^(\d+)\*(\d+)\*(\d+)$/); const model = selectedModel.model; if (model) { const dimensions = model.match(/^(\d+)\*(\d+)\*(\d+)$/); if (dimensions && dimensions.length === 4) { form.length = parseInt(dimensions[1]); form.width = parseInt(dimensions[2]); @@ -818,7 +816,7 @@ searchForm: { customerName: "", productName: "", specification: "", model: "", materialCode: "", applyNo: "", dateRange: [], @@ -838,7 +836,7 @@ Object.assign(searchForm.value, { customerName: "", productName: "", specification: "", model: "", materialCode: "", applyNo: "", dateRange: [], @@ -955,7 +953,7 @@ const firstRow = selectedRows.value[0]; mergeForm.materialCode = selectedserialNo.value; mergeForm.productName = firstRow.productName || ""; mergeForm.specification = firstRow.specification || ""; mergeForm.model = firstRow.model || ""; mergeForm.length = firstRow.length || 0; mergeForm.width = firstRow.width || 0; mergeForm.height = firstRow.height || 0; @@ -1091,7 +1089,7 @@ productName: "", productMaterialId: undefined, productMaterialSkuId: undefined, specification: "", model: "", materialCode: "", quantity: 0, volume: 0, @@ -1118,7 +1116,7 @@ productName: row.productName || "", productMaterialId: row.productMaterialId || undefined, productMaterialSkuId: row.productMaterialSkuId || undefined, specification: row.specification || "", model: row.model || "", materialCode: row.materialCode || "", quantity: row.quantity || 0, volume: row.volume || 0, src/views/productionPlan/summaryByProduct/index.vue
@@ -54,7 +54,7 @@ }, { label: "产品规格", prop: "specification", prop: "model", className: "spec-cell", }, { src/views/qualityManagement/metricBinding/index.vue
@@ -1,11 +1,16 @@ <template> <div class="app-container metric-binding"> <el-row :gutter="16" class="metric-binding-row"> <el-row :gutter="16" class="metric-binding-row"> <!-- 左侧:检测标准列表 --> <el-col :xs="24" :sm="24" :md="12" :lg="14" :xl="14" class="left-col"> <el-col :xs="24" :sm="24" :md="12" :lg="14" :xl="14" class="left-col"> <div class="panel left-panel"> <PIMTable rowKey="id" <PIMTable rowKey="id" :column="standardColumns" :tableData="standardTableData" :page="page" @@ -14,227 +19,261 @@ :tableLoading="tableLoading" :rowClick="handleTableRowClick" @pagination="handlePagination" :total="page.total" > :total="page.total"> <template #standardNoCell="{ row }"> <span class="clickable-link" @click="handleStandardRowClick(row)"> <span class="clickable-link" @click="handleStandardRowClick(row)"> {{ row.standardNo }} </span> </template> <!-- 表头搜索 --> <template #standardNoHeader> <el-input v-model="searchForm.standardNo" <el-input v-model="searchForm.standardNo" placeholder="标准编号" clearable size="small" @change="handleQuery" @clear="handleQuery" /> @clear="handleQuery" /> </template> <template #standardNameHeader> <el-input v-model="searchForm.standardName" <el-input v-model="searchForm.standardName" placeholder="标准名称" clearable size="small" @change="handleQuery" @clear="handleQuery" /> @clear="handleQuery" /> </template> <template #inspectTypeHeader> <el-select v-model="searchForm.inspectType" <el-select v-model="searchForm.inspectType" placeholder="类别" clearable size="small" style="width: 120px" @change="handleQuery" @clear="handleQuery" > <el-option label="原材料检验" value="0" /> <el-option label="过程检验" value="1" /> <el-option label="出厂检验" value="2" /> @clear="handleQuery"> <el-option label="原材料检验" value="0" /> <el-option label="过程检验" value="1" /> <el-option label="出厂检验" value="2" /> </el-select> </template> <template #stateHeader> <el-select v-model="searchForm.state" <el-select v-model="searchForm.state" placeholder="状态" clearable size="small" style="width: 110px" @change="handleQuery" @clear="handleQuery" > <el-option label="草稿" value="0" /> <el-option label="通过" value="1" /> <el-option label="撤销" value="2" /> @clear="handleQuery"> <el-option label="草稿" value="0" /> <el-option label="通过" value="1" /> <el-option label="撤销" value="2" /> </el-select> </template> </PIMTable> </div> </el-col> <!-- 右侧:绑定列表 --> <el-col :xs="24" :sm="24" :md="12" :lg="10" :xl="10" class="right-col"> <el-col :xs="24" :sm="24" :md="12" :lg="10" :xl="10" class="right-col"> <div class="panel right-panel"> <div class="right-header"> <div class="title">绑定关系</div> <div class="desc" v-if="currentStandard"> <div class="desc" v-if="currentStandard"> 当前检测标准编号:<span class="link-text">{{ currentStandard.standardNo }}</span> </div> <div class="desc" v-else>请选择左侧检测标准</div> <div class="desc" v-else>请选择左侧检测标准</div> </div> <div class="right-toolbar"> <el-button type="primary" :disabled="!currentStandard" @click="openBindingDialog">添加绑定</el-button> <el-button type="danger" plain :disabled="!currentStandard" @click="handleBatchUnbind">删除</el-button> <el-button type="primary" :disabled="!currentStandard" @click="openBindingDialog">添加绑定</el-button> <el-button type="danger" plain :disabled="!currentStandard" @click="handleBatchUnbind">删除</el-button> </div> <el-table v-loading="bindingLoading" <el-table v-loading="bindingLoading" :data="bindingTableData" border :row-class-name="() => 'row-center'" class="center-table" style="width: 100%" height="calc(100vh - 220px)" @selection-change="handleBindingSelectionChange" > <el-table-column type="selection" width="48" align="center" /> <el-table-column type="index" label="序号" width="60" align="center" /> <el-table-column prop="productName" label="产品名称" min-width="140" /> <el-table-column label="操作" width="120" fixed="right" align="center"> @selection-change="handleBindingSelectionChange"> <el-table-column type="selection" width="48" align="center" /> <el-table-column type="index" label="序号" width="60" align="center" /> <el-table-column prop="productName" label="产品名称" min-width="140" /> <el-table-column label="操作" width="120" fixed="right" align="center"> <template #default="{ row }"> <el-button link type="danger" size="small" @click="handleUnbind(row)">删除</el-button> <el-button link type="danger" size="small" @click="handleUnbind(row)">删除</el-button> </template> </el-table-column> </el-table> </div> </el-col> </el-row> <!-- 添加绑定弹框 --> <el-dialog v-model="bindingDialogVisible" <el-dialog v-model="bindingDialogVisible" title="添加绑定" width="520px" @close="closeBindingDialog" > @close="closeBindingDialog"> <el-form label-width="100px"> <el-form-item label="产品"> <el-tree-select v-model="selectedProductIds" multiple collapse-tags collapse-tags-tooltip placeholder="请选择产品(可多选)" clearable check-strictly :data="productOptions" :render-after-expand="false" style="width: 100%" /> <el-button type="primary" @click="openProductSelectDialog">选择产品</el-button> <div class="selected-products mt-2" v-if="selectedProducts.length > 0"> <el-tag v-for="product in selectedProducts" :key="product.id" closable @close="removeSelectedProduct(product.id)" class="mr-2 mb-2"> {{ product.productName }} - {{ product.model }} </el-tag> </div> <div v-else class="text-gray-400"></div> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="closeBindingDialog">取消</el-button> <el-button type="primary" @click="submitBinding">确定</el-button> <el-button type="primary" :disabled="selectedProducts.length === 0" @click="submitBinding">确定</el-button> </span> </template> </el-dialog> <!-- 产品选择对话框 --> <ProductSelectDialog v-model="productSelectDialogVisible" :single="false" @confirm="handleProductSelect" /> </div> </template> <script setup> import { Search } from '@element-plus/icons-vue' import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue' import { ElMessageBox } from 'element-plus' import PIMTable from '@/components/PIMTable/PIMTable.vue' import { productTreeList } from '@/api/basicData/product.js' import { qualityTestStandardListPage } from '@/api/qualityManagement/metricMaintenance.js' import { productProcessListPage } from '@/api/basicData/productProcess.js' import { Search } from "@element-plus/icons-vue"; import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue"; import { ElMessageBox, ElMessage } from "element-plus"; import PIMTable from "@/components/PIMTable/PIMTable.vue"; import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; import { qualityTestStandardListPage } from "@/api/qualityManagement/metricMaintenance.js"; import { productProcessListPage } from "@/api/basicData/productProcess.js"; import { qualityTestStandardBindingList, qualityTestStandardBindingAdd, qualityTestStandardBindingDel } from '@/api/qualityManagement/qualityTestStandardBinding.js' qualityTestStandardBindingDel, } from "@/api/qualityManagement/qualityTestStandardBinding.js"; const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance(); // 左侧标准列表:整行内容居中(配合样式) const rowClassNameCenter = () => 'row-center' const rowClassNameCenter = () => "row-center"; const data = reactive({ searchForm: { standardNo: '', standardName: '', state: '', inspectType: '' } }) const { searchForm } = toRefs(data) standardNo: "", standardName: "", state: "", inspectType: "", }, }); const { searchForm } = toRefs(data); // 左侧 const standardTableData = ref([]) const tableLoading = ref(false) const page = reactive({ current: 1, size: 10, total: 0 }) const standardTableData = ref([]); const tableLoading = ref(false); const page = reactive({ current: 1, size: 10, total: 0 }); // 工序下拉(用于列表回显) const processOptions = ref([]) const processOptions = ref([]); const getProcessList = async () => { try { const res = await productProcessListPage({ current: 1, size: 1000 }) const res = await productProcessListPage({ current: 1, size: 1000 }); if (res?.code === 200) { const records = res?.data?.records || [] processOptions.value = records.map((item) => ({ const records = res?.data?.records || []; processOptions.value = records.map(item => ({ label: item.processName || item.name || item.label, value: item.id || item.processId || item.value })) value: item.id || item.processId || item.value, })); } } catch (error) { console.error('获取工序列表失败:', error) console.error("获取工序列表失败:", error); } } }; const standardColumns = ref([ { label: '标准编号', prop: 'standardNo', dataType: 'slot', slot: 'standardNoCell', minWidth: 160, align: 'center', headerSlot: 'standardNoHeader' }, { label: '标准名称', prop: 'standardName', minWidth: 180, align: 'center', headerSlot: 'standardNameHeader' }, { label: '类别', prop: 'inspectType', headerSlot: 'inspectTypeHeader', align: 'center', dataType: 'tag', formatData: (val) => { const map = { 0: '原材料检验', 1: '过程检验', 2: '出厂检验' } return map[val] || val } }, { label: '工序', prop: 'processId', align: 'center', dataType: 'tag', formatData: (val) => { const target = processOptions.value.find( (item) => String(item.value) === String(val) ) return target?.label || val } }, { label: '备注', prop: 'remark', label: "标准编号", prop: "standardNo", dataType: "slot", slot: "standardNoCell", minWidth: 160, align: 'center' } align: "center", headerSlot: "standardNoHeader", }, { label: "标准名称", prop: "standardName", minWidth: 180, align: "center", headerSlot: "standardNameHeader", }, { label: "类别", prop: "inspectType", headerSlot: "inspectTypeHeader", align: "center", dataType: "tag", formatData: val => { const map = { 0: "原材料检验", 1: "过程检验", 2: "出厂检验" }; return map[val] || val; }, }, { label: "工序", prop: "processId", align: "center", dataType: "tag", formatData: val => { const target = processOptions.value.find( item => String(item.value) === String(val) ); return target?.label || val; }, }, { label: "备注", prop: "remark", minWidth: 160, align: "center", }, // { // label: '状态', // prop: 'state', @@ -250,185 +289,184 @@ // return 'info' // } // } ]) ]); const currentStandard = ref(null) const currentStandard = ref(null); // 右侧绑定 const bindingTableData = ref([]) const bindingLoading = ref(false) const bindingSelectedRows = ref([]) const bindingDialogVisible = ref(false) const bindingTableData = ref([]); const bindingLoading = ref(false); const bindingSelectedRows = ref([]); const bindingDialogVisible = ref(false); // 产品树(用于绑定选择) const productOptions = ref([]) const selectedProductIds = ref([]) // 产品选择 const productSelectDialogVisible = ref(false); const selectedProducts = ref([]); const getProductOptions = async () => { // 避免重复请求 if (productOptions.value?.length) return const res = await productTreeList() productOptions.value = convertIdToValue(Array.isArray(res) ? res : []) } const openProductSelectDialog = () => { productSelectDialogVisible.value = true; }; function convertIdToValue(data) { return (data || []).map((item) => { const { id, children, ...rest } = item const newItem = { ...rest, value: id } if (children && children.length > 0) { newItem.children = convertIdToValue(children) } return newItem }) } const handleProductSelect = products => { // 合并已选择的产品,避免重复 const existingIds = new Set(selectedProducts.value.map(p => p.id)); const newProducts = products.filter(p => !existingIds.has(p.id)); selectedProducts.value = [...selectedProducts.value, ...newProducts]; }; const removeSelectedProduct = id => { selectedProducts.value = selectedProducts.value.filter(p => p.id !== id); }; const handleQuery = () => { page.current = 1 getStandardList() } page.current = 1; getStandardList(); }; const handlePagination = (obj) => { page.current = obj.page page.size = obj.limit getStandardList() } const handlePagination = obj => { page.current = obj.page; page.size = obj.limit; getStandardList(); }; const getStandardList = () => { tableLoading.value = true tableLoading.value = true; qualityTestStandardListPage({ ...searchForm.value, current: page.current, size: page.size, state: 1 state: 1, }) .then((res) => { const records = res?.data?.records || [] standardTableData.value = records page.total = res?.data?.total || records.length .then(res => { const records = res?.data?.records || []; standardTableData.value = records; page.total = res?.data?.total || records.length; }) .finally(() => { tableLoading.value = false }) } tableLoading.value = false; }); }; // 表格行点击,加载右侧绑定列表 const handleTableRowClick = (row) => { currentStandard.value = row loadBindingList() } const handleTableRowClick = row => { currentStandard.value = row; loadBindingList(); }; // 左侧行点击,加载右侧绑定列表(保留用于标准编号列的点击) const handleStandardRowClick = (row) => { currentStandard.value = row loadBindingList() } const handleStandardRowClick = row => { currentStandard.value = row; loadBindingList(); }; const loadBindingList = () => { if (!currentStandard.value?.id) { bindingTableData.value = [] return bindingTableData.value = []; return; } bindingLoading.value = true bindingLoading.value = true; qualityTestStandardBindingList({ testStandardId: currentStandard.value.id }) .then((res) => { const base = res?.data || [] .then(res => { const base = res?.data || []; // 将当前标准的工序和备注带到绑定列表中展示 bindingTableData.value = base.map((item) => ({ bindingTableData.value = base.map(item => ({ ...item, processId: currentStandard.value?.processId, remark: currentStandard.value?.remark })) remark: currentStandard.value?.remark, })); }) .finally(() => { bindingLoading.value = false }) } bindingLoading.value = false; }); }; const handleBindingSelectionChange = (selection) => { bindingSelectedRows.value = selection } const handleBindingSelectionChange = selection => { bindingSelectedRows.value = selection; }; const openBindingDialog = () => { if (!currentStandard.value?.id) return selectedProductIds.value = [] getProductOptions() bindingDialogVisible.value = true } if (!currentStandard.value?.id) return; selectedProducts.value = []; bindingDialogVisible.value = true; }; const closeBindingDialog = () => { bindingDialogVisible.value = false } bindingDialogVisible.value = false; selectedProducts.value = []; }; const submitBinding = async () => { const testStandardId = currentStandard.value?.id if (!testStandardId) return const ids = (selectedProductIds.value || []).filter(Boolean) const testStandardId = currentStandard.value?.id; if (!testStandardId) return; const ids = (selectedProducts.value || []).map(p => p.id).filter(Boolean); if (!ids.length) { proxy.$message.warning('请选择产品') return ElMessage.warning("请选择产品"); return; } const payload = ids.map((pid) => ({ const payload = ids.map(pid => ({ productId: pid, testStandardId })) await qualityTestStandardBindingAdd(payload) proxy.$message.success('添加成功') bindingDialogVisible.value = false loadBindingList() } testStandardId, })); await qualityTestStandardBindingAdd(payload); ElMessage.success("添加成功"); bindingDialogVisible.value = false; selectedProducts.value = []; loadBindingList(); }; const handleUnbind = async (row) => { const id = row?.id ?? row?.qualityTestStandardBindingId if (id == null || id === '') return const handleUnbind = async row => { const id = row?.id ?? row?.qualityTestStandardBindingId; if (id == null || id === "") return; try { await ElMessageBox.confirm('确认删除该绑定?', '提示', { type: 'warning' }) await ElMessageBox.confirm("确认删除该绑定?", "提示", { type: "warning" }); } catch { return return; } try { await qualityTestStandardBindingDel([id]) proxy.$message.success('删除成功') loadBindingList() await qualityTestStandardBindingDel([id]); proxy.$message.success("删除成功"); loadBindingList(); } catch (err) { console.error('删除绑定失败:', err) proxy.$message?.error(err?.message || '删除失败') console.error("删除绑定失败:", err); proxy.$message?.error(err?.message || "删除失败"); } } }; const handleBatchUnbind = async () => { if (!bindingSelectedRows.value.length) { proxy.$message.warning('请选择数据') return proxy.$message.warning("请选择数据"); return; } const ids = bindingSelectedRows.value .map((i) => i?.id ?? i?.qualityTestStandardBindingId) .filter((id) => id != null && id !== '') .map(i => i?.id ?? i?.qualityTestStandardBindingId) .filter(id => id != null && id !== ""); if (!ids.length) { proxy.$message.warning('选中数据缺少有效 id') return proxy.$message.warning("选中数据缺少有效 id"); return; } try { await ElMessageBox.confirm('选中的内容将被删除,是否确认删除?', '删除提示', { type: 'warning' }) await ElMessageBox.confirm( "选中的内容将被删除,是否确认删除?", "删除提示", { type: "warning" } ); } catch { return return; } try { await qualityTestStandardBindingDel(ids) proxy.$message.success('删除成功') loadBindingList() await qualityTestStandardBindingDel(ids); proxy.$message.success("删除成功"); loadBindingList(); } catch (err) { console.error('批量删除绑定失败:', err) proxy.$message?.error(err?.message || '删除失败') console.error("批量删除绑定失败:", err); proxy.$message?.error(err?.message || "删除失败"); } } }; onMounted(() => { getStandardList() getProcessList() }) getStandardList(); getProcessList(); }); </script> <style scoped>