update sku mapping

This commit is contained in:
2026-04-20 13:50:20 +08:00
parent dd80286e23
commit efc5cabfbb
2 changed files with 113 additions and 11 deletions
@@ -30,9 +30,10 @@ import { api } from '@/utils/request'
const mockMappings = {
items: [
{ id: 1, company_id: 3, platform_id: 1, store_id: null, origin_sku: '0032', origin_sku_id: 1, platform_outer_sku: 'AMZ-0032', platform_product_id: 'ITEM-001', enabled: true, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
{ id: 1, company_id: 3, platform_id: 1, store_id: null, origin_sku: '0032', origin_sku_id: 1, platform_outer_sku: 'AMZ-0032', platform_product_id: 'ITEM-001', enabled: true, bundled: true, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
{ id: 2, company_id: 3, platform_id: 1, store_id: null, origin_sku: '0033', origin_sku_id: 2, platform_outer_sku: 'AMZ-0033', platform_product_id: 'ITEM-002', enabled: true, bundled: false, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
],
total: 1,
total: 2,
page: 1,
per_page: 15,
}
@@ -148,4 +149,70 @@ describe('SkuMappingsPage', () => {
expect(buttonTexts.some((t) => t.includes('搜索'))).toBe(true)
expect(buttonTexts.some((t) => t.includes('重置'))).toBe(true)
})
it('P7: renders 组合商品 column with blue/default tags per bundled', async () => {
await mountPage()
const html = wrapper.html()
expect(html).toContain('组合商品')
const rows = wrapper.findAll('tbody tr')
const bundledRow = rows.find((r) => r.text().includes('AMZ-0032'))
const plainRow = rows.find((r) => r.text().includes('AMZ-0033'))
expect(bundledRow?.html()).toMatch(/ant-tag-blue[^>]*>\s*是/)
expect(plainRow?.html()).toMatch(/ant-tag[^>]*>\s*否/)
expect(plainRow?.html()).not.toMatch(/ant-tag-blue[^>]*>\s*否/)
})
it('P8: form contains bundled Switch defaulted to off on create', async () => {
await mountPage()
const newBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('新建连接'))
await newBtn?.trigger('click')
await flushPromises()
await nextTick()
const bodyHtml = document.body.innerHTML
expect(bodyHtml).toContain('组合商品')
const switches = document.body.querySelectorAll('.ant-switch')
const bundledSwitch = Array.from(switches).find((s) => {
const label = s.closest('.ant-form-item')?.querySelector('.ant-form-item-label')
return label?.textContent?.includes('组合商品')
})
expect(bundledSwitch).toBeTruthy()
expect(bundledSwitch?.classList.contains('ant-switch-checked')).toBe(false)
})
it('P9: origin_sku_id required validation triggers error on empty submit', async () => {
await mountPage()
const newBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('新建连接'))
await newBtn?.trigger('click')
await flushPromises()
await nextTick()
const okBtn = Array.from(document.body.querySelectorAll('.ant-modal-footer .ant-btn')).find(
(b) => {
const t = (b as HTMLElement).textContent ?? ''
return t.includes('确 定') || t.includes('确定') || t.includes('OK')
},
) as HTMLElement | undefined
okBtn?.click()
await flushPromises()
await nextTick()
await vi.waitFor(
() => {
expect(document.body.innerHTML).toContain('请选择内部 SKU')
},
{ timeout: 8000, interval: 100 },
)
}, 15000)
it('P10: filter area exposes bundled dropdown with 是/否 options', async () => {
await mountPage()
const formItemLabels = wrapper.findAll('.filter-form .ant-form-item-label label')
const bundledLabel = formItemLabels.find((l) => l.text().includes('组合商品'))
expect(bundledLabel).toBeTruthy()
})
})
+44 -9
View File
@@ -26,6 +26,7 @@ const columns = [
{ title: '内部 SKU', dataIndex: 'origin_sku', width: 140 },
{ title: '平台 SKU', dataIndex: 'platform_outer_sku', width: 160 },
{ title: '平台商品ID', dataIndex: 'platform_product_id', width: 160, ellipsis: true },
{ title: '组合商品', key: 'bundled', width: 100 },
{ title: '状态', key: 'enabled', width: 80 },
{ title: '更新时间', key: 'updated_at', width: 170 },
{ title: '操作', key: 'action', width: 200, fixed: 'right' as const },
@@ -49,6 +50,7 @@ const defaultForm = (): SkuMappingForm => ({
generation_strategy: 'prefix',
warehouse_id: undefined,
enabled: true,
bundled: false,
note: '',
})
@@ -57,7 +59,9 @@ const form = reactive<SkuMappingForm>(defaultForm())
const rules: Record<string, Rule[]> = {
company_id: [{ required: true, message: '请选择公司', trigger: 'change' }],
platform_id: [{ required: true, message: '请选择平台', trigger: 'change' }],
origin_sku: [{ required: true, message: '请输入内部 SKU', trigger: 'blur' }],
origin_sku_id: [
{ required: true, message: '请选择内部 SKU', trigger: 'change', type: 'number' },
],
platform_outer_sku: [{ required: true, message: '请输入或生成平台 SKU', trigger: 'blur' }],
}
@@ -175,6 +179,7 @@ function openEdit(record: SkuMappingForm & { id: number }) {
generation_strategy: record.generation_strategy || 'prefix',
warehouse_id: record.warehouse_id || undefined,
enabled: record.enabled ?? true,
bundled: record.bundled ?? false,
note: record.note || '',
})
nextTick(() => { skipCompanyWatch = false })
@@ -338,6 +343,18 @@ watch(
<a-select-option :value="false">禁用</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="组合商品">
<a-select
:value="(store.filters.bundled as any)"
@update:value="(v: any) => { store.filters.bundled = v }"
placeholder="全部"
allow-clear
style="width: 100px"
>
<a-select-option :value="true"></a-select-option>
<a-select-option :value="false"></a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" html-type="submit">
@@ -384,6 +401,11 @@ watch(
</template>
<span v-else class="text-gray-400">平台默认</span>
</template>
<template v-else-if="column.key === 'bundled'">
<a-tag :color="record.bundled ? 'blue' : 'default'">
{{ record.bundled ? '是' : '否' }}
</a-tag>
</template>
<template v-else-if="column.key === 'enabled'">
<a-tag :color="record.enabled ? 'green' : 'default'">
{{ record.enabled ? '启用' : '禁用' }}
@@ -488,7 +510,7 @@ watch(
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="内部 SKU" name="origin_sku">
<a-form-item label="内部 SKU" name="origin_sku_id">
<a-select
v-model:value="form.origin_sku_id"
:placeholder="!form.company_id ? '请先选择公司' : '搜索(最少3个字)或输入SKU'"
@@ -544,13 +566,26 @@ watch(
<a-textarea v-model:value="form.note" placeholder="可选备注" :rows="2" />
</a-form-item>
<a-form-item label="状态">
<a-switch
v-model:checked="form.enabled"
checked-children="启用"
un-checked-children="禁用"
/>
</a-form-item>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="状态">
<a-switch
v-model:checked="form.enabled"
checked-children="启用"
un-checked-children="禁用"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="组合商品" name="bundled">
<a-switch
v-model:checked="form.bundled"
checked-children=""
un-checked-children=""
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-modal>