diff --git a/frontend/src/pages/order-items/__tests__/index.spec.ts b/frontend/src/pages/order-items/__tests__/index.spec.ts index 0f8d9c9..60a4de1 100644 --- a/frontend/src/pages/order-items/__tests__/index.spec.ts +++ b/frontend/src/pages/order-items/__tests__/index.spec.ts @@ -20,6 +20,12 @@ Object.defineProperty(window, 'matchMedia', { }), }) +const mockRouterPush = vi.fn() +vi.mock('vue-router', () => ({ + useRoute: () => ({ query: {} }), + useRouter: () => ({ push: mockRouterPush }), +})) + vi.mock('@/utils/request', () => ({ api: { get: vi.fn(), @@ -100,7 +106,7 @@ const mockLookupCompanies = [ { id: 1, name: 'Company A', label: '公司A' }, { id: 2, name: 'Company B', label: '公司B' }, ] -const mockLookupPlatforms = [{ id: 1, developer_id: 1 }] +const mockLookupPlatforms = [{ id: 1, name: 'Tmall', label: 'Tmall', developer_id: 1 }] const mockLookupStores = [ { id: 1, company_id: 1, platform_id: 1, name: 'Store 1', label: '店铺1' }, { id: 2, company_id: 2, platform_id: 1, name: 'Store 2', label: '店铺2' }, @@ -251,7 +257,7 @@ describe('useOrderItemStore', () => { await store.loadLookups() expect(store.companyMap.get(1)).toBe('公司A') - expect(store.platformMap.get(1)).toBe('平台 #1') + expect(store.platformMap.get(1)).toBe('Tmall') expect(store.storeMap.get(1)).toBe('店铺1') }) @@ -267,6 +273,45 @@ describe('useOrderItemStore', () => { expect(store.companyMap.size).toBe(0) warnSpy.mockRestore() }) + + it('companyMap falls back to name when label is "null"', async () => { + const { api } = await import('@/utils/request') + vi.mocked(api.get) + .mockResolvedValueOnce([{ id: 1, name: 'RealName', label: 'null' }]) + .mockResolvedValueOnce(mockLookupPlatforms) + .mockResolvedValueOnce(mockLookupStores) + + const store = useOrderItemStore() + await store.loadLookups() + + expect(store.companyMap.get(1)).toBe('RealName') + }) + + it('platformMap falls back to name when label is missing', async () => { + const { api } = await import('@/utils/request') + vi.mocked(api.get) + .mockResolvedValueOnce(mockLookupCompanies) + .mockResolvedValueOnce([{ id: 1, name: 'JD', developer_id: 1 }]) + .mockResolvedValueOnce(mockLookupStores) + + const store = useOrderItemStore() + await store.loadLookups() + + expect(store.platformMap.get(1)).toBe('JD') + }) + + it('platformMap shows fallback when both label and name are empty', async () => { + const { api } = await import('@/utils/request') + vi.mocked(api.get) + .mockResolvedValueOnce(mockLookupCompanies) + .mockResolvedValueOnce([{ id: 3, name: '', developer_id: 1 }]) + .mockResolvedValueOnce(mockLookupStores) + + const store = useOrderItemStore() + await store.loadLookups() + + expect(store.platformMap.get(3)).toBe('平台 #3') + }) }) }) @@ -278,6 +323,7 @@ describe('OrderItemsPage', () => { beforeEach(() => { setActivePinia(createPinia()) vi.restoreAllMocks() + mockRouterPush.mockClear() document.body.innerHTML = '' }) @@ -515,4 +561,82 @@ describe('OrderItemsPage', () => { expect(errorSpy).toHaveBeenCalledWith('获取订单项详情失败') }) + + it('filter form has filter-form class', async () => { + await mountPage() + + const form = wrapper.find('form.filter-form') + expect(form.exists()).toBe(true) + }) + + it('renders platform name from lookup map (not hardcoded fallback)', async () => { + await mountPage() + + const html = wrapper.html() + expect(html).toContain('Tmall') + expect(html).not.toContain('平台 #1') + }) + + it('renders copy buttons before text in platform_order_id column', async () => { + await mountPage() + + // Find table cells containing our platform order IDs + const cells = wrapper.findAll('td') + const orderIdCell = cells.find((c) => c.text().includes('ORD-20260101-001')) + expect(orderIdCell).toBeDefined() + + // CopyOutlined stub should appear before the link text + const cellHtml = orderIdCell!.html() + const copyPos = cellHtml.indexOf('copy-icon-stub') + const linkPos = cellHtml.indexOf('ORD-20260101-001') + expect(copyPos).toBeLessThan(linkPos) + }) + + it('renders copy button for sub_order_id when value exists', async () => { + await mountPage() + + // mockOrderItems[0] has sub_order_id = 'SUB-001' + const cells = wrapper.findAll('td') + const subOrderCell = cells.find((c) => c.text().includes('SUB-001')) + expect(subOrderCell).toBeDefined() + expect(subOrderCell!.find('.copy-icon-stub').exists()).toBe(true) + }) + + it('does not render copy button for sub_order_id when value is null', async () => { + await mountPage() + + // mockOrderItems[1] has sub_order_id = null, should show '-' + const cells = wrapper.findAll('td') + // Find all cells that contain exactly '-' and are in sub_order_id column context + // The second row's sub_order_id cell should have '-' and no copy icon + const dashCells = cells.filter((c) => c.text().trim() === '-') + // At least one dash cell should have no copy-icon-stub + const noCopyDash = dashCells.some((c) => !c.find('.copy-icon-stub').exists()) + expect(noCopyDash).toBe(true) + }) + + it('renders copy button for platform_product_id column', async () => { + await mountPage() + + const cells = wrapper.findAll('td') + const prodIdCell = cells.find((c) => c.text().includes('PROD-001')) + expect(prodIdCell).toBeDefined() + expect(prodIdCell!.find('.copy-icon-stub').exists()).toBe(true) + }) + + it('handleGoToOrder includes auto_submit in router push', async () => { + await mountPage() + + const links = wrapper.findAll('a') + const orderLink = links.find((l) => l.text().includes('ORD-20260101-001')) + expect(orderLink).toBeDefined() + + await orderLink!.trigger('click') + await flushPromises() + + expect(mockRouterPush).toHaveBeenCalledWith({ + path: '/orders', + query: { platform_order_id: 'ORD-20260101-001', auto_submit: '1' }, + }) + }) }) diff --git a/frontend/src/pages/order-items/index.vue b/frontend/src/pages/order-items/index.vue index ec10411..68ca30c 100644 --- a/frontend/src/pages/order-items/index.vue +++ b/frontend/src/pages/order-items/index.vue @@ -96,17 +96,20 @@ function formatTime(time: string | null) { return time.replace('T', ' ').substring(0, 16) } -async function handleCopyOrderId(platformOrderId: string) { +async function handleCopy(text: string, label: string = 'ID') { try { - await navigator.clipboard.writeText(platformOrderId) - message.success('已复制平台订单ID') + await navigator.clipboard.writeText(text) + message.success(`已复制${label}`) } catch { message.error('复制失败') } } function handleGoToOrder(platformOrderId: string) { - router.push({ path: '/orders', query: { platform_order_id: platformOrderId } }) + router.push({ + path: '/orders', + query: { platform_order_id: platformOrderId, auto_submit: '1' }, + }) } async function handleViewDetail(record: { id: number }) { @@ -137,7 +140,7 @@ async function handleViewDetail(record: { id: number }) { - + @@ -207,22 +210,35 @@ async function handleViewDetail(record: { id: number }) { {{ store.storeMap.get(record.store_id) || record.store_id }}