From 8b862da08497ff6fff548103bd662f9df67cc68f Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 9 Sep 2026 20:36:49 +0800 Subject: [PATCH] fix(admin): lock submitted measurement rule editing --- .../pages/UnifiedOrdersView.test.ts | 10 +++-- .../pages/UnifiedOrdersView.vue | 45 ++++++++++++------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts index d2dbf48d..148f2874 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts @@ -346,7 +346,8 @@ describe('UnifiedOrdersView contract', () => { expect(source).toContain('仓库修改外箱(宽)') expect(source).toContain('仓库修改外箱(高)') expect(source).toContain('saveWarehouseOuterDimensions') - expect(source).toContain("'MEASURE_REJECTED', 'WAIT_SPLIT'") + expect(source).toContain("'PREPARING', 'WAIT_MEASURE', 'MEASURING', 'MEASURE_REJECTED'") + expect(source).toContain('v-if="measurementDraftEditable"') expect(source).not.toContain('请至少输入一项需要修改的外箱尺寸') expect(source).toContain(".map((value) => value == null || value === '' ? null : Number(value))") expect(source).toContain('相关数值已重新计算') @@ -381,7 +382,7 @@ describe('UnifiedOrdersView contract', () => { expect(source).toContain('label="箱规系数" value="MULTIPLY"') }) - it('keeps preview modes independent and persists both outer-carton selectors immediately', () => { + it('keeps preview modes independent and only persists outer-carton selectors while the measurement draft is editable', () => { expect(source).toContain("measurementSectionModes = reactive>") expect(source).toContain(':model-value="measurementSectionModes.customer"') expect(source).toContain(':model-value="measurementSectionModes.outer"') @@ -391,7 +392,10 @@ describe('UnifiedOrdersView contract', () => { expect(source).not.toContain("updateMeasurementSectionMode('outer', $event)") expect(source.match(/@change="selectAndSaveOuterMeasurementMode\(\$event\)"/g)).toHaveLength(2) expect(source).not.toContain('@visible-change="handleOuterModeDropdownVisibleChange($event)"') - expect(source.match(/:disabled="Boolean\(measurementStrategySavingId\) \|\| !can\('platform:firstleg:inbound:measure:edit'\)"/g)).toHaveLength(2) + expect(source.match(/:disabled="Boolean\(measurementStrategySavingId\) \|\| !measurementDraftEditable"/g)).toHaveLength(2) + expect(source).toContain("measurementDetail.value?.processStatus === 'MEASURE_PENDING'") + expect(source).toContain('测量已提交待审核;如需修改箱规计算规则,请先退回测量') + expect(source).toContain('if (!measurementDraftEditable.value)') expect(source).toContain('const previousMode = measurementSectionModes.outer') expect(source).toContain('if (!saved) measurementSectionModes.outer = previousMode') expect(source).not.toContain('handleOuterModeDropdownVisibleChange') diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.vue b/src/modules/unified-orders/pages/UnifiedOrdersView.vue index d0eda136..2267f0e1 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.vue +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.vue @@ -224,6 +224,18 @@ type MeasurementCalculationMode = 'ACTUAL' | 'ADD' | 'MULTIPLY' const measurementSectionModes = reactive>({ customer: 'ACTUAL', outer: 'ACTUAL', actual: 'ACTUAL', }) +const measurementDraftEditableStatuses = new Set([ + 'PREPARING', 'WAIT_MEASURE', 'MEASURING', 'MEASURE_REJECTED', +]) +const measurementDraftEditable = computed(() => ( + can('platform:firstleg:inbound:measure:edit') + && measurementDraftEditableStatuses.has(measurementDetail.value?.processStatus || '') +)) +const measurementDraftLockedHint = computed(() => { + if (!can('platform:firstleg:inbound:measure:edit')) return '当前账号缺少测量编辑权限' + if (measurementDetail.value?.processStatus === 'MEASURE_PENDING') return '测量已提交待审核;如需修改箱规计算规则,请先退回测量' + return '当前测量状态已冻结,不能修改箱规计算规则' +}) const cargoImagePreviewUrls = new Set() const measurementDialogOpen = ref(false) const openWarehouseSuggestionOnMeasurementLoad = ref(false) @@ -516,6 +528,10 @@ function updateMeasurementSectionMode(section: MeasurementSection, mode: Measure async function selectAndSaveOuterMeasurementMode(mode: MeasurementCalculationMode, ruleId?: string) { if (measurementStrategySavingId.value) return + if (!measurementDraftEditable.value) { + ElMessage.warning(measurementDraftLockedHint.value) + return + } const previousMode = measurementSectionModes.outer if (mode === 'MULTIPLY' && !activeMeasurementChargeRule.value) { ElMessage.warning('该客户尚未启用系数配置,请先到客户计费规则中设置默认规则') @@ -969,7 +985,7 @@ function measurementCalculationModeForRow(row: Record): Measure async function updateMeasurementCalculationMode(row: Record | null, mode: MeasurementCalculationMode, selectedRuleId?: string): Promise { const summary = detail.value?.summary const measurement = measurementDetail.value - if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null || !can('platform:firstleg:inbound:measure:edit')) return false + if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null || !measurementDraftEditable.value) return false const itemId = normalizedIdentifier(row?.id) const itemNo = normalizedIdentifier(row?.itemNo) const targetIds = new Set(measurement.items @@ -1065,19 +1081,14 @@ async function updateMeasurementCalculationMode(row: Record | n async function saveWarehouseOuterDimensions(row: Record) { const summary = detail.value?.summary const measurement = measurementDetail.value - const editableMeasurementStatuses = new Set([ - 'WAIT_MEASURE', 'MEASURING', 'MEASURE_PENDING', 'MEASURE_REJECTED', 'WAIT_SPLIT', - ]) - const currentStatus = editableMeasurementStatuses.has(measurement?.processStatus || '') - ? measurement!.processStatus - : summary?.mainStatus || measurement?.processStatus || '' - if (measurement && !editableMeasurementStatuses.has(currentStatus)) { + const currentStatus = measurement?.processStatus || summary?.mainStatus || '' + if (measurement && !measurementDraftEditableStatuses.has(currentStatus)) { const statusLabel = orderStatusLabel(summary?.mainStatus) || measurementStatusLabel(currentStatus) ElMessage.warning(`当前状态为“${statusLabel}”,该状态不可以修改测量数据`) return } if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null - || !can('platform:firstleg:inbound:measure:edit')) return + || !measurementDraftEditable.value) return const dimensions = [row.outerLengthCm, row.outerWidthCm, row.outerHeightCm] .map((value) => value == null || value === '' ? null : Number(value)) if (dimensions.some((value) => value != null && (!Number.isFinite(value) || value <= 0))) { @@ -2442,7 +2453,7 @@ onBeforeUnmount(() => {
-
+
合计箱数:{{ measurementTotals(outerMeasurementRows).count ?? '—' }}总毛重:{{ formatNumber(measurementTotals(outerMeasurementRows).gross) }}总体积:{{ formatNumber(measurementTotals(outerMeasurementRows).volume, 6) }}总材积:{{ formatNumber(measurementTotals(outerMeasurementRows).volumetric) }}
@@ -2450,12 +2461,12 @@ onBeforeUnmount(() => {
箱规计算规则选择 - + - - 规则参数来源:客户管理 + + {{ measurementDraftEditable ? '规则参数来源:客户管理' : measurementDraftLockedHint }}
@@ -2467,15 +2478,15 @@ onBeforeUnmount(() => { - + - + - + - +