This commit is contained in:
2026-08-14 17:38:06 +08:00
parent d1b4a4d3f3
commit 010204da57
12 changed files with 259 additions and 33 deletions
@@ -14,6 +14,7 @@ import {
downloadWeightImage,
downloadWeightThumbnail,
getWeightWorkspace,
getWeightPalletOptions,
uploadWeightImage,
} from '../api/weightOcr'
import type { WeightResultResource, WeightWorkspaceResource } from '../types'
@@ -30,6 +31,7 @@ vi.mock('../api/weightOcr', async () => {
downloadWeightImage: vi.fn(),
downloadWeightThumbnail: vi.fn(),
getWeightWorkspace: vi.fn(),
getWeightPalletOptions: vi.fn(),
uploadWeightImage: vi.fn(),
}
})
@@ -37,6 +39,11 @@ vi.mock('../api/weightOcr', async () => {
const pendingWeight: WeightResultResource = {
id: '30001',
fileId: '40001',
palletId: '50001',
palletCode: 'TP-001',
palletType: '木托盘',
palletCapacityCbm: 1.2,
palletTareWeightKg: 12,
ocrProvider: 'FILE_WEIGHT_OCR',
ocrRawText: '285.5',
ocrWeightValue: 285.5,
@@ -44,7 +51,8 @@ const pendingWeight: WeightResultResource = {
confidence: 0.98,
adjustedWeightValue: null,
adjustedWeightUnit: null,
finalWeightKg: null,
grossWeightKg: 285.5,
netWeightKg: null,
recognitionStatus: 'PENDING_CONFIRM',
adjustmentReason: null,
adjustedBy: null,
@@ -120,6 +128,9 @@ describe('WeightOcrPanel confirmation behavior', () => {
vi.clearAllMocks()
document.body.innerHTML = ''
vi.mocked(getWeightWorkspace).mockResolvedValue(workspace)
vi.mocked(getWeightPalletOptions).mockResolvedValue([{
palletId: '50001', palletCode: 'TP-001', palletType: '木托盘', capacityCbm: 1.2, tareWeightKg: 12,
}])
vi.mocked(downloadWeightImage).mockResolvedValue(new Blob(['image'], { type: 'image/jpeg' }))
vi.mocked(downloadWeightThumbnail).mockResolvedValue(new Blob(['thumb'], { type: 'image/jpeg' }))
vi.stubGlobal('URL', {
@@ -129,7 +140,8 @@ describe('WeightOcrPanel confirmation behavior', () => {
vi.mocked(confirmWeightResult).mockResolvedValue({
...pendingWeight,
recognitionStatus: 'CONFIRMED',
finalWeightKg: 285.5,
grossWeightKg: 297.5,
netWeightKg: 285.5,
version: 1,
})
})
@@ -154,6 +166,8 @@ describe('WeightOcrPanel confirmation behavior', () => {
})
const wrapper = mountPanel()
await flushPromises()
await wrapper.find('.pallet-picker .el-select').trigger('click')
await new DOMWrapper(document.body).find('.el-select-dropdown__item').trigger('click')
const input = wrapper.get('input[type="file"]')
const file = new File(['image'], 'weight.jpg', { type: 'image/jpeg' })
Object.defineProperty(input.element, 'files', { configurable: true, value: [file] })
@@ -162,6 +176,7 @@ describe('WeightOcrPanel confirmation behavior', () => {
await flushPromises()
expect(uploadWeightImage).toHaveBeenCalledWith('10001', '20001', file)
expect(createWeightResult).toHaveBeenCalledWith('10001', '20001', expect.objectContaining({ palletId: '50001' }))
expect(document.body.textContent).toContain('确认称重图片')
expect(document.body.textContent).toContain('识别重量 12.500 KG')
expect(document.body.querySelector('input[aria-label="当前图片确认重量"]')).not.toBeNull()
@@ -225,7 +240,7 @@ describe('WeightOcrPanel confirmation behavior', () => {
.mockResolvedValueOnce({
...workspace,
actualGrossWeightKg: 285.5,
weightResults: [{ ...pendingWeight, recognitionStatus: 'CONFIRMED', finalWeightKg: 285.5, version: 1 }],
weightResults: [{ ...pendingWeight, recognitionStatus: 'CONFIRMED', grossWeightKg: 297.5, netWeightKg: 285.5, version: 1 }],
})
const wrapper = mountPanel()
await flushPromises()
@@ -236,10 +251,47 @@ describe('WeightOcrPanel confirmation behavior', () => {
expect(wrapper.emitted('summaryChanged')).toEqual([[285.5]])
expect(wrapper.emitted('changed')).toHaveLength(1)
expect(wrapper.text()).toContain('已确认总毛重')
expect(wrapper.text()).toContain('货物总重量')
expect(wrapper.text()).toContain('285.500 KG')
})
it('requires a pallet selection before opening the file picker', async () => {
const wrapper = mountPanel()
await flushPromises()
const click = vi.spyOn(wrapper.get('input[type="file"]').element as HTMLInputElement, 'click')
await wrapper.findAll('button').find((button) => button.text().includes('上传称重图片'))?.trigger('click')
expect(click).not.toHaveBeenCalled()
})
it('shows an actionable empty state when the warehouse has no pallet options', async () => {
vi.mocked(getWeightPalletOptions).mockResolvedValueOnce([])
const wrapper = mountPanel()
await flushPromises()
expect(wrapper.text()).toContain('当前仓库暂无可选托盘')
expect(wrapper.findAll('button').some((button) => button.text().includes('重新加载'))).toBe(true)
})
it('shows pallet loading failures without hiding existing weight results', async () => {
vi.mocked(getWeightPalletOptions).mockRejectedValueOnce(new ApiResponseError('托盘服务暂不可用', 'A0500', 503))
const wrapper = mountPanel()
await flushPromises()
expect(wrapper.text()).toContain('托盘服务暂不可用')
expect(wrapper.findAll('.weight-card')).toHaveLength(1)
})
it('does not load weight or pallet data without measurement view permission', async () => {
const wrapper = mountPanel([])
await flushPromises()
expect(wrapper.text()).toContain('缺少入库测量查看权限')
expect(getWeightWorkspace).not.toHaveBeenCalled()
expect(getWeightPalletOptions).not.toHaveBeenCalled()
})
it('requires explicit image review before confirming a low-confidence OCR value', async () => {
vi.mocked(getWeightWorkspace).mockResolvedValue({
...workspace,