From 27a4e62a43d238758bf2bc5f6fcb437a3529a8e2 Mon Sep 17 00:00:00 2001 From: czl231 <3286836406@qq.com> Date: Sun, 16 Aug 2026 23:33:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=90=E7=8E=B0=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E5=85=B3=E8=81=94=E5=90=8D=E7=A7=B0=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...作日志_提现详情关联名称展示修复_20260816.md | 51 +++++++++++++++++++ docs/项目文档_平台资源中文展示统一_v1.0.md | 2 + .../check-resource-display-contracts.mjs | 35 ++++++++++++- .../src/api/resource-detail-contract.ts | 10 +++- .../src/api/resource-display.ts | 28 ++++++---- frontend/platform_admin/src/api/resources.ts | 20 ++++++-- 6 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 docs/操作日志_提现详情关联名称展示修复_20260816.md diff --git a/docs/操作日志_提现详情关联名称展示修复_20260816.md b/docs/操作日志_提现详情关联名称展示修复_20260816.md new file mode 100644 index 0000000..ec850c4 --- /dev/null +++ b/docs/操作日志_提现详情关联名称展示修复_20260816.md @@ -0,0 +1,51 @@ +# 提现详情关联名称展示修复操作日志 + +操作时间:2026-08-16 + +操作类型:修改 + +影响模块:平台总后台、财务管理、提现记录详情 + +## 操作前状态 + +- 钱包唯一标识被声明为无目标资源的身份字段,详情页无法加载关系名称,固定显示“名称加载失败”。 +- 审核人姓名快照已经展示,但响应中的审核人唯一标识又作为独立字段显示完整 UUID,信息重复且不符合统一展示规范。 + +## 具体操作 + +1. 将提现记录的钱包字段声明为 `/wallet_basic` 关系,按钱包归属类型显示“用户钱包”“工作人员钱包”“气站钱包”“配送点钱包”或“平台钱包”。 +2. 钱包关系继续保留详情跳转和完整 UUID 复制能力。 +3. 将审核人唯一标识声明为 `/platform_account` 关系,优先使用接口已有的 `reviewer_name` 姓名快照展示。 +4. 在提现详情专属契约中隐藏独立的审核人姓名快照字段,避免姓名与 UUID 分成两项重复展示。 +5. 增加静态展示契约断言,防止钱包关系退回“名称加载失败”或审核人退回裸 UUID。 +6. 提现列表直接使用 `reviewer_name` 审核姓名快照作为主文案,同时保留审核人标识复制和详情跳转。 + +## 行为变化 + +- 修改前:钱包显示“名称加载失败”;审核人姓名与完整审核人 UUID 分开显示。 +- 修改后:钱包显示可读归属类型摘要;审核人显示姓名并附带可复制标识,可点击进入对应详情。 +- 列表中的历史审核人不再依赖实时账户名称加载,避免显示“名称加载失败”。 +- 提现金额、状态机、审核动作、接口入参和数据库数据均未改变。 + +## 代码变更 + +- `frontend/platform_admin/src/api/resources.ts`:补齐钱包及审核人的关系展示配置。 +- `frontend/platform_admin/src/api/resource-display.ts`:新增钱包归属类型摘要格式化,并统一复用关系选项格式化器。 +- `frontend/platform_admin/src/api/resource-detail-contract.ts`:增加提现详情字段顺序和姓名快照隐藏规则。 +- `frontend/platform_admin/scripts/check-resource-display-contracts.mjs`:增加提现关系展示回归断言。 +- `docs/项目文档_平台资源中文展示统一_v1.0.md`:记录 v1.7 变更。 + +## 验证结果 + +- `pnpm resource-display-contracts:check`:通过。 +- `pnpm contract:check`:通过,48 个资源契约一致。 +- `pnpm type:check`:通过。 +- `pnpm exec prettier --check ...`:未执行,项目未安装 Prettier 命令;不影响既有质量脚本。 +- `pnpm biome lint src/api/resources.ts src/api/resource-display.ts src/api/resource-detail-contract.ts scripts/check-resource-display-contracts.mjs`:通过;仅报告一项修改前已存在的 `Object.hasOwn` 建议警告。 +- `pnpm lint`:未通过;全仓既有组件存在 2 个错误、188 个警告和 12 项提示,本次修改文件的定向 lint 未产生错误。 +- `pnpm build`:通过,Vite 成功完成 2621 个模块的生产构建。 + +## 风险评估 + +- 本次仅改变提现详情的关联展示,不修改资金事实、权限、状态流转或后端接口。 +- 钱包没有独立业务名称,因此使用归属主体类型作为稳定摘要;完整钱包标识仍可复制并可进入钱包详情核验。 diff --git a/docs/项目文档_平台资源中文展示统一_v1.0.md b/docs/项目文档_平台资源中文展示统一_v1.0.md index a34b8a7..ad46da9 100644 --- a/docs/项目文档_平台资源中文展示统一_v1.0.md +++ b/docs/项目文档_平台资源中文展示统一_v1.0.md @@ -68,3 +68,5 @@ frontend/platform_admin/ - v1.4:商城订单统一展示用户名称及空值业务文案;Mock 订单改用商城独立交易状态,并补齐金额、支付时间和下单快照。 - v1.5:商品评价列表的商城订单、商品和用户关系统一展示可读业务名称,UUID 降级为复制信息。 - v1.6:商品分类的技术标识列与其他电商列表统一为“系统唯一标识”,显示截断值并保留复制能力。 +- v1.7:提现详情的钱包关系改为可读归属类型摘要,审核人合并展示姓名快照与可复制标识,移除“名称加载失败”和重复裸 UUID。 +- v1.7.1:提现列表的审核人改为直接使用审核姓名快照,并保留审核人标识复制与详情跳转,避免历史账户关系加载失败影响列表展示。 diff --git a/frontend/platform_admin/scripts/check-resource-display-contracts.mjs b/frontend/platform_admin/scripts/check-resource-display-contracts.mjs index 1c25359..d8053e6 100644 --- a/frontend/platform_admin/scripts/check-resource-display-contracts.mjs +++ b/frontend/platform_admin/scripts/check-resource-display-contracts.mjs @@ -1,6 +1,6 @@ /** * 功能描述:校验平台48类资源均具备中文展示字段,并防止列表、详情退回数据库ID或动态英文列。 - * 版本:v1.2.1 + * 版本:v1.3.0 */ import fs from 'node:fs'; import path from 'node:path'; @@ -79,6 +79,39 @@ for (const [key, label] of [ } } +// 提现详情必须展示可读钱包摘要和审核人姓名,UUID仅作为复制信息保留。 +const withdrawalDefinition = resources.match( + /define\('wallet_apply_cash',[\s\S]*?\n\s*\], 'list',/, +)?.[0]; +if (!withdrawalDefinition) throw new Error('无法读取提现记录资源定义'); +for (const contract of [ + "relation('wallet_basic_identity', '/wallet_basic'", + "relationOptionDisplay: 'wallet-owner'", + "relation('reviewer_identity', '/platform_account'", + "listDisplayKey: 'reviewer_name'", + 'listDisplayIdentityCopy: true', + "detailDisplayKey: 'reviewer_name'", +]) { + if (!withdrawalDefinition.includes(contract)) { + throw new Error(`提现详情缺少可读关系展示契约:${contract}`); + } +} +assertIncludes( + detailContract, + "wallet_apply_cash: {", + '提现详情必须声明专属字段顺序与审核姓名快照隐藏规则', +); +assertIncludes( + detailContract, + "hiddenKeys: ['reviewer_name']", + '提现详情不得重复展示审核人姓名快照和审核人唯一标识', +); +assertIncludes( + display, + "field.relationOptionDisplay === 'wallet-owner'", + '钱包关系必须提供按归属类型生成的可读摘要', +); + // 购物车关联列必须展示用户和商品名称,UUID仅作为复制与排障信息保留。 const cartDefinition = resources.match( /define\('ec_cart',[\s\S]*?\n\s*\]\),/, diff --git a/frontend/platform_admin/src/api/resource-detail-contract.ts b/frontend/platform_admin/src/api/resource-detail-contract.ts index a74886d..ed32ed4 100644 --- a/frontend/platform_admin/src/api/resource-detail-contract.ts +++ b/frontend/platform_admin/src/api/resource-detail-contract.ts @@ -1,6 +1,6 @@ /** * 功能描述:声明平台资源详情的字段顺序、固定关联表列和 JSON 展示规则。 - * 版本:v1.0.0 + * 版本:v1.1.0 */ export type ResourceCollectionContract = { @@ -132,6 +132,14 @@ const contracts: Record = { 'wallet_basic_identity', 'identity', ], }, + wallet_apply_cash: { + leadingKeys: [ + 'cash_no', 'apply_status', 'wallet_basic_identity', 'amount', + 'reviewer_identity', 'review_reason', 'reviewed_at', 'identity', + ], + // 审核姓名作为审核人关系的可读快照使用,不再重复渲染独立字段。 + hiddenKeys: ['reviewer_name'], + }, ec_order: { leadingKeys: [ 'order_no', 'order_status', 'request_no', 'user_account_identity', diff --git a/frontend/platform_admin/src/api/resource-display.ts b/frontend/platform_admin/src/api/resource-display.ts index 7c9b2f7..eae6e3a 100644 --- a/frontend/platform_admin/src/api/resource-display.ts +++ b/frontend/platform_admin/src/api/resource-display.ts @@ -1,6 +1,6 @@ /** * 功能:统一资源列表与详情页面的字段名称、关系、金额、状态和时间展示。 - * 版本:v1.6.0 + * 版本:v1.7.0 */ import dayjs from 'dayjs'; import type { RecordPageMode, ResourceRow } from './resource-page-rules'; @@ -277,6 +277,9 @@ export function relationOptionLabel( if (field.relationOptionDisplay === 'product-name-type') { return productNameTypeLabel(option, options); } + if (field.relationOptionDisplay === 'wallet-owner') { + return walletOwnerLabel(option); + } const configuredLabel = field.relationOptionLabelKey ? option[field.relationOptionLabelKey] : undefined; @@ -295,6 +298,20 @@ export function relationOptionLabel( : label; } +/** 钱包没有独立业务名称时,按归属主体类型提供稳定可读摘要。 */ +function walletOwnerLabel(option: ResourceRow) { + const ownerType = String(option.owner_type ?? ''); + return ( + { + user: '用户钱包', + staff: '工作人员钱包', + gas: '气站钱包', + delivery: '配送点钱包', + platform: '平台钱包', + }[ownerType] ?? '钱包账户' + ); +} + /** 合同气瓶优先显示具体设备名称和绑定时类型;同名同类型时追加编码以便区分。 */ function productNameTypeLabel(option: ResourceRow, options: ResourceRow[]) { const name = String(option.product_name ?? '').trim(); @@ -326,14 +343,7 @@ function relationLabel( (option) => String(option.identity) === identity, ); if (!match) return '名称加载失败'; - if (field.relation === '/staff_account') { - return relationOptionLabel( - field, - match, - relationOptions[field.relation ?? ''] ?? [], - ); - } - return optionLabel(match); + return relationOptionLabel(field, match, relationOptions[resource] ?? []); } /** 根据当前记录的主体类型解析静态或动态关系资源。 */ diff --git a/frontend/platform_admin/src/api/resources.ts b/frontend/platform_admin/src/api/resources.ts index 5875b30..fbb5b0e 100644 --- a/frontend/platform_admin/src/api/resources.ts +++ b/frontend/platform_admin/src/api/resources.ts @@ -95,8 +95,8 @@ export type ResourceField = { dynamicRelation?: ResourceDynamicRelation; /** 关联选项优先使用的业务展示字段。 */ relationOptionLabelKey?: string; - /** 关联选项的组合展示方式;合同气瓶使用设备名称、绑定类型快照和编码消歧。 */ - relationOptionDisplay?: 'product-name-type'; + /** 关联选项的组合展示方式;合同气瓶和钱包分别使用对应的可读业务摘要。 */ + relationOptionDisplay?: 'product-name-type' | 'wallet-owner'; /** 该字段为真时,在关联选项后追加“默认地址”。 */ relationOptionDefaultKey?: string; /** 候选加载完成后自动选中该布尔字段为真的选项。 */ @@ -784,7 +784,12 @@ export const resources: ResourceUiDefinition[] = [ ], { canCreate: false, canEdit: false, canChangeStatus: false, canArchive: false }), define('wallet_apply_cash', '提现记录', 'readonly', [ f('cash_no'), - f('wallet_basic_identity', { type: 'identity' }), + relation('wallet_basic_identity', '/wallet_basic', false, { + label: '钱包', + relationOptionDisplay: 'wallet-owner', + displayRelationLabel: true, + showIdentityCopy: true, + }), f('amount'), f('apply_status', { type: 'select', options: [ { label: '待处理', value: 10 }, @@ -792,7 +797,14 @@ export const resources: ResourceUiDefinition[] = [ { label: '已驳回', value: 26 }, { label: '已完成', value: 23 }, ] }), - f('reviewer_name'), + relation('reviewer_identity', '/platform_account', false, { + label: '审核人', + listDisplayKey: 'reviewer_name', + listDisplayIdentityCopy: true, + detailDisplayKey: 'reviewer_name', + displayRelationLabel: true, + showIdentityCopy: true, + }), f('review_reason'), f('reviewed_at'), f('completed_at'),