Browse Source
Break API, Monitor, and MediaView call-site updates into bite-sized tasks with repo-wide verification.main
1 changed files with 211 additions and 0 deletions
@ -0,0 +1,211 @@ |
|||||
|
# Live Play-URL streamSessionId Implementation Plan |
||||
|
|
||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
||||
|
|
||||
|
**Goal:** 让所有直播 play-url 请求必带 `streamSessionId`,对齐后端新契约。 |
||||
|
|
||||
|
**Architecture:** 小范围契约变更。`getLivePlayURL` 增加必传 `sessionId` 并用 axios `params` 发送;`useMonitorLive.refreshPlayURL` 与 `MediaView.openLive` 两处调用补齐 `session.id`;无 session 时不发请求。`urls.LIVE_PLAY_URL(dockId)` path 签名保持不变。 |
||||
|
|
||||
|
**Tech Stack:** Vue 3、axios `src/utils/http`、现有 live API / urls 常量 |
||||
|
|
||||
|
**Spec:** `docs/superpowers/specs/2026-09-02-live-play-url-session-id-design.md` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## File map |
||||
|
|
||||
|
| 文件 | 职责 | |
||||
|
|---|---| |
||||
|
| `src/api/live.js` | `getLivePlayURL(dockId, sessionId)` 带 `params.streamSessionId` | |
||||
|
| `src/composables/useMonitorLive.js` | `refreshPlayURL` 守卫 + 传 `live.session.id` | |
||||
|
| `src/views/MediaView/MediaView.vue` | `openLive` 传 `result.session.id`;缺 id 时 toast | |
||||
|
|
||||
|
无测试框架;用全仓检索 + `npm run build` 验收。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 1: API + Monitor 调用 |
||||
|
|
||||
|
**Files:** |
||||
|
- Modify: `src/api/live.js` |
||||
|
- Modify: `src/composables/useMonitorLive.js` |
||||
|
|
||||
|
- [ ] **Step 1: 改 `getLivePlayURL` 签名与 params** |
||||
|
|
||||
|
将 `src/api/live.js` 中: |
||||
|
|
||||
|
```js |
||||
|
export function getLivePlayURL(dockId) { |
||||
|
return request.get(`/v1/live/${dockId}/play-url`) |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
改为: |
||||
|
|
||||
|
```js |
||||
|
export function getLivePlayURL(dockId, sessionId) { |
||||
|
return request.get(`/v1/live/${dockId}/play-url`, { |
||||
|
params: { streamSessionId: sessionId } |
||||
|
}) |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 2: 改 `refreshPlayURL` 守卫与调用** |
||||
|
|
||||
|
将 `src/composables/useMonitorLive.js` 中: |
||||
|
|
||||
|
```js |
||||
|
async function refreshPlayURL() { |
||||
|
if (!live.dockId) return |
||||
|
const play = await getLivePlayURL(live.dockId) |
||||
|
live.playUrl = play.playUrl || '' |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
改为: |
||||
|
|
||||
|
```js |
||||
|
async function refreshPlayURL() { |
||||
|
if (!live.dockId || !live.session?.id) return |
||||
|
const play = await getLivePlayURL(live.dockId, live.session.id) |
||||
|
live.playUrl = play.playUrl || '' |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 3: 静态核对 Monitor 路径** |
||||
|
|
||||
|
确认: |
||||
|
|
||||
|
- `openLive` / heartbeat 仍只通过 `refreshPlayURL` 取 play-url(不必改触发逻辑) |
||||
|
- 本任务未改 `joinLive` / `heartbeatLive` / `leaveLive` |
||||
|
|
||||
|
- [ ] **Step 4: Commit** |
||||
|
|
||||
|
```bash |
||||
|
git add src/api/live.js src/composables/useMonitorLive.js |
||||
|
git commit -m "$(cat <<'EOF' |
||||
|
fix: pass streamSessionId when fetching live play URL |
||||
|
|
||||
|
Require session id in getLivePlayURL and guard Monitor refresh |
||||
|
so play-url requests match the backend contract. |
||||
|
EOF |
||||
|
)" |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 2: MediaView 调用 |
||||
|
|
||||
|
**Files:** |
||||
|
- Modify: `src/views/MediaView/MediaView.vue`(`openLive`) |
||||
|
|
||||
|
- [ ] **Step 1: 改 `openLive` 带 sessionId,缺 id 时 toast** |
||||
|
|
||||
|
将: |
||||
|
|
||||
|
```js |
||||
|
async function openLive(stream) { |
||||
|
try { |
||||
|
const result = await request.post(urls.LIVE_SESSIONS(stream.dockId)) |
||||
|
if (result?.session?.phase === 'streaming') { |
||||
|
const play = await request.get(urls.LIVE_PLAY_URL(stream.dockId)) |
||||
|
if (play?.playUrl && !play.playUrl.startsWith('fake://')) window.open(play.playUrl, '_blank') |
||||
|
else ui.toast('控制面已验证,当前未配置可播放媒体流') |
||||
|
} else { |
||||
|
ui.toast('直播正在启动,请稍后重试') |
||||
|
} |
||||
|
} catch (e) { |
||||
|
ui.toast(e.message || '打开直播失败') |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
改为: |
||||
|
|
||||
|
```js |
||||
|
async function openLive(stream) { |
||||
|
try { |
||||
|
const result = await request.post(urls.LIVE_SESSIONS(stream.dockId)) |
||||
|
if (result?.session?.phase === 'streaming') { |
||||
|
if (!result.session?.id) { |
||||
|
ui.toast('直播会话无效') |
||||
|
return |
||||
|
} |
||||
|
const play = await request.get(urls.LIVE_PLAY_URL(stream.dockId), { |
||||
|
params: { streamSessionId: result.session.id } |
||||
|
}) |
||||
|
if (play?.playUrl && !play.playUrl.startsWith('fake://')) window.open(play.playUrl, '_blank') |
||||
|
else ui.toast('控制面已验证,当前未配置可播放媒体流') |
||||
|
} else { |
||||
|
ui.toast('直播正在启动,请稍后重试') |
||||
|
} |
||||
|
} catch (e) { |
||||
|
ui.toast(e.message || '打开直播失败') |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- [ ] **Step 2: Commit** |
||||
|
|
||||
|
```bash |
||||
|
git add src/views/MediaView/MediaView.vue |
||||
|
git commit -m "$(cat <<'EOF' |
||||
|
fix: send streamSessionId from Media live open |
||||
|
|
||||
|
Pass session id on MediaView play-url fetch and toast when |
||||
|
the joined session is missing an id. |
||||
|
EOF |
||||
|
)" |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### Task 3: 全仓检索 + 构建 |
||||
|
|
||||
|
**Files:** 无代码改动(除非检索发现遗漏) |
||||
|
|
||||
|
- [ ] **Step 1: 全仓检索旧调用** |
||||
|
|
||||
|
```bash |
||||
|
rg -n "getLivePlayURL\\(|LIVE_PLAY_URL\\(|play-url" src |
||||
|
``` |
||||
|
|
||||
|
Expected: |
||||
|
|
||||
|
- `src/api/live.js`:函数定义含 `params: { streamSessionId: sessionId }` |
||||
|
- `src/composables/useMonitorLive.js`:`getLivePlayURL(live.dockId, live.session.id)` |
||||
|
- `src/views/MediaView/MediaView.vue`:`LIVE_PLAY_URL(...)` 调用带 `params.streamSessionId` |
||||
|
- `src/config/urls.js`:path helper 仍为 `(dockId) => .../play-url` |
||||
|
- **无** 仅单参 `getLivePlayURL(x)` 的业务调用 |
||||
|
- **无** 不带 `streamSessionId` 的 play-url GET |
||||
|
|
||||
|
若发现遗漏:当场修并追加 commit,勿留尾巴。 |
||||
|
|
||||
|
- [ ] **Step 2: 构建** |
||||
|
|
||||
|
```bash |
||||
|
npm run build |
||||
|
``` |
||||
|
|
||||
|
Expected: 成功退出。 |
||||
|
|
||||
|
- [ ] **Step 3:(可选)联调冒烟** |
||||
|
|
||||
|
若后端可用:Monitor 开直播 / Media 开直播,确认 Network 里 play-url 请求 query 含 `streamSessionId`。后端不可用则跳过,以检索 + build 为准。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Spec coverage checklist |
||||
|
|
||||
|
| Spec 要求 | Task | |
||||
|
|---|---| |
||||
|
| `getLivePlayURL(dockId, sessionId)` + params | Task 1 | |
||||
|
| `refreshPlayURL` 无 session 不请求 | Task 1 | |
||||
|
| MediaView 带 `streamSessionId` / 缺 id toast | Task 2 | |
||||
|
| 全仓无旧无参调用 | Task 3 | |
||||
|
| build 通过 | Task 3 | |
||||
|
|
||||
|
## Risks |
||||
|
|
||||
|
- MediaView 仍不 leave session:既有问题,本计划不扩 scope |
||||
|
- 后端参数名若不符:以 spec 的 `streamSessionId` 为准 |
||||
Loading…
Reference in new issue