feat(worker-platform): 商品名按来源追加可配置后缀

- 新增来源后缀配置(来源下拉、启停、备注,同一时间仅启用一个)
- 管理端列表/详情与打手端列表/详情/大厅展示「商品名(后缀)」
- 打手端 DTO 透出 sourceProvider,仅展示,不改写商品名
- 新增来源选项接口与前后端单测
This commit is contained in:
2026-11-02 14:25:53 +08:00
parent 86b5347e40
commit 13869d345f
22 changed files with 1008 additions and 49 deletions
@@ -0,0 +1,69 @@
export type ProductNameSourceSuffixItem = {
/** 来源标识,如 91kaquan */
source: string
/** 括号内的后缀文字,如 91卡券 */
suffix: string
/** 未启用(false)的配置不参与展示;缺省按启用处理,兼容打手端精简数据 */
enabled?: boolean
}
/** 后缀只保留括号内的文字:填了外层全角/半角括号时自动剥离。 */
export function normalizeProductNameSuffixText(value: unknown): string {
let text = String(value ?? '').trim()
if (!text) return ''
const wrappedFullWidth = text.startsWith('(') && text.endsWith(')')
const wrappedHalfWidth = text.startsWith('(') && text.endsWith(')')
if ((wrappedFullWidth || wrappedHalfWidth) && text.length >= 2) {
text = text.slice(1, -1).trim()
}
return text
}
/**
* 按来源取后缀:来源精确匹配、不区分大小写,空来源或空后缀不命中。
* 同一来源配置多条时以第一条有效配置为准。
*/
export function resolveProductNameSourceSuffix(
items: ProductNameSourceSuffixItem[] | null | undefined,
provider: unknown,
): string {
const normalizedProvider = String(provider ?? '')
.trim()
.toLowerCase()
if (!normalizedProvider) return ''
for (const item of items ?? []) {
if (item?.enabled === false) continue
const source = String(item?.source ?? '')
.trim()
.toLowerCase()
if (!source || source !== normalizedProvider) continue
const suffix = normalizeProductNameSuffixText(item?.suffix)
if (suffix) return suffix
}
return ''
}
/**
* 在商品名后追加「(后缀)」;没有后缀时原样返回。
* 商品名已以相同后缀结尾(全角/半角括号均可)时不重复追加。
*/
export function appendProductNameSourceSuffix(productName: unknown, suffix: unknown): string {
const name = String(productName ?? '').trim()
const normalizedSuffix = normalizeProductNameSuffixText(suffix)
if (!name || !normalizedSuffix) return name
if (name.endsWith(`(${normalizedSuffix})`) || name.endsWith(`(${normalizedSuffix})`)) {
return name
}
return `${name}(${normalizedSuffix})`
}
/** 展示用:按来源匹配后一次性完成后缀追加;无匹配时返回原商品名。 */
export function applyProductNameSourceSuffix(
productName: unknown,
provider: unknown,
items: ProductNameSourceSuffixItem[] | null | undefined,
): string {
return appendProductNameSourceSuffix(productName, resolveProductNameSourceSuffix(items, provider))
}