Files
junhong_cmp_fiber/openspec/changes/archive/2026-09-20-add-h5-popup-account-names/design.md
break 863607639f
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
归档
2026-09-20 10:46:34 +08:00

3.1 KiB
Raw Blame History

Context

参见 proposal.md 的 Why。当前运营弹窗配置读取链路由 Query 直接读取配置模型并映射为统一响应 DTO配置表只保存 creatorupdater 账号 ID账号名称位于 tb_account.username。列表与详情共用响应 DTO但当前映射函数没有账号名称输入。

项目要求读取使用 Query/GORM关联通过 ID 显式查询,不新增 GORM 关联或数据库外键。账号采用软删除,历史配置需要能解析已删除账号。

Goals / Non-Goals

Goals:

  • 列表和详情使用同一账号名称语义与响应字段。
  • 列表名称补充保持常数次查询,不产生 N+1。
  • 名称查询错误沿既有稳定错误链返回。

Non-Goals:

  • 不保存创建人或更新人的名称快照。
  • 不修改配置写入、版本、启停、排序或权限语义。
  • 不修改账号删除策略或数据库 Schema。

Decisions

1. 在响应 DTO 增加 creator_nameupdater_name

保留 creatorupdater,新增同语义名称字段。这样现有调用方保持兼容,后台可直接展示名称。未采用替换 ID 或嵌套账号对象,因为都会扩大契约变更并增加前端迁移成本。

2. Query 批量读取当前账号名称

列表先读取当页配置,再收集非零且去重后的创建人、更新人 ID通过一次 Unscoped GORM 查询读取 id, username,生成名称映射后投影响应。详情复用同一批量加载函数,以单元素 ID 集合获得相同语义。

未采用 SQL JOIN当前 Query 已先执行总数与分页读取,独立批量查询更容易保持 Count、排序和配置模型扫描不变也符合项目显式关联约束。未采用逐条账号查询避免 N+1。

3. 已删除账号可见,缺失账号返回空名称

账号查询使用 Unscoped,因此软删除账号仍能提供历史用户名。映射中没有对应记录时保留字符串零值,表示账号事实已不存在。该行为不制造占位文案,避免把展示策略固化到 API。

4. 查询失败不得静默降级

账号名称查询失败包装为稳定数据库错误并终止列表或详情响应。静默返回空名称会把数据库故障与“账号记录不存在”混为同一可观察结果,违反契约。

Risks / Trade-offs

  • [账号用户名后续可修改,历史配置展示的是当前用户名而非操作时快照] → 本次明确只补充当前账号名称;若业务要求历史身份不可变,应另建名称快照变更。
  • [列表增加一次账号查询] → 对当页 ID 去重并只选择 id, username,查询数量固定为一次。
  • [历史脏数据引用不存在账号] → 保留账号 ID名称返回空字符串使调用方仍能识别原始关联值。

Migration Plan

  1. 更新响应 DTO 与 Query 投影。
  2. 重新生成 OpenAPI 文档并构建 API、Worker。
  3. 在维护者指定的隔离环境请求列表和详情,核对正常账号、软删除账号及不存在账号三种结果。
  4. 回滚只需恢复应用代码与生成文档;无数据库迁移或数据回滚。