fix(admin): 任务列表商品名与执行器标签改为中文展示

建单时不再把英文 sku 写入商品名,列表按映射反查中文名,并将 Affiliate Dash 等标签本地化。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yml2213
2026-09-15 13:03:47 +08:00
co-authored by Cursor
parent 68f43bf323
commit b7d246e5b9
10 changed files with 92 additions and 9 deletions
@@ -33,6 +33,11 @@ import {
canMarkManualReviewTaskStatus,
canRetryTaskStatus,
} from '../../domain/task-status.js'
import { getAffiliateDashConfig } from '../platforms/affiliate-dash/config.js'
import {
mergeAffiliateDashSkuMapping,
resolveAffiliateDashDisplayProductName,
} from '../platforms/affiliate-dash/sku-mapping.js'
import {
canViewerCloseTask,
canRegenerateClaimLinkForViewer,
@@ -361,7 +366,11 @@ export async function getAdminTaskDetail(
? {
orderItemId: orderItem.id,
skuCode: orderItem.sku_code,
skuName: orderItem.sku_name,
skuName: resolveAffiliateDashDisplayProductName(
String(orderItem.sku_code || ''),
String(orderItem.sku_name || ''),
mergeAffiliateDashSkuMapping(getAffiliateDashConfig().skuMapping),
),
quantity: orderItem.quantity,
}
: null,
@@ -7,6 +7,11 @@ import {
isTaskFulfillmentCompletedStatus,
normalizeTaskStatus,
} from '../../domain/task-status.js'
import { getAffiliateDashConfig } from '../platforms/affiliate-dash/config.js'
import {
mergeAffiliateDashSkuMapping,
resolveAffiliateDashDisplayProductName,
} from '../platforms/affiliate-dash/sku-mapping.js'
import {
createAdminViewerContext,
getTaskPrimaryClaimTokenId,
@@ -81,13 +86,16 @@ export function mapAdminTaskListItem(
viewerContext: AdminViewerContext = createAdminViewerContext(),
): AdminTaskListItem {
const fulfillment = buildTaskFulfillmentState(task)
const skuCode = String(task.sku_code || '').trim()
const rawSkuName = String(task.sku_name || '').trim()
const skuMapping = mergeAffiliateDashSkuMapping(getAffiliateDashConfig().skuMapping)
return {
taskId: task.id,
taskNo: task.task_no,
platformOrderId: task.platform_order_id,
skuCode: task.sku_code || '',
skuName: task.sku_name || '',
skuCode,
skuName: resolveAffiliateDashDisplayProductName(skuCode, rawSkuName, skuMapping),
status: task.task_status,
executorKey: task.executor_key || '',
deliveryStatus: task.delivery_status || '',
@@ -9,6 +9,8 @@ import {
import {
AFFILIATE_DASH_SKU_MAPPING,
mergeAffiliateDashSkuMapping,
resolveAffiliateDashDisplayProductName,
reverseAffiliateDashSkuToProductNo,
} from '../platforms/affiliate-dash/sku-mapping.js'
test('权威表覆盖核心中文商品', () => {
@@ -76,3 +78,21 @@ test('matchAffiliateDashSkuPassthrough 不在商品列表时未命中', () => {
test('matchAffiliateDashSkuPassthrough 空集合未命中', () => {
assert.equal(matchAffiliateDashSkuPassthrough('suit_alan_walker', new Set()), false)
})
test('resolveAffiliateDashDisplayProductName 英文 sku 反查中文', () => {
assert.equal(
resolveAffiliateDashDisplayProductName('suit_romantic_destiny', 'suit_romantic_destiny'),
'套装-浪漫天命',
)
assert.equal(resolveAffiliateDashDisplayProductName('bag_cute_bear', ''), '萌熊伴侣背包')
assert.equal(
resolveAffiliateDashDisplayProductName('suit_romantic_destiny', '套装-浪漫天命'),
'套装-浪漫天命',
)
assert.equal(resolveAffiliateDashDisplayProductName('', '幸运币2个'), '幸运币2个')
})
test('reverseAffiliateDashSkuToProductNo 未命中返回空串', () => {
assert.equal(reverseAffiliateDashSkuToProductNo('not_a_real_sku'), '')
assert.equal(reverseAffiliateDashSkuToProductNo(''), '')
})
@@ -84,8 +84,11 @@ export async function resolveOrderItemForFulfillment({
externalSkuCode,
externalItemId,
])
// 运营侧展示用中文商品名;英文 sku 只写在 skuCode。
const resolvedSkuName = pickFirstNonEmpty([
selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH ? affiliateDashMatch?.sku : '',
selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH
? affiliateDashMatch?.productNo || affiliateDashMatch?.skuName
: '',
item.skuName,
externalSkuName,
resolvedSkuCode,
@@ -60,3 +60,42 @@ export function mergeAffiliateDashSkuMapping(
}
return merged
}
/**
* 英文 sku → 91 中文商品名(运营后台列表展示用)。
* 同一 sku 若被多个中文名映射,取表中先出现的键。
*/
export function reverseAffiliateDashSkuToProductNo(
sku: string,
mapping: Readonly<Record<string, string>> = AFFILIATE_DASH_SKU_MAPPING,
): string {
const target = String(sku || '').trim()
if (!target) {
return ''
}
for (const [productNo, mappedSku] of Object.entries(mapping)) {
if (String(mappedSku || '').trim() === target) {
return String(productNo || '').trim()
}
}
return ''
}
/** 优先用中文商品名展示;已是中文或未命中映射时原样返回。 */
export function resolveAffiliateDashDisplayProductName(
skuCode: string,
skuName = '',
mapping?: Readonly<Record<string, string>> | null,
): string {
const code = String(skuCode || '').trim()
const name = String(skuName || '').trim()
const table = mapping || AFFILIATE_DASH_SKU_MAPPING
return (
reverseAffiliateDashSkuToProductNo(code, table) ||
reverseAffiliateDashSkuToProductNo(name, table) ||
name ||
code
)
}
@@ -28,6 +28,7 @@ const STATUS_LABELS: Record<string, string> = {
delivered: '已发放',
disabled: '已停用',
dispatched_pending_return: '待退还号码',
draft: '草稿',
expired: '已过期',
external: '外部链接',
failed: '失败',
@@ -91,6 +92,7 @@ const STATUS_COLORS: Record<string, string> = {
customer_processing: 'blue',
delivered: 'green',
disabled: 'red',
draft: 'gold',
external: 'cyan',
failed: 'red',
invalid: 'orange',
@@ -845,7 +845,7 @@ function resolveDeliveryStepSummary(detail: AdminTaskDetail) {
function resolveTaskExecutorDisplay(value: unknown) {
const executorKey = String(value || '').trim()
if (executorKey === 'affiliate_dash') {
return { label: 'Affiliate Dash', color: 'green' }
return { label: '联盟发货', color: 'green' }
}
if (executorKey === 'kuaishou_ct_assisted') {
return { label: '乐玩云(已下线)', color: 'default' }
@@ -137,7 +137,9 @@ export default function AdminTasksPage() {
return (
<div className="cell-stack">
<span>{row.skuName || '-'}</span>
<span className="muted">{row.skuCode || '-'}</span>
{row.skuCode && row.skuCode !== row.skuName ? (
<span className="muted">{row.skuCode}</span>
) : null}
<Tag className="task-list-executor-tag" color={executor.color} title={executor.key}>
{executor.label}
</Tag>
@@ -472,7 +474,7 @@ export default function AdminTasksPage() {
function resolveTaskExecutorDisplay(value: unknown) {
const executorKey = String(value || '').trim()
if (executorKey === 'affiliate_dash') {
return { key: executorKey, label: 'Affiliate Dash', color: 'green' }
return { key: executorKey, label: '联盟发货', color: 'green' }
}
if (executorKey === 'kuaishou_ct_assisted') {
return { key: executorKey, label: '乐玩云(已下线)', color: 'default' }
@@ -45,7 +45,7 @@ type EditableRoutingRule = Omit<AdminFulfillmentRoutingRule, 'normalizedProductN
}
const ROUTING_EXECUTORS = [
{ key: 'affiliate_dash', label: 'affiliate-dash', color: 'gold' },
{ key: 'affiliate_dash', label: '联盟发货', color: 'gold' },
{ key: 'manual_dispatch', label: '人工履约', color: 'default' },
]
+1 -1
View File
@@ -7,7 +7,7 @@ export const adminPayStatusOptions = [
]
export const adminOrderExecutorOptions = [
{ label: 'Affiliate Dash', value: 'affiliate_dash' },
{ label: '联盟发货', value: 'affiliate_dash' },
{ label: '行业凭证', value: 'kuaishou-industry' },
{ label: '人工履约', value: 'manual_dispatch' },
]