AI.Demo/DEPLOY.md

492 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AI 英语学习辅助平台 — 线上部署操作流程
## 项目概述
- **项目名称**AI 英语学习辅助平台
- **技术栈**Vue 3 + Vite + Vue RouterHistory 模式)
- **项目结构**纯前端静态文件HTML / CSS / JS可部署到任意静态托管服务
---
## 一、部署前准备
### 1.1 环境要求
| 工具 | 版本要求 | 用途 |
|------|----------|------|
| Node.js | >= 18.x推荐 20.x LTS | 前端构建 |
| npm | >= 9.x | 包管理器 |
```bash
# 检查 Node.js 和 npm 版本
node -v
npm -v
```
### 1.2 安装依赖
```bash
# 安装前端依赖
cd AI_Demo
npm install
```
---
## 二、关键配置说明
### 2.1 API 配置(必须在部署前确认)
项目所有 API 密钥集中在 `src/config/index.js`,部署前请确认以下配置项均已填写正确:
| 配置项 | 说明 |
|--------|------|
| `GRS_API_KEY` | GRS AI 接口密钥(作文批改) |
| `DOUBAO_KEY` | 豆包 API 密钥 |
| `DOUBAO_APP_ID` | 豆包语音 App ID |
| `DOUBAO_ACCESS_TOKEN` | 豆包语音访问令牌 |
| `DOUBAO_RESOURCE_ID` | 豆包 TTS 资源 ID |
| `DOUBAO_ASR_RESOURCE_ID` | 豆包 ASR 资源 ID |
| `ARK_API_KEY` | 火山引擎 Ark 大模型密钥(口语对话) |
| `ARK_MODEL` | Ark 模型名称(如 doubao-pro-4k |
### 2.2 跨域响应头要求(重要)
项目使用了 `@ffmpeg/ffmpeg`WebAssembly需要服务器返回以下响应头
```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```
> 各部署平台的配置方式见下方对应章节。
### 2.3 API 代理配置(重要)
项目在开发环境通过 Vite 代理转发以下 API 请求,**生产环境必须在服务器/网关层配置对应的反向代理**
| 前端请求路径前缀 | 代理目标 | 用途 | 备注 |
|-----------------|----------|------|------|
| `/tts-api` | `https://openspeech.bytedance.com` | 豆包 TTS 语音合成 | 需要反向代理 |
| `/ark-api` | `https://ark.cn-beijing.volces.com` | 火山引擎 Ark 大模型 | 需要反向代理 |
| `/dashscope-api` | `https://dashscope.aliyuncs.com` | 阿里云百炼 | 需要反向代理 |
| `/asr-ws` | `wss://openspeech.bytedance.com` | 豆包 ASR WebSocket | 需要反向代理+注入鉴权 Header |
> **ASR WebSocket 特殊说明**`/asr-ws` 代理需要在代理层注入以下鉴权 Header浏览器原生 WebSocket 不支持自定义 Header
> - `X-Api-App-Key`
> - `X-Api-Access-Key`
> - `X-Api-Resource-Id`
> - `X-Api-Connect-Id`(每次连接随机 UUID
---
## 三、构建生产包
### 3.1 前端构建
```bash
npm run build
```
构建完成后,产物位于 `dist/` 目录,包含:
```
dist/
├── index.html
├── favicon.svg
└── assets/
├── *.js
└── *.css
```
可在本地预览构建结果:
```bash
npm run preview
```
---
## 四、部署方案
### 方案 ANginx 部署(推荐,自有服务器)
#### 4.A.1 上传文件
`dist/` 目录内容上传到服务器,例如 `/var/www/ai-demo/`
```bash
scp -r dist/* user@your-server:/var/www/ai-demo/
```
#### 4.A.2 Nginx 配置
创建或修改 Nginx 站点配置文件(如 `/etc/nginx/sites-available/ai-demo.conf`
```nginx
server {
listen 80;
server_name your-domain.com; # 替换为你的域名或 IP
root /var/www/ai-demo;
index index.html;
# 跨域响应头
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
# Vue Router History 模式:所有路由回退到 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 代理:豆包 TTS
location /tts-api/ {
proxy_pass https://openspeech.bytedance.com/;
proxy_ssl_server_name on;
proxy_set_header Host openspeech.bytedance.com;
}
# 代理:火山引擎 Ark
location /ark-api/ {
proxy_pass https://ark.cn-beijing.volces.com/;
proxy_ssl_server_name on;
proxy_set_header Host ark.cn-beijing.volces.com;
}
# 代理:阿里云百炼
location /dashscope-api/ {
proxy_pass https://dashscope.aliyuncs.com/;
proxy_ssl_server_name on;
proxy_set_header Host dashscope.aliyuncs.com;
}
# 代理:豆包 ASR WebSocket需注入鉴权 Header
location /asr-ws/ {
proxy_pass https://openspeech.bytedance.com/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host openspeech.bytedance.com;
proxy_ssl_server_name on;
# 注入豆包 ASR 鉴权 Header替换为实际值
proxy_set_header X-Api-App-Key "YOUR_DOUBAO_APP_ID";
proxy_set_header X-Api-Access-Key "YOUR_DOUBAO_ACCESS_TOKEN";
proxy_set_header X-Api-Resource-Id "volc.bigasr.sauc.duration";
}
# 静态资源缓存
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
}
}
```
```
#### 4.A.3 启用配置并重启 Nginx
```bash
# 启用站点Ubuntu/Debian
ln -s /etc/nginx/sites-available/ai-demo.conf /etc/nginx/sites-enabled/
# 检查配置语法
nginx -t
# 重载 Nginx
systemctl reload nginx
```
#### 4.A.4 配置 HTTPS推荐
```bash
# 使用 Certbot 申请免费 SSL 证书
apt install certbot python3-certbot-nginx
certbot --nginx -d your-domain.com
```
---
### 方案 BNode.js + Express 部署
适用于需要在 Node.js 环境中自定义响应头的场景。
创建前端静态服务器文件 `frontend-server.js`(项目根目录):
```js
import express from 'express'
import { createProxyMiddleware } from 'http-proxy-middleware'
import { fileURLToPath } from 'url'
import path from 'path'
import crypto from 'crypto'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const app = express()
const PORT = process.env.PORT || 3000
// 第三方 API 代理
app.use('/tts-api', createProxyMiddleware({
target: 'https://openspeech.bytedance.com',
changeOrigin: true,
pathRewrite: { '^/tts-api': '' }
}))
app.use('/ark-api', createProxyMiddleware({
target: 'https://ark.cn-beijing.volces.com',
changeOrigin: true,
pathRewrite: { '^/ark-api': '' }
}))
app.use('/dashscope-api', createProxyMiddleware({
target: 'https://dashscope.aliyuncs.com',
changeOrigin: true,
pathRewrite: { '^/dashscope-api': '' }
}))
app.use('/asr-ws', createProxyMiddleware({
target: 'wss://openspeech.bytedance.com',
changeOrigin: true,
ws: true,
pathRewrite: { '^/asr-ws': '' },
on: {
proxyReqWs: (proxyReq) => {
proxyReq.setHeader('X-Api-App-Key', process.env.DOUBAO_APP_ID)
proxyReq.setHeader('X-Api-Access-Key', process.env.DOUBAO_ACCESS_TOKEN)
proxyReq.setHeader('X-Api-Resource-Id', 'volc.bigasr.sauc.duration')
proxyReq.setHeader('X-Api-Connect-Id', crypto.randomUUID())
}
}
}))
// 静态文件服务
app.use(express.static(path.join(__dirname, 'dist')))
// Vue Router History 模式回退
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(PORT, () => {
console.log(`Frontend server running at http://localhost:${PORT}`)
})
```
#### 4.B.3 安装前端服务器依赖
```bash
# 在项目根目录安装
npm install express http-proxy-middleware
```
#### 4.B.4 启动前端服务器
```bash
# 在项目根目录启动
DOUBAO_APP_ID=xxx DOUBAO_ACCESS_TOKEN=xxx pm2 start frontend-server.js --name ai-demo-frontend
# 查看两个服务的状态
pm2 status
# 设置开机自启
pm2 save
```
前端服务运行在 `http://localhost:3000`(提供静态文件和代理)
---
### 方案 CEdgeOne Pages / Vercel / Netlify纯静态托管
> **注意**:此类平台**不支持服务端代理**`/tts-api`、`/ark-api`、`/dashscope-api`、`/asr-ws` 等接口将因跨域或缺少鉴权 Header 而失败。
> 建议仅用于演示。
#### 部署步骤(以 Vercel 为例)
1. 将项目推送到 GitHub
2. 在 Vercel 控制台导入仓库
3. 构建命令:`npm run build`,输出目录:`dist`
4. 创建 `vercel.json` 配置 History 模式路由回退和响应头:
```json
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }],
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
]
}
]
}
```
---
## 五、部署后验证清单
### 5.1 部署验证
| 验证项 | 检查方法 |
|--------|----------|
| 页面正常加载 | 访问首页,确认功能卡片显示正常 |
| 路由刷新不 404 | 直接访问 `/pronunciation`、`/speaking` 等子路由 |
| COOP/COEP 响应头 | 浏览器 DevTools → Network → 查看 index.html 响应头 |
| TTS 语音合成 | 进入发音练习页,测试语音播放 |
| ASR 语音识别 | 进入口语对话页,测试麦克风录音识别 |
| 作文批改 | 进入作文批改页,提交一段英文作文 |
| 试题分析 | 进入试题分析页,上传图片或输入题目 |
| 单词拼写练习 | 进入单词拼写页,测试拼写检测功能 |
---
## 六、常见问题排查
### Q1页面报错 `SharedArrayBuffer is not defined`
**原因**:服务器未返回 `Cross-Origin-Opener-Policy: same-origin``Cross-Origin-Embedder-Policy: require-corp` 响应头。
**解决**:参考第二节 2.2,在 Nginx 或 Node.js 服务器中添加对应响应头。
### Q2刷新页面出现 404
**原因**Vue Router 使用 History 模式,服务器未配置路由回退。
**解决**Nginx 添加 `try_files $uri $uri/ /index.html;`Node.js 添加通配路由返回 `index.html`
### Q3API 请求跨域报错CORS
**原因**:生产环境未配置反向代理,浏览器直接请求第三方 API 被跨域拦截。
**解决**:参考第二节 2.3,在 Nginx 或 Node.js 中配置对应代理规则。
### Q4ASR 语音识别 WebSocket 连接失败
**原因**:代理未注入豆包 ASR 鉴权 Header或 WebSocket 升级配置缺失。
**解决**:确认 Nginx 配置中包含 `proxy_set_header Upgrade $http_upgrade;` 及三个 `X-Api-*` Header。
### Q5构建时内存不足
**原因**:项目依赖较多,构建产物较大。
**解决**
```bash
# 增大 Node.js 内存限制
NODE_OPTIONS=--max-old-space-size=4096 npm run build
```
---
## 七、页面路由清单
| 路由路径 | 页面名称 | 功能说明 |
|----------|----------|----------|
| `/` | 首页 | 功能导航卡片 |
| `/pronunciation` | 发音练习 | TTS 语音合成,音标学习 |
| `/speaking` | 口语对话 | ASR 语音识别AI 对话 |
| `/essay-correction` | 作文批改 | 图片/文本作文批改 |
| `/exam-analysis` | 试题分析 | 图片题目分析解答 |
| `/spell-practice` | 单词拼写 | 单词拼写练习检测 |
| `/problem-solving` | 解题指导 | AI 解题步骤指导 |
| `/question-generator` | 题目生成 | 自动生成练习题 |
| `/question-variant` | 题目变体 | 生成相似题目变体 |
| `/audio-to-text` | 语音转文字 | 音频转文本功能 |
---
## 八、依赖版本参考
### 前端依赖package.json
| 依赖包 | 版本 |
|--------|------|
| vue | ^3.5.30 |
| vue-router | ^5.0.3 |
| vite | ^8.0.0 |
| @ffmpeg/ffmpeg | ^0.12.15 |
| @ffmpeg/util | ^0.12.2 |
| axios | ^1.13.6 |
| marked | ^17.0.5 |
| pako | ^2.1.0 |
## 九、目录结构参考
```
AI_Demo/
├── dist/ # 前端构建产物(部署此目录)
├── src/ # 前端源码
│ ├── config/index.js # API 密钥配置(部署前确认)
│ ├── router/index.js # 路由定义
│ ├── views/ # 页面组件
│ │ ├── HomePage.vue # 首页
│ │ ├── Pronunciation.vue # 发音练习
│ │ ├── Speaking.vue # 口语对话
│ │ ├── EssayCorrection.vue # 作文批改
│ │ ├── ExamAnalysis.vue # 试题分析
│ │ ├── SpellPractice.vue # 单词拼写
│ │ ├── ProblemSolving.vue # 解题指导
│ │ ├── QuestionGenerator.vue # 题目生成
│ │ ├── QuestionVariant.vue # 题目变体
│ │ └── AudioToText.vue # 语音转文字
│ ├── components/ # 公共组件
│ ├── assets/ # 静态资源
│ └── MainLayout.vue # 布局组件
├── vite.config.js # 开发代理配置(生产环境需在服务器复现)
├── package.json # 前端依赖配置
└── DEPLOY.md # 本文档
```
---
## 十、Docker 部署(可选)
### 10.1 构建镜像
```dockerfile
FROM node:20-alpine
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
RUN npm ci --only=production
# 复制源码
COPY . ./
# 构建
RUN npm run build
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
---
## 十一、安全建议
1. **HTTPS 强制**:生产环境务必启用 HTTPS
2. **API 密钥保护**:不要将 API 密钥提交到代码仓库
3. **输入验证**:对用户输入进行验证和过滤
4. **日志审计**:记录关键操作和错误信息
---
## 十二、更新与维护
### 更新前端
```bash
git pull
npm install
npm run build
# 重新部署 dist/ 目录
```
---
**文档版本**v2.1
**更新日期**2025-04-16
**更新内容**:移除视频讲解功能及相关后端服务