From bbb097726b1d2e1d588f434c6fd992e5f4d80f9d Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Fri, 28 Nov 2025 11:38:06 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=89=E6=8B=A9=E7=89=A9=E6=96=99=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E5=90=8E=E5=90=8C=E6=97=B6=E6=9B=B4=E6=96=B0=E7=89=A9?= =?UTF-8?q?=E6=96=99=E4=B8=BB=E6=95=B0=E6=8D=AE=E7=9A=84FamilyID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/modules/part/bom_create.vue | 433 +++++++++++++++++++++- src/views/modules/part/routing_create.vue | 38 +- 2 files changed, 444 insertions(+), 27 deletions(-) diff --git a/src/views/modules/part/bom_create.vue b/src/views/modules/part/bom_create.vue index fa56f9e..8992d4e 100644 --- a/src/views/modules/part/bom_create.vue +++ b/src/views/modules/part/bom_create.vue @@ -86,7 +86,8 @@ 复制BOM物料 编辑工序 导入 - 删除 + 删除 + 刷新
@@ -113,6 +114,9 @@ + + + {{scope.row[item.columnProp]}} @@ -750,6 +754,37 @@ + + +
+ + + + + + +
+ + 关闭 + +
+ @@ -887,6 +922,8 @@ import BomComponentUpload from "./bom_component_upload.vue" import {partFamilyInformationSearch} from "../../../api/part/partFamilyInformation"; import {bomSearchHeader, getComponentPartList} from "../../../api/part/bomSearch3"; import {getSiteAndBuByUserName} from "@/api/eam/eam.js" +import {umSearch} from "@/api/qc/qc.js" +import {partInformationSearch} from "@/api/part/partInformation.js" import Sortable from 'sortablejs' export default { @@ -1027,6 +1064,7 @@ export default { choosePartList: [], operationList: [], familyList: [], + printUnitList: [], // 物料单位列表 copyBomDataList: [], modalData: { flag: '', @@ -2565,6 +2603,7 @@ export default { saveAllLoading: false, saveDetailLoading: false, computeLoading: false, + refreshLoading: false, copyBomQueryLoading: false, batchUpdateSaveLoading: false, // 控制 @@ -2585,6 +2624,7 @@ export default { batchOperationModelFlag: false, batchUpdateComponentsFlag: false, familyDialogFlag: false, + printUnitDialogFlag: false, // 物料单位对话框 copyBomDialogFlag: false, // ======== 子物料字段分类集合 ======== productionDataFamily: ['RFID003', 'RFID004', 'RFID005', 'RFID006', 'RFID007', 'RFID008', 'RFID009', 'RFID012', 'RFID023', 'RFID024', 'RFID025', 'RFID026', 'RFID027'], @@ -4068,6 +4108,9 @@ export default { }) }, + /** + * 打开物料分类选择对话框 + */ handleFamilySelect(row, index) { this.familyData = { buNo: row.buNo, @@ -4084,6 +4127,19 @@ export default { this.queryFamilyList() }, + /** + * 打开物料单位选择对话框 + */ + handlePrintUnitSelect(row, index) { + this.familyData = { + site: row.site, + buNo: row.buNo, + componentPart: row.componentPart, + indexOfList: index + } + this.queryPrintUnitList() + }, + queryFamilyList() { this.familyData.limit = this.pageSize this.familyData.page = this.pageIndex @@ -4103,6 +4159,367 @@ export default { }) }, + /** + * 查询物料单位列表 + */ + queryPrintUnitList() { + const queryData = { + site: this.familyData.site, + active: 'Y', + page: 1, + limit: 1000 + } + + // 调用API查询UM列表 + umSearch(queryData).then(({data}) => { + if (data && data.code === 0) { + let list = data.rows || [] + + // 将"米"和"千张"排在最前面 + const priorityUnits = ['米', '千张'] + const priorityList = list.filter(item => priorityUnits.includes(item.umName)) + const otherList = list.filter(item => !priorityUnits.includes(item.umName)) + + this.printUnitList = [...priorityList, ...otherList] + this.printUnitDialogFlag = true + } else { + this.$message.error(data.msg || '查询单位列表失败') + } + }).catch(() => { + this.$message.error('查询单位列表异常') + }) + }, + + /** + * 选择物料单位 + * 双击选择后执行两个保存操作: + * 1. 保存到BOM子物料行的 print_unit 字段 + * 2. 保存到物料主数据(part表)的 umid2 字段 + */ + getRowPrintUnit(row) { + console.log('📏 选择物料单位:', row.umId, row.umName) + + // 1. 更新前端显示 + const currentRow = this.subDetailList[this.familyData.indexOfList] + this.$set(this.subDetailList[this.familyData.indexOfList], 'printUnit', row.umId) + this.$set(this.subDetailList[this.familyData.indexOfList], 'printUnitName', row.umName) + + // 2. 关闭对话框 + this.printUnitDialogFlag = false + + // 3. 执行两个保存操作 + this.savePrintUnitToComponentAndPart(currentRow, row) + }, + + /** + * 保存物料单位到BOM子物料和物料主数据 + * @param {Object} bomRow - BOM子物料行数据 + * @param {Object} unitRow - 选择的物料单位数据 + */ + savePrintUnitToComponentAndPart(bomRow, unitRow) { + const saveData = { + site: bomRow.site, + buNo: bomRow.buNo, + partNo: bomRow.partNo, + engChgLevel: bomRow.engChgLevel, + bomType: bomRow.bomType, + alternativeNo: bomRow.alternativeNo, + componentPart: bomRow.componentPart, + lineItemNo: bomRow.lineItemNo, + printUnit: unitRow.umId, // ✅ 物料单位编码 + qtyPerAssembly: bomRow.qtyPerAssembly, + componentScrap: bomRow.componentScrap, + shrinkageFactor: bomRow.shrinkageFactor, + issueType: bomRow.issueType, + operationId: bomRow.operationId, + issueToLoc: bomRow.issueToLoc, + noteText: bomRow.noteText, + lineSequence: bomRow.lineSequence, + consumptionItem: bomRow.consumptionItem, + updateBy: this.$store.state.user.name + } + + console.log('💾 保存物料单位,物料编码:', bomRow.componentPart, ',单位:', unitRow.umId) + + // 显示loading + const loadingInstance = this.$loading({ + lock: true, + text: '正在保存物料单位...', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.3)' + }) + + // 调用更新BOM子物料的API(会同时更新物料主数据) + updateBomComponent(saveData).then(({data}) => { + loadingInstance.close() + if (data && data.code === 0) { + this.$message({ + message: '物料单位保存成功', + type: 'success', + duration: 1500 + }) + console.log('✅ 物料单位保存成功') + + // 刷新子物料列表以获取最新数据 + if (data.rows && data.rows.subDetailList) { + this.subDetailList = data.rows.subDetailList + this.tableKey++ + this.$forceUpdate() + } + } else { + this.$message.error(data.msg || '保存失败') + } + }).catch((error) => { + loadingInstance.close() + console.error('保存物料单位失败:', error) + this.$message.error('保存失败,请重试') + }) + }, + + /** + * 刷新物料信息 + * 查询所有子物料的最新物料分类和物料单位,并更新到列表中 + */ + refreshPartInfo() { + if (!this.subDetailList || this.subDetailList.length === 0) { + this.$message.warning('当前没有子物料数据') + return + } + + console.log('🔄 开始刷新物料信息...') + this.refreshLoading = true + + // 收集所有需要查询的物料编码 + const partNos = [...new Set(this.subDetailList.map(item => item.componentPart).filter(Boolean))] + + if (partNos.length === 0) { + this.$message.warning('没有有效的物料编码') + this.refreshLoading = false + return + } + + console.log('📋 待查询物料数量:', partNos.length) + + // 构建查询条件 + const queryData = { + userName: this.$store.state.user.name, // 用户名 - 权限验证必须 + site: this.subDetailList[0].site, + //buNo: this.subDetailList[0].buNo, + partNos: partNos, // 批量查询物料编码 + page: 1, + limit: 9999 + } + + // 调用API查询物料信息 + partInformationSearch(queryData).then(({data}) => { + this.refreshLoading = false + + if (data && data.code === 0) { + const partInfoMap = {} + const rows = data.page.list || [] + + // 构建物料信息映射表 + rows.forEach(part => { + partInfoMap[part.partNo] = { + familyID: part.familyID, + familyName: part.familyName, + printUnit: part.umId2, // umid2 是物料的打印单位 + printUnitName: part.umName + } + }) + + console.log('📦 查询到物料信息:', rows.length, '条') + + // 更新列表中的物料分类和物料单位 + let updateCount = 0 + const needUpdateList = [] // 需要保存到数据库的数据列表 + + this.subDetailList.forEach((item, index) => { + const partInfo = partInfoMap[item.componentPart] + if (partInfo) { + // 检查是否有更新 + let hasUpdate = false + const updateData = { + site: item.site, + buNo: item.buNo, + partNo: item.partNo, + engChgLevel: item.engChgLevel, + bomType: item.bomType, + alternativeNo: item.alternativeNo, + componentPart: item.componentPart, + lineItemNo: item.lineItemNo, + qtyPerAssembly: item.qtyPerAssembly, + componentScrap: item.componentScrap, + shrinkageFactor: item.shrinkageFactor, + issueType: item.issueType, + operationId: item.operationId, + issueToLoc: item.issueToLoc, + noteText: item.noteText, + lineSequence: item.lineSequence, + consumptionItem: item.consumptionItem, + updateBy: this.$store.state.user.name + } + + if (partInfo.familyID && item.familyID !== partInfo.familyID) { + this.$set(this.subDetailList[index], 'familyID', partInfo.familyID) + this.$set(this.subDetailList[index], 'familyName', partInfo.familyName) + updateData.familyID = partInfo.familyID + hasUpdate = true + } + + if (partInfo.printUnit && item.printUnit !== partInfo.printUnit) { + this.$set(this.subDetailList[index], 'printUnit', partInfo.printUnit) + this.$set(this.subDetailList[index], 'printUnitName', partInfo.printUnitName) + updateData.printUnit = partInfo.printUnit + hasUpdate = true + } + + if (hasUpdate) { + updateCount++ + needUpdateList.push(updateData) + console.log('✅ 更新物料:', item.componentPart, + ',分类:', partInfo.familyID, + ',单位:', partInfo.printUnit) + } + } + }) + + // 强制刷新表格 + this.tableKey++ + this.$forceUpdate() + + if (updateCount > 0) { + // 批量保存到数据库 + this.batchSaveRefreshData(needUpdateList, updateCount) + } else { + this.$message({ + message: '物料信息已是最新,无需更新', + type: 'info', + duration: 2000 + }) + console.log('🎉 刷新完成,无需更新') + } + } else { + this.$message.error(data.msg || '查询物料信息失败') + } + }).catch((error) => { + this.refreshLoading = false + console.error('查询物料信息异常:', error) + this.$message.error('查询物料信息异常') + }) + }, + + /** + * 批量保存刷新的数据到数据库 + * @param {Array} updateList - 需要更新的数据列表 + * @param {Number} updateCount - 更新数量 + */ + async batchSaveRefreshData(updateList, updateCount) { + console.log('💾 开始批量保存到数据库,数量:', updateCount) + + const loadingInstance = this.$loading({ + lock: true, + text: `正在保存 ${updateCount} 条物料信息到数据库...`, + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.3)' + }) + + let successCount = 0 + let failCount = 0 + + try { + // 使用 Promise.all 并行保存,提高效率 + const promises = updateList.map(item => { + return updateBomComponent(item) + .then(({data}) => { + if (data && data.code === 0) { + successCount++ + console.log('✅ 保存成功:', item.componentPart) + return { success: true, item } + } else { + failCount++ + console.error('❌ 保存失败:', item.componentPart, data.msg) + return { success: false, item, msg: data.msg } + } + }) + .catch((error) => { + failCount++ + console.error('❌ 保存异常:', item.componentPart, error) + return { success: false, item, error } + }) + }) + + // 等待所有保存完成 + await Promise.all(promises) + + loadingInstance.close() + + // 显示结果 + if (failCount === 0) { + this.$message.success(`刷新完成!成功更新并保存 ${successCount} 条物料信息`) + console.log('🎉 批量保存完成,成功:', successCount) + } else { + this.$message.warning(`刷新完成!成功 ${successCount} 条,失败 ${failCount} 条`) + console.log('⚠️ 批量保存完成,成功:', successCount, ',失败:', failCount) + } + + // 重新查询 BOM 子物料列表(放在最后,避免同步异常影响提示) + if (successCount > 0) { + try { + this.refreshBomComponentList() + } catch (refreshError) { + console.error('刷新列表失败:', refreshError) + // 刷新列表失败不影响保存成功的提示 + } + } + + } catch (error) { + loadingInstance.close() + console.error('批量保存异常:', error) + this.$message.error('批量保存失败: ' + (error.message || error)) + } + }, + + /** + * 重新查询 BOM 子物料列表 + */ + refreshBomComponentList() { + try { + // 验证必要数据 + if (!this.headerData || !this.headerData.site || !this.headerData.partNo) { + console.warn('headerData 数据不完整,跳过刷新') + return + } + + const queryData = { + site: this.headerData.site, + buNo: this.headerData.buNo, + partNo: this.headerData.partNo, + engChgLevel: this.headerData.engChgLevel, + bomType: this.headerData.bomType, + alternativeNo: this.headerData.alternativeNo + } + + console.log('🔄 开始刷新 BOM 子物料列表...') + + queryBomDetail(queryData).then(({data}) => { + if (data && data.code === 0) { + this.subDetailList = data.rows.componentList || [] + this.tableKey++ + this.$forceUpdate() + console.log('✅ BOM 子物料列表已刷新,数量:', this.subDetailList.length) + } else { + console.error('查询 BOM 子物料列表失败:', data.msg) + } + }).catch((error) => { + console.error('❌ 查询 BOM 子物料列表异常:', error) + }) + } catch (error) { + console.error('❌ refreshBomComponentList 执行异常:', error) + throw error // 重新抛出,让调用方知道出错了 + } + }, + /** * 选择物料分类 * 双击选择后执行两个保存操作: @@ -4111,15 +4528,15 @@ export default { */ getRowData (row) { console.log('📦 选择物料分类:', row.familyID, row.familyName) - + // 1. 更新前端显示 const currentRow = this.subDetailList[this.familyData.indexOfList] this.$set(this.subDetailList[this.familyData.indexOfList], 'familyName', row.familyName) this.$set(this.subDetailList[this.familyData.indexOfList], 'familyID', row.familyID) - + // 2. 关闭对话框 this.familyDialogFlag = false - + // 3. 执行两个保存操作 this.saveFamilyToComponentAndPart(currentRow, row) }, @@ -4152,9 +4569,9 @@ export default { consumptionItem: bomRow.consumptionItem, updateBy: this.$store.state.user.name } - + console.log('💾 保存物料分类,物料编码:', bomRow.componentPart, ',分类:', familyRow.familyID) - + // 显示loading const loadingInstance = this.$loading({ lock: true, @@ -4162,7 +4579,7 @@ export default { spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.3)' }) - + // 调用更新BOM子物料的API(会同时更新物料主数据) updateBomComponent(saveData).then(({data}) => { loadingInstance.close() @@ -4173,7 +4590,7 @@ export default { duration: 1500 }) console.log('✅ 物料分类保存成功') - + // 刷新子物料列表以获取最新数据 if (data.rows && data.rows.subDetailList) { this.subDetailList = data.rows.subDetailList diff --git a/src/views/modules/part/routing_create.vue b/src/views/modules/part/routing_create.vue index 85146e3..2cc1516 100644 --- a/src/views/modules/part/routing_create.vue +++ b/src/views/modules/part/routing_create.vue @@ -923,6 +923,24 @@ export default { fixed: '', columnWidth: 120 }, + { + userId: this.$store.state.user.name, + functionId: 601003, + serialNumber: '104003Table2LaborCycleTime', + tableId: '104003Table2', + tableName: 'Routing工序表', + columnProp: 'laborCycleTime', + headerAlign: 'center', + align: 'right', + columnLabel: '人工处理时间', + columnHidden: false, + columnImage: false, + columnSortable: false, + sortLv: 0, + status: true, + fixed: '', + columnWidth: 90 + }, { userId: this.$store.state.user.name, functionId: 601003, @@ -939,7 +957,7 @@ export default { sortLv: 0, status: true, fixed: '', - columnWidth: 80 + columnWidth: 90 }, { userId: this.$store.state.user.name, @@ -1175,24 +1193,6 @@ export default { // fixed: '', // columnWidth: 100 // }, - { - userId: this.$store.state.user.name, - functionId: 601003, - serialNumber: '104003Table2LaborCycleTime', - tableId: '104003Table2', - tableName: 'Routing工序表', - columnProp: 'laborCycleTime', - headerAlign: 'center', - align: 'right', - columnLabel: '人工处理时间', - columnHidden: false, - columnImage: false, - columnSortable: false, - sortLv: 0, - status: true, - fixed: '', - columnWidth: 100 - }, { userId: this.$store.state.user.name, functionId: 601003,