From 6ab2f62f398d085adeaac51bd1624ecf8ceecf68 Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Tue, 1 Sep 2026 11:23:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E5=86=85=E8=81=94=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E5=95=86=E5=93=81=E8=AF=A6=E6=83=85=E6=8A=BD=E5=B1=89?= =?UTF-8?q?=20(#186)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pdd-products/PddProductDetailDrawer.vue | 170 ++++++ web/src/views/goauto/pdd-products/index.vue | 295 +--------- .../ShopeeProductDetailDrawer.vue | 179 ++++++ .../views/goauto/shopee-products/index.vue | 533 +----------------- web/src/views/goauto/syb-products/index.vue | 20 +- web/tests/e2e/shopee-pdd-picker.spec.ts | 37 ++ web/tests/e2e/syb-product-layout.spec.ts | 21 +- 7 files changed, 469 insertions(+), 786 deletions(-) create mode 100644 web/src/views/goauto/pdd-products/PddProductDetailDrawer.vue create mode 100644 web/src/views/goauto/shopee-products/ShopeeProductDetailDrawer.vue diff --git a/web/src/views/goauto/pdd-products/PddProductDetailDrawer.vue b/web/src/views/goauto/pdd-products/PddProductDetailDrawer.vue new file mode 100644 index 0000000..d7316b3 --- /dev/null +++ b/web/src/views/goauto/pdd-products/PddProductDetailDrawer.vue @@ -0,0 +1,170 @@ + + + + + diff --git a/web/src/views/goauto/pdd-products/index.vue b/web/src/views/goauto/pdd-products/index.vue index 8c0e25f..1dd3b34 100644 --- a/web/src/views/goauto/pdd-products/index.vue +++ b/web/src/views/goauto/pdd-products/index.vue @@ -1,284 +1,47 @@ - diff --git a/web/src/views/goauto/shopee-products/ShopeeProductDetailDrawer.vue b/web/src/views/goauto/shopee-products/ShopeeProductDetailDrawer.vue new file mode 100644 index 0000000..e96ec4a --- /dev/null +++ b/web/src/views/goauto/shopee-products/ShopeeProductDetailDrawer.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/web/src/views/goauto/shopee-products/index.vue b/web/src/views/goauto/shopee-products/index.vue index 2b0331f..e30bdfc 100644 --- a/web/src/views/goauto/shopee-products/index.vue +++ b/web/src/views/goauto/shopee-products/index.vue @@ -1,522 +1,49 @@ - diff --git a/web/src/views/goauto/syb-products/index.vue b/web/src/views/goauto/syb-products/index.vue index 9c7daee..e994386 100644 --- a/web/src/views/goauto/syb-products/index.vue +++ b/web/src/views/goauto/syb-products/index.vue @@ -138,6 +138,9 @@ + + + @@ -152,9 +155,12 @@ import { createPurchaseTasksBatch, previewPurchaseTasks } from '@/api/goauto/pur import { batchCreateCollectionTasks } from '@/api/goauto/collection-tasks' import { listCollectionRules } from '@/api/goauto/collection-rules' import { createRequestId } from '@/utils/request-id' +import ShopeeProductDetailDrawer from '../shopee-products/ShopeeProductDetailDrawer.vue' +import PddProductDetailDrawer from '../pdd-products/PddProductDetailDrawer.vue' export default { name: 'GoAutoSybProducts', + components: { ShopeeProductDetailDrawer, PddProductDetailDrawer }, setup() { return { Search, RefreshLeft } }, data() { return { @@ -169,7 +175,9 @@ export default { collectionBatchRules: { ruleId: [{ required: true, message: '请选择采集规则', trigger: 'change' }] }, query: { page: 1, pageSize: 20, shopName: '', orderCodesText: '', parseStatus: '', processStage: '' }, detail: { open: false, loading: false, item: null }, - correct: { open: false, saving: false, productId: null, targetColor: '', targetSize: '' } + correct: { open: false, saving: false, productId: null, targetColor: '', targetSize: '' }, + shopeeDetail: { open: false, productId: null, targetColor: '', action: '' }, + pddDetail: { open: false, productId: null } } }, computed: { @@ -272,16 +280,12 @@ export default { parseMeta(status) { return { success: { label: '成功', type: 'success' }, uncertain: { label: '存疑', type: 'warning' }, failed: { label: '失败', type: 'danger' }}[status] || { label: status || '-', type: 'info' } }, openShopeeDetail(shopeeProductId, targetColor = '', action = '') { if (!shopeeProductId) { ElMessage.warning('该明细尚未关联虾皮商品'); return } - const query = { productId: shopeeProductId } - if (targetColor) query.targetColor = targetColor - if (action) query.action = action - const route = this.$router.resolve({ path: '/shopee-products/index', query }) - window.open(route.href, '_blank', 'noopener') + this.shopeeDetail = { open: true, productId: Number(shopeeProductId), targetColor: String(targetColor || '').trim(), action: String(action || '') } }, + onShopeeSwitchCancelled(productId) { this.shopeeDetail.productId = Number(productId) }, openPddDetail(pddProductId) { if (!pddProductId) { ElMessage.warning('该明细尚未关联 PDD 商品'); return } - const route = this.$router.resolve({ path: '/pdd-products/index', query: { productId: pddProductId }}) - window.open(route.href, '_blank', 'noopener') + this.pddDetail = { open: true, productId: Number(pddProductId) } }, openPurchaseTask(taskId) { this.$router.push({ path: '/purchase-tasks/index', query: { taskId }}) }, runPurchaseNextAction(row, readiness) { diff --git a/web/tests/e2e/shopee-pdd-picker.spec.ts b/web/tests/e2e/shopee-pdd-picker.spec.ts index 3bcf96f..bfdc4b3 100644 --- a/web/tests/e2e/shopee-pdd-picker.spec.ts +++ b/web/tests/e2e/shopee-pdd-picker.spec.ts @@ -50,3 +50,40 @@ test('PDD 选择器默认最近五条并支持搜索与清空回退', async({ pa expect(listURLs.at(-1)?.searchParams.get('pageSize')).toBe('5') expect(listURLs.at(-1)?.searchParams.get('status')).toBe('active') }) + +test('虾皮详情原地叠加 PDD 抽屉且低置信度 AI 建议不预填', async({ page, context }) => { + await 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: ['purchaser'], name: '采购员', avatar: '', introduction: '', permissions: [] }}}) + if (url.pathname.endsWith('/api/v1/menurole')) return route.fulfill({ json: { code: 200, data: routes }}) + if (url.pathname.endsWith('/api/admin/v1/shopee-products')) return route.fulfill({ json: { code: 200, data: { items: [{ id: 9, shopeeItemId: 'S9', title: '叠加抽屉商品', shopName: '测试店', pddProductId: 17, specs: [{ name: '颜色', role: 'color', values: [{ name: '藏青色', source: 'syb', mapping: null }] }] }], total: 1, page: 1, pageSize: 20 }}}) + if (url.pathname.endsWith('/api/admin/v1/shopee-products/9/specs/mapping/suggest-colors')) { + return route.fulfill({ json: { code: 200, data: { items: [{ valueName: '藏青色', pddValue: '黑色', status: 'ai_suggested', apply: false, confidence: 0.45, reason: '置信度不足,请人工选择' }], matchedCount: 0, pendingCount: 1 }}}) + } + if (url.pathname.endsWith('/api/admin/v1/shopee-products/9')) { + return route.fulfill({ json: { code: 200, data: { product: { id: 9, shopeeItemId: 'S9', title: '叠加抽屉商品', shopName: '测试店', pddProductId: 17, specContextVersion: 3, specs: [{ name: '颜色', role: 'color', values: [{ name: '藏青色', source: 'syb', mapping: null }] }] }}}}) + } + if (url.pathname.endsWith('/api/admin/v1/pdd-products/17/related-syb-products')) return route.fulfill({ json: { code: 200, data: { items: [], total: 0 }}}) + if (url.pathname.endsWith('/api/admin/v1/pdd-products/17')) return route.fulfill({ json: { code: 200, data: { product: { id: 17, goodsId: 'P17', title: 'PDD 叠加详情', shopName: 'PDD 店', status: 'active', url: 'https://mobile.yangkeduo.com/goods.html?goods_id=17', specs: [{ name: '颜色分类', role: 'color', values: [{ name: '黑色', selectable: true, priceCent: 1299 }] }], colorImages: [] }, relatedShopeeProducts: [] }}}) + return route.fulfill({ json: { code: 200, data: [] }}) + }) + + await page.goto('/#/shopee-products') + let popupCount = 0 + page.on('popup', () => { popupCount += 1 }) + await page.getByRole('button', { name: '详情', exact: true }).click() + await expect(page.getByText('虾皮商品详情', { exact: true })).toBeVisible() + await page.getByRole('button', { name: 'AI 匹配', exact: true }).click() + await expect(page.getByText('置信度不足,请人工选择', { exact: true })).toBeVisible() + await expect(page.locator('.el-drawer:visible .mapping-select input').first()).toHaveValue('') + await page.getByLabel('虾皮商品详情').getByText('PDD-17 ↗', { exact: true }).click() + await expect(page.locator('.el-drawer:visible').getByText('PDD 商品详情', { exact: true })).toBeVisible() + await expect(page.getByText('PDD 叠加详情', { exact: true })).toBeVisible() + await page.keyboard.press('Escape') + await expect(page.getByText('PDD 叠加详情', { exact: true })).toBeHidden() + await expect(page.getByText('虾皮商品详情', { exact: true })).toBeVisible() + await expect(page.getByText('置信度不足,请人工选择', { exact: true })).toBeVisible() + expect(popupCount).toBe(0) +}) diff --git a/web/tests/e2e/syb-product-layout.spec.ts b/web/tests/e2e/syb-product-layout.spec.ts index 9f2f2d1..4b8cc9f 100644 --- a/web/tests/e2e/syb-product-layout.spec.ts +++ b/web/tests/e2e/syb-product-layout.spec.ts @@ -101,7 +101,7 @@ test('店铺选项加载失败时仍可输入历史店铺查询', async({ page, expect(listURLs.at(-1)?.searchParams.get('shopName')).toBe('已删除店铺') }) -test('PDD 待采集的下一步打开对应 PDD 商品而不是蝦皮商品', async({ page, context }) => { +test('PDD 待采集的下一步在 SYB 列表上方打开对应 PDD 商品抽屉', async({ page, context }) => { await 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()) @@ -114,11 +114,12 @@ test('PDD 待采集的下一步打开对应 PDD 商品而不是蝦皮商品', as }) await page.goto('/#/syb-products') - const popupPromise = page.waitForEvent('popup') + let popupCount = 0 + page.on('popup', () => { popupCount += 1 }) await page.getByRole('button', { name: '查看 PDD 商品' }).click() - const popup = await popupPromise - await expect.poll(() => popup.url()).toContain('/#/pdd-products/index?productId=17') - expect(popup.url()).not.toContain('/shopee-products/index') + await expect(page.getByText('PDD 商品详情', { exact: true }).last()).toBeVisible() + await expect(page.getByText('SYB-PDD-31', { exact: true })).toBeVisible() + expect(popupCount).toBe(0) }) test('未关联 PDD 显示去关联并直接打开 PDD 商品选择器', async({ page, context }) => { @@ -140,11 +141,13 @@ test('未关联 PDD 显示去关联并直接打开 PDD 商品选择器', async({ await expect(page.getByRole('button', { name: '去关联', exact: true })).toBeVisible() await expect(page.getByRole('button', { name: '去匹配', exact: true })).toBeVisible() - const popupPromise = page.waitForEvent('popup') + let popupCount = 0 + page.on('popup', () => { popupCount += 1 }) await page.getByRole('button', { name: '去关联', exact: true }).click() - const popup = await popupPromise - await expect.poll(() => popup.url()).toContain('/#/shopee-products/index?productId=9&action=link_pdd') - await expect(popup.getByText('搜索并选择 PDD 商品', { exact: true })).toBeVisible() + await expect(page.getByText('虾皮商品详情', { exact: true })).toBeVisible() + await expect(page.getByText('搜索并选择 PDD 商品', { exact: true })).toBeVisible() + await expect(page.getByText('SYB-LINK-41', { exact: true })).toBeVisible() + expect(popupCount).toBe(0) }) test('SYB 商品页不读取或展示后台同步状态', async({ page, context }) => {