AI工具使用页面开发
本文属于《从 0 到 1 AI 产品出海知识库》中的「前端页面开发实战」章节。
AI 工具的使用页面是整个产品的核心价值所在。用户在这里输入需求、等待处理、查看结果——产品好不好用,用户在这个页面上就能给出判断。无论你做的是 AI 写作、AI 绘图、AI 视频还是 AI 对话助手,使用页面都承担着「让用户把需求交出去,把结果拿回来」的职责。
这个页面看起来简单,实际上涉及输入区设计、输出区展示、流式响应处理、加载状态管理、错误恢复机制等多个技术维度。任何一个环节体验不佳,用户都会觉得「这个产品不好用」。
本文将从页面结构拆解开始,逐步深入交互设计要点、流式响应的技术方案、错误处理策略,最后给出用 AI 生成 AI 工具页面的完整流程和实战案例。
在正式开始之前,需要明确一个前提:AI 工具的使用页面和传统的 CRUD 页面有本质区别。传统页面的核心操作是「查找-修改-保存」,响应时间通常在毫秒级别,用户对整个流程有明确的预期。AI 工具页面的核心操作是「表达-等待-获取」,响应时间从几百毫秒到几十秒不等,用户需要在一个不确定的等待过程中保持信心。这种「不确定性」是 AI 工具页面设计的核心挑战,也是本文所有技术方案和交互设计的出发点。
一、AI工具页面的核心要素
一个完整的 AI 工具使用页面,通常由四个核心区域组成:输入区、输出区、控制按钮和历史记录。不同产品类型的侧重点不同,但这四个要素缺一不可。
1.1 输入区
输入区是用户表达需求的入口。根据 AI 工具的类型不同,输入区的形态差异很大:
| 输入类型 | 典型产品 | 输入方式 | 复杂度 |
|---|---|---|---|
| 文本对话 | ChatGPT、Claude | 多行文本框 + 发送按钮 | 低 |
| 结构化表单 | AI 写作工具、SEO 工具 | 多个表单字段(标题、关键词、语气等) | 中 |
| 混合输入 | Midjourney、DALL·E | 文本提示词 + 图片上传 + 参数调节 | 高 |
| 代码/文件 | Cursor、GitHub Copilot | 代码编辑器 + 文件拖拽 + 上下文引用 | 高 |
输入区的设计要点:
- 清晰的输入引导:用 Placeholder 或示例提示告诉用户「可以输入什么」。ChatGPT 的空状态会展示几个示例问题,降低用户的启动成本
- 输入校验与反馈:在用户提交前做基础校验——字数限制、必填项检查、格式提示。不要等提交后才报错
- 支持的输入格式要明确标注:如果支持图片上传、文件拖拽,需要在输入区附近展示支持的格式和大小限制
- 快捷键支持:Enter 发送、Shift+Enter 换行,这是用户已经形成的习惯,不要打破它
1.2 输出区
输出区展示 AI 的处理结果,是用户最关注的区域。
| 输出类型 | 展示方式 | 技术要点 |
|---|---|---|
| 纯文本 | Markdown 渲染 | 支持流式追加,处理不完整 Markdown |
| 富媒体 | 图片、音频、视频 | 懒加载、缩略图 + 预览、下载按钮 |
| 代码块 | 语法高亮 + 复制按钮 | 流式场景下延迟高亮,等代码块闭合后再渲染 |
| 结构化数据 | 表格、卡片、图表 | 需要等数据完整后再渲染,不适合逐字流式 |
输出区的关键原则是「渐进展示」——AI 生成什么就展示什么,不要等全部完成才显示。用户在等待 10 秒和看到内容逐渐出现之间的心理感受完全不同。
1.3 控制按钮
控制按钮让用户对 AI 的处理过程保持掌控感。在 AI 工具中,用户对「等待」和「结果」的焦虑感远高于传统应用,控制按钮的核心作用是降低这种焦虑:
- 提交/发送按钮:提交后变为禁用状态,防止重复提交。禁用态应该有明确的视觉区分(降低透明度 + 禁止鼠标事件),避免用户误以为提交失败而反复点击
- 停止生成按钮:流式输出过程中必须提供,让用户可以随时中断。这个按钮的位置应该紧跟输出区域或替代发送按钮的位置,确保用户在等待过程中一眼就能看到。停止操作应该立即生效,不能让用户再等一个网络往返
- 重新生成按钮:对结果不满意时一键重来。注意:重新生成不应该清除之前的结果,而是在新回复中展示。用户可以对比不同版本的输出,选择最满意的一个
- 复制/下载按钮:方便用户将结果带走。复制应该支持纯文本和 Markdown 两种格式。下载按钮根据输出类型提供对应格式(TXT、PNG、PDF 等)
- 反馈按钮:点赞/点踩,既收集用户反馈也用于模型优化。反馈操作应该是轻量级的——一次点击完成,不需要弹窗填写原因。如果需要更详细的反馈,可以在点击后展开一个可选的文本框
控制按钮的另一个重要原则是「状态一致性」——按钮的可见性和可用性必须与当前流式状态严格匹配。例如,停止按钮只在 streaming 状态下显示,重新生成按钮只在 done 或 error 状态下可用。这种一致性让用户不需要猜测「现在能做什么」。
1.4 历史记录
历史记录让用户可以回顾之前的对话或任务。对于 AI 工具来说,历史记录不仅是功能需求,也是用户留存的关键——用户投入在历史记录中的时间越多,迁移到其他产品的成本越高。
- 会话列表:侧边栏展示历史对话,支持搜索和分组(按日期、按项目)。移动端可以将侧边栏折叠为抽屉,通过汉堡菜单触发
- 会话内消息:完整的对话上下文,支持滚动加载。长对话需要做虚拟滚动优化,避免渲染所有消息导致性能问题
- 持久化策略:本地存储(localStorage / IndexedDB)适合 MVP 阶段,实现简单但跨设备不互通。云端同步适合正式产品,需要考虑数据模型设计、冲突处理、存储成本。很多产品会先做本地存储,再逐步迁移到云端
历史记录的另一个容易忽略的点是「会话标题」。AI 对话的默认标题通常是「新对话」或第一条消息的前几个字,这不够直观。更好的做法是让 AI 根据对话内容自动生成一个简短的标题(可以在后台异步完成),同时允许用户手动修改。
二、交互设计要点
AI 工具页面的交互设计和传统 Web 页面有一个根本区别:AI 的处理时间不可预测。一个 API 调用可能 500ms 返回,也可能 30 秒才出结果。这决定了交互设计的核心是「管理用户的等待感知」。
2.1 实时反馈的三层体系
用户提交请求后,反馈分为三个层次:
第一层:提交确认(0-200ms)。用户点击发送后,输入框清空、消息气泡出现、发送按钮变为禁用。这一层反馈必须在 200ms 内完成,让用户知道「系统收到了我的请求」。
第二层:处理中指示(200ms-首字节到达)。显示加载动画——可以是打字指示器(三个跳动的圆点)、进度条、骨架屏或自定义动画。关键原则是「提交后立即展示加载指示器」,消除网络延迟期间的空白感。
第三层:流式内容展示(首字节到达-完成)。内容逐字或逐块出现,配合光标动画表示「还在生成中」。这一层是 AI 产品特有的体验,后面会详细展开。
2.2 流式展示的设计细节
流式展示不只是「文字一个一个蹦出来」那么简单。以下是实际开发中需要注意的细节:
布局稳定性。不要在每次收到新内容时重新计算整个输出区的布局。Smashing Magazine 的一篇专题文章指出:避免在每次更新时销毁和重建 DOM,应该直接写入当前活跃节点,在新内容前创建一个空文本节点并逐个追加字符,这样文本增长时不会影响周围布局。
滚动管理。当内容不断追加时,页面需要自动滚动到底部。但如果用户主动向上滚动查看历史内容,自动滚动应该暂停。实现方式是设置一个像素阈值(例如 60px),检测用户是否有意向上滚动,用户回到底部时再恢复自动滚动。新流开始时必须重置这个滚动状态。
Markdown 缓冲渲染。如果输出是 Markdown 格式,不能每收到一个 chunk 就重新解析整个文本。一个「朴素的渲染器在每次 chunk 到达时解析 Markdown 会产生闪烁」和布局偏移。正确做法是:对不完整的结构(未闭合的代码块、未完成的表格)做缓冲处理,等结构闭合后再渲染。代码块通常使用延迟语法高亮,等结束标记 ``` 到达后再着色。
光标与状态指示。流式输出时显示一个闪烁的光标,表示生成进行中。停止后移除光标,如果生成被中断,显示「已停止」之类的状态标签。
2.3 加载状态的正确做法
| 加载状态 | 适用场景 | 实现方式 | 避免的问题 |
|---|---|---|---|
| 打字指示器 | 对话类 AI | 三个圆点跳动动画 | 避免空白等待 |
| 骨架屏 | 结构化输出 | 灰色占位块模拟布局 | 避免布局偏移 |
| 进度条 | 可估算时长的任务 | 模拟进度(非线性) | 避免进度卡在 99% |
| 百分比/步骤 | 多步骤任务 | 显示当前步骤名称和进度 | 避免用户不知道在做什么 |
| 内联 spinner | 局部刷新 | 小尺寸旋转图标 | 避免整个页面遮罩 |
加载状态的设计原则:让用户知道「系统正在做什么」和「大概还需要多久」。如果无法估算时间,至少告诉用户当前处于哪个阶段(「正在理解你的需求」「正在生成内容」「正在优化结果」)。
三、流式响应的技术方案
流式响应是 AI 工具页面的核心技术挑战。传统的 HTTP 请求-响应模型无法满足「边生成边展示」的需求,需要用到流式传输协议。
3.1 SSE vs WebSocket vs Web Streams
| 方案 | 方向 | 协议 | 适用场景 | 复杂度 |
|---|---|---|---|---|
| Server-Sent Events(SSE) | 服务端 → 客户端 | HTTP | 大多数 AI 对话场景 | 低 |
| WebSocket | 双向 | ws:// | 需要实时双向通信(协作编辑、语音对话) | 中 |
| Web Streams API | 流处理 | 浏览器原生 | 配合 fetch 处理流式响应体 | 低 |
| HTTP Chunked Transfer | 服务端 → 客户端 | HTTP | 最简单的流式方案 | 最低 |
SSE 是目前 AI 产品中最主流的流式方案。OpenAI、Anthropic、Google 的 API 都支持 SSE 格式的流式响应。它的优势在于:基于标准 HTTP,天然支持断线重连(浏览器自动处理),不需要额外的协议升级,与现有的 HTTP 基础设施(CDN、代理、负载均衡)完全兼容。
3.2 SSE 的实现方式
前端使用 SSE 的典型代码:
async function streamChat(messages: Message[]) {
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, stream: true }),
})
const reader = response.body?.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader!.read()
if (done) break
const chunk = decoder.decode(value, { stream: true })
// 解析 SSE 格式:data: {"content": "你好"}
const lines = chunk.split('\n').filter(line => line.startsWith('data: '))
for (const line of lines) {
const data = line.slice(6)
if (data === '[DONE]') break
const parsed = JSON.parse(data)
appendToOutput(parsed.content)
}
}
}后端(以 Node.js 为例):
app.post('/api/chat', async (req, res) => {
const { messages } = req.body
// 设置 SSE 响应头
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')
const stream = await openai.chat.completions.create({
model: 'gpt-4',
messages,
stream: true,
})
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || ''
res.write(`data: ${JSON.stringify({ content })}\n\n`)
}
res.write('data: [DONE]\n\n')
res.end()
})3.3 前端流式状态管理
流式响应的状态管理比一次性请求复杂得多。你需要跟踪以下状态:
interface StreamState {
// 连接状态
status: 'idle' | 'connecting' | 'streaming' | 'done' | 'error' | 'cancelled'
// 已接收的完整内容
content: string
// 当前正在处理的 chunk
currentChunk: string
// 错误信息
error: string | null
// 是否正在加载
isLoading: boolean
// Token 计数(用于计费和进度展示)
tokenCount: number
}关键的状态转换:
idle→connecting:用户提交请求connecting→streaming:收到第一个 chunkstreaming→done:收到[DONE]信号streaming→cancelled:用户点击停止streaming→error:连接中断或解析失败- 任何状态 →
idle:重新发送请求前重置
如果你使用 Vercel AI SDK,它的 useChat hook 已经封装了上述所有状态管理逻辑,你只需要关注 UI 渲染。
3.4 性能优化
流式渲染的性能问题往往在内容变长后才暴露。以下是几个关键的优化点:
缓冲渲染。不要让每个 chunk 都触发一次 DOM 更新。将接收到的内容放入缓冲区,使用 requestAnimationFrame 在浏览器下一次绘制前统一刷新。这样即使后端每秒发送 50 个 chunk,前端也只渲染 60 帧。
虚拟滚动。当对话历史很长时,不要渲染所有消息。使用虚拟滚动(如 react-virtuoso)只渲染可视区域的消息,大幅减少 DOM 节点数量。
防抖更新。对于 token 计数、进度百分比等辅助信息,使用防抖更新(例如每 200ms 更新一次),避免频繁触发 React 重渲染。
Web Worker 处理。如果需要对流式内容做复杂解析(如实时 Markdown 解析、语法高亮),将解析逻辑放到 Web Worker 中,避免阻塞主线程的渲染。
3.5 停止生成的技术实现
停止生成看似简单,实际上涉及前端和后端的协调。前端需要立即停止 UI 更新,同时通知后端中止处理。
前端的停止操作分两步:
- 立即中止前端流:调用
reader.cancel()关闭 ReadableStream,停止读取后续 chunk。同时清除缓冲区,移除光标动画,将状态标记为cancelled - 通知后端中止:通过 AbortController 中止 fetch 请求,后端收到连接断开信号后停止模型调用。如果后端支持,也可以通过单独的 API 调用发送取消信号
const abortController = new AbortController()
async function stopGeneration() {
// 中止前端流
await reader?.cancel()
// 中止 fetch 请求
abortController.abort()
// 清除缓冲区和动画
clearBuffer()
removeCursor()
// 更新状态
setState({ ...state, status: 'cancelled' })
}停止操作的一个重要细节:取消后保留已接收的部分内容。用户可能已经在已生成的内容中看到了有价值的信息,不应该因为取消而丢失这些内容。同时,提供一个「继续生成」按钮让用户可以从断点恢复。
四、错误处理和重试机制
AI 工具的错误处理比普通 Web 应用更复杂,因为错误可能发生在流式传输的任何阶段。
4.1 常见的错误类型
| 错误类型 | 触发场景 | 用户感知 | 处理策略 |
|---|---|---|---|
| 网络断开 | Wi-Fi 切换、信号弱 | 内容停止生成 | 自动重试或提示手动重试 |
| 超时 | 模型负载高、复杂任务 | 长时间无响应 | 显示超时提示,提供重试 |
| 内容过滤 | 触发安全策略 | 生成中断,显示提示 | 提示修改输入内容 |
| Token 超限 | 输入 + 输出超过模型限制 | 生成截断 | 提示缩短输入或分次生成 |
| 服务端错误 | 500、502、503 | 生成中断 | 自动重试(指数退避) |
| 速率限制 | 超过 API 调用频率 | 请求被拒绝 | 排队等待或提示稍后重试 |
| 解析错误 | SSE 数据格式异常 | 内容显示异常 | 保留已接收内容,提示异常 |
4.2 重试策略
重试不是简单的「失败了再来一次」。一个好的重试机制需要考虑以下几点:
指数退避。重试间隔应该递增:第一次 1 秒,第二次 2 秒,第三次 4 秒。避免在服务端过载时频繁重试加重负担。
最大重试次数。设置上限(通常 3 次),超过后提示用户手动操作或联系客服。
幂等性检查。对于生成类任务,重试前确认上一次请求是否已经完成。避免网络延迟导致的重复生成。
保留部分内容。如果流式传输中途断开,保留已经接收到的内容,让用户选择「继续生成」或「重新开始」,而不是丢弃所有内容。
async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options)
if (response.status === 429) {
// 速率限制:使用 Retry-After 头
const retryAfter = response.headers.get('Retry-After')
await sleep(retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000)
continue
}
if (!response.ok && response.status >= 500) {
await sleep(Math.pow(2, attempt) * 1000)
continue
}
return response
} catch (error) {
if (attempt === maxRetries - 1) throw error
await sleep(Math.pow(2, attempt) * 1000)
}
}
}4.3 错误信息展示
错误信息的展示直接影响用户的挫败感。几个原则:
- 说人话:不要给用户看
502 Bad Gateway,告诉他们「服务暂时不可用,请稍后重试」 - 提供可操作的建议:告诉用户下一步该做什么——重试、修改输入、检查网络
- 区分可恢复和不可恢复错误:网络断开可以重试,内容被过滤需要修改输入
- 在正确的位置展示:错误信息应该出现在输出区而不是弹窗,保持上下文连贯
4.4 超时处理
AI 工具的超时处理比一般 API 更复杂,因为你无法预知模型需要多长时间才能返回结果。以下是几种常见的超时策略:
首字节超时。设置一个较长的超时时间(例如 30-60 秒)等待第一个 chunk 到达。如果在超时时间内没有收到任何数据,认为请求失败,提示用户重试或降低任务复杂度。
chunk 间隔超时。一旦开始接收数据,可以设置一个较短的 chunk 间隔超时(例如 15 秒)。如果连续 15 秒没有收到新 chunk,认为连接可能已经中断。
总时长超时。对于某些任务类型(如图片生成),可以设置一个总时长上限。超时后自动取消任务并通知用户。
超时处理的用户体验关键:超时发生时,保留所有已经接收到的内容(如果有的话),明确告知用户发生了什么,提供「重试」和「修改输入后重试」两个选项。
4.5 错误处理策略对比
| 策略 | 适用场景 | 实现方式 | 用户体验 |
|---|---|---|---|
| 静默重试 | 网络瞬断、502/503 | 自动重试 3 次,用户无感知 | 最好——用户完全不知道出了问题 |
| 提示后重试 | 超时、服务端错误 | 显示错误信息 + 重试按钮 | 好——用户知情,可自主决定 |
| 降级展示 | 模型不可用、限流 | 切换到备用模型或返回缓存结果 | 中——结果可能不如预期但不会中断 |
| 保留部分内容 | 流中断、内容过滤 | 展示已生成内容 + 继续/重试选项 | 好——不浪费已完成的处理 |
| 引导修改 | 内容违规、Token 超限 | 显示具体原因 + 修改建议 | 中——需要用户配合调整 |
| 排队等待 | 速率限制、高并发 | 显示队列位置和预计等待时间 | 中——需要用户耐心等待 |
五、无障碍访问
AI 工具的无障碍访问是一个容易被忽视但越来越重要的领域。流式输出对屏幕阅读器来说尤其具有挑战性——如果处理不当,阅读器可能会逐字播报每一个新 token,造成严重的听觉干扰。
5.1 ARIA 属性配置
输出区需要使用 aria-live="polite" 让屏幕阅读器在新内容到达时自动播报,同时设置 aria-atomic="false" 表示只播报新增内容而非整个消息。角色设置为 role="log" 可以让阅读器以日志模式处理内容追加。
<div role="log" aria-live="polite" aria-atomic="false" aria-label="AI 回复">
{streamingContent}
</div>5.2 光标与动画的无障碍处理
视觉光标(闪烁的竖线)对屏幕阅读器用户没有意义,应该通过 aria-hidden="true" 隐藏,避免阅读器将光标符号读出。对于使用 prefers-reduced-motion 的用户,应该跳过渡印动画(打字效果、光标闪烁),直接展示完整内容。
@media (prefers-reduced-motion: reduce) {
.streaming-cursor {
animation: none;
}
.typewriter-effect {
/* 直接显示全部内容 */
transition: none;
}
}5.3 键盘操作支持
所有控制按钮必须支持键盘操作(Tab 导航、Enter/Space 触发)。停止生成按钮应该有明确的焦点指示。输入区的文本框应该支持 aria-describedby 关联字数限制提示。
对于多轮对话场景,焦点管理尤其重要。当 AI 回复完成后,焦点应该停留在输入框(让用户可以继续输入),而不是跳到输出区顶部。当用户点击「重新生成」按钮时,焦点应该保持在按钮上或移到输出区。
5.4 国际化与多语言
AI 产品面向全球用户时,无障碍访问还涉及多语言支持。RTL(从右到左)语言的布局需要翻转,流式输出的文本方向也需要正确处理。不同语言的文本长度差异很大(例如德语通常比英语长 30%),输出区需要足够灵活以适应这种差异。日期、数字、货币的格式化应该使用 Intl API 而不是硬编码。
六、不同AI工具类型的页面设计对比
不同类型的 AI 工具,页面设计差异很大。理解这些差异有助于你为自己的产品选择合适的方案。
6.1 AI工具页面类型对比
| 维度 | 对话型(Chat) | 生成型(Generate) | 编辑型(Edit) | 对话+工具型(Agent) |
|---|---|---|---|---|
| 代表产品 | ChatGPT、Claude | Midjourney、Suno | Cursor、Notion AI | Claude with tools、Devin |
| 输入方式 | 单文本框 | 表单 + 参数面板 | 内联编辑 + 指令 | 文本框 + 工具调用 |
| 输出展示 | 对话气泡 | 结果卡片/画布 | 原文 + Diff 对比 | 对话 + 工具结果嵌入 |
| 流式需求 | 必须 | 可选(图片类通常不需要) | 可选 | 必须 |
| 历史记录 | 多轮对话 | 任务列表 | 版本历史 | 多轮对话 + 工具调用链 |
| 复杂度 | 中 | 低 | 高 | 最高 |
6.2 交互模式对比
| 交互模式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 单轮请求-响应 | 一次性任务(翻译、摘要) | 实现简单,状态少 | 无法迭代优化 |
| 多轮对话 | 聊天、问答、头脑风暴 | 支持上下文,可迭代 | 上下文管理复杂 |
| 表单 + 预览 | 图片生成、视频生成 | 参数可控,结果直观 | 页面布局复杂 |
| 画布 + 指令 | 代码编辑、文档编辑 | 所见即所得,效率高 | 编辑器开发成本高 |
| 工作流编排 | 复杂多步骤任务 | 可复用,可分享 | 学习曲线陡峭 |
七、用 AI 生成 AI 工具页面
你完全可以用 AI 工具来生成 AI 工具的使用页面。这听起来有些套娃,但实际上是非常高效的开发方式。
7.1 用 AI 生成页面的流程
第一步:准备页面需求描述。明确页面类型、核心功能、交互要求。例如:
请创建一个 AI 写作工具的使用页面。左侧是参数配置面板(文章类型、关键词、语气、字数范围),右侧是输出区域。输入提交后,输出区使用流式展示逐字显示生成的文章。需要提供停止生成、重新生成、复制结果三个按钮。
第二步:让 AI 生成基础组件。使用 Cursor、Claude Code 或 v0 生成初始代码。推荐使用 shadcn/ui 作为基础组件库,搭配 Tailwind CSS 做样式。
第三步:补充流式响应逻辑。AI 生成的页面通常只包含静态 UI,流式逻辑需要你额外描述清楚。明确告诉 AI:「使用 SSE 协议,后端 API 地址是 /api/generate,流式数据格式是 data: {"content": "..."}\n\n。」
第四步:处理边界情况。让 AI 补充空状态、加载状态、错误状态、长内容滚动等边界情况的处理。
7.2 AI工具生成的 Prompt 模板
以下是一个用于生成 AI 工具页面的通用 Prompt 模板:
请为我创建一个 AI {{工具类型}} 的使用页面,技术栈是 {{技术栈}}。
页面布局:
- {{布局描述}}
输入区:
- {{输入控件列表}}
- 提交按钮,提交后禁用
- 输入校验规则:{{校验规则}}
输出区:
- 支持流式展示,逐字/逐块显示
- 流式数据格式:{{数据格式}}
- 支持 {{输出类型}}(Markdown/代码/图片等)
控制按钮:
- 停止生成、重新生成、{{其他按钮}}
状态处理:
- 空状态:显示引导信息
- 加载中:显示 {{加载指示器类型}}
- 错误:显示错误信息 + 重试按钮
- 流中断:保留已生成内容 + 继续/重试选项
额外要求:
- 响应式设计,适配移动端
- 支持暗色模式
- 使用 {{组件库}} 作为基础
7.3 推荐的技术组合
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 快速原型 | v0 + Next.js | 对话式生成,直接预览 |
| 正式产品 | Next.js + shadcn/ui + Vercel AI SDK | 生态成熟,流式支持好 |
| 高度定制 | React + 自建组件 + Web Streams API | 完全控制,适合特殊需求 |
| Python 后端 | FastAPI + StreamingResponse + React | Python 生态 + 前端流式 |
7.4 AI 工具辅助生成能力对比
| 工具 | 适合生成的内容 | 流式支持 | 需要手动补充的部分 |
|---|---|---|---|
| v0 (Vercel) | 完整的 React 页面组件 | 可生成流式 UI 骨架 | 后端 SSE 对接、状态管理 |
| Cursor | 组件代码、Hook 逻辑、API 调用 | 可生成流式处理代码 | 边界情况、性能优化细节 |
| Claude Code | 完整功能模块、类型定义、测试 | 可生成完整流式方案 | 视觉细节、动画微调 |
| Bolt.new | 全栈应用(含后端) | 可生成前后端流式 | 生产级优化、错误恢复 |
八、实战案例分析
案例一:ChatGPT 的对话界面
背景: ChatGPT 是对话型 AI 工具的标杆产品,其界面设计影响了整个行业的设计范式。
界面分析:
-
输入区:底部固定的文本框,支持多行输入、文件上传、语音输入。Placeholder 从「Send a message」到「Ask anything」的演变,体现了引导用户主动使用的思路。Enter 发送、Shift+Enter 换行。
-
输出区:对话气泡形式,用户消息靠右,AI 回复靠左。回复内容支持 Markdown 渲染、代码高亮、表格展示。流式输出时显示光标,完成后出现操作按钮(复制、点赞、点踩、重新生成)。
-
流式处理:使用 SSE 协议,文本逐 token 显示。代码块在生成完成后才启用语法高亮和复制按钮。输出过程中自动滚动,用户上滚时暂停。
-
错误处理:网络中断时在消息流中插入「Something went wrong」提示,附带「Regenerate response」按钮。保留已生成的内容,不会因错误清空整个对话。
-
侧边栏:左侧展示历史对话列表,支持搜索、重命名、删除。新对话按钮始终可见。
核心设计启示: ChatGPT 的界面之所以成为行业标准,不在于功能多复杂,而在于它对「等待体验」的处理。流式输出、自动滚动、停止按钮、错误保留——这些细节让用户感觉「AI 就在我面前思考」。
案例二:Midjourney 的生成界面
背景: Midjourney 是 AI 绘图领域的代表产品。与对话型 AI 不同,图片生成任务的等待时间更长(通常 30-60 秒),输出是图片而非文本,这对界面设计提出了不同的要求。
界面分析:
-
输入方式:Discord 中使用
/imagine命令 + 提示词;Web 端使用文本框 + 丰富的参数面板(风格、比例、模型版本、混乱度等)。参数面板的设计让用户可以在不学习提示词语法的情况下获得高质量结果。 -
等待体验:由于图片生成无法逐像素流式展示,Midjourney 采用进度指示的方式。早期版本显示「Processing...」文字,后续版本加入了模糊预览图,让用户知道「图片正在成形」。
-
结果展示:生成完成后显示 4 张缩略图的网格。每张图下方提供 U(放大)和 V(变体)按钮,引导用户迭代优化。这种设计将「生成-评估-迭代」的循环做得非常流畅。
-
历史管理:Web 端的 Gallery 页面展示所有历史生成结果,支持筛选、收藏、下载。
核心设计启示: Midjourney 的案例说明,当输出类型不支持流式展示时,你可以通过进度指示、模糊预览、分步展示等替代方案来管理用户的等待感知。结果的展示方式(4 张网格 + 操作按钮)直接影响了用户的使用行为。
案例三:Cursor 的代码编辑界面
背景: Cursor 是基于 VS Code 的 AI 代码编辑器,代表了「编辑型」AI 工具的设计范式。
界面分析:
-
双模式交互:Cmd+K 打开内联编辑(在代码中直接修改),Cmd+L 打开侧边对话(讨论和解释代码)。两种模式覆盖了代码编辑的主要场景。
-
流式 Diff 展示:AI 修改代码时,使用红绿 Diff 高亮逐行展示变更。这不是简单的文本流式,而是结构化的 Diff 流式——新增行和删除行实时出现,用户可以实时看到代码的变化。
-
接受/拒绝机制:每个修改块提供 Accept / Reject 按钮。用户可以逐块审查 AI 的修改,而不是全盘接受或拒绝。这种细粒度的控制权对开发者来说非常重要。
-
上下文引用:输入
@可以引用文件、符号、文档等上下文。这让 AI 能更精准地理解代码库的结构。
核心设计启示: Cursor 的设计证明,AI 工具的界面不一定是对话形式。对于专业用户,将 AI 能力嵌入到他们已有的工作流中(代码编辑器),比让他们适应一个新的对话界面更有效。
案例四:Claude 的 Artifacts 功能
背景: Claude 的 Artifacts 功能代表了「对话 + 画布」混合模式的设计范式。用户在对话中生成代码、文档或可视化内容,这些内容会在右侧的独立画布中实时渲染和预览。
界面分析:
-
双栏布局:左侧是对话区,右侧是 Artifacts 画布。两个区域可以独立调整大小。对话区负责沟通和指令,画布负责展示和交互
-
流式 + 实时渲染:代码类型的 Artifact 在流式生成过程中就实时渲染——HTML 即时显示页面效果,React 组件即时可交互。这种设计让用户不需要等代码完全生成就能看到效果
-
版本管理:每个 Artifact 支持多版本切换。用户可以对比不同版本的输出,回滚到之前的版本。这种设计降低了「一次生成不满意就要重来」的焦虑
-
导出能力:Artifact 可以一键复制代码、下载文件或在浏览器中打开。导出格式根据内容类型自动选择
核心设计启示: Claude 的 Artifacts 展示了一种新的 AI 交互范式——对话和创作分离。对话负责意图沟通,画布负责内容展示和交互。这种模式特别适合「生成复杂产物」的场景(代码、文档、图表),比纯对话模式的体验更好。
九、AI工具页面开发流程
以下是从零开发一个 AI 工具使用页面的完整流程:
十、检查清单
在发布 AI 工具使用页面前,逐项确认以下内容:
- 输入引导完善:Placeholder 或示例提示清晰,用户知道可以输入什么
- 输入校验到位:字数限制、必填项、格式校验在提交前完成
- 提交防重复:发送按钮在请求处理期间禁用,防止重复提交
- 加载状态完整:提交确认、处理中指示、流式展示三层反馈全部实现
- 流式渲染稳定:Markdown 缓冲渲染、代码块延迟高亮、布局无偏移
- 自动滚动合理:内容追加时自动滚动到底部,用户上滚时暂停
- 停止按钮可用:流式输出过程中可以随时停止,停止后清除缓冲和动画
- 错误恢复友好:错误信息可理解,支持重试,部分内容不丢失
- 空状态有引导:首次进入或清空后,展示使用引导或示例
- 历史记录可访问:用户可以找到并回顾之前的对话或任务
- 移动端适配:输入区、输出区、按钮在移动端可用,不存在溢出或重叠
- 暗色模式支持:所有组件(包括代码高亮、加载动画)在暗色模式下显示正常
- 无障碍访问:使用
aria-live="polite"让屏幕阅读器播报新内容,尊重prefers-reduced-motion设置 - 性能基准达标:长对话场景下无卡顿,虚拟滚动正常工作,内存无泄漏
- Token 计费准确:如果涉及计费,输入和输出的 token 计数准确,并在界面上可见
十一、小结
- AI 工具使用页面是产品的核心触点,由输入区、输出区、控制按钮和历史记录四部分组成
- 交互设计的核心是管理用户的等待感知——提交确认、处理中指示、流式展示三层反馈缺一不可
- SSE 是目前最主流的流式方案,前端使用 Web Streams API 处理,注意缓冲渲染和虚拟滚动
- 错误处理要区分错误类型,保留已接收内容,提供可操作的恢复建议
- 无障碍访问不是可选项——ARIA 属性、减少动画、键盘导航是必须实现的基础能力
- 不同类型的 AI 工具(对话型、生成型、编辑型、Agent 型)需要不同的页面设计策略
- 可以用 AI 生成 AI 工具页面,但流式逻辑和边界情况需要额外描述,AI 工具擅长生成静态 UI,流式处理和状态管理需要你补充清晰的描述
- 发布前务必逐项检查输入引导、流式渲染、错误恢复、无障碍访问等 15 个关键点
AI 工具的使用页面是用户与产品之间最直接的接触点。在这个页面上,技术实现和用户体验是不可分割的——流式响应的技术方案直接影响用户的等待感受,错误处理的方式决定了用户遇到问题是留下还是离开。把这些细节做好,产品就有了竞争力。
参考资料
- AI SDK UI - Chatbot — Vercel AI SDK 的 useChat hook 文档,封装了流式对话的完整状态管理
- assistant-ui - React Chat UI for AI Apps — 开源 React 聊天 UI 组件库,支持流式、工具调用、主题定制
- prompt-kit - Chat UI Components for React — 即插即用的 React 聊天 UI 组件,包含流式响应渲染和 Markdown 处理
- The AI Chat Interface Playbook — AI 聊天界面的 5 个核心模式,从业余到专业的关键差异
- Designing Stable Interfaces for Streaming Content — Smashing Magazine 关于流式内容界面稳定性的深度文章
- What Is Streaming UI in AI Applications? — thefrontkit 对 Streaming UI 概念和设计模式的全面解读
- Outputs AI UX Pattern — Streaming — AI UX Playground 对流式输出交互模式的总结
- Chatbot UI (GitHub) — 开源 AI 聊天界面,支持任意模型,代码结构清晰适合学习参考