Files
Arkie-Library-Frontend/docs/specs/2026-05-29-popular-resources-section.md
TerryM 7eb2aa8b5b feat: 区块标题改回「热门资料」/ Popular assets
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:42:16 +08:00

207 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 社群常用资料(热门资料)区块 — 设计与后端接口文档
- 日期2026-05-29
- 作者:前端
- 状态:待评审
- 关联需求1.6 熱門資料區
---
## 1. 背景与问题
首页(第一页)的「热门资料」区块当前与「最新更新」区块**使用同一个组件**`LatestUpdateRow`,图标 + 文字行卡),两个区块视觉上几乎一模一样,用户无法区分。同时该区块:
- **没有封面**,不符合需求「展示封面」;
- 与官方推荐(大封面横滑)、最新更新(图标行卡)需要在首页形成**三种不同的版式**。
需求 1.6 明确:热门资料由后台数据自动排序,但**前端只展示资料、不展示具体数字**。
本文档定义两部分工作:
- **前端**:把该区块改造为「榜单」版式(封面 + 名次,无任何数字)。
- **后端**:提供/调整支撑该区块的接口(本文档的主要交付物,交付给后端团队实现)。
---
## 2. 范围
> **产品前提:第一版不做登录系统。** 凡是依赖用户身份的功能(收藏)一律顺延到 Phase 2。
### Phase 1本次
- 前端:首页区块改为榜单版式,卡片含**预览 + 下载**操作(两者都不依赖登录)。
- 后端:
- `GET /api/posts?sort=popular` 热度排序;
- 下载计数;
- 管理员推荐权重字段。
### Phase 2后续本文档仅登记不在本次实现
- 收藏功能(依赖登录 / 用户身份系统——第一版无登录,故顺延;当前 Favorites 页仍为 Coming Soon
- 分享计数;
- 独立的「热门资料」Tab / 列表页。
---
## 3. 命名
- 区块标题:**热门资料**zh-CN / **Popular assets**en
- 内部排序标识沿用 `sort=popular`,不改路由与参数。
> 备注:热度时间窗(累计 vs 本周)见 §7 开放问题。
---
## 4. 前端排版设计(前端负责)
### 4.1 组件
新增榜单组件(暂名 `PopularRankRow` / `PopularRankList`),替换首页 `popular` 区块当前的 `LatestUpdateRow` 网格(桌面)与 `MessageBubble` 列表(移动)。最多展示 **5 条**
数据来源不变:继续调用 `/api/posts?sort=popular`,经现有 `postToResource` 适配为前端资源对象。
### 4.2 单行结构(从左到右)
| 元素 | 说明 |
|---|---|
| 名次徽章 | 第 13 名 🥇🥈🥉;第 45 名灰色等宽序号(`tabular-nums` |
| 封面缩略图 | 取 `attachments[0]``thumbnailUrl` / `posterUrl`(复用现有 `coverFor` 逻辑);前 3 名加金色描边;无封面时回退分类图标 |
| 标题 | 两行截断(`line-clamp-2` |
| Meta 行 | `类型 · 分类 · 更新时间` |
| 操作 | **预览 + 下载**图标按钮(均不依赖登录;收藏依赖登录,见 Phase 2 |
### 4.3 交互
- 整行可点击,跳转 `/resource/:id`
- **预览**按钮:打开资料预览(图片 / 视频 / 文档),不触发下载;复用现有预览浮层逻辑。
- **下载**按钮:复用现有 `downloadAttachment(postId, attachmentId)` 逻辑。
- 预览 / 下载按钮均独立响应(`stopPropagation`),点击不冒泡触发整行跳转。
### 4.4 响应式
- 移动端:单列榜单。
- 桌面端:居中定宽单列(保留「榜单」语义,避免退化成网格而与其他区块再次撞脸),行内加宽留白。
### 4.5 铁律与状态
- **零数字(指数量)**:下载量 / 收藏量 / 分享量 / 热度分等任何**数量型计数一律不显示**(即 1.6 所指「下载 500 次」类数字)。
- **名次序号属于「排名」非「数量」**:榜单展示完整名次 15前 3 名 🥇🥈🥉45 灰色等宽序号)。名次表达相对排序、不暴露任何后台计数,与「避免显示数字」的意图不冲突。
- 加载态:骨架屏。
- 不足 5 条:沿用现有 `ComingSoon` 占位。
---
## 5. 后端接口契约(后端负责 · 核心交付)
### 5.1 热度排序 `GET /api/posts?sort=popular`
**请求参数**(沿用现有约定,无新增必填项):
```
GET /api/posts?sort=popular&lang=zh-CN&language=<sourceLang>&limit=5
```
**排序逻辑**:后端按热度分降序返回。
```
popularityScore =
w_download * downloadCount
+ w_favorite * favoriteCount
+ w_share * shareCount
+ adminWeight
```
- 建议初始权重(可配置):`w_download = 1.0``w_favorite = 2.0``w_share = 3.0``adminWeight` 直接相加。
- Phase 1`favoriteCount` / `shareCount` 暂为 0不影响公式正确性功能上线后自然生效。
- 同分回退顺序:`adminWeight` 降序 → `updatedAt` 降序。
**响应结构**:沿用现有 `PostListResponse`
```jsonc
{
"items": [ /* Post[] */ ],
"nextCursor": "..." // 可选
}
```
**❗硬性约束**`items` 中**不得包含**任何计数 / 分值字段(`downloadCount``favoriteCount``shareCount``popularityScore` 等)。这些仅用于后端排序,前端不需要也不允许展示。
**Post 必含字段**(前端 `postToResource` 依赖,缺失会导致封面 / 类型 / 标题渲染异常):
```jsonc
{
"id": "string",
"postType": "ppt | pdf | image | video | music | link | text | archive",
"categoryId": 0,
"categorySlug": "string",
"language": "string",
"attachments": [
{
"id": "string",
"kind": "image | video | document",
"url": "string",
"mime": "string",
"filename": "string",
"thumbnailUrl": "string?", // 封面优先取这里
"posterUrl": "string?" // 视频封面回退
}
],
"isRecommended": false,
"publishedAt": "ISO8601",
"updatedAt": "ISO8601",
"localizations": { /* */ },
"tags": ["string"]
}
```
**封面 / 缩略图(重要)**:前端封面取值顺序为 `attachments[0].thumbnailUrl``posterUrl`。后端应在 body JSON 中为每条资料提供可用的封面 / 缩略图:
- 图片:`thumbnailUrl`(压缩图);
- 视频:`posterUrl`(首帧 / 封面);
- 文档ppt/pdf 等):尽量提供后端生成的预览缩略图 `thumbnailUrl`;若暂时无法生成,前端会按**资料类型**渲染兜底封面(类型色渐变 + 类型图标),但**仍建议后端长期补齐文档缩略图**以获得最佳效果。
> 前端兜底仅为优雅降级;最终视觉效果依赖后端在 body 中提供真实封面 / 缩略图。
### 5.2 下载计数
下载行为发生时累加 `downloadCount`(排序输入)。
- 采集点:现有下载接口(前端通过 `downloadAttachment(postId, attachmentId)` 触发)。
- 实现建议:在现有下载端点内 `++downloadCount`,或提供 `POST /api/posts/:postId/attachments/:attachmentId/download` 返回文件并计数。
- 防刷建议(后端定夺):同一 IP / 设备在 N 分钟内对同一资源只计一次。
### 5.3 管理员推荐权重
- `Post` 增加字段 `adminWeight: number`(默认 `0`)。
- 后台资料编辑表单(`/api/admin/resources`)可设置该值,用于人工置顶热门。
### 5.4 Phase 2登记暂不实现
- **收藏**`POST` / `DELETE /api/posts/:id/favorite`,依赖登录 / 用户身份;累加 `favoriteCount`;提供收藏状态查询与收藏列表(支撑 Favorites 页)。
- **分享计数**:分享行为上报 `POST /api/posts/:id/share``++shareCount`
---
## 6. 后端内部字段(不对外暴露)
`downloadCount``favoriteCount``shareCount``adminWeight`,以及派生的 `popularityScore`。前端响应中**不返回**。
---
## 7. 开放问题(需后端 / 产品确认)
1. **下载接口的确切路径与契约**:前端 `downloadAttachment` 当前对应的后端端点是什么?计数挂在哪里?
2. **热度时间窗**:是「累计热门」还是「本周 / 近 30 天热门」?若要「本周精选」语义需按时间窗统计计数。当前命名「社群常用资料」默认**累计**。
3. **数量与分页**:首页固定 5 条Phase 2 独立热门页是否需要分页?
4. **防刷计数策略**的具体规则。
5. **预览实现**:图片 / 视频可直接用 `attachment.url` / `thumbnailUrl`文档类ppt/pdf在线预览是否已有渲染服务还是仅展示封面缩略图预览预计**不需要后端新接口**,待确认)
---
## 8. 验收标准
- `GET /api/posts?sort=popular` 按热度分降序返回,且响应中**无任何计数 / 分值字段**。
- 下载行为能累加 `downloadCount` 并反映到排序。
- 后台可设置 `adminWeight` 并影响排序。
- 前端首页区块呈现为榜单(含封面、名次、无数字),与「最新更新」「官方推荐」区块视觉区分明显。