import { expect, test } from '@playwright/test'; const task = { id: 11, executionMode: 'live', status: 'order_created', sybProductId: 21, shopeeProductId: 31, pddProductId: 41, deviceId: 5, deviceName: 'Samsung 测试机', shopeeItemIdSnapshot: '26154802794', shopeeTitleSnapshot: '大码纯棉短袖', shopeeShopNameSnapshot: '大碼臻選', pddGoodsIdSnapshot: '731370706977', pddTitleSnapshot: '宽松纯棉短袖女装', targetColorSnapshot: '黑色', targetSizeSnapshot: 'XL', mappedColorSnapshot: '黑色款', mappedSizeSnapshot: 'XL(建议 60-70kg)', specSource: 'manual', quantity: 2, referenceUnitPriceCent: 2000, minUnitPriceCent: 400, maxUnitPriceCent: 3000, currency: 'CNY', pddAccountRefSnapshot: '', addressSuffix: '_cg11', pddOrderNo: 'PDD20260820001', orderSubmittedAt: '2026-08-20T08:30:00Z', paymentReviewStatus: 'pending', logisticsStatus: 'pending', writebackStatus: 'not_selected', statusChangedAt: '2026-08-20T08:30:00Z', createdAt: '2026-08-20T08:00:00Z', }; async function mockAdmin(page: any, status = 'order_created') { let current = { ...task, status }; let paymentPayload: any; let listQuery: URLSearchParams | undefined; await page.context().addCookies([{ name: 'Admin-Token', value: 'prototype-test-token', domain: 'localhost', path: '/' }]); await page.route('**/api/**', async route => { const url = new URL(route.request().url()); if (url.pathname.startsWith('/src/api/')) return route.continue(); if (url.pathname.endsWith('/api/v1/getinfo')) return route.fulfill({ json: { code: 200, data: { roles: ['admin'], name: '管理员', avatar: '', introduction: '', permissions: [] } } }); if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/11/payment-review')) { paymentPayload = route.request().postDataJSON(); current = { ...current, paymentReviewStatus: paymentPayload.status, paymentReviewedAt: '2026-08-20T09:00:00Z' }; return route.fulfill({ json: { code: 200, data: current } }); } if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/11/resolve-unknown')) { const payload = route.request().postDataJSON(); current = { ...current, status: payload.status, pddOrderNo: payload.pddOrderNo, orderSubmittedAt: payload.orderSubmittedAt }; return route.fulfill({ json: { code: 200, data: current } }); } if (url.pathname.endsWith('/api/admin/v1/purchase-tasks/11')) return route.fulfill({ json: { code: 200, data: { task: current, attempts: [{ attemptId: 'a-1', attemptNumber: 1, phase: 'order', status: 'completed', resultType: 'order_created', createdAt: task.createdAt }] } } }); if (url.pathname.endsWith('/api/admin/v1/purchase-tasks')) { listQuery = url.searchParams; return route.fulfill({ json: { code: 200, data: { items: [current], total: 1, page: 1, pageSize: 20 } } }); } return route.fulfill({ json: { code: 200, data: [] } }); }); return { paymentPayload: () => paymentPayload, listQuery: () => listQuery }; } test('采购管理只管理已有任务,并可复核支付状态', async ({ page }) => { const state = await mockAdmin(page); await page.goto('http://localhost:9527/#/purchase-tasks/index'); await expect(page.locator('.page-heading')).toHaveCount(0); await expect(page.getByLabel('模式')).toHaveCount(0); await expect.poll(() => state.listQuery()?.get('executionMode')).toBe('live'); const filterBoxes = await Promise.all(['.task-input', '.syb-input', '.order-input'].map(selector => page.locator(selector).boundingBox())); expect(filterBoxes.map(box => Math.round(box?.width || 0))).toEqual([72, 100, 120]); const actionBoxes = await Promise.all(['查询', '重置'].map(name => page.getByRole('button', { name, exact: true }).boundingBox())); expect(new Set([...filterBoxes, ...actionBoxes].map(box => Math.round(box?.y || 0))).size).toBe(1); expect([...filterBoxes, ...actionBoxes].map(box => box?.x || 0)).toEqual([...filterBoxes, ...actionBoxes].map(box => box?.x || 0).sort((a, b) => a - b)); await expect(page.getByText('CG-11')).toBeVisible(); await expect(page.getByText('大码纯棉短袖')).toBeVisible(); await expect(page.getByRole('button', { name: /创建采购任务|支付/ })).toHaveCount(0); await page.getByRole('button', { name: '详情' }).click(); await expect(page.getByText('采购任务详情')).toBeVisible(); await expect(page.getByText('_cg11')).toBeVisible(); await expect(page.getByText('仅人工记录,系统不支付')).toBeVisible(); await page.getByRole('button', { name: '标记已支付' }).click(); await expect(page.getByText('确认支付复核')).toBeVisible(); await page.getByRole('button', { name: '确认已支付' }).click(); await expect.poll(() => state.paymentPayload()?.status).toBe('paid'); await expect(page.getByText('已支付', { exact: true }).first()).toBeVisible(); }); test('订单结果未知时明确禁止重复采购并可人工解除', async ({ page }) => { await mockAdmin(page, 'order_result_unknown'); await page.goto('http://localhost:9527/#/purchase-tasks/index'); await page.getByRole('button', { name: '详情' }).click(); await expect(page.getByText('订单结果未知,禁止重复采购')).toBeVisible(); await expect(page.getByRole('button', { name: '允许重新采购' })).toHaveCount(0); await page.getByRole('button', { name: '处理未知结果' }).click(); const dialog = page.getByRole('dialog', { name: '处理订单结果未知' }); await dialog.getByLabel('PDD 订单号').fill('PDD-CHECKED-001'); await dialog.getByLabel('下单时间').fill('2026-08-20 18:00:00'); await dialog.getByLabel('下单时间').press('Tab'); await dialog.getByRole('button', { name: '确认处理结果' }).click(); await expect(page.getByText('订单已创建', { exact: true }).first()).toBeVisible(); });