diff --git a/src/views/modules/qc/inboundNotification.vue b/src/views/modules/qc/inboundNotification.vue index 05c064f..376a82c 100644 --- a/src/views/modules/qc/inboundNotification.vue +++ b/src/views/modules/qc/inboundNotification.vue @@ -507,8 +507,8 @@ - 添加>> - 删除<< + 添加>> + 删除<< @@ -704,8 +704,8 @@ - 添加>> - 删除<< + 添加>> + 删除<< @@ -931,6 +931,7 @@ partSelections2: [], partList1: [], partList2: [], + partOperateLoading: false, dataListLoading: false, // 展示列集 columnList: [ @@ -1860,6 +1861,7 @@ this.partSelections2 = [] this.partList1 = [] this.partList2 = [] + this.partOperateLoading = false this.pageIndex2 = 1 this.pageSize2 = 20 this.totalPage2 = 0 @@ -1870,19 +1872,6 @@ this.detailModal = true }, - handleGetProjectPartList () { - this.detailSearchData.limit = this.pageSize2 - this.detailSearchData.page = this.pageIndex2 - getInboundPartList(this.detailSearchData).then(({data}) => { - if (data && data.code === 0){ - this.partList1 = data.page.list - this.pageIndex2 = data.page.currPage - this.pageSize2 = data.page.pageSize - this.totalPage2 = data.page.totalCount - } - }) - }, - // 可选物料 partClickRow1 (row) { const tableRef = this.detailSearchData.orderType === '其他入库' @@ -1915,42 +1904,141 @@ searchTypeChange () { // 生产入库按卷号排除,其他入库按物料编码排除 if (this.detailSearchData.orderType === '生产入库') { - let rollNos = this.partList2.map(part => part.rollNo) + let rollNos = this.partList2.map(part => part.rollNo).filter(item => item) this.detailSearchData.partNos = rollNos.join(",") } else { - let partNos = this.partList2.map(part => part.partNo) + let partNos = this.partList2.map(part => part.partNo).filter(item => item) this.detailSearchData.partNos = partNos.join(",") } - this.handleGetProjectPartList() + return this.handleGetProjectPartList() + }, + + handleGetProjectPartList () { + this.detailSearchData.limit = this.pageSize2 + this.detailSearchData.page = this.pageIndex2 + return getInboundPartList(this.detailSearchData).then(({data}) => { + if (data && data.code === 0){ + this.partList1 = data.page.list + this.pageIndex2 = data.page.currPage + this.pageSize2 = data.page.pageSize + this.totalPage2 = data.page.totalCount + } + }) + }, + + isProductionInboundDetail () { + return this.detailSearchData.orderType === '生产入库' + }, + + getPartUniqueKey (part) { + if (!part) { + return '' + } + if (this.isProductionInboundDetail()) { + return (part.rollNo || '').trim() + } + return (part.partNo || '').trim() + }, + + getExistingSelectedKeySet () { + const keys = new Set() + ;(this.partList2 || []).forEach(part => { + const key = this.getPartUniqueKey(part) + if (key) { + keys.add(key) + } + }) + return keys + }, + + findDuplicateSelectedParts (selectedList) { + const existingKeys = this.getExistingSelectedKeySet() + const seenKeys = new Set() + const duplicates = [] + ;(selectedList || []).forEach(item => { + const key = this.getPartUniqueKey(item) + if (!key) { + return + } + if (existingKeys.has(key) || seenKeys.has(key)) { + if (duplicates.indexOf(key) === -1) { + duplicates.push(key) + } + return + } + seenKeys.add(key) + }) + return duplicates + }, + + clearPartTableSelection (tableNo) { + const isOther = this.detailSearchData.orderType === '其他入库' + let tableRef = null + if (tableNo === 1) { + tableRef = isOther ? this.$refs.partTable1Other : this.$refs.partTable1Production + this.partSelections1 = [] + } else { + tableRef = isOther ? this.$refs.partTable2Other : this.$refs.partTable2Production + this.partSelections2 = [] + } + this.$nextTick(() => { + if (tableRef && tableRef.clearSelection) { + tableRef.clearSelection() + } + }) }, // 添加物料 addPart () { + if (this.partOperateLoading) { + return + } if (this.partSelections1 == null || this.partSelections1.length === 0) { this.$message.warning('请选择可选物料!') return } - this.partSelections1.forEach(item => { + const duplicates = this.findDuplicateSelectedParts(this.partSelections1) + if (duplicates.length > 0) { + const label = this.isProductionInboundDetail() ? '卷号' : '物料编码' + this.$message.warning(`所选物料中以下${label}已在已选列表中,请勿重复添加:${duplicates.join('、')}`) + return + } + const selectedItems = this.partSelections1.slice() + const addedKeys = new Set(selectedItems.map(item => this.getPartUniqueKey(item)).filter(item => item)) + selectedItems.forEach(item => { this.partList2.push(item) }) - this.searchTypeChange() + this.partList1 = (this.partList1 || []).filter(part => !addedKeys.has(this.getPartUniqueKey(part))) + this.clearPartTableSelection(1) + this.partOperateLoading = true + Promise.resolve(this.searchTypeChange()).finally(() => { + this.partOperateLoading = false + }) }, // 删除物料 deletePart () { + if (this.partOperateLoading) { + return + } if(this.partSelections2 == null || this.partSelections2.length === 0) { this.$message.warning('请选择已选物料!') return } - this.partSelections2.forEach(item => { + const selectedItems = this.partSelections2.slice() + selectedItems.forEach(item => { // 生产入库按卷号删除,其他入库按物料编码删除 - if (this.detailSearchData.orderType === '生产入库') { + if (this.isProductionInboundDetail()) { this.partList2 = this.partList2.filter(part => part.rollNo !== item.rollNo) } else { this.partList2 = this.partList2.filter(part => part.partNo !== item.partNo) } }) - this.searchTypeChange() + this.clearPartTableSelection(2) + this.partOperateLoading = true + Promise.resolve(this.searchTypeChange()).finally(() => { + this.partOperateLoading = false + }) }, // 新增明细 @@ -1960,6 +2048,26 @@ this.$message.warning('请选择物料!') return } + const selectedDuplicates = [] + const seenKeys = new Set() + this.partList2.forEach(part => { + const key = this.getPartUniqueKey(part) + if (!key) { + return + } + if (seenKeys.has(key)) { + if (selectedDuplicates.indexOf(key) === -1) { + selectedDuplicates.push(key) + } + return + } + seenKeys.add(key) + }) + if (selectedDuplicates.length > 0) { + const label = this.isProductionInboundDetail() ? '卷号' : '物料编码' + this.$message.warning(`已选物料存在重复${label}:${selectedDuplicates.join('、')}`) + return + } // 校验关联单号和关联单行号必填 for (let i = 0; i < this.partList2.length; i++) { const part = this.partList2[i] @@ -1973,7 +2081,10 @@ } } let tempData = { + site: this.detailSearchData.site, + buNo: this.detailSearchData.buNo, orderNo: this.detailSearchData.orderNo, + orderType: this.detailSearchData.orderType, createdBy: this.$store.state.user.name, partList: this.partList2, } diff --git a/src/views/modules/qc/outboundNotification.vue b/src/views/modules/qc/outboundNotification.vue index e7ff13f..7f9e0ee 100644 --- a/src/views/modules/qc/outboundNotification.vue +++ b/src/views/modules/qc/outboundNotification.vue @@ -531,8 +531,8 @@ - 添加>> - 删除<< + 添加>> + 删除<< @@ -695,8 +695,8 @@ - 添加>> - 删除<< + 添加>> + 删除<< @@ -910,6 +910,7 @@ partSelections2: [], partList1: [], partList2: [], + partOperateLoading: false, dataListLoading: false, // 展示列集 columnList: [ @@ -1899,6 +1900,7 @@ this.partSelections2 = [] this.partList1 = [] this.partList2 = [] + this.partOperateLoading = false this.pageIndex2 = 1 this.pageSize2 = 20 this.totalPage2 = 0 @@ -1911,7 +1913,7 @@ handleGetProjectPartList () { this.detailSearchData.limit = this.pageSize2 this.detailSearchData.page = this.pageIndex2 - getOutboundPartList(this.detailSearchData).then(({data}) => { + return getOutboundPartList(this.detailSearchData).then(({data}) => { if (data && data.code === 0){ this.partList1 = data.page.list this.pageIndex2 = data.page.currPage @@ -1940,38 +1942,153 @@ this.partSelections2 = val }, + getPartUniqueKey (part) { + if (!part) { + return '' + } + const site = (part.site || this.detailSearchData.site || '').trim() + const relatedOrderNo = (part.relatedOrderNo || '').trim() + const relatedOrderLineNo = String(part.relatedOrderLineNo == null ? '' : part.relatedOrderLineNo).trim() + if (relatedOrderNo && relatedOrderLineNo) { + return [site, relatedOrderNo, relatedOrderLineNo].join('|') + } + return (part.partNo || '').trim() + }, + + getPartUniqueDisplay (part) { + if (!part) { + return '' + } + const relatedOrderNo = (part.relatedOrderNo || '').trim() + const relatedOrderLineNo = String(part.relatedOrderLineNo == null ? '' : part.relatedOrderLineNo).trim() + if (relatedOrderNo && relatedOrderLineNo) { + return relatedOrderNo + ' / ' + relatedOrderLineNo + } + return (part.partNo || '').trim() + }, + + getPartUniqueLabel (part) { + const relatedOrderNo = part && (part.relatedOrderNo || '').trim() + const relatedOrderLineNo = String(part && part.relatedOrderLineNo != null ? part.relatedOrderLineNo : '').trim() + if (relatedOrderNo && relatedOrderLineNo) { + return '采购订单+行号' + } + return '物料编码' + }, + + getExistingSelectedKeySet () { + const keys = new Set() + ;(this.partList2 || []).forEach(part => { + const key = this.getPartUniqueKey(part) + if (key) { + keys.add(key) + } + }) + return keys + }, + + findDuplicateSelectedParts (selectedList) { + const existingKeys = this.getExistingSelectedKeySet() + const seenKeys = new Set() + const duplicates = [] + ;(selectedList || []).forEach(item => { + const key = this.getPartUniqueKey(item) + if (!key) { + return + } + if (existingKeys.has(key) || seenKeys.has(key)) { + const display = this.getPartUniqueDisplay(item) + if (duplicates.indexOf(display) === -1) { + duplicates.push(display) + } + return + } + seenKeys.add(key) + }) + return duplicates + }, + + clearPartTableSelection (tableNo) { + const tableRef = tableNo === 1 ? this.$refs.partTable1 : this.$refs.partTable2 + if (tableNo === 1) { + this.partSelections1 = [] + } else { + this.partSelections2 = [] + } + this.$nextTick(() => { + if (tableRef && tableRef.clearSelection) { + tableRef.clearSelection() + } + }) + }, + // 改变事件 searchTypeChange () { - // 使用 map 提取 partNo 并加上单引号 - let partNos = this.partList2.map(part => part.partNo) - // 使用 join 将 partNo 连接成一个字符串 - this.detailSearchData.partNos = partNos.join(",") - this.handleGetProjectPartList() + if (this.detailSearchData.orderType === '采购退货') { + this.detailSearchData.partNos = (this.partList2 || []) + .map(part => { + const relatedOrderNo = (part.relatedOrderNo || '').trim() + const relatedOrderLineNo = String(part.relatedOrderLineNo == null ? '' : part.relatedOrderLineNo).trim() + if (!relatedOrderNo || !relatedOrderLineNo) { + return '' + } + return relatedOrderNo + '||' + relatedOrderLineNo + }) + .filter(item => item) + .join(',') + } else { + this.detailSearchData.partNos = (this.partList2 || []).map(part => part.partNo).filter(item => item).join(',') + } + return this.handleGetProjectPartList() }, // 添加物料 addPart () { + if (this.partOperateLoading) { + return + } if (this.partSelections1 == null || this.partSelections1.length === 0) { this.$message.warning('请选择可选物料!') return } - this.partSelections1.forEach(item => { + const duplicates = this.findDuplicateSelectedParts(this.partSelections1) + if (duplicates.length > 0) { + const label = this.getPartUniqueLabel(this.partSelections1[0]) + this.$message.warning(`所选物料中以下${label}已在已选列表中,请勿重复添加:${duplicates.join('、')}`) + return + } + const selectedItems = this.partSelections1.slice() + const addedKeys = new Set(selectedItems.map(item => this.getPartUniqueKey(item)).filter(item => item)) + selectedItems.forEach(item => { this.partList2.push(item) }) - this.searchTypeChange() + this.partList1 = (this.partList1 || []).filter(part => !addedKeys.has(this.getPartUniqueKey(part))) + this.clearPartTableSelection(1) + this.partOperateLoading = true + Promise.resolve(this.searchTypeChange()).finally(() => { + this.partOperateLoading = false + }) }, // 删除物料 deletePart () { + if (this.partOperateLoading) { + return + } if(this.partSelections2 == null || this.partSelections2.length === 0) { this.$message.warning('请选择已选物料!') return } - this.partSelections2.forEach(item => { - // 使用 filter 过滤掉 partList2 中与 selection.part_no 相同的项 - this.partList2 = this.partList2.filter(part => part.partNo !== item.partNo) + const selectedItems = this.partSelections2.slice() + selectedItems.forEach(item => { + const key = this.getPartUniqueKey(item) + this.partList2 = this.partList2.filter(part => this.getPartUniqueKey(part) !== key) + }) + this.clearPartTableSelection(2) + this.partOperateLoading = true + Promise.resolve(this.searchTypeChange()).finally(() => { + this.partOperateLoading = false }) - this.searchTypeChange() }, // 新增明细 @@ -1981,6 +2098,27 @@ this.$message.warning('请选择物料!') return } + const selectedDuplicates = [] + const seenKeys = new Set() + this.partList2.forEach(part => { + const key = this.getPartUniqueKey(part) + if (!key) { + return + } + if (seenKeys.has(key)) { + const display = this.getPartUniqueDisplay(part) + if (selectedDuplicates.indexOf(display) === -1) { + selectedDuplicates.push(display) + } + return + } + seenKeys.add(key) + }) + if (selectedDuplicates.length > 0) { + const label = this.getPartUniqueLabel(this.partList2[0]) + this.$message.warning(`已选物料存在重复${label}:${selectedDuplicates.join('、')}`) + return + } // 校验关联单号和关联单行号必填 for (let i = 0; i < this.partList2.length; i++) { const part = this.partList2[i] @@ -1994,7 +2132,10 @@ } } let tempData = { + site: this.detailSearchData.site, + buNo: this.detailSearchData.buNo, orderNo: this.detailSearchData.orderNo, + orderType: this.detailSearchData.orderType, createdBy: this.$store.state.user.name, partList: this.partList2, }