From 4ccad3bc3c132cf583b6d9baa33dfd05844c302e Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 9 Sep 2026 12:15:24 +0800 Subject: [PATCH] fix(admin): consume booking link actions when cached pages reactivate --- .../pages/ContainersView.test.ts | 60 ++++++++++++++++--- .../pages/ContainersView.vue | 23 ++++--- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/modules/container-loading/pages/ContainersView.test.ts b/src/modules/container-loading/pages/ContainersView.test.ts index 1e2ba78c..c86ff490 100644 --- a/src/modules/container-loading/pages/ContainersView.test.ts +++ b/src/modules/container-loading/pages/ContainersView.test.ts @@ -1,6 +1,7 @@ import ElementPlus from 'element-plus' import { createPinia, setActivePinia } from 'pinia' import { createMemoryHistory, createRouter } from 'vue-router' +import { defineComponent } from 'vue' import { flushPromises, mount } from '@vue/test-utils' import { beforeEach, describe, expect, it, vi } from 'vitest' import { readFileSync } from 'node:fs' @@ -34,7 +35,7 @@ const drayage = { function createTestRouter() { return createRouter({ history: createMemoryHistory(), routes: [ - { path: '/', component: ContainersView }, + { path: '/', name: 'domestic-container-workbench', component: ContainersView }, { path: '/container-loading/domestic/:containerId/smart-loading', name: 'smart-loading-workbench', component: { template: '
' } }, { path: '/loading-plans', name: 'loading-plans', component: { template: '
' } }, { path: '/container-loading/domestic/:containerId', name: 'domestic-container-detail', component: { template: '
' } }, @@ -417,12 +418,57 @@ describe('ContainersView', () => { wrapper.unmount() }) - it('opens the existing released-booking workflow when entered from container detail', () => { - const source = readFileSync(resolve(process.cwd(), 'src/modules/container-loading/pages/ContainersView.vue'), 'utf8') - expect(source).toContain('route.query.linkContainerId') - expect(source).toContain("const target = await getContainer(linkContainerId, 'DOMESTIC')") - expect(source).toContain('await openLink(target)') - expect(source).toContain("void router.replace({ name: 'domestic-container-workbench' })") + it('consumes the booking-link action once when returning to a cached list and preserves other query state', async () => { + vi.mocked(getContainer).mockClear() + vi.mocked(listContainers).mockClear() + vi.mocked(listOceanBookingLinkCandidates).mockClear().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 }) + const router = createTestRouter() + await router.push('/'); await router.isReady() + const shell = defineComponent({ template: '' }) + const wrapper = mount(shell, { global: { plugins: [ElementPlus, router] } }) + await flushPromises() + const initial = wrapper.findComponent(ContainersView).vm.$.uid + await router.push('/container-loading/domestic/9001') + await flushPromises() + await router.push({ name: 'domestic-container-workbench', query: { linkContainerId: '9001', keyword: 'CB-1' }, hash: '#table' }) + await flushPromises() + expect(wrapper.findComponent(ContainersView).vm.$.uid).toBe(initial) + expect(getContainer).toHaveBeenCalledTimes(1) + expect(listOceanBookingLinkCandidates).toHaveBeenCalledTimes(1) + expect(listContainers).toHaveBeenCalledTimes(1) + expect(router.currentRoute.value.query).toEqual({ keyword: 'CB-1' }) + expect(router.currentRoute.value.hash).toBe('#table') + const dialog = wrapper.findAllComponents(AppDialog).find((item) => item.props('title') === '关联已放舱订舱')! + expect(dialog.props('modelValue')).toBe(true) + dialog.vm.$emit('update:modelValue', false) + await flushPromises() + await router.push('/container-loading/domestic/9001') + await router.push({ name: 'domestic-container-workbench' }) + await flushPromises() + expect(dialog.props('modelValue')).toBe(false) + expect(getContainer).toHaveBeenCalledTimes(1) + expect(listOceanBookingLinkCandidates).toHaveBeenCalledTimes(1) + wrapper.unmount() + }) + + it('ignores a stale linking response after leaving the list', async () => { + const target = await vi.mocked(getContainer).getMockImplementation()!('9001', 'DOMESTIC') + let finish!: (value: typeof target) => void + vi.mocked(getContainer).mockClear().mockImplementationOnce(() => new Promise((resolve) => { finish = resolve })) + vi.mocked(listOceanBookingLinkCandidates).mockClear() + const router = createTestRouter() + await router.push({ name: 'domestic-container-workbench', query: { linkContainerId: '9001' } }); await router.isReady() + const wrapper = mount(ContainersView, { global: { plugins: [ElementPlus, router] } }) + await flushPromises() + await router.replace({ query: { linkContainerId: '9001', keyword: 'updated' } }) + await flushPromises() + expect(getContainer).toHaveBeenCalledTimes(1) + await router.push('/container-loading/domestic/9001') + finish(target) + await flushPromises() + expect(listOceanBookingLinkCandidates).not.toHaveBeenCalled() + expect(router.currentRoute.value.name).toBe('domestic-container-detail') + wrapper.unmount() }) it('normalizes an optional booking-link container number', async () => { diff --git a/src/modules/container-loading/pages/ContainersView.vue b/src/modules/container-loading/pages/ContainersView.vue index c8fc56c1..ce8f98dc 100644 --- a/src/modules/container-loading/pages/ContainersView.vue +++ b/src/modules/container-loading/pages/ContainersView.vue @@ -1,5 +1,5 @@