From bbd82b7963a21a85255c82d80e295bc7e2d7d3ca Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Sun, 30 Aug 2026 11:09:37 +0800 Subject: [PATCH] fix(web-admin): harden contract product validation and fetch race Co-authored-by: Cursor --- .../business/pl-plan-form-dialog/index.vue | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/web-admin/src/components/business/pl-plan-form-dialog/index.vue b/web-admin/src/components/business/pl-plan-form-dialog/index.vue index 90b9f8f6d..0290b4aeb 100644 --- a/web-admin/src/components/business/pl-plan-form-dialog/index.vue +++ b/web-admin/src/components/business/pl-plan-form-dialog/index.vue @@ -513,6 +513,8 @@ const productSelectorVisible = ref(false) /** 当前装货合同明细中的 CRM productId(非内部客户限制选品) */ const loadContractProductIds = ref([]) + /** 装货合同明细拉取序号,避免快速换合同时旧响应覆盖新结果 */ + 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