feat(appointment): add shared container followup workspace

This commit is contained in:
2026-10-10 08:42:03 +08:00
parent b835e52bcb
commit 84488adf12
9 changed files with 173 additions and 27 deletions
@@ -2,10 +2,11 @@ import ElementPlus from 'element-plus'
import { flushPromises, mount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import AppointmentCargoPanel from './AppointmentCargoPanel.vue'
import AppointmentContainerPanel from './AppointmentContainerPanel.vue'
import AppointmentFollowupDialog from './AppointmentFollowupDialog.vue'
import { getFollowups, listPlanningCargo, resolvePlanningSource, type PlanningCargo, type PlanningSource } from './planningApi'
import { getFollowups, listPlanningCargo, resolvePlanningSource, listPlanningContainers, resolvePlanningContainer, type PlanningCargo, type PlanningSource } from './planningApi'
vi.mock('./planningApi', () => ({ listPlanningCargo: vi.fn(), resolvePlanningSource: vi.fn(), getFollowups: vi.fn(), saveFollowup: vi.fn() }))
vi.mock('./planningApi', () => ({ listPlanningCargo: vi.fn(), resolvePlanningSource: vi.fn(), getFollowups: vi.fn(), saveFollowup: vi.fn(), listPlanningContainers: vi.fn(), resolvePlanningContainer: vi.fn() }))
vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) }))
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
const source: PlanningSource = { sourceKey: 'ORDER:1', customerId: 'A', orderId: '1', inboundCode: 'IN-A', bookingNo: null, containerNo: 'CONTAINER-A', originWarehouseId: '100', originWarehouseName: '美国仓', destinationKey: 'FBA:ONT8', destinationWarehouseCode: 'ONT8', packages: 20, sourceVersion: 'ORDER:1', canFollowup: true, blockReasons: [] }
@@ -14,6 +15,23 @@ const coverage = { status: 'UNASSIGNED', appointments: [], missingFields: [], ch
describe('appointment tables use actual shared table slots', () => {
beforeEach(() => vi.resetAllMocks())
it('renders one shared container and resolves each receiving warehouse without per-row requests', async () => {
vi.mocked(listPlanningContainers).mockResolvedValue({ total: 1, records: [{ containerBookingId: 'C1', containerNo: 'CONTAINER-A', orderCount: 20, customerCount: 12, packages: null, unknownPackageOrders: 1, earliestArrivalAt: null, latestArrivalAt: null, standardNode: 'DEPARTED', sourceVersion: null, incompleteScope: false, warehouses: [{ warehouseId: '100', warehouseName: '洛杉矶仓', orderCount: 20, customerCount: 12 }] }] })
vi.mocked(resolvePlanningContainer).mockResolvedValue({ containerBookingId: 'C1', containerNo: 'CONTAINER-A', warehouseId: '100', warehouseName: '洛杉矶仓', canFollowup: true, blockReasons: [] })
const wrapper = mount(AppointmentContainerPanel, { global: { plugins: [ElementPlus], stubs: { AppointmentFollowupDialog: true } } })
await flushPromises()
expect(listPlanningContainers).toHaveBeenCalledTimes(1)
expect(resolvePlanningContainer).not.toHaveBeenCalled()
const rows = wrapper.findAll('.el-table__body-wrapper .el-table__row')
expect(rows).toHaveLength(1)
expect(rows[0]!.text()).toContain('待核实')
expect(rows[0]!.text()).toContain('洛杉矶仓')
await rows[0]!.findAll('button').find(button => button.text() === '接仓跟进')!.trigger('click')
await flushPromises()
expect(resolvePlanningContainer).toHaveBeenCalledExactlyOnceWith('C1', '100')
expect(wrapper.findComponent(AppointmentFollowupDialog).props('container')?.warehouseId).toBe('100')
wrapper.unmount()
})
it('renders working source actions and readable progress through DataTable and RowActions', async () => {
vi.mocked(listPlanningCargo).mockResolvedValue({ records: [cargo], page: 1, size: 20, total: 1, pages: 1 })
vi.mocked(resolvePlanningSource).mockResolvedValue({ source, coverage })