feat(views): 添加AI智能解题功能页面

This commit is contained in:
cc 2026-03-24 10:52:00 +08:00
parent b0ff44887c
commit 9be5af017f
5 changed files with 1781 additions and 2 deletions

View File

@ -0,0 +1,210 @@
---
name: AI智能解题功能开发
overview: 开发一个支持多轮对话的AI智能解题页面用户可通过文本或图片上传试题AI以卡片式步骤引导用户思考并解答题目。
design:
architecture:
framework: vue
styleKeywords:
- Glassmorphism
- Dark Theme
- Card-based Layout
- Streaming Animation
fontSystem:
fontFamily: Inter
heading:
size: 1.2rem
weight: 600
subheading:
size: 1rem
weight: 500
body:
size: 0.95rem
weight: 400
colorSystem:
primary:
- "#6366f1"
- "#8b5cf6"
background:
- "#0d0f17"
- rgba(255,255,255,0.03)
text:
- "#ffffff"
- "#94a3b8"
functional:
- "#6366f1"
- "#14b8a6"
- "#ef4444"
todos:
- id: create-problem-solving-page
content: 创建 ProblemSolving.vue 页面,实现输入面板和对话展示区布局
status: completed
- id: implement-input-panel
content: 实现文本输入和图片上传Tab切换功能
status: completed
dependencies:
- create-problem-solving-page
- id: implement-dialog-engine
content: 实现多轮对话核心引擎和消息历史管理
status: completed
dependencies:
- create-problem-solving-page
- id: implement-card-rendering
content: 实现卡片式步骤解析和流式渲染逻辑
status: completed
dependencies:
- implement-dialog-engine
- id: update-config
content: 更新配置文件添加解题API参数
status: completed
- id: update-router
content: 更新路由配置添加解题页面路由
status: completed
dependencies:
- create-problem-solving-page
- id: update-homepage
content: 更新首页添加AI智能解题功能卡片
status: completed
dependencies:
- update-router
---
## 产品概述
开发一个AI智能解题页面支持用户通过文本输入或图片上传提交试题通过多轮对话交互方式逐步引导用户思考并完成解题。
## 核心功能
- **双重输入方式**:支持文本输入和图片上传两种试题提交方式
- **AI图片分析**上传图片后由AI直接识别并分析图片中的试题内容
- **多轮对话交互**AI逐步引导用户思考支持用户追问和互动
- **卡片式步骤展示**:每个解题步骤以独立卡片形式展示,清晰易懂
- **通用学科支持**:支持数学、物理、化学等多学科题目
- **流式输出**实时显示AI解题过程提升用户体验
## 技术栈选择
- **前端框架**Vue 3 + Composition API (script setup)
- **路由**Vue Router
- **HTTP客户端**Axios流式输出
- **AI模型**GRS AI API (gemini-3.1-pro) - 支持图文混合输入
- **样式**Scoped CSS + CSS Variables
## 实现方案
### 页面架构
采用左右分栏布局:左侧为输入区(文本/图片上传),右侧为多轮对话展示区。参考 ExamAnalysis.vue 的布局结构和 Speaking.vue 的多轮对话逻辑。
### 对话流程设计
1. 用户提交试题后AI首先分析题目并输出初步理解
2. AI逐步给出解题步骤每步一个卡片
3. 用户可在任意步骤提问或请求详细解释
4. AI根据用户反馈调整后续引导策略
### System Prompt 设计
设计引导式解题Prompt要求AI
- 先理解题目类型和关键信息
- 分步骤给出解题思路
- 每步引导用户思考而非直接给答案
- 鼓励用户参与互动
### 图片处理方案
复用 ExamAnalysis.vue 的图片上传和Base64编码逻辑构建 OpenAI 兼容格式的多模态请求text + image_url
## 架构设计
```
┌─────────────────────────────────────────────────────┐
│ ProblemSolving.vue │
├──────────────────┬──────────────────────────────────┤
│ 输入面板(左) │ 对话面板(右) │
│ ┌────────────┐ │ ┌────────────────────────────┐ │
│ │ Tab切换 │ │ │ 对话消息列表 │ │
│ │ - 文本输入 │ │ │ - 用户消息气泡 │ │
│ │ - 图片上传 │ │ │ - AI消息卡片(步骤展示) │ │
│ └────────────┘ │ │ - 步骤标题 │ │
│ ┌────────────┐ │ │ - 步骤内容 │ │
│ │ 提交按钮 │ │ │ - 流式输出动画 │ │
│ └────────────┘ │ └────────────────────────────┘ │
└──────────────────┴──────────────────────────────────┘
```
## 目录结构
```
c:/code/work/AI_Demo/
├── src/
│ ├── views/
│ │ └── ProblemSolving.vue # [NEW] AI智能解题页面。实现多轮对话交互、图文输入、卡片式步骤展示。核心功能包括试题提交(文本/图片)、对话历史管理、AI流式响应解析、卡片式步骤渲染。
│ ├── router/
│ │ └── index.js # [MODIFY] 添加 /problem-solving 路由
│ ├── config/
│ │ └── index.js # [MODIFY] 添加解题API配置(PROBLEM_API_URL, PROBLEM_MODEL, PROBLEM_SYSTEM_PROMPT)
│ └── views/
│ └── HomePage.vue # [MODIFY] 添加"AI智能解题"功能卡片(第7个)
```
## 关键实现细节
### 1. 多轮对话历史管理
```javascript
// 对话消息结构
const messages = ref([])
// 消息格式: { id, role: 'user'|'assistant', content, type: 'text'|'step', stepData?: {...} }
```
### 2. 流式输出处理
复用 ExamAnalysis.vue 的 SSE 解析逻辑,增加对话历史追加机制。
### 3. 卡片式步骤解析
AI输出使用特定格式标记步骤
```
## 步骤1理解题意
...
## 步骤2分析条件
...
```
解析后渲染为独立卡片。
### 4. 图片上传处理
- 支持格式JPG、PNG、WebP
- 大小限制10MB
- 编码方式Base64
- 请求格式OpenAI多模态格式
## 设计风格
延续项目现有的深色主题与玻璃态设计风格,打造沉浸式解题体验。
## 页面布局
- **顶部导航栏**:返回按钮 + 页面标题
- **主体区域**:左右分栏布局
- 左侧40%输入面板包含Tab切换文本/图片)、输入区域、提交按钮
- 右侧60%):对话展示区,垂直滚动显示对话历史
- **移动端**:上下堆叠布局
## 视觉设计
- 背景使用深色渐变(#0d0f17配合紫色调光晕效果
- 卡片使用半透明背景rgba(255,255,255,0.03)+ 模糊效果
- 步骤卡片左侧带有主题色边框标识
- AI消息卡片带有微妙的发光动画
## 交互设计
- 输入框聚焦时边框高亮
- 卡片淡入上浮动画fadeInUp
- 流式输出时显示打字光标闪烁效果
- 按钮hover时轻微上移+阴影增强

View File

@ -42,6 +42,11 @@ export const ARK_HISTORY_LIMIT = 20; // 保留最近对话条数
// ── 外部链接 ──
export const LISTENING_AUDIO_URL = "https://jz5k88k7vv.coze.site"; // 听力音频生成
// 智能解题接口(使用 Doubao-Seed-2.0-lite
export const PROBLEM_API_URL = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";
export const PROBLEM_MODEL = "doubao-seed-2-0-lite-260215";
export const PROBLEM_API_KEY = "2d46f767-6476-4858-8041-540fcae99808"; // 使用 DOUBAO_KEY
// ── 文件上传限制 ──
export const IMAGE_MAX_SIZE_MB = 10;
export const IMAGE_ALLOWED_TYPES_ESSAY = ["image/jpeg", "image/jpg", "image/png"];

View File

@ -5,6 +5,7 @@ import Speaking from '../views/Speaking.vue'
import EssayCorrection from '../views/EssayCorrection.vue'
import ExamAnalysis from '../views/ExamAnalysis.vue'
import SpellPractice from '../views/SpellPractice.vue'
import ProblemSolving from '../views/ProblemSolving.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@ -39,6 +40,11 @@ const router = createRouter({
name: 'spell-practice',
component: SpellPractice
},
{
path: '/problem-solving',
name: 'problem-solving',
component: ProblemSolving
},
]
})

View File

@ -53,6 +53,14 @@ const features = ref([
icon: "speaker",
route: "/pronunciation",
},
{
id: 7,
title: "AI智能解题",
desc: "支持文本或图片上传题目AI 以对话方式一步步引导思考,卡片式展示解题步骤,让解题过程清晰易懂,支持多学科通用解题。",
class: "card-7",
icon: "puzzle",
route: "/problem-solving",
},
]);
// Hover effect for glassmorphism glare
@ -218,6 +226,22 @@ onUnmounted(() => {
d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z"
/>
</svg>
<!-- Puzzle Icon (Brain/Puzzle) -->
<svg
v-else-if="feature.icon === 'puzzle'"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
/>
</svg>
</div>
<h2 class="card-title">{{ feature.title }}</h2>
</div>
@ -391,8 +415,8 @@ h1 {
}
.card-7 .icon-wrapper {
background: linear-gradient(135deg, #f472b6, #db2777);
box-shadow: 0 8px 20px -6px rgba(244, 114, 182, 0.5);
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
box-shadow: 0 8px 20px -6px rgba(139, 92, 246, 0.5);
}
.card-title {

1534
src/views/ProblemSolving.vue Normal file

File diff suppressed because it is too large Load Diff