统一寄卖仓库与提报审核规格展示
- 规格标签只显示值,0 璀璨不再显示「无」 - 仓库列表长规格文本改为纯值一行 - 列表物品名展示层清理历史 0 璀璨残留 - 补充规格展示回归测试
This commit is contained in:
@@ -67,8 +67,10 @@ import { buildConsignmentCategoryGroups } from '@/utils/consignment-category-tre
|
||||
import { describeGiftEvidence, resolveGiftEvidenceBadge } from '@/utils/consignment-evidence'
|
||||
import {
|
||||
CONSIGNMENT_SPEC_TAG_COLORS,
|
||||
resolveConsignmentSpecDisplayItems,
|
||||
resolveConsignmentDisplayItemName,
|
||||
resolveConsignmentSpecTagItems,
|
||||
resolveConsignmentSpecText,
|
||||
resolveConsignmentSpecValueText,
|
||||
} from '@/utils/consignment-spec-display'
|
||||
import { CONSIGNMENT_SYSTEM_OPTIONS, CONSIGNMENT_ZONE_OPTIONS } from '@/utils/consignment-spec'
|
||||
import { formatDateTime } from '@/utils/date-time'
|
||||
@@ -480,64 +482,69 @@ export default function ConsignmentInventoryPanel() {
|
||||
title: '物品/寄卖单号',
|
||||
key: 'item',
|
||||
width: 240,
|
||||
render: (_, record) => (
|
||||
<div>
|
||||
<div style={{ fontWeight: 600, fontSize: 14 }}>{record.itemName}</div>
|
||||
{record.specText ? (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{record.specText}
|
||||
</Text>
|
||||
) : null}
|
||||
<Space size={4} align="center">
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
寄卖单号
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 12, fontWeight: 600 }}>
|
||||
{resolveConsignmentNo(record)}
|
||||
</Text>
|
||||
</Space>
|
||||
{record.giftWorkOrderNo ? (
|
||||
render: (_, record) => {
|
||||
const specLine = resolveConsignmentSpecValueText(record, { omitZeroBrilliance: true })
|
||||
return (
|
||||
<div>
|
||||
<div style={{ fontWeight: 600, fontSize: 14 }}>
|
||||
{resolveConsignmentDisplayItemName(record)}
|
||||
</div>
|
||||
{specLine ? (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{specLine}
|
||||
</Text>
|
||||
) : null}
|
||||
<Space size={4} align="center">
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
寄卖单号
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 12, fontWeight: 600 }}>
|
||||
{resolveConsignmentNo(record)}
|
||||
</Text>
|
||||
</Space>
|
||||
{record.giftWorkOrderNo ? (
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<Space size={4} align="center" wrap>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
关联工单
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 12, fontWeight: 600, color: '#1677ff' }}>
|
||||
{record.giftWorkOrderNo}
|
||||
</Text>
|
||||
{record.giftWorkOrderStatus ? (
|
||||
<Tag
|
||||
color="cyan"
|
||||
style={{
|
||||
fontSize: 10,
|
||||
lineHeight: '16px',
|
||||
padding: '0 4px',
|
||||
marginInlineEnd: 0,
|
||||
}}
|
||||
>
|
||||
{formatGiftWorkOrderStatus(record.giftWorkOrderStatus)}
|
||||
</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
) : null}
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<Space size={4} align="center" wrap>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
关联工单
|
||||
</Text>
|
||||
<Text copyable style={{ fontSize: 12, fontWeight: 600, color: '#1677ff' }}>
|
||||
{record.giftWorkOrderNo}
|
||||
</Text>
|
||||
{record.giftWorkOrderStatus ? (
|
||||
<Tag
|
||||
color="cyan"
|
||||
style={{
|
||||
fontSize: 10,
|
||||
lineHeight: '16px',
|
||||
padding: '0 4px',
|
||||
marginInlineEnd: 0,
|
||||
}}
|
||||
>
|
||||
{formatGiftWorkOrderStatus(record.giftWorkOrderStatus)}
|
||||
</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
{record.sourceType === 'worker_portal' ? (
|
||||
<Tag color="purple" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
打手端提报
|
||||
</Tag>
|
||||
) : record.sourceType === 'recycle' ? (
|
||||
<Tag color="green" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
回收
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color="blue" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
人工入库
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<div style={{ marginTop: 2 }}>
|
||||
{record.sourceType === 'worker_portal' ? (
|
||||
<Tag color="purple" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
打手端提报
|
||||
</Tag>
|
||||
) : record.sourceType === 'recycle' ? (
|
||||
<Tag color="green" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
回收
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color="blue" style={{ fontSize: 11, padding: '0 4px' }}>
|
||||
人工入库
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '寄卖分类',
|
||||
@@ -562,7 +569,7 @@ export default function ConsignmentInventoryPanel() {
|
||||
width: 220,
|
||||
render: (_, record) => {
|
||||
// 规格按该分类已发布的寄卖模板渲染;没有规格配置的历史库存才回退旧字段。
|
||||
const specItems = resolveConsignmentSpecDisplayItems(record.specs, record.specValues)
|
||||
const specItems = resolveConsignmentSpecTagItems(record.specs, record.specValues)
|
||||
if (specItems.length > 0) {
|
||||
return (
|
||||
<Space size={4} wrap>
|
||||
@@ -570,8 +577,10 @@ export default function ConsignmentInventoryPanel() {
|
||||
<Tag
|
||||
key={item.key}
|
||||
color={CONSIGNMENT_SPEC_TAG_COLORS[index % CONSIGNMENT_SPEC_TAG_COLORS.length]}
|
||||
title={`${item.label}:${item.value}`}
|
||||
style={{ marginInlineEnd: 0, fontSize: 11, padding: '0 6px' }}
|
||||
>
|
||||
{item.label} {item.value}
|
||||
{item.value}
|
||||
</Tag>
|
||||
))}
|
||||
</Space>
|
||||
|
||||
@@ -46,7 +46,8 @@ import { formatConsignmentContactSupporter } from '@/utils/consignment-contact'
|
||||
import { describeGiftEvidence, resolveGiftEvidenceBadge } from '@/utils/consignment-evidence'
|
||||
import {
|
||||
CONSIGNMENT_SPEC_TAG_COLORS,
|
||||
resolveConsignmentSpecDisplayItems,
|
||||
resolveConsignmentDisplayItemName,
|
||||
resolveConsignmentSpecTagItems,
|
||||
resolveConsignmentSpecText,
|
||||
} from '@/utils/consignment-spec-display'
|
||||
import { CONSIGNMENT_SYSTEM_OPTIONS, CONSIGNMENT_ZONE_OPTIONS } from '@/utils/consignment-spec'
|
||||
@@ -245,18 +246,20 @@ export default function ConsignmentSubmissionsPanel() {
|
||||
width: 230,
|
||||
render: (_, record) => {
|
||||
// 规格按该分类已发布的寄卖模板渲染;没配置规格的历史提报才回退旧字段。
|
||||
const specItems = resolveConsignmentSpecDisplayItems(record.specs, record.specValues)
|
||||
const specItems = resolveConsignmentSpecTagItems(record.specs, record.specValues)
|
||||
return (
|
||||
<Space direction="vertical" size={2}>
|
||||
<div style={{ fontWeight: 600 }}>{record.itemName}</div>
|
||||
<div style={{ fontWeight: 600 }}>{resolveConsignmentDisplayItemName(record)}</div>
|
||||
<Space size={4} wrap>
|
||||
{specItems.length > 0 ? (
|
||||
specItems.map((item, index) => (
|
||||
<Tag
|
||||
key={item.key}
|
||||
color={CONSIGNMENT_SPEC_TAG_COLORS[index % CONSIGNMENT_SPEC_TAG_COLORS.length]}
|
||||
title={`${item.label}:${item.value}`}
|
||||
style={{ marginInlineEnd: 0, fontSize: 11, padding: '0 6px' }}
|
||||
>
|
||||
{item.label} {item.value}
|
||||
{item.value}
|
||||
</Tag>
|
||||
))
|
||||
) : (
|
||||
|
||||
@@ -72,6 +72,56 @@ export function formatLegacyConsignmentSpec(record: ConsignmentLegacySpecRecord)
|
||||
return parts.join(' / ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表用规格标签:只保留值,0 璀璨属于默认值,不占标签位。
|
||||
* 详情/审核弹窗需要字段名时仍用 resolveConsignmentSpecDisplayItems。
|
||||
*/
|
||||
export function resolveConsignmentSpecTagItems(
|
||||
specs: ConsignmentSpecField[] | null | undefined,
|
||||
values: ConsignmentSpecValues | null | undefined,
|
||||
): ConsignmentSpecDisplayItem[] {
|
||||
return resolveConsignmentSpecDisplayItems(specs, values).filter((item) => {
|
||||
if (item.key !== 'brillianceCount') return true
|
||||
if (item.value === '无') return false
|
||||
const raw = String(values?.[item.key] ?? '').trim()
|
||||
const numeric = Number(raw)
|
||||
return !(raw && Number.isFinite(numeric) && numeric <= 0)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表用纯值规格文本:不带字段名,方便和物品名并排扫读;0 璀璨省略。
|
||||
* 没有动态规格的历史数据回退旧 5 项(本身也是纯值)。
|
||||
*/
|
||||
export function resolveConsignmentSpecValueText(
|
||||
input: {
|
||||
specs?: ConsignmentSpecField[] | null
|
||||
specValues?: ConsignmentSpecValues | null
|
||||
} & ConsignmentLegacySpecRecord,
|
||||
options: { omitZeroBrilliance?: boolean } = {},
|
||||
): string {
|
||||
const items = options.omitZeroBrilliance
|
||||
? resolveConsignmentSpecTagItems(input.specs, input.specValues)
|
||||
: resolveConsignmentSpecDisplayItems(input.specs, input.specValues)
|
||||
if (items.length > 0) return items.map((item) => item.value).join(' / ')
|
||||
return formatLegacyConsignmentSpec(input)
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表展示用物品名:历史 0 璀璨数据会留下「N钻璀璨」这种断尾单位,
|
||||
* 只在展示层去掉,不改库;详情仍显示原始 item_name。
|
||||
* 只匹配「钻」后面紧跟的「璀璨」,避免误伤系列名里真实包含的「璀璨」。
|
||||
*/
|
||||
export function resolveConsignmentDisplayItemName(input: {
|
||||
itemName?: string | null
|
||||
brillianceCount?: number | null
|
||||
}): string {
|
||||
const name = String(input.itemName || '').trim()
|
||||
if (!name) return ''
|
||||
if (Number(input.brillianceCount || 0) > 0) return name
|
||||
return name.replace(/(\d+\s*钻)\s*(?:0\s*)?璀璨/g, '$1').trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情页规格文本:后端 specText 优先(已含选项名称),其次按模板现拼,最后回退旧字段。
|
||||
*/
|
||||
|
||||
@@ -14,8 +14,17 @@ test('提报审核:规格按寄卖模板渲染,有模板时不再写死旧
|
||||
const page = readPanel('ConsignmentSubmissionsPanel.tsx')
|
||||
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecDisplayItems(record.specs, record.specValues)'),
|
||||
'提报列表必须按模板字段渲染规格',
|
||||
page.includes('resolveConsignmentSpecTagItems(record.specs, record.specValues)'),
|
||||
'提报列表必须按模板字段渲染规格标签',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentDisplayItemName(record)'),
|
||||
'提报列表物品名必须清掉历史 0 璀璨残留',
|
||||
)
|
||||
assert.ok(!page.includes('{item.label} {item.value}'), '提报列表规格标签只显示值')
|
||||
assert.ok(
|
||||
page.includes('title={`${item.label}:${item.value}`}'),
|
||||
'提报列表规格标签悬浮显示字段名',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecText(viewingSubmission)'),
|
||||
@@ -40,8 +49,21 @@ test('寄售仓库:列表/详情按模板渲染,编辑不再写死旧字段'
|
||||
assert.ok(!page.includes("title: '和平精英规格'"), '仓库列表列名不得写死和平精英')
|
||||
assert.ok(page.includes("title: '寄卖规格'"), '仓库列表列名应为通用「寄卖规格」')
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecDisplayItems(record.specs, record.specValues)'),
|
||||
'仓库列表必须按模板字段渲染规格',
|
||||
page.includes('resolveConsignmentSpecTagItems(record.specs, record.specValues)'),
|
||||
'仓库列表必须按模板字段渲染规格标签',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecValueText(record, { omitZeroBrilliance: true })'),
|
||||
'仓库列表规格行必须只显示值并省略 0 璀璨',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentDisplayItemName(record)'),
|
||||
'仓库列表物品名必须清掉历史 0 璀璨残留',
|
||||
)
|
||||
assert.ok(!page.includes('{record.specText}'), '仓库列表不得再显示重复的长规格文本')
|
||||
assert.ok(
|
||||
page.includes('title={`${item.label}:${item.value}`}'),
|
||||
'仓库列表规格标签悬浮显示字段名',
|
||||
)
|
||||
assert.ok(
|
||||
page.includes('resolveConsignmentSpecText(viewingItem)'),
|
||||
|
||||
@@ -4,8 +4,11 @@ import test from 'node:test'
|
||||
import type { ConsignmentSpecField } from '../src/types/consignment.ts'
|
||||
import {
|
||||
formatLegacyConsignmentSpec,
|
||||
resolveConsignmentDisplayItemName,
|
||||
resolveConsignmentSpecDisplayItems,
|
||||
resolveConsignmentSpecTagItems,
|
||||
resolveConsignmentSpecText,
|
||||
resolveConsignmentSpecValueText,
|
||||
} from '../src/utils/consignment-spec-display.ts'
|
||||
|
||||
function makeSpec(
|
||||
@@ -110,3 +113,114 @@ test('规格文本:没有模板规格时回退旧列,0 璀璨不展示', ()
|
||||
assert.equal(formatLegacyConsignmentSpec({ diamondLevel: 1, brillianceCount: 0 }), '1钻')
|
||||
assert.equal(resolveConsignmentSpecText({}), '-')
|
||||
})
|
||||
|
||||
const diamondSpec = makeSpec({
|
||||
key: 'diamondLevel',
|
||||
label: '钻石等级',
|
||||
type: 'select',
|
||||
sortOrder: 2,
|
||||
options: [
|
||||
{ label: '3钻', value: '3', enabled: true },
|
||||
{ label: '4钻', value: '4', enabled: true },
|
||||
],
|
||||
})
|
||||
|
||||
const brillianceSpec = makeSpec({
|
||||
key: 'brillianceCount',
|
||||
label: '璀璨数',
|
||||
type: 'select',
|
||||
sortOrder: 3,
|
||||
options: [
|
||||
{ label: '无', value: '0', enabled: true },
|
||||
{ label: '1璀璨', value: '1', enabled: true },
|
||||
{ label: '2璀璨', value: '2', enabled: true },
|
||||
],
|
||||
})
|
||||
|
||||
test('列表规格标签:只保留值,0 璀璨不占标签位', () => {
|
||||
const zero = resolveConsignmentSpecTagItems([systemSpec, diamondSpec, brillianceSpec], {
|
||||
system: 'ios',
|
||||
diamondLevel: '4',
|
||||
brillianceCount: '0',
|
||||
})
|
||||
assert.deepEqual(
|
||||
zero.map((item) => item.value),
|
||||
['苹果', '4钻'],
|
||||
)
|
||||
|
||||
const withBrilliance = resolveConsignmentSpecTagItems([systemSpec, diamondSpec, brillianceSpec], {
|
||||
system: 'ios',
|
||||
diamondLevel: '4',
|
||||
brillianceCount: '2',
|
||||
})
|
||||
assert.deepEqual(
|
||||
withBrilliance.map((item) => item.value),
|
||||
['苹果', '4钻', '2璀璨'],
|
||||
)
|
||||
})
|
||||
|
||||
test('列表规格纯值文本:不含字段名,0 璀璨省略', () => {
|
||||
assert.equal(
|
||||
resolveConsignmentSpecValueText(
|
||||
{
|
||||
specs: [systemSpec, diamondSpec, brillianceSpec],
|
||||
specValues: { system: 'ios', diamondLevel: '4', brillianceCount: '0' },
|
||||
},
|
||||
{ omitZeroBrilliance: true },
|
||||
),
|
||||
'苹果 / 4钻',
|
||||
)
|
||||
assert.equal(
|
||||
resolveConsignmentSpecValueText(
|
||||
{
|
||||
specs: [systemSpec, diamondSpec, brillianceSpec],
|
||||
specValues: { system: 'ios', diamondLevel: '4', brillianceCount: '1' },
|
||||
},
|
||||
{ omitZeroBrilliance: true },
|
||||
),
|
||||
'苹果 / 4钻 / 1璀璨',
|
||||
)
|
||||
// 没有动态规格的历史提报/库存回退旧字段,本身就是纯值
|
||||
assert.equal(
|
||||
resolveConsignmentSpecValueText({
|
||||
system: '苹果',
|
||||
serverZone: '微信区',
|
||||
series: '暗潮',
|
||||
diamondLevel: 3,
|
||||
brillianceCount: 2,
|
||||
}),
|
||||
'苹果 / 微信区 / 暗潮 / 3钻 / 2璀璨',
|
||||
)
|
||||
})
|
||||
|
||||
test('列表物品名:0 璀璨的历史断尾单位只在展示层清掉', () => {
|
||||
assert.equal(
|
||||
resolveConsignmentDisplayItemName({
|
||||
itemName: '安卓暗潮2钻璀璨 苏尔南',
|
||||
brillianceCount: 0,
|
||||
}),
|
||||
'安卓暗潮2钻 苏尔南',
|
||||
)
|
||||
assert.equal(
|
||||
resolveConsignmentDisplayItemName({
|
||||
itemName: '安卓暗潮2钻0璀璨 苏尔南',
|
||||
brillianceCount: 0,
|
||||
}),
|
||||
'安卓暗潮2钻 苏尔南',
|
||||
)
|
||||
assert.equal(
|
||||
resolveConsignmentDisplayItemName({
|
||||
itemName: '苹果血宴1钻1璀璨 苏尔南',
|
||||
brillianceCount: 1,
|
||||
}),
|
||||
'苹果血宴1钻1璀璨 苏尔南',
|
||||
)
|
||||
// 系列名本身含「璀璨」时不能误删
|
||||
assert.equal(
|
||||
resolveConsignmentDisplayItemName({
|
||||
itemName: '璀璨系列2钻 苏尔南',
|
||||
brillianceCount: 0,
|
||||
}),
|
||||
'璀璨系列2钻 苏尔南',
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user