docs(spec): P4 author page design (pure frontend aggregation)
- docs/specs/2026-09-29-author-page-design.md: /users/:user pure aggregation page, minimal list, zero backend/migration changes - docs/ROADMAP.md: P4 scope refined per design (frontend filtering instead of API author filter), register spec in doc index
This commit is contained in:
+2
-2
@@ -24,7 +24,7 @@
|
||||
|
||||
| # | 子项目 | 内容 | 涉及仓库 | 依赖 | 状态 |
|
||||
|---|--------|------|----------|------|------|
|
||||
| P4 | 作者主页 | `/users/:user` 聚合页(该作者全部作品),API 列表按作者过滤;顺带 `/games/:user/:slug` 面包屑与作者名互链 | 三仓(API 过滤 + 前端页面) | 无强依赖,可提前并行 | 待启动 |
|
||||
| P4 | 作者主页 | `/users/:user` 聚合页(该作者全部已上架作品,前端按命名空间过滤,**零后端改动**),按最新上架排序;顺带 `/games/:user/:slug` 面包屑与作者名互链。spec:`docs/specs/2026-09-29-author-page-design.md` | crearte(前端) | 无强依赖,可提前并行 | 设计已批,待实现计划 |
|
||||
| P5 | 收藏 / 评分 | 新数据表 + 用户态 API + 目录/详情页 UI;产品线里最大的一块 | 三仓 | 建议 P2 先落地 | 待启动 |
|
||||
| P6 | hosted 作品投稿 | 范围模糊,需先定义 hosted 托管语义(只存 URL 还是真托管文件),再定投稿/审核流 | 三仓 | 需先决策 | 待澄清 |
|
||||
|
||||
@@ -50,4 +50,4 @@
|
||||
|
||||
| 子项目 | spec | 实现计划 |
|
||||
|--------|------|----------|
|
||||
| (待补) | | |
|
||||
| P4 作者主页 | `docs/specs/2026-09-29-author-page-design.md` | (待写) |
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# P4 作者主页(`/users/:user`)设计 / Author Page Design
|
||||
|
||||
- **状态**:设计已批准(2026-09-29),待 spec 审阅后转实现计划。
|
||||
- **路线图**:`docs/ROADMAP.md` P4(第二波)。
|
||||
- **范围定性**:纯作品聚合页,极简列表;**零后端改动、零数据迁移**。
|
||||
|
||||
## 1. 背景与意图
|
||||
|
||||
crearte 的作品链接已按用户命名空间组织(`/games/<user>/<slug>`),但站内没有任何按作者聚合的入口:读者读完一个作品想看同作者的其他作品,只能回目录页手动搜索。P4 补上这块:**给每位创作者一个可分享的主页 `/users/:user`,列出其全部已上架作品**。
|
||||
|
||||
成功标准:从作品详情页点作者名能到作者页,页面只显示该作者的作品,按最新上架排序;未知用户名不报错。
|
||||
|
||||
约束(与维护者确认):
|
||||
|
||||
- 范围只到"纯作品聚合页":不做作者简介/头像等档案字段(不碰 `users` 表、不碰上传链路)。
|
||||
- 列表极简:无筛选侧栏、无查询参数(YAGNI,日后需要再加)。
|
||||
|
||||
## 2. 方案选型
|
||||
|
||||
| 方案 | 内容 | 取舍 |
|
||||
|---|---|---|
|
||||
| **A. 纯前端过滤(已选)** | `AuthorView` 复用 `repo.listGames()`,按 `resolveUserSlug(game).user` 过滤 | 零后端改动;与目录页同样拉全量列表(现状即如此,ETag/304);分页化另立子项目时再迁服务端过滤 |
|
||||
| B. 后端 `GET /api/games?author=` | 服务端过滤 + ETag 按参数派生 | 为分页铺路,但当下 YAGNI;动 handler/service/repository 三层 |
|
||||
| C. 新端点 `GET /api/users/:user` | 聚合用户信息 + 作品 | 引入用户名存在性探测面,超出纯聚合范围 |
|
||||
|
||||
**对路线图的偏离**:`docs/ROADMAP.md` P4 原文写"API 列表按作者过滤"。设计阶段发现列表 DTO(`GameSummary`)已含 `user?`/`slug?` 与 `resolveUserSlug()`,前端过滤即可满足需求,因此 P4 **不修改 crearte-server**(顺带不占用 Postgres 迁移号段)。路线图措辞随本 spec 落地同步修订。
|
||||
|
||||
## 3. 设计详述
|
||||
|
||||
### 3.1 路由与页面
|
||||
|
||||
- 新路由 `/users/:user`(与 `/games/:user/:slug` 风格一致),注册于 `src/app/router/index.ts`。
|
||||
- 新视图 `src/app/views/AuthorView.vue`,复用既有组件:`GameCard`、`StatePanel`、`BaseButton` 等。
|
||||
- 页面头部:`@<username>` + 作品数。**语义注意**:展示的是账号 `username`(命名空间所有者),不是作品元数据 `author_name`(自由文本、可空);卡片上的 `author_name` 照旧展示,两者不混用、不互相推导。
|
||||
- 列表按"最新上架"倒序,复用 `src/app/lib/filter.ts` 的既有排序逻辑(优先调用 `filterGames` 或其导出的比较器,**不复制**排序代码)。
|
||||
- 面包屑「目录 / @user」。
|
||||
- 入口:`GameView` 详情页作者名、`GameCard` 作者字样 → `/users/:user`。
|
||||
|
||||
### 3.2 数据流
|
||||
|
||||
`AuthorView` → `useAsync(repo.listGames())`(`src/app/data/` 的 `mergeRepo`:API + static 双源合并,API 宕机降级 static,与目录页同一链路)→ 按 `resolveUserSlug(game).user` 精确过滤(兼容旧式单段 id 作品:取 `id` 中 `/` 前段)→ `sort: 'new'` 排序 → 渲染。
|
||||
|
||||
### 3.3 边界与错误处理
|
||||
|
||||
- 未知用户名 / 该作者无已上架作品:空态「该作者暂无已上架作品」+ 返回目录按钮。**不做**用户存在性探测(需要新端点,YAGNI)。
|
||||
- 可见性语义与目录页完全一致:列表接口只返回已上架未下架作品,作者页自动继承。
|
||||
- 加载 / 失败态复用 `useAsync` + `StatePanel` 既有模式,不做新错误面。
|
||||
|
||||
## 4. 测试
|
||||
|
||||
- **Vitest**:AuthorView 过滤正确性(含 legacy 单段 id 形态与 `user` 字段缺失的回退)、空态渲染、`sort: 'new'` 排序、作者名链接跳转。
|
||||
- **Playwright `noauth`**:`/users/:user` 只显示该作者作品(基于 `src/fixtures/catalog` 现成作品数据)。
|
||||
- **后端**:无(零后端改动)。
|
||||
|
||||
## 5. 影响文件(预估)
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `src/app/router/index.ts` | 注册 `/users/:user` |
|
||||
| `src/app/views/AuthorView.vue` | 新建 |
|
||||
| `src/app/views/GameView.vue` | 作者名加链接 |
|
||||
| `src/app/components/GameCard.vue` | 作者字样加链接(如展示作者) |
|
||||
| `src/app/lib/filter.ts` | 导出排序逻辑供 AuthorView 复用(如未导出) |
|
||||
| 测试文件 | 与视图测试同目录、同命名约定(co-located)新建 |
|
||||
| `docs/CHANGELOG.md`(crearte 仓) | 双语条目 |
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
1. `/users/:user` 只显示该作者的已上架作品(API+static 合并源),按最新上架倒序。
|
||||
2. 旧式单段 id 作品不破坏过滤逻辑(`resolveUserSlug` 回退路径覆盖)。
|
||||
3. 未知用户名 / 无作品:空态渲染,无报错、无 404 路由错误。
|
||||
4. `GameView` 与 `GameCard` 的作者入口可跳转到作者页。
|
||||
5. 新增 Vitest 与 `noauth` Playwright 用例通过,且**存量测试全绿**(含 `vue-tsc` 类型检查)。
|
||||
6. `crearte-server` 零改动(本子项目不产生任何后端 diff)。
|
||||
|
||||
## 7. 明确不做(Out of scope)
|
||||
|
||||
- 作者简介 / 头像 / 关注 / 统计等档案与社交面(对应路线图 P5 之后再议)。
|
||||
- 目录分页 / 服务端过滤(独立子项目)。
|
||||
- 用户存在性探测、`GET /api/users/:user` 类端点。
|
||||
- 静态兜底目录(P8)。
|
||||
Reference in New Issue
Block a user