diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts index 3c449d9b..c6c09e2b 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts @@ -407,9 +407,14 @@ describe('UnifiedOrdersView contract', () => { expect(source).toContain('outerLengthCm: item.outerLengthCm') expect(source).toContain('outerWidthCm: item.outerWidthCm') expect(source).toContain('outerHeightCm: item.outerHeightCm') - expect(source).toContain("String(item.chargeRuleId) === String(activeRule!.id)") - expect(source).toContain('item.calculatedOuterLengthCm, item.calculatedOuterWidthCm, item.calculatedOuterHeightCm') - expect(source).toContain('if (dimensions.every((dimension) => dimension == null)) return true') + expect(source).toContain('const savedDraft = await saveInboundMeasurementDraft') + expect(source).toContain('version: savedDraft.version') + expect(source).toContain('waitForSavedMeasurementVersion(') + expect(source).toContain('Number(refreshed.version) >= savedVersion') + expect(source).toContain('setTimeout(resolve, 250)') + expect(source).toContain("chargeRuleId: mode === 'MULTIPLY' ? activeRule!.id : null") + expect(source).toContain('calculatedOuterLengthCm: null') + expect(source).not.toContain('计算策略保存后回读不一致,请刷新后重试') expect(source).toContain('已保存并绑定计算规则,体积已重新计算') expect(source).toContain('const measuredGrossWeight = Number(measurementDetail.value?.actualGrossWeightKg)') expect(source).toContain('const measuredNetWeight = Number(measurementDetail.value?.actualNetWeightKg)') diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.vue b/src/modules/unified-orders/pages/UnifiedOrdersView.vue index 57f9c1e2..1c07f275 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.vue +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.vue @@ -478,6 +478,19 @@ async function handleOuterModeDropdownVisibleChange(visible: boolean) { } } +async function waitForSavedMeasurementVersion(tenantId: string, inboundId: string, savedVersion: number) { + for (let attempt = 0; attempt < 6; attempt += 1) { + try { + const refreshed = await getInboundMeasurement(tenantId, inboundId) + if (Number(refreshed.version) >= savedVersion) return refreshed + } catch { + // 保存结果已由 PUT 确认,短暂的详情读取失败只影响同步等待。 + } + await new Promise((resolve) => setTimeout(resolve, 250)) + } + return null +} + const statusTabs = computed(() => [ { value: '' as const, label: '全部' }, ...unifiedOrderStatusOptions, @@ -898,9 +911,6 @@ async function updateMeasurementCalculationMode(row: Record | n const targetIds = new Set(measurement.items .filter((item) => !row || (itemId ? String(item.id) === itemId : normalizedIdentifier(item.itemNo) === itemNo)) .map((item) => String(item.id))) - const targetItemNos = new Set(measurement.items - .filter((item) => targetIds.has(String(item.id))) - .map((item) => normalizedIdentifier(item.itemNo))) if (!targetIds.size) { ElMessage.warning('当前数据尚未关联实测明细,暂不能设置计算方式') return false @@ -924,7 +934,7 @@ async function updateMeasurementCalculationMode(row: Record | n ElMessage.warning('该客户尚未启用系数配置,请先到客户计费规则中设置默认规则') return false } - await saveInboundMeasurementDraft(String(summary.tenantId), String(summary.inboundId), { + const savedDraft = await saveInboundMeasurementDraft(String(summary.tenantId), String(summary.inboundId), { measurementId: String(measurement.measurementId), version: measurement.version, actualGoodsName: measurement.actualGoodsName, @@ -954,25 +964,28 @@ async function updateMeasurementCalculationMode(row: Record | n remark: item.remark, })), }) - measurementLoadedKey.value = '' - await loadMeasurementDetails() - const persistedItems = measurementDetail.value?.items - .filter((item) => targetItemNos.has(normalizedIdentifier(item.itemNo))) || [] - const persisted = persistedItems.length === targetItemNos.size && persistedItems.every((item) => ( - item.coefficientMode === mode - && (mode !== 'MULTIPLY' || String(item.chargeRuleId) === String(activeRule!.id)) - && [item.calculatedOuterLengthCm, item.calculatedOuterWidthCm, item.calculatedOuterHeightCm] - .every((value, index, dimensions) => { - // 旧服务实例可能尚未返回新版计算结果字段;计算方式已回读成功时不能误判并回滚下拉。 - if (dimensions.every((dimension) => dimension == null)) return true - if (value == null) return false - const expected = calculatedMeasurementRow(item as unknown as Record, mode) - return Math.abs(Number(value) - Number([expected.lengthCm, expected.widthCm, expected.heightCm][index])) < 0.001 - }) - )) - if (!persisted) { - throw new Error('计算策略保存后回读不一致,请刷新后重试') + // PUT 返回的新版本已经代表事务保存成功。详情查询可能经过读副本并短暂返回旧版本, + // 不能用紧随其后的旧数据否定本次成功保存;先按新版本和本次规则更新本地视图。 + measurementDetail.value = { + ...measurement, + version: savedDraft.version, + measurementStatus: savedDraft.status, + items: measurement.items.map((item) => targetIds.has(String(item.id)) ? { + ...item, + coefficientMode: mode, + chargeRuleId: mode === 'MULTIPLY' ? activeRule!.id : null, + calculatedOuterLengthCm: null, + calculatedOuterWidthCm: null, + calculatedOuterHeightCm: null, + } : item), } + measurementSectionModes.outer = mode + const refreshed = await waitForSavedMeasurementVersion( + String(summary.tenantId), String(summary.inboundId), savedDraft.version, + ) + if (refreshed) measurementDetail.value = refreshed + measurementSectionModes.outer = mode + measurementLoadedKey.value = '' ElMessage.success(`${row ? '当前数据' : '全部测量数据'}已保存并绑定计算规则,体积已重新计算`) return true } catch (error) {