记录星册首页 More 按钮恢复的方案说明与 TDD 实施计划,作为本次特性 commit e079a6c 的设计依据。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8.7 KiB
8.7 KiB
星册首页“更多”按钮恢复设计
★ MVP 优先:本次仅恢复旧版星册首页“每组预览 3 张 + 超出显示更多”的既有行为,不引入新分页框架、不修改前端布局。
方案概述(必读)
要解决的问题
业务问题
- 星册首页的原创、典藏和活动分组均不再显示“更多”按钮。
- 用户无法从首页进入对应分类的完整藏品列表。
技术问题
assetService迁移后,分组构建器返回全部藏品,并把AssetGroup.HasMore、GradeSection.HasMore固定为false。- protobuf 的
false字段可能因omitempty不出现在 JSON 中,前端v-if="group.has_more"和v-if="gradeItem.has_more"均不成立。 - 当前分组构建器同时被首页
GetMyAssets和查看更多GetAssetsByType复用,不能直接统一截断,否则查看更多页面也只能拿到前三张。
整体实现路径
- 为共享分组构建器增加预览上限参数,约 0.5 小时。
- 首页传入固定上限 3,查看更多传入 0(不限),约 0.5 小时。
- 补充首页截断和查看更多完整返回测试,约 1 小时。
- 执行 assetService、gateway 相关测试和全服务预编译,约 0.5 小时。
预计总工作量:约 2.5 小时。
关键决策
- 恢复旧版
HomePageSize = 3行为:用户已确认每个分组或等级最多预览 3 张。 - 统一按点赞数选取首页前三张:原创、典藏、活动均使用
models.Asset.LikeCount按点赞数降序;点赞数相同时按asset_id升序,沿用项目排行榜的稳定排序口径。 - 后端计算
has_more:保证 API 契约真实,避免前端下载全部数据后再截断。 - 参数化复用现有构建器:首页限制 3,查看更多限制 0,避免复制三套分组逻辑。
- 不修改前端模板:现有
v-if在后端返回正确字段后即可工作。
核心架构图(TL;DR)
GET /api/v1/starbook/home
│
▼
GetMyAssets ── previewLimit=3 ──► group builders
│
├─ items[:3]
├─ total_count=真实数量
└─ has_more=(真实数量 > 3)
GET /api/v1/starbook/items
│
▼
GetAssetsByType ── previewLimit=0 ──► 同一组 builders
│
├─ items=全部匹配项
└─ 不因首页规则截断
文档说明
- 适用范围:星册首页分组预览和“更多”入口。
- 不包含:前端布局重做、数据库查询级分页重构、新增缓存。
- 前置版本:
starbookService已删除,相关能力已迁移到assetService。 - 历史依据:旧版
starbookService使用HomePageSize = 3,原创按等级截断并计算has_more。 - 目标读者:后端开发、前端联调和测试人员。
1. 当前行为与根因
StarbookContent.vue 已正确消费以下字段:
- 原创:
gradeItem.has_more - 典藏/活动:
group.has_more
问题位于 assetService/service/asset_service.go:三个分组构建器返回所有项目,并把 HasMore 固定为 false。因此前端不需要增加兜底逻辑,修复应落在 API 数据生产端。
2. 分组构建器接口
三个构建器增加 previewLimit int 参数:
buildRegularGroupForAssets(..., previewLimit int) *pb.AssetGroup
buildCollectionGroupForAssets(..., previewLimit int) *pb.AssetGroup
buildActivityGroupForAssets(..., previewLimit int) *pb.AssetGroup
参数语义:
previewLimit > 0:先按models.Asset.LikeCount DESC, Asset.ID ASC排序,再最多保留指定数量;has_more表示是否有项目被本次预览截断。previewLimit <= 0:不截断,用于查看更多接口;分组和等级的has_more必须为false,避免把“无限制模式”错误解释成仍有未返回项目。
定义首页常量:
const homePreviewLimit = 3
不增加配置文件或环境变量;该值是已确认的固定产品规则。
3. 首页数据规则
3.1 原创藏品
原创按 grade 独立计算:
- 只统计能关联到真实
Asset的有效注册记录。 - 每个等级使用关联到的
models.Asset.LikeCount按点赞数降序排序;点赞数相同时按Asset.ID升序,不能使用可能漂移的AssetRegistry.LikeCount。 - 每个等级最多返回 3 张。
GradeSection.TotalCount为该等级有效项目总数。GradeSection.HasMore = previewLimit > 0 && TotalCount > previewLimit。AssetGroup.HasMore为任一等级HasMore=true。- 保持现有 grade 降序输出。
3.2 典收藏品
- 构建有效项目列表。
- 使用关联到的
models.Asset.LikeCount按点赞数降序排序;点赞数相同时按Asset.ID升序,不能使用AssetRegistry.LikeCount。 - 首页最多返回前三张。
TotalCount为有效项目总数。HasMore = previewLimit > 0 && TotalCount > previewLimit。
3.3 活动藏品
规则与典藏一致:使用 models.Asset.LikeCount 按点赞数降序并以 Asset.ID ASC 稳定并列顺序,有效项目总数超过 3 时截断并返回 HasMore=true。
4. 查看更多数据规则
GetAssetsByType 调用构建器时传 previewLimit=0:
- 不执行首页前三张截断。
- 保留当前 type/category/grade 过滤逻辑。
- 返回结果沿用首页的统一排序:
models.Asset.LikeCount DESC, Asset.ID ASC。 - 返回所有匹配分组项目,确保首页点击“更多”后能看到完整数据。
- 本次不扩展数据库级分页;现有接口的分页字段行为不在此次修复范围内。
5. 前端行为
frontend/pages/components/StarbookContent.vue 不需要修改:
- 原创继续使用
v-if="gradeItem.has_more"。 - 典藏和活动继续使用
v-if="group.has_more"。 processGroupsWithValidUrls的深拷贝会保留值为true的has_more字段。
验收行为:
| 实际数量 | 首页显示数量 | “更多”按钮 |
|---|---|---|
| 0 | 0 | 不显示 |
| 1–3 | 1–3 | 不显示 |
| 4+ | 3 | 显示 |
6. 测试设计
6.1 Service 单元测试
至少覆盖:
- 原创某等级 3 张:返回 3 张,等级和外层
has_more=false。 - 原创某等级 4 张:首页按
Asset.LikeCount DESC, Asset.ID ASC返回前三张,total_count=4,等级和外层has_more=true。 - 典藏 4 张:首页按
Asset.LikeCount DESC, Asset.ID ASC返回前三张,total_count=4,has_more=true。 - 活动 4 张:首页按
Asset.LikeCount DESC, Asset.ID ASC返回前三张,total_count=4,has_more=true。 - 点赞来源口径:故意让
AssetRegistry.LikeCount与Asset.LikeCount相反,断言排序严格采用Asset.LikeCount。 - 查看更多模式 4 张:按同一规则返回全部 4 张,分组/等级
has_more=false,不受首页上限影响。 - 边界值
previewLimit=3:数量为 0、1、3、4 时分别验证返回数量和has_more,防止 off-by-one。 - 注册记录找不到对应资产时:无效记录不应制造错误的
total_count或has_more。 - 多个原创等级中仅一个等级超过 3 张:仅该等级
has_more=true,外层AssetGroup.HasMore=true。
6.2 回归验证
- 运行 assetService 相关 service/provider 测试。
- 运行 Starbook gateway controller 测试。
- 编译 gateway 和 assetService。
- 按
dev.sh服务列表预编译全部后端服务。 - 检查
GetMyAssets与GetAssetsByType的调用方,确认二者分别传入 3 和 0。
7. 错误处理与兼容性
- 不改变 protobuf 字段或 REST 响应结构。
- 不改变身份校验和 type/category/grade 过滤规则。
- 空分组维持现有行为。
has_more=false仍可能被 JSON 省略,前端将其视为假值,符合预期;只有需要按钮时必须返回true。
8. 实施文件
预计修改:
backend/services/assetService/service/asset_service.go- 对应的 assetService 测试文件(优先复用现有测试文件)
预计不修改:
frontend/pages/components/StarbookContent.vuebackend/proto/asset.proto- 生成的 protobuf 文件
- 数据库与 migration
9. 非目标与后续项
本次明确不做:
- 数据库查询层的真实分页与 limit/offset 下推。
- 首页排序规则重构。
- collection/activity 的分类结构重构。
- 前端“更多”按钮样式调整。
如果单个用户藏品数量显著超过当前 GetByOwner(..., 1000, 0) 上限,应另立任务把首页预览下推到 repository 查询层;这不影响本次恢复既有按钮行为。