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,