6.5 KiB
| name | overview | design | todos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ai-speaking-dialog | 新建 AI 口语对话页面 SpeakingDialog.vue,复用豆包 TTS API(同 Pronunciation.vue),实现用户输入文字/语音 → AI 外教回复 → TTS 朗读的完整对话流程,并在首页和路由中注册入口。 |
|
|
用户需求
基于现有项目的豆包 TTS API,新建一个 AI 口语对话页面,实现与 AI 英语外教的实时对话练习功能。
产品概述
页面采用聊天气泡布局,用户在底部输入框输入英语文本,AI 外教自动回复并通过豆包 TTS 合成语音播放。页面风格与现有项目保持一致(深色玻璃拟态风格),并接入首页 card-2 入口。
核心功能
- 对话界面:聊天气泡布局,用户消息靠右(蓝紫色),AI 消息靠左(带头像),支持滚动历史记录
- AI 回复:调用字节跳动 Ark 大模型 API(
/ark-api/api/v3/chat/completions)生成英语对话回复;未配置 API Key 时降级为预设模板回复 - TTS 朗读:AI 每条回复自动调用豆包 TTS 合成语音播放,消息旁提供重播按钮,播放时显示动态音波动画
- 音色选择:顶部可选英语音色(Dacey 美音、Tim 美音、Tina 英音等)
- 场景选择:提供日常对话、面试练习、旅游英语、购物场景等预设场景,切换场景重置对话并注入对应系统提示词
- 路由与入口:注册
/speaking路由,首页 card-2 的route改为/speaking
技术栈
- Vue 3 Composition API(
<script setup>)+ Vite,与现有项目完全一致 - Vue Router 4,复用现有路由配置模式
- 原生 CSS(scoped),复用现有 CSS 变量(
--card-bg、--accent-1等) - 豆包 TTS V3 API(已有代理
/tts-api) - 字节跳动 Ark Chat API(新增代理
/ark-api)
实现方案
AI 对话回复
调用 Ark API(POST /ark-api/api/v3/chat/completions),携带系统提示词(根据场景动态注入)和对话历史,模型使用 doubao-pro-4k。用户需在页面顶部配置 ARK_API_KEY;若为空则使用预设英语回复模板降级,保证页面可用性。
TTS 朗读
复用 Pronunciation.vue 中已验证的流式 Chunked JSON 解析逻辑,AI 消息生成后自动触发 TTS 合成并播放。每条 AI 消息独立维护播放状态,支持重播,同一时刻只允许一个音频实例播放。
对话历史管理
维护 messages 数组({ role, content, audioUrl, isPlaying, isLoading }),AI 回复时先插入 loading 占位气泡,完成后替换内容并触发 TTS,避免界面跳动。
性能考量
- TTS 音频 Blob URL 在组件卸载时统一
revokeObjectURL,防止内存泄漏 - 对话历史最多保留最近 20 条发送给 API,避免 token 超限
- 消息新增后自动滚动到底部(
nextTick+scrollIntoView)
架构设计
graph TD
A[用户输入文本] --> B[发送消息]
B --> C{ARK_API_KEY 是否配置?}
C -- 是 --> D[调用 Ark Chat API]
C -- 否 --> E[预设模板回复]
D --> F[AI 回复文本]
E --> F
F --> G[插入 AI 消息气泡]
G --> H[调用豆包 TTS API]
H --> I[流式解析 Chunked JSON]
I --> J[合并音频 Blob 自动播放]
J --> K[消息旁显示重播按钮]
目录结构
src/
├── views/
│ ├── HomePage.vue # [MODIFY] card-2 的 route: null 改为 route: '/speaking'
│ ├── Pronunciation.vue # [不变]
│ └── Speaking.vue # [NEW] AI 口语对话页面主组件
│ # 包含:场景选择栏、音色选择、聊天气泡列表、底部输入框
│ # 实现:Ark API 调用、TTS 合成复用逻辑、消息状态管理、音频生命周期管理
└── router/
└── index.js # [MODIFY] 新增 /speaking 路由指向 Speaking.vue
vite.config.js # [MODIFY] 新增 /ark-api 代理指向 https://ark.cn-beijing.volces.com
关键接口定义
// 消息数据结构
{
id: Number, // 唯一标识
role: 'user' | 'assistant',
content: String, // 消息文本
audioUrl: String | null, // TTS 生成的 Blob URL
isPlaying: Boolean,
isLoading: Boolean // AI 回复生成中占位
}
// 场景配置
{
id: String,
name: String, // 显示名称
systemPrompt: String // 注入给 Ark API 的系统提示词
}
设计风格
延续现有项目的深色玻璃拟态(Glassmorphism)风格,与 Pronunciation.vue 视觉语言保持一致。整体背景深色,面板使用 --card-bg 半透明毛玻璃效果,强调色使用紫蓝渐变(--accent-1 / #8b5cf6)。
页面布局
顶部导航栏
返回按钮(左)+ 页面标题"AI 口语对话"(居中)+ 音色选择下拉(右)。与 Pronunciation.vue 导航栏结构一致。
场景选择栏
横向滚动 Tab 条,提供"日常对话 / 面试练习 / 旅游英语 / 购物场景 / 自由练习"5 个场景,选中态使用 accent 色高亮,切换时重置对话。
聊天消息区域
占据页面主体,垂直滚动。AI 消息靠左(头像 + 气泡),用户消息靠右(气泡)。AI 气泡下方显示播放/重播按钮及音波动画。Loading 状态显示三点跳动动画。
底部输入区域
固定在底部,输入框 + 发送按钮。发送中禁用输入,按钮显示 loading 状态。支持 Enter 发送(Shift+Enter 换行)。