fix(web-admin): harden contract product validation and fetch race

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-30 11:09:37 +08:00
1 parent 946a71b2e0
commit bbd82b7963
1 file changed
+26 -12
@@ -513,6 +513,8 @@
const productSelectorVisible = ref(false)
/** 当前装货合同明细中的 CRM productId(非内部客户限制选品) */
const loadContractProductIds = ref<string[]>([])
/** 装货合同明细拉取序号,避免快速换合同时旧响应覆盖新结果 */
let loadContractFetchSeq = 0
/**
* 内部客户:undefined → ProductSelector 全量目录
* 非内部:始终传 string[](合同无明细时为 [])→ 受限模式,勿与「未传」混淆
@@ -1017,16 +1019,22 @@
const id = String(contracts?.[0]?.contractId || '').trim()
const prevId = String(prev?.[0]?.contractId || '').trim()
if (!id) {
loadContractFetchSeq += 1
loadContractProductIds.value = []
return
}
const seq = ++loadContractFetchSeq
let allowedIds: string[] = []
try {
const res = await getContract(id)
if (seq !== loadContractFetchSeq) return
const detail = pickBxData<{ products?: Array<{ productId?: string | null }> }>(res)
loadContractProductIds.value = collectContractProductIds(detail?.products || [])
allowedIds = collectContractProductIds(detail?.products || [])
} catch {
loadContractProductIds.value = []
if (seq !== loadContractFetchSeq) return
allowedIds = []
}
loadContractProductIds.value = allowedIds
// 合同 id 变化时过滤装货产品(详情首次灌入同 id / 加载中不刷)
if (
prev &&
@@ -1036,7 +1044,7 @@
) {
const nextProducts = filterProductsByAllowedProductIds(
loadForm.value.products || [],
loadContractProductIds.value
allowedIds
)
loadForm.value = { ...loadForm.value, products: nextProducts }
syncFromLoadProducts()
@@ -1739,16 +1747,22 @@
}
if (
!isPlInternalCustomerName(loadForm.value.customerName) &&
(loadForm.value.contracts || []).length === 1 &&
loadContractProductIds.value.length
(loadForm.value.contracts || []).length === 1
) {
const allowed = new Set(loadContractProductIds.value.map((id) => String(id).trim()))
const orphan = (loadForm.value.products || []).some(
(row) => !allowed.has(String(row.productId || '').trim())
)
if (orphan) {
ElMessage.warning('装货产品须属于所选合同')
return false
const products = loadForm.value.products || []
if (products.length) {
const allowed = new Set(
loadContractProductIds.value.map((id) => String(id).trim()).filter(Boolean)
)
if (!allowed.size) {
ElMessage.warning('所选合同暂无产品明细,或合同明细加载失败,请重选合同后再保存')
return false
}
const orphan = products.some((row) => !allowed.has(String(row.productId || '').trim()))
if (orphan) {
ElMessage.warning('装货产品须属于所选合同')
return false
}
}
}
return true