feat: 增加 BOM 另存为跨版本内容查重校验

This commit is contained in:
dxc
2026-03-06 10:38:58 +08:00
parent 902c4f248f
commit 4048447123
2 changed files with 56 additions and 3 deletions

View File

@ -143,7 +143,7 @@ class BomService:
@staticmethod
def save_bom(data):
"""保存 BOM (支持多版本)"""
"""保存 BOM (支持多版本),新增跨版本内容查重"""
bom_no = data.get('bom_no')
version = data.get('version', 'V1.0')
parent_id = data['parent_id']
@ -157,6 +157,38 @@ class BomService:
if child['child_id'] == parent_id:
raise ValueError('父件与子件不能是同一物料')
# ===== 跨版本内容查重 =====
# 将当前提交的 children 转换为可比较的集合 (child_id, dosage)
current_children_set = set()
for child in children:
# 用 (child_id, dosage) 元组表示dosage 转为整数比较
dosage_val = int(child.get('dosage', 0)) if child.get('dosage') else 0
current_children_set.add((child['child_id'], dosage_val))
# 查询该 bom_no 下所有其他版本的子件配置
existing_versions = db.session.query(
BomTable.version,
BomTable.child_id,
BomTable.dosage
).filter(
BomTable.bom_no == bom_no,
BomTable.version != version # 排除当前正在保存的版本
).all()
# 按版本分组,构建每个版本的子件集合
version_children = {}
for ver, child_id, dosage in existing_versions:
if ver not in version_children:
version_children[ver] = set()
dosage_val = int(dosage) if dosage else 0
version_children[ver].add((child_id, dosage_val))
# 比对每个版本
for ver, existing_set in version_children.items():
if current_children_set == existing_set:
raise ValueError(f'保存失败!当前子件配置与已有版本 {ver} 完全一致,请勿重复保存')
# ===== 执行保存 =====
# 仅删除当前版本的旧记录
BomTable.query.filter_by(bom_no=bom_no, version=version).delete()

View File

@ -224,6 +224,7 @@ const isEditMode = ref(false)
const isSaveAsMode = ref(false) // 任务1标记是否为另存为模式
let originalVersion = '' // 保存原始版本号用于计算升级选项
let currentBomNo = '' // 保存当前操作的 BOM 编号用于计算版本避让
let originalChildren: ChildRow[] = [] // 保存原始子件数据用于本地查重
const bomList = ref<BomItem[]>([])
const materialOptions = ref<MaterialBase[]>([])
@ -441,6 +442,8 @@ const handleSaveAs = async (row: BomItem) => {
// 保存原始版本号和 BOM 编号用于计算升级选项
originalVersion = form.version
currentBomNo = row.bom_no // 保存当前操作的 BOM 编号
// 保存原始子件数据用于本地查重
originalChildren = JSON.parse(JSON.stringify(form.children))
// 默认选中次版本升级
form.versionUpgradeType = 'minor'
form.version = versionOptions.value.minor
@ -524,6 +527,21 @@ const submitForm = async () => {
return ElMessage.warning('子件列表中存在重复物料,请合并用量或删除重复项')
}
// ===== 另存为本地查重:检查是否修改过 =====
if (isSaveAsMode.value && originalChildren.length > 0) {
// 将当前 children 和原始 children 转换为 set 进行比较
const currentSet = new Set(form.children.map(c => `${c.child_id}-${c.dosage}`))
const originalSet = new Set(originalChildren.map(c => `${c.child_id}-${c.dosage}`))
// 比较两个集合是否完全相同
const isIdentical = currentSet.size === originalSet.size &&
[...currentSet].every(item => originalSet.has(item))
if (isIdentical) {
return ElMessage.warning('您未修改任何子件,与原版本内容一致,请修改后再保存')
}
}
const payload = {
bom_no: fullBomNo.value,
version: form.version,
@ -540,8 +558,11 @@ const submitForm = async () => {
dialogVisible.value = false
fetchBomList()
} else { ElMessage.error(res.msg || '保存失败') }
} catch (e) {
// 错误已由全局拦截器统一处理
} catch (e: any) {
// 确保后端返回的错误信息能正确展示
if (e.response?.data?.msg) {
ElMessage.error(e.response.data.msg)
}
}
finally { saving.value = false }
})