feat(consignment): 后台寄卖规格按分类模板动态渲染

This commit is contained in:
2026-11-08 11:50:51 +08:00
parent caa2358bbd
commit e03abc3a8a
5 changed files with 483 additions and 142 deletions
@@ -0,0 +1,90 @@
import type { ConsignmentSpecField, ConsignmentSpecValues } from '../types/consignment'
export type ConsignmentSpecDisplayItem = {
key: string
label: string
value: string
}
/** 旧版内置规格字段(没有动态规格配置的历史分类才会用到)。 */
export type ConsignmentLegacySpecRecord = {
system?: string
serverZone?: string
series?: string
diamondLevel?: number | null
brillianceCount?: number | null
}
/** 动态规格字段按模板顺序展示时的标签配色。 */
export const CONSIGNMENT_SPEC_TAG_COLORS = [
'geekblue',
'cyan',
'orange',
'gold',
'magenta',
'green',
]
/** 选项值统一按字符串匹配(配置里 value 是字符串,历史数据可能是数字)。 */
function formatSpecValue(field: ConsignmentSpecField, raw: unknown): string {
if (raw === undefined || raw === null) return ''
const text = String(raw).trim()
if (!text) return ''
if (field.type === 'select' || field.type === 'radio') {
const option = field.options?.find((item) => String(item.value) === text)
return option?.label || text
}
return text
}
/**
* 按寄卖分类模板把 specValues 转成可展示的 {label, value}。
*
* 顺序与后端 buildConsignmentSpecText 保持一致(sortOrder 升序,其次 key),
* 选项型字段把存储的选项值映射回选项名称(如 product=15 → 碎梦浮光珍宝礼盒)。
*/
export function resolveConsignmentSpecDisplayItems(
specs: ConsignmentSpecField[] | null | undefined,
values: ConsignmentSpecValues | null | undefined,
): ConsignmentSpecDisplayItem[] {
if (!specs || specs.length === 0) return []
return [...specs]
.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0) || a.key.localeCompare(b.key))
.map((field) => ({
key: field.key,
label: field.label,
value: formatSpecValue(field, values?.[field.key]),
}))
.filter((item) => item.value !== '')
}
/** 旧版内置字段拼成一行(历史分类 & 历史数据兜底)。 */
export function formatLegacyConsignmentSpec(record: ConsignmentLegacySpecRecord): string {
const parts = [
record.system,
record.serverZone,
record.series,
record.diamondLevel ? `${record.diamondLevel}钻` : '',
record.brillianceCount ? `${record.brillianceCount}璀璨` : '',
]
.map((part) => String(part ?? '').trim())
.filter(Boolean)
return parts.join(' / ')
}
/**
* 详情页规格文本:后端 specText 优先(已含选项名称),其次按模板现拼,最后回退旧字段。
*/
export function resolveConsignmentSpecText(
input: {
specText?: string
specs?: ConsignmentSpecField[] | null
specValues?: ConsignmentSpecValues | null
} & ConsignmentLegacySpecRecord,
): string {
const specText = String(input.specText ?? '').trim()
if (specText) return specText
const items = resolveConsignmentSpecDisplayItems(input.specs, input.specValues)
if (items.length > 0) return items.map((item) => `${item.label} ${item.value}`).join(' / ')
return formatLegacyConsignmentSpec(input) || '-'
}