# 回归测试用例（main-old.js 拆分后）

> 用途：验证 `main.js` + `asr/realtime-asr-pipeline.js` + `composables/useRecordingOperations.js` 拆分后，与原 `main-old.js` 行为一致，且 4 个回归（说话人名字不显示 / 高亮不渲染 / 点击外部不收起建议 / 清空对象错误）已修复。
>
> 行为差异编号对应各源文件顶部注释中的【行为差异】条目。

---

## 一、说话人管理与转录显示（修复回归 1/2/3/4 + 行为差异 A）

### TC-1.1 打开说话人 modal 输入名字，转录正文实时显示
**前置**：选中一条带说话人分轨（JSON 格式）的录音，进入详情。
**步骤**：
1. 点击「管理说话人」打开 modal。
2. 在某个 speaker 的输入框里输入名字（例如把 `SPEAKER_00` 改成「张三」）。
**预期**：
- 转录正文（simple / bubble / JSON 三种视图任选其一）中该 speaker 的显示名**实时**变成「张三」。
- segment 颜色 class（`speaker-color-N`）保持正常。
- **修复前**：正文一直显示原始 ID `SPEAKER_00`，输入名字不反映（回归 1）。

### TC-1.2 纯文本格式转录的 v-html 高亮与着色
**前置**：选中一条**纯文本格式**（非 JSON）的录音，transcription 含 `[SPEAKER_00]: ...` 这样的标签。
**步骤**：
1. 打开说话人 modal，输入名字。
2. focus 该 speaker 的输入框（触发 `highlightSpeakerInTranscript`）。
**预期**：
- 纯文本视图（`v-html="highlightedTranscript"`）中 `[SPEAKER_00]` 被替换成 `[张三]`，并包成 `<span class="speaker-tag speaker-color-N speaker-highlight" data-speaker-id="SPEAKER_00">[张三]</span>`。
- HTML 已转义（`<` `>` 显示为字面量，无脚本执行）。
- `\n` 被转成 `<br>`，换行正常。
- **修复前**：`highlightedTranscript` 只返回原始字符串，无转义、无高亮、无着色（回归 2 + XSS 风险）。

### TC-1.3 点击 modal 外部收起建议下拉
**前置**：打开说话人 modal，在某个 speaker 输入框输入字符触发 `searchSpeakers`，下拉出现建议。
**步骤**：点击输入框之外的空白处。
**预期**：
- 所有 speaker 的建议下拉**立即收起**（`speakerSuggestions[speakerId] = []`）。
- **修复前**：`handleClickAway` 里 `showSpeakerModal.value` 永远是 false（读的是 main.js 那份空 ref），分支进不去；即便进去清的也是空的 `speakerSuggestions`，下拉不收起（回归 3 + 4）。

### TC-1.4 保存说话人名字后正文回退到原始 ID（保留原行为，行为差异 A）
**前置**：TC-1.1 完成后。
**步骤**：点击「保存」。
**预期**：
- modal 关闭。
- 转录正文回退到显示原始 speaker ID（`SPEAKER_00`），不再显示「张三」。
- 这是 **main-old.js 的原始行为**（`closeSpeakerModal` 把 `speakerMap` 清空成 `{}`），拆分后保留。
- **如果产品希望保存后正文继续显示名字**，需要额外在 `saveSpeakerNames` 成功后从后端返回的 recording 里把 speaker_map 灌回 `speakerMap` ref（当前未做，属待确认增强）。
- 验证点：确认这个回退行为符合产品预期；若不符合，提需求做增强。

### TC-1.5 autoIdentifySpeakers 识别结果实时反映到正文
**前置**：打开说话人 modal。
**步骤**：点击「自动识别说话人」按钮。
**预期**：
- 识别完成后，被识别的 speaker 输入框自动填入名字。
- 转录正文同步显示识别出的名字（与 TC-1.1 同源，应实时刷新）。
- **修复前**：识别结果只填到 composable 那份 speakerMap，正文读的是 main.js 那份空 speakerMap，不刷新。

### TC-1.6 高亮 + 上下导航
**前置**：纯文本或 JSON 格式转录，有多个 speaker。
**步骤**：
1. 在 modal 里 focus 某个 speaker 输入框。
2. 点击「上一组 / 下一组」导航按钮。
**预期**：
- 对应 speaker 的所有段落高亮（`speaker-highlight` class）。
- 导航按钮在多组之间循环跳转，滚动到对应分组。
- 按钮禁用态：无高亮 speaker 或分组数 ≤ 1 时按钮 disabled。

---

## 二、重处理 / 状态管理（行为差异 A：asrReprocessOptions 改 ref）

### TC-2.1 重处理 transcription，modal 表单绑定正常
**前置**：选中一条录音，使用 ASR endpoint（`useAsrEndpoint === true`）。
**步骤**：
1. 点击「重处理转写」。
2. 在 modal 里修改 language / min_speakers / max_speakers 输入。
3. 点击确认。
**预期**：
- `asrReprocessOptions.language / min_speakers / max_speakers` 的 `v-model` 绑定正常（输入值实时同步）。
- 提交后台的 payload 带正确参数。
- 进度 modal 弹出，轮询开始，状态变化时进度条 / 文案更新。
- 完成后 toast「Reprocessing completed successfully」。
- **风险点**：`asrReprocessOptions` 从 `reactive` 改为 `ref`，模板自动解包应正常；如发现 v-model 不响应，优先排查这里。

### TC-2.2 重处理 summary
**步骤**：点击「重处理总结」→ 确认。
**预期**：同 TC-2.1，进度 modal + 轮询 + 完成 toast。

### TC-2.3 reset recording status
**步骤**：对一条卡在 PROCESSING/SUMMARIZING 的录音点「重置状态」→ 确认。
**预期**：modal 正常开关，状态重置成功，列表 / 详情同步刷新。

---

## 三、实时 ASR 录音全流程（行为差异 B/C/D + pipeline 差异 1-8）

### TC-3.1 新建录音 → 暂停 → 恢复 → 暂停 → 恢复 → 停止
**步骤**：
1. 进入录音视图，选择麦克风/系统音频，开始录音。
2. 说几句话，等实时转写出现。
3. 暂停 → 恢复 → 暂停 → 恢复 → 停止。
**预期**：
- 每次恢复时，`resetRealtimeTranscript` 立刻清空 pipeline 状态（**行为差异 B**：原代码用 `resetTranscriptionFlag` 延迟到下一条 ws 消息时清，新代码立刻清）。
- 暂停期间的历史转写（`pausedTranscription`）保留，恢复后新转写追加在后面，不重复。
- 停止时 `pipeline.finish(3500)` 发送 stop 帧并等待后端 flush 最后的 offline/LLM 结果（**行为差异 2**：会立即 `closeRecorders()`，恢复时重建）。
- 最终上传 / 草稿片段保存正常。

### TC-3.2 录音中手动编辑转写
**步骤**：录音中点「编辑」→ 修改文本 → 退出编辑。
**预期**：
- `enterEditMode` 记录 `editModeBufferStartIndex` + 时间屏障 + carryover 尾巴。
- `applyEditedText` 以编辑结果为准，旧 ASR 文本不回灌。
- 后续 offline 句子用 carryover 裁掉与编辑尾巴重叠的部分，不重复。
- 暂停 / 停止时若仍在编辑模式，会先 `exitEditMode` 再等 LLM 矫正。

### TC-3.3 WebSocket 断连（行为差异 1）
**步骤**：录音中模拟 ws 断连（断网 / 后端 ASR 重启）。
**预期**：
- `handleOnlineState(2)` / `handleOfflineState(2)` 调 `this.stop()`，优雅关闭 ASR 通道（ws + Recorder + AudioContext）。
- **不会**自动停止 MediaRecorder 或把 `isRecording` 置 false（pipeline 只管 ASR 通道）。
- **原 main-old.js 行为**：调用未定义的 `stop()` 抛 ReferenceError。新代码是改进。
- **待确认**：若产品希望 ws 断连时整体停录，需在 `main.js` 的 `onActiveChange(false)` 或新增 `onDisconnect` 回调里补处理（当前未做）。

### TC-3.4 correct 接口带 scene 字段（行为差异 3）
**步骤**：切换场景（CG / YL）后录音，等 offline 句子触发 LLM 矫正。
**预期**：
- `/tool/speakr/api/asr/correct` 请求 body 为 `{ text, scene }`。
- **前置条件**：后端必须容忍/使用 `scene` 字段。如后端报错，回退为去掉 scene 或后端补兼容。
- **原 main-old.js**：只传 `{ text }`。

### TC-3.5 场景切换（行为差异 6）
**步骤**：未录音时在 CG / YL 之间切换。
**预期**：
- `selectedScene` 持久化到 localStorage。
- 录音时 `setSelectedScene` 拒绝切换并 toast「录音中无法切换场景」。
- 新建 pipeline 时 `createSockets` 把 `getScene` 传给 `WebSocketConnectMethod`，按场景路由到不同后端 ASR URL。
- **原 main-old.js**：无场景概念，wsconnecter 走默认 "cg"。

### TC-3.6 离开录音视图后迟到回调不污染（行为差异 8）
**步骤**：录音中立即切到上传视图，观察是否有迟到的转写文本写入。
**预期**：
- `disposeRealtimeAsrPipeline` 设 `disposed=true`，迟到的 ws/LLM 回调被 `handleOnlineMessage` / `handleOfflineMessage` / `processRecorderFrame` 入口检查忽略。
- 上传视图的 `asrResult` 等不被污染。
- **原 main-old.js**：迟到回调可能写入页面状态。

### TC-3.7 草稿加载（行为差异 C）
**步骤**：加载一个已有草稿继续录音。
**预期**：
- `continueDraftRecording` 调 `resetRealtimeTranscript({ clearTimestampBarrier: true })`，清空 `pendingSentenceQueue` 并 `startNewEpoch`。
- 历史转写加载到 `asrResult` / `pausedTranscription`，新录音追加在后面。
- **原 main-old.js**：只重置 `segmentRenderStartIndex=0`，不清 pending。新代码更彻底，若依赖 pending 残留需注意。

---

## 四、转写编辑器（文本 / ASR JSON）

### TC-4.1 纯文本编辑器
**步骤**：选中纯文本格式录音 → 「编辑转写」→ 修改 → 保存。
**预期**：modal 开关正常，保存后 `selectedRecording` 刷新，toast 成功。

### TC-4.2 ASR JSON 编辑器
**步骤**：选中 JSON 格式录音 → 「编辑转写」。
**预期**：
- segment 列表正常渲染，speaker 下拉建议可用（`filterSpeakers` / `openSpeakerSuggestions` / `selectSpeaker`）。
- `adjustTime` 调整 start/end_time 正常。
- `addSegment` / `removeSegment` 正常。
- 保存时去掉 `id / showSuggestions / filteredSpeakers` 字段，提交干净 JSON。

---

## 五、标记 / 分享 / 草稿

### TC-5.1 toggleInbox / toggleHighlight
**步骤**：对录音点 inbox / highlight 切换。
**预期**：状态切换，列表同步，toast 正常。

### TC-5.2 分享链接创建 / 列表 / 删除
**步骤**：创建分享 → 查看列表 → 删除。
**预期**：modal 开关、链接复制、列表刷新正常。

### TC-5.3 草稿重命名 / 删除
**步骤**：重命名草稿 → 删除草稿。
**预期**：列表刷新，删除当前草稿时清状态 + `resetRealtimeTranscript`。

---

## 六、全局 / 兼容性

### TC-6.1 i18n 切换语言
**步骤**：切换 UI 语言。
**预期**：所有 t() 文案更新，无 key 裸露。

### TC-6.2 暗色模式 / 配色
**步骤**：切换暗色模式 + 选配色。
**预期**：转录区 speaker-color-N class 在暗色下可读，高亮 speaker-highlight 可见。

### TC-6.3 移动端布局
**步骤**：窗口宽度 < 1024。
**预期**：`isMobileScreen` 为 true，侧栏自动折叠，转录区可读。

---

## 回归判定

- **必须通过**：TC-1.1 / TC-1.2 / TC-1.3（4 个回归的核心修复点）。
- **重点观察**：TC-1.4（确认回退原始 ID 的行为是否符合产品预期）。
- **后端联动**：TC-3.4（correct 带 scene，需后端兼容）。
- **行为变化确认**：TC-3.3（ws 断连是否需要整体停录）、TC-3.7（草稿加载清 pending 是否影响业务）。
