Files
tps-dashboard/docs/cross_project/分钟收视回放/分钟收视回放_主project答复_v1.md
T

365 lines
16 KiB
Markdown
Raw 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.
# 主 project 答复 — 分钟收视回放子板块
> 版本:v1
> 日期:2026-06-11
> 作者:TPS 主 project 顾问 (Claude Opus 4.7) + 制片人 刘通
> 状态:已采纳,待秒级 chat 接收并按本文件推进实现
> 上一版:无
> 对应文档:秒级收视 project《军事科技_分钟收视回放_子板块需求规格.md》v12026-06-10
---
## 一、本文件用途
回复秒级 chat 那份 PRD 第八节的 6 个对接问题,并把主 project 这边的**红线、修订建议、交付物期待**全部白纸黑字写下来。本文件是子板块继续推进的**最终输入**,秒级 chat 这边可基于此开干。
子板块结束前,要按本文件第九节的清单产出**五份交付物**给主 project。主 project 这边的 Cline 拿着五份交付物落代码,完成最终整合。
---
## 二、对 6 个对接问题的最终答复
### 1. TPS 工作台有没有"每期节目详情页"?
**没有。子板块需要附带把详情页骨架建起来。**
现状:仪表盘 (Dashboard) 是聚合视角,责编录入页 (EditorDesk) 是表单 + 列表,**没有"看单期 + 该期所有维度"的页面**。分钟收视回放需要这个容器,整个工作台早晚也需要这个页面,借这次一起做掉。
入口规划:
- 仪表盘柱图每根柱子点进去 → 详情页
- EditorDesk 列表行点进去 → 详情页
- 路由建议:`/episodes/:id``:id``episodes.id`SERIAL 主键)
详情页骨架要预留位置承载未来其他维度(审片意见、文稿、外拍信息等),分钟收视回放是其中**第一个模块**。
### 2. 数据库技术栈
**PostgreSQL 16 + pgvector1536 维)**ORM 是 **SQLModel(同步,非 async**
手写 SQL 走 `backend/sql/00X_*.sql`,不用 Alembic。
第五节那两张表的接入方式见第四节"数据模型修改建议"——简短版:**别新建"节目期次表",复用现有 `episodes` 表**;分钟数据表新建,命名 `episode_minute_ratings`,外键挂到 `episodes.id`
### 3. 视频和截图存储方案
**最终决策:视频不入工作台。**
- 视频本体由制片人在本地/百度网盘/极空间多渠道自存
- 工作台只接收**截图**(27 张 jpg)
- 不再讨论服务端 ffmpeg、视频压缩、转码删源片等服务端方案
截图处理走**本地切图工具**(子板块产出,详见第五节):
- 责编本地双击工具 → 拖入源片 → 自动切 27 张 480p 截图 + 命名好
- 责编打开工作台 → 一键多文件上传截图(~5 MB 一次传完)
截图存储:服务器文件系统 `/screenshots/{episode_id}/{分钟序号_两位数}.jpg`,数据库只存 URL。
### 4. 前端技术栈
**React 18 + Vite + Ant Design 5 + Zustand**JavaScript(不用 TS),项目宪法锁定。
图表库选型:
- **优先 @ant-design/charts**:与现有 AntD 5 视觉血缘最近,配色和圆角自然贴合
- **次选 ECharts**:自定义 tooltip 模板灵活成熟
- **已用过 Recharts**:仪表盘柱图已采用
**不要再引第三方图表库**。三选一即可,最终选哪个由 Cline 在 Plan 阶段定。
### 5. 后台异步任务怎么跑
**在"视频不入工作台 + 本地切图工具"决策下,服务端没有重型异步任务。**
工作台后端只接收截图入库 + 跑数据校验(见第四节建议 E),都是毫秒级同步操作,**FastAPI BackgroundTasks 都用不上**。
如果未来某个新场景确实需要异步任务,再启用 FastAPI BackgroundTasks。**不引 Celery、不引 Redis 队列**——8 人栏目用这些是过度工程。
### 6. 录入身份/权限
**有完整用户系统**Session + Cookie 认证,三角色拼音枚举锁定(`zhipianren` / `zebian` / `biandao`)。
写权限规则参照 `yearly_targets` 既有口径平移:
- **POST/PATCH/DELETE 录入分钟数据 + 上传截图**:`zhipianren` + `zebian` 可写,`biandao` 返回 403
- **GET 查看分钟回放**:三角色均可读
**实现细节**FastAPI 后端直接从 session 拿 user_id 写入 `created_by` 字段,**前端不要把"录入人"作为字段提交**。
字段命名用 `created_by INTEGER REFERENCES users(id)`**不要用 string 类型的"录入人姓名"**——主 project backlog 里有一条 "操作留痕 schema"(待办池 B2),分钟收视这张新表作为落地先例。
---
## 三、视频/截图最终方案(决策落地)
### 责编一周一期的标准流程(最终版)
```
周二 21:20-21:47 节目播出
周二 22:00 后 责编到总编室账号抄 27 个份额数字(保留原方案)
次日 责编打开本地切图工具
拖入当期源片 mp4 → 工具自动切 27 张 480p jpg
+ 自动命名为 01.jpg ~ 27.jpg
责编登录工作台 → 进入"节目期次"管理
→ 选择当期 episode(基于已录入的 episodes 记录)
→ 进入分钟收视模块
上传 27 张截图(多文件选择 / 拖拽)
→ 服务器存到 /screenshots/{episode_id}/
→ 数据库写入 27 条 episode_minute_ratings 记录
录入 27 个份额数字
(推荐:"批量粘贴一列数字"输入框,
从 Excel 复制 27 个数字粘贴后系统按行切分)
→ 系统软校验(数据齐全?范围合理?均值与已录全期均值吻合?)
→ 保存
该期详情页里"分钟收视回放"模块即刻可看
```
### 主 project 这边不做的事
- 服务端 ffmpeg(不需要)
- 视频上传接口(不需要)
- 视频压缩转码(不需要)
- 异步任务队列(不需要)
- 视频删除/清理脚本(不需要)
---
## 四、数据模型修改建议(主 project 在此明确给出)
> 任何 schema 改动**必须经主 project 顾问 (Opus) 审、配回补方案,Cline 不得自行动手**。这是项目红线。下面是建议方案,最终落地前还会过一遍审查。
### 建议 A:复用现有 `episodes` 表,**不新建"节目期次表"**
现有 episodes 表已涵盖你需要的全部"节目期次"信息:
| 你的字段 | 对应现有 episodes 字段 |
|---|---|
| 期次主键 | `id`SERIAL |
| 期数显示 | 前端从 `air_date` + `episode_number` 拼,不入库 |
| 节目名称 | `program_name` |
| 播出日期 | `air_date` |
| 播出时段 | 不入库,前端常量 "21:20-21:47" |
| 备注 | `notes` |
理由:新建一张冗余表会割裂 episodes 与其他模块(收视成绩、外拍、未来选题、审片意见)的关联,破坏单一事实源。
### 建议 B:用 `episodes.id`INTEGER)做外键,**不用"播出日期 string"做主键**
秒级 chat v1 文档建议"期次主键用 `2026-06-09` 字符串"。这与 `episodes.id SERIAL` 体系冲突。
最终方案:分钟数据表用 `episode_id INTEGER REFERENCES episodes(id)` 外键,所有展示字符串("2026 年第 23 期 · 2026-06-09")由前端从 episodes 数据拼出,不入库。
### 建议 C`收视份额` 用 `NUMERIC(6,4)`**不用 float**
与现有 `episodes.audience_share NUMERIC(6,4)` 类型对齐,避免浮点比较的怪事。
### 建议 D:新表 `episode_minute_ratings` 建议 schema
```sql
CREATE TABLE IF NOT EXISTS episode_minute_ratings (
id SERIAL PRIMARY KEY,
episode_id INTEGER NOT NULL REFERENCES episodes(id) ON DELETE CASCADE,
minute_index INTEGER NOT NULL CHECK (minute_index BETWEEN 1 AND 27),
audience_share NUMERIC(6,4) NOT NULL,
screenshot_url VARCHAR(500),
created_by INTEGER NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(episode_id, minute_index)
);
CREATE INDEX idx_minute_ratings_episode ON episode_minute_ratings (episode_id);
```
P1+ 扩展(多期对比、批注/标签):1.0 不建表,到 P1 触发时再说。当前 UNIQUE 复合键和外键设计已留好扩展空间。
### 建议 E:工作流补一个"软校验"环节
录入 27 个分钟份额时,系统应做**非阻塞**的合理性提示:
- 27 个数字是否齐?
- 最大值/最小值是否在合理区间(如 0-3)?
- 27 个数字的平均值是否与已录的 `episodes.audience_share`(该期全期均值)大致吻合?误差 > 30% 给"数据可能录错"提示
不阻塞保存,只是温柔提醒。理由:分钟数据是栏目考核依据,权重最高,录错一个小数点不发现就一直错。
### 建议 F:批量导入接口复用现有 ExcelService
23 期历史数据一次性导入:复用主 project 已有的 ExcelService 框架(Phase 2 Task 2 跑通),但单开一个 endpoint:
- 上传一份"期次 × 27 列分钟份额"的 Excel
- 按行展开成 23 × 27 = 621 条 `episode_minute_ratings` 入库
- 截图 URL 字段第一次导入时留空,后续走本地工具补传
### 建议 Gepisodes 表是否要加视频 URL 字段?
**不加。**
因为视频不入工作台。如果未来某天想记录"这一期视频存在哪个网盘 / 哪个本地路径",可以走 `episodes.notes` 字段写自由文本,不需要专门字段。
---
## 五、本地切图工具规格(子板块产出物之一)
子板块的 Claude 负责设计与实现这个工具。
### 5.1 形态
- 一个 Windows 上能跑的可执行文件(py 源码 + pyinstaller 打包成 exe
- 双击即用,无安装步骤
- 不依赖网络,不依赖工作台,完全离线
- 不需要责编装 Python 环境
### 5.2 用户界面
简洁到极致:
- 一个窗口,拖文件进去即可(或"选择文件"按钮)
- 接收 mp4 / mov / mkv 等常见格式
- 进度条显示切图进度
- 完成后弹"已生成 27 张截图于 [输出文件夹]"
- 自动打开输出文件夹
### 5.3 切图规则(与秒级 chat v1 文档保持一致)
```bash
# 27 张截图,每分钟第 30 秒位置,480p (854 × 480)
for i in $(seq 0 26); do
sec=$((i*60+30)) # 0:30, 1:30, 2:30, ..., 26:30
ffmpeg -i 源片.mp4 -ss $sec -vframes 1 -vf scale=854:480 \
"$(printf "%02d" $((i+1))).jpg" -y
done
```
输出文件名规则:**`01.jpg` ~ `27.jpg`**(两位数,零填充,便于排序)。
### 5.4 输出文件夹组织
工具自动新建一个文件夹,命名建议:`截图_{源片文件名去后缀}_{日期}/`,里面 27 张 jpg。
### 5.5 ffmpeg 依赖
打包时把 ffmpeg.exe 一并塞进 exe,或者用 `imageio-ffmpeg` 包自动下载。**绝对不要让责编手动装 ffmpeg**。
### 5.6 错误处理
- 源片读不到 → 弹窗"文件无法读取,请检查格式"
- 源片时长 < 26 分 30 秒 → 弹窗"视频时长不足 27 分钟,是否继续?"(允许跳过缺失分钟)
- 输出文件夹已存在 → 自动加时间戳后缀
### 5.7 给责编的使用说明
子板块产出一份 `使用说明.md`,傻瓜级,要有截图。预期长度 200-400 字 + 3-5 张截图。
---
## 六、主 project 红线(不可越)
子板块设计与实现过程中,下面这几条是**主 project 宪法**,任何方案不得违反:
1. **改 schema 须主 project 顾问 (Opus) 审**:包括新建表、改字段、加字段。Cline / 子板块 Claude 不得自行动手。
2. **角色枚举锁定拼音值**`zhipianren` / `zebian` / `biandao`,不许新增枚举,不许用英文别名。
3. **AI 给方向不给答案**:分钟收视回放的 P1+ 功能(多期对比找规律、批注 AI 建议等)若涉及 AI,必须保持"建议草稿 + 制片人审核"的三档置信度,不得 AI 直接拍板。
4. **编导关联用"软引用 + 快照"**:本子板块如需展示编导信息,沿用 `episodes.editor_id` + `episodes.editor_name_snapshot` 双字段,不许新增编导关联字段。
5. **收视颜色判定**:红=优秀(>摸高目标)/ 蓝=达标 / 绿=待提升(<基础目标)。反直觉规约,分钟收视回放折线图如果上色,按此规则。
6. **AI 输出必须有"忽略 / 我来改写"否决权**:任何 AI 建议(如本子板块 P1+ 的 AI 找规律功能)必须给编导否决入口。
7. **不引新依赖**:图表库三选一(@ant-design/charts / ECharts / Recharts),不引第四个;后端不引 Celery / Redis 队列。
---
## 七、子板块产出物清单(最终交付包)
子板块结束前,请凝结成以下**五份交付物**,作为整体交付给主 project:
### 产物 1:决策摘要 md
记录子板块全程的关键决策。每条决策三句话:
```
决策 X[一句话决策内容]
- 背景:为什么需要这个决策
- 拍板理由:选这条不选那条的理由
- 拍板人:[制片人 / 主 project 顾问 / 子 project Claude 建议+制片人采纳]
```
10-20 条决策足以讲清整个子板块"为什么这么做"。
### 产物 2:接口约定 md(最技术、最精确)
把子板块与主 project 接驳的所有"接口"白纸黑字写出来:
- **数据接口**:新建表 / 字段 / 类型 / 约束(细化到 SQL DDL 级别)
- **API 接口**:新增 endpoint URL / 方法 / 请求体 / 响应体 / 错误码
- **UI 接口**:在主 project 哪个页面挂载、入口、路由
- **权限接口**:哪些角色可以做什么操作
- **存储接口**:截图存到哪个目录、命名规则、URL 拼接规则
要具体到"主 project 的 Cline 拿着这份就能写代码"的程度。**这是子 project 给主 project 的"合同"**。
### 产物 3:本地切图工具完整包
- `screenshot_tool.py`:源码,注释齐全
- `screenshot_tool.exe`:打包好的可执行文件,责编双击即用
- `使用说明.md`:傻瓜级文档 + 截图
工具规格见本文件第五节。
### 产物 4:未尽事项 backlog
诚实写出"子板块讨论中提到但没做的事"。每条三行:
- 是什么
- 为什么没做(暂缓 / P1+ / 等条件成熟)
- 触发时机(什么时候应该捡起来)
放进主 project 的 backlog 池子里。
### 产物 5:给主 project Claude 的"接手提示词"
一两段话,告诉主 project 顾问"如果你是接手这件事的 Claude,最重要的三件事是 X、Y、Z"。
这次至少要包含:
- 复用 episodes 表,不新建节目期次表
- 权限沿用 yearly_targets 口径
- 本地切图工具与工作台零耦合,不在工作台 UI 里给它留接口
---
## 八、跨 project 协作规矩(子板块这边也要遵守)
1. **不动主 project 代码**:子板块产出文档 + 独立工具,不写主 project 的实际代码。代码合入由主 project 的 Cline 完成。
2. **遇到吃不准的事回主 project 问**:本次 v1 文档第八节就是好榜样,继续保持。
3. **每份跨 project 文档顶部带元信息块**:版本、日期、作者、状态、上一版、主要变化(v2 以上必填)。
4. **一份文档只谈一件事**:不要在分钟收视回放交付包里夹带其他议题。
---
## 九、给秒级 chat Claude 的明确动作清单
收到本文件后,请按下面顺序推进:
1. **吸收本文件所有决策与红线**,回到秒级 chat 的 PRD v1,把不一致处标注出来(如果有)
2. **如有需要修订的地方,出 PRD v2**,顶部元信息块写明跟 v1 的变化点
3. **设计本地切图工具**:与制片人讨论用户体验细节,定稿后凭工具规格让秒级 chat 的 Cline 实现(如果有)或制片人自己找 v0/Lovable 等工具生成 demo
4. **凝结成最终五份交付物**(第七节清单)
5. **交付给制片人**,由制片人带回主 project,主 project 顾问 (Opus) 审一遍,无冲突后主 project 的 Cline 落实施
---
## 十、附:版本演进规约
本文件未来如修订(v2+),顶部元信息块"主要变化"必须写清楚改了什么。
历史版本不覆盖,旧文件保留在 `docs/cross_project/` 目录(主 project 这边)以便回看决策史。
---
*本文件由主 project 顾问 (Claude Opus 4.7) 于 2026-06-11 基于与制片人刘通的两轮对话整理生成,供秒级收视项目接收使用。*