|
|
@ -92,6 +92,7 @@ |
|
|
<div class="rq "> |
|
|
<div class="rq "> |
|
|
<el-table |
|
|
<el-table |
|
|
:data="subDetailList" |
|
|
:data="subDetailList" |
|
|
|
|
|
:key="tableKey" |
|
|
height="320px" |
|
|
height="320px" |
|
|
border |
|
|
border |
|
|
@selection-change="componentSelectionChange" |
|
|
@selection-change="componentSelectionChange" |
|
|
@ -886,6 +887,8 @@ import BomComponentUpload from "./bom_component_upload.vue" |
|
|
import {partFamilyInformationSearch} from "../../../api/part/partFamilyInformation"; |
|
|
import {partFamilyInformationSearch} from "../../../api/part/partFamilyInformation"; |
|
|
import {bomSearchHeader, getComponentPartList} from "../../../api/part/bomSearch3"; |
|
|
import {bomSearchHeader, getComponentPartList} from "../../../api/part/bomSearch3"; |
|
|
import {getSiteAndBuByUserName} from "@/api/eam/eam.js" |
|
|
import {getSiteAndBuByUserName} from "@/api/eam/eam.js" |
|
|
|
|
|
import Sortable from 'sortablejs' |
|
|
|
|
|
|
|
|
export default { |
|
|
export default { |
|
|
components: { |
|
|
components: { |
|
|
BomComponentUpload, |
|
|
BomComponentUpload, |
|
|
@ -1673,7 +1676,7 @@ export default { |
|
|
sortLv: 0, |
|
|
sortLv: 0, |
|
|
status: true, |
|
|
status: true, |
|
|
fixed: '', |
|
|
fixed: '', |
|
|
columnWidth: 200 |
|
|
|
|
|
|
|
|
columnWidth: 120 |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
userId: this.$store.state.user.name, |
|
|
userId: this.$store.state.user.name, |
|
|
@ -2599,13 +2602,198 @@ export default { |
|
|
materialWeightFamily: ['RFID018', 'RFID019'], |
|
|
materialWeightFamily: ['RFID018', 'RFID019'], |
|
|
materialLength2Family: ['RFID018', 'RFID019'], |
|
|
materialLength2Family: ['RFID018', 'RFID019'], |
|
|
unitConversionFamily: ['RFID018', 'RFID019'], |
|
|
unitConversionFamily: ['RFID018', 'RFID019'], |
|
|
|
|
|
sortableInstance: null, // 保存 Sortable 实例 |
|
|
|
|
|
isDragging: false, // 标记是否正在拖拽,避免重复初始化 |
|
|
|
|
|
tableKey: 0 // 表格的 key,用于强制刷新表格 |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
created () { |
|
|
created () { |
|
|
// 获取用户的 site 和 bu |
|
|
// 获取用户的 site 和 bu |
|
|
this.getSiteAndBuByUserName() |
|
|
this.getSiteAndBuByUserName() |
|
|
}, |
|
|
}, |
|
|
|
|
|
mounted() { |
|
|
|
|
|
// 初始化表格行拖拽排序功能 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.initTableRowDrag() |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
updated() { |
|
|
|
|
|
// 组件更新后重新初始化拖拽功能 |
|
|
|
|
|
// 只在非拖拽状态下初始化,避免拖拽操作触发重复初始化 |
|
|
|
|
|
if (!this.isDragging) { |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
this.initTableRowDrag() |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
methods: { |
|
|
methods: { |
|
|
|
|
|
/** |
|
|
|
|
|
* 初始化表格行拖拽排序功能 |
|
|
|
|
|
* 拖拽后自动重新计算序号并保存到数据库 |
|
|
|
|
|
*/ |
|
|
|
|
|
initTableRowDrag() { |
|
|
|
|
|
// 如果正在拖拽,不重新初始化 |
|
|
|
|
|
if (this.isDragging) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 销毁旧的 Sortable 实例 |
|
|
|
|
|
if (this.sortableInstance) { |
|
|
|
|
|
this.sortableInstance.destroy() |
|
|
|
|
|
this.sortableInstance = null |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const el = document.querySelector('.rq .el-table__body-wrapper tbody') |
|
|
|
|
|
if (!el) { |
|
|
|
|
|
console.warn('未找到表格DOM元素,拖拽功能初始化失败') |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建新的 Sortable 实例 |
|
|
|
|
|
this.sortableInstance = Sortable.create(el, { |
|
|
|
|
|
animation: 150, |
|
|
|
|
|
handle: 'tr', // 整行可拖拽 |
|
|
|
|
|
ghostClass: 'sortable-ghost', |
|
|
|
|
|
chosenClass: 'sortable-chosen', |
|
|
|
|
|
dragClass: 'sortable-drag', |
|
|
|
|
|
onStart: () => { |
|
|
|
|
|
this.isDragging = true |
|
|
|
|
|
}, |
|
|
|
|
|
onEnd: (evt) => { |
|
|
|
|
|
const { oldIndex, newIndex } = evt |
|
|
|
|
|
this.isDragging = false |
|
|
|
|
|
|
|
|
|
|
|
if (oldIndex === newIndex) return |
|
|
|
|
|
|
|
|
|
|
|
console.log(`🔄 拖拽: 从位置 ${oldIndex} (序号${this.subDetailList[oldIndex].lineSequence}) 移动到位置 ${newIndex}`) |
|
|
|
|
|
|
|
|
|
|
|
// 1. 更新本地数据顺序 |
|
|
|
|
|
const movedItem = this.subDetailList.splice(oldIndex, 1)[0] |
|
|
|
|
|
this.subDetailList.splice(newIndex, 0, movedItem) |
|
|
|
|
|
|
|
|
|
|
|
// 2. 重新计算所有序号(从1开始)- 使用 Vue.set 确保响应式更新 |
|
|
|
|
|
this.subDetailList.forEach((item, index) => { |
|
|
|
|
|
this.$set(item, 'lineSequence', index + 1) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
console.log('📝 拖拽后新序号:', this.subDetailList.map((item, idx) => |
|
|
|
|
|
`位置${idx}: ${item.componentPart} (序号${item.lineSequence})` |
|
|
|
|
|
).join(', ')) |
|
|
|
|
|
|
|
|
|
|
|
// 3. 强制刷新视图 - 使用多种方式确保更新 |
|
|
|
|
|
this.tableKey++ // 强制刷新表格 |
|
|
|
|
|
this.$forceUpdate() |
|
|
|
|
|
|
|
|
|
|
|
// 4. 使用 nextTick 确保 DOM 更新后再保存 |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
// 5. 保存到数据库 |
|
|
|
|
|
this.saveBomComponentSequence() |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
console.log('✅ 拖拽功能初始化成功') |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 保存BOM子物料序号到数据库 |
|
|
|
|
|
* 将整个列表的数据(包含新序号)提交到后端保存 |
|
|
|
|
|
*/ |
|
|
|
|
|
saveBomComponentSequence() { |
|
|
|
|
|
if (this.subDetailList.length === 0) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log('💾 === 拖拽排序保存开始 ===') |
|
|
|
|
|
console.log('准备保存的数据:') |
|
|
|
|
|
this.subDetailList.forEach((item, index) => { |
|
|
|
|
|
console.log(` 位置${index}: ${item.componentPart} → 新序号 ${item.lineSequence}`) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 构建保存数据 |
|
|
|
|
|
const tempData = { |
|
|
|
|
|
site: this.modalData.site, |
|
|
|
|
|
buNo: this.modalData.buNo, |
|
|
|
|
|
partNo: this.modalData.partNo, |
|
|
|
|
|
partDesc: this.modalData.partDesc, |
|
|
|
|
|
engChgLevel: this.modalData.engChgLevel, |
|
|
|
|
|
bomType: this.modalData.bomType, |
|
|
|
|
|
noteText: this.modalData.noteText, |
|
|
|
|
|
effPhaseInDate: this.modalData.effPhaseInDate, |
|
|
|
|
|
effPhaseOutDate: this.modalData.effPhaseOutDate, |
|
|
|
|
|
engRevision: this.modalData.engRevision, |
|
|
|
|
|
typeFlag: this.modalData.typeFlag, |
|
|
|
|
|
netWeight: this.modalData.netWeight, |
|
|
|
|
|
alternativeNo: this.detailData.alternativeNo, |
|
|
|
|
|
alternativeDescription: this.detailData.alternativeDescription, |
|
|
|
|
|
minLotQty: this.detailData.minLotQty, |
|
|
|
|
|
defaultFlag: this.detailData.defaultFlag, |
|
|
|
|
|
detailNoteText: this.detailData.detailNoteText, |
|
|
|
|
|
status: this.detailData.status, |
|
|
|
|
|
createBy: this.$store.state.user.name, |
|
|
|
|
|
updateBy: this.$store.state.user.name, |
|
|
|
|
|
informationList: this.subDetailList, |
|
|
|
|
|
processUnit: this.modalData.processUnit |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 显示loading |
|
|
|
|
|
const loadingInstance = this.$loading({ |
|
|
|
|
|
lock: true, |
|
|
|
|
|
text: '正在保存序号排序...', |
|
|
|
|
|
spinner: 'el-icon-loading', |
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.3)' |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 调用保存API |
|
|
|
|
|
bomManagementSave(tempData).then(({data}) => { |
|
|
|
|
|
loadingInstance.close() |
|
|
|
|
|
if (data && data.code === 0) { |
|
|
|
|
|
this.$message({ |
|
|
|
|
|
message: '序号排序保存成功', |
|
|
|
|
|
type: 'success', |
|
|
|
|
|
duration: 1500 |
|
|
|
|
|
}) |
|
|
|
|
|
// ✅ 保存成功后,保持前端已排序的数据,不使用后端返回的数据 |
|
|
|
|
|
// 因为后端返回的数据是按旧的 line_sequence 排序的,会覆盖我们的新顺序 |
|
|
|
|
|
console.log('✅ 序号保存成功,当前顺序:', this.subDetailList.map(item => ({ |
|
|
|
|
|
componentPart: item.componentPart, |
|
|
|
|
|
lineSequence: item.lineSequence |
|
|
|
|
|
}))) |
|
|
|
|
|
|
|
|
|
|
|
// 如果需要更新其他字段(如计算字段),可以从后端数据中提取并合并 |
|
|
|
|
|
if (data.rows && data.rows.subDetailList) { |
|
|
|
|
|
const backendList = data.rows.subDetailList |
|
|
|
|
|
// 按照前端的顺序,更新后端返回的其他字段 |
|
|
|
|
|
this.subDetailList = this.subDetailList.map(frontItem => { |
|
|
|
|
|
const backendItem = backendList.find(b => |
|
|
|
|
|
b.componentPart === frontItem.componentPart && |
|
|
|
|
|
b.lineItemNo === frontItem.lineItemNo |
|
|
|
|
|
) |
|
|
|
|
|
// 保留前端的 lineSequence,更新其他字段 |
|
|
|
|
|
return backendItem ? { |
|
|
|
|
|
...backendItem, |
|
|
|
|
|
lineSequence: frontItem.lineSequence |
|
|
|
|
|
} : frontItem |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 强制刷新表格显示 |
|
|
|
|
|
this.tableKey++ |
|
|
|
|
|
this.$forceUpdate() |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$message.error(data.msg || '保存失败') |
|
|
|
|
|
// 保存失败时刷新数据,恢复原序号 |
|
|
|
|
|
this.alternativeChange() |
|
|
|
|
|
} |
|
|
|
|
|
}).catch((error) => { |
|
|
|
|
|
loadingInstance.close() |
|
|
|
|
|
console.error('保存失败:', error) |
|
|
|
|
|
this.$message.error('保存失败,请重试') |
|
|
|
|
|
// 保存失败时刷新数据,恢复原序号 |
|
|
|
|
|
this.alternativeChange() |
|
|
|
|
|
}) |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
// 初始化组件的参数 |
|
|
// 初始化组件的参数 |
|
|
async init (tempData) { |
|
|
async init (tempData) { |
|
|
await getBomInformationByPartNo(tempData).then(({data}) => { |
|
|
await getBomInformationByPartNo(tempData).then(({data}) => { |
|
|
@ -4277,6 +4465,32 @@ export default { |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
<style lang="scss" scoped> |
|
|
|
|
|
/* 拖拽排序样式 */ |
|
|
|
|
|
.sortable-ghost { |
|
|
|
|
|
opacity: 0.5; |
|
|
|
|
|
background: #f0f9ff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.sortable-chosen { |
|
|
|
|
|
background: #e0f2fe; |
|
|
|
|
|
cursor: move; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.sortable-drag { |
|
|
|
|
|
opacity: 0.8; |
|
|
|
|
|
background: #bae6fd; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* 为表格行添加拖拽指示 */ |
|
|
|
|
|
/deep/ .rq .el-table__body-wrapper tbody tr { |
|
|
|
|
|
cursor: move; |
|
|
|
|
|
user-select: none; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/deep/ .rq .el-table__body-wrapper tbody tr:hover { |
|
|
|
|
|
background-color: #f5f7fa; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/deep/ .detail-tab .el-tabs__content { |
|
|
/deep/ .detail-tab .el-tabs__content { |
|
|
height: 165px; |
|
|
height: 165px; |
|
|
padding: 15px 0px 0px 0px; |
|
|
padding: 15px 0px 0px 0px; |
|
|
|