3.1 KiB
3.1 KiB
Context
参见 proposal.md 的 Why。当前运营弹窗配置读取链路由 Query 直接读取配置模型并映射为统一响应 DTO;配置表只保存 creator、updater 账号 ID,账号名称位于 tb_account.username。列表与详情共用响应 DTO,但当前映射函数没有账号名称输入。
项目要求读取使用 Query/GORM,关联通过 ID 显式查询,不新增 GORM 关联或数据库外键。账号采用软删除,历史配置需要能解析已删除账号。
Goals / Non-Goals
Goals:
- 列表和详情使用同一账号名称语义与响应字段。
- 列表名称补充保持常数次查询,不产生 N+1。
- 名称查询错误沿既有稳定错误链返回。
Non-Goals:
- 不保存创建人或更新人的名称快照。
- 不修改配置写入、版本、启停、排序或权限语义。
- 不修改账号删除策略或数据库 Schema。
Decisions
1. 在响应 DTO 增加 creator_name 与 updater_name
保留 creator、updater,新增同语义名称字段。这样现有调用方保持兼容,后台可直接展示名称。未采用替换 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
- 更新响应 DTO 与 Query 投影。
- 重新生成 OpenAPI 文档并构建 API、Worker。
- 在维护者指定的隔离环境请求列表和详情,核对正常账号、软删除账号及不存在账号三种结果。
- 回滚只需恢复应用代码与生成文档;无数据库迁移或数据回滚。