feat(admin): 彻底优化任务列表与详情界面,集成到账存证凭单与联盟直充面板
- 优化任务列表角色列:支持从 affiliateDash 及 claimIdentity 中自动提取并展示角色名与 UID(含一键复制) - 列表操作栏支持一键查看到账存证凭单,支持直接复制图片发给买家或下载保存 - 任务详情页全面现代化重构: - 新增「兑换成功 · 官方直充到账存证凭据」大卡片,实时生成 640x960 Retina 高清卡片,支持一键写入系统剪贴板(微信/QQ/客服窗口直接 Ctrl+V 发送)、下载 PNG 大图与全屏预览 - 新增「联盟直充履约 (affiliate_dash)」专属面板,结构化展示上游订单号、直充状态、点数积分、核销状态及供应商回执 - 优化凭据生成器 (voucher.ts):强制优先读取本地高清商品图,彻底消除上游图片文字水印与圆环破图问题 - 验证方式:npm run build & npm test (133 项单测全量通过)
This commit is contained in:
@@ -139,7 +139,7 @@ export async function getAdminOrders(
|
||||
}
|
||||
}
|
||||
|
||||
function groupRowsByOrderId<T extends { order_id: number | string }>(rows: T[]): Map<number, T[]> {
|
||||
function groupRowsByOrderId<T extends { order_id?: number | string | null }>(rows: T[]): Map<number, T[]> {
|
||||
const grouped = new Map<number, T[]>()
|
||||
for (const row of rows) {
|
||||
// pg BIGINT 常以 string 返回;统一 Number 键,避免列表挂不上 order_items →「商品 0」。
|
||||
@@ -431,6 +431,7 @@ export async function getAdminTaskDetail(
|
||||
kuaishouCloudFulfillment,
|
||||
kuaishouIndustryVoucher,
|
||||
manualDispatch: mapManualDispatchContext(taskContext.manualDispatch, viewerContext),
|
||||
affiliateDash: taskContext.affiliateDash || null,
|
||||
events: taskEvents.map(mapAdminTaskEvent),
|
||||
operations: {
|
||||
canRetry:
|
||||
|
||||
@@ -285,9 +285,53 @@ function getTaskRetryCount(task: TaskRow | null | undefined): number {
|
||||
}
|
||||
|
||||
function resolveTaskDisplayRoleName(task: TaskRow): string {
|
||||
return String(task.kuaishou_role_name || task.role_name || '').trim()
|
||||
if (task.kuaishou_role_name || task.role_name) {
|
||||
return String(task.kuaishou_role_name || task.role_name).trim()
|
||||
}
|
||||
const context = safeParseJson(task.context_json)
|
||||
const affiliateDash = context.affiliateDash
|
||||
if (affiliateDash && typeof affiliateDash === 'object') {
|
||||
const dash = affiliateDash as Record<string, unknown>
|
||||
const name = String(dash.roleName || dash.boundRoleName || dash.game_account_role_name || '').trim()
|
||||
if (name) return name
|
||||
}
|
||||
const kuaishouCloud = context.kuaishouCloudFulfillment
|
||||
if (kuaishouCloud && typeof kuaishouCloud === 'object') {
|
||||
const cloud = kuaishouCloud as Record<string, unknown>
|
||||
const roleObj = cloud.role as Record<string, unknown> | undefined
|
||||
if (roleObj?.name) return String(roleObj.name).trim()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function resolveTaskDisplayRoleId(task: TaskRow): string {
|
||||
return String(task.kuaishou_role_id || task.role_id || '').trim()
|
||||
if (task.kuaishou_role_id || task.role_id) {
|
||||
return String(task.kuaishou_role_id || task.role_id).trim()
|
||||
}
|
||||
const context = safeParseJson(task.context_json)
|
||||
const affiliateDash = context.affiliateDash
|
||||
if (affiliateDash && typeof affiliateDash === 'object') {
|
||||
const dash = affiliateDash as Record<string, unknown>
|
||||
const id = String(
|
||||
dash.boundAccount ||
|
||||
dash.gameAccount ||
|
||||
dash.expectedGameAccount ||
|
||||
dash.game_uid ||
|
||||
dash.game_account ||
|
||||
'',
|
||||
).trim()
|
||||
if (id) return id
|
||||
}
|
||||
const claimIdentity = context.claimIdentity
|
||||
if (claimIdentity && typeof claimIdentity === 'object') {
|
||||
const id = String((claimIdentity as Record<string, unknown>).expectedUid || '').trim()
|
||||
if (id) return id
|
||||
}
|
||||
const kuaishouCloud = context.kuaishouCloudFulfillment
|
||||
if (kuaishouCloud && typeof kuaishouCloud === 'object') {
|
||||
const cloud = kuaishouCloud as Record<string, unknown>
|
||||
const roleObj = cloud.role as Record<string, unknown> | undefined
|
||||
if (roleObj?.rid) return String(roleObj.rid).trim()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ export type AdminTaskDetailView = {
|
||||
kuaishouCloudFulfillment: JsonObject | null
|
||||
kuaishouIndustryVoucher: JsonObject | null
|
||||
manualDispatch: JsonObject | null
|
||||
affiliateDash: JsonObject | null
|
||||
events: JsonObject[]
|
||||
operations: JsonObject
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user