fix(appointments): prioritize calendar and collapse data notices

This commit is contained in:
2026-10-10 16:08:25 +08:00
parent c69115f1b7
commit e404fe1049
4 changed files with 41 additions and 28 deletions
@@ -31,7 +31,7 @@ function render(openCalendar = true) {
const wrapper = mount(AppointmentCalendarView, { global: { directives: { loading: {} }, stubs: {
AdminPage: { template: '<main><slot /></main>' },
AppointmentContainerPanel: true,
AppointmentCalendarPanel: { name: 'AppointmentCalendarPanel', mounted() { this.$emit('layers', { arrivals: true, trips: true }) }, props: ['events', 'incomplete'], template: '<button data-create @click="$emit(\'create\', \'2026-10-09\')">新增预约</button>' },
AppointmentCalendarPanel: { name: 'AppointmentCalendarPanel', mounted() { this.$emit('layers', { arrivals: true, trips: true }) }, props: ['events', 'incomplete', 'notices'], template: '<div><button data-create @click="$emit(\'create\', \'2026-10-09\')">新增预约</button><slot name="notice-actions" /></div>' },
AppDialog: { props: ['modelValue'], template: '<div v-if="modelValue"><slot /><button data-save @click="$emit(\'confirm\')">保存</button></div>' },
ElForm: { template: '<form><slot /></form>' },
ElFormItem: { template: '<label><slot /></label>' },
@@ -61,23 +61,23 @@ describe('appointment calendar data integration', () => {
vi.mocked(createFbaAppointment).mockResolvedValue({ version: 0, id: '1', appointmentNo: 'APT-AB', plannedDate: '2026-10-09', appointmentAt: null, originWarehouseId: '100', appointmentStatus: 'PENDING', selectedCount: 2, fbaWarehouseCode: 'ONT8', items: [] })
})
it('keeps exactly the documented three work views and defaults to the container list without calendar requests', async () => {
it('puts calendar first and opens it by default without reloading when switching back', async () => {
const wrapper = render(false); await flushPromises()
const tabs = wrapper.get('[aria-label="预约工作视图"]').findAll('button')
expect(tabs.map(button => button.text())).toEqual(['提柜与到仓', '送仓与排车', '预约日历'])
expect(tabs.map(button => button.text())).toEqual(['预约日历', '提柜与到仓', '送仓与排车'])
expect(tabs[0]!.attributes('aria-pressed')).toBe('true')
expect(wrapper.text()).not.toContain('美国预约总览')
expect(listFbaAppointmentCalendar).not.toHaveBeenCalled()
expect(listArrivalCalendar).not.toHaveBeenCalled()
await tabs[2]!.trigger('click'); await flushPromises()
expect(listFbaAppointmentCalendar).toHaveBeenCalledTimes(1)
await tabs[0]!.trigger('click'); await tabs[2]!.trigger('click'); await flushPromises()
expect(listArrivalCalendar).toHaveBeenCalledTimes(1)
await tabs[1]!.trigger('click'); await flushPromises()
expect(listFbaAppointmentCalendar).toHaveBeenCalledTimes(1)
await tabs[0]!.trigger('click'); await flushPromises()
expect(listFbaAppointmentCalendar).toHaveBeenCalledTimes(1)
})
it('distinguishes missing country data from truncation instead of suggesting a narrower date range', async () => {
vi.mocked(listPickupCalendar).mockResolvedValueOnce({ records: [], truncated: false, unclassifiedCount: 74, scopeBasis: 'US_DESTINATION_WAREHOUSE', timeBasis: 'SOURCE_LOCAL_UNSPECIFIED' })
const wrapper = render(); await flushPromises()
expect(wrapper.text()).toContain('74 条提柜记录')
expect(wrapper.findComponent({ name: 'AppointmentCalendarPanel' }).props('notices').join(' ')).toContain('74 条提柜记录')
expect(wrapper.text()).not.toContain('缩小日期范围')
})
it('shows the original pickup time once without claiming a port time zone and retains partial-source warnings', async () => {
@@ -86,14 +86,14 @@ describe('appointment calendar data integration', () => {
const panel=wrapper.findComponent({name:'AppointmentCalendarPanel'})
expect(panel.props('events')).toEqual([expect.objectContaining({type:'pickup',date:'2026-10-09',time:'11:00',sourcePath:'/container-loading/overseas/123'})])
expect(panel.props('incomplete')).toBe(true)
expect(wrapper.text()).toContain('目的仓国家待核实')
expect(wrapper.findComponent({ name: 'AppointmentCalendarPanel' }).props('notices').join(' ')).toContain('目的仓国家待核实')
expect(listPickupCalendar).toHaveBeenCalledTimes(1)
})
it('does not request pickup records without pickup list permission and discloses the omitted source', async () => {
routing.canPickup=false
const wrapper=render(); await flushPromises()
expect(listPickupCalendar).not.toHaveBeenCalled()
expect(wrapper.text()).toContain('无提柜查看权限')
expect(wrapper.findComponent({ name: 'AppointmentCalendarPanel' }).props('notices').join(' ')).toContain('无提柜查看权限')
expect(wrapper.findComponent({name:'AppointmentCalendarPanel'}).props('incomplete')).toBe(true)
})
it('keeps successful arrival data visible when the pickup source fails', async () => {
@@ -108,13 +108,16 @@ describe('appointment calendar data integration', () => {
routing.canTrips=false
const wrapper=render();await flushPromises()
expect(listTripCalendar).not.toHaveBeenCalled();expect(listArrivalCalendar).toHaveBeenCalledTimes(1)
expect(wrapper.text()).toContain('无车次查看权限')
expect(wrapper.findComponent({ name: 'AppointmentCalendarPanel' }).props('notices').join(' ')).toContain('无车次查看权限')
})
it('keeps unresolved trip origins outside daily slots and clearly labels their UTC source time', async () => {
vi.mocked(listTripCalendar).mockResolvedValueOnce({records:[],unresolvedRecords:[{sourceType:'TRIP_PLAN',tripNo:'TR-UNKNOWN',status:'PLANNED',originWarehouseId:null,originWarehouseCode:null,originWarehouseName:null,originCountryCode:null,originTimezone:null,originWarehouseStatus:null,plannedDepartureAt:'2026-10-10T12:00:00Z',expectedDriverEndAt:null,departedAt:null,completedAt:null,stops:[],incompleteReasons:['ORIGIN_WAREHOUSE_UNKNOWN']}]})
const wrapper=render();await flushPromises()
expect(wrapper.findComponent({name:'AppointmentCalendarPanel'}).props('events')).toEqual([])
expect(wrapper.text()).toContain('待核实地点的车次(1)');expect(wrapper.text()).toContain('原计划时间保留 UTC')
expect(wrapper.find('.appointment-extra').exists()).toBe(false)
expect(wrapper.text()).not.toContain('原计划时间保留 UTC')
await wrapper.findAll('button').find(button => button.text() === '查看待核实车次(1)')!.trigger('click')
expect(wrapper.text()).toContain('原计划时间保留 UTC')
expect(listTripCalendar).toHaveBeenCalledTimes(1)
})
it('creates one shared appointment for two customers without sending a fabricated header customer', async () => {