fix(pl): 隔离同合同产品加载请求并允许失败后重新选择。

This commit is contained in:
wuzilong committed 2026-11-01 22:43:12 +08:00
1 parent 136a85dda7
commit eb4a34cd5d
2 files changed
+91 -13

No files matched your search

+33 -11
View File
@@ -300,9 +300,8 @@
<el-select
multiple
:model-value="row.products.map((p: any) => p.contractProductId)"
:disabled="
saving || form.bindingsEditable === false || !bindingProducts[row.contractId]
"
:disabled="saving || form.bindingsEditable === false"
:loading="bindingProductLoading[row.contractId]"
placeholder="勾选适用产品"
style="width: 100%"
@change="(ids: string[]) => setBindingProducts($index, ids)"
@@ -312,6 +311,7 @@
v-for="product in bindingProductOptions(row)"
:key="product.id"
:value="product.id"
:disabled="bindingProductLoading[row.contractId]"
:label="
product.productName +
(product.model ? ' / ' + product.model : '') +
@@ -611,6 +611,8 @@
const bindingContracts = ref<ContractOption[]>([])
const bindingProducts = ref<Record<string, ContractProduct[]>>({})
const bindingSearching = ref(false)
const bindingProductEpochs = new Map<string, number>()
const bindingProductLoading = ref<Record<string, boolean>>({})
const removedBindings = new Map<string, CertificateContractBinding>()
const originalScopes = new Map<string, CertificateContractBinding['products']>()
function bindingContractLabel(id: string) {
@@ -654,16 +656,25 @@
}
async function loadBindingProducts(contractId: string) {
const session = editSession
const result = await quotaCertApi.products(contractId)
if (
session !== editSession ||
!formVisible.value ||
!form.value.contractBindings?.some(
const current = (bindingProductEpochs.get(contractId) || 0) + 1
bindingProductEpochs.set(contractId, current)
bindingProductLoading.value[contractId] = true
const isCurrent = () =>
session === editSession &&
current === bindingProductEpochs.get(contractId) &&
formVisible.value &&
form.value.contractBindings?.some(
(b: CertificateContractBinding) => b.contractId === contractId
)
)
return
bindingProducts.value = { ...bindingProducts.value, [contractId]: result }
try {
const result = await quotaCertApi.products(contractId)
if (!isCurrent()) return
bindingProducts.value = { ...bindingProducts.value, [contractId]: result }
} catch {
// 请求层已提示错误;允许再次打开产品下拉重试。
} finally {
if (isCurrent()) bindingProductLoading.value[contractId] = false
}
}
function addContractBinding(contractId: string) {
if (
@@ -685,10 +696,17 @@
if (saving.value || form.value.bindingsEditable === false) return
const [removed] = form.value.contractBindings.splice(index, 1)
removedBindings.set(removed.contractId, removed)
bindingProductEpochs.set(
removed.contractId,
(bindingProductEpochs.get(removed.contractId) || 0) + 1
)
delete bindingProducts.value[removed.contractId]
delete bindingProductLoading.value[removed.contractId]
}
function setBindingProducts(index: number, ids: string[]) {
if (saving.value || form.value.bindingsEditable === false) return
const binding = form.value.contractBindings[index] as CertificateContractBinding
if (bindingProductLoading.value[binding.contractId]) return
const previous = [...binding.products, ...(originalScopes.get(binding.contractId) || [])]
binding.products = ids.map(
(id) =>
@@ -747,6 +765,8 @@
recognitionImage.value = ''
bindingContracts.value = contracts
bindingProducts.value = {}
bindingProductLoading.value = {}
bindingProductEpochs.clear()
bindingSearching.value = false
originalScopes.clear()
removedBindings.clear()
@@ -809,6 +829,8 @@
}
bindingContracts.value = []
bindingProducts.value = {}
bindingProductLoading.value = {}
bindingProductEpochs.clear()
bindingSearching.value = false
originalScopes.clear()
removedBindings.clear()