feat(consignment): 后台寄卖规格按分类模板动态渲染
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import test from 'node:test'
|
||||
|
||||
function readPanel(name: string) {
|
||||
return readFileSync(
|
||||
fileURLToPath(new URL(`../src/pages/admin/panels/${name}`, import.meta.url)),
|
||||
'utf8',
|
||||
)
|
||||
}
|
||||
|
||||
test('提报审核:规格按寄卖模板渲染,有模板时不再写死旧字段', () => {
|
||||
const page = readPanel('ConsignmentSubmissionsPanel.tsx')
|
||||
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecDisplayItems(record.specs, record.specValues)'),
|
||||
'提报列表必须按模板字段渲染规格',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecText(viewingSubmission)'),
|
||||
'提报详情必须使用模板规格文本',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('{approveModalItem?.specs?.length ? null : ('),
|
||||
'有模板规格时审核弹窗必须隐藏系统/区服/系列/钻级/璀璨旧字段',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('const hasDynamicSpecs = Boolean(approveModalItem.specs?.length)'),
|
||||
'提交前必须判断该分类是否有模板规格',
|
||||
)
|
||||
assert.ok(page.includes('...(hasDynamicSpecs'), '有模板规格时不得再提交旧规格字段')
|
||||
assert.ok(page.includes('规格(按寄卖分类模板)'), '审核弹窗需要标明规格来自寄卖模板')
|
||||
assert.ok(page.includes('请填写「'), '动态必填字段必须在表单层校验')
|
||||
})
|
||||
|
||||
test('寄售仓库:列表/详情按模板渲染,编辑不再写死旧字段', () => {
|
||||
const page = readPanel('ConsignmentInventoryPanel.tsx')
|
||||
|
||||
assert.ok(!page.includes("title: '和平精英规格'"), '仓库列表列名不得写死和平精英')
|
||||
assert.ok(page.includes("title: '寄卖规格'"), '仓库列表列名应为通用「寄卖规格」')
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecDisplayItems(record.specs, record.specValues)'),
|
||||
'仓库列表必须按模板字段渲染规格',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecText(viewingItem)'),
|
||||
'仓库详情必须使用模板规格文本',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('{editingItem?.specs?.length ? null : ('),
|
||||
'有模板规格时编辑弹窗必须隐藏旧规格字段',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('const hasDynamicSpecs = Boolean(editingItem.specs?.length)'),
|
||||
'保存前必须判断该分类是否有模板规格',
|
||||
)
|
||||
assert.ok(page.includes('...(hasDynamicSpecs'), '有模板规格时不得再提交旧规格字段')
|
||||
assert.ok(page.includes('请填写「'), '动态必填字段必须在表单层校验')
|
||||
})
|
||||
@@ -0,0 +1,112 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import type { ConsignmentSpecField } from '../src/types/consignment.ts'
|
||||
import {
|
||||
formatLegacyConsignmentSpec,
|
||||
resolveConsignmentSpecDisplayItems,
|
||||
resolveConsignmentSpecText,
|
||||
} from '../src/utils/consignment-spec-display.ts'
|
||||
|
||||
function makeSpec(
|
||||
overrides: Partial<ConsignmentSpecField> & Pick<ConsignmentSpecField, 'key' | 'label'>,
|
||||
): ConsignmentSpecField {
|
||||
return {
|
||||
type: 'text',
|
||||
required: false,
|
||||
options: [],
|
||||
placeholder: '',
|
||||
helpText: '',
|
||||
matchMode: 'exact',
|
||||
wildcardValues: [],
|
||||
showInItemName: false,
|
||||
sortOrder: 0,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
const productSpec = makeSpec({
|
||||
key: 'product',
|
||||
label: '商品',
|
||||
type: 'select',
|
||||
required: true,
|
||||
sortOrder: 10,
|
||||
options: [
|
||||
{ label: '碎梦浮光珍宝礼盒', value: '15', enabled: true },
|
||||
{ label: '指挥官密钥', value: '9', enabled: true },
|
||||
],
|
||||
})
|
||||
|
||||
const systemSpec = makeSpec({
|
||||
key: 'system',
|
||||
label: '系统',
|
||||
type: 'select',
|
||||
sortOrder: 1,
|
||||
options: [
|
||||
{ label: '苹果', value: 'ios', enabled: true },
|
||||
{ label: '安卓', value: 'android', enabled: true },
|
||||
],
|
||||
})
|
||||
|
||||
const levelSpec = makeSpec({
|
||||
key: 'diamondLevel',
|
||||
label: '钻石等级',
|
||||
type: 'number',
|
||||
sortOrder: 2,
|
||||
})
|
||||
|
||||
test('动态规格:选项值映射成选项名称(密钥分类 product=15)', () => {
|
||||
const items = resolveConsignmentSpecDisplayItems([productSpec], { product: '15' })
|
||||
assert.deepEqual(items, [{ key: 'product', label: '商品', value: '碎梦浮光珍宝礼盒' }])
|
||||
})
|
||||
|
||||
test('动态规格:按模板 sortOrder 排序,空值不展示', () => {
|
||||
const items = resolveConsignmentSpecDisplayItems([productSpec, levelSpec, systemSpec], {
|
||||
product: '15',
|
||||
system: 'ios',
|
||||
diamondLevel: '',
|
||||
})
|
||||
assert.deepEqual(
|
||||
items.map((item) => item.key),
|
||||
['system', 'product'],
|
||||
)
|
||||
assert.equal(items[0]?.value, '苹果')
|
||||
})
|
||||
|
||||
test('动态规格:没有模板字段时返回空数组', () => {
|
||||
assert.deepEqual(resolveConsignmentSpecDisplayItems([], { product: '15' }), [])
|
||||
assert.deepEqual(resolveConsignmentSpecDisplayItems(undefined, undefined), [])
|
||||
})
|
||||
|
||||
test('规格文本:后端 specText 优先', () => {
|
||||
assert.equal(
|
||||
resolveConsignmentSpecText({
|
||||
specText: '商品 碎梦浮光珍宝礼盒',
|
||||
specs: [productSpec],
|
||||
specValues: { product: '9' },
|
||||
}),
|
||||
'商品 碎梦浮光珍宝礼盒',
|
||||
)
|
||||
})
|
||||
|
||||
test('规格文本:无 specText 时按模板现拼', () => {
|
||||
assert.equal(
|
||||
resolveConsignmentSpecText({ specs: [productSpec], specValues: { product: '15' } }),
|
||||
'商品 碎梦浮光珍宝礼盒',
|
||||
)
|
||||
})
|
||||
|
||||
test('规格文本:没有模板规格时回退旧列,0 璀璨不展示', () => {
|
||||
assert.equal(
|
||||
resolveConsignmentSpecText({
|
||||
system: '苹果',
|
||||
serverZone: '微信区',
|
||||
series: '暗潮',
|
||||
diamondLevel: 3,
|
||||
brillianceCount: 2,
|
||||
}),
|
||||
'苹果 / 微信区 / 暗潮 / 3钻 / 2璀璨',
|
||||
)
|
||||
assert.equal(formatLegacyConsignmentSpec({ diamondLevel: 1, brillianceCount: 0 }), '1钻')
|
||||
assert.equal(resolveConsignmentSpecText({}), '-')
|
||||
})
|
||||
Reference in New Issue
Block a user