优化
This commit is contained in:
@@ -61,6 +61,14 @@ const pendingWeight: WeightResultResource = {
|
||||
adjustedAt: null,
|
||||
confirmedBy: null,
|
||||
confirmedAt: null,
|
||||
palletSequence: 1,
|
||||
blockId: '70001',
|
||||
slotNo: 1,
|
||||
reservationId: '71001',
|
||||
locationId: '72001',
|
||||
locationCode: 'A01',
|
||||
sharedOverflow: false,
|
||||
slotStatus: 'BOUND',
|
||||
version: 0,
|
||||
}
|
||||
|
||||
@@ -71,6 +79,24 @@ const workspace: WeightWorkspaceResource = {
|
||||
actualGrossWeightKg: null,
|
||||
actualNetWeightKg: null,
|
||||
weightResults: [pendingWeight],
|
||||
palletLocationGuide: {
|
||||
blockId: '70001',
|
||||
reservedSlotCount: 1,
|
||||
actualPalletCount: 1,
|
||||
reservedEmptySlotCount: 0,
|
||||
slots: [{
|
||||
slotNo: 1,
|
||||
reservationId: '71001',
|
||||
locationId: '72001',
|
||||
locationCode: 'A01',
|
||||
sharedOverflow: false,
|
||||
slotStatus: 'BOUND',
|
||||
boundWeightResultId: '30001',
|
||||
palletSequence: 1,
|
||||
palletId: '50001',
|
||||
palletCode: 'TP-001',
|
||||
}],
|
||||
},
|
||||
}
|
||||
|
||||
function palletPage(records = [{
|
||||
@@ -205,9 +231,137 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
expect(wrapper.text()).not.toContain('raw-0')
|
||||
})
|
||||
|
||||
it('renders server-bound pallet sequence, target location, and pending putaway status ahead of OCR facts', async () => {
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
const card = wrapper.get('.weight-card')
|
||||
expect(card.text()).toContain('第 1 托')
|
||||
expect(card.text()).toContain('目标库位')
|
||||
expect(card.text()).toContain('A01')
|
||||
expect(card.text()).toContain('整票预留库位')
|
||||
expect(card.text()).toContain('待上架')
|
||||
const putawayGuide = card.get('.weight-card__putaway').element
|
||||
expect(putawayGuide.compareDocumentPosition(
|
||||
card.get('.weight-card__value').element,
|
||||
) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders the authoritative whole-inbound reservation summary and an empty reserved slot', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
palletLocationGuide: {
|
||||
blockId: '70001',
|
||||
reservedSlotCount: 3,
|
||||
actualPalletCount: 2,
|
||||
reservedEmptySlotCount: 1,
|
||||
slots: [
|
||||
{ slotNo: 1, reservationId: '71001', locationId: '72001', locationCode: 'A01', sharedOverflow: false, slotStatus: 'BOUND', boundWeightResultId: '30001', palletSequence: 1, palletId: '50001', palletCode: 'TP-001' },
|
||||
{ slotNo: 2, reservationId: '71002', locationId: '72002', locationCode: 'A02', sharedOverflow: false, slotStatus: 'TRANSFERRED', boundWeightResultId: '30002', palletSequence: 2, palletId: '50002', palletCode: 'TP-002' },
|
||||
{ slotNo: 3, reservationId: '71003', locationId: '72003', locationCode: 'A03', sharedOverflow: false, slotStatus: 'RESERVED_EMPTY', boundWeightResultId: null, palletSequence: null, palletId: null, palletCode: null },
|
||||
],
|
||||
},
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
const guide = wrapper.get('.putaway-guide')
|
||||
expect(guide.text()).toContain('整票预留库位')
|
||||
expect(guide.text()).toContain('A01 / A02 / A03')
|
||||
expect(guide.text()).toContain('预留槽位数3')
|
||||
expect(guide.text()).toContain('实际托数2')
|
||||
expect(guide.text()).toContain('预留空位数1')
|
||||
expect(guide.text()).toContain('A03预留空位本票预留空位')
|
||||
})
|
||||
|
||||
it('shows an explicit whole-inbound unassigned state when no guide exists', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({ ...workspace, palletLocationGuide: null })
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain('尚未分配整票预留库位')
|
||||
})
|
||||
|
||||
it('marks A0 as a temporary overflow location from the server flag', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
weightResults: [{ ...pendingWeight, locationCode: 'A0', sharedOverflow: true }],
|
||||
palletLocationGuide: {
|
||||
...workspace.palletLocationGuide!,
|
||||
slots: [{
|
||||
...workspace.palletLocationGuide!.slots[0]!,
|
||||
locationCode: 'A0',
|
||||
sharedOverflow: true,
|
||||
}],
|
||||
},
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain('A0 临时溢出位')
|
||||
expect(wrapper.get('.weight-card__putaway').classes()).toContain('is-overflow')
|
||||
expect(wrapper.get('.putaway-guide__slots li').classes()).toContain('is-overflow')
|
||||
})
|
||||
|
||||
it.each([
|
||||
['TRANSFERRED', '已上架'],
|
||||
['RELEASED', '已释放'],
|
||||
['RESERVED_EMPTY', '预留空位'],
|
||||
] as const)('renders the authoritative %s slot status as %s', async (slotStatus, label) => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
weightResults: [{ ...pendingWeight, slotStatus }],
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain(label)
|
||||
})
|
||||
|
||||
it('shows an explicit unassigned state when the server has not bound a slot', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockResolvedValue({
|
||||
...workspace,
|
||||
weightResults: [{
|
||||
...pendingWeight,
|
||||
palletSequence: null,
|
||||
blockId: null,
|
||||
slotNo: null,
|
||||
reservationId: null,
|
||||
locationId: null,
|
||||
locationCode: null,
|
||||
sharedOverflow: null,
|
||||
slotStatus: null,
|
||||
}],
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain('托盘未分配')
|
||||
expect(wrapper.text()).toContain('目标库位未分配')
|
||||
})
|
||||
|
||||
it('deletes a pending image with its optimistic-lock version', async () => {
|
||||
vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue(undefined as never)
|
||||
const confirm = vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue(undefined as never)
|
||||
vi.mocked(deleteWeightResult).mockResolvedValue(undefined)
|
||||
vi.mocked(getWeightWorkspace)
|
||||
.mockResolvedValueOnce(workspace)
|
||||
.mockResolvedValueOnce({
|
||||
...workspace,
|
||||
weightResults: [],
|
||||
palletLocationGuide: {
|
||||
...workspace.palletLocationGuide!,
|
||||
actualPalletCount: 0,
|
||||
reservedEmptySlotCount: 1,
|
||||
slots: [{
|
||||
...workspace.palletLocationGuide!.slots[0]!,
|
||||
slotStatus: 'RESERVED_EMPTY',
|
||||
boundWeightResultId: null,
|
||||
palletSequence: null,
|
||||
palletId: null,
|
||||
palletCode: null,
|
||||
}],
|
||||
},
|
||||
})
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
@@ -215,6 +369,48 @@ describe('WeightOcrPanel confirmation behavior', () => {
|
||||
await flushPromises()
|
||||
|
||||
expect(deleteWeightResult).toHaveBeenCalledWith('10001', '20001', '30001', 0)
|
||||
expect(confirm).toHaveBeenCalledWith(
|
||||
expect.stringContaining('对应库位仍为本票保留,不会释放给其他订单'),
|
||||
'删除称重图片',
|
||||
expect.any(Object),
|
||||
)
|
||||
expect(getWeightWorkspace).toHaveBeenCalledTimes(2)
|
||||
expect(wrapper.findAll('.weight-card')).toHaveLength(0)
|
||||
expect(wrapper.get('.putaway-guide').text()).toContain('预留空位数1')
|
||||
expect(wrapper.get('.putaway-guide').text()).toContain('A01预留空位本票预留空位')
|
||||
})
|
||||
|
||||
it('keeps the image and server workspace visible when deletion fails', async () => {
|
||||
vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue(undefined as never)
|
||||
const errorMessage = vi.spyOn(ElMessage, 'error')
|
||||
vi.mocked(deleteWeightResult).mockRejectedValueOnce(
|
||||
new ApiResponseError('无权删除当前称重图片', 'A0403', 403),
|
||||
)
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
await wrapper.get('button[aria-label="删除称重图片 1"]').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.findAll('.weight-card')).toHaveLength(1)
|
||||
expect(wrapper.text()).toContain('A01')
|
||||
expect(getWeightWorkspace).toHaveBeenCalledTimes(1)
|
||||
expect(errorMessage).toHaveBeenCalledWith(expect.objectContaining({
|
||||
message: '当前账号无权访问该数据,请联系管理员确认权限',
|
||||
}))
|
||||
})
|
||||
|
||||
it('shows a retryable workspace load failure without fabricating putaway guidance', async () => {
|
||||
vi.mocked(getWeightWorkspace).mockRejectedValueOnce(
|
||||
new ApiResponseError('称重工作区暂不可用', 'A0500', 503),
|
||||
)
|
||||
const wrapper = mountPanel()
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain('称重数据加载失败')
|
||||
expect(wrapper.text()).toContain('称重工作区暂不可用')
|
||||
expect(wrapper.find('.putaway-guide').exists()).toBe(false)
|
||||
expect(wrapper.find('.putaway-guide-empty').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('shows only the key weights and allows direct confirmation', async () => {
|
||||
|
||||
Reference in New Issue
Block a user