fix(web-admin): harden contract product validation and fetch race
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user