diff --git a/src/api/part/partInfo.js b/src/api/part/partInfo.js index 5f7ea78..d6f08f3 100644 --- a/src/api/part/partInfo.js +++ b/src/api/part/partInfo.js @@ -7,6 +7,8 @@ export const updatePart = data => createAPI('/part/save', 'POST', data) export const copyPartByBase = data => createAPI('/part/copyByBasePartNo', 'POST', data) export const startPartFormalApprove = data => createAPI('/part/startFormalApprove', 'POST', data) export const changePartDefaultSupplier = data => createAPI('/part/changeDefaultSupplier', 'POST', data) +// 查询基准料号下已维护过的SKU(去重),用于新增时SKU联想 +export const listSkuByBasePartNo = data => createAPI('/part/listSkuByBasePartNo', 'POST', data) export const searchPartInfo = data => createAPI('part/getPart','POST', data) export const deletePart = data => createAPI('/part/delete', 'POST', data) //产品审批 diff --git a/src/api/supplier/supplierPartMoqPrice.js b/src/api/supplier/supplierPartMoqPrice.js index 8de9ad0..9ac42dc 100644 --- a/src/api/supplier/supplierPartMoqPrice.js +++ b/src/api/supplier/supplierPartMoqPrice.js @@ -5,6 +5,8 @@ export const listSupplierPartMoq = data => createAPI('/supplier/supplierPartMoqP export const listSupplierPartMoqPage = data => createAPI('/supplier/supplierPartMoqPrice/listSupplierPartPage', 'post', data) export const saveSupplierPartMoq = data => createAPI('/supplier/supplierPartMoqPrice/saveSupplierPart', 'post', data) export const addSupplierPartMoq = data => createAPI('/supplier/supplierPartMoqPrice/addSupplierPart', 'post', data) +export const deleteSupplierPartMoq = data => createAPI('/supplier/supplierPartMoqPrice/deleteSupplierPart', 'post', data) +export const checkSupplierPartByItemSku = data => createAPI('/supplier/supplierPartMoqPrice/checkSupplierPartByItemSku', 'post', data) // 阶梯价接口 - rqrq export const listCurrentTierPrice = data => createAPI('/supplier/supplierPartMoqPrice/listCurrentTierPrice', 'post', data) diff --git a/src/views/modules/inspection/inspectionScheduleOverview.vue b/src/views/modules/inspection/inspectionScheduleOverview.vue new file mode 100644 index 0000000..d5b27eb --- /dev/null +++ b/src/views/modules/inspection/inspectionScheduleOverview.vue @@ -0,0 +1,732 @@ + + + + + diff --git a/src/views/modules/srmPart/partInfoList.vue b/src/views/modules/srmPart/partInfoList.vue index 6808584..acc019b 100644 --- a/src/views/modules/srmPart/partInfoList.vue +++ b/src/views/modules/srmPart/partInfoList.vue @@ -146,7 +146,7 @@ - + @@ -186,7 +186,13 @@ SKU - + + @@ -387,8 +393,11 @@ import { copyPartByBase, deletePart, startPartFormalApprove, - changePartDefaultSupplier + changePartDefaultSupplier, + listSkuByBasePartNo } from '@/api/part/partInfo.js' +import { checkSupplierPartByItemSku } from '@/api/supplier/supplierPartMoqPrice' +import { startNewProductAudit } from '@/api/supplier/supplierPartNewProductAudit' import excel from '@/utils/excel-util.js' import Chooselist from '@/views/modules/common/Chooselist_eam' import basicInfo from './com_part_BasicInfo' @@ -887,6 +896,7 @@ export default { // 产品对话框相关 partDialogVisible: false, isAdd: true, + skuOptions: [], currentpart: { partNo: '', basePartNo: '', @@ -1087,6 +1097,37 @@ export default { if (!this.isAdd) return this.currentpart.partNo = this.generatePartNo(this.currentpart.basePartNo, this.currentpart.partSuffix) }, + // 基准料号失焦:查询该基准料号下已维护过的SKU,作为SKU联想建议(仍允许输入不存在的SKU) + onBasePartNoBlur () { + if (!this.isAdd) return + const basePartNo = (this.currentpart.basePartNo || '').trim().toUpperCase() + if (!basePartNo) { + this.skuOptions = [] + return + } + const site = (this.$store.state.user.site || '').trim().toUpperCase() + // 当前SKU为空、或是上一次自动带出/联想列表中的值时,才允许被新的第一个覆盖,避免冲掉用户手动录入的自定义SKU + const prevOptions = this.skuOptions || [] + const curSku = this.currentpart.sku + const canOverwrite = !curSku || prevOptions.indexOf(curSku) !== -1 + listSkuByBasePartNo({ site, basePartNo }).then(({ data }) => { + const rows = (data && data.code === 0 && data.rows) ? data.rows : [] + this.skuOptions = rows + // 默认选中第一个自动赋值给SKU输入框 + if (rows.length && canOverwrite) { + this.currentpart.sku = rows[0] + } + }).catch(() => { + this.skuOptions = [] + }) + }, + // SKU 联想:从已维护的 skuOptions 中前缀/包含匹配,无匹配时也允许直接录入 + querySkuSuggestions (queryString, cb) { + const list = this.skuOptions || [] + const kw = (queryString || '').trim().toUpperCase() + const results = kw ? list.filter(item => (item || '').toUpperCase().indexOf(kw) !== -1) : list + cb(results.map(item => ({ value: item }))) + }, extractBasePartNo (partNo) { const value = (partNo || '').trim().toUpperCase() if (!value) return '' @@ -1529,6 +1570,7 @@ export default { // 新增产品 addPart() { this.isAdd = true + this.skuOptions = [] this.currentpart = { partNo: '', basePartNo: '', @@ -1564,6 +1606,7 @@ export default { return } this.isAdd = false + this.skuOptions = [] this.currentpart = {...row} // 编辑时基准料号以原值为准,空值保持为空 - rqrq this.currentpart.partSuffix = this.extractPartSuffix(this.currentpart.partNo) @@ -1620,36 +1663,121 @@ export default { this.currentpart.partNo = this.generatePartNo(basePartNo, partSuffix) } this.$refs.partForm.validate((valid) => { - if (valid) { - const apiCall = this.isAdd ? createPart(this.currentpart) : updatePart(this.currentpart) - - apiCall.then(({data}) => { - if (data && data.code === 0) { - const finishSave = (refreshOk) => { - const successMsg = this.isAdd - ? (refreshOk ? '新增产品成功,已刷新属性模板' : '新增产品成功') - : '修改产品成功' - this.$message.success(successMsg) - this.partDialogVisible = false - this.getMainData() - } - // 新增后自动执行“刷新属性模板”按钮同等逻辑 - rqrq - if (this.isAdd) { - this.autoRefreshPartPropertiesAfterCreate().then((refreshOk) => { - finishSave(refreshOk) - }) - return - } - finishSave(false) + if (!valid) { + this.$message.warning('请填写必填字段') + return + } + const supplierCode = (this.currentpart.defaultSupplierNo || '').trim().toUpperCase() + const item = (this.currentpart.item || '').trim().toUpperCase() + const sku = (this.currentpart.sku || '').trim().toUpperCase() + // 供应商编码、Item、SKU 三者都有值时,校验价格表是否已存在该组合 + if (supplierCode && item && sku) { + checkSupplierPartByItemSku({ + site: this.$store.state.user.site, + supplierCode, + item, + sku + }).then(({ data }) => { + if (data && data.code === 0 && data.exists) { + // 价格表已存在该组合,正常保存 + this.doSavePart(false) } else { - this.$message.error(data.msg || '操作失败') + // 价格表不存在该组合,弹窗让用户选择是否执行审核 + this.promptNewProductAuditChoice() } - }).catch(error => { - this.$message.error('操作失败: ' + error.message) + }).catch(() => { + // 校验接口异常时不阻塞保存 + this.doSavePart(false) }) } else { - this.$message.warning('请填写必填字段') + this.doSavePart(false) + } + }) + }, + + /** + * 弹窗询问是否跳过新品审核流程: + * 选择“跳过”→保存并自动执行开始审核;选择“不跳过”→仅保存不执行审核 + */ + promptNewProductAuditChoice () { + this.$confirm( + '供应商产品价格表中未找到记录,是否跳过新品审核流程?', + '新品审核', + { + confirmButtonText: '跳过', + cancelButtonText: '不跳过', + distinguishCancelAndClose: true, + type: 'warning' + } + ).then(() => { + // 用户选择“跳过”,保存后自动执行开始审核 + this.doSavePart(true) + }).catch(action => { + if (action === 'cancel') { + // 用户选择“不跳过”,仅保存不执行审核 + this.doSavePart(false) + } + // action === 'close' 时不做任何操作 + }) + }, + + /** + * 执行实际保存逻辑 + * @param {boolean} needStartAudit 保存成功后是否自动发起新品审核 + */ + doSavePart (needStartAudit) { + const apiCall = this.isAdd ? createPart(this.currentpart) : updatePart(this.currentpart) + apiCall.then(({data}) => { + if (data && data.code === 0) { + const finishSave = (refreshOk) => { + const successMsg = this.isAdd + ? (refreshOk ? '新增产品成功,已刷新属性模板' : '新增产品成功') + : '修改产品成功' + this.$message.success(successMsg) + this.partDialogVisible = false + this.getMainData() + // 保存成功后,根据用户选择决定是否发起新品审核 + if (needStartAudit) { + this.executeStartNewProductAudit() + } + } + // 新增后自动执行“刷新属性模板”按钮同等逻辑 - rqrq + if (this.isAdd) { + this.autoRefreshPartPropertiesAfterCreate().then((refreshOk) => { + finishSave(refreshOk) + }) + return + } + finishSave(false) + } else { + this.$message.error(data.msg || '操作失败') + } + }).catch(error => { + this.$message.error('操作失败: ' + error.message) + }) + }, + + /** + * 调用开始审核接口,生成新品审核记录 + */ + executeStartNewProductAudit () { + const supplierCode = (this.currentpart.defaultSupplierNo || '').trim().toUpperCase() + const partNo = (this.currentpart.partNo || '').trim().toUpperCase() + if (!supplierCode || !partNo) { + return + } + startNewProductAudit({ + site: this.$store.state.user.site, + supplierCode, + partNo + }).then(({ data }) => { + if (data && data.code === 0) { + this.$message.success('已创建新品审核记录') + } else { + this.$message.warning((data && data.msg) || '开始审核失败') } + }).catch(() => { + this.$message.warning('开始审核失败') }) }, diff --git a/src/views/modules/supplier/priceSheetReport.vue b/src/views/modules/supplier/priceSheetReport.vue index 9da70dd..1f71be1 100644 --- a/src/views/modules/supplier/priceSheetReport.vue +++ b/src/views/modules/supplier/priceSheetReport.vue @@ -50,6 +50,7 @@ 重置 { + if (data && data.code === 0) { + // value 为 'Y' 表示有权限 + this.hasExportPermission = String(data.value).trim() === 'Y' + } else { + this.hasExportPermission = false + } + }).catch(error => { + console.error('查询导出权限失败:', error) + this.hasExportPermission = false + }) + }, updateTableHeight () { this.$nextTick(() => { const table = this.$refs[`${this.activeTab}Table`] diff --git a/src/views/modules/supplier/supplierPartMoqPrice.vue b/src/views/modules/supplier/supplierPartMoqPrice.vue index 3a6fca5..eade8ec 100644 --- a/src/views/modules/supplier/supplierPartMoqPrice.vue +++ b/src/views/modules/supplier/supplierPartMoqPrice.vue @@ -94,6 +94,12 @@ {{ scope.row.active === 'Y' ? '是' : '否' }} + + + -
- 变更 -
{ + const inData = { + site: this.$store.state.user.site, + supplierCode: row.supplierCode, + partNo: row.partNo + } + deleteSupplierPartMoq(inData).then(({ data }) => { + if (data && data.code === 0) { + this.$message.success('删除成功') + this.selectedSupplierPart = null + this.currentTierPriceList = [] + this.searchSupplierPartList(false) + } else { + this.$alert((data && data.msg) || '删除失败', '错误', { confirmButtonText: '确定' }) + } + }).catch(() => { + this.$message.error('删除失败') + }) + }).catch(() => {}) + }, openCopyDialog () { if (!this.selectedSupplierPart || !this.selectedSupplierPart.partNo || !this.selectedSupplierPart.supplierCode) { this.$message.warning('请先选择供应商物料')