fix: 完成 doco src layout 重构,文件移至 src/doco/ 子目录
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
# 主 project 答复 — 分钟收视回放子板块
|
||||
|
||||
> 版本:v1
|
||||
> 日期:2026-06-11
|
||||
> 作者:TPS 主 project 顾问 (Claude Opus 4.7) + 制片人 刘通
|
||||
> 状态:已采纳,待秒级 chat 接收并按本文件推进实现
|
||||
> 上一版:无
|
||||
> 对应文档:秒级收视 project《军事科技_分钟收视回放_子板块需求规格.md》v1(2026-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 + pgvector(1536 维)**,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 字段第一次导入时留空,后续走本地工具补传
|
||||
|
||||
### 建议 G:episodes 表是否要加视频 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 基于与制片人刘通的两轮对话整理生成,供秒级收视项目接收使用。*
|
||||
Reference in New Issue
Block a user