diff --git a/docs/superpowers/specs/2026-06-29-scriptview-chat-buttons-fix-design.md b/docs/superpowers/specs/2026-06-29-scriptview-chat-buttons-fix-design.md
new file mode 100644
index 0000000..0f6feee
--- /dev/null
+++ b/docs/superpowers/specs/2026-06-29-scriptview-chat-buttons-fix-design.md
@@ -0,0 +1,286 @@
+---
+author: Peanut
+created_at: 2026-06-29
+purpose: 完整修复 ScriptView 对话模式的按钮缺失问题,补齐 spec 要求的版本/改写/续写/历史版本/删除功能
+---
+
+# ScriptView 对话模式按钮完整修复设计
+
+## 背景
+
+`bf6f279 feat: ScriptView 改造为对话中心查看/修改模式` 重构后,对话模式的按钮出现多处丢失:
+
+1. **旧版按钮丢失**:`MessageCard` 在 `isShortMessage=true`(短消息)分支没有按钮组,而旧版 assistant 消息后面有「复制/换个方向/不像我/继续生成/播放」按钮组(commit `0db434c` 添加)
+2. **Spec 功能未实现**:`2026-06-28-script-dialogue-design.md` 第 5.4 节要求 AI 剧本消息有「改写 / 续写 / 查看历史版本 / 删除版本」按钮,当前完全没实现
+3. **根版本被过滤**:`displayMessages` 用 `m.type !== 'script' || !m.parentMessageId` 过滤,把根版本 AI 剧本消息丢掉了
+4. **版本标签缺失**:AI 消息没有 `V1 / V2` 版本号标签和「(当前)」标记
+
+## 设计
+
+### 1. MessageCard.vue 重构
+
+**新增 props**:
+- `messageType`: `'script' | 'chat' | 'system'`,默认 `'script'`
+- `versionLabel`: 版本号显示(如 `V1 (当前)`),script 类型必填,其他类型不传
+- `hasChildren`: 是否有子版本(布尔,用于控制「查看历史版本」按钮是否显示)
+- `canDelete`: 是否可删除(布尔,当前生效版本不可删除)
+- `canRewrite`: 是否可改写(布尔,默认 true)
+- `canContinue`: 是否可续写(布尔,默认 true)
+
+**渲染规则**:
+
+| messageType | 渲染方式 |
+|---|---|
+| `'script'` | **永远**走长文本 story-card 分支(不论 `isShortMessage`),因为剧本消息总是需要按钮组 |
+| `'chat'` 或 `'system'` | 保持原逻辑(短消息气泡 / 长消息 story-card) |
+
+**按钮组**(按 messageType 切换):
+
+```
+script 消息按钮组:
+ ┌─ 顶部操作(story-head-actions,不变)
+ │ · 收起/展开
+ │ · 复制
+ ├─ 版本标签(新增,仅在 versionLabel 有值时显示)
+ │ · V1 (当前) / V2 / ...
+ ├─ 功能按钮(新增,script 专属)
+ │ · 改写(emit 'rewrite')
+ │ · 续写(emit 'continue-script')
+ │ · 查看历史版本(emit 'view-versions',hasChildren=true 才显示)
+ │ · 删除版本(emit 'delete-version',canDelete=true 才显示)
+ └─ 通用操作(保留旧版)
+ · TTS 播放(emit 'play-tts')
+
+chat 消息按钮组(isShortMessage=false 时):
+ ┌─ 复制
+ ├─ 收起/展开
+ └─ TTS 播放(emit 'play-tts')
+
+system 消息(isShortMessage=true 默认走气泡):
+ └─ 不变
+```
+
+**新增 emits**:
+- `rewrite` — 改写按钮
+- `continue-script` — 续写按钮(避免和旧 `continue` 语义冲突,但保留旧 `continue` 兼容)
+- `view-versions` — 查看历史版本
+- `delete-version` — 删除版本
+
+### 2. ScriptView.vue 改动
+
+**改动 2.1:显示根版本**
+
+```js
+// 旧
+const displayMessages = computed(() => {
+ return messages.value.filter(m => m.type !== 'script' || !m.parentMessageId)
+})
+
+// 新:保留所有消息,根版本作为 chat 列表首条
+const displayMessages = computed(() => messages.value)
+```
+
+**改动 2.2:传 messageType 给 MessageCard**
+
+```vue
+
+```
+
+**改动 2.3:版本标签生成函数**
+
+```js
+const formatVersionLabel = (message) => {
+ if (message.type !== 'script') return ''
+ const versionNum = message.versionNumber || 1
+ const isCurrent = message.id === currentVersionMessageId.value
+ return isCurrent ? `V${versionNum} (当前)` : `V${versionNum}`
+}
+
+const messageHasChildren = (message) => {
+ // 通过 versions 数组长度判断(已加载的)或 metadata 推断
+ return versions.value.some(v => v.parentMessageId === message.id)
+ || (message.versionNumber && message.versionNumber > 1)
+ || (message.childrenCount && message.childrenCount > 0)
+}
+```
+
+**改动 2.4:查看历史版本**
+
+新增 `viewMessageVersions(msg)` 函数:
+1. 调用 `listMessageVersions(msg.id)`
+2. 用 `uni.showActionSheet` 列出所有版本(V1、V2...)
+3. 用户选择后:
+ - 如果选的是当前版本:`uni.showToast` 提示「当前已生效」
+ - 如果选的是其他版本:调用 `switchVersion({ scriptId, messageId: selectedId })` → 更新 `currentVersionMessageId` → `loadMessages()` 刷新
+
+### 4. 历史剧本兼容层(高优先级)
+
+### 现状
+
+DB 中绝大多数历史剧本的 `conversation_id` 是前端早期自造的临时 ID(`conv--` 格式),**`t_conversation` 表中没有对应记录**。
+
+```
+329987360219471872 我的人生剧本 → YES (最新剧本,走新流程创建)
+f82818b702d5ad4a... 高考 → NO
+a3dadb7e85a6c75b... 我高考了 → NO
+49ae0f432253aaff... 我中了100w → NO
+... 其余 6 条 → NO
+```
+
+### 影响分析
+
+| 场景 | 是否受影响 | 原因 |
+|---|---|---|
+| ScriptDetailView 阅读模式 | ✅ 正常 | 读 `t_epic_script.plotJson`,不依赖 conversation |
+| ScriptView `viewMode='read'` 阅读模式 | ✅ 正常 | 通过 `currentScriptContent` 读 `currentVersionMessageId` 指向的 message;fallback 到 `plotJson` |
+| ScriptView `viewMode='chat'` 聊天模式 | ❌ 异常 | `listByConversation` 返回空,对话历史丢失 |
+| 改写 / 续写 / 版本切换 | ❌ 异常 | 需要有效的 conversation 和 message 才能操作 |
+
+### 兼容策略:前端 fallback + 后端自动建表
+
+**改动 A:后端自动建 conversation**
+
+在 `EpicScriptServiceImpl.getScriptById`(或 `getListByCurrentUser` 返回前)检查:
+- 若 `script.conversation_id` 指向的 conversation 不存在 → 自动创建一条 `t_conversation` 记录,写入 `user_id`、`script_id`、`type='script'`、`status='active'`,并回填 `t_epic_script.conversation_id` 为新 ID
+
+**改动 B:前端首次进入聊天模式时,基于 `plotJson` 初始化首条消息**
+
+在 ScriptView.vue 的 `loadMessages` 中:
+- 若 API 返回空列表 && `script.plotJson?.fullContent` 存在 → 自动调用 `/message/create` 创建一条 `type='script'` 的 AI 剧本消息(content 来自 plotJson)
+- 后续改写/续写/版本切换基于这条真实消息操作
+
+**改动 C:ScriptView 阅读模式 fallback 强化**
+
+当前 `currentScriptContent` 已在 message 不存在时 fallback 到 `plotJson`。需确保:
+- `viewMode='read'` 下,版本标签在没有 versions 数据时隐藏(不显示"V0"之类)
+- "进入对话修改"按钮在没有 conversation 时仍可点击,触发改动 B 的初始化流程
+
+### 验收标准(历史剧本)
+
+- [ ] 历史剧本在 ScriptDetailView 完整显示标题、summary、content
+- [ ] 历史剧本在 ScriptView `viewMode='read'` 完整显示标题、章节内容(无版本标签时 UI 不异常)
+- [ ] 历史剧本点击"进入对话修改" → 自动创建 conversation + 初始化首条 AI 消息 → 进入 chat 模式
+- [ ] 历史剧本进入 chat 模式后,能看到完整对话历史(首条为用户心愿 + AI 剧本)
+- [ ] 历史剧本的"改写/续写/查看历史版本"功能可正常使用
+- [ ] 新创建的剧本所有功能不受影响(回归验证)
+
+## 5. 实施顺序
+
+| 顺序 | 任务 | 类型 |
+|---|---|---|
+| 1 | 后端 `getScriptById` 自动建 conversation | 数据兼容 |
+| 2 | 前端 MessageCard 重构 + 按钮组 | 功能补齐 |
+| 3 | 前端 ScriptView displayMessages 去掉根版本过滤 | Bug 修复 |
+| 4 | 前端 loadMessages 空结果时自动初始化首条消息 | 数据兼容 |
+| 5 | 前端 chat 模式传 messageType/versionLabel 等 props | 功能补齐 |
+| 6 | 端到端验收(新剧本 + 历史剧本) | 验收 |
+
+## 6. 影响范围
+
+| 文件 | 改动量 |
+|---|---|
+| `server/.../EpicScriptServiceImpl.java` | 小(getScriptById 检查 + 自动建 conversation) |
+| `mini-program/src/components/MessageCard.vue` | 中(+props、+emits、+按钮组条件渲染) |
+| `mini-program/src/pages/main/ScriptView.vue` | 中(displayMessages filter、MessageCard props、formatVersionLabel、viewMessageVersions、loadMessages 初始化) |
+
+## 验收标准(代码层面)
+
+- [ ] chat 模式下,根版本 AI 剧本消息显示为 chat 列表首条
+- [ ] AI 剧本消息显示 V1 / V2 版本号 + (当前) 标记
+- [ ] AI 剧本消息按钮组包含:收起/展开、复制、TTS 播放、改写、续写、查看历史版本、删除版本
+- [ ] 用户消息(type=chat)保持气泡样式,有收起/展开按钮
+- [ ] 点击「改写」弹出 modal 输入改写意图,提交后生成新版本
+- [ ] 点击「续写」直接生成新版本
+- [ ] 点击「查看历史版本」弹 ActionSheet 列出版本,切换后 UI 更新
+- [ ] 当前生效版本不显示「删除版本」按钮
+- [ ] 历史剧本进入 ScriptView chat 模式 → 自动创建 conversation + 初始化首条 AI 消息
+- [ ] 浏览器 Console 无报错
+- [ ] 不影响 read 模式(阅读模式保持现状)
+
+## H5 端到端验收流程(强制)
+
+**后端验证码**:`AuthServiceImpl.java:80` 已硬编码 `DEFAULT_SMS_CODE = "123456"`,无需改动。
+
+**测试账号**:手机号 `19928748688`,验证码 `123456`。
+
+### 步骤 1:启动本地 H5
+```bash
+python dev-services.py start mini-program
+# 访问 http://localhost:5180
+```
+
+### 步骤 2:登录
+1. 打开 `http://localhost:5180`
+2. 输入手机号 `19928748688`
+3. **必须点击"发送验证码"按钮**(触发 `/auth/sms-code` 接口,后端写入 Redis 并返回固定验证码)
+4. 输入验证码 `123456`
+5. 提交登录
+
+### 步骤 3:新剧本完整流程
+1. 首页输入心愿 → 生成第一个剧本
+2. 查看剧本详情 → 标题、summary、content 完整显示
+3. 点击"继续" → 进入 ScriptView chat 模式
+4. **验证**:
+ - 用户心愿气泡显示
+ - AI 剧本消息显示,带 `V1 (当前)` 版本标签
+ - AI 消息按钮组包含:收起/展开、复制、TTS 播放、**改写**、**续写**、**查看历史版本**、**删除版本**(当前版本不显示删除)
+5. 点"改写" → 输入改写意图 → 生成新版本 V2
+6. 点"查看历史版本" → ActionSheet 列出 V1/V2,点击切换
+7. 点"续写" → 生成新内容
+
+### 步骤 4:历史剧本完整流程
+1. 点"历史"按钮 → 进入剧本库
+2. 点任一**历史剧本**(非本次新生成的)→ 进入 ScriptDetailView
+3. **验证**:
+ - 标题、summary、content 完整显示(读 `plotJson.fullContent`)
+ - 风格、篇幅、字数正确
+4. 点"继续" → 进入 ScriptView
+5. **验证**:
+ - 自动创建 `t_conversation`(DB 中新增记录)
+ - 自动初始化首条 AI 消息(基于 plotJson)
+ - chat 模式看到完整对话历史(心愿 + AI 剧本)
+ - AI 消息带版本标签
+ - 改写/续写/查看历史版本 可正常操作
+
+### 步骤 5:Console 与 Network 检查
+- DevTools Console 无报错
+- Network 中所有 API 调用返回 2xx(无 5xx、无 401、无 403)
+- `listByConversation` 调用返回 200 且有数据
+
+### 步骤 6:验收通过标准
+- ✅ 新剧本 + 历史剧本所有功能正常
+- ✅ 按钮组完整
+- ✅ 版本标签正确
+- ✅ Console 无报错
+- ✅ 历史剧本 conversation 自动创建成功
+
+**未通过的处理**:任一验收项失败 → 停止 → 定位问题 → 修复 → 重新验收 → 直到全部通过才算完成
+
+## 风险与回退
+
+- **MessageCard 重构风险**:新增 props 都带默认值,不会破坏非对话模式(生成页、结果页)的现有用法
+- **向后兼容**:旧 `continue` emit 保留,新增 `continue-script` 作为 script 专属,避免语义冲突
+- **回退方案**:git revert 单个 commit 即可