95976ae2c3
CI / docs-build (push) Failing after 1s
- 01 任务拆解:用户实测 6 项反馈的分类与处置;**数据模型审计推翻迁移预估** (nickname/avatar_asset_id 列 V1/V3 早已存在、purpose 白名单是配置项)→ 本批零迁移 - 02 第一批已交付:中文本地化 + 日期录入收口 + 花费卡月份(flutter 502→526) - 6 项待拍板(首页 demo 裁剪范围、获赞端点形态、头像写权限档等) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
12 KiB
12 KiB
01 M3.5 任务拆解:体验补齐
迭代定位:M3 收官(v0.3.0 发布)后,用户桌面实测反馈 6 项问题的补齐迭代。规模远小于 M1~M3,不做 8 角色开工分析。 执行人:主会话(PM agent 两次卡死未落盘,实情由主会话独立审计取得) 日期:2026-09-10
0. 缘起与范围
用户 2026-09-10 在 Linux 桌面实测 M3 成果,反馈 6 项问题。分类后:
| 用户反馈 | 定性 | 归属 |
|---|---|---|
| ① 日历英文 | 缺陷(从未配本地化) | 第一批已修(M3.5-01) |
② 月份只能 < > 切 |
可用性缺陷,已实际致误录 | 第一批已修(M3.5-02) |
| ⑤ 本月花费 ¥0 | 不是 bug:记录在 2026-04-09、当天 2026-09-10,9 月确实为 0;根因是 ② | 第一批已修 UI 可自查性(M3.5-03) |
| ③ 宠物无头像上传 | ADR-010 剪出项,M3 媒体链路已就位 | 本批 |
| ④ 资料页无法改昵称/头像、显示 demo | 代码层缺口 | 本批 |
| ⑥ 资料页关注/获赞/作品是假数据 | 同 ④(同一 demo 页) | 本批 |
| (未提)首页顶部 demo | 混合性质,须裁剪 | 本批部分 |
本批范围一句话:把「用户资料(昵称+头像)与宠物头像」从 demo 打通为真实读写,资料页数据真实化,并裁剪首页 demo 中属本迭代的部分。
1. 数据模型实情审计(推翻了原先的迁移预估)
开工前一度以为需要 Flyway V6 加列。逐一核实原始 SQL 与代码后确认:所需列全部早已存在,本批零迁移。
| 需求 | 原预估 | 实情(已核实) |
|---|---|---|
| 用户昵称 | identity.users 无 nickname 列,需加 |
V1 第 63 行就有 nickname varchar(32),含 ck_users_nickname(btrim + 1~32 长度);UserRepository.insertUser(id, username, nickname, phone) 注册时已在写 |
| 用户头像 | 需加列 | V1 第 67 行就有 avatar_asset_id uuid,含 fk_users_avatar_asset(→media.assets ON DELETE SET NULL)与索引 ix_users_avatar_asset |
| 宠物头像 | 需加列 | V3 第 64 行就有 avatar_asset_id uuid REFERENCES media.assets(id) ON DELETE SET NULL,含索引 ix_pets_avatar。但 pet 模块代码零处读写它(grep 无命中) |
| 获赞总数 | 需加冗余列 | community.posts 已有 like_count/comment_count/bookmark_count 冗余列(M3 写侧同事务维护),SUM(like_count) 即可 |
| 头像 media 用途 | 需加枚举/约束迁移 | media.assets.purpose 为 varchar(32) NOT NULL 无 CHECK 约束;白名单在 配置项 MediaProperties.allowedPurposes = List.of("post_image") —— 加新用途只改配置 + 契约枚举 |
已就位可直接复用的能力:
/internal/users/profiles已返回PublicProfileResponse(userId, nickname, avatarAssetId),nickname→username 回退在 SQL 层完成(M3 T3-05 交付)。即 Feed 作者名一旦用户设了昵称即自动生效,无需改社区侧。- media 两步上传(user :8082)+ 客户端
MediaUploader六态编排(M3 T3-03/T3-13)。 MediaAssetGateway的 asset 校验先例(ready + 属本人,M3 T3-04)。GET /api/v1/me/posts(含草稿)、GET /api/v1/me/bookmarks、GET /api/v1/users/{id}/follow-stats均已实现。
真实缺口只在代码层:MeResponse 只有 (userId, username, phone, createdAt) 缺昵称/头像;无任何写接口(无 PATCH /me);pets 不读写头像列;获赞总数无端点。
2. 工单拆解
编号自 T3.5-04 起(01~03 已由第一批客户端修复占用)。
第一波:后端与契约
T3.5-04 用户资料读写(user 模块)
- 仓库:patbond-api(patbond-user)
- 描述:
GET /api/v1/me响应补nickname、avatarUrl(预签名 GET,沿用 M3 私有桶签名读口径,URL 会过期不得持久化);新增PATCH /api/v1/me支持改nickname与avatarAssetId(置 null 即清除头像)。校验:nickname 与ck_users_nickname对齐(btrim、1~32);avatarAssetId 必须status='ready'、属当前用户、purpose='user_avatar'(复用 MediaAssetGateway 同类校验语义,错误码沿用 40405/42203)。MediaProperties.allowedPurposes增user_avatar。 - 验收:设昵称后
/me与/internal/users/profiles双端一致;清空昵称回退 username(回退逻辑已在 SQL 层,勿重复实现);非 ready/非本人/错 purpose 的 asset 被拒;六类路径覆盖。 - 依赖:无。规模:M
T3.5-05 宠物头像读写(pet 模块)
- 仓库:patbond-api(patbond-pet)
- 描述:
PATCH /api/v1/pets/{petId}支持avatarAssetId(含置 null);宠物详情/列表/FeedCard 无关响应补avatarUrl(预签名 GET,community 侧本地现签先例见 M3 T3-04)。asset 校验复用MediaAssetGateway(ready + 属本人)+purpose='pet_avatar'。权限沿用PetAccessService:改头像属 WRITE 档(owner+caregiver)还是 MANAGE 档(仅 owner)——见待拍板 D3.5-3。allowedPurposes增pet_avatar。 - 验收:owner 设头像后详情返回可访问 URL;viewer 改被拒;version 乐观锁沿用 40902;非法 asset 被拒。
- 依赖:无(与 T3.5-04 可并行,但同仓需串行提交)。规模:S~M
T3.5-06 获赞总数聚合(community 模块)
- 仓库:patbond-api(patbond-community)
- 描述:提供当前用户的社区统计:获赞总数(
SUM(like_count)over 本人未删帖)、作品数(已发布帖数)。端点形态见待拍板 D3.5-2(新增GET /api/v1/me/community-statsvs 扩展既有 follow-stats)。不引入新冗余列——写侧维护成本高于读侧聚合收益,且量级远未到瓶颈。 - 验收:草稿/软删帖不计入;空数据返回 0 而非 null;口径写入契约描述。
- 依赖:无。规模:S
T3.5-07 契约冻结 v1.4.0
- 仓库:patbond-doc(openapi.yaml)+ patbond-api(快照同步)
- 描述:沿用 M2/M3 迭代式冻结:草案(TODO-FREEZE 标注待定型点)→ 随 04/05/06 实现定型回填 → 拍板 → 合入 v1.4.0 → 四模块字节级快照同步(pet/auth/community/user 的
src/test/resources/contract/)→ 契约矩阵扩展新操作全响应格。 - 验收:
mkdocs build --strict通过;契约矩阵零漂移;升版后 CI 绿(漏快照同步必红,见 iteration-3/19)。 - 依赖:T3.5-04/05/06 定型。本波闸门,不冻结不放行第二波前端。规模:M
第二波:客户端
T3.5-08 资料页真实化 + 编辑页
- 仓库:patbond-flutter
- 描述:
lib/features/profile/profile_page.dart(现 176 行全硬编码 demo:「萌宠新手(豆豆家长)」/24/1.8k/2)替换为真实数据——昵称(空则 username)、头像、获赞、作品数、关注数;新增编辑页(昵称输入 + 头像上传复用MediaUploader,复用 M3 的 gating/失败语义);四态齐备。 - 验收:登录
llx显示llx而非 demo 文案;改昵称后 Feed 作者名同步(同一后端回退链);头像上传全链路;四态有 widget 测试。 - 依赖:T3.5-07 冻结。规模:L
T3.5-09 宠物头像上传接线
- 仓库:patbond-flutter
- 描述:宠物详情页头像的铅笔角标(当前已渲染但无功能)接
MediaUploader;列表/详情展示真实头像(SignedNetworkImage复用,缓存 key 剥签名参数已就位);无头像回退现有爪印占位。 - 验收:上传后详情与列表同步显示;viewer 不显示编辑入口;失败态可重试。
- 依赖:T3.5-07 冻结。规模:M
T3.5-10 首页 demo 裁剪
- 仓库:patbond-flutter
- 描述:首页顶部 demo 分项处置——问候语「下午好,豆豆」改真实昵称(本批做);天气/位置(接外部服务,建议出本批);圈子「柴犬圈/猫咪圈/救助站」(实为话题,ADR-018 已剪出,建议出本批);促销卡「新用户首单立减 ¥20」(属 M5 服务域,建议出本批)。见待拍板 D3.5-1。
- 验收:按拍板结果,保留项标注为「刻意保留的占位」并在报告登记,避免下次实测重复反馈。
- 依赖:T3.5-04 定型(昵称字段)。规模:S~M
3. 波次与关键路径
第一波: T3.5-04 / T3.5-05 / T3.5-06(同仓串行提交)→ [T3.5-07 契约冻结 v1.4.0 闸门]
第二波: T3.5-08(L) / T3.5-09 / T3.5-10
预计一到两波收,无 L 工单堆叠在关键路径(仅 T3.5-08 一个 L)。发布按 releases.md 的新流程走 PR(main 已受保护,首发的直推写法已作废)。
4. 待拍板清单
| # | 决策 | 选项与影响 | 建议 |
|---|---|---|---|
| D3.5-1 | 首页 demo 裁剪范围 | 天气/位置需接外部服务(和风天气类,含 key 管理与配额);圈子=话题(ADR-018 剪出);促销卡属 M5 服务域 | 仅做问候语真实化,其余三项留待对应里程碑,并在代码注释与报告显式标注「刻意保留的 demo 占位」 |
| D3.5-2 | 获赞总数端点形态 | A. 新增 GET /api/v1/me/community-stats(语义清晰、可扩展);B. 扩展既有 follow-stats(少一个端点,但语义混杂——它现在是「某用户的关注数」,加"我的获赞"会变成两种主体) |
A |
| D3.5-3 | 宠物头像的写权限档 | WRITE(owner+caregiver 都能改)vs MANAGE(仅 owner) | WRITE——头像属日常照护信息,与体重/疫苗同档;照护人本就能改这些 |
| D3.5-4 | nickname 唯一性 | 现 DB 无唯一约束(仅长度/btrim CHECK)。允许重名(社区常见,靠 userId 区分)vs 加唯一约束(需迁移,破本批零迁移前提) | 允许重名,不加约束 |
| D3.5-5 | 注册时是否让用户填昵称 | 现注册只收 username/phone/password(nickname 走 insertUser 但值来源需确认)。加一个可选昵称输入 vs 保持不填、注册后到资料页设 |
保持不填(少一步注册摩擦),资料页可设 |
| D3.5-6 | 版本号 | v0.3.1(补丁语义)vs v0.4.0(含新端点,属功能增量) | v0.4.0——加了端点与字段,不是纯修补 |
5. 风险清单
| # | 风险 | 缓解 |
|---|---|---|
| R1 | 契约升版漏同步快照 → 四模块守卫测试全红 | 冻结与快照同步放同一工单(T3.5-07)连贯执行,iteration-3/19 已有可照抄的操作序列 |
| R2 | 头像 URL 是会过期的预签名 GET,客户端若持久化会出现"图突然裂" | 沿用 M3 纪律:URL 不入本地存储;SignedNetworkImage 缓存 key 已剥签名参数 |
| R3 | 同仓(patbond-api)三个后端工单并行会抢工作树 | 同仓串行派工(M2/M3 已验证的模式) |
| R4 | 首页 demo 裁剪范围失控,滑向"顺手把首页重做一遍" | D3.5-1 钉死范围;保留项显式登记,避免反复 |
| R5 | 头像功能上线后,真机验证清单需新增项(弱网上传头像、头像缓存) | 收口时按维护约定登记进 development/device-verification.md |
6. 与既有纪律的衔接
- 零迁移:本批不新增 Flyway 版本(下一个版本号仍为 V6,留给后续真正需要建表的迭代)
- 契约先行:T3.5-07 冻结前,前端不得依赖未冻结字段
- 分支保护:日常推 dev;发布走 PR(releases.md「发布后生效的纪律」)
- 路径参数化:文档内命令一律
cd <你的工作区>/<仓名>