187 lines
7.6 KiB
Markdown
187 lines
7.6 KiB
Markdown
---
|
||
name: exam-analysis-page
|
||
overview: 新增"英语试题AI分析"页面(ExamAnalysis.vue),支持文本输入和图片上传两种方式,通过流式调用 Gemini API 对试题进行多维度深度解析,并实时展示分析结果。
|
||
design:
|
||
architecture:
|
||
framework: vue
|
||
styleKeywords:
|
||
- Glassmorphism
|
||
- Dark Theme
|
||
- Teal Accent
|
||
- Streaming Typewriter
|
||
- Card Layout
|
||
- Minimalism
|
||
fontSystem:
|
||
fontFamily: Inter
|
||
heading:
|
||
size: 1.2rem
|
||
weight: 600
|
||
subheading:
|
||
size: 1rem
|
||
weight: 500
|
||
body:
|
||
size: 0.95rem
|
||
weight: 400
|
||
colorSystem:
|
||
primary:
|
||
- "#14b8a6"
|
||
- "#0d9488"
|
||
background:
|
||
- "#0d0f17"
|
||
- rgba(255,255,255,0.03)
|
||
text:
|
||
- "#ffffff"
|
||
- "#94a3b8"
|
||
functional:
|
||
- "#ef4444"
|
||
- "#fca5a5"
|
||
- rgba(20,184,166,0.15)
|
||
todos:
|
||
- id: create-exam-analysis-page
|
||
content: 创建 src/views/ExamAnalysis.vue,实现双模式输入、流式 Gemini API 调用、五维度结果卡片及完整状态管理
|
||
status: completed
|
||
- id: register-route-and-update-homepage
|
||
content: 更新 src/router/index.js 注册 /exam-analysis 路由,并修改 src/views/HomePage.vue 中 card-4 的 route 为 '/exam-analysis'
|
||
status: completed
|
||
dependencies:
|
||
- create-exam-analysis-page
|
||
---
|
||
|
||
## 用户需求
|
||
|
||
开发一个英语试题 AI 分析页面,集成到现有 Vue 3 项目中,作为首页第 4 个功能卡片(英语试题AI分析)的目标页面。
|
||
|
||
## 产品概述
|
||
|
||
用户可通过文本输入或图片上传两种方式提交英语试题,系统调用 Gemini API 进行流式深度解析,分析结果实时逐字渲染展示,整体风格与现有页面保持一致(深色 Glassmorphism 风格,Teal 主题色)。
|
||
|
||
## 核心功能
|
||
|
||
- **双模式输入**:支持文本粘贴输入和图片上传(JPG/PNG,拖拽或点击),两种模式通过 Tab 切换
|
||
- **流式 AI 分析**:通过 axios + `onDownloadProgress` 回调流式调用 Gemini API,分析结果实时逐字输出
|
||
- **多维度解析展示**:将分析结果结构化展示为五个维度卡片:题干理解、考点识别、解题思路、正确答案、详细解析
|
||
- **实时流式渲染**:分析过程中显示打字机效果,内容逐步呈现,用户可看到实时生成进度
|
||
- **状态管理**:idle / analyzing / done / error 四种状态,含加载动画、错误提示、重新分析等交互
|
||
- **路由集成**:注册 `/exam-analysis` 路由,首页 card-4 的 `route: null` 更新为 `/exam-analysis`
|
||
|
||
## 技术栈
|
||
|
||
- **框架**:Vue 3 + `<script setup>` + Composition API(与现有项目一致)
|
||
- **路由**:vue-router(现有,仅新增路由条目)
|
||
- **HTTP/流式请求**:`axios` + `onDownloadProgress` 回调(Gemini SSE 流式响应,与项目现有 axios 依赖保持一致)
|
||
- **样式**:Scoped CSS,复用现有 CSS 变量(`--bg-color`、`--card-bg`、`--card-border`、`--text-primary`、`--text-secondary`、`--accent-4`)
|
||
|
||
## 实现方案
|
||
|
||
### 流式调用策略
|
||
|
||
Gemini API 支持 SSE(Server-Sent Events)流式输出。使用 `axios` 发起请求,设置 `responseType: 'text'`,通过 `onDownloadProgress` 回调监听每次数据块到达,从 `event.target.responseText` 中增量提取新内容,逐步拼接到响应字符串中,触发 Vue 响应式更新实现打字机效果。与项目现有 axios 依赖保持一致,无需引入额外依赖。
|
||
|
||
### 结构化解析策略
|
||
|
||
AI 返回的 Markdown 文本通过正则表达式按标题(`##` 或特定关键词)分割为五个维度模块,每个模块独立渲染为卡片。流式过程中实时更新当前正在生成的模块内容,已完成的模块保持稳定显示。
|
||
|
||
### Prompt 设计
|
||
|
||
系统 Prompt 要求 Gemini 严格按照固定格式输出,包含五个 `##` 标题段落,便于前端解析分割。
|
||
|
||
## 架构设计
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[ExamAnalysis.vue] --> B[输入区域 - Tab切换]
|
||
B --> C[文本输入 Textarea]
|
||
B --> D[图片上传 拖拽/点击]
|
||
A --> E[分析按钮]
|
||
E --> F[geminiStream 流式请求]
|
||
F --> G[axios + onDownloadProgress]
|
||
G --> H[event.target.responseText 增量提取]
|
||
H --> I[实时拼接 rawContent]
|
||
I --> J[parseAnalysis 解析分割]
|
||
J --> K[五维度卡片渲染]
|
||
A --> L[状态机: idle/analyzing/done/error]
|
||
```
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
src/
|
||
├── views/
|
||
│ └── ExamAnalysis.vue # [NEW] 英语试题AI分析页面主组件
|
||
│ # 包含:双模式输入(文本/图片Tab切换)、
|
||
│ # 流式调用 Gemini API、实时渲染分析结果、
|
||
│ # 五维度结构化卡片展示、完整状态管理
|
||
├── router/
|
||
│ └── index.js # [MODIFY] 新增 /exam-analysis 路由,
|
||
│ # import ExamAnalysis 并添加路由条目
|
||
└── views/
|
||
└── HomePage.vue # [MODIFY] 第37行 card-4 的 route: null
|
||
# 改为 route: '/exam-analysis'
|
||
```
|
||
|
||
## 关键实现细节
|
||
|
||
### 流式请求核心逻辑
|
||
|
||
```js
|
||
// Gemini API 流式调用(axios + onDownloadProgress)
|
||
const streamAnalysis = async (prompt, imageBase64 = null) => {
|
||
let lastLength = 0
|
||
await axios.post(GEMINI_API_URL, buildRequestBody(prompt, imageBase64), {
|
||
headers: { 'Content-Type': 'application/json', 'x-goog-api-key': API_KEY },
|
||
responseType: 'text',
|
||
onDownloadProgress: (event) => {
|
||
const text = event.target.responseText
|
||
const newChunk = text.slice(lastLength)
|
||
lastLength = text.length
|
||
// 解析 SSE data 行,提取 text delta
|
||
rawContent.value += extractTextDelta(newChunk)
|
||
analysisBlocks.value = parseAnalysis(rawContent.value)
|
||
}
|
||
})
|
||
}
|
||
```
|
||
|
||
### 分析结果解析
|
||
|
||
将 AI 输出按 `## 题干理解 / ## 考点识别 / ## 解题思路 / ## 正确答案 / ## 详细解析` 五个标题分割,每个块独立渲染,支持基础 Markdown(加粗、换行)。
|
||
|
||
### 性能注意事项
|
||
|
||
- 流式更新频率较高,`parseAnalysis` 使用轻量正则,避免每次 chunk 触发重量级 DOM 操作
|
||
- 图片 base64 转换在 `FileReader` 异步完成后才启用分析按钮,防止空数据提交
|
||
- 组件卸载时调用 `axios.CancelToken` 中止未完成的流请求,防止内存泄漏
|
||
|
||
## 设计风格
|
||
|
||
延续现有项目的深色 Glassmorphism 风格,以 Teal(#14b8a6 / #0d9488)为主题色,与首页 card-4 保持一致。整体布局参考 EssayCorrection.vue 的三段式结构:顶部固定导航栏 + 中部内容区 + 底部结果区。
|
||
|
||
## 页面布局
|
||
|
||
### 1. 顶部导航栏
|
||
|
||
固定在顶部,毛玻璃背景,左侧返回按钮,中间标题"英语试题 AI 分析"(Teal 渐变文字),与其他页面导航栏完全一致的视觉规范。
|
||
|
||
### 2. 输入区域(Tab 切换)
|
||
|
||
两个 Tab 标签(文本输入 / 图片上传),Teal 色激活态下划线。
|
||
|
||
- **文本 Tab**:大尺寸 Textarea,深色背景,Teal 聚焦边框光晕,占位符提示文字
|
||
- **图片 Tab**:虚线上传区(Teal 色边框),支持拖拽,图片预览缩略图,重新上传按钮
|
||
|
||
### 3. 分析按钮
|
||
|
||
居中大按钮,Teal 渐变背景,分析中显示旋转 Spinner + "分析中..."文字,禁用态半透明。
|
||
|
||
### 4. 分析结果区域
|
||
|
||
五个维度卡片纵向排列,每张卡片:
|
||
|
||
- 左侧 Teal 色竖线 + 图标 + 标题
|
||
- 卡片内容区白色文字,支持基础 Markdown 渲染(加粗、换行)
|
||
- 流式生成中的卡片末尾显示闪烁光标动画
|
||
- 卡片入场动画(fadeInUp,依次延迟)
|
||
|
||
### 5. 错误提示
|
||
|
||
红色半透明 Banner,可关闭,与 EssayCorrection.vue 保持一致。 |