diff --git a/src/modules/inbounds/measurement/InboundMeasurementPanel.test.ts b/src/modules/inbounds/measurement/InboundMeasurementPanel.test.ts index f78872b8..c0b6ee32 100644 --- a/src/modules/inbounds/measurement/InboundMeasurementPanel.test.ts +++ b/src/modules/inbounds/measurement/InboundMeasurementPanel.test.ts @@ -114,7 +114,14 @@ function measurement(overrides: Partial = {}): Inbound outerHeightCm: null, remark: '设备自动回传', }], - weightResults: [], + weightResults: [{ + id: '30001', fileId: '40001', palletId: '50001', palletCode: 'TP-001', palletType: '木托盘', + palletCapacityCbm: 1.2, palletTareWeightKg: 10, ocrProvider: 'FILE_WEIGHT_OCR', ocrRawText: '120', + ocrWeightValue: 120, ocrWeightUnit: 'KG', confidence: 0.98, adjustedWeightValue: null, + adjustedWeightUnit: null, grossWeightKg: 120, netWeightKg: 110, recognitionStatus: 'CONFIRMED', + adjustmentReason: null, adjustedBy: null, adjustedAt: null, confirmedBy: '9', + confirmedAt: '2026-08-04T10:35:00+08:00', version: 1, + }], ...overrides, } } @@ -478,6 +485,16 @@ describe('InboundMeasurementPanel', () => { expect(wrapper.emitted('changed')).toHaveLength(1) }) + it('requires at least one confirmed weight image before submitting for review', async () => { + vi.mocked(getInboundMeasurement).mockResolvedValueOnce(measurement({ weightResults: [] })) + const wrapper = await mountPanel() + + expect(wrapper.text()).toContain('至少上传并确认一张称重图片后才能提交审核') + const submit = wrapper.findAll('button').find((button) => button.text().includes('提交审核')) + expect(submit?.attributes('disabled')).toBeDefined() + expect(submitInboundMeasurement).not.toHaveBeenCalled() + }) + it('emits updated without closing the parent task after manual carton entry', async () => { const wrapper = await mountPanel() const source = await import('./InboundMeasurementPanel.vue?raw').then((module) => module.default) diff --git a/src/modules/inbounds/measurement/InboundMeasurementPanel.vue b/src/modules/inbounds/measurement/InboundMeasurementPanel.vue index 1a3fa6e9..69438c9e 100644 --- a/src/modules/inbounds/measurement/InboundMeasurementPanel.vue +++ b/src/modules/inbounds/measurement/InboundMeasurementPanel.vue @@ -112,7 +112,8 @@ const confirmedPackageCount = computed(() => form.items.reduce((sum, item) => su const expectedPackageCount = computed(() => detail.value?.originalPackageCount ?? null) const packageCountDifference = computed(() => expectedPackageCount.value == null ? null : confirmedPackageCount.value - expectedPackageCount.value) const packageCountMatched = computed(() => packageCountDifference.value === null || packageCountDifference.value === 0) -const maySubmit = computed(() => canSubmit.value && submitEditableProcess.value && Boolean(form.measurementId) && packageCountMatched.value && !loading.value && !saving.value) +const hasConfirmedWeightResult = computed(() => detail.value?.weightResults.some((item) => item.recognitionStatus === 'CONFIRMED') === true) +const maySubmit = computed(() => canSubmit.value && submitEditableProcess.value && Boolean(form.measurementId) && packageCountMatched.value && hasConfirmedWeightResult.value && !loading.value && !saving.value) const snapshot = computed(() => JSON.stringify(form)) const isDirty = computed(() => Boolean(detail.value) && snapshot.value !== baseline.value) const registrationOpen = computed(() => hasContext.value && canView.value && Boolean(detail.value)) @@ -776,7 +777,8 @@ defineExpose({ saveDraft, submitForReview, updateActualWeights, mayMaintain, may