fix(admin): 任务列表商品名与执行器标签改为中文展示
建单时不再把英文 sku 写入商品名,列表按映射反查中文名,并将 Affiliate Dash 等标签本地化。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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' },
|
||||
]
|
||||
|
||||
|
||||
@@ -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' },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user