---
author: Peanut
created_at: 2026-06-28
purpose: 回滚 ScriptView 的临时 conversationId 正则短路保护，修复历史剧本消息卡片不显示的回归
---

# 回滚 ScriptView 临时 ID 正则短路保护

## 背景

commit 19337b9（"ScriptView loadMessages 对临时 conversationId 正则短路保护"）引入了一个回归 bug：
用户从"历史剧本"列表点进详情再点"继续"进入 ScriptView，**看不到完整的消息卡片**。

## 根因

DB 中历史剧本的 `conversation_id` 字段值就是 `conv-<ts>-<rand>` 格式（前端在早期版本自造后写入）：

```
conv-1782552967659-615gen
conv-1782228787632-fkifia
conv-1781497026473-7l8jco
...
```

这些 conversationId 完全匹配 commit 19337b9 加的正则 `^conv-\d+-[a-z0-9]{6}$`。
并且这些 conversation 在 `t_conversation` 表中大多没有对应记录（`current_version_message_id` 字段全为 NULL，佐证了当时 conversation 没有完整落库）。

用户打开历史剧本的 ScriptView 时：
1. 从 store 拿到 script，`conversationId = script.conversationId` = `conv-1782552967659-615gen`
2. 进入 `loadMessages()`
3. 正则匹配 + `backedByScript=false`（script 上没有 conversationId 背书？错，有背书但被误判）
4. 实际上 `currentResult.value.conversationId` 在 `openScriptChat` 里被赋值为 `script.conversationId`，但 `openScriptChat` 是在 ScriptView 页内调用的，详情页 "继续" 按钮走的是 `continueCurrent` → `uni.reLaunch({ url: '/pages/main/index?tab=script' })`，ScriptView 重新初始化时 `currentResult.value` 还未被赋值
5. 正则保护触发 → `messages.value = []` → **所有消息卡片不显示**

## 修复方案

**删除** commit 19337b9 在 `mini-program/src/pages/main/ScriptView.vue` 的 `loadMessages` 中添加的正则短路保护代码。恢复为：

```javascript
const loadMessages = async () => {
  if (!conversationId.value) return
  try {
    const res = await listMessagesByConversation({ conversationId: conversationId.value, includeVersions: false })
    messages.value = res.data || []
    const scriptMessages = messages.value.filter(m => m.type === 'script')
    if (scriptMessages.length > 0) {
      const rootMessage = scriptMessages[0]
      const versionRes = await listMessageVersions(rootMessage.id)
      versions.value = versionRes.data || []
    }
  } catch (error) {
    uni.showToast({ title: error.message || '加载消息失败', icon: 'none' })
  }
}
```

**为什么可以直接回滚**：
- commit e3eb1af 已让后端 `listByConversation` 在 conversation 不存在时返回空列表（不抛 500）
- 所以前端调 API 时即使传了"不存在"的 conversationId，也只会得到空数据，不会再 500
- 5xx 噪音问题已由后端修复兜底，前端的正则保护属于过度防御

## 验证步骤

1. 修改 `mini-program/src/pages/main/ScriptView.vue`，删除正则短路保护
2. 启动 H5：`python dev-services.py start mini-program`（端口 5180）
3. 浏览器访问 `http://localhost:5180`，登录一个有历史剧本的账号
4. 进入任一历史剧本的 ScriptView
5. 验证：
   - 不再看到正则保护导致的"消息全空"
   - Network 面板有 `/message/listByConversation` 请求
   - 响应状态 200，body 为 `{"code":200,"data":[]}`（conversation 不存在）或有数据
   - Console 无报错

## 风险与回退

- **回退方案**：如果回滚后出现 500 噪音，可以再在前端加判断（但后端已兜底，不应再出现）
- **影响面**：仅影响 ScriptView.vue 的 loadMessages 函数，其他页面不受影响

## 长期改进（不在本次范围）

历史剧本的 conversation_id 是前端自造的临时 ID，但被当作"真实 conversationId"写入了 `t_epic_script.conversation_id`。这是数据模型上的不一致：
- 要么在写入 epic_script 时同步创建 t_conversation 记录
- 要么 epic_script.conversation_id 字段只存真实落库的 ID
- 本次不处理，单独跟踪
