# 08 全链路复盘（功能拉通盘点）

> 时间：2026-10-03 ｜ 盘点对象：`/mnt/data/live-console`（Flask 单体，线上 `live.netf.top`）
> 前序：`07_工程回顾与落地盘点.md`（2026-09-28 基线）—— 本文是其后 5 天迭代（适当性分层、event_bus、大厅/房间页两轮重构、行情条 Mock、人卡融合）之后的现状复盘。
> **方法：只认证据** —— 路由表、sqlite 行数、pip list、access.log、systemd 单元、浏览器 DOM 实测。结论均附证据位。

---

## 一、一句话结论

**配置链、播放链、预告主链（注入/命中/恢复）、订阅通知链（站内 WS）四条链已拉通可跑；合规闸门、真实回放、生产级 WS 三条链仍未闭环。** 工程从「能演示」推进到了「半生产」，卡点集中在：闸门 0 调用点（P0）、回放全是 mock 数据、gunicorn sync worker 与 WebSocket 不兼容。

---

## 二、六链拉通矩阵

### 1️⃣ 配置链（后台配置 → 数据 → 前端展示）✅ 已拉通

| 环节 | 现状 | 证据 |
|---|---|---|
| 频道同步 | 182 频道 PolyV → `polyv_channel`/`live_room` | 表各 182 行；`/api/polyv/sync` |
| 预告 CRUD | 建/改/删/手动注入/手动恢复 | `/api/previews` ×5；preview 5 行（pending 3 / ended 2） |
| 板块/品种配置 | `room_tag`（sector/variety）→ 行情条 + 卡片标签 | ⚠️ **仅 1 个房间配了**（room_id=1：能源化工/原油），room_tag 共 2 行 |
| 适当性/VIP 配置 | `min_suit_level`(R 系列)/`min_vip_tier` 落库、后台可配 | 仅 3062764 填了 R3/VIP1，其余可见房间 NULL |
| 人员体系 | `researcher` 43 人 + `room_researcher` 关联 + fqc_no/icc_no/职务 | 房间页人卡五字段渲染正常（2026-10-03 实测） |
| 配置→展示一致性 | 预告流转（inject 覆盖 room.name）+ 关联品种 → 行情条/标签/标题同源 | 2026-10-02 行情条改造实测通过 |

### 2️⃣ 预告主链（T-30 注入 → 命中 → T+30 恢复）✅ 已拉通

| 段 | 现状 | 证据 |
|---|---|---|
| T-30 注入 | ✅ `preview_service.inject_preview` | 写 injected_at + status=live + 同步 PolyV；audit_log 有记录 |
| 命中检测 | ✅ `check_preview_hit` + `sync_preview_hits`，scheduler 60s | 写 hit_status/hit_at；audit_log `preview.missed` 有记录 |
| T+30 恢复 | ✅ `restore_room` | 写 restored_at + status=ended |
| 手动触发 | ✅ 新增 `/api/previews/{id}/inject|restore` + `/api/_demo/trigger_hit` | 2026-10-02 起可人工演练 |
| **hit → 通知** | ✅ **已接通（07 断链点 ① 已补）** | `check_preview_hit` 命中 → `event_bus.publish("preview.hit")` → 写 notification + WS 投送；notification 5 行（channel=ws, status=sent） |

### 3️⃣ 订阅通知链 ⚠️ 通了但不生产级

| 环节 | 现状 | 证据 |
|---|---|---|
| 前端预约 | ✅ room.html 生成 gid(localStorage) → `POST /api/previews/{id}/subscribe` | subscription 5 行（含真实 uuid gid） |
| 订阅管理 | ✅ subscribe/unsubscribe/subscriptions 三接口 | 路由 758/775/786 |
| 事件总线 | ✅ `event_bus.py` 进程内 pub/sub + flask-socketio 直投，预留 Redis Streams 切换缝 | app.py:41 import；Notification 审计副本落库 |
| WS 端点 | ⚠️ `/socket.io/` polling 200，但 **gunicorn `-w 2` sync worker**，WebSocket 升级挂不住 | systemd ExecStart 无 `-k gthread/eventlet` |
| 通知回指 | ⚠️ `notification.subscription_id` 恒 NULL | 5 行全 NULL，通知未关联订阅记录 |

### 4️⃣ 播放链（房间页播放/聊天/课件/统计）✅ 已拉通

| 环节 | 现状 | 证据 |
|---|---|---|
| 播放器 | ✅ polyvLivePlayer（resume/pause/volume/muted 全屏，方法名已实测校准） | room.html；控制台自适应 |
| 聊天室 | ✅ PolyvChatRoom + `POST /api/play/{cid}/chat-token`（form 代理） | 切互动 Tab 时才 init（坑已修） |
| 课件 | ✅ `GET /api/play/{cid}/docs` | isShowUrl=Y 取 fileUrl |
| 统计 | ✅ `GET /api/play/{cid}/stats`（v4 basic/get） | 在线/观看/点赞 |
| 房间页 UI | ✅ hero 叠加式 + 行情条 Mock + 频道信息融合卡（人卡行）+ Tab 卡 100dvh | 2026-10-02/03 三轮重构，双端 DOM 断言 + 截图验收 |

### 5️⃣ 回放链 ⚠️ 页面在、数据是 mock

| 环节 | 现状 | 证据 |
|---|---|---|
| 回放列表/推荐 | ✅ `/api/play/{cid}/playbacks`、`/api/replays/recommended`、`/playback/{vid}` 页面 | 大厅/房间页回放卡渲染正常 |
| 回放数据 | ❌ **playback 5 行全是 `mock-vid-00x`**，非真实 PolyV VOD | sqlite 实查 |
| ended → 生成回放 | ❌ `/webhook/polyv/status` 路由**仍不存在**；access.log `webhook` **0 次** | 07 断链点 ② **仍未补** |
| 就绪能力 | polyv.py 已有 `list_playbacks` + `get_playback_safe_token` | 缺编排层与回调接线 |

### 6️⃣ 身份鉴权链 ❌ 闸门仍未落下（P0）

| 环节 | 现状 | 证据 |
|---|---|---|
| 游客身份 | ✅ **已补**（07 半落地项）：room.html 生成/携带 gid，user 表按 gid upsert | room.html:388；`/api/play/*/chat-token?viewer_id=` |
| 适当性分层 | ✅ **R/C 双层已拍板落地**（09-28）：配置层 R1-R5，对客层 `suit_to_display()` 映射 C1-C5 | config.py + context_processor |
| 判定函数 | ❌ `check_view_permission` **仍然 0 调用点**（死代码） | `grep -rn` 仅 import 一处 |
| PolyV 回调闸门 | ❌ `/webhook/polyv/auth` 走 mock 固定放行，**不查房间门槛**；access.log 0 次调用 | audience 表 0 行 |
| 后果 | **拿到频道号仍能看** —— 与 04_RAG对查报告 P0 同源，至今未闭环 | — |

---

## 三、遗留真问题（较 07 的变化）

| # | 问题 | 07 状态 | 现在 | 性质 |
|---|---|---|---|---|
| 1 | 适当性 R/C 单位不一致 | ❌ 会全员被拒 | ✅ **已修**（配置 R / 对客 C，`suit_to_display` 映射 + `check_view_permission` 用 R 比较） | 已闭环 |
| 2 | 闸门三处断链 | ❌ | ❌ **仍在**（判定 0 调用点、auth/check mock、webhook mock） | **P0 未闭环** |
| 3 | 根路径给了后台 | ❌ `/` → `/console` | ❌ **仍在**（app.py:160-162） | 小问题 |
| 4 | 通知链路全无 | ❌ | ✅ **已补**（event_bus + subscription/notification + 前端预约） | 已闭环 |
| 5 | WS 依赖缺失 | ❌ 三件套未装 | ⚠️ **装了一半**（flask-socketio 已装；redis/eventlet 未装，gunicorn 仍 sync×2） | 半闭环 |
| 6 | 回放断链 | ❌ | ❌ **仍在**（无回调、无 playback_service，数据 mock） | **P1 未闭环** |
| 7 | publisher / polyv_anchor_id 字段 | ❌ 缺 | ❌ **仍缺**（PRAGMA 确认 live_room 25 列无此二者） | 数据完整性 |
| 8 | 控制台状态卡文案过期 | ⚠️ | ⚠️ **仍在**（console_index.html:106「阶段2 待做」把已完成项列在待做） | 文案 |

---

## 四、待确认问题清单（留给隽侬拍板）

> 按优先级排。每条给出「问题 + 我的倾向 + 需要你说的点」。

| # | 优先级 | 问题 | 我的倾向 | 待你定 |
|---|---|---|---|---|
| Q1 | **P0** | **闸门何时接线？** 判定函数就绪但 0 调用点，现在拿到频道号就能看，合规上站不住 | 尽快接进 `/live/{cid}` 房间页入口 + `/webhook/polyv/auth`，改动集中成本低 | 接线时机；未登录/等级不足用户给「拦截页」还是「引导页」 |
| Q2 | **P0** | **真实回放链路**：✅ 已取证（2026-10-03 用 `v4/user/global-setting/callback/get` 查实）——**两边都缺**：PolyV 后台回调全空（playbackCallbackUrl / streamCallbackUrl / recordCallbackUrl 均 null），应用侧只建了 `/webhook/polyv/auth`、`/webhook/polyv/status` 未建，access.log webhook 0 调用 | ① 应用补 `/webhook/polyv/status` 路由（验签 + ended→playback 落库）② 调 `v4/user/global-setting/callback/set` 或 PolyV 后台把回调指到 `live.netf.top/webhook/polyv/status` ③ 灰度用 1 个频道开播下播验证 | 无需再查后台；只需拍板何时排 |
| Q3 | P1 | **WS 生产化**：gunicorn sync worker 挂不住 WebSocket，现靠长轮询兜底。换 `gthread`/`eventlet` worker 还是现阶段接受长轮询？ | 阶段1 用户 ≤100，长轮询够用；上 Redis Streams 时再换 eventlet，一次到位避免两次折腾 | 接受长轮询 or 现在就换 worker |
| Q4 | P1 | **房间配置覆盖**：可见房间 8 个，只有 3062764 配了板块/品种/分级门槛。其余 7 个要不要补？不补则无标签、无门槛、无行情条 | 批量补默认值（至少品种+板块），行情条/卡片才完整 | 补哪几个房间、各配什么品种/门槛 |
| Q5 | P2 | **根路径** `/` → `/console`，观众进来看到的是管理后台 | 改为 `/` → `/live`，后台入口挪 `/console` | 确认即可 |
| Q6 | P2 | **通知回指**：notification.subscription_id 恒 NULL，通知没关联订阅记录，后续做「通知历史/补推」会断 | 补上关联写入（改动小） | 确认要做即可 |
| Q7 | P2 | **人员体系字段**：`publisher`（主持人字符串）/`polyv_anchor_id`（主播实体）两字段仍未落库，人卡的「主持人」目前靠 room_researcher.role 模拟 | 二者都是 PolyV 侧能力（换绑主播、频道展示主持人），若只做自有后台展示可以再等 | 是否需要真绑 PolyV 主播实体 |
| Q8 | P2 | **回放封面**：回放卡封面继承 preview.cover_url 的方案（DESIGN v2 待解项）还没定，现在 mock 无封面 | 继承预告封面 + 无封面时用房间 default-room.svg 兜底 | 确认继承方案 |
| Q9 | P2 | **适当性/VIP 真实数据源**（阶段3 SSO）：user.suit_level 现在是 mock（默认 R4），真实用户等级从哪来、何时接 | 阶段3 再定，先把闸门接线做好，数据源留缝 | 阶段3 排期 |
| Q10 | P3 | **版本控制**：无 .git，回滚靠 7 个 .bak 文件 | `git init` + 首提交，.env 进 .gitignore，成本 5 分钟 | 确认要做即可 |
| Q11 | P3 | **控制台状态卡文案过期**（「阶段2 待做」含已完成项），且 mock-vid 回放混在正常数据里，运营看板会误导 | 顺手修文案；mock 数据加标记或单独演示环境 | 确认要做即可 |

---

## 五、五天迭代回顾（09-28 → 10-03 做了什么）

1. **09-28** 适当性分层拍板落地：配置层 R1-R5 / 对客层 C1-C5 映射，`suit_to_display` 注入模板
2. **10-02** 大厅 `/live` 三模块重构：Banner 轮播 → 预告卡（pending 升序）→ 大厅（直播中优先+回放降序）
3. **10-02** 房间页 hero 叠加式重构：深色 hero + 行情条 + 频道卡 + Tab 卡 100dvh，移动端 display:contents 重排
4. **10-02** 行情条改造：新结构「品种名+合约数字+涨跌幅%」，涨无 + 号，Mock 行情（品种来自关联品种字段，配置与显示一致）
5. **10-02** 回放/推荐模块下边距收口：`1fr`→`auto` 行高，四象限底边对齐
6. **10-03** 人卡改造：「一句话看懂」→ 直播标题；主持人/嘉宾每人一张矩形卡（头像/名字/职务/身份/职业编号）
7. **10-03** 频道卡与人卡融合单卡：上=频道信息区，下=人卡行（单行并排可横滑），info-swipe 移除

---

_复盘人：拾光 ⟡ ｜ 本文只陈述证据与差异。Q1–Q11 待隽侬逐条拍板，拍完即可排下一轮迭代。_
