This commit is contained in:
2026-08-07 18:44:55 +08:00
parent 2425e0cac1
commit 38a0ffd3e3
9 changed files with 272 additions and 40 deletions
@@ -112,6 +112,19 @@ describe('inbound weight OCR API', () => {
{ version: 1 },
{ params: { tenantId: '10001' } },
)
const confirmWithAdjustment = {
version: 0,
adjustedWeightValue: 286.125,
adjustedWeightUnit: 'KG' as const,
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 286.125 KG',
}
await confirmWeightResult('10001', '20001', '30002', confirmWithAdjustment)
expect(http.post).toHaveBeenLastCalledWith(
'/platform/v1/first-leg/inbounds/20001/weight-results/30002/confirm',
confirmWithAdjustment,
{ params: { tenantId: '10001' } },
)
})
it('downloads an authenticated image as a blob', async () => {
@@ -0,0 +1,115 @@
import ElementPlus from 'element-plus'
import { createPinia, setActivePinia } from 'pinia'
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { useAccessPreviewStore } from '@/core/access/accessPreview'
import { useAuthStore } from '@/core/auth/auth'
import {
confirmWeightResult,
correctWeightResult,
getWeightWorkspace,
} from '../api/weightOcr'
import type { WeightResultResource, WeightWorkspaceResource } from '../types'
import WeightOcrPanel from './WeightOcrPanel.vue'
vi.mock('../api/weightOcr', async () => {
const actual = await vi.importActual<typeof import('../api/weightOcr')>('../api/weightOcr')
return {
...actual,
confirmWeightResult: vi.fn(),
correctWeightResult: vi.fn(),
getWeightWorkspace: vi.fn(),
}
})
const pendingWeight: WeightResultResource = {
id: '30001',
fileId: '40001',
ocrProvider: 'FILE_WEIGHT_OCR',
ocrRawText: '285.5',
ocrWeightValue: 285.5,
ocrWeightUnit: 'KG',
confidence: 0.50972,
adjustedWeightValue: null,
adjustedWeightUnit: null,
finalWeightKg: null,
recognitionStatus: 'PENDING_CONFIRM',
adjustmentReason: null,
adjustedBy: null,
adjustedAt: null,
confirmedBy: null,
confirmedAt: null,
version: 0,
}
const workspace: WeightWorkspaceResource = {
inboundId: '20001',
inboundCode: 'RK-20001',
processStatus: 'MEASURING',
actualGrossWeightKg: null,
weightResults: [pendingWeight],
}
enableAutoUnmount(afterEach)
function mountPanel() {
const pinia = createPinia()
setActivePinia(pinia)
const auth = useAuthStore()
auth.token = 'token'
auth.permissions = [
'platform:firstleg:inbound:measure:view',
'platform:firstleg:inbound:weight:edit',
'platform:firstleg:inbound:weight:confirm',
]
useAccessPreviewStore().initializeAfterLogin()
return mount(WeightOcrPanel, {
attachTo: document.body,
props: { customerId: '10001', inboundId: '20001' },
global: { plugins: [pinia, ElementPlus] },
})
}
describe('WeightOcrPanel confirmation behavior', () => {
beforeEach(() => {
vi.clearAllMocks()
document.body.innerHTML = ''
vi.mocked(getWeightWorkspace).mockResolvedValue(workspace)
vi.mocked(confirmWeightResult).mockResolvedValue({
...pendingWeight,
recognitionStatus: 'CONFIRMED',
finalWeightKg: 285.5,
version: 1,
})
})
it('confirms an unchanged OCR value with one request', async () => {
const wrapper = mountPanel()
await flushPromises()
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
await flushPromises()
expect(confirmWeightResult).toHaveBeenCalledTimes(1)
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', { version: 0 })
expect(correctWeightResult).not.toHaveBeenCalled()
})
it('sends the adjusted value and a specific audit reason in the same confirmation request', async () => {
const wrapper = mountPanel()
await flushPromises()
await wrapper.get('input[aria-label="称重图片序号 1 的确认重量"]').setValue('286.125')
await wrapper.get('.weight-row__editor .el-button--success').trigger('click')
await flushPromises()
expect(confirmWeightResult).toHaveBeenCalledTimes(1)
expect(confirmWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', {
version: 0,
adjustedWeightValue: 286.125,
adjustedWeightUnit: 'KG',
adjustmentReason: 'OCR 原值 285.500 KG,人工确认 286.125 KG',
})
expect(correctWeightResult).not.toHaveBeenCalled()
})
})
@@ -25,8 +25,9 @@ describe('WeightOcrPanel contract', () => {
expect(source).toContain('workspace.value?.actualGrossWeightKg')
expect(source).toContain('v-model="weightDrafts[row.id].value"')
expect(source).toContain('识别值已自动填入,可修改后直接确认保存。')
expect(source).toContain("adjustmentReason: '人工核对后修改识别重量'")
expect(source).toContain('version = corrected.version')
expect(source).toContain('payload.adjustedWeightValue = Number(draft.value)')
expect(source).toContain('payload.adjustmentReason = buildAdjustmentReason(row)')
expect(source).not.toContain('version = corrected.version')
expect(source).not.toContain('title="人工修正重量"')
})
@@ -106,6 +106,12 @@ function hasWeightDraftChanged(row: WeightResultResource) {
return Number(draft.value) !== Number(savedValue) || draft.unit !== savedUnit
}
function buildAdjustmentReason(row: WeightResultResource) {
const draft = weightDrafts.value[row.id]
const ocrUnit = normalizeUnit(row.ocrWeightUnit)
return `OCR 原值 ${formatWeight(row.ocrWeightValue, ocrUnit)},人工确认 ${formatWeight(Number(draft.value), draft.unit)}`
}
async function loadWorkspace() {
if (!customerId.value || !props.inboundId || !canView.value) {
workspace.value = null
@@ -188,21 +194,17 @@ async function confirmResult(row: WeightResultResource) {
activeAction.value = key
actionError.value = null
try {
let version = row.version
const payload = { version: row.version } as Parameters<typeof confirmWeightResult>[3]
if (hasWeightDraftChanged(row)) {
if (!canEdit.value) {
ElMessage.warning('当前账号缺少重量修改权限')
return
}
const corrected = await correctWeightResult(customerId.value, props.inboundId, row.id, {
version,
adjustedWeightValue: Number(draft.value),
adjustedWeightUnit: draft.unit,
adjustmentReason: '人工核对后修改识别重量',
})
version = corrected.version
payload.adjustedWeightValue = Number(draft.value)
payload.adjustedWeightUnit = draft.unit
payload.adjustmentReason = buildAdjustmentReason(row)
}
await confirmWeightResult(customerId.value, props.inboundId, row.id, { version })
await confirmWeightResult(customerId.value, props.inboundId, row.id, payload)
ElMessage.success('重量已确认并计入实际总重量')
await loadWorkspace()
emit('changed')
@@ -399,6 +401,7 @@ defineExpose({ reload: loadWorkspace })
<span>单位</span>
<el-segmented
v-model="weightDrafts[row.id].unit"
:aria-label="`称重图片序号 ${index + 1} 的重量单位`"
:options="['KG', 'LB']"
:disabled="Boolean(activeAction) || !editable || !canEdit || !canConfirm"
/>
+3
View File
@@ -60,4 +60,7 @@ export interface CorrectWeightResultRequest {
export interface ConfirmWeightResultRequest {
version: number
adjustedWeightValue?: number
adjustedWeightUnit?: 'KG' | 'LB'
adjustmentReason?: string
}