feat(admin): 新增观看记录分页与评论分集信息

This commit is contained in:
Zhou Weidong committed 2026-10-21 16:35:26 +08:00
1 parent d52b805adf
commit 1d316791b1
14 files changed
+953 -7

No files matched your search

+5 -1
View File
@@ -590,6 +590,7 @@ GET /app/notices?pageIndex=1&pageSize=20
| GET | `/admin/app-users/{id}` | `app-user:list` | 详情 |
| GET | `/admin/app-users/{id}/ban-records` | `app-user:list` | 封禁与申诉记录 |
| GET | `/admin/app-users/{id}/watch-history` | `app-user:list` | 观看流水明细(带剧名/集号,客服核对用) |
| GET | `/admin/watch-history/page` | `watch-history:list` | 跨用户观看记录分页:keyword、userId、dramaTitle、dramaId、episodeId、source、finished、startTime、endTime |
| PUT | `/admin/app-users/{id}/status` | `app-user:update` | 改状态:normal/limited/banned |
状态处置会**立即吊销该用户全部会话**并写入封禁记录,避免"封了还能用"。
@@ -607,7 +608,7 @@ GET /app/notices?pageIndex=1&pageSize=20
| 方法 | 路径 | 权限点 | 说明 |
| --- | --- | --- | --- |
| GET | `/admin/comments/page` | `comment:list` | 检索评论,`status=pending` 即审核队列 |
| GET | `/admin/comments/page` | `comment:list` | 检索评论;`status` 为空返回全部,`pending` 即审核队列 |
| GET | `/admin/comments/{id}/audit-records` | `comment:list` | 审核留证:机审与人审的完整链路 |
| PUT | `/admin/comments/{id}/audit` | `comment:audit` | 通过 / 驳回(带原因码与说明) |
| DELETE | `/admin/comments/{id}` | `comment:audit` | 删除评论 |
@@ -616,6 +617,9 @@ GET /app/notices?pageIndex=1&pageSize=20
| GET | `/admin/sensitive-words/page` | `sensitive-word:list` | 敏感词检索 |
| POST/PUT/DELETE | `/admin/sensitive-words[/{id}]` | `sensitive-word:update` | 维护词库,改动即时生效(服务端缓存失效重建) |
后台评论行除 `dramaId/episodeId` 外,还返回 `dramaTitle/episodeNo/episodeTitle`;
剧或集已删除时对应展示字段留空。后台评论与举报的 `status` 空值均表示全部状态。
### 2.6 订单与权益(已实现)
| 方法 | 路径 | 权限点 | 说明 |
+114
View File
@@ -0,0 +1,114 @@
# K91 后台观看记录独立菜单、评论分集展示与全部状态筛选
## 目标
- FruitServer 新增跨用户观看记录分页接口,并给后台评论补充短剧名、集号与集标题。
- ReelShortWeb 新增「观看记录」独立页面,评论/举报状态筛选默认展示全部。
- 迁移脚本只提交文件,不执行数据库变更;不改 specs 仓库和 Flutter 客户端。
## 分支
- FruitServer:`feat/k91-watch-history`,从 `origin/develop` 创建。
- ReelShortWeb:`feat/k91-watch-history-page`,从 `origin/develop` 创建。
## A. FruitServer
### A1 观看记录分页
1. 新增 `WatchHistoryQueryReqVO`,字段:
`pageIndex/pageSize/keyword/userId/dramaTitle/dramaId/episodeId/source/finished/startTime/endTime`。
2. 新增 `AdminWatchHistoryVO`,返回用户、短剧、分集、进度、完成、来源、设备与观看时间。
3. 新增 `WatchHistoryAdminService`,直接注入:
- `WatchHistoryMapper`
- `AppUserMapper`
- `DramaMapper`
- `DramaEpisodeMapper`
4. 查询流程:
- `keyword` 先批量命中 `app_user.uid/nickname` 的 id;无命中直接空页。
- `dramaTitle` 先批量命中 `drama.title` 的 id;无命中直接空页。
- 精确 id 条件与模糊命中集合取交集。
- `finished` 在 SQL 层表达,允许区间两侧都落在 `duration_ms = 0` 等边界。
- 按 `watched_at DESC, id DESC` 排序。
- 对结果页的用户、剧、集各做一次批量查询后装配,禁止逐行查询。
5. 新增 `WatchHistoryAdminController`,权限点 `watch-history:list`,保留旧用户详情观看流水接口。
### A2 评论后台分集信息
1. `CommentRespVO` 增加 `dramaTitle/episodeNo/episodeTitle`。
2. 仅 `CommentService.adminPage` 对当前页批量补剧、集信息。
3. `toRespList` 的 C 端路径保持不增加查询。
### A3 SQL 与契约
1. 新增幂等迁移 `sql/migrate-k91-watch-history-menu.sql`:
- 权限点 `1105 watch-history:list`
- 菜单使用 id `34`,挂 parent `15`
- `component=views/userManagement/WatchHistoryView`
- 超管角色权限与菜单关联
2. 同步 `sql/data-phase1.sql`。
3. 更新 `docs/api-phase1.md` §2.3、§2.5。
### A4 测试
- `WatchHistoryAdminServiceTest` 覆盖:
- 默认分页与排序
- keyword 用户命中
- dramaTitle 剧名命中
- finished 真/假 SQL 条件
- 时间范围
- 命中集合为空直接空页
- pageSize 上限收敛为 100
- `CommentServiceTest` 覆盖后台页批量补齐剧名、集号、集标题。
- 门禁:`mvn test` 全模块通过。
## B. ReelShortWeb
### B1 类型/API
- 扩展 `WatchHistoryItem`:`userId/uid/nickname/episodeTitle`。
- 扩展 `CommentItem`:`dramaTitle/episodeNo/episodeTitle`。
- `appUser.ts` 新增 `pageWatchHistoryApi(params)`。
### B2 观看记录页面
- 新建 `src/views/userManagement/WatchHistoryView.vue`:
- 用户、短剧名称、来源、完成状态、时间范围筛选。
- 观看时间、用户、短剧、分集、进度、完成、来源、设备列。
- 10/20/50 分页。
- 复用 App 用户页的 `panel/console-toolbar/pagination/app-user-*` 视觉与格式化函数。
### B3 评论/举报全部状态
- 评论与举报状态首项增加 `{ value: '', label: '全部状态', tag: 'info' }`。
- 两个筛选默认值改为空串,请求时空串转 `undefined`。
- 评论表以「短剧 / 分集」替换短剧 ID 单列:
- 显示剧名与集号/集标题。
- 缺少剧名时回退短剧 id。
- 缺少集号时回退分集 id;历史 `episodeId=0` 显示未关联分集。
- 原始短剧 id / 分集 id 通过 tooltip 保留。
### B4 门禁
- `pnpm ts:check`
- `pnpm build:dev`
## 风险与待确认
1. `watch_history` 是月分区表,现有索引为 `(user_id, watched_at)` 与
`(drama_id, watched_at)`,没有跨用户的全局 `watched_at` 索引。本次按要求实现跨用户时间排序,
不擅自新增索引;数据量增长后由 PM 评估是否增加全局观看时间索引。
2. 用户/剧名模糊检索先取 id 集合,符合“命中为空不退化成全表”的要求;
超大关键词命中集合的批大小由后续实际数据量评估,本次不擅自加截断以免漏结果。
3. 历史评论的 `episode_id=0` 不回填;后台显示“未关联分集”,原始 id 仍保留在 tooltip。
4. 迁移脚本只写文件,不执行数据库;菜单落库由 PM 按发布流程执行。
5. 任务书建议菜单 id `26`,但当前 `data-phase1.sql` 已将 `26` 用作“创作者中心”目录,
`27-30` 为其子菜单。为避免覆盖线上已有菜单树,本次使用下一个空闲 id `34`;
父级、路由、组件与权限点均不变。
## 提交与合并
- FruitServer 提交:`feat(admin): 新增观看记录分页与评论分集信息`
- ReelShortWeb 提交:`feat(admin): 观看记录独立菜单与治理状态全部筛选`
- 两仓库均 `--no-ff` 合回 `develop` 并 push。
- 作者与提交者:`Zhou Weidong <502333560@qq.com>`。
- 禁止 `git add -A`,所有文件逐项暂存。
+69
View File
@@ -23782,3 +23782,72 @@ $ flutter test --no-pub
```
说明:本任务仅修改 ReelShort 客户端,未改 FruitServer 功能代码、specs 仓库或后台接口;未安装真机,等待用户验收。
## 2026-10-21 K91 后台观看记录、评论分集与全部状态筛选
- 已完整读取 `docs/plans/INBOX.md`、`AGENTS.md`、`CODING_STANDARDS.md`、`GIT_WORKFLOW.md` 及相关契约/代码结构。
- 已创建 FruitServer 分支 `feat/k91-watch-history` 与 ReelShortWeb 分支 `feat/k91-watch-history-page`,均基于最新 `origin/develop`。
- 已先写计划文档 `docs/plans/2026-10-21-K91-watch-history.md`,其中记录 A/B 实施步骤、测试矩阵、迁移边界和风险。
- 本轮计划只提交 SQL 迁移文件,不执行数据库变更;不改 specs 与 Flutter 客户端。
- 勘察发现任务书建议的菜单 id `26` 已被“创作者中心”目录占用(`27-30` 为其子菜单);
为避免覆盖现有菜单树,采用下一个空闲 id `34`,仍挂 parent `15`,其余菜单字段按任务书执行。
- 已完成 A1/A2 主体代码:新增观看记录查询/返回 VO、admin-api 分页服务与控制器;
评论响应增加剧名/集号/集标题,只在后台 `adminPage` 当前页批量装配。
- 已补 `WatchHistoryAdminServiceTest` 与 `CommentServiceTest`,待执行定向 Maven 测试确认。
- 定向测试已通过:
```text
$ JAVA_HOME=<jdk21> mvn -pl fruitshorts-admin-api -am \
-Dtest=WatchHistoryAdminServiceTest,CommentServiceTest \
-Dsurefire.failIfNoSpecifiedTests=false test
[INFO] fruitshorts-admin-api ... SUCCESS
[INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
```
解读:观看记录默认分页、模糊命中、完成条件、时间范围、空命中与 pageSize 收敛均通过;
评论后台页的剧名/集号/集标题批量装配通过。
- 已完成 A4/A5:新增 `sql/migrate-k91-watch-history-menu.sql`,同步 `sql/data-phase1.sql`
的权限 1105、菜单 34 与超管授权;更新 `docs/api-phase1.md` §2.3/§2.5。
- 迁移脚本只创建文件,未执行数据库变更。菜单 id 调整原因已写在迁移注释、计划和本节留痕中。
- 下一步执行 FruitServer 全模块 `mvn test` 门禁;通过后再做 ReelShortWeb。
- FruitServer 全模块门禁已通过:
```text
$ JAVA_HOME=<jdk21> mvn test
[INFO] fruitshorts-admin-api .............................. SUCCESS
[INFO] fruitshorts-app-api ................................ SUCCESS
[INFO] fruitshorts-transcode-worker ....................... SUCCESS
[INFO] BUILD SUCCESS
[INFO] Total time: 16.813 s
```
解读:本次运行包含全部 14 个 Reactor 模块,新增观看记录/评论分集测试与既有后端测试全过;
`mvn test` 不执行数据库迁移,K91 SQL 文件仍未落库。
- 已开始 B:Web `WatchHistoryItem`/`CommentItem` 扩展字段,`appUser.ts` 增加
`pageWatchHistoryApi`;新建 `WatchHistoryView.vue`;评论/举报状态默认改为全部,
评论表改为展示「短剧 / 分集」并通过 tooltip 保留原始 id。
- ReelShortWeb 门禁已通过:
```text
$ pnpm ts:check
> fruitshorts-admin@1.0.0 ts:check
> pnpm vue-tsc --noEmit --skipLibCheck
exit 0
$ pnpm build:dev
> fruitshorts-admin@1.0.0 build:dev
> VITE_CJS_IGNORE_WARNING=1 vite build --mode dev
Build successful. Please see dist-dev directory
```
解读:新增观看记录页面与治理页改动通过类型检查和 dev 构建。构建保留既有
`element-plus` circular chunk 警告,不影响成功退出;未修改依赖或锁文件。
- 额外对 K91 修改的 Vue/TS 文件运行定向 ESLint,零错误:
```text
$ pnpm exec eslint src/api/admin/appUser.ts src/api/admin/types.ts \
src/views/governance/ContentGovernanceView.vue \
src/views/userManagement/WatchHistoryView.vue
exit 0
```