chore: update project files
This commit is contained in:
29
.claude/settings.local.json
Normal file
29
.claude/settings.local.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(netstat:*)",
|
||||||
|
"Bash(findstr:*)",
|
||||||
|
"Bash(tasklist:*)",
|
||||||
|
"Bash(taskkill /F /PID 34568)",
|
||||||
|
"Bash(powershell \"Stop-Process -Id 34568 -Force\")",
|
||||||
|
"Bash(mvn clean:*)",
|
||||||
|
"Bash(cmd /c \"mvn clean\")",
|
||||||
|
"Bash(dir:*)",
|
||||||
|
"Bash(nul)",
|
||||||
|
"Bash(.mvnw.cmd clean package:*)",
|
||||||
|
"Bash(powershell -Command \"./mvnw.cmd clean package -DskipTests\")",
|
||||||
|
"Bash(powershell -Command:*)",
|
||||||
|
"Bash(timeout /t 3 /nobreak)",
|
||||||
|
"Bash(git rm:*)",
|
||||||
|
"Bash(if exist .dockerignore del .dockerignore)",
|
||||||
|
"Bash(if exist Dockerfile del Dockerfile)",
|
||||||
|
"Bash(if exist nginx.conf del nginx.conf)",
|
||||||
|
"Bash(if exist Dockerfile.java21 del Dockerfile.java21)",
|
||||||
|
"Bash(if exist Dockerfile.linux del Dockerfile.linux)",
|
||||||
|
"Bash(if exist docker-compose.example.yml del docker-compose.example.yml)",
|
||||||
|
"Bash(if exist nginx rmdir /s /q nginx)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -63,3 +63,6 @@ startup.log
|
|||||||
# 其他
|
# 其他
|
||||||
*.jar
|
*.jar
|
||||||
!mysql-connector-java-8.0.33.jar
|
!mysql-connector-java-8.0.33.jar
|
||||||
|
|
||||||
|
# Windows 保留名占位文件
|
||||||
|
nul
|
||||||
39
SSH_SETUP.md
39
SSH_SETUP.md
@@ -1,39 +0,0 @@
|
|||||||
# SSH密钥配置说明
|
|
||||||
|
|
||||||
## 您的SSH公钥
|
|
||||||
```
|
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFh5WK5GBuW/5xcZv5suVAs5LEFeea2A01zPRP5Slzh1 984523799@qq.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置步骤
|
|
||||||
|
|
||||||
### 1. 将公钥添加到Git服务器
|
|
||||||
- 复制上面的公钥内容
|
|
||||||
- 登录您的Git服务器管理界面
|
|
||||||
- 找到"SSH密钥"或"SSH Keys"设置
|
|
||||||
- 添加新的SSH密钥,粘贴公钥内容
|
|
||||||
- 保存设置
|
|
||||||
|
|
||||||
### 2. 测试SSH连接
|
|
||||||
```bash
|
|
||||||
ssh -T git@49.234.3.145 -p 222
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 推送代码
|
|
||||||
```bash
|
|
||||||
git push -u origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
## 当前状态
|
|
||||||
- ✅ SSH密钥已生成
|
|
||||||
- ✅ Git仓库已初始化
|
|
||||||
- ✅ 代码已提交到本地
|
|
||||||
- ⏳ 等待SSH公钥添加到服务器
|
|
||||||
|
|
||||||
## 如果SSH配置有问题
|
|
||||||
可以使用HTTPS方式:
|
|
||||||
```bash
|
|
||||||
git remote set-url origin https://49.234.3.145:222/blandarebiter/AIGC.git
|
|
||||||
git push -u origin master
|
|
||||||
```
|
|
||||||
(需要输入用户名和密码)
|
|
||||||
145
UPLOAD_GUIDE.md
145
UPLOAD_GUIDE.md
@@ -1,145 +0,0 @@
|
|||||||
# AIGC项目代码上传指南
|
|
||||||
|
|
||||||
## 项目概述
|
|
||||||
这是一个完整的AIGC(AI Generated Content)项目,包含:
|
|
||||||
- **前端**: Vue.js 3 + Element Plus + Vite
|
|
||||||
- **后端**: Spring Boot 3.5.6 + Spring Security + JWT
|
|
||||||
- **数据库**: MySQL
|
|
||||||
- **支付**: 支付宝 + PayPal集成
|
|
||||||
|
|
||||||
## 代码上传方法
|
|
||||||
|
|
||||||
### 方法一:使用SSH密钥(推荐)
|
|
||||||
|
|
||||||
✅ **SSH密钥已生成**:
|
|
||||||
- 私钥:`C:\Users\UI\.ssh\id_ed25519`
|
|
||||||
- 公钥:`C:\Users\UI\.ssh\id_ed25519.pub`
|
|
||||||
|
|
||||||
**您的SSH公钥**:
|
|
||||||
```
|
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFh5WK5GBuW/5xcZv5suVAs5LEFeea2A01zPRP5Slzh1 984523799@qq.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**下一步操作**:
|
|
||||||
1. **将公钥添加到Git服务器**:
|
|
||||||
- 复制上面的公钥内容
|
|
||||||
- 登录Git服务器管理界面
|
|
||||||
- 在SSH密钥设置中添加此公钥
|
|
||||||
|
|
||||||
2. **推送代码**:
|
|
||||||
```bash
|
|
||||||
git remote set-url origin ssh://git@49.234.3.145:222/blandarebiter/AIGC.git
|
|
||||||
git push -u origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方法二:使用HTTPS(需要用户名密码)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git remote set-url origin https://49.234.3.145:222/blandarebiter/AIGC.git
|
|
||||||
git push -u origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方法三:代码打包上传
|
|
||||||
|
|
||||||
如果网络连接有问题,可以:
|
|
||||||
|
|
||||||
1. **创建代码压缩包**:
|
|
||||||
```bash
|
|
||||||
# Windows
|
|
||||||
powershell Compress-Archive -Path "demo" -DestinationPath "AIGC-Project.zip"
|
|
||||||
|
|
||||||
# Linux/Mac
|
|
||||||
tar -czf AIGC-Project.tar.gz demo/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **手动上传到服务器**
|
|
||||||
|
|
||||||
## 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
AIGC/
|
|
||||||
├── demo/ # 主项目目录
|
|
||||||
│ ├── frontend/ # Vue.js前端
|
|
||||||
│ │ ├── src/
|
|
||||||
│ │ │ ├── views/ # 页面组件
|
|
||||||
│ │ │ ├── components/ # 通用组件
|
|
||||||
│ │ │ ├── api/ # API接口
|
|
||||||
│ │ │ ├── stores/ # Pinia状态管理
|
|
||||||
│ │ │ └── router/ # 路由配置
|
|
||||||
│ │ └── package.json
|
|
||||||
│ ├── src/main/java/ # Spring Boot后端
|
|
||||||
│ │ └── com/example/demo/
|
|
||||||
│ │ ├── controller/ # 控制器
|
|
||||||
│ │ ├── service/ # 业务逻辑
|
|
||||||
│ │ ├── model/ # 数据模型
|
|
||||||
│ │ ├── repository/ # 数据访问
|
|
||||||
│ │ └── security/ # 安全配置
|
|
||||||
│ ├── pom.xml # Maven配置
|
|
||||||
│ └── start.sh # 启动脚本
|
|
||||||
└── README.md # 项目说明
|
|
||||||
```
|
|
||||||
|
|
||||||
## 主要功能
|
|
||||||
|
|
||||||
### 前端功能
|
|
||||||
- ✅ 用户登录/注册
|
|
||||||
- ✅ 个人主页
|
|
||||||
- ✅ 订单管理
|
|
||||||
- ✅ 支付记录
|
|
||||||
- ✅ 我的作品
|
|
||||||
- ✅ 文生视频
|
|
||||||
- ✅ 图生视频
|
|
||||||
- ✅ 分镜视频
|
|
||||||
- ✅ 会员订阅
|
|
||||||
- ✅ 管理员后台
|
|
||||||
|
|
||||||
### 后端功能
|
|
||||||
- ✅ JWT认证
|
|
||||||
- ✅ 用户管理
|
|
||||||
- ✅ 订单系统
|
|
||||||
- ✅ 支付集成
|
|
||||||
- ✅ 文件上传
|
|
||||||
- ✅ 权限控制
|
|
||||||
|
|
||||||
## 启动说明
|
|
||||||
|
|
||||||
### 后端启动
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
./start.sh
|
|
||||||
# 或者
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 前端启动
|
|
||||||
```bash
|
|
||||||
cd demo/frontend
|
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试账号
|
|
||||||
|
|
||||||
- **普通用户**: 15538239326 / 0627
|
|
||||||
- **管理员**: 15538239327 / admin123
|
|
||||||
- **测试用户**: 15538239328 / test123
|
|
||||||
- **个人主页**: 15538239329 / 123456
|
|
||||||
|
|
||||||
## 技术栈
|
|
||||||
|
|
||||||
- **前端**: Vue 3, Element Plus, Vite, Pinia, Vue Router, Axios
|
|
||||||
- **后端**: Spring Boot 3.5.6, Spring Security, JWT, Spring Data JPA
|
|
||||||
- **数据库**: MySQL 8.0
|
|
||||||
- **支付**: 支付宝SDK, PayPal SDK
|
|
||||||
- **构建**: Maven, npm
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. 确保MySQL服务已启动
|
|
||||||
2. 配置正确的数据库连接信息
|
|
||||||
3. 设置支付网关的API密钥
|
|
||||||
4. 确保端口8080和3000未被占用
|
|
||||||
|
|
||||||
## 联系方式
|
|
||||||
|
|
||||||
如有问题,请联系开发团队。
|
|
||||||
24
demo/.claude/settings.local.json
Normal file
24
demo/.claude/settings.local.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(mvn clean package:*)",
|
||||||
|
"Bash(powershell.exe -ExecutionPolicy Bypass -File deploy.ps1)",
|
||||||
|
"Bash(mvn clean spring-boot:run:*)",
|
||||||
|
"Bash(where:*)",
|
||||||
|
"Bash(cmd.exe /c mvnw.cmd clean spring-boot:run -DskipTests)",
|
||||||
|
"Bash(tasklist:*)",
|
||||||
|
"Bash(netstat:*)",
|
||||||
|
"Bash(taskkill:*)",
|
||||||
|
"Bash(powershell.exe -Command \"cd ''C:\\Users\\UI\\Desktop\\AIGC\\demo''; mvn clean compile -DskipTests\")",
|
||||||
|
"Bash(npm install:*)",
|
||||||
|
"Bash(npm cache clean:*)",
|
||||||
|
"Bash(npm run dev:*)",
|
||||||
|
"Bash(timeout:*)",
|
||||||
|
"Bash(powershell.exe -Command \"Start-Sleep -Seconds 5\")",
|
||||||
|
"Bash(findstr:*)",
|
||||||
|
"Bash(powershell.exe -Command \"Get-Process node | Stop-Process -Force\")"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
target/
|
|
||||||
node_modules/
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
*.md
|
|
||||||
!README.md
|
|
||||||
*.log
|
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
*.iml
|
|
||||||
.env
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
# 支付宝支付问题诊断指南
|
|
||||||
|
|
||||||
## 当前问题
|
|
||||||
|
|
||||||
根据日志显示,支付宝API调用出现 **"Read timed out"** 错误。
|
|
||||||
|
|
||||||
## 可能的原因
|
|
||||||
|
|
||||||
### 1. 网络连接问题
|
|
||||||
- **网络延迟过高**:从本地到支付宝沙箱服务器(openapi.alipaydev.com)的网络延迟可能超过60秒
|
|
||||||
- **网络不稳定**:网络连接可能间歇性中断
|
|
||||||
|
|
||||||
### 2. 支付宝沙箱环境问题
|
|
||||||
- **服务响应慢**:支付宝沙箱环境可能响应较慢或不稳定
|
|
||||||
- **服务暂时不可用**:沙箱环境可能正在维护
|
|
||||||
|
|
||||||
### 3. 防火墙或代理问题
|
|
||||||
- **防火墙阻止**:本地防火墙可能阻止对支付宝API的访问
|
|
||||||
- **代理服务器配置**:如果使用代理,可能需要配置代理设置
|
|
||||||
|
|
||||||
### 4. ngrok隧道问题
|
|
||||||
- **隧道过期**:ngrok免费隧道可能已过期或不可用
|
|
||||||
- **通知URL不可达**:支付宝无法访问通知URL,可能导致超时
|
|
||||||
|
|
||||||
## 诊断步骤
|
|
||||||
|
|
||||||
### 1. 检查网络连接
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
# 测试能否连接到支付宝沙箱服务器
|
|
||||||
ping openapi.alipaydev.com
|
|
||||||
|
|
||||||
# 测试DNS解析
|
|
||||||
nslookup openapi.alipaydev.com
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 检查ngrok隧道
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
# 检查ngrok是否运行
|
|
||||||
Get-Process -Name ngrok -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
# 访问ngrok控制面板查看隧道状态
|
|
||||||
# 浏览器打开: http://127.0.0.1:4040
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 测试网络可达性
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
# 使用PowerShell测试HTTPS连接
|
|
||||||
$url = "https://openapi.alipaydev.com/gateway.do"
|
|
||||||
try {
|
|
||||||
$response = Invoke-WebRequest -Uri $url -Method GET -TimeoutSec 10
|
|
||||||
Write-Host "连接成功: $($response.StatusCode)"
|
|
||||||
} catch {
|
|
||||||
Write-Host "连接失败: $($_.Exception.Message)"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 检查防火墙设置
|
|
||||||
|
|
||||||
确保防火墙允许以下连接:
|
|
||||||
- 出站连接:`openapi.alipaydev.com:443`
|
|
||||||
- 如果有ngrok,确保ngrok可访问
|
|
||||||
|
|
||||||
## 解决方案
|
|
||||||
|
|
||||||
### 方案1: 增加超时时间(已实施)
|
|
||||||
|
|
||||||
已在代码中将超时时间从30秒增加到60秒:
|
|
||||||
- 连接超时:60秒
|
|
||||||
- 读取超时:60秒
|
|
||||||
|
|
||||||
### 方案2: 检查ngrok配置
|
|
||||||
|
|
||||||
1. **确认ngrok隧道运行**
|
|
||||||
```bash
|
|
||||||
ngrok http 8080
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **更新配置文件中的URL**
|
|
||||||
```properties
|
|
||||||
alipay.notify-url=https://YOUR-NGROK-URL/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://YOUR-NGROK-URL/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **重新编译并重启服务**
|
|
||||||
|
|
||||||
### 方案3: 使用代理或VPN
|
|
||||||
|
|
||||||
如果网络环境限制了对支付宝服务器的访问:
|
|
||||||
1. 配置HTTP代理
|
|
||||||
2. 或使用VPN连接到支持的地区
|
|
||||||
|
|
||||||
### 方案4: 检查支付宝沙箱配置
|
|
||||||
|
|
||||||
1. **登录支付宝开放平台**:https://open.alipay.com/
|
|
||||||
2. **检查应用配置**:
|
|
||||||
- 应用ID是否正确
|
|
||||||
- 密钥是否正确
|
|
||||||
- 网关地址是否为沙箱地址:`https://openapi.alipaydev.com/gateway.do`
|
|
||||||
|
|
||||||
### 方案5: 测试开发模式
|
|
||||||
|
|
||||||
如果暂时无法连接到支付宝,可以考虑:
|
|
||||||
1. 在开发环境中模拟支付宝响应
|
|
||||||
2. 或暂时跳过支付功能进行其他功能的测试
|
|
||||||
|
|
||||||
## 当前配置
|
|
||||||
|
|
||||||
根据 `application-dev.properties`:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
alipay.app-id=9021000157616562
|
|
||||||
alipay.gateway-url=https://openapi.alipaydev.com/gateway.do
|
|
||||||
alipay.charset=UTF-8
|
|
||||||
alipay.sign-type=RSA2
|
|
||||||
alipay.notify-url=https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
## 日志分析
|
|
||||||
|
|
||||||
错误日志示例:
|
|
||||||
```
|
|
||||||
Read timed out
|
|
||||||
```
|
|
||||||
|
|
||||||
这通常表示:
|
|
||||||
- 网络连接建立成功
|
|
||||||
- 但服务器在60秒内没有响应
|
|
||||||
- 可能是服务器负载高或网络延迟
|
|
||||||
|
|
||||||
## 建议的排查顺序
|
|
||||||
|
|
||||||
1. ✅ **检查网络连接**:ping openapi.alipaydev.com
|
|
||||||
2. ✅ **检查ngrok隧道**:确认隧道是否运行
|
|
||||||
3. ✅ **查看详细日志**:重启服务后查看新增的诊断信息
|
|
||||||
4. ⚠️ **如果问题持续**:考虑使用代理或联系支付宝技术支持
|
|
||||||
|
|
||||||
## 下一步
|
|
||||||
|
|
||||||
重新编译项目后,尝试创建支付订单,查看新的诊断日志输出,这将提供更详细的错误信息和解决建议。
|
|
||||||
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
# 支付宝支付集成准备指南
|
|
||||||
|
|
||||||
## 一、必需准备项
|
|
||||||
|
|
||||||
### 1. 支付宝商户账号
|
|
||||||
- **个人开发者**:注册支付宝开放平台账号(https://open.alipay.com)
|
|
||||||
- **企业用户**:需要营业执照等企业资质,申请企业支付宝账号
|
|
||||||
|
|
||||||
### 2. 创建应用并获取配置信息
|
|
||||||
登录支付宝开放平台后,需要创建应用并获取以下配置:
|
|
||||||
|
|
||||||
#### 开发环境(沙箱测试)
|
|
||||||
- **APPID(应用ID)**:`alipay.app-id`
|
|
||||||
- **应用私钥(Private Key)**:`alipay.private-key`
|
|
||||||
- **支付宝公钥(Public Key)**:`alipay.public-key`
|
|
||||||
- **网关地址**:`https://openapi.alipaydev.com/gateway.do`(沙箱)
|
|
||||||
- **字符集**:`UTF-8`
|
|
||||||
- **签名方式**:`RSA2`
|
|
||||||
|
|
||||||
#### 生产环境
|
|
||||||
- **网关地址**:`https://openapi.alipay.com/gateway.do`
|
|
||||||
- 其他配置同开发环境
|
|
||||||
|
|
||||||
### 3. 密钥生成和配置
|
|
||||||
支付宝使用RSA2签名,需要生成密钥对:
|
|
||||||
|
|
||||||
#### 方法1:使用支付宝密钥生成工具
|
|
||||||
- 下载支付宝官方密钥生成工具
|
|
||||||
- 生成密钥对(RSA2,2048位)
|
|
||||||
- 保存私钥(用于配置 `alipay.private-key`)
|
|
||||||
- 将公钥上传到支付宝开放平台,获取支付宝公钥(用于配置 `alipay.public-key`)
|
|
||||||
|
|
||||||
#### 方法2:使用OpenSSL生成
|
|
||||||
```bash
|
|
||||||
# 生成私钥
|
|
||||||
openssl genrsa -out app_private_key.pem 2048
|
|
||||||
|
|
||||||
# 生成公钥
|
|
||||||
openssl rsa -in app_private_key.pem -pubout -out app_public_key.pem
|
|
||||||
|
|
||||||
# 查看私钥内容(去除头尾,保留中间部分配置到private-key)
|
|
||||||
cat app_private_key.pem
|
|
||||||
|
|
||||||
# 将app_public_key.pem内容上传到支付宝开放平台
|
|
||||||
```
|
|
||||||
|
|
||||||
**重要**:
|
|
||||||
- 私钥需要去除 `-----BEGIN RSA PRIVATE KEY-----` 和 `-----END RSA PRIVATE KEY-----`
|
|
||||||
- 私钥和公钥配置在配置文件中时,需要去掉换行符或使用转义
|
|
||||||
|
|
||||||
### 4. 配置回调地址
|
|
||||||
需要配置两个回调地址:
|
|
||||||
|
|
||||||
#### 异步通知地址(notify-url)
|
|
||||||
- 用于接收支付宝的支付结果异步通知
|
|
||||||
- 必须是公网可访问的HTTPS地址
|
|
||||||
- 示例:`https://yourdomain.com/api/payments/alipay/notify`
|
|
||||||
- **注意**:开发环境可以使用ngrok等内网穿透工具
|
|
||||||
|
|
||||||
#### 同步返回地址(return-url)
|
|
||||||
- 用户支付完成后跳转的页面
|
|
||||||
- 可以是HTTP或HTTPS地址
|
|
||||||
- 示例:`https://yourdomain.com/api/payments/alipay/return`
|
|
||||||
|
|
||||||
### 5. 数据库表准备
|
|
||||||
项目已经包含了Payment相关表,确保数据库已创建:
|
|
||||||
- `payments` 表
|
|
||||||
- `orders` 表
|
|
||||||
|
|
||||||
### 6. Maven依赖(已配置)
|
|
||||||
项目已包含支付宝SDK依赖:
|
|
||||||
```xml
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.javen205</groupId>
|
|
||||||
<artifactId>IJPay-AliPay</artifactId>
|
|
||||||
<version>2.9.12.1</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 二、配置文件设置
|
|
||||||
|
|
||||||
### 开发环境配置(application-dev.properties)
|
|
||||||
```properties
|
|
||||||
# 支付宝配置 (开发环境 - 沙箱测试)
|
|
||||||
alipay.app-id=你的沙箱APPID
|
|
||||||
alipay.private-key=你的应用私钥(去除头尾和换行)
|
|
||||||
alipay.public-key=支付宝公钥(从开放平台获取)
|
|
||||||
alipay.gateway-url=https://openapi.alipaydev.com/gateway.do
|
|
||||||
alipay.charset=UTF-8
|
|
||||||
alipay.sign-type=RSA2
|
|
||||||
alipay.notify-url=https://your-ngrok-url.ngrok-free.dev/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://your-ngrok-url.ngrok-free.dev/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
### 生产环境配置(application-prod.properties)
|
|
||||||
```properties
|
|
||||||
# 支付宝配置 (生产环境)
|
|
||||||
alipay.app-id=${ALIPAY_APP_ID}
|
|
||||||
alipay.private-key=${ALIPAY_PRIVATE_KEY}
|
|
||||||
alipay.public-key=${ALIPAY_PUBLIC_KEY}
|
|
||||||
alipay.gateway-url=https://openapi.alipay.com/gateway.do
|
|
||||||
alipay.charset=UTF-8
|
|
||||||
alipay.sign-type=RSA2
|
|
||||||
alipay.notify-url=${ALIPAY_NOTIFY_URL}
|
|
||||||
alipay.return-url=${ALIPAY_RETURN_URL}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 三、测试步骤
|
|
||||||
|
|
||||||
### 1. 沙箱测试环境准备
|
|
||||||
1. 登录支付宝开放平台:https://open.alipay.com
|
|
||||||
2. 进入"沙箱环境"
|
|
||||||
3. 获取沙箱APPID
|
|
||||||
4. 下载"支付宝密钥生成工具",生成密钥对
|
|
||||||
5. 上传公钥到支付宝,获取支付宝公钥
|
|
||||||
6. 配置沙箱测试账号(买家账号和卖家账号)
|
|
||||||
|
|
||||||
### 2. 内网穿透配置(开发测试)
|
|
||||||
如果本地开发,需要使用ngrok等工具暴露本地服务:
|
|
||||||
```bash
|
|
||||||
# 安装ngrok
|
|
||||||
# 启动本地服务(端口8080)
|
|
||||||
# 使用ngrok暴露
|
|
||||||
ngrok http 8080
|
|
||||||
# 获取https地址,配置到notify-url和return-url
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 功能测试
|
|
||||||
- 创建支付订单
|
|
||||||
- 生成支付宝二维码
|
|
||||||
- 使用沙箱账号扫码支付
|
|
||||||
- 验证异步通知接收
|
|
||||||
- 验证支付状态更新
|
|
||||||
|
|
||||||
## 四、已实现的功能
|
|
||||||
|
|
||||||
### 后端接口
|
|
||||||
✅ `POST /api/payments/alipay/create` - 创建支付宝支付并生成二维码
|
|
||||||
✅ `POST /api/payments/alipay/notify` - 接收支付宝异步通知
|
|
||||||
✅ `GET /api/payments/alipay/return` - 处理支付宝同步返回
|
|
||||||
|
|
||||||
### 前端页面
|
|
||||||
✅ 支付模态框组件(PaymentModal.vue)
|
|
||||||
✅ 订阅页面支付集成(Subscription.vue)
|
|
||||||
|
|
||||||
### 核心服务
|
|
||||||
✅ `AlipayService` - 支付宝服务封装
|
|
||||||
- `createPayment()` - 创建支付订单
|
|
||||||
- `handleNotify()` - 处理异步通知
|
|
||||||
- `handleReturn()` - 处理同步返回
|
|
||||||
|
|
||||||
## 五、常见问题
|
|
||||||
|
|
||||||
### 1. 签名验证失败
|
|
||||||
- 检查私钥和公钥是否正确配置
|
|
||||||
- 确认私钥格式正确(去除头尾和换行)
|
|
||||||
- 确认使用RSA2签名方式
|
|
||||||
|
|
||||||
### 2. 回调地址无法访问
|
|
||||||
- 确保回调地址是公网可访问的HTTPS地址
|
|
||||||
- 开发环境可以使用ngrok等内网穿透工具
|
|
||||||
- 检查防火墙和服务器配置
|
|
||||||
|
|
||||||
### 3. 沙箱测试账号
|
|
||||||
- 在支付宝开放平台沙箱环境中获取测试账号
|
|
||||||
- 使用"沙箱买家"账号进行支付测试
|
|
||||||
- 注意:沙箱环境有金额限制
|
|
||||||
|
|
||||||
### 4. 生产环境上线
|
|
||||||
- 申请正式应用(需要审核)
|
|
||||||
- 配置正式环境的APPID和密钥
|
|
||||||
- 确保回调地址使用正式域名
|
|
||||||
- 完成商户资质认证
|
|
||||||
|
|
||||||
## 六、安全检查
|
|
||||||
|
|
||||||
1. **密钥安全**
|
|
||||||
- 私钥绝对不能泄露
|
|
||||||
- 生产环境使用环境变量或密钥管理服务
|
|
||||||
- 不要将密钥提交到代码仓库
|
|
||||||
|
|
||||||
2. **回调验证**
|
|
||||||
- 所有回调必须验证签名
|
|
||||||
- 验证订单金额和状态
|
|
||||||
- 防止重复处理
|
|
||||||
|
|
||||||
3. **HTTPS要求**
|
|
||||||
- 生产环境必须使用HTTPS
|
|
||||||
- 回调地址必须是HTTPS
|
|
||||||
|
|
||||||
## 七、当前项目状态
|
|
||||||
|
|
||||||
✅ 代码已实现
|
|
||||||
✅ Maven依赖已配置
|
|
||||||
⚠️ 需要配置支付宝账号和密钥
|
|
||||||
⚠️ 需要配置回调地址(开发环境可用ngrok)
|
|
||||||
|
|
||||||
## 八、快速开始
|
|
||||||
|
|
||||||
1. **注册支付宝开放平台账号**
|
|
||||||
2. **创建应用获取APPID**
|
|
||||||
3. **生成密钥对并配置**
|
|
||||||
4. **配置回调地址(开发环境使用ngrok)**
|
|
||||||
5. **更新application-dev.properties配置文件**
|
|
||||||
6. **启动项目测试支付功能**
|
|
||||||
|
|
||||||
## 九、参考文档
|
|
||||||
|
|
||||||
- 支付宝开放平台:https://open.alipay.com
|
|
||||||
- 支付宝开发者文档:https://opendocs.alipay.com
|
|
||||||
- IJPay文档:https://github.com/Javen205/IJPay
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
81
demo/API_DOCUMENTATION.md
Normal file
81
demo/API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# API 接口文档使用说明
|
||||||
|
|
||||||
|
## 访问地址
|
||||||
|
|
||||||
|
启动应用后,可以通过以下地址访问 API 文档:
|
||||||
|
|
||||||
|
- **Swagger UI 界面**: http://localhost:8080/swagger-ui.html
|
||||||
|
- **API 文档 JSON**: http://localhost:8080/v3/api-docs
|
||||||
|
- **所有API分组**: http://localhost:8080/v3/api-docs/all
|
||||||
|
|
||||||
|
## 环境地址
|
||||||
|
|
||||||
|
根据部署环境,访问地址会有所不同:
|
||||||
|
|
||||||
|
- **本地开发**: http://localhost:8080/swagger-ui.html
|
||||||
|
- **内网环境**: http://172.22.0.1:8080/swagger-ui.html
|
||||||
|
- **生产环境**: https://vionow.com/swagger-ui.html
|
||||||
|
|
||||||
|
## API 分组
|
||||||
|
|
||||||
|
文档按功能模块分为以下分组:
|
||||||
|
|
||||||
|
1. **所有API (all)** - 查看所有接口
|
||||||
|
2. **认证授权 (auth)** - 用户登录、注册、验证码等
|
||||||
|
3. **用户作品 (user-works)** - 用户作品管理
|
||||||
|
4. **视频生成 (video-generation)** - 文生视频、图生视频、分镜视频
|
||||||
|
5. **支付管理 (payment)** - 订单、支付相关接口
|
||||||
|
6. **会员管理 (member)** - 会员订阅、会员管理
|
||||||
|
7. **积分系统 (points)** - 积分相关接口
|
||||||
|
8. **任务管理 (tasks)** - 任务队列、任务状态
|
||||||
|
9. **管理后台 (admin)** - 管理员功能、数据分析
|
||||||
|
10. **系统设置 (settings)** - 系统配置、API密钥管理
|
||||||
|
11. **公共接口 (public)** - 无需认证的公共接口
|
||||||
|
|
||||||
|
## 使用 JWT 认证
|
||||||
|
|
||||||
|
大部分接口需要 JWT 认证,使用步骤如下:
|
||||||
|
|
||||||
|
1. 在 Swagger UI 页面右上角点击 **"Authorize"** 按钮
|
||||||
|
2. 在弹出框中输入 JWT Token(格式:`Bearer {token}` 或直接输入 token)
|
||||||
|
3. 点击 **"Authorize"** 确认
|
||||||
|
4. 之后所有请求都会自动携带认证信息
|
||||||
|
|
||||||
|
### 获取 Token
|
||||||
|
|
||||||
|
1. 调用 `/api/verification/email/send` 发送邮箱验证码
|
||||||
|
2. 调用 `/api/auth/login/email` 使用邮箱和验证码登录
|
||||||
|
3. 从响应中获取 `token` 字段
|
||||||
|
4. 在 Swagger UI 中使用该 token 进行认证
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- ✅ 自动生成 API 文档
|
||||||
|
- ✅ 在线测试接口
|
||||||
|
- ✅ 支持 JWT 认证
|
||||||
|
- ✅ API 分组管理
|
||||||
|
- ✅ 请求/响应示例
|
||||||
|
- ✅ 参数说明和验证规则
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **生产环境**: 建议在生产环境中限制 Swagger UI 的访问,或完全禁用
|
||||||
|
2. **认证**: 大部分接口需要 JWT Token,请先登录获取 Token
|
||||||
|
3. **权限**: 部分接口需要管理员权限,普通用户无法访问
|
||||||
|
4. **跨域**: 如果遇到跨域问题,请检查 CORS 配置
|
||||||
|
|
||||||
|
## 禁用 Swagger UI(生产环境)
|
||||||
|
|
||||||
|
如果需要在生产环境禁用 Swagger UI,可以在 `application-prod.properties` 中添加:
|
||||||
|
|
||||||
|
```properties
|
||||||
|
springdoc.swagger-ui.enabled=false
|
||||||
|
```
|
||||||
|
|
||||||
|
或者通过环境变量:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export SPRINGDOC_SWAGGER_UI_ENABLED=false
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# ✅ 配置检查清单
|
|
||||||
|
|
||||||
## 已完成的检查
|
|
||||||
|
|
||||||
### 1. Nginx 配置 ✅
|
|
||||||
- ✅ `nginx/nginx.conf` 语法正确
|
|
||||||
- ✅ upstream backend 配置正确
|
|
||||||
- ✅ proxy_pass 指向正确(`http://backend`)
|
|
||||||
- ✅ 前端静态文件路径正确(`/usr/share/nginx/html`)
|
|
||||||
- ✅ API 代理路径正确(`/api/` → `backend:8080`)
|
|
||||||
|
|
||||||
### 2. Docker Compose 配置 ✅
|
|
||||||
- ✅ 服务定义完整(mysql, backend, nginx)
|
|
||||||
- ✅ 网络配置正确(app-network)
|
|
||||||
- ✅ 卷映射正确
|
|
||||||
- ✅ 依赖关系正确(nginx depends_on backend, backend depends_on mysql)
|
|
||||||
|
|
||||||
### 3. Dockerfile 配置 ✅
|
|
||||||
- ✅ `Dockerfile.backend` 包含 wget(用于健康检查)
|
|
||||||
- ✅ `nginx/Dockerfile` 配置正确
|
|
||||||
- ✅ 多阶段构建配置正确
|
|
||||||
|
|
||||||
### 4. 环境变量配置 ✅
|
|
||||||
- ✅ docker-compose.yml 中环境变量与 application-prod.properties 匹配
|
|
||||||
- ✅ 数据库连接字符串正确
|
|
||||||
|
|
||||||
### 5. 文件路径检查 ✅
|
|
||||||
- ✅ `frontend/dist` 目录存在(前端构建产物)
|
|
||||||
- ✅ `pom.xml` 存在(后端构建文件)
|
|
||||||
|
|
||||||
## 潜在问题及修复
|
|
||||||
|
|
||||||
### 已修复的问题
|
|
||||||
1. ✅ **后端健康检查缺少 wget**
|
|
||||||
- 修复:在 Dockerfile.backend 中添加 `RUN apk add --no-cache wget`
|
|
||||||
|
|
||||||
2. ✅ **环境变量不匹配**
|
|
||||||
- 修复:将 `SPRING_DATASOURCE_*` 改为 `DB_*` 以匹配 application-prod.properties
|
|
||||||
|
|
||||||
## 部署前检查清单
|
|
||||||
|
|
||||||
在运行 `docker-compose up` 之前,请确保:
|
|
||||||
|
|
||||||
- [ ] 前端已构建:`cd frontend && npm run build`
|
|
||||||
- [ ] Docker 和 Docker Compose 已安装
|
|
||||||
- [ ] 端口 80、8080、3306 未被占用
|
|
||||||
- [ ] 有足够的磁盘空间(至少 2GB)
|
|
||||||
|
|
||||||
## 验证命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查 Docker Compose 配置
|
|
||||||
docker-compose config
|
|
||||||
|
|
||||||
# 检查服务状态
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
docker-compose logs -f nginx
|
|
||||||
docker-compose logs -f backend
|
|
||||||
|
|
||||||
# 测试 Nginx 配置
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
```
|
|
||||||
|
|
||||||
## 访问地址
|
|
||||||
|
|
||||||
部署成功后:
|
|
||||||
- 🌐 前端:http://localhost
|
|
||||||
- 🔗 API:http://localhost/api
|
|
||||||
- 🏥 健康检查:http://localhost/health
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
# 代码问题修复报告
|
|
||||||
|
|
||||||
## 修复的问题
|
|
||||||
|
|
||||||
### 1. **严重错误 - SystemSettings.vue 缺少结束标签** ✅ 已修复
|
|
||||||
- **问题**: `SystemSettings.vue` 文件缺少 `</template>` 结束标签
|
|
||||||
- **位置**: 第373行
|
|
||||||
- **影响**: 导致 Vue 编译错误,前端无法正常运行
|
|
||||||
- **修复**: 在第373行后添加了 `</template>` 和 `</div>` 标签
|
|
||||||
|
|
||||||
### 2. **OrderService.java - Switch 语句缺少枚举值处理** ✅ 已修复
|
|
||||||
- **问题**: `updateOrderStatus` 方法中的 switch 语句缺少部分枚举值的处理
|
|
||||||
- **位置**: `OrderService.java` 第166行
|
|
||||||
- **影响**: 当订单状态为 `PENDING`, `CONFIRMED`, `PROCESSING`, `REFUNDED` 时,会触发编译警告
|
|
||||||
- **修复**: 为所有 `OrderStatus` 枚举值添加了对应的 case 分支处理
|
|
||||||
|
|
||||||
### 3. **ImageToVideoTask.java - 潜在的 NullPointerException** ✅ 已修复
|
|
||||||
- **问题**: `calculateCost()` 方法中直接使用 `duration`,可能出现空指针解包
|
|
||||||
- **位置**: `ImageToVideoTask.java` 第94行
|
|
||||||
- **影响**: 当 `duration` 为 null 时,可能出现 NullPointerException
|
|
||||||
- **修复**: 添加了安全处理,先赋值给局部变量再使用
|
|
||||||
|
|
||||||
## 发现的警告(非严重)
|
|
||||||
|
|
||||||
### 1. **TencentSesMailService.java**
|
|
||||||
- `fromName` 变量未使用 - 这是配置变量,保留用于未来扩展
|
|
||||||
- 异常处理可以优化为 multicatch - 不影响功能
|
|
||||||
|
|
||||||
### 2. **PaymentService.java**
|
|
||||||
- 第319行空指针警告 - 代码已有null检查,实际安全
|
|
||||||
- 异常处理可以优化 - 不影响功能
|
|
||||||
|
|
||||||
### 3. **AlipayService.java**
|
|
||||||
- 第144行可能的空指针 - 需要在调用前验证 response 是否为 null
|
|
||||||
|
|
||||||
### 4. **前端文件**
|
|
||||||
- SystemSettings.vue 已修复
|
|
||||||
- 其他警告多为代码风格建议,不影响功能
|
|
||||||
|
|
||||||
## 建议进一步优化
|
|
||||||
|
|
||||||
1. **AlipayService.java** - 添加 response 的 null 检查
|
|
||||||
2. **异常处理优化** - 多个文件可以使用 Java 7+ 的 multicatch 语法
|
|
||||||
3. **代码清理** - 移除未使用的导入和方法(标记为未使用本地的方法)
|
|
||||||
4. **Switch 表达式** - 考虑使用 Java 14+ 的 switch 表达式简化代码
|
|
||||||
|
|
||||||
## 测试建议
|
|
||||||
|
|
||||||
1. **前端测试** - 验证 SystemSettings.vue 页面可以正常加载和渲染
|
|
||||||
2. **订单状态测试** - 测试所有订单状态的转换是否正常工作
|
|
||||||
3. **空值测试** - 测试 duration 为 null 的情况是否处理正确
|
|
||||||
|
|
||||||
## 已修复文件列表
|
|
||||||
|
|
||||||
- ✅ `demo/frontend/src/views/SystemSettings.vue`
|
|
||||||
- ✅ `demo/src/main/java/com/example/demo/service/OrderService.java`
|
|
||||||
- ✅ `demo/src/main/java/com/example/demo/model/ImageToVideoTask.java`
|
|
||||||
|
|
||||||
## 编译状态
|
|
||||||
|
|
||||||
所有修复后应能正常编译,建议重新编译验证:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
.\mvnw.cmd clean package -DskipTests
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
# 代码检查报告
|
|
||||||
|
|
||||||
## 发现的问题
|
|
||||||
|
|
||||||
### 1. IJPay配置问题 ⚠️
|
|
||||||
|
|
||||||
**问题**:`AlipayService` 使用 IJPay 的 `AliPayApi`,但 IJPay 可能没有正确配置。
|
|
||||||
|
|
||||||
**位置**:`AlipayService.java`
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- `AlipayService` 使用 `@Value` 注入配置,但 IJPay 的 `AliPayApi` 可能不会自动读取这些配置
|
|
||||||
- IJPay 的 `AliPayApi` 需要显式配置或通过系统属性/配置文件读取
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 检查 IJPay 是否需要初始化配置
|
|
||||||
- 或者使用 `PaymentConfig.AliPayConfig` 来配置 IJPay
|
|
||||||
|
|
||||||
### 2. 配置文件不一致 ⚠️
|
|
||||||
|
|
||||||
**问题**:`payment.properties` 中有模板值,但实际配置在 `application-dev.properties` 中。
|
|
||||||
|
|
||||||
**位置**:
|
|
||||||
- `payment.properties` - 包含模板值("您的APPID")
|
|
||||||
- `application-dev.properties` - 包含实际配置
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- `PaymentConfig` 使用 `@PropertySource("classpath:payment.properties")`
|
|
||||||
- 但 `AlipayService` 使用 `@Value` 从 `application-dev.properties` 读取配置
|
|
||||||
- 这可能导致配置不一致
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 统一配置文件路径
|
|
||||||
- 或者在 `payment.properties` 中也配置实际值
|
|
||||||
|
|
||||||
### 3. 异步通知参数获取 ⚠️
|
|
||||||
|
|
||||||
**问题**:`PaymentController.alipayNotify()` 中参数获取方式可能不正确。
|
|
||||||
|
|
||||||
**位置**:`PaymentController.java` 第 100-117 行
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 使用 `request.getParameterMap()` 获取参数
|
|
||||||
- 但支付宝异步通知可能使用 POST 请求体,而不是 URL 参数
|
|
||||||
- 应该使用 `AliPayApi.toMap(request)` 来获取参数(如 `AlipayController` 中所示)
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 使用 IJPay 的 `AliPayApi.toMap(request)` 方法获取参数
|
|
||||||
- 或者检查支付宝异步通知的实际参数格式
|
|
||||||
|
|
||||||
### 4. 未使用的变量警告 ⚠️
|
|
||||||
|
|
||||||
**问题**:`AlipayService` 中的 `privateKey` 变量未使用。
|
|
||||||
|
|
||||||
**位置**:`AlipayService.java` 第 33 行
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- `privateKey` 被注入但未在代码中直接使用
|
|
||||||
- IJPay 内部可能需要使用它,但当前代码中未显式使用
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 如果 IJPay 内部使用,可以保留
|
|
||||||
- 或者添加注释说明
|
|
||||||
|
|
||||||
### 5. 类型转换警告 ⚠️
|
|
||||||
|
|
||||||
**问题**:JSON 解析时存在类型转换警告。
|
|
||||||
|
|
||||||
**位置**:`AlipayService.java` 第 136-137 行
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 使用 `objectMapper.readValue(responseBody, Map.class)` 时存在类型转换警告
|
|
||||||
- 应该使用 `TypeReference` 或 `MapType` 来避免警告
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
- 使用 `TypeReference` 或 `MapType` 来明确类型
|
|
||||||
|
|
||||||
## 修复建议
|
|
||||||
|
|
||||||
### 1. 修复 IJPay 配置
|
|
||||||
|
|
||||||
检查 IJPay 是否需要显式配置,如果需要,可以创建一个配置类来初始化 IJPay。
|
|
||||||
|
|
||||||
### 2. 统一配置文件
|
|
||||||
|
|
||||||
确保所有配置文件中的配置一致,或者统一使用一个配置文件。
|
|
||||||
|
|
||||||
### 3. 修复异步通知参数获取
|
|
||||||
|
|
||||||
使用 IJPay 的 `AliPayApi.toMap(request)` 方法获取参数。
|
|
||||||
|
|
||||||
### 4. 修复类型转换警告
|
|
||||||
|
|
||||||
使用 `TypeReference` 或 `MapType` 来明确类型。
|
|
||||||
|
|
||||||
## 代码质量
|
|
||||||
|
|
||||||
### 优点
|
|
||||||
- 代码结构清晰
|
|
||||||
- 有良好的日志记录
|
|
||||||
- 有重试机制和错误处理
|
|
||||||
- 使用了 IJPay 封装
|
|
||||||
|
|
||||||
### 需要改进
|
|
||||||
- 配置文件一致性
|
|
||||||
- IJPay 配置初始化
|
|
||||||
- 异步通知参数获取方式
|
|
||||||
- 类型转换警告
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,306 +0,0 @@
|
|||||||
# 系统配置指南
|
|
||||||
|
|
||||||
本文档列出了系统中所有需要手动配置的重要配置项。
|
|
||||||
|
|
||||||
## 📋 配置项分类
|
|
||||||
|
|
||||||
### 1. 🔐 数据库配置(必须)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境(直接配置)
|
|
||||||
spring.datasource.url=jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
|
||||||
spring.datasource.username=root
|
|
||||||
spring.datasource.password=你的数据库密码
|
|
||||||
|
|
||||||
# 生产环境(使用环境变量)
|
|
||||||
spring.datasource.url=${DB_URL}
|
|
||||||
spring.datasource.username=${DB_USERNAME}
|
|
||||||
spring.datasource.password=${DB_PASSWORD}
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 开发环境:直接修改配置文件中的数据库连接信息
|
|
||||||
- 生产环境:通过环境变量配置,更安全
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 🔑 JWT配置(必须)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境
|
|
||||||
jwt.secret=你的JWT密钥(至少128位,建议256位)
|
|
||||||
jwt.expiration=86400000 # 24小时,单位毫秒
|
|
||||||
|
|
||||||
# 生产环境(使用环境变量)
|
|
||||||
jwt.secret=${JWT_SECRET}
|
|
||||||
jwt.expiration=${JWT_EXPIRATION:604800000} # 默认7天
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- `jwt.secret`: 用于签名JWT token的密钥,**必须修改为强随机字符串**
|
|
||||||
- `jwt.expiration`: Token过期时间(毫秒)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 🤖 AI API配置(必须)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# Comfly API配置(文生视频、图生视频、分镜视频)
|
|
||||||
ai.api.base-url=https://ai.comfly.chat
|
|
||||||
ai.api.key=你的Comfly API密钥
|
|
||||||
|
|
||||||
# Comfly API配置(文生图)
|
|
||||||
ai.image.api.base-url=https://ai.comfly.chat
|
|
||||||
ai.image.api.key=你的Comfly API密钥
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 可通过 **API管理页面** 在线修改(推荐)
|
|
||||||
- 或直接修改配置文件
|
|
||||||
- 修改后需要重启应用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 💰 支付宝配置(可选,如需支付功能)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境(沙箱测试)
|
|
||||||
alipay.app-id=你的支付宝应用ID
|
|
||||||
alipay.private-key=你的应用私钥(RSA2格式)
|
|
||||||
alipay.public-key=支付宝公钥(RSA2格式)
|
|
||||||
alipay.gateway-url=https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
|
||||||
alipay.notify-url=你的回调通知URL
|
|
||||||
alipay.return-url=你的支付返回URL
|
|
||||||
|
|
||||||
# 生产环境(使用环境变量)
|
|
||||||
alipay.app-id=${ALIPAY_APP_ID}
|
|
||||||
alipay.private-key=${ALIPAY_PRIVATE_KEY}
|
|
||||||
alipay.public-key=${ALIPAY_PUBLIC_KEY}
|
|
||||||
alipay.gateway-url=https://openapi.alipay.com/gateway.do
|
|
||||||
alipay.notify-url=${ALIPAY_NOTIFY_URL}
|
|
||||||
alipay.return-url=${ALIPAY_RETURN_URL}
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 开发环境使用支付宝沙箱进行测试
|
|
||||||
- 生产环境需要申请正式支付宝应用
|
|
||||||
- 私钥和公钥必须是RSA2格式
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 📧 腾讯云SES邮件配置(可选,如需邮件功能)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境
|
|
||||||
tencent.ses.secret-id=你的腾讯云SecretId
|
|
||||||
tencent.ses.secret-key=你的腾讯云SecretKey
|
|
||||||
tencent.ses.region=ap-hongkong
|
|
||||||
tencent.ses.from-email=你的发件邮箱
|
|
||||||
tencent.ses.from-name=AIGC平台
|
|
||||||
tencent.ses.template-id=你的邮件模板ID
|
|
||||||
|
|
||||||
# 生产环境(使用环境变量)
|
|
||||||
tencent.ses.secret-id=${TENCENT_SES_SECRET_ID}
|
|
||||||
tencent.ses.secret-key=${TENCENT_SES_SECRET_KEY}
|
|
||||||
tencent.ses.from-email=${TENCENT_SES_FROM_EMAIL}
|
|
||||||
tencent.ses.template-id=${TENCENT_SES_TEMPLATE_ID}
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 需要在腾讯云SES控制台创建邮件模板
|
|
||||||
- 如果`template-id`为0或未配置,将使用开发模式(仅记录日志)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. 🎬 FFmpeg配置(可选,如需视频拼接功能)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境
|
|
||||||
app.ffmpeg.path=C:/Users/UI/AppData/Local/Microsoft/WinGet/Packages/Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe/ffmpeg-8.0-full_build/bin/ffmpeg.exe
|
|
||||||
app.temp.dir=./temp
|
|
||||||
|
|
||||||
# 生产环境(使用环境变量)
|
|
||||||
app.ffmpeg.path=${FFMPEG_PATH:ffmpeg} # 如果在PATH中,直接使用"ffmpeg"
|
|
||||||
app.temp.dir=${TEMP_DIR:./temp}
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- `app.ffmpeg.path`: FFmpeg可执行文件路径
|
|
||||||
- Windows: 使用完整路径,如 `C:\ffmpeg\bin\ffmpeg.exe`
|
|
||||||
- Linux/Mac: 如果在PATH中,使用 `ffmpeg`;否则使用完整路径,如 `/usr/bin/ffmpeg`
|
|
||||||
- `app.temp.dir`: 临时文件目录(用于视频处理)
|
|
||||||
- 相对路径:基于应用运行目录
|
|
||||||
- 绝对路径:如 `/app/temp` 或 `C:\app\temp`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 7. 🖥️ 服务器配置(可选,根据需求调整)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 服务器端口
|
|
||||||
server.port=8080
|
|
||||||
|
|
||||||
# Tomcat线程池配置(支持并发)
|
|
||||||
server.tomcat.threads.max=1000
|
|
||||||
server.tomcat.threads.min-spare=100
|
|
||||||
server.tomcat.max-connections=10000
|
|
||||||
server.tomcat.accept-count=500
|
|
||||||
|
|
||||||
# 请求体大小限制(支持大图片Base64编码)
|
|
||||||
server.tomcat.max-http-post-size=600MB
|
|
||||||
spring.servlet.multipart.max-file-size=500MB
|
|
||||||
spring.servlet.multipart.max-request-size=600MB
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 根据实际并发需求调整线程池配置
|
|
||||||
- 如果不需要处理大文件,可以减小请求体大小限制
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 8. 📊 数据库连接池配置(可选,根据需求调整)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# HikariCP连接池配置
|
|
||||||
spring.datasource.hikari.maximum-pool-size=200
|
|
||||||
spring.datasource.hikari.minimum-idle=20
|
|
||||||
spring.datasource.hikari.idle-timeout=300000
|
|
||||||
spring.datasource.hikari.max-lifetime=1200000
|
|
||||||
spring.datasource.hikari.connection-timeout=30000
|
|
||||||
spring.datasource.hikari.leak-detection-threshold=60000
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- 根据数据库服务器性能和并发需求调整
|
|
||||||
- 默认配置支持50人并发
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 9. 🗄️ JPA配置(开发/生产环境不同)
|
|
||||||
|
|
||||||
**位置**: `application-dev.properties` / `application-prod.properties`
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 开发环境
|
|
||||||
spring.jpa.hibernate.ddl-auto=update # 自动更新表结构
|
|
||||||
spring.jpa.show-sql=true # 显示SQL语句
|
|
||||||
|
|
||||||
# 生产环境
|
|
||||||
spring.jpa.hibernate.ddl-auto=validate # 仅验证,不自动修改
|
|
||||||
spring.jpa.show-sql=false # 不显示SQL语句
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明**:
|
|
||||||
- **生产环境必须使用 `validate`**,避免自动修改数据库结构
|
|
||||||
- 开发环境可以使用 `update` 方便开发
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速配置清单
|
|
||||||
|
|
||||||
### 开发环境必须配置:
|
|
||||||
- [ ] 数据库连接信息(URL、用户名、密码)
|
|
||||||
- [ ] JWT密钥(修改为强随机字符串)
|
|
||||||
- [ ] AI API密钥(Comfly API)
|
|
||||||
|
|
||||||
### 开发环境可选配置:
|
|
||||||
- [ ] 支付宝沙箱配置(如需测试支付)
|
|
||||||
- [ ] 腾讯云SES配置(如需测试邮件)
|
|
||||||
- [ ] FFmpeg路径(如需视频拼接)
|
|
||||||
|
|
||||||
### 生产环境必须配置(通过环境变量):
|
|
||||||
- [ ] `DB_URL` - 数据库连接URL
|
|
||||||
- [ ] `DB_USERNAME` - 数据库用户名
|
|
||||||
- [ ] `DB_PASSWORD` - 数据库密码
|
|
||||||
- [ ] `JWT_SECRET` - JWT密钥
|
|
||||||
- [ ] `ALIPAY_APP_ID` - 支付宝应用ID(如需支付)
|
|
||||||
- [ ] `ALIPAY_PRIVATE_KEY` - 支付宝私钥(如需支付)
|
|
||||||
- [ ] `ALIPAY_PUBLIC_KEY` - 支付宝公钥(如需支付)
|
|
||||||
- [ ] `ALIPAY_NOTIFY_URL` - 支付回调URL(如需支付)
|
|
||||||
- [ ] `ALIPAY_RETURN_URL` - 支付返回URL(如需支付)
|
|
||||||
- [ ] `TENCENT_SES_SECRET_ID` - 腾讯云SecretId(如需邮件)
|
|
||||||
- [ ] `TENCENT_SES_SECRET_KEY` - 腾讯云SecretKey(如需邮件)
|
|
||||||
- [ ] `TENCENT_SES_FROM_EMAIL` - 发件邮箱(如需邮件)
|
|
||||||
- [ ] `TENCENT_SES_TEMPLATE_ID` - 邮件模板ID(如需邮件)
|
|
||||||
- [ ] `FFMPEG_PATH` - FFmpeg路径(如需视频拼接)
|
|
||||||
- [ ] `TEMP_DIR` - 临时文件目录(如需视频拼接)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 安全注意事项
|
|
||||||
|
|
||||||
1. **不要将生产环境配置提交到代码仓库**
|
|
||||||
- 使用环境变量或外部配置文件
|
|
||||||
- 将敏感信息添加到 `.gitignore`
|
|
||||||
|
|
||||||
2. **JWT密钥必须足够强**
|
|
||||||
- 至少128位,建议256位
|
|
||||||
- 使用随机字符串生成器生成
|
|
||||||
|
|
||||||
3. **数据库密码**
|
|
||||||
- 使用强密码
|
|
||||||
- 生产环境必须通过环境变量配置
|
|
||||||
|
|
||||||
4. **API密钥**
|
|
||||||
- 定期更换
|
|
||||||
- 不要泄露给他人
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 配置优先级
|
|
||||||
|
|
||||||
1. **环境变量** > 配置文件
|
|
||||||
2. **application-{profile}.properties** > **application.properties**
|
|
||||||
3. **外部配置文件** > **classpath配置文件**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 配置更新方式
|
|
||||||
|
|
||||||
### 方式1:直接修改配置文件(开发环境)
|
|
||||||
- 修改 `application-dev.properties`
|
|
||||||
- 重启应用
|
|
||||||
|
|
||||||
### 方式2:通过管理页面(推荐)
|
|
||||||
- **API密钥**:通过"API管理"页面在线修改
|
|
||||||
- **会员价格**:通过"系统设置"页面在线修改
|
|
||||||
|
|
||||||
### 方式3:环境变量(生产环境)
|
|
||||||
- 设置环境变量
|
|
||||||
- 重启应用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 配置问题排查
|
|
||||||
|
|
||||||
1. **配置不生效**
|
|
||||||
- 检查配置文件路径是否正确
|
|
||||||
- 检查环境变量是否正确设置
|
|
||||||
- 检查是否需要重启应用
|
|
||||||
|
|
||||||
2. **数据库连接失败**
|
|
||||||
- 检查数据库服务是否启动
|
|
||||||
- 检查连接URL、用户名、密码是否正确
|
|
||||||
- 检查防火墙设置
|
|
||||||
|
|
||||||
3. **API调用失败**
|
|
||||||
- 检查API密钥是否正确
|
|
||||||
- 检查网络连接
|
|
||||||
- 查看日志文件获取详细错误信息
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
# ✅ Nginx 反向代理配置验证报告
|
|
||||||
|
|
||||||
## 📊 验证结果:✅ **配置可用**
|
|
||||||
|
|
||||||
所有配置文件已通过验证,可以正常使用。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 详细检查结果
|
|
||||||
|
|
||||||
### 1. Nginx 配置文件 ✅
|
|
||||||
|
|
||||||
**文件**: `nginx/nginx.conf`
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ 语法正确
|
|
||||||
- ✅ upstream backend 配置:`server backend:8080;`
|
|
||||||
- ✅ 前端静态文件服务:`root /usr/share/nginx/html;`
|
|
||||||
- ✅ API 代理配置:`location /api/` → `proxy_pass http://backend;`
|
|
||||||
- ✅ WebSocket 支持:`location /ws/`
|
|
||||||
- ✅ 健康检查端点:`location /health`
|
|
||||||
- ✅ Gzip 压缩已启用
|
|
||||||
- ✅ 静态资源缓存配置正确
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. Docker Compose 配置 ✅
|
|
||||||
|
|
||||||
**文件**: `docker-compose.yml`
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ 服务定义完整(mysql, backend, nginx)
|
|
||||||
- ✅ 网络配置:`app-network` bridge 模式
|
|
||||||
- ✅ 卷映射正确:
|
|
||||||
- `frontend/dist` → `/usr/share/nginx/html`
|
|
||||||
- `nginx/nginx.conf` → `/etc/nginx/nginx.conf`
|
|
||||||
- ✅ 依赖关系:
|
|
||||||
- `nginx` depends_on `backend`
|
|
||||||
- `backend` depends_on `mysql` (healthcheck)
|
|
||||||
- ✅ 环境变量正确:
|
|
||||||
- `DB_URL`, `DB_USERNAME`, `DB_PASSWORD`
|
|
||||||
- `SPRING_PROFILES_ACTIVE=prod`
|
|
||||||
- ✅ 端口映射:
|
|
||||||
- Nginx: `80:80`
|
|
||||||
- Backend: `8080:8080`
|
|
||||||
- MySQL: `3306:3306`
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. Dockerfile 配置 ✅
|
|
||||||
|
|
||||||
#### 后端 Dockerfile (`Dockerfile.backend`)
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ 多阶段构建(Maven 构建 + JRE 运行)
|
|
||||||
- ✅ wget 已安装(用于健康检查)
|
|
||||||
- ✅ 健康检查配置正确
|
|
||||||
- ✅ 上传目录已创建
|
|
||||||
- ✅ Java 21 运行时
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
#### Nginx Dockerfile (`nginx/Dockerfile`)
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ 基于 nginx:alpine
|
|
||||||
- ✅ 配置文件复制正确
|
|
||||||
- ✅ 目录创建完整
|
|
||||||
- ✅ 端口暴露正确
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 环境变量配置 ✅
|
|
||||||
|
|
||||||
**文件**: `application-prod.properties` vs `docker-compose.yml`
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ 环境变量名称匹配:
|
|
||||||
- `${DB_URL}` ← `DB_URL`
|
|
||||||
- `${DB_USERNAME}` ← `DB_USERNAME`
|
|
||||||
- `${DB_PASSWORD}` ← `DB_PASSWORD`
|
|
||||||
- ✅ 数据库连接字符串格式正确
|
|
||||||
- ✅ Spring Profile 配置正确
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 文件路径检查 ✅
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ `frontend/dist` 目录存在
|
|
||||||
- ✅ `pom.xml` 存在
|
|
||||||
- ✅ `nginx/nginx.conf` 存在
|
|
||||||
- ✅ `Dockerfile.backend` 存在
|
|
||||||
- ✅ `nginx/Dockerfile` 存在
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. Docker 环境检查 ✅
|
|
||||||
|
|
||||||
**检查项**:
|
|
||||||
- ✅ Docker 已安装:v28.4.0
|
|
||||||
- ✅ Docker Compose 已安装:v2.39.2
|
|
||||||
- ✅ Docker Compose 配置验证通过
|
|
||||||
- ✅ 所有服务定义正确(mysql, backend, nginx)
|
|
||||||
|
|
||||||
**状态**: ✅ **通过**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 已修复的问题
|
|
||||||
|
|
||||||
### 1. 后端健康检查工具缺失
|
|
||||||
- **问题**: Alpine 镜像默认没有 wget
|
|
||||||
- **修复**: 在 Dockerfile.backend 中添加 `RUN apk add --no-cache wget`
|
|
||||||
|
|
||||||
### 2. 环境变量不匹配
|
|
||||||
- **问题**: docker-compose.yml 使用 `SPRING_DATASOURCE_*`,但 application-prod.properties 期望 `DB_*`
|
|
||||||
- **修复**: 统一使用 `DB_URL`, `DB_USERNAME`, `DB_PASSWORD`
|
|
||||||
|
|
||||||
### 3. Docker Compose 版本警告
|
|
||||||
- **问题**: `version: '3.8'` 在新版本中已过时
|
|
||||||
- **修复**: 移除 version 字段
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 部署前检查清单
|
|
||||||
|
|
||||||
在运行 `docker-compose up` 之前:
|
|
||||||
|
|
||||||
- [x] ✅ 所有配置文件语法正确
|
|
||||||
- [x] ✅ 环境变量匹配
|
|
||||||
- [x] ✅ Docker 和 Docker Compose 已安装
|
|
||||||
- [ ] ⚠️ 前端已构建:`cd frontend && npm run build`
|
|
||||||
- [ ] ⚠️ 端口 80、8080、3306 未被占用
|
|
||||||
- [ ] ⚠️ 有足够的磁盘空间(至少 2GB)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 部署命令
|
|
||||||
|
|
||||||
### 方式一:使用部署脚本(推荐)
|
|
||||||
|
|
||||||
**Windows**:
|
|
||||||
```powershell
|
|
||||||
.\deploy.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux/Mac**:
|
|
||||||
```bash
|
|
||||||
chmod +x deploy.sh
|
|
||||||
./deploy.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方式二:手动部署
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 构建前端
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 2. 启动所有服务
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# 3. 查看日志
|
|
||||||
docker-compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 访问地址
|
|
||||||
|
|
||||||
部署成功后:
|
|
||||||
- 🌐 **前端**: http://localhost
|
|
||||||
- 🔗 **API**: http://localhost/api
|
|
||||||
- 🏥 **健康检查**: http://localhost/health
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 验证命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查服务状态
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
docker-compose logs -f nginx
|
|
||||||
docker-compose logs -f backend
|
|
||||||
|
|
||||||
# 测试 Nginx 配置
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
|
|
||||||
# 测试健康检查
|
|
||||||
curl http://localhost/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 总结
|
|
||||||
|
|
||||||
**配置状态**: ✅ **完全可用**
|
|
||||||
|
|
||||||
所有配置文件已验证通过,可以直接使用 Docker Compose 进行部署。
|
|
||||||
|
|
||||||
**建议**:
|
|
||||||
1. 先构建前端:`cd frontend && npm run build`
|
|
||||||
2. 然后启动服务:`docker-compose up -d --build`
|
|
||||||
3. 访问 http://localhost 验证部署
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**生成时间**: 2025-11-03
|
|
||||||
**验证工具**: Docker Compose v2.39.2
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,672 +0,0 @@
|
|||||||
# 🚀 项目上线部署准备清单
|
|
||||||
|
|
||||||
本文档提供了项目上线前的完整准备清单和部署步骤。
|
|
||||||
|
|
||||||
## 📋 一、服务器环境准备
|
|
||||||
|
|
||||||
### 1.1 服务器要求
|
|
||||||
|
|
||||||
**最低配置:**
|
|
||||||
- CPU: 4核
|
|
||||||
- 内存: 8GB
|
|
||||||
- 磁盘: 100GB SSD
|
|
||||||
- 带宽: 10Mbps
|
|
||||||
|
|
||||||
**推荐配置(支持50人并发):**
|
|
||||||
- CPU: 4核
|
|
||||||
- 内存: 8GB
|
|
||||||
- 磁盘: 100GB+ SSD
|
|
||||||
- 带宽: 20Mbps
|
|
||||||
|
|
||||||
### 1.2 操作系统
|
|
||||||
|
|
||||||
- **Linux**: Ubuntu 20.04+ / CentOS 7+ / Debian 11+
|
|
||||||
- **Windows Server**: Windows Server 2019+
|
|
||||||
|
|
||||||
### 1.3 必需软件安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Java 21 (必需)
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install openjdk-21-jdk
|
|
||||||
|
|
||||||
# 验证安装
|
|
||||||
java -version
|
|
||||||
|
|
||||||
# MySQL 8.0+ (必需)
|
|
||||||
sudo apt install mysql-server
|
|
||||||
sudo systemctl start mysql
|
|
||||||
sudo systemctl enable mysql
|
|
||||||
|
|
||||||
# FFmpeg (视频拼接功能需要)
|
|
||||||
# Ubuntu/Debian
|
|
||||||
sudo apt install ffmpeg
|
|
||||||
|
|
||||||
# CentOS/RHEL
|
|
||||||
sudo yum install epel-release
|
|
||||||
sudo yum install ffmpeg
|
|
||||||
|
|
||||||
# 验证安装
|
|
||||||
ffmpeg -version
|
|
||||||
|
|
||||||
# Nginx (反向代理,推荐)
|
|
||||||
sudo apt install nginx
|
|
||||||
|
|
||||||
# Maven (构建项目)
|
|
||||||
sudo apt install maven
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.4 目录结构准备
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建应用目录
|
|
||||||
sudo mkdir -p /app/aigc-platform
|
|
||||||
sudo mkdir -p /app/aigc-platform/logs
|
|
||||||
sudo mkdir -p /app/aigc-platform/uploads
|
|
||||||
sudo mkdir -p /app/aigc-platform/temp
|
|
||||||
sudo mkdir -p /app/aigc-platform/config
|
|
||||||
|
|
||||||
# 设置权限
|
|
||||||
sudo chown -R $USER:$USER /app/aigc-platform
|
|
||||||
chmod -R 755 /app/aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗄️ 二、数据库准备
|
|
||||||
|
|
||||||
### 2.1 创建数据库
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 登录MySQL
|
|
||||||
mysql -u root -p
|
|
||||||
|
|
||||||
-- 创建数据库
|
|
||||||
CREATE DATABASE aigc_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- 创建用户(推荐)
|
|
||||||
CREATE USER 'aigc_user'@'localhost' IDENTIFIED BY '强密码';
|
|
||||||
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_user'@'localhost';
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
|
|
||||||
-- 退出
|
|
||||||
EXIT;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 数据库配置优化
|
|
||||||
|
|
||||||
编辑 `/etc/mysql/mysql.conf.d/mysqld.cnf`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[mysqld]
|
|
||||||
# 字符集
|
|
||||||
character-set-server=utf8mb4
|
|
||||||
collation-server=utf8mb4_unicode_ci
|
|
||||||
|
|
||||||
# 连接数
|
|
||||||
max_connections=500
|
|
||||||
max_user_connections=400
|
|
||||||
|
|
||||||
# 缓冲池(根据内存调整,建议为内存的50-70%)
|
|
||||||
# 8GB内存服务器建议设置为2-4G
|
|
||||||
innodb_buffer_pool_size=2G
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
slow_query_log=1
|
|
||||||
slow_query_log_file=/var/log/mysql/slow-query.log
|
|
||||||
long_query_time=2
|
|
||||||
```
|
|
||||||
|
|
||||||
重启MySQL:
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart mysql
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ 三、环境变量配置
|
|
||||||
|
|
||||||
### 3.1 创建环境变量文件
|
|
||||||
|
|
||||||
创建 `/app/aigc-platform/config/.env`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 数据库配置
|
|
||||||
export DB_URL="jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"
|
|
||||||
export DB_USERNAME="aigc_user"
|
|
||||||
export DB_PASSWORD="你的数据库密码"
|
|
||||||
|
|
||||||
# JWT配置
|
|
||||||
export JWT_SECRET="生成一个至少128位的随机字符串"
|
|
||||||
export JWT_EXPIRATION="604800000"
|
|
||||||
|
|
||||||
# AI API配置(可通过管理页面修改,但建议先配置)
|
|
||||||
export AI_API_BASE_URL="https://ai.comfly.chat"
|
|
||||||
export AI_API_KEY="你的Comfly API密钥"
|
|
||||||
export AI_IMAGE_API_BASE_URL="https://ai.comfly.chat"
|
|
||||||
export AI_IMAGE_API_KEY="你的Comfly API密钥(文生图)"
|
|
||||||
|
|
||||||
# 支付宝配置(如需支付功能)
|
|
||||||
export ALIPAY_APP_ID="你的支付宝应用ID"
|
|
||||||
export ALIPAY_PRIVATE_KEY="你的应用私钥(RSA2格式,完整内容)"
|
|
||||||
export ALIPAY_PUBLIC_KEY="支付宝公钥(RSA2格式,完整内容)"
|
|
||||||
export ALIPAY_NOTIFY_URL="https://yourdomain.com/api/payments/alipay/notify"
|
|
||||||
export ALIPAY_RETURN_URL="https://yourdomain.com/api/payments/alipay/return"
|
|
||||||
|
|
||||||
# 腾讯云SES配置(如需邮件功能)
|
|
||||||
export TENCENT_SES_SECRET_ID="你的SecretId"
|
|
||||||
export TENCENT_SES_SECRET_KEY="你的SecretKey"
|
|
||||||
export TENCENT_SES_FROM_EMAIL="你的发件邮箱"
|
|
||||||
export TENCENT_SES_TEMPLATE_ID="你的邮件模板ID"
|
|
||||||
|
|
||||||
# 文件路径配置
|
|
||||||
export FFMPEG_PATH="/usr/bin/ffmpeg"
|
|
||||||
export TEMP_DIR="/app/aigc-platform/temp"
|
|
||||||
export UPLOAD_PATH="/app/aigc-platform/uploads"
|
|
||||||
export LOG_FILE_PATH="/app/aigc-platform/logs/application.log"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 生成JWT密钥
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 方法1:使用OpenSSL
|
|
||||||
openssl rand -base64 64
|
|
||||||
|
|
||||||
# 方法2:使用Python
|
|
||||||
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
|
|
||||||
|
|
||||||
# 方法3:在线生成
|
|
||||||
# 访问 https://www.random.org/strings/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 加载环境变量
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 编辑 ~/.bashrc 或 ~/.profile
|
|
||||||
echo "source /app/aigc-platform/config/.env" >> ~/.bashrc
|
|
||||||
source ~/.bashrc
|
|
||||||
|
|
||||||
# 或创建 systemd service 时直接加载
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 四、项目构建与部署
|
|
||||||
|
|
||||||
### 4.1 构建项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 进入项目目录
|
|
||||||
cd /path/to/AIGC/demo
|
|
||||||
|
|
||||||
# 清理并打包(跳过测试)
|
|
||||||
./mvnw clean package -DskipTests
|
|
||||||
|
|
||||||
# 或使用Maven
|
|
||||||
mvn clean package -DskipTests
|
|
||||||
|
|
||||||
# 打包后的JAR文件位置
|
|
||||||
# target/demo-0.0.1-SNAPSHOT.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 上传文件到服务器
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用SCP上传
|
|
||||||
scp target/demo-0.0.1-SNAPSHOT.jar user@server:/app/aigc-platform/
|
|
||||||
|
|
||||||
# 或使用FTP/SFTP工具
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 前端构建
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 进入前端目录
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
# 安装依赖(如果还没有)
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 构建生产版本
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# 构建后的文件在 dist/ 目录
|
|
||||||
# 需要配置Nginx指向 dist/ 目录
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 五、应用配置
|
|
||||||
|
|
||||||
### 5.1 创建生产环境配置文件
|
|
||||||
|
|
||||||
在服务器上创建 `/app/aigc-platform/config/application-prod.properties`:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 激活生产环境配置
|
|
||||||
spring.profiles.active=prod
|
|
||||||
|
|
||||||
# 数据库配置(使用环境变量)
|
|
||||||
spring.datasource.url=${DB_URL}
|
|
||||||
spring.datasource.username=${DB_USERNAME}
|
|
||||||
spring.datasource.password=${DB_PASSWORD}
|
|
||||||
|
|
||||||
# JWT配置
|
|
||||||
jwt.secret=${JWT_SECRET}
|
|
||||||
jwt.expiration=${JWT_EXPIRATION:604800000}
|
|
||||||
|
|
||||||
# 支付宝配置
|
|
||||||
alipay.app-id=${ALIPAY_APP_ID}
|
|
||||||
alipay.private-key=${ALIPAY_PRIVATE_KEY}
|
|
||||||
alipay.public-key=${ALIPAY_PUBLIC_KEY}
|
|
||||||
alipay.gateway-url=https://openapi.alipay.com/gateway.do
|
|
||||||
alipay.notify-url=${ALIPAY_NOTIFY_URL}
|
|
||||||
alipay.return-url=${ALIPAY_RETURN_URL}
|
|
||||||
|
|
||||||
# 腾讯云SES配置
|
|
||||||
tencent.ses.secret-id=${TENCENT_SES_SECRET_ID}
|
|
||||||
tencent.ses.secret-key=${TENCENT_SES_SECRET_KEY}
|
|
||||||
tencent.ses.from-email=${TENCENT_SES_FROM_EMAIL}
|
|
||||||
tencent.ses.template-id=${TENCENT_SES_TEMPLATE_ID}
|
|
||||||
|
|
||||||
# 文件路径
|
|
||||||
app.ffmpeg.path=${FFMPEG_PATH:ffmpeg}
|
|
||||||
app.temp.dir=${TEMP_DIR:./temp}
|
|
||||||
app.upload.path=${UPLOAD_PATH:./uploads}
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
logging.file.name=${LOG_FILE_PATH:./logs/application.log}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 创建Systemd服务(Linux)
|
|
||||||
|
|
||||||
创建 `/etc/systemd/system/aigc-platform.service`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Unit]
|
|
||||||
Description=AIGC Platform Application
|
|
||||||
After=network.target mysql.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=your-user
|
|
||||||
WorkingDirectory=/app/aigc-platform
|
|
||||||
EnvironmentFile=/app/aigc-platform/config/.env
|
|
||||||
ExecStart=/usr/bin/java -jar \
|
|
||||||
-Xms1g \
|
|
||||||
-Xmx4g \
|
|
||||||
-XX:+UseG1GC \
|
|
||||||
-XX:MaxGCPauseMillis=200 \
|
|
||||||
-Dspring.profiles.active=prod \
|
|
||||||
-Dspring.config.location=file:/app/aigc-platform/config/application-prod.properties \
|
|
||||||
/app/aigc-platform/demo-0.0.1-SNAPSHOT.jar
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=aigc-platform
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
|
||||||
|
|
||||||
启动服务:
|
|
||||||
```bash
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable aigc-platform
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
查看日志:
|
|
||||||
```bash
|
|
||||||
sudo journalctl -u aigc-platform -f
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 六、Nginx反向代理配置
|
|
||||||
|
|
||||||
### 6.1 创建Nginx配置
|
|
||||||
|
|
||||||
创建 `/etc/nginx/sites-available/aigc-platform`:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream aigc_backend {
|
|
||||||
server localhost:8080;
|
|
||||||
keepalive 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name yourdomain.com www.yourdomain.com;
|
|
||||||
|
|
||||||
# 重定向到HTTPS
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name yourdomain.com www.yourdomain.com;
|
|
||||||
|
|
||||||
# SSL证书配置
|
|
||||||
ssl_certificate /path/to/your/cert.pem;
|
|
||||||
ssl_certificate_key /path/to/your/key.pem;
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
# 前端静态文件
|
|
||||||
root /path/to/frontend/dist;
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
# 前端路由
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 后端API代理
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://aigc_backend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection 'upgrade';
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_cache_bypass $http_upgrade;
|
|
||||||
|
|
||||||
# 超时设置
|
|
||||||
proxy_connect_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 文件上传代理(支持大文件)
|
|
||||||
location /uploads/ {
|
|
||||||
proxy_pass http://aigc_backend;
|
|
||||||
proxy_request_buffering off;
|
|
||||||
client_max_body_size 500M;
|
|
||||||
proxy_connect_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
access_log /var/log/nginx/aigc-platform-access.log;
|
|
||||||
error_log /var/log/nginx/aigc-platform-error.log;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
启用配置:
|
|
||||||
```bash
|
|
||||||
sudo ln -s /etc/nginx/sites-available/aigc-platform /etc/nginx/sites-enabled/
|
|
||||||
sudo nginx -t
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.2 SSL证书(Let's Encrypt)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 安装Certbot
|
|
||||||
sudo apt install certbot python3-certbot-nginx
|
|
||||||
|
|
||||||
# 获取证书
|
|
||||||
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
|
|
||||||
|
|
||||||
# 自动续期
|
|
||||||
sudo certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 七、安全配置
|
|
||||||
|
|
||||||
### 7.1 防火墙配置
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# UFW (Ubuntu)
|
|
||||||
sudo ufw allow 22/tcp
|
|
||||||
sudo ufw allow 80/tcp
|
|
||||||
sudo ufw allow 443/tcp
|
|
||||||
sudo ufw enable
|
|
||||||
|
|
||||||
# Firewalld (CentOS)
|
|
||||||
sudo firewall-cmd --permanent --add-service=ssh
|
|
||||||
sudo firewall-cmd --permanent --add-service=http
|
|
||||||
sudo firewall-cmd --permanent --add-service=https
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.2 数据库安全
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 删除匿名用户
|
|
||||||
DELETE FROM mysql.user WHERE User='';
|
|
||||||
|
|
||||||
-- 禁止root远程登录(如果不需要)
|
|
||||||
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
|
|
||||||
|
|
||||||
-- 刷新权限
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.3 文件权限
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 配置文件权限
|
|
||||||
chmod 600 /app/aigc-platform/config/.env
|
|
||||||
chmod 600 /app/aigc-platform/config/application-prod.properties
|
|
||||||
|
|
||||||
# 日志目录权限
|
|
||||||
chmod 755 /app/aigc-platform/logs
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 八、监控与日志
|
|
||||||
|
|
||||||
### 8.1 日志管理
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 配置日志轮转
|
|
||||||
sudo nano /etc/logrotate.d/aigc-platform
|
|
||||||
|
|
||||||
# 内容:
|
|
||||||
/app/aigc-platform/logs/*.log {
|
|
||||||
daily
|
|
||||||
rotate 30
|
|
||||||
compress
|
|
||||||
delaycompress
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
create 0644 your-user your-user
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 监控脚本
|
|
||||||
|
|
||||||
创建 `/app/aigc-platform/scripts/health-check.sh`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
HEALTH_URL="http://localhost:8080/api/health"
|
|
||||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)
|
|
||||||
|
|
||||||
if [ $RESPONSE -ne 200 ]; then
|
|
||||||
echo "Health check failed: $RESPONSE"
|
|
||||||
systemctl restart aigc-platform
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
添加到crontab:
|
|
||||||
```bash
|
|
||||||
# 每5分钟检查一次
|
|
||||||
*/5 * * * * /app/aigc-platform/scripts/health-check.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 九、上线前检查清单
|
|
||||||
|
|
||||||
### 9.1 配置检查
|
|
||||||
|
|
||||||
- [ ] 数据库连接配置正确
|
|
||||||
- [ ] JWT密钥已生成并配置
|
|
||||||
- [ ] AI API密钥已配置
|
|
||||||
- [ ] 支付宝配置(如需要)
|
|
||||||
- [ ] 腾讯云SES配置(如需要)
|
|
||||||
- [ ] FFmpeg路径正确
|
|
||||||
- [ ] 文件上传目录权限正确
|
|
||||||
- [ ] 日志目录权限正确
|
|
||||||
|
|
||||||
### 9.2 功能测试
|
|
||||||
|
|
||||||
- [ ] 用户注册/登录
|
|
||||||
- [ ] 文生视频功能
|
|
||||||
- [ ] 图生视频功能
|
|
||||||
- [ ] 分镜视频功能
|
|
||||||
- [ ] 支付功能(如需要)
|
|
||||||
- [ ] 邮件发送(如需要)
|
|
||||||
- [ ] 文件上传/下载
|
|
||||||
- [ ] 视频拼接功能
|
|
||||||
|
|
||||||
### 9.3 性能测试
|
|
||||||
|
|
||||||
- [ ] 并发测试(建议使用JMeter)
|
|
||||||
- [ ] 数据库连接池测试
|
|
||||||
- [ ] 内存使用监控
|
|
||||||
- [ ] CPU使用监控
|
|
||||||
- [ ] 磁盘空间监控
|
|
||||||
|
|
||||||
### 9.4 安全检查
|
|
||||||
|
|
||||||
- [ ] 防火墙已配置
|
|
||||||
- [ ] SSL证书已安装
|
|
||||||
- [ ] 敏感信息使用环境变量
|
|
||||||
- [ ] 数据库用户权限最小化
|
|
||||||
- [ ] 文件权限已设置
|
|
||||||
|
|
||||||
### 9.5 备份策略
|
|
||||||
|
|
||||||
- [ ] 数据库自动备份脚本
|
|
||||||
- [ ] 文件上传目录备份
|
|
||||||
- [ ] 配置文件备份
|
|
||||||
- [ ] 备份恢复测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 十、部署流程
|
|
||||||
|
|
||||||
### 10.1 首次部署
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 准备服务器环境
|
|
||||||
# 2. 安装必需软件
|
|
||||||
# 3. 配置数据库
|
|
||||||
# 4. 配置环境变量
|
|
||||||
# 5. 构建项目
|
|
||||||
# 6. 上传文件
|
|
||||||
# 7. 配置Nginx
|
|
||||||
# 8. 启动服务
|
|
||||||
# 9. 测试功能
|
|
||||||
# 10. 配置监控
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10.2 更新部署
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 备份当前版本
|
|
||||||
cp demo-0.0.1-SNAPSHOT.jar demo-0.0.1-SNAPSHOT.jar.backup
|
|
||||||
|
|
||||||
# 2. 停止服务
|
|
||||||
sudo systemctl stop aigc-platform
|
|
||||||
|
|
||||||
# 3. 上传新版本
|
|
||||||
scp target/demo-0.0.1-SNAPSHOT.jar user@server:/app/aigc-platform/
|
|
||||||
|
|
||||||
# 4. 启动服务
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
|
|
||||||
# 5. 检查状态
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
sudo journalctl -u aigc-platform -f
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🆘 十一、常见问题排查
|
|
||||||
|
|
||||||
### 11.1 应用无法启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看日志
|
|
||||||
sudo journalctl -u aigc-platform -n 100
|
|
||||||
|
|
||||||
# 检查Java版本
|
|
||||||
java -version
|
|
||||||
|
|
||||||
# 检查端口占用
|
|
||||||
sudo netstat -tlnp | grep 8080
|
|
||||||
|
|
||||||
# 检查环境变量
|
|
||||||
env | grep DB_
|
|
||||||
```
|
|
||||||
|
|
||||||
### 11.2 数据库连接失败
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试数据库连接
|
|
||||||
mysql -h localhost -u aigc_user -p aigc_platform
|
|
||||||
|
|
||||||
# 检查MySQL服务
|
|
||||||
sudo systemctl status mysql
|
|
||||||
|
|
||||||
# 检查防火墙
|
|
||||||
sudo ufw status
|
|
||||||
```
|
|
||||||
|
|
||||||
### 11.3 文件上传失败
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查目录权限
|
|
||||||
ls -la /app/aigc-platform/uploads
|
|
||||||
|
|
||||||
# 检查磁盘空间
|
|
||||||
df -h
|
|
||||||
|
|
||||||
# 检查Nginx配置
|
|
||||||
sudo nginx -t
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 十二、技术支持
|
|
||||||
|
|
||||||
如遇到问题,请检查:
|
|
||||||
1. 应用日志:`/app/aigc-platform/logs/application.log`
|
|
||||||
2. 系统日志:`sudo journalctl -u aigc-platform`
|
|
||||||
3. Nginx日志:`/var/log/nginx/aigc-platform-error.log`
|
|
||||||
4. MySQL日志:`/var/log/mysql/error.log`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 十三、维护计划
|
|
||||||
|
|
||||||
### 日常维护
|
|
||||||
|
|
||||||
- **每日**: 检查日志、监控系统资源
|
|
||||||
- **每周**: 检查备份、清理临时文件
|
|
||||||
- **每月**: 更新依赖、安全补丁
|
|
||||||
|
|
||||||
### 定期任务
|
|
||||||
|
|
||||||
- **数据库备份**: 每天凌晨2点
|
|
||||||
- **日志清理**: 每天凌晨4点
|
|
||||||
- **任务清理**: 每天凌晨4点(已配置定时任务)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**祝部署顺利!** 🎉
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# 构建阶段
|
|
||||||
FROM maven:3.9-eclipse-temurin-21 AS build
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# 复制 pom.xml 和源代码
|
|
||||||
COPY pom.xml .
|
|
||||||
COPY src ./src
|
|
||||||
|
|
||||||
# 构建应用
|
|
||||||
RUN mvn clean package -DskipTests
|
|
||||||
|
|
||||||
# 运行阶段
|
|
||||||
FROM eclipse-temurin:21-jre-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# 安装wget用于健康检查
|
|
||||||
RUN apk add --no-cache wget
|
|
||||||
|
|
||||||
# 创建上传目录
|
|
||||||
RUN mkdir -p /app/uploads
|
|
||||||
|
|
||||||
# 复制构建的 JAR 文件
|
|
||||||
COPY --from=build /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
|
|
||||||
|
|
||||||
# 暴露端口
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
||||||
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
|
||||||
|
|
||||||
# 启动应用
|
|
||||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
|
||||||
|
|
||||||
@@ -1,348 +0,0 @@
|
|||||||
# 邮件登录模块配置清单
|
|
||||||
|
|
||||||
## 一、已配置项 ✅
|
|
||||||
|
|
||||||
### 1. 开发环境配置(application-dev.properties)
|
|
||||||
- ✅ `tencent.ses.secret-id` - SecretID(已配置)
|
|
||||||
- ✅ `tencent.ses.secret-key` - SecretKey(已配置)
|
|
||||||
- ✅ `tencent.ses.region` - 服务区域(ap-beijing)
|
|
||||||
- ✅ `tencent.ses.from-email` - 发信地址(newletter@vionow.com)
|
|
||||||
- ✅ `tencent.ses.from-name` - 发件人名称(AIGC平台)
|
|
||||||
- ✅ `tencent.ses.template-id` - 模板ID(154360,生产模式)
|
|
||||||
|
|
||||||
### 2. 代码实现
|
|
||||||
- ✅ 邮箱验证码登录接口(`/api/auth/login/email`)
|
|
||||||
- ✅ 发送验证码接口(`/api/verification/email/send`)
|
|
||||||
- ✅ 验证码服务(VerificationCodeService)
|
|
||||||
- ✅ 腾讯云SES邮件服务(TencentSesMailService)
|
|
||||||
- ✅ 前端登录页面(Login.vue)
|
|
||||||
- ✅ 用户名密码登录已禁用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 二、需要检查/更新项 ⚠️
|
|
||||||
|
|
||||||
### 1. 腾讯云SES服务权限检查 ⚠️ **重要**
|
|
||||||
|
|
||||||
**当前配置的账号信息:**
|
|
||||||
- 主账号ID: `100040185043`
|
|
||||||
- 用户名: `test`
|
|
||||||
- SecretID: `AKIDXw8HBtNfjdJm480xljV4QZUDi05wa0DE`
|
|
||||||
- SecretKey: `tZyHMDsKadS4ScZhhU3PYUErGUVIqBIB`
|
|
||||||
|
|
||||||
**需要确认:**
|
|
||||||
- [ ] **SecretID/SecretKey 是否有效**
|
|
||||||
- 检查密钥是否过期或被撤销
|
|
||||||
- 访问:https://console.cloud.tencent.com/cam/capi
|
|
||||||
|
|
||||||
- [ ] **是否有SES服务访问权限**
|
|
||||||
- 子账号需要有SES(邮件推送)服务的访问权限
|
|
||||||
- 如果没有权限,需要在主账号中授权
|
|
||||||
|
|
||||||
**检查步骤:**
|
|
||||||
1. 登录腾讯云控制台
|
|
||||||
2. 进入"访问管理" → "API密钥管理"
|
|
||||||
3. 检查密钥状态
|
|
||||||
4. 检查子账号权限策略
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 发信地址验证 ⚠️ **重要(生产环境必需)**
|
|
||||||
|
|
||||||
**当前配置:**
|
|
||||||
- 发信地址: `newletter@vionow.com`
|
|
||||||
|
|
||||||
**需要操作:**
|
|
||||||
- [ ] **确认发信地址是否已验证**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses/address
|
|
||||||
- 检查 `newletter@vionow.com` 的状态
|
|
||||||
- 如果状态为"未验证"或"验证失败":
|
|
||||||
|
|
||||||
**验证步骤:**
|
|
||||||
1. 进入SES控制台 → "发信地址"
|
|
||||||
2. 点击"创建发信地址"或编辑现有地址
|
|
||||||
3. 输入邮箱:`newletter@vionow.com`
|
|
||||||
4. 腾讯云会发送验证邮件到该邮箱
|
|
||||||
5. 点击邮件中的验证链接完成验证
|
|
||||||
6. 确认状态变为"已验证"
|
|
||||||
|
|
||||||
**注意:**
|
|
||||||
- ⚠️ 只有验证通过的邮箱才能发送邮件
|
|
||||||
- ⚠️ 开发模式(template-id=0)不需要验证也能测试,但不会实际发邮件
|
|
||||||
- ⚠️ 生产模式必须有已验证的发信地址
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 邮件模板配置 ✅ **已配置**
|
|
||||||
|
|
||||||
**当前状态:**
|
|
||||||
- `template-id=154360` - 生产模式(已配置)
|
|
||||||
|
|
||||||
**当前配置:**
|
|
||||||
- ✅ 模板ID已配置为 `154360`
|
|
||||||
- ✅ 系统将使用生产模式,实际发送邮件
|
|
||||||
|
|
||||||
**模板说明:**
|
|
||||||
- 模板ID: `154360`
|
|
||||||
- 模式: 生产模式(会实际发送邮件)
|
|
||||||
- 验证码变量: 模板中应包含 `{{code}}` 变量用于替换验证码
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 生产环境配置 ⚠️ **缺失**
|
|
||||||
|
|
||||||
**当前状态:**
|
|
||||||
`application-prod.properties` 中**没有腾讯云SES配置**
|
|
||||||
|
|
||||||
**需要添加:**
|
|
||||||
- [ ] **在生产环境配置文件中添加SES配置**
|
|
||||||
|
|
||||||
**操作步骤:**
|
|
||||||
在 `demo/src/main/resources/application-prod.properties` 中添加:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 腾讯云SES配置 (生产环境)
|
|
||||||
tencent.ses.secret-id=${TENCENT_SES_SECRET_ID}
|
|
||||||
tencent.ses.secret-key=${TENCENT_SES_SECRET_KEY}
|
|
||||||
tencent.ses.region=ap-beijing
|
|
||||||
tencent.ses.from-email=${TENCENT_SES_FROM_EMAIL}
|
|
||||||
tencent.ses.from-name=AIGC平台
|
|
||||||
tencent.ses.template-id=${TENCENT_SES_TEMPLATE_ID}
|
|
||||||
```
|
|
||||||
|
|
||||||
**环境变量设置:**
|
|
||||||
```bash
|
|
||||||
export TENCENT_SES_SECRET_ID=你的SecretID
|
|
||||||
export TENCENT_SES_SECRET_KEY=你的SecretKey
|
|
||||||
export TENCENT_SES_FROM_EMAIL=newletter@vionow.com
|
|
||||||
export TENCENT_SES_TEMPLATE_ID=你的模板ID
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. SES服务开通和额度 ⚠️ **重要**
|
|
||||||
|
|
||||||
**需要确认:**
|
|
||||||
- [ ] **SES服务是否已开通**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses
|
|
||||||
- 检查服务状态
|
|
||||||
|
|
||||||
- [ ] **是否有可用额度**
|
|
||||||
- 检查账户余额或免费额度
|
|
||||||
- 确认是否有足够的邮件发送配额
|
|
||||||
- 查看计费信息
|
|
||||||
|
|
||||||
**检查步骤:**
|
|
||||||
1. 登录腾讯云控制台
|
|
||||||
2. 进入SES服务控制台
|
|
||||||
3. 查看"概览"页面的配额和用量信息
|
|
||||||
4. 确认是否有可用额度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. 测试验证 ⚠️ **重要**
|
|
||||||
|
|
||||||
**开发模式测试:**
|
|
||||||
- [ ] **启动服务并测试**
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
./mvnw spring-boot:run
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **测试发送验证码**
|
|
||||||
```bash
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **检查邮箱**
|
|
||||||
- 应该收到实际邮件,包含6位数字验证码
|
|
||||||
- 邮件来自:newletter@vionow.com
|
|
||||||
|
|
||||||
- [ ] **测试登录**
|
|
||||||
- 访问登录页面
|
|
||||||
- 输入邮箱和验证码
|
|
||||||
- 验证登录功能
|
|
||||||
|
|
||||||
**生产模式测试(已完成配置):**
|
|
||||||
- [x] ✅ **Template-id已配置为154360**
|
|
||||||
- [ ] **重启服务**(如果服务正在运行)
|
|
||||||
- [ ] **发送测试邮件**
|
|
||||||
- [ ] **检查实际邮箱是否收到邮件**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、配置优先级
|
|
||||||
|
|
||||||
### 🔴 紧急(必须配置)
|
|
||||||
1. **发信地址验证** - 生产环境必须验证才能发送邮件
|
|
||||||
2. **邮件模板创建** - 生产环境必须配置模板ID
|
|
||||||
3. **生产环境配置** - `application-prod.properties` 缺少SES配置
|
|
||||||
|
|
||||||
### 🟡 重要(建议配置)
|
|
||||||
4. **SES服务权限检查** - 确保账号有权限访问SES服务
|
|
||||||
5. **SES服务开通和额度** - 确保有可用配额
|
|
||||||
6. **测试验证** - 确保功能正常(会实际发送邮件)
|
|
||||||
7. **发信地址验证** - 确保 newletter@vionow.com 已验证
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 四、配置检查清单
|
|
||||||
|
|
||||||
### 开发环境配置状态
|
|
||||||
|
|
||||||
| 配置项 | 状态 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| SecretID | ✅ 已配置 | 需确认有效性和权限 |
|
|
||||||
| SecretKey | ✅ 已配置 | 需确认有效性 |
|
|
||||||
| Region | ✅ 已配置 | ap-beijing |
|
|
||||||
| From-email | ✅ 已配置 | newletter@vionow.com(需确认已验证) |
|
|
||||||
| From-name | ✅ 已配置 | AIGC平台 |
|
|
||||||
| Template-id | ✅ 已配置 | 154360(生产模式) |
|
|
||||||
|
|
||||||
### 生产环境配置状态
|
|
||||||
|
|
||||||
| 配置项 | 状态 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| SecretID | ❌ 未配置 | 需要添加环境变量 |
|
|
||||||
| SecretKey | ❌ 未配置 | 需要添加环境变量 |
|
|
||||||
| Region | ❌ 未配置 | 需要添加配置 |
|
|
||||||
| From-email | ❌ 未配置 | 需要添加环境变量 |
|
|
||||||
| From-name | ❌ 未配置 | 需要添加配置 |
|
|
||||||
| Template-id | ❌ 未配置 | 需要创建模板并配置ID |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 五、快速检查命令
|
|
||||||
|
|
||||||
### 检查配置文件
|
|
||||||
```bash
|
|
||||||
# Windows PowerShell
|
|
||||||
Test-Path demo/src/main/resources/application-dev.properties
|
|
||||||
Test-Path demo/src/main/resources/application-prod.properties
|
|
||||||
|
|
||||||
# 检查SES配置项
|
|
||||||
Select-String -Path "demo/src/main/resources/application-dev.properties" -Pattern "tencent.ses"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试邮件发送功能
|
|
||||||
```bash
|
|
||||||
# 开发模式测试(不会实际发送邮件)
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com"}'
|
|
||||||
|
|
||||||
# 检查日志中的验证码
|
|
||||||
# 应该看到:开发模式:邮件验证码发送到: test@example.com, 验证码: XXXXXX
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试登录功能
|
|
||||||
```bash
|
|
||||||
# 使用开发接口设置验证码(开发模式)
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/dev-set \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com","code":"123456"}'
|
|
||||||
|
|
||||||
# 测试登录
|
|
||||||
curl -X POST http://localhost:8080/api/auth/login/email \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com","code":"123456"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 六、常见问题
|
|
||||||
|
|
||||||
### Q1: 当前配置为生产模式
|
|
||||||
**A:** 当前模板ID已配置为154360(生产模式),系统会实际发送邮件。请确保:
|
|
||||||
- 发信地址 `newletter@vionow.com` 已验证
|
|
||||||
- SES服务有可用额度
|
|
||||||
- 模板ID 154360 在腾讯云SES控制台已审核通过
|
|
||||||
|
|
||||||
### Q2: 发送失败 - 认证错误
|
|
||||||
```
|
|
||||||
InvalidSecretId.InvalidSignature
|
|
||||||
```
|
|
||||||
**解决:**
|
|
||||||
- 检查SecretID和SecretKey是否正确
|
|
||||||
- 确认密钥是否有SES服务权限
|
|
||||||
- 检查密钥是否过期
|
|
||||||
|
|
||||||
### Q3: 发送失败 - 发信地址未验证
|
|
||||||
```
|
|
||||||
InvalidParameter.EmailAddressNotVerified
|
|
||||||
```
|
|
||||||
**解决:**
|
|
||||||
- 在SES控制台验证发信地址
|
|
||||||
- 检查 `tencent.ses.from-email` 配置是否正确
|
|
||||||
- 注意:开发模式(template-id=0)不需要验证也能测试
|
|
||||||
|
|
||||||
### Q4: 发送失败 - 模板不存在
|
|
||||||
```
|
|
||||||
ResourceNotFound.TemplateNotFound
|
|
||||||
```
|
|
||||||
**解决:**
|
|
||||||
- 确认模板ID是否正确
|
|
||||||
- 检查模板是否已审核通过
|
|
||||||
- 确认模板区域与配置的region一致
|
|
||||||
|
|
||||||
### Q5: 当前已是生产模式
|
|
||||||
**A:** 当前已配置为生产模式(template-id=154360),系统会实际发送邮件。如需切换回开发模式,将template-id设置为0即可。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 七、下一步操作建议
|
|
||||||
|
|
||||||
### 当前配置(生产模式)
|
|
||||||
1. ✅ **模板ID已配置为154360**(生产模式)
|
|
||||||
2. ⚠️ **验证发信地址**(重要)
|
|
||||||
- 确保 `newletter@vionow.com` 在SES控制台已验证
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses/address
|
|
||||||
|
|
||||||
3. ⚠️ **测试实际发送邮件**
|
|
||||||
- 重启服务(如果正在运行)
|
|
||||||
- 发送测试验证码
|
|
||||||
- 检查邮箱是否收到邮件
|
|
||||||
|
|
||||||
4. ⚠️ **更新生产环境配置**
|
|
||||||
- 在 `application-prod.properties` 中已添加SES配置
|
|
||||||
- 设置环境变量 `TENCENT_SES_TEMPLATE_ID=154360`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 八、相关文档链接
|
|
||||||
|
|
||||||
- **腾讯云SES控制台**: https://console.cloud.tencent.com/ses
|
|
||||||
- **发信地址管理**: https://console.cloud.tencent.com/ses/address
|
|
||||||
- **邮件模板管理**: https://console.cloud.tencent.com/ses/template
|
|
||||||
- **API密钥管理**: https://console.cloud.tencent.com/cam/capi
|
|
||||||
- **SES文档**: https://cloud.tencent.com/document/product/1288
|
|
||||||
- **邮箱验证登录指南**: `EMAIL_VERIFICATION_LOGIN_GUIDE.md`
|
|
||||||
- **SES启动检查清单**: `TENCENT_SES_STARTUP_CHECKLIST.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 九、总结
|
|
||||||
|
|
||||||
### 当前状态
|
|
||||||
- ✅ **开发环境配置已完成**,包括模板ID 154360
|
|
||||||
- ✅ **生产模式已启用**(template-id=154360),会实际发送邮件
|
|
||||||
- ⚠️ **需要确保发信地址已验证**
|
|
||||||
|
|
||||||
### 最小启动要求
|
|
||||||
1. ✅ SecretID和SecretKey(已配置)
|
|
||||||
2. ✅ From-email地址(已配置:newletter@vionow.com)
|
|
||||||
3. ✅ Template-id=154360(生产模式,已配置)
|
|
||||||
|
|
||||||
### 生产环境要求
|
|
||||||
1. ⚠️ 已验证的发信地址(newletter@vionow.com)
|
|
||||||
2. ✅ 已配置的邮件模板(ID: 154360)
|
|
||||||
3. ✅ 生产环境配置文件中的SES配置(已添加)
|
|
||||||
4. ⚠️ 有效的SecretID/SecretKey和SES服务权限(需确认)
|
|
||||||
|
|
||||||
**当前状态:** 已配置为生产模式,会实际发送邮件。请确保:
|
|
||||||
- 发信地址 `newletter@vionow.com` 已验证
|
|
||||||
- 模板ID 154360 已审核通过
|
|
||||||
- SES服务有可用额度
|
|
||||||
|
|
||||||
@@ -1,378 +0,0 @@
|
|||||||
# 邮件登录模块测试检查清单
|
|
||||||
|
|
||||||
## 📋 测试前检查
|
|
||||||
|
|
||||||
### 1. 配置检查 ✅
|
|
||||||
|
|
||||||
**当前配置状态:**
|
|
||||||
- ✅ SecretID: `AKIDXw8HBtNfjdJm480xljV4QZUDi05wa0DE`
|
|
||||||
- ✅ SecretKey: `tZyHMDsKadS4ScZhhU3PYUErGUVIqBIB`
|
|
||||||
- ✅ Region: `ap-beijing`
|
|
||||||
- ✅ From-email: `newletter@vionow.com`
|
|
||||||
- ✅ Template-id: `154360`(生产模式)
|
|
||||||
|
|
||||||
**需要确认:**
|
|
||||||
- [ ] **发信地址是否已验证**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses/address
|
|
||||||
- 检查 `newletter@vionow.com` 状态应为"已验证"
|
|
||||||
- ⚠️ **重要**:未验证的发信地址无法发送邮件
|
|
||||||
|
|
||||||
- [ ] **模板ID是否有效**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses/template
|
|
||||||
- 检查模板ID `154360` 是否已审核通过
|
|
||||||
- 确认模板中包含 `{{code}}` 变量
|
|
||||||
|
|
||||||
- [ ] **SES服务是否有可用额度**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses
|
|
||||||
- 检查账户余额或免费额度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 服务检查
|
|
||||||
|
|
||||||
- [ ] **后端服务是否运行**
|
|
||||||
```bash
|
|
||||||
# 检查服务是否在运行
|
|
||||||
# 访问:http://localhost:8080
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **前端服务是否运行**
|
|
||||||
```bash
|
|
||||||
# 检查前端是否在运行
|
|
||||||
# 访问:http://localhost:5173
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] **数据库是否正常**
|
|
||||||
- 确认数据库连接正常
|
|
||||||
- 确认用户表等表结构存在
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 测试邮箱准备
|
|
||||||
|
|
||||||
- [ ] **准备测试邮箱地址**
|
|
||||||
- 使用真实的邮箱地址(可以正常接收邮件)
|
|
||||||
- 建议使用常用邮箱:Gmail、QQ邮箱、163邮箱等
|
|
||||||
- 确保可以访问邮箱查看验证码
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 测试步骤
|
|
||||||
|
|
||||||
### 步骤1:访问登录页面
|
|
||||||
|
|
||||||
1. 打开浏览器访问:`http://localhost:5173/login`
|
|
||||||
- 或访问部署的前端地址
|
|
||||||
|
|
||||||
2. 确认页面显示:
|
|
||||||
- ✅ 邮箱输入框
|
|
||||||
- ✅ 验证码输入框
|
|
||||||
- ✅ "获取验证码"按钮
|
|
||||||
- ✅ "登录/注册"按钮
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤2:发送验证码
|
|
||||||
|
|
||||||
1. **输入邮箱地址**
|
|
||||||
- 输入一个有效的邮箱地址(例如:`test@example.com`)
|
|
||||||
|
|
||||||
2. **点击"获取验证码"按钮**
|
|
||||||
- 观察按钮是否进入60秒倒计时状态
|
|
||||||
- 观察是否有成功提示
|
|
||||||
|
|
||||||
3. **检查结果:**
|
|
||||||
- ✅ **成功**:显示"验证码已发送到您的邮箱"
|
|
||||||
- ❌ **失败**:检查错误信息
|
|
||||||
|
|
||||||
4. **查看日志(如有错误)**
|
|
||||||
```bash
|
|
||||||
# 查看后端日志,查找错误信息
|
|
||||||
# 可能的问题:
|
|
||||||
# - 发信地址未验证
|
|
||||||
# - 模板ID无效
|
|
||||||
# - 权限不足
|
|
||||||
# - 额度不足
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤3:接收验证码
|
|
||||||
|
|
||||||
**当前配置为生产模式(template-id=154360),会实际发送邮件。**
|
|
||||||
|
|
||||||
1. **检查邮箱收件箱**
|
|
||||||
- 邮件来自:`newletter@vionow.com`
|
|
||||||
- 邮件主题:根据模板配置
|
|
||||||
- 邮件内容:包含6位数字验证码
|
|
||||||
|
|
||||||
2. **如果未收到邮件:**
|
|
||||||
- 检查垃圾邮件文件夹
|
|
||||||
- 等待1-2分钟(邮件发送可能有延迟)
|
|
||||||
- 检查邮箱是否正确输入
|
|
||||||
- 查看后端日志是否有错误
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤4:输入验证码并登录
|
|
||||||
|
|
||||||
1. **输入验证码**
|
|
||||||
- 输入邮箱中收到的6位数字验证码
|
|
||||||
|
|
||||||
2. **点击"登录/注册"按钮**
|
|
||||||
|
|
||||||
3. **检查结果:**
|
|
||||||
- ✅ **成功**:
|
|
||||||
- 跳转到主页或个人中心
|
|
||||||
- 显示登录成功提示
|
|
||||||
- 浏览器控制台中保存了token
|
|
||||||
- ❌ **失败**:检查错误信息
|
|
||||||
- 验证码错误
|
|
||||||
- 验证码过期(5分钟)
|
|
||||||
- 其他错误
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 步骤5:验证登录状态
|
|
||||||
|
|
||||||
1. **检查Token是否保存**
|
|
||||||
- 打开浏览器开发者工具
|
|
||||||
- 查看 `sessionStorage` 或 `localStorage`
|
|
||||||
- 确认 `token` 和 `user` 信息已保存
|
|
||||||
|
|
||||||
2. **检查用户信息**
|
|
||||||
- 查看个人中心或用户信息页面
|
|
||||||
- 确认邮箱等信息正确显示
|
|
||||||
|
|
||||||
3. **测试自动注册功能**
|
|
||||||
- 使用一个新的邮箱地址测试
|
|
||||||
- 系统应自动创建新用户并登录
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 常见问题排查
|
|
||||||
|
|
||||||
### 问题1:点击获取验证码后没有反应
|
|
||||||
|
|
||||||
**可能原因:**
|
|
||||||
- 前端服务未启动
|
|
||||||
- 后端服务未启动
|
|
||||||
- 网络连接问题
|
|
||||||
|
|
||||||
**解决方法:**
|
|
||||||
1. 检查前端控制台错误信息
|
|
||||||
2. 检查后端服务是否运行
|
|
||||||
3. 检查API接口地址是否正确
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 问题2:显示"发送失败"或错误信息
|
|
||||||
|
|
||||||
**可能原因:**
|
|
||||||
- 发信地址未验证
|
|
||||||
- 模板ID无效或未审核
|
|
||||||
- SecretID/SecretKey权限不足
|
|
||||||
- SES服务额度不足
|
|
||||||
|
|
||||||
**解决方法:**
|
|
||||||
1. 检查SES控制台发信地址状态
|
|
||||||
2. 检查模板ID是否正确且已审核
|
|
||||||
3. 检查API密钥权限
|
|
||||||
4. 检查SES服务额度
|
|
||||||
|
|
||||||
**查看后端日志:**
|
|
||||||
```bash
|
|
||||||
# 查看详细的错误信息
|
|
||||||
# 常见错误:
|
|
||||||
# - InvalidParameter.EmailAddressNotVerified(发信地址未验证)
|
|
||||||
# - ResourceNotFound.TemplateNotFound(模板不存在)
|
|
||||||
# - InvalidSecretId.InvalidSignature(密钥错误)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 问题3:收不到邮件
|
|
||||||
|
|
||||||
**可能原因:**
|
|
||||||
- 邮箱地址输入错误
|
|
||||||
- 邮件被垃圾邮件过滤器拦截
|
|
||||||
- 邮件发送延迟
|
|
||||||
- 发信地址未验证(生产模式)
|
|
||||||
|
|
||||||
**解决方法:**
|
|
||||||
1. 检查邮箱地址是否正确
|
|
||||||
2. 检查垃圾邮件文件夹
|
|
||||||
3. 等待1-2分钟
|
|
||||||
4. 确认发信地址已验证
|
|
||||||
5. 查看后端日志确认是否发送成功
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 问题4:验证码验证失败
|
|
||||||
|
|
||||||
**可能原因:**
|
|
||||||
- 验证码输入错误
|
|
||||||
- 验证码已过期(5分钟)
|
|
||||||
- 验证码已被使用
|
|
||||||
- 邮箱地址不匹配
|
|
||||||
|
|
||||||
**解决方法:**
|
|
||||||
1. 确认验证码输入正确(6位数字)
|
|
||||||
2. 确认在5分钟内使用
|
|
||||||
3. 重新获取验证码
|
|
||||||
4. 确认邮箱地址与获取验证码时一致
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试用例
|
|
||||||
|
|
||||||
### 测试用例1:正常登录流程
|
|
||||||
|
|
||||||
**步骤:**
|
|
||||||
1. 输入邮箱:`test@example.com`
|
|
||||||
2. 点击"获取验证码"
|
|
||||||
3. 等待邮件到达(生产模式)
|
|
||||||
4. 输入验证码
|
|
||||||
5. 点击"登录/注册"
|
|
||||||
|
|
||||||
**预期结果:**
|
|
||||||
- ✅ 验证码发送成功
|
|
||||||
- ✅ 收到邮件
|
|
||||||
- ✅ 登录成功
|
|
||||||
- ✅ 跳转到主页
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 测试用例2:自动注册新用户
|
|
||||||
|
|
||||||
**步骤:**
|
|
||||||
1. 输入一个从未使用过的邮箱:`newuser@example.com`
|
|
||||||
2. 点击"获取验证码"
|
|
||||||
3. 收到验证码后输入
|
|
||||||
4. 点击"登录/注册"
|
|
||||||
|
|
||||||
**预期结果:**
|
|
||||||
- ✅ 系统自动创建新用户
|
|
||||||
- ✅ 自动登录
|
|
||||||
- ✅ 用户信息正确保存
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 测试用例3:验证码过期测试
|
|
||||||
|
|
||||||
**步骤:**
|
|
||||||
1. 获取验证码
|
|
||||||
2. 等待超过5分钟
|
|
||||||
3. 输入验证码尝试登录
|
|
||||||
|
|
||||||
**预期结果:**
|
|
||||||
- ❌ 提示验证码已过期
|
|
||||||
- ✅ 需要重新获取验证码
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 测试用例4:发送频率限制
|
|
||||||
|
|
||||||
**步骤:**
|
|
||||||
1. 点击"获取验证码"
|
|
||||||
2. 在60秒内再次点击"获取验证码"
|
|
||||||
|
|
||||||
**预期结果:**
|
|
||||||
- ✅ 按钮处于倒计时状态,无法点击
|
|
||||||
- ✅ 或提示"发送过于频繁"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 测试用例5:邮箱格式验证
|
|
||||||
|
|
||||||
**步骤:**
|
|
||||||
1. 输入无效邮箱:`invalid-email`
|
|
||||||
2. 点击"获取验证码"
|
|
||||||
|
|
||||||
**预期结果:**
|
|
||||||
- ❌ 提示"请输入正确的邮箱地址"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 测试完成检查清单
|
|
||||||
|
|
||||||
完成测试后,确认以下功能正常:
|
|
||||||
|
|
||||||
- [ ] ✅ 可以发送验证码
|
|
||||||
- [ ] ✅ 可以收到邮件(生产模式)
|
|
||||||
- [ ] ✅ 可以输入验证码登录
|
|
||||||
- [ ] ✅ 新用户可以自动注册
|
|
||||||
- [ ] ✅ Token正确保存
|
|
||||||
- [ ] ✅ 用户信息正确显示
|
|
||||||
- [ ] ✅ 验证码过期机制正常
|
|
||||||
- [ ] ✅ 发送频率限制正常
|
|
||||||
- [ ] ✅ 邮箱格式验证正常
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 测试记录模板
|
|
||||||
|
|
||||||
```
|
|
||||||
测试时间:____年__月__日 __:__
|
|
||||||
测试环境:开发/生产
|
|
||||||
发信地址状态:已验证/未验证
|
|
||||||
模板ID状态:已审核/未审核
|
|
||||||
|
|
||||||
测试邮箱:_______________
|
|
||||||
测试结果:
|
|
||||||
[ ] 发送验证码成功
|
|
||||||
[ ] 收到邮件
|
|
||||||
[ ] 登录成功
|
|
||||||
[ ] 自动注册成功
|
|
||||||
|
|
||||||
遇到的问题:
|
|
||||||
_________________________________
|
|
||||||
|
|
||||||
解决方案:
|
|
||||||
_________________________________
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚨 重要提醒
|
|
||||||
|
|
||||||
### 生产模式注意事项
|
|
||||||
|
|
||||||
**当前配置为生产模式(template-id=154360),会实际发送邮件。**
|
|
||||||
|
|
||||||
⚠️ **必须确保:**
|
|
||||||
1. 发信地址 `newletter@vionow.com` 已验证
|
|
||||||
2. 模板ID `154360` 已审核通过
|
|
||||||
3. SES服务有可用额度
|
|
||||||
4. API密钥有SES服务权限
|
|
||||||
|
|
||||||
### 如果发信地址未验证
|
|
||||||
|
|
||||||
**临时解决方案(仅用于测试):**
|
|
||||||
可以将 `template-id` 临时改为 `0`,进入开发模式:
|
|
||||||
```properties
|
|
||||||
tencent.ses.template-id=0
|
|
||||||
```
|
|
||||||
开发模式下不会实际发送邮件,验证码会在日志中显示。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔗 相关资源
|
|
||||||
|
|
||||||
- **腾讯云SES控制台**: https://console.cloud.tencent.com/ses
|
|
||||||
- **发信地址管理**: https://console.cloud.tencent.com/ses/address
|
|
||||||
- **邮件模板管理**: https://console.cloud.tencent.com/ses/template
|
|
||||||
- **邮箱验证登录指南**: `EMAIL_VERIFICATION_LOGIN_GUIDE.md`
|
|
||||||
- **邮件登录配置清单**: `EMAIL_LOGIN_CONFIGURATION_CHECKLIST.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 测试准备完成
|
|
||||||
|
|
||||||
**配置状态:**
|
|
||||||
- ✅ 所有必需配置已设置
|
|
||||||
- ⚠️ 需要确认发信地址已验证
|
|
||||||
- ⚠️ 需要确认模板ID已审核
|
|
||||||
|
|
||||||
**可以开始测试!**
|
|
||||||
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
# 邮件发送问题诊断指南
|
|
||||||
|
|
||||||
## 🔍 问题分析
|
|
||||||
|
|
||||||
根据你提供的日志,发现了以下情况:
|
|
||||||
|
|
||||||
### 日志分析
|
|
||||||
|
|
||||||
**你的日志显示:**
|
|
||||||
```
|
|
||||||
INFO ... VerificationCodeService : 邮件验证码发送成功,邮箱: 984523799@qq.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**但是缺少以下关键日志:**
|
|
||||||
- ❌ 没有看到 "当前邮件模板ID配置: xxx"
|
|
||||||
- ❌ 没有看到 "未配置邮件模板ID,使用开发模式"(开发模式警告)
|
|
||||||
- ❌ 没有看到 "使用生产模式发送邮件"(生产模式日志)
|
|
||||||
- ❌ 没有看到 "开始发送邮件,收件人: ..."(TencentSesMailService日志)
|
|
||||||
|
|
||||||
### 可能的原因
|
|
||||||
|
|
||||||
1. **配置值未正确读取**
|
|
||||||
- `template-id=154360` 可能没有被正确读取
|
|
||||||
- 默认值 `0` 被使用,进入了开发模式
|
|
||||||
- 但开发模式的警告日志也没有出现
|
|
||||||
|
|
||||||
2. **服务使用旧版本代码**
|
|
||||||
- 可能运行的jar包是旧版本
|
|
||||||
- 需要重新编译并启动
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ 诊断步骤
|
|
||||||
|
|
||||||
### 步骤1:检查配置是否正确读取
|
|
||||||
|
|
||||||
我已经更新了代码,添加了更详细的日志。请:
|
|
||||||
|
|
||||||
1. **重新编译项目**
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
mvn clean package
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **重新启动服务**
|
|
||||||
```bash
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **再次测试发送验证码**
|
|
||||||
|
|
||||||
4. **查看新的日志输出**,应该能看到:
|
|
||||||
```
|
|
||||||
INFO ... VerificationCodeService : 当前邮件模板ID配置: 154360
|
|
||||||
INFO ... VerificationCodeService : 使用生产模式发送邮件,收件人: xxx@qq.com, 模板ID: 154360
|
|
||||||
INFO ... TencentSesMailService : 开始发送邮件,收件人: xxx@qq.com, 主题: 验证码, 模板ID: 154360
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤2:检查配置文件
|
|
||||||
|
|
||||||
确认 `application-dev.properties` 中的配置:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
tencent.ses.template-id=154360
|
|
||||||
```
|
|
||||||
|
|
||||||
**注意:**
|
|
||||||
- 确保没有空格
|
|
||||||
- 确保值是正确的数字
|
|
||||||
- 确保配置文件被正确加载(使用 `--spring.profiles.active=dev`)
|
|
||||||
|
|
||||||
### 步骤3:检查日志输出
|
|
||||||
|
|
||||||
**如果看到:**
|
|
||||||
```
|
|
||||||
INFO 当前邮件模板ID配置: 0
|
|
||||||
WARN 未配置邮件模板ID,使用开发模式
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明:** 配置值没有正确读取,使用的是默认值0。
|
|
||||||
|
|
||||||
**解决方案:**
|
|
||||||
1. 检查配置文件路径
|
|
||||||
2. 确认使用的是dev配置:`--spring.profiles.active=dev`
|
|
||||||
3. 检查配置文件名是否正确
|
|
||||||
|
|
||||||
**如果看到:**
|
|
||||||
```
|
|
||||||
INFO 当前邮件模板ID配置: 154360
|
|
||||||
INFO 使用生产模式发送邮件,收件人: xxx@qq.com, 模板ID: 154360
|
|
||||||
INFO 开始发送邮件,收件人: xxx@qq.com, 主题: 验证码, 模板ID: 154360
|
|
||||||
ERROR 邮件验证码发送失败,邮箱: xxx@qq.com
|
|
||||||
```
|
|
||||||
|
|
||||||
**说明:** 配置正确,但邮件发送失败。
|
|
||||||
|
|
||||||
**常见错误:**
|
|
||||||
|
|
||||||
1. **发信地址未验证**
|
|
||||||
```
|
|
||||||
InvalidParameter.EmailAddressNotVerified
|
|
||||||
```
|
|
||||||
**解决:** 在腾讯云SES控制台验证 `newletter@vionow.com`
|
|
||||||
|
|
||||||
2. **模板ID不存在或未审核**
|
|
||||||
```
|
|
||||||
ResourceNotFound.TemplateNotFound
|
|
||||||
```
|
|
||||||
**解决:** 确认模板ID 154360 已审核通过
|
|
||||||
|
|
||||||
3. **权限不足**
|
|
||||||
```
|
|
||||||
InvalidSecretId.InvalidSignature
|
|
||||||
```
|
|
||||||
**解决:** 检查SecretID/SecretKey是否正确,是否有SES服务权限
|
|
||||||
|
|
||||||
4. **额度不足**
|
|
||||||
```
|
|
||||||
余额不足
|
|
||||||
```
|
|
||||||
**解决:** 充值或检查免费额度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速测试方案
|
|
||||||
|
|
||||||
### 方案1:临时使用开发模式测试
|
|
||||||
|
|
||||||
如果发信地址未验证或需要快速测试登录功能,可以临时切换到开发模式:
|
|
||||||
|
|
||||||
1. **修改配置文件**
|
|
||||||
```properties
|
|
||||||
tencent.ses.template-id=0
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **重新编译并启动**
|
|
||||||
```bash
|
|
||||||
mvn clean package
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **测试发送验证码**
|
|
||||||
- 会看到日志:`开发模式:邮件验证码发送到: xxx@qq.com, 验证码: 123456`
|
|
||||||
- 从日志中获取验证码用于登录测试
|
|
||||||
|
|
||||||
### 方案2:检查SES配置状态
|
|
||||||
|
|
||||||
1. **访问SES控制台**
|
|
||||||
- 发信地址管理:https://console.cloud.tencent.com/ses/address
|
|
||||||
- 邮件模板管理:https://console.cloud.tencent.com/ses/template
|
|
||||||
|
|
||||||
2. **确认以下状态:**
|
|
||||||
- [ ] `newletter@vionow.com` 状态为"已验证"
|
|
||||||
- [ ] 模板ID `154360` 状态为"已审核"
|
|
||||||
- [ ] SES服务有可用额度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 诊断检查清单
|
|
||||||
|
|
||||||
请按照以下顺序检查:
|
|
||||||
|
|
||||||
- [ ] **1. 配置检查**
|
|
||||||
- 配置文件 `application-dev.properties` 中存在 `tencent.ses.template-id=154360`
|
|
||||||
- 没有多余空格或特殊字符
|
|
||||||
|
|
||||||
- [ ] **2. 编译检查**
|
|
||||||
- 执行了 `mvn clean package`
|
|
||||||
- 编译成功,没有错误
|
|
||||||
|
|
||||||
- [ ] **3. 启动检查**
|
|
||||||
- 使用 `--spring.profiles.active=dev` 启动
|
|
||||||
- 启动日志中没有配置相关的错误
|
|
||||||
|
|
||||||
- [ ] **4. 日志检查**
|
|
||||||
- 重新启动后,测试发送验证码
|
|
||||||
- 查看日志中是否有新的详细信息
|
|
||||||
|
|
||||||
- [ ] **5. SES配置检查**
|
|
||||||
- 发信地址已验证
|
|
||||||
- 模板ID已审核
|
|
||||||
- 有可用额度
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 下一步操作
|
|
||||||
|
|
||||||
1. **立即执行:**
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
mvn clean package
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **再次测试发送验证码**
|
|
||||||
|
|
||||||
3. **查看新的日志输出**,告诉我你看到了什么日志信息
|
|
||||||
|
|
||||||
4. **根据新的日志信息,我可以进一步帮你诊断问题**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 重要提示
|
|
||||||
|
|
||||||
**当前代码已更新,添加了更详细的日志输出。请重新编译并启动服务,然后再次测试。新的日志会帮助我们准确定位问题。**
|
|
||||||
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
# 邮箱验证码登录系统说明
|
|
||||||
|
|
||||||
## 📋 系统说明
|
|
||||||
|
|
||||||
系统**已完全禁用用户名密码登录**,现在**仅支持邮箱验证码登录**。
|
|
||||||
|
|
||||||
## 🔐 登录流程
|
|
||||||
|
|
||||||
### 1. 用户登录流程
|
|
||||||
|
|
||||||
```
|
|
||||||
输入邮箱 → 点击"获取验证码" → 接收邮件验证码 → 输入验证码 → 点击"登录/注册" → 进入系统
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 详细步骤
|
|
||||||
|
|
||||||
1. **输入邮箱地址**
|
|
||||||
- 用户在登录页面输入邮箱地址
|
|
||||||
- 系统会验证邮箱格式
|
|
||||||
|
|
||||||
2. **获取验证码**
|
|
||||||
- 点击"获取验证码"按钮
|
|
||||||
- 系统调用腾讯云SES发送验证码邮件
|
|
||||||
- 按钮进入60秒倒计时状态(防重复发送)
|
|
||||||
|
|
||||||
3. **接收验证码**
|
|
||||||
- 用户查收邮箱中的验证码
|
|
||||||
- 验证码为6位数字
|
|
||||||
- 验证码有效期:5分钟
|
|
||||||
|
|
||||||
4. **输入验证码**
|
|
||||||
- 用户输入收到的6位数字验证码
|
|
||||||
- 系统会验证验证码格式
|
|
||||||
|
|
||||||
5. **完成登录**
|
|
||||||
- 点击"登录/注册"按钮
|
|
||||||
- 系统验证验证码是否正确
|
|
||||||
- 验证通过后:
|
|
||||||
- 如果用户存在:直接登录
|
|
||||||
- 如果用户不存在:自动注册新用户并登录
|
|
||||||
- 登录成功后生成JWT Token
|
|
||||||
- 跳转到个人主页
|
|
||||||
|
|
||||||
## ✅ 已实现的功能
|
|
||||||
|
|
||||||
### 后端功能
|
|
||||||
✅ **邮箱验证码登录接口** - `/api/auth/login/email`
|
|
||||||
- 验证邮箱验证码
|
|
||||||
- 自动注册新用户(如不存在)
|
|
||||||
- 生成JWT Token
|
|
||||||
- 返回用户信息
|
|
||||||
|
|
||||||
✅ **用户名密码登录已禁用** - `/api/auth/login`
|
|
||||||
- 返回提示信息:"系统已禁用用户名密码登录,请使用邮箱验证码登录"
|
|
||||||
|
|
||||||
✅ **验证码服务**
|
|
||||||
- 发送验证码邮件:`/api/verification/email/send`
|
|
||||||
- 验证验证码:`/api/verification/email/verify`
|
|
||||||
- 开发模式支持:`/api/verification/email/dev-set`
|
|
||||||
|
|
||||||
### 前端功能
|
|
||||||
✅ **登录页面**
|
|
||||||
- 邮箱输入框
|
|
||||||
- 验证码输入框
|
|
||||||
- 获取验证码按钮(带倒计时)
|
|
||||||
- 登录/注册按钮
|
|
||||||
- 表单验证
|
|
||||||
- 错误提示
|
|
||||||
|
|
||||||
✅ **登录流程**
|
|
||||||
- 发送验证码请求
|
|
||||||
- 验证码格式验证(6位数字)
|
|
||||||
- 调用邮箱验证码登录API
|
|
||||||
- Token存储
|
|
||||||
- 自动跳转
|
|
||||||
|
|
||||||
## 📝 API接口说明
|
|
||||||
|
|
||||||
### 1. 发送验证码
|
|
||||||
```
|
|
||||||
POST /api/verification/email/send
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"email": "user@example.com"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "验证码发送成功"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 邮箱验证码登录
|
|
||||||
```
|
|
||||||
POST /api/auth/login/email
|
|
||||||
Content-Type: application/json
|
|
||||||
|
|
||||||
{
|
|
||||||
"email": "user@example.com",
|
|
||||||
"code": "123456"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "登录成功",
|
|
||||||
"data": {
|
|
||||||
"user": {
|
|
||||||
"id": 1,
|
|
||||||
"username": "user",
|
|
||||||
"email": "user@example.com",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"token": "eyJhbGciOiJIUzI1NiIs..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔒 安全特性
|
|
||||||
|
|
||||||
### 1. 验证码安全
|
|
||||||
- ✅ 验证码有效期:5分钟
|
|
||||||
- ✅ 验证码长度:6位数字
|
|
||||||
- ✅ 发送频率限制:60秒内只能发送一次
|
|
||||||
- ✅ 验证后自动删除,防止重复使用
|
|
||||||
|
|
||||||
### 2. 登录安全
|
|
||||||
- ✅ 必须验证验证码才能登录
|
|
||||||
- ✅ 用户名密码登录已完全禁用
|
|
||||||
- ✅ 使用JWT Token进行身份认证
|
|
||||||
- ✅ 自动注册用户时设置默认权限(ROLE_USER)
|
|
||||||
|
|
||||||
## 🎯 用户体验
|
|
||||||
|
|
||||||
### 优点
|
|
||||||
- ✅ 无需记忆密码
|
|
||||||
- ✅ 登录流程简单
|
|
||||||
- ✅ 自动注册新用户
|
|
||||||
- ✅ 安全可靠
|
|
||||||
|
|
||||||
### 注意事项
|
|
||||||
- ⚠️ 需要邮箱能够正常接收邮件
|
|
||||||
- ⚠️ 验证码有时效性(5分钟)
|
|
||||||
- ⚠️ 发送验证码有频率限制(60秒)
|
|
||||||
|
|
||||||
## 🛠️ 开发模式
|
|
||||||
|
|
||||||
### 开发环境配置
|
|
||||||
当 `tencent.ses.template-id=0` 时,系统进入开发模式:
|
|
||||||
|
|
||||||
- ✅ 不会实际发送邮件
|
|
||||||
- ✅ 验证码显示在日志中
|
|
||||||
- ✅ 可以使用开发接口手动设置验证码
|
|
||||||
|
|
||||||
### 开发模式测试
|
|
||||||
```bash
|
|
||||||
# 1. 发送验证码(开发模式)
|
|
||||||
POST /api/verification/email/send
|
|
||||||
{
|
|
||||||
"email": "test@example.com"
|
|
||||||
}
|
|
||||||
# 查看日志获取验证码
|
|
||||||
|
|
||||||
# 2. 或者直接设置验证码
|
|
||||||
POST /api/verification/email/dev-set
|
|
||||||
{
|
|
||||||
"email": "test@example.com",
|
|
||||||
"code": "123456"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 3. 使用设置的验证码登录
|
|
||||||
POST /api/auth/login/email
|
|
||||||
{
|
|
||||||
"email": "test@example.com",
|
|
||||||
"code": "123456"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 登录流程对比
|
|
||||||
|
|
||||||
### 旧流程(已禁用)
|
|
||||||
```
|
|
||||||
输入用户名 → 输入密码 → 点击登录 → 进入系统
|
|
||||||
```
|
|
||||||
|
|
||||||
### 新流程(当前)
|
|
||||||
```
|
|
||||||
输入邮箱 → 获取验证码 → 接收邮件 → 输入验证码 → 登录/注册 → 进入系统
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚙️ 配置要求
|
|
||||||
|
|
||||||
### 必需配置
|
|
||||||
```properties
|
|
||||||
# 腾讯云SES配置
|
|
||||||
tencent.ses.secret-id=你的SecretID
|
|
||||||
tencent.ses.secret-key=你的SecretKey
|
|
||||||
tencent.ses.from-email=已验证的发信地址
|
|
||||||
tencent.ses.template-id=0 # 0=开发模式,实际ID=生产模式
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 使用示例
|
|
||||||
|
|
||||||
### 前端调用示例
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 1. 发送验证码
|
|
||||||
const response = await fetch('/api/verification/email/send', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ email: 'user@example.com' })
|
|
||||||
})
|
|
||||||
|
|
||||||
// 2. 登录(使用收到的验证码)
|
|
||||||
const loginResponse = await fetch('/api/auth/login/email', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({
|
|
||||||
email: 'user@example.com',
|
|
||||||
code: '123456' // 从邮箱获取的验证码
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const result = await loginResponse.json()
|
|
||||||
if (result.success) {
|
|
||||||
// 保存token和用户信息
|
|
||||||
sessionStorage.setItem('token', result.data.token)
|
|
||||||
sessionStorage.setItem('user', JSON.stringify(result.data.user))
|
|
||||||
// 跳转到主页
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚠️ 重要说明
|
|
||||||
|
|
||||||
1. **用户名密码登录已完全禁用**
|
|
||||||
- 即使调用 `/api/auth/login`,也会返回错误提示
|
|
||||||
- 所有登录必须通过邮箱验证码方式
|
|
||||||
|
|
||||||
2. **自动注册**
|
|
||||||
- 如果邮箱对应的用户不存在,系统会自动创建新用户
|
|
||||||
- 用户名自动从邮箱生成(邮箱@前面的部分)
|
|
||||||
- 默认角色:ROLE_USER(普通用户)
|
|
||||||
- 默认积分:50
|
|
||||||
|
|
||||||
3. **验证码管理**
|
|
||||||
- 验证码存储在内存中(重启服务会清除)
|
|
||||||
- 验证成功后自动删除
|
|
||||||
- 过期后自动清除
|
|
||||||
|
|
||||||
## 🔄 后续优化建议
|
|
||||||
|
|
||||||
如需进一步提升,可以考虑:
|
|
||||||
- 将验证码存储到Redis(支持分布式)
|
|
||||||
- 添加图形验证码防止机器人
|
|
||||||
- 支持手机号验证码登录
|
|
||||||
- 添加登录日志记录
|
|
||||||
|
|
||||||
## ✅ 总结
|
|
||||||
|
|
||||||
系统现在**完全使用邮箱验证码登录**,用户名密码登录已禁用。用户只需:
|
|
||||||
1. 输入邮箱
|
|
||||||
2. 获取验证码
|
|
||||||
3. 输入验证码
|
|
||||||
4. 完成登录/注册
|
|
||||||
|
|
||||||
安全和用户体验都得到了提升!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
# 🎯 Nginx + Ngrok 内网穿透最终配置
|
|
||||||
|
|
||||||
## ✅ 配置完成状态
|
|
||||||
|
|
||||||
所有配置已完成并验证通过,可以直接使用!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 当前配置
|
|
||||||
|
|
||||||
### Ngrok 穿透信息
|
|
||||||
- **穿透地址**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
- **穿透端口**: `80` (Nginx)
|
|
||||||
- **协议**: HTTPS(由 Ngrok 自动提供)
|
|
||||||
|
|
||||||
### 架构流程
|
|
||||||
```
|
|
||||||
外部用户
|
|
||||||
↓
|
|
||||||
https://curtly-aphorismatic-ginger.ngrok-free.dev (Ngrok HTTPS)
|
|
||||||
↓
|
|
||||||
localhost:80 (Nginx - 唯一需要穿透的端口)
|
|
||||||
├─ GET / → 前端静态文件
|
|
||||||
├─ GET /api/* → proxy_pass → backend:8080 (内部 Docker 网络)
|
|
||||||
└─ GET /health → Nginx 健康检查
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 已完成的配置更新
|
|
||||||
|
|
||||||
### 1. Nginx 配置 ✅
|
|
||||||
**文件**: `nginx/nginx.conf`
|
|
||||||
- ✅ 添加 `server_name` 支持 ngrok 域名
|
|
||||||
- ✅ API 代理配置:`/api/` → `backend:8080`
|
|
||||||
- ✅ CORS 配置优化,支持动态来源
|
|
||||||
- ✅ 前端静态文件服务
|
|
||||||
|
|
||||||
### 2. 前端 API 自动适配 ✅
|
|
||||||
**文件**:
|
|
||||||
- `frontend/src/utils/apiHelper.js` - 统一的 API 工具函数
|
|
||||||
- `frontend/src/api/request.js` - 使用工具函数
|
|
||||||
- `frontend/src/api/cleanup.js` - 使用工具函数
|
|
||||||
- `frontend/src/views/Login.vue` - 使用工具函数
|
|
||||||
|
|
||||||
**功能**:
|
|
||||||
- ✅ 自动检测当前访问域名
|
|
||||||
- ✅ 通过 ngrok 访问:使用相对路径 `/api`(自动适配)
|
|
||||||
- ✅ 本地开发:使用 `http://localhost:8080/api`
|
|
||||||
|
|
||||||
### 3. 支付宝回调配置 ✅
|
|
||||||
**文件**: `src/main/resources/application-dev.properties`
|
|
||||||
- ✅ `alipay.notify-url`: `https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify`
|
|
||||||
- ✅ `alipay.return-url`: `https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return`
|
|
||||||
|
|
||||||
### 4. 后端 CORS 配置 ✅
|
|
||||||
**文件**: `src/main/java/com/example/demo/config/SecurityConfig.java`
|
|
||||||
- ✅ 支持 `*.ngrok-free.app` 域名模式
|
|
||||||
- ✅ 支持所有 ngrok 子域名
|
|
||||||
|
|
||||||
### 5. Docker Compose 配置 ✅
|
|
||||||
**文件**: `docker-compose.yml`
|
|
||||||
- ✅ 服务编排:MySQL、Backend、Nginx
|
|
||||||
- ✅ 网络配置:`app-network`
|
|
||||||
- ✅ 端口映射:仅 Nginx 暴露 80 端口(后端和 MySQL 不对外暴露)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 部署步骤
|
|
||||||
|
|
||||||
### 步骤 1: 构建前端
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
**重要**: 确保 `frontend/dist` 目录存在。
|
|
||||||
|
|
||||||
### 步骤 2: 启动 Docker 服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 启动所有服务
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# 查看服务状态
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
docker-compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤 3: 启动 Ngrok(穿透 80 端口)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 重要:必须穿透 80 端口(Nginx),不是 8080(后端)
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
**输出示例**:
|
|
||||||
```
|
|
||||||
Forwarding https://curtly-aphorismatic-ginger.ngrok-free.dev -> http://localhost:80
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤 4: 访问应用
|
|
||||||
|
|
||||||
在浏览器中打开:
|
|
||||||
- 🌐 **前端**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
- 🔗 **API**: `https://curtly-aphorismatic-ginger.ngrok-free.dev/api`
|
|
||||||
- 🏥 **健康检查**: `https://curtly-aphorismatic-ginger.ngrok-free.dev/health`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 验证测试
|
|
||||||
|
|
||||||
### 1. 测试前端访问
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 测试 API 代理
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/api/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 测试健康检查
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 测试登录 API
|
|
||||||
```bash
|
|
||||||
curl -X POST https://curtly-aphorismatic-ginger.ngrok-free.dev/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 配置清单
|
|
||||||
|
|
||||||
| 配置项 | 文件位置 | 状态 | 说明 |
|
|
||||||
|--------|----------|------|------|
|
|
||||||
| Nginx server_name | `nginx/nginx.conf` | ✅ | 已添加 ngrok 域名 |
|
|
||||||
| Nginx 端口 | `docker-compose.yml` | ✅ | 80 端口(唯一对外暴露) |
|
|
||||||
| 前端 API 基础路径 | `frontend/src/api/request.js` | ✅ | 自动适配域名 |
|
|
||||||
| API 工具函数 | `frontend/src/utils/apiHelper.js` | ✅ | 统一处理 API URL |
|
|
||||||
| 支付宝通知地址 | `application-dev.properties` | ✅ | 已配置 ngrok URL |
|
|
||||||
| 支付宝返回地址 | `application-dev.properties` | ✅ | 已配置 ngrok URL |
|
|
||||||
| 后端 CORS | `SecurityConfig.java` | ✅ | 支持 ngrok 域名模式 |
|
|
||||||
| Docker 网络 | `docker-compose.yml` | ✅ | app-network bridge |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 重要提醒
|
|
||||||
|
|
||||||
### 1. 端口穿透
|
|
||||||
- ✅ **只穿透 80 端口**(Nginx)
|
|
||||||
- ❌ **不要穿透 8080 端口**(后端,通过 Nginx 内部访问)
|
|
||||||
- ❌ **不要穿透 3306 端口**(MySQL,仅在 Docker 网络内访问)
|
|
||||||
|
|
||||||
### 2. Ngrok 地址变化
|
|
||||||
如果 ngrok 地址变化,需要更新:
|
|
||||||
1. `nginx/nginx.conf` - `server_name` 行
|
|
||||||
2. `application-dev.properties` - `alipay.notify-url` 和 `alipay.return-url`
|
|
||||||
|
|
||||||
### 3. 前端构建
|
|
||||||
每次修改前端代码后,需要重新构建:
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Nginx 配置重载
|
|
||||||
修改 Nginx 配置后:
|
|
||||||
```bash
|
|
||||||
# 测试配置
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
|
|
||||||
# 重载配置(不中断服务)
|
|
||||||
docker exec demo-nginx nginx -s reload
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 故障排查
|
|
||||||
|
|
||||||
### 502 Bad Gateway
|
|
||||||
```bash
|
|
||||||
# 检查后端服务
|
|
||||||
docker-compose logs backend
|
|
||||||
docker-compose restart backend
|
|
||||||
```
|
|
||||||
|
|
||||||
### 404 Not Found
|
|
||||||
```bash
|
|
||||||
# 检查前端构建产物
|
|
||||||
ls frontend/dist
|
|
||||||
|
|
||||||
# 检查 Nginx 配置
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
```
|
|
||||||
|
|
||||||
### CORS 错误
|
|
||||||
- 检查后端 CORS 配置是否包含 ngrok 域名
|
|
||||||
- 检查 Nginx CORS 头设置
|
|
||||||
- 确认请求使用正确的域名
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
- [Nginx 反向代理配置指南](./NGINX_REVERSE_PROXY_GUIDE.md)
|
|
||||||
- [Ngrok 内网穿透配置](./NGINX_INTRANET_TUNNEL.md)
|
|
||||||
- [Ngrok 部署指南](./NGROK_DEPLOYMENT_GUIDE.md)
|
|
||||||
- [配置验证报告](./CONFIG_VALIDATION_REPORT.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 最终状态
|
|
||||||
|
|
||||||
**所有配置已完成并验证通过!**
|
|
||||||
|
|
||||||
可以开始部署:
|
|
||||||
1. ✅ 构建前端
|
|
||||||
2. ✅ 启动 Docker 服务
|
|
||||||
3. ✅ 启动 Ngrok(穿透 80 端口)
|
|
||||||
4. ✅ 访问应用
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**配置完成时间**: 2025-11-03
|
|
||||||
**Ngrok 地址**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
**穿透端口**: `80` (Nginx)
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
# FRP 快速开始指南
|
|
||||||
|
|
||||||
## 最简单的配置方法(使用 OpenFrp)
|
|
||||||
|
|
||||||
### 1. 注册并创建隧道
|
|
||||||
|
|
||||||
1. 访问:https://www.openfrp.net/
|
|
||||||
2. 注册账号并登录
|
|
||||||
3. 点击"创建隧道"
|
|
||||||
4. 配置:
|
|
||||||
- 节点:选择国内节点
|
|
||||||
- 类型:HTTP
|
|
||||||
- 本地端口:8080
|
|
||||||
- 域名:使用系统分配的或自定义
|
|
||||||
5. 创建成功后,记录:
|
|
||||||
- 访问地址(如:`https://xxx.openfrp.net`)
|
|
||||||
- 服务器地址
|
|
||||||
- Token
|
|
||||||
|
|
||||||
### 2. 下载 FRP 客户端
|
|
||||||
|
|
||||||
1. 访问:https://github.com/fatedier/frp/releases
|
|
||||||
2. 下载最新版本的 Windows 版本(如:`frp_0.52.3_windows_amd64.zip`)
|
|
||||||
3. 解压到 `demo` 目录
|
|
||||||
|
|
||||||
### 3. 配置 FRP 客户端
|
|
||||||
|
|
||||||
1. 在 `demo` 目录下创建 `frpc.ini` 文件
|
|
||||||
2. 复制 `frpc.ini.example` 的内容
|
|
||||||
3. 修改配置:
|
|
||||||
```ini
|
|
||||||
[common]
|
|
||||||
server_addr = 从OpenFrp控制台获取
|
|
||||||
server_port = 7000
|
|
||||||
token = 从OpenFrp控制台获取
|
|
||||||
|
|
||||||
[payment]
|
|
||||||
type = http
|
|
||||||
local_ip = 127.0.0.1
|
|
||||||
local_port = 8080
|
|
||||||
custom_domains = 你的域名.openfrp.net
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 启动 FRP
|
|
||||||
|
|
||||||
双击运行 `start-frpc.bat`,或手动运行:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
cd demo
|
|
||||||
.\frpc.exe -c frpc.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 更新配置文件
|
|
||||||
|
|
||||||
更新以下文件中的回调URL:
|
|
||||||
|
|
||||||
**`demo/src/main/resources/application-dev.properties`:**
|
|
||||||
```properties
|
|
||||||
alipay.notify-url=https://你的域名.openfrp.net/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://你的域名.openfrp.net/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
**`demo/src/main/resources/payment.properties`:**
|
|
||||||
```properties
|
|
||||||
alipay.domain=https://你的域名.openfrp.net
|
|
||||||
alipay.notify-url=https://你的域名.openfrp.net/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://你的域名.openfrp.net/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. 重启服务器
|
|
||||||
|
|
||||||
重启 Spring Boot 应用,新的回调地址就会生效。
|
|
||||||
|
|
||||||
### 7. 测试
|
|
||||||
|
|
||||||
1. 访问 `https://你的域名.openfrp.net` - 应该能看到应用
|
|
||||||
2. 测试回调接口:
|
|
||||||
```powershell
|
|
||||||
Invoke-WebRequest -Uri "https://你的域名.openfrp.net/api/payments/alipay/notify" -Method HEAD
|
|
||||||
```
|
|
||||||
应该返回 200,而不是 302
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
- FRP 客户端需要一直运行,关闭后内网穿透会断开
|
|
||||||
- 免费服务可能有流量限制,建议用于开发测试
|
|
||||||
- 生产环境建议使用固定域名和服务器
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
# 📤 Git 上传到云端指南
|
|
||||||
|
|
||||||
## 一、准备工作
|
|
||||||
|
|
||||||
### 1.1 检查敏感信息
|
|
||||||
|
|
||||||
已更新 `.gitignore` 文件,以下文件不会被提交:
|
|
||||||
- `application-dev.properties` - 开发环境配置(包含数据库密码、API密钥等)
|
|
||||||
- `application-prod.properties` - 生产环境配置
|
|
||||||
- `.env` - 环境变量文件
|
|
||||||
- `uploads/` - 上传文件目录
|
|
||||||
- `temp/` - 临时文件目录
|
|
||||||
- `logs/` - 日志文件
|
|
||||||
- `target/` - 构建产物
|
|
||||||
- `frontend/node_modules/` - 前端依赖
|
|
||||||
|
|
||||||
### 1.2 创建配置文件模板
|
|
||||||
|
|
||||||
如果需要保留配置结构,可以创建模板文件:
|
|
||||||
- `application-dev.properties.example`
|
|
||||||
- `application-prod.properties.example`
|
|
||||||
- `.env.example`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 二、上传步骤
|
|
||||||
|
|
||||||
### 2.1 添加所有更改
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 进入项目目录
|
|
||||||
cd C:\Users\UI\Desktop\AIGC\demo
|
|
||||||
|
|
||||||
# 添加所有更改的文件
|
|
||||||
git add .
|
|
||||||
|
|
||||||
# 或者只添加特定文件
|
|
||||||
git add src/
|
|
||||||
git add frontend/
|
|
||||||
git add pom.xml
|
|
||||||
git add .gitignore
|
|
||||||
git add DEPLOYMENT_CHECKLIST.md
|
|
||||||
git add QUICK_DEPLOY.md
|
|
||||||
git add CONFIGURATION_GUIDE.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 提交更改
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 提交更改
|
|
||||||
git commit -m "feat: 优化系统配置,支持50人并发
|
|
||||||
|
|
||||||
- 调整数据库连接池配置(30个连接)
|
|
||||||
- 调整Tomcat线程池配置(150个线程)
|
|
||||||
- 调整异步任务执行器配置(5核心线程,20最大线程)
|
|
||||||
- 调整任务队列消费者线程数(5个线程)
|
|
||||||
- 添加无界阻塞队列支持
|
|
||||||
- 实现分镜视频保存功能
|
|
||||||
- 统一管理页面导航栏和右上角样式
|
|
||||||
- 添加日活用户统计功能
|
|
||||||
- 添加部署文档和快速部署指南"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 推送到远程仓库
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 推送到远程仓库
|
|
||||||
git push origin main
|
|
||||||
|
|
||||||
# 或者如果主分支是 master
|
|
||||||
git push origin master
|
|
||||||
|
|
||||||
# 如果是第一次推送,需要设置上游分支
|
|
||||||
git push -u origin main
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、常见问题
|
|
||||||
|
|
||||||
### 3.1 如果远程仓库已有新提交
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 先拉取远程更改
|
|
||||||
git pull origin main
|
|
||||||
|
|
||||||
# 如果有冲突,解决冲突后
|
|
||||||
git add .
|
|
||||||
git commit -m "解决合并冲突"
|
|
||||||
git push origin main
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 如果文件太大无法推送
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查大文件
|
|
||||||
git ls-files | xargs du -h | sort -rh | head -20
|
|
||||||
|
|
||||||
# 如果确实需要大文件,考虑使用 Git LFS
|
|
||||||
git lfs install
|
|
||||||
git lfs track "*.jar"
|
|
||||||
git lfs track "*.zip"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 如果推送被拒绝
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 强制推送(谨慎使用)
|
|
||||||
git push -f origin main
|
|
||||||
|
|
||||||
# 或者先拉取再推送
|
|
||||||
git pull --rebase origin main
|
|
||||||
git push origin main
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 四、验证上传
|
|
||||||
|
|
||||||
### 4.1 检查远程仓库
|
|
||||||
|
|
||||||
访问远程仓库地址,确认文件已上传:
|
|
||||||
- `ssh://git@49.234.3.145:222/blandarebiter/AIGC.git`
|
|
||||||
|
|
||||||
### 4.2 克隆验证
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在另一个目录克隆仓库验证
|
|
||||||
cd /tmp
|
|
||||||
git clone ssh://git@49.234.3.145:222/blandarebiter/AIGC.git test-clone
|
|
||||||
cd test-clone
|
|
||||||
ls -la
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 五、后续维护
|
|
||||||
|
|
||||||
### 5.1 定期提交
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 每天工作结束后提交
|
|
||||||
git add .
|
|
||||||
git commit -m "更新: 描述本次更改"
|
|
||||||
git push origin main
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 创建标签(版本发布)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建版本标签
|
|
||||||
git tag -a v1.0.0 -m "版本 1.0.0 - 初始发布"
|
|
||||||
git push origin v1.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 创建分支(功能开发)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建功能分支
|
|
||||||
git checkout -b feature/new-feature
|
|
||||||
# 开发完成后合并
|
|
||||||
git checkout main
|
|
||||||
git merge feature/new-feature
|
|
||||||
git push origin main
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 重要提醒
|
|
||||||
|
|
||||||
1. **不要提交敏感信息**
|
|
||||||
- 数据库密码
|
|
||||||
- API密钥
|
|
||||||
- JWT密钥
|
|
||||||
- 支付宝私钥
|
|
||||||
- 腾讯云密钥
|
|
||||||
|
|
||||||
2. **提交前检查**
|
|
||||||
```bash
|
|
||||||
git status
|
|
||||||
git diff
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **使用有意义的提交信息**
|
|
||||||
- 清晰描述本次更改
|
|
||||||
- 遵循提交信息规范
|
|
||||||
|
|
||||||
4. **定期备份**
|
|
||||||
- 本地备份重要文件
|
|
||||||
- 定期推送到远程仓库
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 快速命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 一键提交并推送
|
|
||||||
git add . && git commit -m "更新代码" && git push origin main
|
|
||||||
|
|
||||||
# 查看提交历史
|
|
||||||
git log --oneline -10
|
|
||||||
|
|
||||||
# 查看远程仓库
|
|
||||||
git remote -v
|
|
||||||
|
|
||||||
# 查看当前分支
|
|
||||||
git branch
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
# IJPay 使用指南
|
|
||||||
|
|
||||||
## 一、IJPay 简介
|
|
||||||
|
|
||||||
IJPay 是一个简洁易用的 Java 聚合支付 SDK,支持微信支付、支付宝支付、银联支付等多种支付方式。
|
|
||||||
|
|
||||||
项目已集成 IJPay-AliPay 模块,用于支付宝支付功能。
|
|
||||||
|
|
||||||
## 二、项目中的 IJPay 使用方式
|
|
||||||
|
|
||||||
### 1. 依赖配置
|
|
||||||
|
|
||||||
在 `pom.xml` 中已添加 IJPay 依赖:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.javen205</groupId>
|
|
||||||
<artifactId>IJPay-AliPay</artifactId>
|
|
||||||
<version>2.9.12.1</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 代码使用方式
|
|
||||||
|
|
||||||
项目中主要通过 `AlipayController.java` 使用 IJPay 的 `AliPayApi` 类进行支付操作。
|
|
||||||
|
|
||||||
#### 2.1 扫码支付(QR码支付)
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/qr-pay")
|
|
||||||
public ResponseEntity<Map<String, Object>> qrPay(...) {
|
|
||||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
model.setTotalAmount(totalAmount);
|
|
||||||
model.setSubject(subject);
|
|
||||||
model.setBody(body);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 调用预创建接口
|
|
||||||
String qrCode = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl).getBody();
|
|
||||||
// 返回二维码字符串
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.2 PC网页支付
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/pc-pay")
|
|
||||||
public void pcPay(...) {
|
|
||||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
model.setProductCode("FAST_INSTANT_TRADE_PAY");
|
|
||||||
model.setTotalAmount(totalAmount);
|
|
||||||
model.setSubject(subject);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 进行页面跳转
|
|
||||||
AliPayApi.tradePage(response, model, notifyUrl, returnUrl);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.3 手机网页支付
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/wap-pay")
|
|
||||||
public void wapPay(...) {
|
|
||||||
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
model.setProductCode("QUICK_WAP_PAY");
|
|
||||||
model.setTotalAmount(totalAmount);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 进行手机支付
|
|
||||||
AliPayApi.wapPay(response, model, returnUrl, notifyUrl);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.4 APP支付
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/app-pay")
|
|
||||||
public ResponseEntity<Map<String, Object>> appPay(...) {
|
|
||||||
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
model.setProductCode("QUICK_MSECURITY_PAY");
|
|
||||||
model.setTotalAmount(totalAmount);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 获取 APP 支付订单信息
|
|
||||||
String orderInfo = AliPayApi.appPayToResponse(model, notifyUrl).getBody();
|
|
||||||
// 返回订单信息给 APP
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.5 订单查询
|
|
||||||
|
|
||||||
```java
|
|
||||||
@GetMapping("/query")
|
|
||||||
public ResponseEntity<Map<String, Object>> queryOrder(...) {
|
|
||||||
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 查询订单
|
|
||||||
String result = AliPayApi.tradeQueryToResponse(model).getBody();
|
|
||||||
// 返回查询结果
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.6 退款
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/refund")
|
|
||||||
public ResponseEntity<Map<String, Object>> refund(...) {
|
|
||||||
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
|
|
||||||
model.setOutTradeNo(outTradeNo);
|
|
||||||
model.setRefundAmount(refundAmount);
|
|
||||||
model.setRefundReason(refundReason);
|
|
||||||
|
|
||||||
// 使用 IJPay 的 AliPayApi 发起退款
|
|
||||||
String result = AliPayApi.tradeRefundToResponse(model).getBody();
|
|
||||||
// 返回退款结果
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.7 异步通知处理
|
|
||||||
|
|
||||||
```java
|
|
||||||
@PostMapping("/notify")
|
|
||||||
public String notifyUrl(HttpServletRequest request) {
|
|
||||||
// 使用 IJPay 的 AliPayApi 将请求参数转换为 Map
|
|
||||||
Map<String, String> params = AliPayApi.toMap(request);
|
|
||||||
|
|
||||||
// 验证签名
|
|
||||||
boolean verifyResult = AlipaySignature.rsaCertCheckV1(
|
|
||||||
params, aliPayConfig.getAliPayCertPath(), "UTF-8", "RSA2");
|
|
||||||
|
|
||||||
if (verifyResult) {
|
|
||||||
// 处理支付成功逻辑
|
|
||||||
return "success";
|
|
||||||
} else {
|
|
||||||
return "failure";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 三、IJPay 配置说明
|
|
||||||
|
|
||||||
### 3.1 配置方式
|
|
||||||
|
|
||||||
IJPay 的 `AliPayApi` 类内部会自动读取系统属性或配置文件中的支付宝配置。
|
|
||||||
|
|
||||||
需要配置的参数包括:
|
|
||||||
- `appId`: 支付宝应用ID
|
|
||||||
- `privateKey`: 应用私钥
|
|
||||||
- `publicKey`: 支付宝公钥
|
|
||||||
- `gatewayUrl`: 支付宝网关地址
|
|
||||||
- `charset`: 字符编码(通常为 UTF-8)
|
|
||||||
- `signType`: 签名类型(通常为 RSA2)
|
|
||||||
|
|
||||||
### 3.2 配置文件
|
|
||||||
|
|
||||||
配置在 `application-dev.properties` 或 `application-prod.properties` 中:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 支付宝配置
|
|
||||||
alipay.app-id=你的APPID
|
|
||||||
alipay.private-key=你的应用私钥
|
|
||||||
alipay.public-key=支付宝公钥
|
|
||||||
alipay.gateway-url=https://openapi.alipaydev.com/gateway.do
|
|
||||||
alipay.charset=UTF-8
|
|
||||||
alipay.sign-type=RSA2
|
|
||||||
alipay.notify-url=回调通知地址
|
|
||||||
alipay.return-url=同步返回地址
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 IJPay 初始化(可选)
|
|
||||||
|
|
||||||
如果需要显式初始化 IJPay,可以在应用启动时配置:
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Configuration
|
|
||||||
public class IJPayConfig {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AliPayConfig aliPayConfig;
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() {
|
|
||||||
// IJPay 的 AliPayApi 会自动读取配置
|
|
||||||
// 如果需要显式配置,可以使用 AliPayApiConfigKit
|
|
||||||
// 注意:具体初始化方式取决于 IJPay 版本
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 四、IJPay vs 原生 Alipay SDK
|
|
||||||
|
|
||||||
项目中同时使用了两种方式:
|
|
||||||
|
|
||||||
1. **IJPay (AliPayApi)** - 在 `AlipayController.java` 中使用
|
|
||||||
- 优点:封装更简洁,使用更方便
|
|
||||||
- 缺点:需要额外依赖 IJPay 库
|
|
||||||
|
|
||||||
2. **原生 Alipay SDK (DefaultAlipayClient)** - 在 `AlipayService.java` 中使用
|
|
||||||
- 优点:官方 SDK,功能完整
|
|
||||||
- 缺点:需要手动创建客户端和处理响应
|
|
||||||
|
|
||||||
## 五、常见问题
|
|
||||||
|
|
||||||
### Q1: IJPay 如何初始化?
|
|
||||||
|
|
||||||
A: IJPay 的 `AliPayApi` 类内部会自动读取配置,通常不需要显式初始化。如果遇到配置问题,可以检查:
|
|
||||||
1. 配置文件中的参数是否正确
|
|
||||||
2. 系统属性是否设置
|
|
||||||
3. 环境变量是否配置
|
|
||||||
|
|
||||||
### Q2: 如何切换到 IJPay?
|
|
||||||
|
|
||||||
A: 如果当前使用原生 Alipay SDK,可以:
|
|
||||||
1. 修改 `AlipayService.java`,使用 `AliPayApi` 替代 `DefaultAlipayClient`
|
|
||||||
2. 或者直接使用 `AlipayController` 中的接口
|
|
||||||
|
|
||||||
### Q3: IJPay 和原生 SDK 的区别?
|
|
||||||
|
|
||||||
A: IJPay 是对原生 SDK 的封装,提供了更简洁的 API。底层实现仍然使用支付宝官方 SDK。
|
|
||||||
|
|
||||||
## 六、参考文档
|
|
||||||
|
|
||||||
- IJPay 官方文档:https://github.com/Javen205/IJPay
|
|
||||||
- IJPay 示例项目:https://github.com/Javen205/IJPay-Demo
|
|
||||||
- 支付宝开放平台:https://open.alipay.com
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
# 图生视频API配置说明
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
图生视频API允许用户上传图片并生成视频内容。系统支持首帧图片(必填)和尾帧图片(可选),结合用户描述文字生成动态视频。
|
|
||||||
|
|
||||||
## 功能特性
|
|
||||||
|
|
||||||
- ✅ 图片上传(支持JPG、PNG、WEBP格式)
|
|
||||||
- ✅ 多种视频比例(16:9、4:3、1:1、3:4、9:16)
|
|
||||||
- ✅ 可调节视频时长(5s、10s、15s、30s)
|
|
||||||
- ✅ 高清模式(1080P,额外消耗积分)
|
|
||||||
- ✅ 实时任务状态监控
|
|
||||||
- ✅ 进度条显示
|
|
||||||
- ✅ 任务取消功能
|
|
||||||
- ✅ 积分消耗计算
|
|
||||||
|
|
||||||
## API接口
|
|
||||||
|
|
||||||
### 1. 创建图生视频任务
|
|
||||||
|
|
||||||
**POST** `/api/image-to-video/create`
|
|
||||||
|
|
||||||
**请求参数:**
|
|
||||||
- `firstFrame` (File, 必填): 首帧图片
|
|
||||||
- `lastFrame` (File, 可选): 尾帧图片
|
|
||||||
- `prompt` (String, 必填): 描述文字
|
|
||||||
- `aspectRatio` (String, 可选): 视频比例,默认"16:9"
|
|
||||||
- `duration` (Integer, 可选): 视频时长(秒),默认5
|
|
||||||
- `hdMode` (Boolean, 可选): 是否高清模式,默认false
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "任务创建成功",
|
|
||||||
"data": {
|
|
||||||
"id": 1,
|
|
||||||
"taskId": "img2vid_abc123def456",
|
|
||||||
"username": "test_user",
|
|
||||||
"firstFrameUrl": "/uploads/img2vid_abc123def456/first_frame_1234567890.jpg",
|
|
||||||
"prompt": "测试图生视频",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false,
|
|
||||||
"status": "PENDING",
|
|
||||||
"progress": 0,
|
|
||||||
"costPoints": 20,
|
|
||||||
"createdAt": "2025-01-24T10:30:00"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 获取用户任务列表
|
|
||||||
|
|
||||||
**GET** `/api/image-to-video/tasks`
|
|
||||||
|
|
||||||
**查询参数:**
|
|
||||||
- `page` (Integer, 可选): 页码,默认0
|
|
||||||
- `size` (Integer, 可选): 每页数量,默认10
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"taskId": "img2vid_abc123def456",
|
|
||||||
"status": "COMPLETED",
|
|
||||||
"progress": 100,
|
|
||||||
"resultUrl": "/outputs/img2vid_abc123def456/video_1234567890.mp4",
|
|
||||||
"createdAt": "2025-01-24T10:30:00"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total": 1,
|
|
||||||
"page": 0,
|
|
||||||
"size": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 获取任务详情
|
|
||||||
|
|
||||||
**GET** `/api/image-to-video/tasks/{taskId}`
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"taskId": "img2vid_abc123def456",
|
|
||||||
"username": "test_user",
|
|
||||||
"firstFrameUrl": "/uploads/img2vid_abc123def456/first_frame_1234567890.jpg",
|
|
||||||
"prompt": "测试图生视频",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false,
|
|
||||||
"status": "COMPLETED",
|
|
||||||
"progress": 100,
|
|
||||||
"resultUrl": "/outputs/img2vid_abc123def456/video_1234567890.mp4",
|
|
||||||
"costPoints": 20,
|
|
||||||
"createdAt": "2025-01-24T10:30:00",
|
|
||||||
"completedAt": "2025-01-24T10:35:00"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 获取任务状态
|
|
||||||
|
|
||||||
**GET** `/api/image-to-video/tasks/{taskId}/status`
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"id": "img2vid_abc123def456",
|
|
||||||
"status": "PROCESSING",
|
|
||||||
"progress": 45,
|
|
||||||
"resultUrl": null,
|
|
||||||
"errorMessage": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 取消任务
|
|
||||||
|
|
||||||
**POST** `/api/image-to-video/tasks/{taskId}/cancel`
|
|
||||||
|
|
||||||
**响应示例:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "任务已取消"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 任务状态说明
|
|
||||||
|
|
||||||
| 状态 | 描述 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| PENDING | 等待中 | 任务已创建,等待处理 |
|
|
||||||
| PROCESSING | 处理中 | 正在生成视频 |
|
|
||||||
| COMPLETED | 已完成 | 视频生成成功 |
|
|
||||||
| FAILED | 失败 | 生成过程中出现错误 |
|
|
||||||
| CANCELLED | 已取消 | 用户主动取消任务 |
|
|
||||||
|
|
||||||
## 积分消耗计算
|
|
||||||
|
|
||||||
- **基础消耗**: 10积分
|
|
||||||
- **时长消耗**: 时长(秒) × 2积分
|
|
||||||
- **高清模式**: 额外20积分
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
- 5秒普通视频:10 + 5×2 = 20积分
|
|
||||||
- 10秒高清视频:10 + 10×2 + 20 = 50积分
|
|
||||||
|
|
||||||
## 前端集成示例
|
|
||||||
|
|
||||||
### 1. 创建任务
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import { imageToVideoApi } from '@/api/imageToVideo'
|
|
||||||
|
|
||||||
const createTask = async () => {
|
|
||||||
const params = {
|
|
||||||
firstFrame: firstFrameFile.value,
|
|
||||||
lastFrame: lastFrameFile.value, // 可选
|
|
||||||
prompt: inputText.value.trim(),
|
|
||||||
aspectRatio: aspectRatio.value,
|
|
||||||
duration: parseInt(duration.value),
|
|
||||||
hdMode: hdMode.value
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await imageToVideoApi.createTask(params)
|
|
||||||
if (response.data.success) {
|
|
||||||
console.log('任务创建成功:', response.data.data)
|
|
||||||
// 开始轮询任务状态
|
|
||||||
startPollingTask(response.data.data.taskId)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('创建任务失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 轮询任务状态
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const startPollingTask = (taskId) => {
|
|
||||||
const stopPolling = imageToVideoApi.pollTaskStatus(
|
|
||||||
taskId,
|
|
||||||
// 进度回调
|
|
||||||
(progressData) => {
|
|
||||||
console.log('任务进度:', progressData.progress + '%')
|
|
||||||
updateProgressBar(progressData.progress)
|
|
||||||
},
|
|
||||||
// 完成回调
|
|
||||||
(taskData) => {
|
|
||||||
console.log('任务完成:', taskData.resultUrl)
|
|
||||||
showResult(taskData.resultUrl)
|
|
||||||
},
|
|
||||||
// 错误回调
|
|
||||||
(error) => {
|
|
||||||
console.error('任务失败:', error.message)
|
|
||||||
showError(error.message)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// 可以调用 stopPolling() 来停止轮询
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 文件上传限制
|
|
||||||
|
|
||||||
- **文件大小**: 最大10MB
|
|
||||||
- **支持格式**: JPG、PNG、WEBP
|
|
||||||
- **存储路径**: `/uploads/{taskId}/`
|
|
||||||
- **输出路径**: `/outputs/{taskId}/`
|
|
||||||
|
|
||||||
## 数据库表结构
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE image_to_video_tasks (
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
task_id VARCHAR(50) NOT NULL UNIQUE,
|
|
||||||
username VARCHAR(100) NOT NULL,
|
|
||||||
first_frame_url VARCHAR(500) NOT NULL,
|
|
||||||
last_frame_url VARCHAR(500),
|
|
||||||
prompt TEXT,
|
|
||||||
aspect_ratio VARCHAR(10) NOT NULL DEFAULT '16:9',
|
|
||||||
duration INT NOT NULL DEFAULT 5,
|
|
||||||
hd_mode BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
|
||||||
progress INT DEFAULT 0,
|
|
||||||
result_url VARCHAR(500),
|
|
||||||
error_message TEXT,
|
|
||||||
cost_points INT DEFAULT 0,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
completed_at TIMESTAMP NULL
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
## 部署注意事项
|
|
||||||
|
|
||||||
1. **文件存储**: 确保 `uploads` 和 `outputs` 目录有写入权限
|
|
||||||
2. **异步处理**: 已启用 `@EnableAsync` 支持异步任务处理
|
|
||||||
3. **安全配置**: 图生视频API需要用户认证
|
|
||||||
4. **CORS配置**: 已配置支持前端跨域访问
|
|
||||||
5. **文件大小**: 已设置最大上传文件大小为10MB
|
|
||||||
|
|
||||||
## 测试方法
|
|
||||||
|
|
||||||
1. 启动后端服务
|
|
||||||
2. 运行测试脚本:`./test-image-to-video-api.sh`
|
|
||||||
3. 或使用前端页面进行测试
|
|
||||||
|
|
||||||
## 故障排除
|
|
||||||
|
|
||||||
### 常见问题
|
|
||||||
|
|
||||||
1. **文件上传失败**
|
|
||||||
- 检查文件大小是否超过10MB
|
|
||||||
- 确认文件格式是否支持
|
|
||||||
- 检查服务器存储权限
|
|
||||||
|
|
||||||
2. **任务状态不更新**
|
|
||||||
- 检查异步处理是否正常
|
|
||||||
- 查看服务器日志
|
|
||||||
- 确认数据库连接正常
|
|
||||||
|
|
||||||
3. **前端轮询失败**
|
|
||||||
- 检查网络连接
|
|
||||||
- 确认API接口地址正确
|
|
||||||
- 查看浏览器控制台错误
|
|
||||||
|
|
||||||
### 日志查看
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看应用日志
|
|
||||||
tail -f logs/application.log
|
|
||||||
|
|
||||||
# 查看特定任务日志
|
|
||||||
grep "img2vid_abc123def456" logs/application.log
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,846 +0,0 @@
|
|||||||
# 🐧 Linux 云端部署完整指南
|
|
||||||
|
|
||||||
本文档提供将项目打包并部署到Linux云服务器的完整步骤。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 一、本地打包(Windows/Mac)
|
|
||||||
|
|
||||||
### 1.1 打包后端JAR文件
|
|
||||||
|
|
||||||
在项目根目录(`demo/`)执行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Windows (PowerShell)
|
|
||||||
.\mvnw.cmd clean package -DskipTests
|
|
||||||
|
|
||||||
# Linux/Mac
|
|
||||||
./mvnw clean package -DskipTests
|
|
||||||
```
|
|
||||||
|
|
||||||
打包成功后,JAR文件位置:
|
|
||||||
```
|
|
||||||
demo/target/demo-0.0.1-SNAPSHOT.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 打包前端
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 进入前端目录
|
|
||||||
cd frontend
|
|
||||||
|
|
||||||
# 安装依赖(首次需要)
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 构建生产版本
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
构建成功后,前端文件位置:
|
|
||||||
```
|
|
||||||
demo/frontend/dist/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.3 准备部署文件
|
|
||||||
|
|
||||||
创建部署包目录结构:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在项目根目录创建部署包
|
|
||||||
mkdir -p deploy-package
|
|
||||||
mkdir -p deploy-package/backend
|
|
||||||
mkdir -p deploy-package/frontend
|
|
||||||
mkdir -p deploy-package/scripts
|
|
||||||
mkdir -p deploy-package/config
|
|
||||||
|
|
||||||
# 复制文件
|
|
||||||
cp target/demo-0.0.1-SNAPSHOT.jar deploy-package/backend/
|
|
||||||
cp -r frontend/dist/* deploy-package/frontend/
|
|
||||||
cp deploy.sh deploy-package/scripts/
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 二、服务器环境准备
|
|
||||||
|
|
||||||
### 2.1 连接服务器
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用SSH连接服务器
|
|
||||||
ssh username@your-server-ip
|
|
||||||
|
|
||||||
# 或使用密钥
|
|
||||||
ssh -i ~/.ssh/your-key.pem username@your-server-ip
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 安装必需软件
|
|
||||||
|
|
||||||
#### Ubuntu/Debian
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 更新系统
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
|
|
||||||
# 安装Java 21
|
|
||||||
sudo apt install -y openjdk-21-jdk
|
|
||||||
|
|
||||||
# 验证Java安装
|
|
||||||
java -version
|
|
||||||
# 应该显示: openjdk version "21.x.x"
|
|
||||||
|
|
||||||
# 安装MySQL 8.0
|
|
||||||
sudo apt install -y mysql-server
|
|
||||||
|
|
||||||
# 启动MySQL服务
|
|
||||||
sudo systemctl start mysql
|
|
||||||
sudo systemctl enable mysql
|
|
||||||
|
|
||||||
# 安装FFmpeg(视频处理需要)
|
|
||||||
sudo apt install -y ffmpeg
|
|
||||||
|
|
||||||
# 验证FFmpeg安装
|
|
||||||
ffmpeg -version
|
|
||||||
|
|
||||||
# 安装Nginx(反向代理)
|
|
||||||
sudo apt install -y nginx
|
|
||||||
|
|
||||||
# 安装Maven(可选,用于重新构建)
|
|
||||||
sudo apt install -y maven
|
|
||||||
```
|
|
||||||
|
|
||||||
#### CentOS/RHEL
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 更新系统
|
|
||||||
sudo yum update -y
|
|
||||||
|
|
||||||
# 安装Java 21
|
|
||||||
sudo yum install -y java-21-openjdk java-21-openjdk-devel
|
|
||||||
|
|
||||||
# 安装MySQL 8.0
|
|
||||||
sudo yum install -y mysql-server
|
|
||||||
|
|
||||||
# 启动MySQL服务
|
|
||||||
sudo systemctl start mysqld
|
|
||||||
sudo systemctl enable mysqld
|
|
||||||
|
|
||||||
# 安装FFmpeg
|
|
||||||
sudo yum install -y epel-release
|
|
||||||
sudo yum install -y ffmpeg
|
|
||||||
|
|
||||||
# 安装Nginx
|
|
||||||
sudo yum install -y nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 创建应用目录
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建应用目录结构
|
|
||||||
sudo mkdir -p /app/aigc-platform
|
|
||||||
sudo mkdir -p /app/aigc-platform/{logs,uploads,temp,config,backend,frontend}
|
|
||||||
|
|
||||||
# 设置权限
|
|
||||||
sudo chown -R $USER:$USER /app/aigc-platform
|
|
||||||
chmod -R 755 /app/aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🗄️ 三、数据库配置
|
|
||||||
|
|
||||||
### 3.1 配置MySQL
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 安全配置MySQL(首次安装)
|
|
||||||
sudo mysql_secure_installation
|
|
||||||
|
|
||||||
# 登录MySQL
|
|
||||||
sudo mysql -u root -p
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 创建数据库和用户
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- 创建数据库
|
|
||||||
CREATE DATABASE aigc_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- 创建用户(替换'your_password'为强密码)
|
|
||||||
CREATE USER 'aigc_user'@'localhost' IDENTIFIED BY 'your_password';
|
|
||||||
|
|
||||||
-- 授予权限
|
|
||||||
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_user'@'localhost';
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
|
|
||||||
-- 退出
|
|
||||||
EXIT;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.3 优化MySQL配置
|
|
||||||
|
|
||||||
编辑MySQL配置文件:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Ubuntu/Debian
|
|
||||||
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
|
|
||||||
|
|
||||||
# CentOS/RHEL
|
|
||||||
sudo nano /etc/my.cnf
|
|
||||||
```
|
|
||||||
|
|
||||||
添加/修改以下配置:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[mysqld]
|
|
||||||
# 字符集
|
|
||||||
character-set-server=utf8mb4
|
|
||||||
collation-server=utf8mb4_unicode_ci
|
|
||||||
|
|
||||||
# 连接数(50人并发)
|
|
||||||
max_connections=100
|
|
||||||
max_user_connections=50
|
|
||||||
|
|
||||||
# 缓冲池(根据内存调整,8GB服务器建议2-4GB)
|
|
||||||
innodb_buffer_pool_size=2G
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
slow_query_log=1
|
|
||||||
slow_query_log_file=/var/log/mysql/slow-query.log
|
|
||||||
long_query_time=2
|
|
||||||
|
|
||||||
# 时区
|
|
||||||
default-time-zone='+08:00'
|
|
||||||
```
|
|
||||||
|
|
||||||
重启MySQL:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart mysql
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📤 四、上传文件到服务器
|
|
||||||
|
|
||||||
### 4.1 使用SCP上传(推荐)
|
|
||||||
|
|
||||||
在**本地**执行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 上传JAR文件
|
|
||||||
scp target/demo-0.0.1-SNAPSHOT.jar username@your-server-ip:/app/aigc-platform/backend/
|
|
||||||
|
|
||||||
# 上传前端文件
|
|
||||||
scp -r frontend/dist/* username@your-server-ip:/app/aigc-platform/frontend/
|
|
||||||
|
|
||||||
# 或使用rsync(更高效)
|
|
||||||
rsync -avz frontend/dist/ username@your-server-ip:/app/aigc-platform/frontend/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 使用FTP/SFTP工具
|
|
||||||
|
|
||||||
使用FileZilla、WinSCP等工具上传文件到:
|
|
||||||
- JAR文件 → `/app/aigc-platform/backend/`
|
|
||||||
- 前端文件 → `/app/aigc-platform/frontend/`
|
|
||||||
|
|
||||||
### 4.3 使用Git(如果服务器有Git)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在服务器上克隆仓库
|
|
||||||
cd /app/aigc-platform
|
|
||||||
git clone ssh://git@your-git-server/path/to/repo.git
|
|
||||||
|
|
||||||
# 构建
|
|
||||||
cd repo/demo
|
|
||||||
./mvnw clean package -DskipTests
|
|
||||||
cp target/demo-0.0.1-SNAPSHOT.jar /app/aigc-platform/backend/
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ 五、应用配置
|
|
||||||
|
|
||||||
### 5.1 创建配置文件
|
|
||||||
|
|
||||||
在服务器上创建配置文件:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建生产环境配置
|
|
||||||
sudo nano /app/aigc-platform/config/application-prod.properties
|
|
||||||
```
|
|
||||||
|
|
||||||
配置文件内容:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 数据库配置
|
|
||||||
spring.datasource.url=jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai
|
|
||||||
spring.datasource.username=aigc_user
|
|
||||||
spring.datasource.password=your_password
|
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
|
||||||
|
|
||||||
# 连接池配置(50人并发)
|
|
||||||
spring.datasource.hikari.maximum-pool-size=30
|
|
||||||
spring.datasource.hikari.minimum-idle=10
|
|
||||||
spring.datasource.hikari.connection-timeout=30000
|
|
||||||
spring.datasource.hikari.idle-timeout=600000
|
|
||||||
spring.datasource.hikari.max-lifetime=1800000
|
|
||||||
|
|
||||||
# JPA配置
|
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
|
||||||
spring.jpa.show-sql=false
|
|
||||||
spring.jpa.properties.hibernate.format_sql=true
|
|
||||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
|
|
||||||
|
|
||||||
# 服务器配置
|
|
||||||
server.port=8080
|
|
||||||
server.tomcat.threads.max=150
|
|
||||||
server.tomcat.threads.min-spare=20
|
|
||||||
server.tomcat.max-connections=200
|
|
||||||
server.tomcat.accept-count=100
|
|
||||||
|
|
||||||
# JWT配置
|
|
||||||
jwt.secret=your-jwt-secret-key-change-this-to-random-string
|
|
||||||
jwt.expiration=86400000
|
|
||||||
|
|
||||||
# AI API配置(从环境变量读取)
|
|
||||||
ai.api.base-url=${AI_API_BASE_URL:https://api.openai.com}
|
|
||||||
ai.api.key=${AI_API_KEY:your-api-key}
|
|
||||||
ai.image.api.base-url=${AI_IMAGE_API_BASE_URL:https://api.openai.com}
|
|
||||||
ai.image.api.key=${AI_IMAGE_API_KEY:your-api-key}
|
|
||||||
|
|
||||||
# 文件上传配置
|
|
||||||
app.upload.path=${UPLOAD_PATH:/app/aigc-platform/uploads}
|
|
||||||
spring.servlet.multipart.max-file-size=100MB
|
|
||||||
spring.servlet.multipart.max-request-size=100MB
|
|
||||||
|
|
||||||
# 日志配置
|
|
||||||
logging.level.root=INFO
|
|
||||||
logging.level.com.example.demo=DEBUG
|
|
||||||
logging.file.path=/app/aigc-platform/logs
|
|
||||||
logging.file.name=${logging.file.path}/application.log
|
|
||||||
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
|
||||||
|
|
||||||
# 时区
|
|
||||||
spring.jackson.time-zone=Asia/Shanghai
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.2 创建环境变量文件(可选)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /app/aigc-platform/config/.env
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 数据库配置
|
|
||||||
export DB_URL="jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai"
|
|
||||||
export DB_USERNAME="aigc_user"
|
|
||||||
export DB_PASSWORD="your_password"
|
|
||||||
|
|
||||||
# JWT密钥(生成随机密钥)
|
|
||||||
export JWT_SECRET="$(openssl rand -base64 64)"
|
|
||||||
|
|
||||||
# AI API密钥
|
|
||||||
export AI_API_KEY="your-api-key"
|
|
||||||
export AI_IMAGE_API_KEY="your-api-key"
|
|
||||||
|
|
||||||
# 文件路径
|
|
||||||
export UPLOAD_PATH="/app/aigc-platform/uploads"
|
|
||||||
export TEMP_DIR="/app/aigc-platform/temp"
|
|
||||||
export FFMPEG_PATH="/usr/bin/ffmpeg"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 六、创建Systemd服务
|
|
||||||
|
|
||||||
### 6.1 创建服务文件
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/systemd/system/aigc-platform.service
|
|
||||||
```
|
|
||||||
|
|
||||||
服务文件内容:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Unit]
|
|
||||||
Description=AIGC Platform Application
|
|
||||||
After=network.target mysql.service
|
|
||||||
Requires=mysql.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=your-username
|
|
||||||
Group=your-group
|
|
||||||
WorkingDirectory=/app/aigc-platform/backend
|
|
||||||
|
|
||||||
# 环境变量(可选,如果使用.env文件)
|
|
||||||
# EnvironmentFile=/app/aigc-platform/config/.env
|
|
||||||
|
|
||||||
# JVM参数(根据服务器内存调整)
|
|
||||||
# 8GB内存服务器建议:-Xms1g -Xmx4g
|
|
||||||
# 16GB内存服务器建议:-Xms2g -Xmx8g
|
|
||||||
ExecStart=/usr/bin/java \
|
|
||||||
-Xms1g \
|
|
||||||
-Xmx4g \
|
|
||||||
-XX:+UseG1GC \
|
|
||||||
-XX:MaxGCPauseMillis=200 \
|
|
||||||
-Dspring.profiles.active=prod \
|
|
||||||
-Dspring.config.location=file:/app/aigc-platform/config/application-prod.properties \
|
|
||||||
-jar /app/aigc-platform/backend/demo-0.0.1-SNAPSHOT.jar
|
|
||||||
|
|
||||||
# 重启策略
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=aigc-platform
|
|
||||||
|
|
||||||
# 安全设置
|
|
||||||
NoNewPrivileges=true
|
|
||||||
PrivateTmp=true
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
|
||||||
|
|
||||||
**重要:** 将 `your-username` 和 `your-group` 替换为实际的用户名和组。
|
|
||||||
|
|
||||||
### 6.2 启动服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 重新加载systemd配置
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
|
|
||||||
# 启用服务(开机自启)
|
|
||||||
sudo systemctl enable aigc-platform
|
|
||||||
|
|
||||||
# 启动服务
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
|
|
||||||
# 查看服务状态
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
sudo journalctl -u aigc-platform -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 常用服务管理命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 启动服务
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
|
|
||||||
# 停止服务
|
|
||||||
sudo systemctl stop aigc-platform
|
|
||||||
|
|
||||||
# 重启服务
|
|
||||||
sudo systemctl restart aigc-platform
|
|
||||||
|
|
||||||
# 查看状态
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
sudo journalctl -u aigc-platform -n 100 -f
|
|
||||||
|
|
||||||
# 查看最近错误
|
|
||||||
sudo journalctl -u aigc-platform -p err -n 50
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🌐 七、Nginx反向代理配置
|
|
||||||
|
|
||||||
### 7.1 创建Nginx配置
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/nginx/sites-available/aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
配置内容:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
# HTTP服务器(重定向到HTTPS)
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name your-domain.com www.your-domain.com;
|
|
||||||
|
|
||||||
# 重定向到HTTPS
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
# HTTPS服务器
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name your-domain.com www.your-domain.com;
|
|
||||||
|
|
||||||
# SSL证书配置(使用Let's Encrypt)
|
|
||||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
# 日志
|
|
||||||
access_log /var/log/nginx/aigc-platform-access.log;
|
|
||||||
error_log /var/log/nginx/aigc-platform-error.log;
|
|
||||||
|
|
||||||
# 客户端最大上传大小
|
|
||||||
client_max_body_size 100M;
|
|
||||||
|
|
||||||
# API代理
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:8080;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# WebSocket支持(如果需要)
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection "upgrade";
|
|
||||||
|
|
||||||
# 超时设置
|
|
||||||
proxy_connect_timeout 60s;
|
|
||||||
proxy_send_timeout 60s;
|
|
||||||
proxy_read_timeout 60s;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 上传文件代理
|
|
||||||
location /uploads/ {
|
|
||||||
proxy_pass http://localhost:8080;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# 缓存设置
|
|
||||||
expires 7d;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
|
|
||||||
# 前端静态文件
|
|
||||||
location / {
|
|
||||||
root /app/aigc-platform/frontend;
|
|
||||||
index index.html;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
|
|
||||||
# 缓存设置
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
location /health {
|
|
||||||
proxy_pass http://localhost:8080/actuator/health;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.2 启用配置
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 创建符号链接
|
|
||||||
sudo ln -s /etc/nginx/sites-available/aigc-platform /etc/nginx/sites-enabled/
|
|
||||||
|
|
||||||
# 测试配置
|
|
||||||
sudo nginx -t
|
|
||||||
|
|
||||||
# 重新加载Nginx
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7.3 配置SSL证书(Let's Encrypt)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 安装Certbot
|
|
||||||
sudo apt install -y certbot python3-certbot-nginx
|
|
||||||
|
|
||||||
# 获取证书(自动配置Nginx)
|
|
||||||
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
|
|
||||||
|
|
||||||
# 测试自动续期
|
|
||||||
sudo certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 八、验证部署
|
|
||||||
|
|
||||||
### 8.1 检查服务状态
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查应用服务
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
|
|
||||||
# 检查MySQL服务
|
|
||||||
sudo systemctl status mysql
|
|
||||||
|
|
||||||
# 检查Nginx服务
|
|
||||||
sudo systemctl status nginx
|
|
||||||
|
|
||||||
# 检查端口占用
|
|
||||||
sudo netstat -tlnp | grep -E '8080|80|443'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 测试API
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试健康检查
|
|
||||||
curl http://localhost:8080/actuator/health
|
|
||||||
|
|
||||||
# 测试API(需要认证)
|
|
||||||
curl -X POST http://localhost:8080/api/auth/login \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"username":"test","password":"test"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.3 测试前端
|
|
||||||
|
|
||||||
在浏览器中访问:
|
|
||||||
- HTTP: `http://your-server-ip`
|
|
||||||
- HTTPS: `https://your-domain.com`
|
|
||||||
|
|
||||||
### 8.4 检查日志
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 应用日志
|
|
||||||
tail -f /app/aigc-platform/logs/application.log
|
|
||||||
|
|
||||||
# 系统日志
|
|
||||||
sudo journalctl -u aigc-platform -f
|
|
||||||
|
|
||||||
# Nginx日志
|
|
||||||
sudo tail -f /var/log/nginx/aigc-platform-access.log
|
|
||||||
sudo tail -f /var/log/nginx/aigc-platform-error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 九、更新部署
|
|
||||||
|
|
||||||
### 9.1 更新后端
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 停止服务
|
|
||||||
sudo systemctl stop aigc-platform
|
|
||||||
|
|
||||||
# 2. 备份旧版本
|
|
||||||
cp /app/aigc-platform/backend/demo-0.0.1-SNAPSHOT.jar \
|
|
||||||
/app/aigc-platform/backend/demo-0.0.1-SNAPSHOT.jar.backup
|
|
||||||
|
|
||||||
# 3. 上传新版本(从本地)
|
|
||||||
# scp target/demo-0.0.1-SNAPSHOT.jar username@server:/app/aigc-platform/backend/
|
|
||||||
|
|
||||||
# 4. 启动服务
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
|
|
||||||
# 5. 检查状态
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.2 更新前端
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 备份旧版本
|
|
||||||
cp -r /app/aigc-platform/frontend /app/aigc-platform/frontend.backup
|
|
||||||
|
|
||||||
# 2. 上传新版本(从本地)
|
|
||||||
# scp -r frontend/dist/* username@server:/app/aigc-platform/frontend/
|
|
||||||
|
|
||||||
# 3. 重新加载Nginx
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠️ 十、故障排查
|
|
||||||
|
|
||||||
### 10.1 应用无法启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看详细日志
|
|
||||||
sudo journalctl -u aigc-platform -n 100
|
|
||||||
|
|
||||||
# 检查Java版本
|
|
||||||
java -version
|
|
||||||
|
|
||||||
# 检查端口占用
|
|
||||||
sudo lsof -i :8080
|
|
||||||
|
|
||||||
# 检查文件权限
|
|
||||||
ls -la /app/aigc-platform/backend/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10.2 数据库连接失败
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试MySQL连接
|
|
||||||
mysql -u aigc_user -p aigc_platform
|
|
||||||
|
|
||||||
# 检查MySQL服务
|
|
||||||
sudo systemctl status mysql
|
|
||||||
|
|
||||||
# 查看MySQL日志
|
|
||||||
sudo tail -f /var/log/mysql/error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10.3 Nginx配置错误
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试配置
|
|
||||||
sudo nginx -t
|
|
||||||
|
|
||||||
# 查看错误日志
|
|
||||||
sudo tail -f /var/log/nginx/error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10.4 内存不足
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看内存使用
|
|
||||||
free -h
|
|
||||||
|
|
||||||
# 查看Java进程内存
|
|
||||||
ps aux | grep java
|
|
||||||
|
|
||||||
# 调整JVM参数(在systemd服务文件中)
|
|
||||||
# -Xms1g -Xmx4g # 减少内存使用
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 十一、性能监控
|
|
||||||
|
|
||||||
### 11.1 系统监控
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# CPU和内存使用
|
|
||||||
top
|
|
||||||
htop # 如果安装了
|
|
||||||
|
|
||||||
# 磁盘使用
|
|
||||||
df -h
|
|
||||||
|
|
||||||
# 网络连接
|
|
||||||
netstat -an | grep ESTABLISHED | wc -l
|
|
||||||
```
|
|
||||||
|
|
||||||
### 11.2 应用监控
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看JVM内存使用
|
|
||||||
jstat -gc <pid> 1000
|
|
||||||
|
|
||||||
# 查看线程
|
|
||||||
jstack <pid>
|
|
||||||
|
|
||||||
# 查看应用日志
|
|
||||||
tail -f /app/aigc-platform/logs/application.log | grep ERROR
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 十二、安全建议
|
|
||||||
|
|
||||||
1. **防火墙配置**
|
|
||||||
```bash
|
|
||||||
# 只开放必要端口
|
|
||||||
sudo ufw allow 22/tcp # SSH
|
|
||||||
sudo ufw allow 80/tcp # HTTP
|
|
||||||
sudo ufw allow 443/tcp # HTTPS
|
|
||||||
sudo ufw enable
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **定期备份**
|
|
||||||
```bash
|
|
||||||
# 备份数据库
|
|
||||||
mysqldump -u aigc_user -p aigc_platform > backup_$(date +%Y%m%d).sql
|
|
||||||
|
|
||||||
# 备份上传文件
|
|
||||||
tar -czf uploads_backup_$(date +%Y%m%d).tar.gz /app/aigc-platform/uploads
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **更新系统**
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 快速部署脚本
|
|
||||||
|
|
||||||
创建一键部署脚本 `deploy-linux.sh`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 开始部署 AIGC 平台..."
|
|
||||||
|
|
||||||
# 检查Java
|
|
||||||
if ! command -v java &> /dev/null; then
|
|
||||||
echo "❌ Java未安装,请先安装Java 21"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查MySQL
|
|
||||||
if ! systemctl is-active --quiet mysql; then
|
|
||||||
echo "❌ MySQL服务未运行"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 停止服务
|
|
||||||
echo "🛑 停止服务..."
|
|
||||||
sudo systemctl stop aigc-platform || true
|
|
||||||
|
|
||||||
# 备份
|
|
||||||
echo "💾 备份旧版本..."
|
|
||||||
BACKUP_DIR="/app/aigc-platform/backup/$(date +%Y%m%d_%H%M%S)"
|
|
||||||
mkdir -p $BACKUP_DIR
|
|
||||||
cp /app/aigc-platform/backend/demo-0.0.1-SNAPSHOT.jar $BACKUP_DIR/ || true
|
|
||||||
|
|
||||||
# 启动服务
|
|
||||||
echo "▶️ 启动服务..."
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
|
|
||||||
# 等待启动
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
# 检查状态
|
|
||||||
if systemctl is-active --quiet aigc-platform; then
|
|
||||||
echo "✅ 部署成功!"
|
|
||||||
sudo systemctl status aigc-platform
|
|
||||||
else
|
|
||||||
echo "❌ 部署失败,查看日志:"
|
|
||||||
sudo journalctl -u aigc-platform -n 50
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
使用:
|
|
||||||
```bash
|
|
||||||
chmod +x deploy-linux.sh
|
|
||||||
./deploy-linux.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 支持
|
|
||||||
|
|
||||||
如遇问题,请检查:
|
|
||||||
1. 日志文件:`/app/aigc-platform/logs/application.log`
|
|
||||||
2. 系统日志:`sudo journalctl -u aigc-platform`
|
|
||||||
3. Nginx日志:`/var/log/nginx/aigc-platform-error.log`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**部署完成后,访问:**
|
|
||||||
- 前端:`https://your-domain.com`
|
|
||||||
- API:`https://your-domain.com/api`
|
|
||||||
- 健康检查:`https://your-domain.com/health`
|
|
||||||
|
|
||||||
80
demo/LINUX_DEPLOY_COMMANDS.sh
Normal file
80
demo/LINUX_DEPLOY_COMMANDS.sh
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Linux服务器部署命令脚本
|
||||||
|
# 使用方法: bash LINUX_DEPLOY_COMMANDS.sh
|
||||||
|
|
||||||
|
set -e # 遇到错误立即退出
|
||||||
|
|
||||||
|
echo "============================================================"
|
||||||
|
echo "开始部署 Spring Boot + Vue 项目"
|
||||||
|
echo "============================================================"
|
||||||
|
|
||||||
|
# 进入项目目录
|
||||||
|
cd /home/ubuntu/spring-vue-app || cd ~/spring-vue-app || exit 1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 1: 检查 Dockerfile"
|
||||||
|
echo "============================================================"
|
||||||
|
if [ -f "backend/Dockerfile" ]; then
|
||||||
|
echo "✅ 找到 backend/Dockerfile"
|
||||||
|
echo "检查使用的镜像:"
|
||||||
|
grep "FROM" backend/Dockerfile | head -2
|
||||||
|
else
|
||||||
|
echo "❌ 未找到 backend/Dockerfile"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 2: 构建 Docker 镜像"
|
||||||
|
echo "============================================================"
|
||||||
|
sudo docker-compose build --no-cache
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 3: 启动服务"
|
||||||
|
echo "============================================================"
|
||||||
|
sudo docker-compose up -d
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 4: 等待服务启动(30秒)"
|
||||||
|
echo "============================================================"
|
||||||
|
sleep 30
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 5: 检查服务状态"
|
||||||
|
echo "============================================================"
|
||||||
|
sudo docker-compose ps
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "步骤 6: 健康检查"
|
||||||
|
echo "============================================================"
|
||||||
|
# 检查后端健康状态(不依赖Actuator,直接检查根路径)
|
||||||
|
if curl -f http://localhost:8080/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ 后端服务健康检查通过"
|
||||||
|
else
|
||||||
|
echo "⚠️ 后端服务可能还在启动中,请稍后检查"
|
||||||
|
echo "查看日志: sudo docker-compose logs backend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查前端
|
||||||
|
if curl -f http://localhost/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ 前端服务健康检查通过"
|
||||||
|
else
|
||||||
|
echo "⚠️ 前端服务可能还在启动中,请稍后检查"
|
||||||
|
echo "查看日志: sudo docker-compose logs frontend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================================"
|
||||||
|
echo "✅ 部署完成!"
|
||||||
|
echo "============================================================"
|
||||||
|
echo ""
|
||||||
|
echo "访问地址:"
|
||||||
|
echo " 前端: http://localhost"
|
||||||
|
echo " 后端: http://localhost:8080"
|
||||||
|
echo ""
|
||||||
|
echo "常用命令:"
|
||||||
|
echo " 查看日志: sudo docker-compose logs -f"
|
||||||
|
echo " 停止服务: sudo docker-compose down"
|
||||||
|
echo " 重启服务: sudo docker-compose restart"
|
||||||
|
echo "============================================================"
|
||||||
|
|
||||||
|
|
||||||
76
demo/LINUX_DEPLOY_SCRIPT.sh
Normal file
76
demo/LINUX_DEPLOY_SCRIPT.sh
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Linux服务器部署命令(已修改为使用正确的镜像)
|
||||||
|
|
||||||
|
cd /home/ubuntu/spring-vue-app/backend
|
||||||
|
|
||||||
|
# 创建/更新 Dockerfile(使用正确的镜像)
|
||||||
|
cat > Dockerfile << 'EOF'
|
||||||
|
# 多阶段构建:构建阶段
|
||||||
|
FROM maven:3.9-eclipse-temurin-21 AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制 pom.xml 并下载依赖(利用Docker缓存)
|
||||||
|
COPY pom.xml .
|
||||||
|
RUN mvn dependency:go-offline -B || true
|
||||||
|
|
||||||
|
# 复制源码
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# 打包应用(跳过测试)
|
||||||
|
RUN mvn clean package -DskipTests -B
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
|
FROM eclipse-temurin:21-jre
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装时区支持和wget(健康检查)
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
tzdata \
|
||||||
|
wget \
|
||||||
|
curl && \
|
||||||
|
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||||
|
echo "Asia/Shanghai" > /etc/timezone && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 创建非root用户(安全考虑)
|
||||||
|
RUN groupadd -r spring && useradd -r -g spring spring
|
||||||
|
|
||||||
|
# 创建必要的目录并设置权限
|
||||||
|
RUN mkdir -p /app/uploads /app/temp /app/logs && \
|
||||||
|
chown -R spring:spring /app
|
||||||
|
|
||||||
|
# 从构建阶段复制JAR文件(项目生成的JAR文件名:demo-0.0.1-SNAPSHOT.jar)
|
||||||
|
COPY --from=builder --chown=spring:spring /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
|
||||||
|
|
||||||
|
# 切换到非root用户
|
||||||
|
USER spring
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# JVM 参数优化(适配50人并发,建议2-4GB内存)
|
||||||
|
ENV JAVA_OPTS="-Xmx2g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Djava.security.egd=file:/dev/./urandom"
|
||||||
|
|
||||||
|
# 健康检查(检查应用是否响应,不依赖Actuator)
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 返回项目根目录
|
||||||
|
cd /home/ubuntu/spring-vue-app
|
||||||
|
|
||||||
|
# 构建并启动服务
|
||||||
|
sudo docker-compose build --no-cache
|
||||||
|
sudo docker-compose up -d
|
||||||
|
|
||||||
|
# 等待服务启动
|
||||||
|
sleep 30
|
||||||
|
|
||||||
|
# 检查服务状态
|
||||||
|
sudo docker-compose ps
|
||||||
|
|
||||||
|
# 健康检查(不依赖Actuator,直接检查根路径)
|
||||||
|
curl -f http://localhost:8080/ || echo "后端服务可能还在启动中,请稍后检查"
|
||||||
|
curl -f http://localhost/ || echo "前端服务可能还在启动中,请稍后检查"
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
194
demo/LOGIN_FIX_SUMMARY.md
Normal file
194
demo/LOGIN_FIX_SUMMARY.md
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# 登录验证码403错误修复总结
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
从宝塔面板日志和前端截图显示:
|
||||||
|
- 请求地址:`POST http://43.156.12.172/api/verification/email/send`
|
||||||
|
- 错误状态:403 Forbidden
|
||||||
|
- 问题:无法发送邮箱验证码
|
||||||
|
|
||||||
|
## 根本原因
|
||||||
|
1. **CORS跨域问题**:后端 SecurityConfig 中没有配置允许 43.x.x.x IP段的跨域访问
|
||||||
|
2. **JWT过滤器问题**:虽然配置了 `permitAll()`,但 JWT 过滤器仍然会处理所有请求,包括登录请求
|
||||||
|
3. **前端token处理问题**:登录请求也携带了 token,导致认证流程混乱
|
||||||
|
|
||||||
|
## 修复方案
|
||||||
|
|
||||||
|
### 1. 后端修改
|
||||||
|
|
||||||
|
#### 修改1:SecurityConfig.java - CORS配置
|
||||||
|
**文件路径**: `src/main/java/com/example/demo/config/SecurityConfig.java`
|
||||||
|
**修改位置**: 第136-140行
|
||||||
|
|
||||||
|
添加对云服务器IP段的CORS支持:
|
||||||
|
```java
|
||||||
|
// 云服务器 IP 段(43.x.x.x)
|
||||||
|
"http://43.*.*.*:*",
|
||||||
|
"https://43.*.*.*:*",
|
||||||
|
"http://43.*.*.*",
|
||||||
|
"https://43.*.*.*",
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 修改2:JwtAuthenticationFilter.java - 跳过公开路径
|
||||||
|
**文件路径**: `src/main/java/com/example/demo/security/JwtAuthenticationFilter.java`
|
||||||
|
**修改位置**: 第40-122行
|
||||||
|
|
||||||
|
添加公开路径列表,JWT过滤器直接放行这些路径:
|
||||||
|
```java
|
||||||
|
// 定义不需要JWT验证的路径
|
||||||
|
String[] publicPaths = {
|
||||||
|
"/api/auth/login",
|
||||||
|
"/api/auth/login/email",
|
||||||
|
"/api/auth/register",
|
||||||
|
"/api/verification/",
|
||||||
|
"/api/public/",
|
||||||
|
"/api/email/",
|
||||||
|
"/api/payments/alipay/notify",
|
||||||
|
"/api/payments/alipay/return",
|
||||||
|
"/swagger-ui",
|
||||||
|
"/v3/api-docs",
|
||||||
|
"/api-docs"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果是公开路径,直接放行,不进行JWT验证
|
||||||
|
if (isPublicPath) {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 前端修改
|
||||||
|
|
||||||
|
#### 修改1:request.js - 请求拦截器
|
||||||
|
**文件路径**: `frontend/src/api/request.js`
|
||||||
|
**修改位置**: 第22-58行
|
||||||
|
|
||||||
|
登录相关请求不携带token:
|
||||||
|
```javascript
|
||||||
|
// 登录相关的接口不需要添加token
|
||||||
|
const loginUrls = [
|
||||||
|
'/auth/login',
|
||||||
|
'/auth/login/email',
|
||||||
|
'/auth/register',
|
||||||
|
'/verification/email/send',
|
||||||
|
'/verification/email/verify',
|
||||||
|
'/verification/email/dev-set',
|
||||||
|
'/public/'
|
||||||
|
]
|
||||||
|
|
||||||
|
// 检查当前请求是否是登录相关接口
|
||||||
|
const isLoginRequest = loginUrls.some(url => config.url.includes(url))
|
||||||
|
|
||||||
|
if (!isLoginRequest) {
|
||||||
|
// 非登录请求才添加Authorization头
|
||||||
|
const token = sessionStorage.getItem('token')
|
||||||
|
if (token && token !== 'null' && token.trim() !== '') {
|
||||||
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 修改2:request.js - 响应拦截器
|
||||||
|
**文件路径**: `frontend/src/api/request.js`
|
||||||
|
**修改位置**: 第60-177行
|
||||||
|
|
||||||
|
区分登录请求和非登录请求的错误处理:
|
||||||
|
- 只有非登录请求出现401/302错误时才清除token并跳转
|
||||||
|
- 登录请求的403错误显示具体错误信息,不显示"权限不足"
|
||||||
|
|
||||||
|
## 部署步骤
|
||||||
|
|
||||||
|
### 1. 重新编译后端
|
||||||
|
```bash
|
||||||
|
cd C:\Users\UI\Desktop\AIGC\demo
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 停止旧的后端服务
|
||||||
|
在宝塔面板中停止当前运行的 Java 应用
|
||||||
|
|
||||||
|
### 3. 上传新的 JAR 包
|
||||||
|
将 `target/demo-0.0.1-SNAPSHOT.jar` 上传到服务器
|
||||||
|
|
||||||
|
### 4. 重启后端服务
|
||||||
|
在宝塔面板中启动 Java 应用,或使用命令:
|
||||||
|
```bash
|
||||||
|
java -jar demo-0.0.1-SNAPSHOT.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 重新编译前端(可选)
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. 清除浏览器缓存
|
||||||
|
清除浏览器的缓存和 sessionStorage
|
||||||
|
|
||||||
|
## 验证步骤
|
||||||
|
|
||||||
|
1. 访问登录页面:`http://43.156.12.172`
|
||||||
|
2. 输入邮箱地址
|
||||||
|
3. 点击"获取验证码"按钮
|
||||||
|
4. 应该看到以下日志:
|
||||||
|
```
|
||||||
|
JWT过滤器: 跳过公开路径 /api/verification/email/send
|
||||||
|
```
|
||||||
|
5. 验证码应该成功发送,不再出现403错误
|
||||||
|
6. 输入验证码,完成登录
|
||||||
|
7. 登录成功后,所有后续请求都会自动携带token
|
||||||
|
|
||||||
|
## 技术要点
|
||||||
|
|
||||||
|
### 登录流程
|
||||||
|
1. **登录前**:所有登录相关的请求(发送验证码、登录、注册)不携带token
|
||||||
|
2. **登录中**:后端验证验证码,生成JWT token返回
|
||||||
|
3. **登录后**:前端保存token,所有后续请求自动携带token进行认证
|
||||||
|
|
||||||
|
### 安全性
|
||||||
|
- JWT过滤器只处理需要认证的请求
|
||||||
|
- 公开路径(登录、注册、验证码)完全跳过JWT验证
|
||||||
|
- CORS配置支持多种环境(本地开发、内网、云服务器、ngrok)
|
||||||
|
|
||||||
|
### 错误处理
|
||||||
|
- 登录请求失败不会触发"重新登录"跳转
|
||||||
|
- 非登录请求未认证才会跳转到登录页
|
||||||
|
- 403错误根据请求类型显示不同提示
|
||||||
|
|
||||||
|
## 预期效果
|
||||||
|
|
||||||
|
修复后,登录流程应该如下:
|
||||||
|
1. ✅ 访问登录页面正常
|
||||||
|
2. ✅ 点击"获取验证码"成功发送(不再403)
|
||||||
|
3. ✅ 输入验证码后登录成功
|
||||||
|
4. ✅ 登录后所有功能正常使用
|
||||||
|
5. ✅ Token过期或无效时自动跳转登录页
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 确保后端和前端都重新编译部署
|
||||||
|
2. 清除浏览器缓存避免旧代码影响
|
||||||
|
3. 检查宝塔面板日志确认修改生效
|
||||||
|
4. 如果还有问题,检查后端日志中的具体错误信息
|
||||||
|
|
||||||
|
## 相关文件清单
|
||||||
|
|
||||||
|
### 后端文件
|
||||||
|
- `src/main/java/com/example/demo/config/SecurityConfig.java`
|
||||||
|
- `src/main/java/com/example/demo/security/JwtAuthenticationFilter.java`
|
||||||
|
|
||||||
|
### 前端文件
|
||||||
|
- `frontend/src/api/request.js`
|
||||||
|
|
||||||
|
### 配置文件
|
||||||
|
- `frontend/.env.production`
|
||||||
|
- `frontend/vite.config.js`
|
||||||
|
|
||||||
|
## 问题排查
|
||||||
|
|
||||||
|
如果修复后仍有问题,请检查:
|
||||||
|
|
||||||
|
1. **后端日志**:查看是否有异常堆栈
|
||||||
|
2. **CORS头**:使用浏览器开发者工具查看响应头
|
||||||
|
3. **请求头**:确认登录请求没有 Authorization 头
|
||||||
|
4. **网络**:确认服务器防火墙允许访问
|
||||||
|
5. **端口**:确认后端监听在正确的端口(8080)
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
# 🔗 Nginx 内网穿透配置指南
|
|
||||||
|
|
||||||
## 📋 概述
|
|
||||||
|
|
||||||
使用 Nginx 反向代理后,**只需要穿透一个端口:80端口**
|
|
||||||
|
|
||||||
## 🎯 需要穿透的端口
|
|
||||||
|
|
||||||
### ✅ 必须穿透的端口
|
|
||||||
|
|
||||||
**端口 80** - Nginx 反向代理服务
|
|
||||||
- 这是唯一需要穿透的端口
|
|
||||||
- 用户通过此端口访问整个应用(前端 + API)
|
|
||||||
- Nginx 会自动将 `/api/` 请求代理到后端服务
|
|
||||||
|
|
||||||
### ❌ 不需要穿透的端口
|
|
||||||
|
|
||||||
- **8080** - 后端服务端口
|
|
||||||
- 原因:通过 Nginx 内部代理访问,不需要对外暴露
|
|
||||||
- 即使暴露,也建议关闭以提高安全性
|
|
||||||
|
|
||||||
- **3306** - MySQL 数据库端口
|
|
||||||
- 原因:仅在 Docker 网络内部使用
|
|
||||||
- 安全建议:永远不要对外暴露数据库端口
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 内网穿透工具配置
|
|
||||||
|
|
||||||
### 方式一:使用 ngrok(推荐)
|
|
||||||
|
|
||||||
#### 1. 安装 ngrok
|
|
||||||
```bash
|
|
||||||
# 下载 ngrok
|
|
||||||
# https://ngrok.com/download
|
|
||||||
|
|
||||||
# Windows: 下载 exe 文件
|
|
||||||
# Linux/Mac:
|
|
||||||
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz
|
|
||||||
tar -xzf ngrok-v3-stable-linux-amd64.tgz
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 启动 ngrok 穿透 80 端口
|
|
||||||
```bash
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 获取穿透地址
|
|
||||||
ngrok 会输出类似:
|
|
||||||
```
|
|
||||||
Forwarding https://xxxxx.ngrok-free.app -> http://localhost:80
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. 配置 Nginx(如果需要自定义域名)
|
|
||||||
|
|
||||||
修改 `nginx/nginx.conf`:
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name xxxxx.ngrok-free.app; # ngrok 分配的域名
|
|
||||||
# ... 其他配置
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 方式二:使用 frp(Fast Reverse Proxy)
|
|
||||||
|
|
||||||
#### 1. 服务器端配置(frps.ini)
|
|
||||||
```ini
|
|
||||||
[common]
|
|
||||||
bind_port = 7000
|
|
||||||
|
|
||||||
# 如果使用自定义域名
|
|
||||||
subdomain_host = yourdomain.com
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 客户端配置(frpc.ini)
|
|
||||||
```ini
|
|
||||||
[common]
|
|
||||||
server_addr = your-server-ip
|
|
||||||
server_port = 7000
|
|
||||||
|
|
||||||
[web]
|
|
||||||
type = http
|
|
||||||
local_ip = 127.0.0.1
|
|
||||||
local_port = 80
|
|
||||||
custom_domains = your-domain.com
|
|
||||||
# 或者使用子域名
|
|
||||||
# subdomain = aigc
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 启动 frp 客户端
|
|
||||||
```bash
|
|
||||||
frpc -c frpc.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 方式三:使用 NPS(Nginx Proxy Server)
|
|
||||||
|
|
||||||
#### 1. 服务器端配置
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tcp": [
|
|
||||||
{
|
|
||||||
"port": 80,
|
|
||||||
"target": "your-local-ip:80"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 客户端连接服务器
|
|
||||||
```bash
|
|
||||||
npc -server=server-ip:port -vkey=your-key
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔐 安全建议
|
|
||||||
|
|
||||||
### 1. 只暴露必要的端口
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml
|
|
||||||
# ✅ 保留(需要穿透)
|
|
||||||
nginx:
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
|
|
||||||
# ❌ 建议移除(提高安全性)
|
|
||||||
backend:
|
|
||||||
# ports:
|
|
||||||
# - "8080:8080" # 注释掉,不对外暴露
|
|
||||||
|
|
||||||
mysql:
|
|
||||||
# ports:
|
|
||||||
# - "3306:3306" # 注释掉,不对外暴露
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 配置 HTTPS(推荐)
|
|
||||||
|
|
||||||
#### 使用 ngrok(自动HTTPS)
|
|
||||||
```bash
|
|
||||||
# ngrok 自动提供 HTTPS
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 使用 Nginx + Let's Encrypt
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
server_name your-domain.com;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
|
||||||
# ... 其他配置
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 配置示例
|
|
||||||
|
|
||||||
### 完整的 docker-compose.yml(优化版 - 只暴露80端口)
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
mysql:
|
|
||||||
image: mysql:8.0
|
|
||||||
# 移除 ports,不对外暴露
|
|
||||||
# ports:
|
|
||||||
# - "3306:3306"
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
backend:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.backend
|
|
||||||
# 移除 ports,通过 Nginx 内部访问
|
|
||||||
# ports:
|
|
||||||
# - "8080:8080"
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
build:
|
|
||||||
context: ./nginx
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
ports:
|
|
||||||
- "80:80" # ✅ 唯一需要穿透的端口
|
|
||||||
networks:
|
|
||||||
- app-network
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试内网穿透
|
|
||||||
|
|
||||||
### 1. 启动服务
|
|
||||||
```bash
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 启动内网穿透工具
|
|
||||||
```bash
|
|
||||||
# 使用 ngrok
|
|
||||||
ngrok http 80
|
|
||||||
|
|
||||||
# 或使用 frp
|
|
||||||
frpc -c frpc.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 访问测试
|
|
||||||
```bash
|
|
||||||
# 使用穿透地址访问
|
|
||||||
curl https://xxxxx.ngrok-free.app/health
|
|
||||||
|
|
||||||
# 测试 API
|
|
||||||
curl https://xxxxx.ngrok-free.app/api/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 端口使用总结
|
|
||||||
|
|
||||||
| 服务 | 端口 | 是否需要穿透 | 说明 |
|
|
||||||
|------|------|-------------|------|
|
|
||||||
| Nginx | 80 | ✅ **是** | 唯一需要穿透的端口 |
|
|
||||||
| Backend | 8080 | ❌ 否 | 通过 Nginx 内部访问 |
|
|
||||||
| MySQL | 3306 | ❌ 否 | 仅在 Docker 网络内访问 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速开始
|
|
||||||
|
|
||||||
### 使用 ngrok(最简单)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 启动所有服务
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 2. 启动 ngrok
|
|
||||||
ngrok http 80
|
|
||||||
|
|
||||||
# 3. 复制 ngrok 提供的 HTTPS 地址
|
|
||||||
# 例如: https://xxxxx.ngrok-free.app
|
|
||||||
|
|
||||||
# 4. 在浏览器中访问该地址
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 常见问题
|
|
||||||
|
|
||||||
### Q: 为什么不需要穿透 8080 端口?
|
|
||||||
A: 因为 Nginx 已经配置了反向代理,所有 `/api/` 请求都会自动转发到后端服务,用户只需要访问 Nginx 的 80 端口即可。
|
|
||||||
|
|
||||||
### Q: 如果需要直接访问后端 API 怎么办?
|
|
||||||
A: 如果确实需要直接访问,可以在 docker-compose.yml 中保留 8080 端口的映射,但不推荐。
|
|
||||||
|
|
||||||
### Q: ngrok 的地址会变吗?
|
|
||||||
A: 免费版 ngrok 每次启动地址都会变化。可以:
|
|
||||||
- 使用付费版获得固定域名
|
|
||||||
- 使用其他工具如 frp 配置自定义域名
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
- [ngrok 官方文档](https://ngrok.com/docs)
|
|
||||||
- [frp 官方文档](https://gofrp.org/docs/)
|
|
||||||
- [Nginx 反向代理指南](./NGINX_REVERSE_PROXY_GUIDE.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**总结:只需要穿透 80 端口即可!** ✅
|
|
||||||
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
# Nginx 反向代理配置指南
|
|
||||||
|
|
||||||
## 📋 概述
|
|
||||||
|
|
||||||
本项目已配置使用 Nginx 作为反向代理服务器,实现以下功能:
|
|
||||||
- 前端静态文件服务(Vue.js 构建产物)
|
|
||||||
- API 请求代理到后端 Spring Boot 服务
|
|
||||||
- 负载均衡和健康检查
|
|
||||||
- Gzip 压缩优化
|
|
||||||
- WebSocket 支持
|
|
||||||
|
|
||||||
## 🏗️ 架构
|
|
||||||
|
|
||||||
```
|
|
||||||
用户请求
|
|
||||||
↓
|
|
||||||
Nginx (端口 80)
|
|
||||||
├─ / → 前端静态文件 (dist/)
|
|
||||||
└─ /api/ → 代理到后端 (backend:8080)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📁 文件结构
|
|
||||||
|
|
||||||
```
|
|
||||||
demo/
|
|
||||||
├── nginx/
|
|
||||||
│ ├── nginx.conf # Nginx 主配置文件
|
|
||||||
│ ├── Dockerfile # Nginx 容器镜像
|
|
||||||
│ └── docker-compose.yml # 独立 Nginx 部署(可选)
|
|
||||||
├── docker-compose.yml # 完整的服务编排(包含 Nginx)
|
|
||||||
└── Dockerfile.backend # 后端服务镜像
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 快速开始
|
|
||||||
|
|
||||||
### 方式一:使用 Docker Compose(推荐)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 构建前端
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 2. 启动所有服务(包括 Nginx)
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 3. 访问应用
|
|
||||||
# 前端: http://localhost
|
|
||||||
# 后端API: http://localhost/api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方式二:独立部署 Nginx
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 构建前端
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# 2. 启动后端服务
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
|
|
||||||
|
|
||||||
# 3. 启动 Nginx(在 nginx 目录下)
|
|
||||||
cd nginx
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚙️ Nginx 配置详解
|
|
||||||
|
|
||||||
### 主要配置项
|
|
||||||
|
|
||||||
#### 1. 上游服务器配置
|
|
||||||
```nginx
|
|
||||||
upstream backend {
|
|
||||||
server backend:8080; # 后端服务地址(Docker 服务名)
|
|
||||||
keepalive 32;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 前端静态文件服务
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html; # SPA 路由支持
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. API 代理配置
|
|
||||||
```nginx
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://backend;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 功能特性
|
|
||||||
|
|
||||||
#### ✅ 静态资源缓存
|
|
||||||
- 图片、CSS、JS 等静态资源缓存 30 天
|
|
||||||
- 提升页面加载速度
|
|
||||||
|
|
||||||
#### ✅ Gzip 压缩
|
|
||||||
- 自动压缩文本文件(HTML、CSS、JS、JSON)
|
|
||||||
- 减少传输数据量
|
|
||||||
|
|
||||||
#### ✅ WebSocket 支持
|
|
||||||
- 支持 WebSocket 连接(`/ws/` 路径)
|
|
||||||
- 自动处理升级协议
|
|
||||||
|
|
||||||
#### ✅ 健康检查
|
|
||||||
- `/health` 端点用于健康检查
|
|
||||||
- 便于监控和负载均衡
|
|
||||||
|
|
||||||
#### ✅ CORS 处理
|
|
||||||
- 自动处理跨域请求
|
|
||||||
- 支持预检请求(OPTIONS)
|
|
||||||
|
|
||||||
## 🔧 配置修改
|
|
||||||
|
|
||||||
### 修改端口
|
|
||||||
|
|
||||||
编辑 `docker-compose.yml`:
|
|
||||||
```yaml
|
|
||||||
nginx:
|
|
||||||
ports:
|
|
||||||
- "8080:80" # 外部端口:容器端口
|
|
||||||
```
|
|
||||||
|
|
||||||
### 修改后端地址
|
|
||||||
|
|
||||||
编辑 `nginx/nginx.conf`:
|
|
||||||
```nginx
|
|
||||||
upstream backend {
|
|
||||||
server your-backend-host:8080; # 修改为实际后端地址
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 添加 SSL/HTTPS
|
|
||||||
|
|
||||||
1. 将 SSL 证书放在 `nginx/ssl/` 目录
|
|
||||||
2. 修改 `nginx.conf` 添加 HTTPS 配置:
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
ssl_certificate /etc/nginx/ssl/cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/key.pem;
|
|
||||||
# ... 其他配置
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📝 环境变量配置
|
|
||||||
|
|
||||||
### 生产环境变量
|
|
||||||
|
|
||||||
创建 `.env` 文件或设置环境变量:
|
|
||||||
```bash
|
|
||||||
# 数据库配置
|
|
||||||
MYSQL_ROOT_PASSWORD=your_password
|
|
||||||
MYSQL_DATABASE=aigc_platform
|
|
||||||
|
|
||||||
# Spring Boot 配置
|
|
||||||
SPRING_PROFILES_ACTIVE=prod
|
|
||||||
SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/aigc_platform
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 故障排查
|
|
||||||
|
|
||||||
### 检查 Nginx 日志
|
|
||||||
```bash
|
|
||||||
# 查看 Nginx 容器日志
|
|
||||||
docker logs demo-nginx
|
|
||||||
|
|
||||||
# 查看错误日志
|
|
||||||
docker exec demo-nginx cat /var/log/nginx/error.log
|
|
||||||
|
|
||||||
# 查看访问日志
|
|
||||||
docker exec demo-nginx cat /var/log/nginx/access.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试配置
|
|
||||||
```bash
|
|
||||||
# 检查 Nginx 配置语法
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
|
|
||||||
# 重新加载配置(不中断服务)
|
|
||||||
docker exec demo-nginx nginx -s reload
|
|
||||||
```
|
|
||||||
|
|
||||||
### 常见问题
|
|
||||||
|
|
||||||
#### 1. 502 Bad Gateway
|
|
||||||
- **原因**:后端服务未启动或无法连接
|
|
||||||
- **解决**:检查后端服务状态 `docker ps`
|
|
||||||
|
|
||||||
#### 2. 404 Not Found(前端路由)
|
|
||||||
- **原因**:缺少 `try_files` 配置
|
|
||||||
- **解决**:确保配置了 `try_files $uri $uri/ /index.html;`
|
|
||||||
|
|
||||||
#### 3. CORS 错误
|
|
||||||
- **原因**:代理头设置不正确
|
|
||||||
- **解决**:检查 `proxy_set_header` 配置
|
|
||||||
|
|
||||||
## 🧪 测试
|
|
||||||
|
|
||||||
### 测试前端访问
|
|
||||||
```bash
|
|
||||||
curl http://localhost/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试 API 代理
|
|
||||||
```bash
|
|
||||||
curl http://localhost/api/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 测试健康检查
|
|
||||||
```bash
|
|
||||||
curl http://localhost/health
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 性能优化
|
|
||||||
|
|
||||||
### 1. 启用 HTTP/2
|
|
||||||
```nginx
|
|
||||||
listen 443 ssl http2;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 增加缓存
|
|
||||||
```nginx
|
|
||||||
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api_cache:10m;
|
|
||||||
location /api/ {
|
|
||||||
proxy_cache api_cache;
|
|
||||||
proxy_cache_valid 200 5m;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 限制请求速率
|
|
||||||
```nginx
|
|
||||||
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
|
|
||||||
location /api/ {
|
|
||||||
limit_req zone=api_limit burst=20;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔐 安全建议
|
|
||||||
|
|
||||||
1. **隐藏 Nginx 版本**
|
|
||||||
```nginx
|
|
||||||
server_tokens off;
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **限制请求大小**
|
|
||||||
```nginx
|
|
||||||
client_max_body_size 100M;
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **使用 HTTPS**
|
|
||||||
- 配置 SSL 证书
|
|
||||||
- 启用 HSTS
|
|
||||||
|
|
||||||
4. **IP 白名单**(如需要)
|
|
||||||
```nginx
|
|
||||||
location /admin/ {
|
|
||||||
allow 192.168.1.0/24;
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
- [Nginx 官方文档](https://nginx.org/en/docs/)
|
|
||||||
- [Docker Compose 文档](https://docs.docker.com/compose/)
|
|
||||||
- [Vue.js 部署指南](https://router.vuejs.org/guide/essentials/history-mode.html)
|
|
||||||
|
|
||||||
## 🎯 下一步
|
|
||||||
|
|
||||||
1. ✅ 配置已完成
|
|
||||||
2. 构建前端:`cd frontend && npm run build`
|
|
||||||
3. 启动服务:`docker-compose up -d`
|
|
||||||
4. 访问应用:`http://localhost`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**注意**:首次部署前请确保:
|
|
||||||
- 前端已构建(`frontend/dist` 目录存在)
|
|
||||||
- 数据库已初始化
|
|
||||||
- 环境变量已配置
|
|
||||||
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
# 🔗 Ngrok 内网穿透配置完成
|
|
||||||
|
|
||||||
## ✅ 已配置的穿透地址
|
|
||||||
|
|
||||||
**Ngrok 穿透 URL**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
|
|
||||||
## 📋 配置更新总结
|
|
||||||
|
|
||||||
### 1. Nginx 配置 ✅
|
|
||||||
- ✅ 已添加 `server_name` 支持 ngrok 域名
|
|
||||||
- ✅ CORS 配置已优化,支持动态来源
|
|
||||||
- ✅ 已配置反向代理,所有 `/api/` 请求自动转发到后端
|
|
||||||
|
|
||||||
**文件**: `nginx/nginx.conf`
|
|
||||||
```nginx
|
|
||||||
server_name localhost curtly-aphorismatic-ginger.ngrok-free.dev;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 前端 API 配置 ✅
|
|
||||||
- ✅ API 请求自动检测当前域名
|
|
||||||
- ✅ 通过 ngrok 访问时使用相对路径 `/api`(自动适配当前域名)
|
|
||||||
- ✅ 本地开发时仍使用 `http://localhost:8080/api`
|
|
||||||
|
|
||||||
**文件**: `frontend/src/api/request.js`
|
|
||||||
|
|
||||||
### 3. 支付宝回调配置 ✅
|
|
||||||
- ✅ 通知地址:`https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify`
|
|
||||||
- ✅ 返回地址:`https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return`
|
|
||||||
|
|
||||||
**文件**: `src/main/resources/application-dev.properties`
|
|
||||||
|
|
||||||
### 4. 后端 CORS 配置 ✅
|
|
||||||
- ✅ 已配置支持 `*.ngrok-free.app` 域名模式
|
|
||||||
- ✅ 支持所有 ngrok 子域名
|
|
||||||
|
|
||||||
**文件**: `src/main/java/com/example/demo/config/SecurityConfig.java`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 使用方法
|
|
||||||
|
|
||||||
### 1. 启动服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用 Docker Compose(推荐)
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# 或直接启动后端
|
|
||||||
java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 启动 Ngrok
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 穿透 Nginx 的 80 端口
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
**注意**: Ngrok 应该指向 **80 端口**(Nginx),而不是 8080(后端)
|
|
||||||
|
|
||||||
### 3. 访问应用
|
|
||||||
|
|
||||||
通过 ngrok 地址访问:
|
|
||||||
- 🌐 **前端**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
- 🔗 **API**: `https://curtly-aphorismatic-ginger.ngrok-free.dev/api`
|
|
||||||
- 🏥 **健康检查**: `https://curtly-aphorismatic-ginger.ngrok-free.dev/health`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 配置说明
|
|
||||||
|
|
||||||
### 端口穿透
|
|
||||||
|
|
||||||
**只需要穿透 80 端口**(Nginx)
|
|
||||||
- ✅ Nginx 会处理所有前端请求
|
|
||||||
- ✅ Nginx 会自动将 `/api/` 请求代理到后端(内部访问)
|
|
||||||
- ❌ 不需要穿透 8080 端口(后端)
|
|
||||||
- ❌ 不需要穿透 3306 端口(MySQL)
|
|
||||||
|
|
||||||
### 请求流程
|
|
||||||
|
|
||||||
```
|
|
||||||
外网用户
|
|
||||||
↓
|
|
||||||
https://curtly-aphorismatic-ginger.ngrok-free.dev (Ngrok)
|
|
||||||
↓
|
|
||||||
localhost:80 (Nginx)
|
|
||||||
├─ / → 前端静态文件
|
|
||||||
└─ /api/ → proxy_pass → backend:8080 (内部 Docker 网络)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 测试验证
|
|
||||||
|
|
||||||
### 1. 测试前端访问
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 测试 API 代理
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/api/health
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 测试健康检查
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 注意事项
|
|
||||||
|
|
||||||
### 1. Ngrok 地址可能变化
|
|
||||||
- 免费版 ngrok 每次重启地址会变化
|
|
||||||
- 如果地址变化,需要更新:
|
|
||||||
1. `nginx/nginx.conf` 中的 `server_name`
|
|
||||||
2. `application-dev.properties` 中的 `alipay.notify-url` 和 `alipay.return-url`
|
|
||||||
|
|
||||||
### 2. Ngrok 警告页面
|
|
||||||
- 免费版 ngrok 会在浏览器显示警告页面
|
|
||||||
- 可以点击 "Visit Site" 继续访问
|
|
||||||
- 付费版可以移除警告
|
|
||||||
|
|
||||||
### 3. HTTPS 证书
|
|
||||||
- Ngrok 自动提供 HTTPS 证书
|
|
||||||
- 无需额外配置 SSL
|
|
||||||
- 确保使用 `https://` 协议访问
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 更新配置(如果 Ngrok 地址变化)
|
|
||||||
|
|
||||||
如果 ngrok 地址变化为 `https://new-address.ngrok-free.dev`:
|
|
||||||
|
|
||||||
### 1. 更新 Nginx 配置
|
|
||||||
```nginx
|
|
||||||
server_name localhost new-address.ngrok-free.dev;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 更新支付宝回调地址
|
|
||||||
```properties
|
|
||||||
alipay.notify-url=https://new-address.ngrok-free.dev/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://new-address.ngrok-free.dev/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 重新加载配置
|
|
||||||
```bash
|
|
||||||
# Nginx 配置重新加载
|
|
||||||
docker exec demo-nginx nginx -s reload
|
|
||||||
|
|
||||||
# 或重启服务
|
|
||||||
docker-compose restart nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 当前配置状态
|
|
||||||
|
|
||||||
| 配置项 | 状态 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| Nginx server_name | ✅ | 已配置 ngrok 域名 |
|
|
||||||
| 前端 API 基础路径 | ✅ | 自动适配当前域名 |
|
|
||||||
| 支付宝回调地址 | ✅ | 已配置 ngrok URL |
|
|
||||||
| 后端 CORS | ✅ | 支持 ngrok 域名模式 |
|
|
||||||
| 端口穿透 | ✅ | 只需穿透 80 端口 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 快速检查清单
|
|
||||||
|
|
||||||
- [x] ✅ Nginx 配置已更新 server_name
|
|
||||||
- [x] ✅ 前端 API 配置支持相对路径
|
|
||||||
- [x] ✅ 支付宝回调地址已配置
|
|
||||||
- [x] ✅ 后端 CORS 已支持 ngrok 域名
|
|
||||||
- [ ] ⚠️ Ngrok 服务正在运行并指向 80 端口
|
|
||||||
- [ ] ⚠️ 已测试前端访问
|
|
||||||
- [ ] ⚠️ 已测试 API 代理
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**配置完成!可以通过 `https://curtly-aphorismatic-ginger.ngrok-free.dev` 访问应用了!** 🎉
|
|
||||||
|
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
# 🚀 Ngrok 内网穿透部署完整指南
|
|
||||||
|
|
||||||
## 📋 当前配置
|
|
||||||
|
|
||||||
**Ngrok 穿透地址**: `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
**穿透端口**: `80` (Nginx)
|
|
||||||
|
|
||||||
## ✅ 已完成的配置
|
|
||||||
|
|
||||||
### 1. Nginx 反向代理配置 ✅
|
|
||||||
- ✅ `server_name` 已配置支持 ngrok 域名
|
|
||||||
- ✅ 前端静态文件服务
|
|
||||||
- ✅ API 代理到后端(`/api/` → `backend:8080`)
|
|
||||||
- ✅ CORS 配置已优化
|
|
||||||
|
|
||||||
### 2. 前端 API 自动适配 ✅
|
|
||||||
- ✅ 自动检测当前访问域名
|
|
||||||
- ✅ 通过 ngrok 访问:使用相对路径 `/api`
|
|
||||||
- ✅ 本地开发:使用 `http://localhost:8080/api`
|
|
||||||
|
|
||||||
### 3. 支付宝回调地址 ✅
|
|
||||||
- ✅ 通知地址:`https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify`
|
|
||||||
- ✅ 返回地址:`https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return`
|
|
||||||
|
|
||||||
### 4. 后端 CORS 配置 ✅
|
|
||||||
- ✅ 支持 `*.ngrok-free.app` 域名模式
|
|
||||||
- ✅ 支持所有 ngrok 子域名
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 部署步骤
|
|
||||||
|
|
||||||
### 步骤 1: 构建前端
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
**重要**: 确保 `frontend/dist` 目录存在且包含构建产物。
|
|
||||||
|
|
||||||
### 步骤 2: 启动 Docker 服务
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 启动所有服务(MySQL、后端、Nginx)
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# 查看服务状态
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# 查看日志
|
|
||||||
docker-compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### 步骤 3: 启动 Ngrok(穿透 80 端口)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 确保指向 Nginx 的 80 端口
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
**关键提示**:
|
|
||||||
- ✅ 正确:`ngrok http 80`(Nginx 端口)
|
|
||||||
- ❌ 错误:`ngrok http 8080`(后端端口,不需要)
|
|
||||||
|
|
||||||
### 步骤 4: 验证访问
|
|
||||||
|
|
||||||
访问 `https://curtly-aphorismatic-ginger.ngrok-free.dev` 测试:
|
|
||||||
|
|
||||||
1. **前端页面**: 应能正常加载
|
|
||||||
2. **API 请求**: 应能正常响应(通过 `/api/` 路径)
|
|
||||||
3. **健康检查**: `https://curtly-aphorismatic-ginger.ngrok-free.dev/health`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 验证清单
|
|
||||||
|
|
||||||
### ✅ 服务状态检查
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查容器状态
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# 应该看到:
|
|
||||||
# - demo-mysql (running)
|
|
||||||
# - demo-backend (running)
|
|
||||||
# - demo-nginx (running)
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ Nginx 配置验证
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试 Nginx 配置语法
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
|
|
||||||
# 应该输出:
|
|
||||||
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
|
||||||
# nginx: configuration file /etc/nginx/nginx.conf test is successful
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ 端口检查
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查 80 端口是否被 Nginx 监听
|
|
||||||
netstat -an | findstr :80
|
|
||||||
|
|
||||||
# 或使用 PowerShell
|
|
||||||
Get-NetTCPConnection -LocalPort 80 -ErrorAction SilentlyContinue
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ Ngrok 隧道检查
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 检查 ngrok 进程
|
|
||||||
Get-Process -Name ngrok -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
# 访问 ngrok 控制面板
|
|
||||||
# 浏览器打开: http://127.0.0.1:4040
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 功能测试
|
|
||||||
|
|
||||||
### 1. 测试前端访问
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在浏览器中访问
|
|
||||||
https://curtly-aphorismatic-ginger.ngrok-free.dev
|
|
||||||
|
|
||||||
# 或使用 curl
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 测试 API 代理
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 测试 API 请求(应该通过 Nginx 代理到后端)
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/api/health
|
|
||||||
|
|
||||||
# 测试登录 API
|
|
||||||
curl -X POST https://curtly-aphorismatic-ginger.ngrok-free.dev/api/auth/login \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"username":"test","password":"test"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 测试健康检查
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl https://curtly-aphorismatic-ginger.ngrok-free.dev/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 常见问题
|
|
||||||
|
|
||||||
### 1. Ngrok 显示 "Tunnel not found"
|
|
||||||
**原因**: Ngrok 没有运行或端口错误
|
|
||||||
**解决**:
|
|
||||||
```bash
|
|
||||||
# 检查 ngrok 是否运行
|
|
||||||
Get-Process -Name ngrok
|
|
||||||
|
|
||||||
# 确保穿透的是 80 端口
|
|
||||||
ngrok http 80
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 502 Bad Gateway
|
|
||||||
**原因**: 后端服务未启动或无法连接
|
|
||||||
**解决**:
|
|
||||||
```bash
|
|
||||||
# 检查后端服务状态
|
|
||||||
docker-compose logs backend
|
|
||||||
|
|
||||||
# 重启后端服务
|
|
||||||
docker-compose restart backend
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 前端页面显示但 API 请求失败
|
|
||||||
**原因**: API 代理配置问题
|
|
||||||
**解决**:
|
|
||||||
```bash
|
|
||||||
# 检查 Nginx 配置
|
|
||||||
docker exec demo-nginx nginx -t
|
|
||||||
|
|
||||||
# 检查 Nginx 日志
|
|
||||||
docker-compose logs nginx
|
|
||||||
|
|
||||||
# 确认前端使用的是相对路径 /api,而不是绝对路径
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. CORS 错误
|
|
||||||
**原因**: CORS 配置问题
|
|
||||||
**解决**:
|
|
||||||
- 检查后端 CORS 配置是否包含 ngrok 域名模式
|
|
||||||
- 检查 Nginx CORS 头设置
|
|
||||||
- 确认请求使用正确的域名(ngrok 地址)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 请求流程图
|
|
||||||
|
|
||||||
```
|
|
||||||
外部用户
|
|
||||||
↓
|
|
||||||
https://curtly-aphorismatic-ginger.ngrok-free.dev (Ngrok HTTPS)
|
|
||||||
↓
|
|
||||||
localhost:80 (Nginx - 唯一需要穿透的端口)
|
|
||||||
├─ GET / → 返回前端静态文件 (frontend/dist/index.html)
|
|
||||||
├─ GET /api/* → proxy_pass → backend:8080 (内部 Docker 网络)
|
|
||||||
└─ GET /health → 返回健康检查
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 如果 Ngrok 地址变化
|
|
||||||
|
|
||||||
如果 ngrok 地址变为 `https://new-address.ngrok-free.dev`:
|
|
||||||
|
|
||||||
### 1. 更新 Nginx 配置
|
|
||||||
```bash
|
|
||||||
# 编辑 nginx/nginx.conf
|
|
||||||
# 修改 server_name 行:
|
|
||||||
server_name localhost new-address.ngrok-free.dev;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 更新支付宝回调地址
|
|
||||||
```bash
|
|
||||||
# 编辑 src/main/resources/application-dev.properties
|
|
||||||
alipay.notify-url=https://new-address.ngrok-free.dev/api/payments/alipay/notify
|
|
||||||
alipay.return-url=https://new-address.ngrok-free.dev/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 重新加载配置
|
|
||||||
```bash
|
|
||||||
# 重新加载 Nginx(不中断服务)
|
|
||||||
docker exec demo-nginx nginx -s reload
|
|
||||||
|
|
||||||
# 或重启服务
|
|
||||||
docker-compose restart nginx backend
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 当前配置状态
|
|
||||||
|
|
||||||
| 组件 | 配置项 | 状态 | 值 |
|
|
||||||
|------|--------|------|-----|
|
|
||||||
| Nginx | server_name | ✅ | localhost, curtly-aphorismatic-ginger.ngrok-free.dev |
|
|
||||||
| Nginx | 监听端口 | ✅ | 80 |
|
|
||||||
| Nginx | API 代理 | ✅ | /api/ → backend:8080 |
|
|
||||||
| 前端 | API baseURL | ✅ | 自动检测(/api 或 http://localhost:8080/api) |
|
|
||||||
| 后端 | CORS origins | ✅ | *.ngrok-free.app |
|
|
||||||
| 支付宝 | notify-url | ✅ | https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/notify |
|
|
||||||
| 支付宝 | return-url | ✅ | https://curtly-aphorismatic-ginger.ngrok-free.dev/api/payments/alipay/return |
|
|
||||||
| Ngrok | 穿透端口 | ✅ | 80 (Nginx) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 下一步操作
|
|
||||||
|
|
||||||
1. ✅ **构建前端**: `cd frontend && npm run build`
|
|
||||||
2. ✅ **启动服务**: `docker-compose up -d --build`
|
|
||||||
3. ✅ **启动 Ngrok**: `ngrok http 80`
|
|
||||||
4. ✅ **测试访问**: 浏览器打开 `https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**配置已完成!所有服务已准备好通过 ngrok 访问!** 🎉
|
|
||||||
|
|
||||||
@@ -1,259 +0,0 @@
|
|||||||
# 支付功能模块配置清单
|
|
||||||
|
|
||||||
## 一、已配置项 ✅
|
|
||||||
|
|
||||||
### 1. 支付宝基础配置(开发环境)
|
|
||||||
- ✅ `alipay.app-id` - 应用ID
|
|
||||||
- ✅ `alipay.private-key` - 应用私钥
|
|
||||||
- ✅ `alipay.public-key` - 支付宝公钥
|
|
||||||
- ✅ `alipay.gateway-url` - 网关地址(沙箱)
|
|
||||||
- ✅ `alipay.charset` - 字符集(UTF-8)
|
|
||||||
- ✅ `alipay.sign-type` - 签名方式(RSA2)
|
|
||||||
- ✅ `alipay.notify-url` - 异步通知地址(当前使用ngrok)
|
|
||||||
- ✅ `alipay.return-url` - 同步返回地址(当前使用ngrok)
|
|
||||||
|
|
||||||
### 2. 后端代码实现
|
|
||||||
- ✅ 支付宝服务(AlipayService)
|
|
||||||
- ✅ 支付API控制器(PaymentApiController)
|
|
||||||
- ✅ 支付服务(PaymentService)
|
|
||||||
- ✅ 支付数据模型(Payment, PaymentStatus, PaymentMethod)
|
|
||||||
|
|
||||||
### 3. 前端代码实现
|
|
||||||
- ✅ 支付API封装(payments.js)
|
|
||||||
- ✅ 支付模态框组件(PaymentModal.vue)
|
|
||||||
- ✅ 订阅页面(Subscription.vue)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 二、需要检查/更新项 ⚠️
|
|
||||||
|
|
||||||
### 1. 支付宝回调地址配置
|
|
||||||
|
|
||||||
**当前状态:**
|
|
||||||
- 开发环境使用 ngrok 地址:`https://curtly-aphorismatic-ginger.ngrok-free.dev`
|
|
||||||
|
|
||||||
**需要操作:**
|
|
||||||
- [ ] **如果 ngrok 地址已过期**,需要:
|
|
||||||
1. 重新运行 `ngrok http 8080` 获取新地址
|
|
||||||
2. 更新 `application-dev.properties` 中的 `alipay.notify-url` 和 `alipay.return-url`
|
|
||||||
3. 在支付宝开放平台配置新的回调地址
|
|
||||||
|
|
||||||
- [ ] **如果部署到生产环境**,需要:
|
|
||||||
1. 使用正式域名替换 ngrok 地址
|
|
||||||
2. 确保回调地址是 HTTPS(支付宝要求)
|
|
||||||
3. 在支付宝开放平台配置生产环境的回调地址
|
|
||||||
|
|
||||||
**配置文件位置:**
|
|
||||||
```
|
|
||||||
demo/src/main/resources/application-dev.properties (开发环境)
|
|
||||||
demo/src/main/resources/application-prod.properties (生产环境)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 支付宝开放平台配置
|
|
||||||
|
|
||||||
**需要在支付宝开放平台配置:**
|
|
||||||
|
|
||||||
- [ ] **应用回调地址**
|
|
||||||
- 登录支付宝开放平台:https://open.alipay.com
|
|
||||||
- 进入"我的应用" → 选择应用
|
|
||||||
- 配置"应用网关"和"回调地址"
|
|
||||||
- 添加 `notify-url` 和 `return-url`
|
|
||||||
|
|
||||||
- [ ] **公钥配置**
|
|
||||||
- 确认应用公钥已上传到支付宝平台
|
|
||||||
- 确认支付宝公钥已配置在 `alipay.public-key`
|
|
||||||
|
|
||||||
- [ ] **沙箱测试账号**
|
|
||||||
- 获取沙箱买家账号和密码
|
|
||||||
- 用于测试支付流程
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 生产环境配置(如需上线)
|
|
||||||
|
|
||||||
**需要配置环境变量或更新配置文件:**
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 生产环境支付宝配置
|
|
||||||
alipay.app-id=${ALIPAY_APP_ID} # 需要在环境变量中配置
|
|
||||||
alipay.private-key=${ALIPAY_PRIVATE_KEY} # 需要在环境变量中配置
|
|
||||||
alipay.public-key=${ALIPAY_PUBLIC_KEY} # 需要在环境变量中配置
|
|
||||||
alipay.gateway-url=https://openapi.alipay.com/gateway.do
|
|
||||||
alipay.notify-url=${ALIPAY_NOTIFY_URL} # 需要配置正式域名
|
|
||||||
alipay.return-url=${ALIPAY_RETURN_URL} # 需要配置正式域名
|
|
||||||
```
|
|
||||||
|
|
||||||
**操作步骤:**
|
|
||||||
1. [ ] 在服务器环境变量中设置上述变量
|
|
||||||
2. [ ] 或创建 `application-prod.properties` 并填写实际值
|
|
||||||
3. [ ] 确保使用正式环境的 APPID 和密钥(不是沙箱)
|
|
||||||
4. [ ] 确保回调地址使用 HTTPS 协议
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. PayPal 配置(如果使用)
|
|
||||||
|
|
||||||
**当前状态:** PayPal 配置存在但可能需要更新
|
|
||||||
|
|
||||||
**需要配置项:**
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# PayPal配置(在 application-dev.properties 或 application-prod.properties)
|
|
||||||
paypal.client-id=你的PayPal客户端ID
|
|
||||||
paypal.client-secret=你的PayPal客户端密钥
|
|
||||||
paypal.mode=sandbox # 或 live(生产环境)
|
|
||||||
paypal.return-url=http://yourdomain.com/api/payments/paypal/return
|
|
||||||
paypal.cancel-url=http://yourdomain.com/api/payments/paypal/cancel
|
|
||||||
```
|
|
||||||
|
|
||||||
**操作步骤:**
|
|
||||||
1. [ ] 如果使用 PayPal,需要:
|
|
||||||
- 在 PayPal 开发者控制台创建应用
|
|
||||||
- 获取 Client ID 和 Client Secret
|
|
||||||
- 配置回调地址
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 数据库表检查
|
|
||||||
|
|
||||||
**需要确认以下表已创建:**
|
|
||||||
|
|
||||||
- [ ] `payments` 表
|
|
||||||
- [ ] `orders` 表(支付成功后创建订单)
|
|
||||||
- [ ] 相关外键和索引
|
|
||||||
|
|
||||||
**检查方法:**
|
|
||||||
```sql
|
|
||||||
SHOW TABLES LIKE 'payments';
|
|
||||||
SHOW TABLES LIKE 'orders';
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. 网络安全配置
|
|
||||||
|
|
||||||
**回调地址安全要求:**
|
|
||||||
|
|
||||||
- [ ] **开发环境:**
|
|
||||||
- 确保 ngrok 服务运行
|
|
||||||
- 回调地址必须是公网可访问的 HTTPS
|
|
||||||
|
|
||||||
- [ ] **生产环境:**
|
|
||||||
- 配置 SSL 证书
|
|
||||||
- 确保回调地址使用 HTTPS
|
|
||||||
- 配置防火墙规则,允许支付宝服务器访问回调接口
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 7. 支付测试配置
|
|
||||||
|
|
||||||
**测试前需要确认:**
|
|
||||||
|
|
||||||
- [ ] 支付宝沙箱账号已配置
|
|
||||||
- [ ] 沙箱买家账号可用于测试支付
|
|
||||||
- [ ] 回调地址在支付宝平台已配置
|
|
||||||
- [ ] 本地或服务器可以接收到支付宝回调
|
|
||||||
|
|
||||||
**测试步骤:**
|
|
||||||
1. [ ] 创建测试支付订单
|
|
||||||
2. [ ] 使用沙箱账号扫码支付
|
|
||||||
3. [ ] 验证异步通知是否接收
|
|
||||||
4. [ ] 验证支付状态是否正确更新
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 三、配置优先级
|
|
||||||
|
|
||||||
### 🔴 紧急(必须配置)
|
|
||||||
1. **支付宝回调地址** - 如果 ngrok 地址已过期,需要立即更新
|
|
||||||
2. **支付宝开放平台回调配置** - 必须配置才能接收支付通知
|
|
||||||
|
|
||||||
### 🟡 重要(建议配置)
|
|
||||||
3. **生产环境配置** - 如需上线必须配置
|
|
||||||
4. **数据库表检查** - 确保表结构完整
|
|
||||||
|
|
||||||
### 🟢 可选(按需配置)
|
|
||||||
5. **PayPal 配置** - 如果使用 PayPal 支付
|
|
||||||
6. **支付测试环境** - 用于测试支付功能
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 四、快速检查命令
|
|
||||||
|
|
||||||
### 检查配置文件是否存在
|
|
||||||
```bash
|
|
||||||
# Windows PowerShell
|
|
||||||
Test-Path demo/src/main/resources/application-dev.properties
|
|
||||||
Test-Path demo/src/main/resources/application-prod.properties
|
|
||||||
```
|
|
||||||
|
|
||||||
### 检查支付宝配置是否完整
|
|
||||||
查看配置文件中的以下项是否都已填写:
|
|
||||||
- `alipay.app-id`
|
|
||||||
- `alipay.private-key`
|
|
||||||
- `alipay.public-key`
|
|
||||||
- `alipay.gateway-url`
|
|
||||||
- `alipay.notify-url`
|
|
||||||
- `alipay.return-url`
|
|
||||||
|
|
||||||
### 测试回调地址可访问性
|
|
||||||
```bash
|
|
||||||
# 测试 notify-url 是否可访问
|
|
||||||
curl -X POST https://your-notify-url/api/payments/alipay/notify
|
|
||||||
|
|
||||||
# 测试 return-url 是否可访问
|
|
||||||
curl https://your-return-url/api/payments/alipay/return
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 五、常见问题
|
|
||||||
|
|
||||||
### Q1: ngrok 地址已过期怎么办?
|
|
||||||
**A:**
|
|
||||||
1. 重新运行 `ngrok http 8080`
|
|
||||||
2. 获取新的 HTTPS 地址
|
|
||||||
3. 更新 `application-dev.properties` 中的回调地址
|
|
||||||
4. 在支付宝开放平台更新回调地址配置
|
|
||||||
|
|
||||||
### Q2: 生产环境如何配置回调地址?
|
|
||||||
**A:**
|
|
||||||
1. 使用正式域名(必须是 HTTPS)
|
|
||||||
2. 在支付宝开放平台配置生产环境回调地址
|
|
||||||
3. 确保服务器防火墙允许支付宝 IP 访问
|
|
||||||
|
|
||||||
### Q3: 如何验证配置是否正确?
|
|
||||||
**A:**
|
|
||||||
1. 创建测试支付订单
|
|
||||||
2. 使用沙箱账号支付
|
|
||||||
3. 检查日志是否收到支付宝回调
|
|
||||||
4. 验证支付状态是否正确更新
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 六、下一步操作建议
|
|
||||||
|
|
||||||
根据当前配置状态,建议按以下顺序操作:
|
|
||||||
|
|
||||||
1. ✅ **检查 ngrok 地址是否有效**
|
|
||||||
- 如果无效,更新回调地址配置
|
|
||||||
|
|
||||||
2. ✅ **验证支付宝开放平台配置**
|
|
||||||
- 确认回调地址已在平台配置
|
|
||||||
- 确认公钥配置正确
|
|
||||||
|
|
||||||
3. ✅ **测试支付流程**
|
|
||||||
- 创建测试订单
|
|
||||||
- 完成支付测试
|
|
||||||
- 验证回调接收
|
|
||||||
|
|
||||||
4. ✅ **准备生产环境配置**
|
|
||||||
- 配置生产环境变量
|
|
||||||
- 申请正式支付宝应用(如需)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**最后更新:** 请根据实际部署环境调整上述配置项。
|
|
||||||
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
# 积分冻结系统
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
积分冻结系统实现了任务提交时冻结积分、任务完成时扣除、任务失败时返还的完整积分管理流程。
|
|
||||||
|
|
||||||
## 系统特性
|
|
||||||
|
|
||||||
### 🔒 **积分状态管理**
|
|
||||||
- **正常积分**: 用户可以自由使用的积分
|
|
||||||
- **冻结积分**: 任务提交时临时冻结的积分,不可使用
|
|
||||||
- **可用积分**: 正常积分 - 冻结积分
|
|
||||||
|
|
||||||
### 📋 **冻结记录管理**
|
|
||||||
- 完整的积分冻结记录追踪
|
|
||||||
- 支持多种冻结状态:已冻结、已扣除、已返还、已过期
|
|
||||||
- 自动处理过期冻结记录(24小时)
|
|
||||||
|
|
||||||
### ⚡ **自动积分处理**
|
|
||||||
- **任务提交**: 自动冻结相应积分
|
|
||||||
- **任务完成**: 自动扣除冻结积分
|
|
||||||
- **任务失败**: 自动返还冻结积分
|
|
||||||
- **任务取消**: 自动返还冻结积分
|
|
||||||
- **任务超时**: 自动返还冻结积分
|
|
||||||
|
|
||||||
## 数据库结构
|
|
||||||
|
|
||||||
### 用户表修改
|
|
||||||
```sql
|
|
||||||
-- 添加冻结积分字段
|
|
||||||
ALTER TABLE users ADD COLUMN frozen_points INT NOT NULL DEFAULT 0 COMMENT '冻结积分';
|
|
||||||
```
|
|
||||||
|
|
||||||
### 积分冻结记录表
|
|
||||||
```sql
|
|
||||||
CREATE TABLE points_freeze_records (
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
|
||||||
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
|
||||||
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO') NOT NULL COMMENT '任务类型',
|
|
||||||
freeze_points INT NOT NULL COMMENT '冻结的积分数量',
|
|
||||||
status ENUM('FROZEN', 'DEDUCTED', 'RETURNED', 'EXPIRED') NOT NULL DEFAULT 'FROZEN' COMMENT '冻结状态',
|
|
||||||
freeze_reason VARCHAR(200) COMMENT '冻结原因',
|
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
||||||
completed_at DATETIME COMMENT '完成时间'
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
## API接口
|
|
||||||
|
|
||||||
### 获取积分信息
|
|
||||||
```
|
|
||||||
GET /api/points/info
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
|
|
||||||
Response:
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"totalPoints": 1000,
|
|
||||||
"frozenPoints": 80,
|
|
||||||
"availablePoints": 920
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取冻结记录
|
|
||||||
```
|
|
||||||
GET /api/points/freeze-records
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
|
|
||||||
Response:
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"username": "user1",
|
|
||||||
"taskId": "txt2vid_123",
|
|
||||||
"taskType": "TEXT_TO_VIDEO",
|
|
||||||
"freezePoints": 80,
|
|
||||||
"status": "FROZEN",
|
|
||||||
"freezeReason": "任务提交冻结积分 - 文生视频",
|
|
||||||
"createdAt": "2024-01-01T10:00:00",
|
|
||||||
"updatedAt": "2024-01-01T10:00:00"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 处理过期记录(管理员)
|
|
||||||
```
|
|
||||||
POST /api/points/process-expired
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
|
|
||||||
Response:
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "处理过期记录完成",
|
|
||||||
"processedCount": 5
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 服务方法
|
|
||||||
|
|
||||||
### UserService 积分冻结方法
|
|
||||||
|
|
||||||
#### 冻结积分
|
|
||||||
```java
|
|
||||||
PointsFreezeRecord freezePoints(String username, String taskId,
|
|
||||||
PointsFreezeRecord.TaskType taskType, Integer points, String reason)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 扣除冻结积分(任务完成)
|
|
||||||
```java
|
|
||||||
void deductFrozenPoints(String taskId)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 返还冻结积分(任务失败)
|
|
||||||
```java
|
|
||||||
void returnFrozenPoints(String taskId)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 获取可用积分
|
|
||||||
```java
|
|
||||||
Integer getAvailablePoints(String username)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 获取冻结积分
|
|
||||||
```java
|
|
||||||
Integer getFrozenPoints(String username)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 获取冻结记录
|
|
||||||
```java
|
|
||||||
List<PointsFreezeRecord> getPointsFreezeRecords(String username)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 处理过期记录
|
|
||||||
```java
|
|
||||||
int processExpiredFrozenRecords()
|
|
||||||
```
|
|
||||||
|
|
||||||
## 积分计算规则
|
|
||||||
|
|
||||||
### 默认积分消耗
|
|
||||||
- **文生视频**: 80积分
|
|
||||||
- **图生视频**: 90积分
|
|
||||||
|
|
||||||
### 积分检查逻辑
|
|
||||||
1. 检查用户可用积分是否足够
|
|
||||||
2. 冻结相应积分
|
|
||||||
3. 创建冻结记录
|
|
||||||
4. 添加到任务队列
|
|
||||||
|
|
||||||
## 定时任务
|
|
||||||
|
|
||||||
### 过期记录处理
|
|
||||||
- **频率**: 每小时执行一次
|
|
||||||
- **功能**: 自动处理超过24小时的冻结记录
|
|
||||||
- **处理方式**: 返还冻结积分,更新记录状态为"已过期"
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
### 1. 任务提交流程
|
|
||||||
```
|
|
||||||
用户提交任务 → 检查可用积分 → 冻结积分 → 创建冻结记录 → 添加到队列
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 任务完成流程
|
|
||||||
```
|
|
||||||
任务完成 → 扣除冻结积分 → 更新冻结记录状态 → 更新原始任务状态
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 任务失败流程
|
|
||||||
```
|
|
||||||
任务失败 → 返还冻结积分 → 更新冻结记录状态 → 更新原始任务状态
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 任务取消流程
|
|
||||||
```
|
|
||||||
用户取消任务 → 返还冻结积分 → 更新冻结记录状态 → 更新原始任务状态
|
|
||||||
```
|
|
||||||
|
|
||||||
## 异常处理
|
|
||||||
|
|
||||||
### 积分不足
|
|
||||||
- 检查可用积分时如果不足,抛出异常
|
|
||||||
- 异常信息包含当前可用积分和所需积分
|
|
||||||
|
|
||||||
### 冻结记录不存在
|
|
||||||
- 扣除或返还积分时如果记录不存在,抛出异常
|
|
||||||
- 确保数据一致性
|
|
||||||
|
|
||||||
### 状态不正确
|
|
||||||
- 操作冻结记录时检查状态是否正确
|
|
||||||
- 防止重复操作
|
|
||||||
|
|
||||||
## 监控和日志
|
|
||||||
|
|
||||||
### 关键日志
|
|
||||||
- 积分冻结成功/失败
|
|
||||||
- 积分扣除成功/失败
|
|
||||||
- 积分返还成功/失败
|
|
||||||
- 过期记录处理
|
|
||||||
|
|
||||||
### 监控指标
|
|
||||||
- 冻结积分总量
|
|
||||||
- 过期记录数量
|
|
||||||
- 积分操作成功率
|
|
||||||
|
|
||||||
## 安全考虑
|
|
||||||
|
|
||||||
### 数据一致性
|
|
||||||
- 使用事务确保积分和记录状态一致
|
|
||||||
- 防止并发操作导致的数据不一致
|
|
||||||
|
|
||||||
### 权限控制
|
|
||||||
- 只有任务所有者可以操作相关积分
|
|
||||||
- 管理员可以处理过期记录
|
|
||||||
|
|
||||||
### 异常恢复
|
|
||||||
- 完善的异常处理机制
|
|
||||||
- 自动重试和恢复机制
|
|
||||||
|
|
||||||
## 扩展功能
|
|
||||||
|
|
||||||
### 未来可扩展的功能
|
|
||||||
1. **动态积分计算**: 根据任务参数动态计算所需积分
|
|
||||||
2. **积分优惠**: 会员等级影响积分消耗
|
|
||||||
3. **积分返还策略**: 不同失败原因的不同返还策略
|
|
||||||
4. **积分统计**: 详细的积分使用统计和分析
|
|
||||||
5. **积分预警**: 积分不足时的预警机制
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 前端集成示例
|
|
||||||
```javascript
|
|
||||||
// 获取用户积分信息
|
|
||||||
const getPointsInfo = async () => {
|
|
||||||
const response = await fetch('/api/points/info', {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
return data.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取冻结记录
|
|
||||||
const getFreezeRecords = async () => {
|
|
||||||
const response = await fetch('/api/points/freeze-records', {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
return data.data;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### 后端集成示例
|
|
||||||
```java
|
|
||||||
// 在任务创建时自动冻结积分
|
|
||||||
@Transactional
|
|
||||||
public TaskQueue addTextToVideoTask(String username, String taskId) {
|
|
||||||
// 计算所需积分
|
|
||||||
Integer requiredPoints = calculateRequiredPoints(TaskQueue.TaskType.TEXT_TO_VIDEO);
|
|
||||||
|
|
||||||
// 冻结积分
|
|
||||||
userService.freezePoints(username, taskId,
|
|
||||||
PointsFreezeRecord.TaskType.TEXT_TO_VIDEO, requiredPoints,
|
|
||||||
"任务提交冻结积分 - 文生视频");
|
|
||||||
|
|
||||||
// 添加到队列
|
|
||||||
return addTaskToQueue(username, taskId, TaskQueue.TaskType.TEXT_TO_VIDEO);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **积分检查**: 在冻结积分前必须检查可用积分是否足够
|
|
||||||
2. **状态管理**: 确保冻结记录状态与任务状态保持一致
|
|
||||||
3. **异常处理**: 完善的异常处理确保积分不会丢失
|
|
||||||
4. **定时清理**: 定期清理过期的冻结记录
|
|
||||||
5. **监控告警**: 监控积分冻结系统的运行状态
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -42,6 +42,10 @@ public class PasswordChecker {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
# 🚀 快速部署指南
|
|
||||||
|
|
||||||
本文档提供最精简的上线步骤,适合有经验的运维人员。
|
|
||||||
|
|
||||||
## 一、服务器准备(5分钟)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 安装Java 21
|
|
||||||
sudo apt update && sudo apt install -y openjdk-21-jdk
|
|
||||||
|
|
||||||
# 2. 安装MySQL 8.0
|
|
||||||
sudo apt install -y mysql-server
|
|
||||||
sudo mysql_secure_installation
|
|
||||||
|
|
||||||
# 3. 安装FFmpeg
|
|
||||||
sudo apt install -y ffmpeg
|
|
||||||
|
|
||||||
# 4. 安装Nginx
|
|
||||||
sudo apt install -y nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
## 二、数据库设置(2分钟)
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE DATABASE aigc_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
CREATE USER 'aigc_user'@'localhost' IDENTIFIED BY '强密码';
|
|
||||||
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_user'@'localhost';
|
|
||||||
FLUSH PRIVILEGES;
|
|
||||||
```
|
|
||||||
|
|
||||||
## 三、环境变量(3分钟)
|
|
||||||
|
|
||||||
创建 `/app/aigc-platform/config/.env`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export DB_URL="jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai"
|
|
||||||
export DB_USERNAME="aigc_user"
|
|
||||||
export DB_PASSWORD="数据库密码"
|
|
||||||
export JWT_SECRET="$(openssl rand -base64 64)"
|
|
||||||
export AI_API_KEY="你的API密钥"
|
|
||||||
export AI_IMAGE_API_KEY="你的API密钥"
|
|
||||||
export FFMPEG_PATH="/usr/bin/ffmpeg"
|
|
||||||
export TEMP_DIR="/app/aigc-platform/temp"
|
|
||||||
export UPLOAD_PATH="/app/aigc-platform/uploads"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 四、部署应用(5分钟)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. 创建目录
|
|
||||||
sudo mkdir -p /app/aigc-platform/{logs,uploads,temp,config}
|
|
||||||
sudo chown -R $USER:$USER /app/aigc-platform
|
|
||||||
|
|
||||||
# 2. 上传JAR文件
|
|
||||||
scp target/demo-0.0.1-SNAPSHOT.jar user@server:/app/aigc-platform/
|
|
||||||
|
|
||||||
# 3. 创建systemd服务
|
|
||||||
sudo nano /etc/systemd/system/aigc-platform.service
|
|
||||||
```
|
|
||||||
|
|
||||||
systemd服务内容:
|
|
||||||
```ini
|
|
||||||
[Unit]
|
|
||||||
Description=AIGC Platform
|
|
||||||
After=network.target mysql.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=your-user
|
|
||||||
WorkingDirectory=/app/aigc-platform
|
|
||||||
EnvironmentFile=/app/aigc-platform/config/.env
|
|
||||||
ExecStart=/usr/bin/java -jar -Xms1g -Xmx4g \
|
|
||||||
-Dspring.profiles.active=prod \
|
|
||||||
/app/aigc-platform/demo-0.0.1-SNAPSHOT.jar
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 4. 启动服务
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable aigc-platform
|
|
||||||
sudo systemctl start aigc-platform
|
|
||||||
```
|
|
||||||
|
|
||||||
## 五、Nginx配置(3分钟)
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name yourdomain.com;
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://localhost:8080;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /path/to/frontend/dist;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 六、SSL证书(2分钟)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install certbot python3-certbot-nginx
|
|
||||||
sudo certbot --nginx -d yourdomain.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## ✅ 检查清单
|
|
||||||
|
|
||||||
- [ ] 应用启动成功:`sudo systemctl status aigc-platform`
|
|
||||||
- [ ] 数据库连接正常:查看日志
|
|
||||||
- [ ] API可访问:`curl http://localhost:8080/api/health`
|
|
||||||
- [ ] 前端可访问:浏览器打开域名
|
|
||||||
- [ ] SSL证书有效:`https://yourdomain.com`
|
|
||||||
|
|
||||||
**总耗时:约20分钟**
|
|
||||||
|
|
||||||
详细配置请参考 `DEPLOYMENT_CHECKLIST.md`
|
|
||||||
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# 🚀 Nginx 反向代理快速启动指南
|
|
||||||
|
|
||||||
## 快速部署
|
|
||||||
|
|
||||||
### Windows (PowerShell)
|
|
||||||
```powershell
|
|
||||||
.\deploy.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Linux/Mac (Bash)
|
|
||||||
```bash
|
|
||||||
chmod +x deploy.sh
|
|
||||||
./deploy.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 手动部署
|
|
||||||
|
|
||||||
#### 1. 构建前端
|
|
||||||
```bash
|
|
||||||
cd frontend
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
cd ..
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 启动服务
|
|
||||||
```bash
|
|
||||||
docker-compose up -d --build
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. 访问应用
|
|
||||||
- 🌐 前端: http://localhost
|
|
||||||
- 🔗 API: http://localhost/api
|
|
||||||
|
|
||||||
## 📁 配置文件说明
|
|
||||||
|
|
||||||
- `nginx/nginx.conf` - Nginx 主配置文件
|
|
||||||
- `docker-compose.yml` - Docker Compose 编排文件
|
|
||||||
- `Dockerfile.backend` - 后端镜像构建文件
|
|
||||||
- `nginx/Dockerfile` - Nginx 镜像构建文件
|
|
||||||
|
|
||||||
## 🔧 常用命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看日志
|
|
||||||
docker-compose logs -f nginx
|
|
||||||
docker-compose logs -f backend
|
|
||||||
|
|
||||||
# 重启服务
|
|
||||||
docker-compose restart nginx
|
|
||||||
|
|
||||||
# 停止服务
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# 重新构建
|
|
||||||
docker-compose up -d --build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📖 详细文档
|
|
||||||
|
|
||||||
查看 `NGINX_REVERSE_PROXY_GUIDE.md` 获取完整配置说明。
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
313
demo/ROUTE_ANALYSIS.md
Normal file
313
demo/ROUTE_ANALYSIS.md
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
# 项目路由分析报告
|
||||||
|
|
||||||
|
## 统一前缀路由
|
||||||
|
|
||||||
|
### API 路由前缀
|
||||||
|
**主要前缀:`/api/`**
|
||||||
|
|
||||||
|
所有后端 REST API 接口统一使用 `/api/` 作为前缀。
|
||||||
|
|
||||||
|
## 详细路由分类
|
||||||
|
|
||||||
|
### 1. REST API 路由(`/api/`)
|
||||||
|
|
||||||
|
#### 认证授权模块
|
||||||
|
- `/api/auth/**` - 用户认证(登录、注册)
|
||||||
|
- `/api/verification/**` - 验证码服务
|
||||||
|
- `/api/email/**` - 邮件服务
|
||||||
|
- `/api/tencent/**` - 腾讯云服务集成
|
||||||
|
|
||||||
|
#### 视频生成模块
|
||||||
|
- `/api/text-to-video/**` - 文生视频
|
||||||
|
- `/api/image-to-video/**` - 图生视频
|
||||||
|
- `/api/storyboard-video/**` - 分镜视频
|
||||||
|
|
||||||
|
#### 用户作品模块
|
||||||
|
- `/api/works/**` - 用户作品管理
|
||||||
|
|
||||||
|
#### 支付订单模块
|
||||||
|
- `/api/payments/**` - 支付相关
|
||||||
|
- `/api/payments/alipay/**` - 支付宝支付
|
||||||
|
- `/api/orders/**` - 订单管理
|
||||||
|
|
||||||
|
#### 会员积分模块
|
||||||
|
- `/api/members/**` - 会员管理
|
||||||
|
- `/api/points/**` - 积分系统
|
||||||
|
|
||||||
|
#### 任务管理模块
|
||||||
|
- `/api/task-queue/**` - 任务队列
|
||||||
|
- `/api/task-status/**` - 任务状态
|
||||||
|
- `/api/cleanup/**` - 任务清理
|
||||||
|
|
||||||
|
#### 管理后台模块
|
||||||
|
- `/api/admin/**` - 管理员接口
|
||||||
|
- `/api/dashboard/**` - 数据仪表盘
|
||||||
|
- `/api/analytics/**` - 数据分析
|
||||||
|
|
||||||
|
#### 系统设置模块
|
||||||
|
- `/api/api-key/**` - API 密钥管理
|
||||||
|
- `/api/prompt/**` - 提示词优化
|
||||||
|
|
||||||
|
#### 测试诊断模块
|
||||||
|
- `/api/test/**` - 测试接口
|
||||||
|
- `/api/diagnostic/**` - 诊断接口
|
||||||
|
- `/api/polling/**` - 轮询测试
|
||||||
|
- `/api/polling-diagnostic/**` - 轮询诊断
|
||||||
|
- `/api/monitor/**` - 监控接口
|
||||||
|
|
||||||
|
#### 公共接口
|
||||||
|
- `/api/public/**` - 公共API(无需认证)
|
||||||
|
- `/api/health/**` - 健康检查接口
|
||||||
|
|
||||||
|
### 2. 页面路由(非 API)
|
||||||
|
|
||||||
|
#### 用户页面
|
||||||
|
- `/login` - 登录页面
|
||||||
|
- `/register` - 注册页面
|
||||||
|
- `/payment/**` - 支付页面
|
||||||
|
- `/orders/**` - 订单页面
|
||||||
|
|
||||||
|
#### 管理员页面
|
||||||
|
- `/settings/**` - 系统设置页面(管理员)
|
||||||
|
- `/users/**` - 用户管理页面(管理员)
|
||||||
|
|
||||||
|
#### 开发工具
|
||||||
|
- `/h2-console/**` - H2 数据库控制台(开发环境)
|
||||||
|
|
||||||
|
### 3. API 文档路由
|
||||||
|
|
||||||
|
- `/swagger-ui.html` - Swagger UI 主页
|
||||||
|
- `/swagger-ui/**` - Swagger UI 资源
|
||||||
|
- `/v3/api-docs/**` - OpenAPI 文档 JSON
|
||||||
|
- `/swagger-resources/**` - Swagger 资源
|
||||||
|
- `/webjars/**` - Web 资源库
|
||||||
|
|
||||||
|
### 4. 静态资源路由
|
||||||
|
|
||||||
|
- `/css/**` - CSS 样式文件
|
||||||
|
- `/js/**` - JavaScript 文件
|
||||||
|
- `/uploads/**` - 上传文件
|
||||||
|
|
||||||
|
## 路由代理配置
|
||||||
|
|
||||||
|
### Nginx 代理配置
|
||||||
|
|
||||||
|
#### 1. API 代理(推荐配置)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# API 代理到后端
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://172.22.0.1:8080/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 超时设置(视频生成可能需要较长时间)
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 900s;
|
||||||
|
proxy_read_timeout 900s;
|
||||||
|
|
||||||
|
# 支持大文件上传
|
||||||
|
client_max_body_size 600M;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Swagger UI 代理(可选,用于生产环境)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# API 文档代理
|
||||||
|
location ~ ^/(swagger-ui|v3/api-docs|swagger-resources|webjars) {
|
||||||
|
proxy_pass http://172.22.0.1:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 上传文件代理
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# 上传文件代理
|
||||||
|
location /uploads/ {
|
||||||
|
proxy_pass http://172.22.0.1:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 缓存设置
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. WebSocket 支持(如果需要)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://172.22.0.1:8080;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Apache 代理配置(如果使用 Apache)
|
||||||
|
|
||||||
|
```apache
|
||||||
|
# 启用代理模块
|
||||||
|
LoadModule proxy_module modules/mod_proxy.so
|
||||||
|
LoadModule proxy_http_module modules/mod_proxy_http.so
|
||||||
|
|
||||||
|
# API 代理
|
||||||
|
ProxyPass /api/ http://172.22.0.1:8080/
|
||||||
|
ProxyPassReverse /api/ http://172.22.0.1:8080/
|
||||||
|
|
||||||
|
# Swagger UI 代理
|
||||||
|
ProxyPass /swagger-ui/ http://172.22.0.1:8080/swagger-ui/
|
||||||
|
ProxyPassReverse /swagger-ui/ http://172.22.0.1:8080/swagger-ui/
|
||||||
|
|
||||||
|
ProxyPass /v3/api-docs/ http://172.22.0.1:8080/v3/api-docs/
|
||||||
|
ProxyPassReverse /v3/api-docs/ http://172.22.0.1:8080/v3/api-docs/
|
||||||
|
```
|
||||||
|
|
||||||
|
## 权限配置
|
||||||
|
|
||||||
|
### 无需认证(公开访问)
|
||||||
|
|
||||||
|
```
|
||||||
|
/login
|
||||||
|
/register
|
||||||
|
/api/public/**
|
||||||
|
/api/auth/**
|
||||||
|
/api/verification/**
|
||||||
|
/api/email/**
|
||||||
|
/api/tencent/**
|
||||||
|
/api/test/**
|
||||||
|
/api/health/**
|
||||||
|
/api/orders/stats
|
||||||
|
/api/payments/alipay/notify
|
||||||
|
/api/payments/alipay/return
|
||||||
|
/swagger-ui/**
|
||||||
|
/v3/api-docs/**
|
||||||
|
```
|
||||||
|
|
||||||
|
### 需要认证
|
||||||
|
|
||||||
|
```
|
||||||
|
/api/orders/**(除 /api/orders/stats)
|
||||||
|
/api/payments/**(除支付宝回调)
|
||||||
|
/api/image-to-video/**
|
||||||
|
/api/text-to-video/**
|
||||||
|
/api/works/**
|
||||||
|
/api/points/**
|
||||||
|
/api/members/**
|
||||||
|
```
|
||||||
|
|
||||||
|
### 需要管理员权限
|
||||||
|
|
||||||
|
```
|
||||||
|
/api/dashboard/**
|
||||||
|
/api/admin/**
|
||||||
|
/settings/**
|
||||||
|
/users/**
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整 Nginx 配置示例
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
root /www/wwwroot/your-domain.com;
|
||||||
|
index index.html index.htm;
|
||||||
|
|
||||||
|
# 开启gzip压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
|
||||||
|
|
||||||
|
# 前端路由支持(History模式)
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API 代理到后端(主要路由)
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://172.22.0.1:8080/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 超时设置
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 900s;
|
||||||
|
proxy_read_timeout 900s;
|
||||||
|
|
||||||
|
# 支持大文件上传
|
||||||
|
client_max_body_size 600M;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Swagger UI 代理
|
||||||
|
location ~ ^/(swagger-ui|v3/api-docs|swagger-resources|webjars) {
|
||||||
|
proxy_pass http://172.22.0.1:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传文件代理
|
||||||
|
location /uploads/ {
|
||||||
|
proxy_pass http://172.22.0.1:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态资源缓存
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 禁止访问隐藏文件
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 宝塔面板配置
|
||||||
|
|
||||||
|
在宝塔面板中配置反向代理:
|
||||||
|
|
||||||
|
1. 进入网站设置 → 反向代理
|
||||||
|
2. 添加反向代理规则:
|
||||||
|
- **代理名称**: API代理
|
||||||
|
- **目标URL**: http://172.22.0.1:8080
|
||||||
|
- **发送域名**: $host
|
||||||
|
- **代理路径**: /api/
|
||||||
|
- **缓存**: 关闭
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
- **统一API前缀**: `/api/`
|
||||||
|
- **后端服务地址**: `http://172.22.0.1:8080`
|
||||||
|
- **主要代理路径**: `/api/` → `http://172.22.0.1:8080/`
|
||||||
|
- **文档访问**: `/swagger-ui.html`
|
||||||
|
- **特殊配置**: 需要支持大文件上传(600M)和长时间请求(15分钟)
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
# 腾讯云SES邮件发送问题排查指南
|
|
||||||
|
|
||||||
## 当前错误
|
|
||||||
|
|
||||||
```
|
|
||||||
错误码: FailedOperation.SendEmailErr
|
|
||||||
错误信息: 操作失败。您的发送遇到问题,请检查Region参数是否指定准确,若Region参数无误,请联系腾讯云提交工单沟通原因并解决。
|
|
||||||
```
|
|
||||||
|
|
||||||
## 问题诊断
|
|
||||||
|
|
||||||
这个错误通常表示以下问题之一:
|
|
||||||
|
|
||||||
### 1. **发信地址未验证** ⚠️ 最常见
|
|
||||||
- 发信地址 `newletter@vionow.com` 可能未在腾讯云SES控制台的 **广州区域** 验证
|
|
||||||
- 需要在对应区域验证发信地址或域名
|
|
||||||
|
|
||||||
### 2. **模板ID不存在或区域不匹配**
|
|
||||||
- 模板ID `154360` 可能不存在于广州区域
|
|
||||||
- 模板可能在其他区域创建,需要确认模板所在区域
|
|
||||||
|
|
||||||
### 3. **区域配置不匹配**
|
|
||||||
- 当前配置区域:`ap-guangzhou`(广州)
|
|
||||||
- 需要确保腾讯云控制台选择的地域与代码配置一致
|
|
||||||
|
|
||||||
## 解决步骤
|
|
||||||
|
|
||||||
### 步骤1: 登录腾讯云SES控制台
|
|
||||||
|
|
||||||
访问:https://console.cloud.tencent.com/ses
|
|
||||||
|
|
||||||
### 步骤2: 确认选择的地域
|
|
||||||
|
|
||||||
1. 在控制台右上角,确认当前选择的地域是否为 **"广州"**(ap-guangzhou)
|
|
||||||
2. 如果选择了其他地域,切换到广州区域
|
|
||||||
|
|
||||||
### 步骤3: 验证发信地址
|
|
||||||
|
|
||||||
1. 进入 **"发信地址"** 或 **"身份验证"** 页面
|
|
||||||
2. 检查 `newletter@vionow.com` 是否已添加并验证通过
|
|
||||||
3. 如果未添加:
|
|
||||||
- 点击 **"添加发信地址"**
|
|
||||||
- 输入 `newletter@vionow.com`
|
|
||||||
- 完成验证(通常会收到验证邮件)
|
|
||||||
- 等待审核通过(通常几分钟到几小时)
|
|
||||||
|
|
||||||
### 步骤4: 检查模板ID
|
|
||||||
|
|
||||||
1. 进入 **"邮件模板"** 页面
|
|
||||||
2. 确认模板ID `154360` 是否存在
|
|
||||||
3. 确认模板状态为 **"已审核"** 或 **"已通过"**
|
|
||||||
4. 如果模板不存在:
|
|
||||||
- 检查模板是否在其他区域创建
|
|
||||||
- 或者在当前区域重新创建模板
|
|
||||||
- 获取新的模板ID并更新配置
|
|
||||||
|
|
||||||
### 步骤5: 检查账户状态
|
|
||||||
|
|
||||||
1. 确认SES服务已开通
|
|
||||||
2. 检查账户是否有发送配额
|
|
||||||
3. 检查是否有账户限制或黑名单
|
|
||||||
|
|
||||||
## 当前配置信息
|
|
||||||
|
|
||||||
根据您的配置文件:
|
|
||||||
- **SecretID**: `AKIDoaEjFbqxxqZAcv8EE6oZCg2IQPG1fCxm`
|
|
||||||
- **区域**: `ap-guangzhou`(广州)✅
|
|
||||||
- **发信地址**: `newletter@vionow.com` ⚠️ 需要验证
|
|
||||||
- **模板ID**: `154360` ⚠️ 需要确认存在
|
|
||||||
|
|
||||||
## 快速检查清单
|
|
||||||
|
|
||||||
- [ ] 在腾讯云SES控制台选择的地域是否为"广州"?
|
|
||||||
- [ ] 发信地址 `newletter@vionow.com` 是否已在广州区域验证通过?
|
|
||||||
- [ ] 模板ID `154360` 是否存在于广州区域?
|
|
||||||
- [ ] 模板状态是否为"已审核"?
|
|
||||||
- [ ] 账户是否有发送配额?
|
|
||||||
- [ ] 访问密钥是否具有SES发送邮件权限?
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### Q: 发信地址验证需要多长时间?
|
|
||||||
A: 通常几分钟到几小时,验证邮件会发送到邮箱地址的邮箱管理员处。
|
|
||||||
|
|
||||||
### Q: 如何验证域名而不是单个邮箱?
|
|
||||||
A: 可以添加域名 `vionow.com` 进行验证,验证后该域名下所有邮箱都可以发信。
|
|
||||||
|
|
||||||
### Q: 模板在不同区域可以通用吗?
|
|
||||||
A: 不可以,模板是区域隔离的,需要在使用的区域创建模板。
|
|
||||||
|
|
||||||
### Q: 如何查看模板的详细信息?
|
|
||||||
A: 在SES控制台的"邮件模板"页面,点击模板ID查看详情,确认模板内容和状态。
|
|
||||||
|
|
||||||
## 如果仍然失败
|
|
||||||
|
|
||||||
如果完成以上步骤后仍然失败,请:
|
|
||||||
|
|
||||||
1. **检查腾讯云工单**:提交工单获取技术支持
|
|
||||||
2. **查看详细日志**:检查应用日志中的完整错误堆栈
|
|
||||||
3. **联系腾讯云客服**:通过控制台联系客服获取帮助
|
|
||||||
|
|
||||||
## 临时解决方案
|
|
||||||
|
|
||||||
如果需要快速测试,可以临时使用开发模式:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 在 application-dev.properties 中
|
|
||||||
tencent.ses.template-id=0
|
|
||||||
```
|
|
||||||
|
|
||||||
开发模式下不会发送真实邮件,验证码会记录在日志中。
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
# 任务清理系统实现说明
|
|
||||||
|
|
||||||
## 功能概述
|
|
||||||
|
|
||||||
本系统实现了定期清理任务列表的功能,将成功的任务导出到专门的归档表中,失败的任务记录到清理日志后删除。
|
|
||||||
|
|
||||||
## 系统架构
|
|
||||||
|
|
||||||
### 1. 数据库表结构
|
|
||||||
|
|
||||||
#### 成功任务归档表 (`completed_tasks_archive`)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE completed_tasks_archive (
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
task_id VARCHAR(255) NOT NULL,
|
|
||||||
username VARCHAR(255) NOT NULL,
|
|
||||||
task_type VARCHAR(50) NOT NULL,
|
|
||||||
prompt TEXT,
|
|
||||||
aspect_ratio VARCHAR(20),
|
|
||||||
duration INT,
|
|
||||||
hd_mode BOOLEAN DEFAULT FALSE,
|
|
||||||
result_url TEXT,
|
|
||||||
real_task_id VARCHAR(255),
|
|
||||||
progress INT DEFAULT 100,
|
|
||||||
created_at TIMESTAMP NOT NULL,
|
|
||||||
completed_at TIMESTAMP NOT NULL,
|
|
||||||
archived_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
points_cost INT DEFAULT 0
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 失败任务清理日志表 (`failed_tasks_cleanup_log`)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE failed_tasks_cleanup_log (
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
task_id VARCHAR(255) NOT NULL,
|
|
||||||
username VARCHAR(255) NOT NULL,
|
|
||||||
task_type VARCHAR(50) NOT NULL,
|
|
||||||
error_message TEXT,
|
|
||||||
created_at TIMESTAMP NOT NULL,
|
|
||||||
failed_at TIMESTAMP NOT NULL,
|
|
||||||
cleaned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 核心组件
|
|
||||||
|
|
||||||
#### TaskCleanupService
|
|
||||||
- **功能**: 执行任务清理的核心服务
|
|
||||||
- **主要方法**:
|
|
||||||
- `performFullCleanup()`: 执行完整清理
|
|
||||||
- `cleanupTextToVideoTasks()`: 清理文生视频任务
|
|
||||||
- `cleanupImageToVideoTasks()`: 清理图生视频任务
|
|
||||||
- `cleanupTaskQueue()`: 清理任务队列
|
|
||||||
- `cleanupExpiredArchives()`: 清理过期归档
|
|
||||||
- `cleanupUserTasks()`: 清理指定用户任务
|
|
||||||
|
|
||||||
#### TaskQueueScheduler
|
|
||||||
- **功能**: 定时调度器
|
|
||||||
- **调度任务**:
|
|
||||||
- 每天凌晨4点执行任务清理 (`@Scheduled(cron = "0 0 4 * * ?")`)
|
|
||||||
|
|
||||||
#### CleanupController
|
|
||||||
- **功能**: 提供手动清理的API接口
|
|
||||||
- **接口**:
|
|
||||||
- `POST /api/cleanup/full-cleanup`: 执行完整清理
|
|
||||||
- `POST /api/cleanup/user-tasks/{username}`: 清理指定用户任务
|
|
||||||
- `GET /api/cleanup/cleanup-stats`: 获取清理统计信息
|
|
||||||
|
|
||||||
## 清理流程
|
|
||||||
|
|
||||||
### 1. 成功任务处理
|
|
||||||
1. 查找所有状态为 `COMPLETED` 的任务
|
|
||||||
2. 将任务信息导出到 `completed_tasks_archive` 表
|
|
||||||
3. 从原始任务表中删除记录
|
|
||||||
|
|
||||||
### 2. 失败任务处理
|
|
||||||
1. 查找所有状态为 `FAILED` 的任务
|
|
||||||
2. 将任务信息记录到 `failed_tasks_cleanup_log` 表
|
|
||||||
3. 从原始任务表中删除记录
|
|
||||||
|
|
||||||
### 3. 任务队列清理
|
|
||||||
1. 删除状态为 `COMPLETED` 和 `FAILED` 的任务队列记录
|
|
||||||
|
|
||||||
### 4. 过期归档清理
|
|
||||||
1. 删除超过保留期的归档记录和清理日志
|
|
||||||
|
|
||||||
## 配置参数
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 任务保留天数(默认30天)
|
|
||||||
task.cleanup.retention-days=30
|
|
||||||
|
|
||||||
# 归档保留天数(默认365天)
|
|
||||||
task.cleanup.archive-retention-days=365
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 1. 自动清理
|
|
||||||
系统每天凌晨4点自动执行清理任务,无需人工干预。
|
|
||||||
|
|
||||||
### 2. 手动清理
|
|
||||||
```bash
|
|
||||||
# 执行完整清理
|
|
||||||
curl -X POST "http://localhost:8080/api/cleanup/full-cleanup"
|
|
||||||
|
|
||||||
# 清理指定用户任务
|
|
||||||
curl -X POST "http://localhost:8080/api/cleanup/user-tasks/admin"
|
|
||||||
|
|
||||||
# 获取清理统计信息
|
|
||||||
curl "http://localhost:8080/api/cleanup/cleanup-stats"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. PowerShell测试脚本
|
|
||||||
```powershell
|
|
||||||
# 运行测试脚本
|
|
||||||
.\test-cleanup.ps1
|
|
||||||
```
|
|
||||||
|
|
||||||
## 监控和统计
|
|
||||||
|
|
||||||
### 清理统计信息
|
|
||||||
- 当前任务数量(按状态分类)
|
|
||||||
- 归档任务数量
|
|
||||||
- 清理日志数量
|
|
||||||
- 配置参数
|
|
||||||
|
|
||||||
### 日志记录
|
|
||||||
- 清理操作的详细日志
|
|
||||||
- 错误处理和异常记录
|
|
||||||
- 性能监控信息
|
|
||||||
|
|
||||||
## 安全考虑
|
|
||||||
|
|
||||||
1. **事务处理**: 所有清理操作都在事务中执行,确保数据一致性
|
|
||||||
2. **错误处理**: 完善的异常处理机制,避免清理过程中的数据丢失
|
|
||||||
3. **权限控制**: API接口需要适当的权限验证
|
|
||||||
4. **数据备份**: 建议在清理前进行数据备份
|
|
||||||
|
|
||||||
## 扩展功能
|
|
||||||
|
|
||||||
### 1. 自定义清理策略
|
|
||||||
- 支持按任务类型设置不同的保留期
|
|
||||||
- 支持按用户等级设置不同的清理策略
|
|
||||||
|
|
||||||
### 2. 清理报告
|
|
||||||
- 生成清理操作的详细报告
|
|
||||||
- 支持邮件通知清理结果
|
|
||||||
|
|
||||||
### 3. 数据导出
|
|
||||||
- 支持将归档数据导出为CSV或Excel格式
|
|
||||||
- 支持按时间范围导出数据
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **数据恢复**: 清理后的数据无法直接恢复,需要从归档表中查找
|
|
||||||
2. **性能影响**: 大量数据清理可能影响系统性能,建议在低峰期执行
|
|
||||||
3. **存储空间**: 归档表会占用额外的存储空间,需要定期清理过期数据
|
|
||||||
4. **备份策略**: 建议定期备份归档表数据
|
|
||||||
|
|
||||||
---
|
|
||||||
*文档生成时间: 2025-01-24*
|
|
||||||
*版本: 1.0*
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
# 任务队列系统
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
任务队列系统用于管理用户的视频生成任务,实现以下功能:
|
|
||||||
|
|
||||||
- **任务限制**: 每个用户最多同时有3个待处理任务
|
|
||||||
- **定时检查**: 每2分钟自动检查一次任务状态
|
|
||||||
- **优先级管理**: 支持任务优先级排序
|
|
||||||
- **状态跟踪**: 完整的任务状态生命周期管理
|
|
||||||
- **自动清理**: 定期清理过期任务
|
|
||||||
|
|
||||||
## 系统架构
|
|
||||||
|
|
||||||
### 核心组件
|
|
||||||
|
|
||||||
1. **TaskQueue 实体类**: 任务队列数据模型
|
|
||||||
2. **TaskQueueRepository**: 数据访问层
|
|
||||||
3. **TaskQueueService**: 业务逻辑层
|
|
||||||
4. **TaskQueueScheduler**: 定时任务调度器
|
|
||||||
5. **TaskQueueApiController**: API控制器
|
|
||||||
|
|
||||||
### 任务状态
|
|
||||||
|
|
||||||
- `PENDING`: 等待处理
|
|
||||||
- `PROCESSING`: 正在处理
|
|
||||||
- `COMPLETED`: 已完成
|
|
||||||
- `FAILED`: 失败
|
|
||||||
- `CANCELLED`: 已取消
|
|
||||||
- `TIMEOUT`: 超时
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 1. 添加任务到队列
|
|
||||||
|
|
||||||
```java
|
|
||||||
// 文生视频任务
|
|
||||||
taskQueueService.addTextToVideoTask(username, taskId);
|
|
||||||
|
|
||||||
// 图生视频任务
|
|
||||||
taskQueueService.addImageToVideoTask(username, taskId);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 获取用户任务队列
|
|
||||||
|
|
||||||
```java
|
|
||||||
List<TaskQueue> userTasks = taskQueueService.getUserTaskQueue(username);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 取消任务
|
|
||||||
|
|
||||||
```java
|
|
||||||
boolean cancelled = taskQueueService.cancelTask(taskId, username);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 获取统计信息
|
|
||||||
|
|
||||||
```java
|
|
||||||
long totalCount = taskQueueService.getUserTaskCount(username);
|
|
||||||
```
|
|
||||||
|
|
||||||
## API接口
|
|
||||||
|
|
||||||
### 获取用户任务队列
|
|
||||||
```
|
|
||||||
GET /api/task-queue/user-tasks
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 取消任务
|
|
||||||
```
|
|
||||||
POST /api/task-queue/cancel/{taskId}
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取队列统计
|
|
||||||
```
|
|
||||||
GET /api/task-queue/stats
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 手动处理任务(管理员)
|
|
||||||
```
|
|
||||||
POST /api/task-queue/process-pending
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 手动检查状态(管理员)
|
|
||||||
```
|
|
||||||
POST /api/task-queue/check-statuses
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 定时任务
|
|
||||||
|
|
||||||
### 1. 处理待处理任务
|
|
||||||
- **频率**: 每30秒
|
|
||||||
- **功能**: 处理队列中的待处理任务,提交到外部API
|
|
||||||
|
|
||||||
### 2. 检查任务状态
|
|
||||||
- **频率**: 每2分钟
|
|
||||||
- **功能**: 检查正在处理的任务状态,更新任务状态
|
|
||||||
|
|
||||||
### 3. 清理过期任务
|
|
||||||
- **频率**: 每天凌晨2点
|
|
||||||
- **功能**: 清理超过7天的任务记录
|
|
||||||
|
|
||||||
### 4. 队列状态监控
|
|
||||||
- **频率**: 每5分钟
|
|
||||||
- **功能**: 记录队列运行状态
|
|
||||||
|
|
||||||
## 配置参数
|
|
||||||
|
|
||||||
### 任务限制
|
|
||||||
- 每个用户最多3个待处理任务
|
|
||||||
- 可通过修改 `MAX_TASKS_PER_USER` 常量调整
|
|
||||||
|
|
||||||
### 超时设置
|
|
||||||
- 默认最大检查次数:30次
|
|
||||||
- 检查间隔:2分钟
|
|
||||||
- 总超时时间:60分钟
|
|
||||||
- 可通过修改 `maxCheckCount` 字段调整
|
|
||||||
|
|
||||||
### 清理策略
|
|
||||||
- 过期时间:7天
|
|
||||||
- 可通过修改 `cleanupExpiredTasks` 方法调整
|
|
||||||
|
|
||||||
## 数据库表结构
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE task_queue (
|
|
||||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
username VARCHAR(100) NOT NULL,
|
|
||||||
task_id VARCHAR(50) NOT NULL UNIQUE,
|
|
||||||
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO') NOT NULL,
|
|
||||||
status ENUM('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED', 'TIMEOUT') NOT NULL DEFAULT 'PENDING',
|
|
||||||
priority INT NOT NULL DEFAULT 0,
|
|
||||||
real_task_id VARCHAR(100),
|
|
||||||
last_check_time DATETIME,
|
|
||||||
check_count INT NOT NULL DEFAULT 0,
|
|
||||||
max_check_count INT NOT NULL DEFAULT 30,
|
|
||||||
error_message TEXT,
|
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
completed_at DATETIME
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
## 集成说明
|
|
||||||
|
|
||||||
### 现有服务修改
|
|
||||||
|
|
||||||
1. **TextToVideoService**:
|
|
||||||
- 移除了原有的异步处理逻辑
|
|
||||||
- 改为添加任务到队列
|
|
||||||
|
|
||||||
2. **ImageToVideoService**:
|
|
||||||
- 移除了原有的异步处理逻辑
|
|
||||||
- 改为添加任务到队列
|
|
||||||
|
|
||||||
### 工作流程
|
|
||||||
|
|
||||||
1. 用户创建任务 → 保存到数据库 → 添加到队列
|
|
||||||
2. 定时任务处理队列 → 提交到外部API → 更新状态为PROCESSING
|
|
||||||
3. 定时任务检查状态 → 查询外部API → 更新任务状态
|
|
||||||
4. 任务完成/失败 → 更新原始任务状态 → 从队列中移除
|
|
||||||
|
|
||||||
## 监控和日志
|
|
||||||
|
|
||||||
### 关键日志
|
|
||||||
- 任务添加到队列
|
|
||||||
- 任务状态变更
|
|
||||||
- API调用结果
|
|
||||||
- 错误和异常
|
|
||||||
|
|
||||||
### 监控指标
|
|
||||||
- 队列中任务数量
|
|
||||||
- 各状态任务分布
|
|
||||||
- 处理成功率
|
|
||||||
- 平均处理时间
|
|
||||||
|
|
||||||
## 故障处理
|
|
||||||
|
|
||||||
### 常见问题
|
|
||||||
|
|
||||||
1. **任务卡在PROCESSING状态**
|
|
||||||
- 检查外部API是否正常
|
|
||||||
- 查看错误日志
|
|
||||||
- 手动触发状态检查
|
|
||||||
|
|
||||||
2. **队列积压**
|
|
||||||
- 检查外部API响应时间
|
|
||||||
- 调整检查频率
|
|
||||||
- 增加处理线程
|
|
||||||
|
|
||||||
3. **任务超时**
|
|
||||||
- 检查网络连接
|
|
||||||
- 调整超时设置
|
|
||||||
- 优化API调用
|
|
||||||
|
|
||||||
### 恢复策略
|
|
||||||
|
|
||||||
1. **自动恢复**: 系统会自动重试失败的任务
|
|
||||||
2. **手动干预**: 通过API接口手动处理
|
|
||||||
3. **数据修复**: 清理异常状态的任务
|
|
||||||
|
|
||||||
## 性能优化
|
|
||||||
|
|
||||||
### 数据库优化
|
|
||||||
- 添加适当的索引
|
|
||||||
- 定期清理过期数据
|
|
||||||
- 使用分页查询
|
|
||||||
|
|
||||||
### 系统优化
|
|
||||||
- 异步处理任务
|
|
||||||
- 批量操作
|
|
||||||
- 缓存热点数据
|
|
||||||
|
|
||||||
## 扩展功能
|
|
||||||
|
|
||||||
### 未来可扩展的功能
|
|
||||||
1. **任务优先级**: 支持动态调整优先级
|
|
||||||
2. **负载均衡**: 多实例部署时的任务分配
|
|
||||||
3. **任务依赖**: 支持任务间的依赖关系
|
|
||||||
4. **通知系统**: 任务完成后的消息通知
|
|
||||||
5. **统计分析**: 详细的性能统计和分析
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
# 腾讯云SES权限配置指南
|
|
||||||
|
|
||||||
## 问题描述
|
|
||||||
|
|
||||||
当前错误:
|
|
||||||
```
|
|
||||||
AuthFailure.UnauthorizedOperation
|
|
||||||
you are not authorized to perform operation (ses:SendEmail)
|
|
||||||
resource (*) has no permission
|
|
||||||
```
|
|
||||||
|
|
||||||
这个错误表示您的腾讯云访问密钥没有发送邮件的权限。
|
|
||||||
|
|
||||||
## 解决方案
|
|
||||||
|
|
||||||
### 方案1:在腾讯云控制台配置权限(推荐)
|
|
||||||
|
|
||||||
1. **登录腾讯云控制台**
|
|
||||||
- 访问:https://console.cloud.tencent.com/
|
|
||||||
|
|
||||||
2. **进入访问管理(CAM)**
|
|
||||||
- 在控制台顶部搜索"访问管理"或"CAM"
|
|
||||||
- 或者直接访问:https://console.cloud.tencent.com/cam
|
|
||||||
|
|
||||||
3. **配置子账号权限**
|
|
||||||
- 如果使用的是子账号密钥,需要为该子账号添加SES权限:
|
|
||||||
- 进入"用户" → 找到对应用户 → 点击"授权"
|
|
||||||
- 搜索"SES"或"邮件推送"
|
|
||||||
- 添加策略:`QcloudSESFullAccess`(SES全读写访问权限)
|
|
||||||
- 或者使用自定义策略,只授予`ses:SendEmail`权限
|
|
||||||
|
|
||||||
4. **如果使用主账号密钥**
|
|
||||||
- 主账号默认拥有所有权限
|
|
||||||
- 如果仍然报错,可能是密钥错误或已禁用
|
|
||||||
- 检查:访问管理 → API密钥管理 → 查看密钥状态
|
|
||||||
|
|
||||||
5. **验证配置**
|
|
||||||
- 权限配置后可能需要几分钟生效
|
|
||||||
- 重新启动应用并测试
|
|
||||||
|
|
||||||
### 方案2:使用开发模式(临时方案)
|
|
||||||
|
|
||||||
如果您在开发环境测试,可以暂时使用开发模式:
|
|
||||||
|
|
||||||
1. **修改配置文件** `application-dev.properties`:
|
|
||||||
```properties
|
|
||||||
# 设置为0以使用开发模式(不发送真实邮件,仅在日志中记录验证码)
|
|
||||||
tencent.ses.template-id=0
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **开发模式行为**
|
|
||||||
- 不会调用腾讯云SES API
|
|
||||||
- 验证码会记录在日志中
|
|
||||||
- 可以直接使用日志中的验证码进行测试
|
|
||||||
|
|
||||||
### 方案3:创建自定义CAM策略(精细化权限)
|
|
||||||
|
|
||||||
如果您只想授予发送邮件权限,可以创建自定义策略:
|
|
||||||
|
|
||||||
1. **进入CAM策略管理**
|
|
||||||
- 访问:https://console.cloud.tencent.com/cam/policy
|
|
||||||
|
|
||||||
2. **创建自定义策略**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "2.0",
|
|
||||||
"statement": [
|
|
||||||
{
|
|
||||||
"effect": "allow",
|
|
||||||
"action": [
|
|
||||||
"ses:SendEmail"
|
|
||||||
],
|
|
||||||
"resource": "*"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **将策略绑定到子账号**
|
|
||||||
- 进入"用户" → 找到对应用户 → 点击"授权"
|
|
||||||
- 选择刚创建的自定义策略
|
|
||||||
|
|
||||||
## 当前配置信息
|
|
||||||
|
|
||||||
根据您的配置文件:
|
|
||||||
- **SecretID**: `AKIDXw8HBtNfjdJm480xljV4QZUDi05wa0DE`
|
|
||||||
- **区域**: `ap-beijing`
|
|
||||||
- **发信地址**: `newletter@vionow.com`
|
|
||||||
- **模板ID**: `154360`
|
|
||||||
|
|
||||||
## 检查清单
|
|
||||||
|
|
||||||
- [ ] 验证发信地址 `newletter@vionow.com` 已在腾讯云SES控制台验证通过
|
|
||||||
- [ ] 验证模板ID `154360` 存在且已审核通过
|
|
||||||
- [ ] 验证访问密钥所属账号具有SES发送邮件权限
|
|
||||||
- [ ] 验证密钥未过期或被禁用
|
|
||||||
- [ ] 等待权限配置生效(通常1-2分钟)
|
|
||||||
|
|
||||||
## 相关文档
|
|
||||||
|
|
||||||
- [腾讯云SES权限说明](https://cloud.tencent.com/document/product/1288/45321)
|
|
||||||
- [CAM策略语法](https://cloud.tencent.com/document/product/598/10603)
|
|
||||||
- [发信地址验证指南](https://cloud.tencent.com/document/product/1288/68353)
|
|
||||||
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
# 腾讯云SES邮件服务启动检查清单
|
|
||||||
|
|
||||||
## ✅ 启动前必需准备项
|
|
||||||
|
|
||||||
### 1. 腾讯云账号和凭证 ⚠️ **必需**
|
|
||||||
|
|
||||||
#### 获取步骤:
|
|
||||||
1. **登录腾讯云控制台**
|
|
||||||
- 访问:https://console.cloud.tencent.com
|
|
||||||
- 如无账号,需先注册
|
|
||||||
|
|
||||||
2. **获取API密钥**
|
|
||||||
- 访问:https://console.cloud.tencent.com/cam/capi
|
|
||||||
- 创建或查看API密钥
|
|
||||||
- 获取以下信息:
|
|
||||||
```
|
|
||||||
SecretID: 例如 AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA
|
|
||||||
SecretKey: 例如 Gu5t9xGARNpqDXcd3I4WZkFpAALPVZ7pKbNScfFsj
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **开通SES(邮件推送)服务**
|
|
||||||
- 访问:https://console.cloud.tencent.com/ses
|
|
||||||
- 确保服务已开通
|
|
||||||
- 查看是否有免费额度或已充值
|
|
||||||
|
|
||||||
### 2. 配置发信地址 ⚠️ **必需**
|
|
||||||
|
|
||||||
#### 配置步骤:
|
|
||||||
1. **创建发信地址**
|
|
||||||
- 在SES控制台的"发信地址"中创建
|
|
||||||
- 输入你的邮箱地址(例如:noreply@yourdomain.com)
|
|
||||||
|
|
||||||
2. **验证发信地址**
|
|
||||||
- 腾讯云会向该邮箱发送验证邮件
|
|
||||||
- 点击邮件中的验证链接完成验证
|
|
||||||
- ⚠️ **重要**:只有验证通过的邮箱才能发送邮件
|
|
||||||
|
|
||||||
3. **记录已验证的发信地址**
|
|
||||||
- 例如:`noreply@vionow.com`
|
|
||||||
- 配置到 `application-dev.properties` 中的 `tencent.ses.from-email`
|
|
||||||
|
|
||||||
### 3. 创建邮件模板 ⚠️ **必需(生产环境)**
|
|
||||||
|
|
||||||
#### 配置步骤:
|
|
||||||
1. **访问模板管理**
|
|
||||||
- 在SES控制台的"邮件模板"中创建
|
|
||||||
|
|
||||||
2. **创建模板**
|
|
||||||
- 模板类型:选择"触发邮件"或"批量邮件"
|
|
||||||
- 模板内容示例:
|
|
||||||
```
|
|
||||||
您的验证码是:{{code}}
|
|
||||||
验证码有效期5分钟,请勿泄露给他人。
|
|
||||||
如果不是您本人操作,请忽略此邮件。
|
|
||||||
```
|
|
||||||
- 在模板中使用 `{{变量名}}` 来定义可替换的变量
|
|
||||||
|
|
||||||
3. **记录模板ID**
|
|
||||||
- 创建成功后,在模板列表中找到模板ID
|
|
||||||
- 例如:`12345`
|
|
||||||
- 配置到 `application-dev.properties` 中的 `tencent.ses.template-id`
|
|
||||||
|
|
||||||
### 4. 配置文件更新 ⚠️ **必需**
|
|
||||||
|
|
||||||
#### 更新 `demo/src/main/resources/application-dev.properties`:
|
|
||||||
|
|
||||||
```properties
|
|
||||||
# 腾讯云SES配置
|
|
||||||
tencent.ses.secret-id=你的SecretID # ⚠️ 必须配置
|
|
||||||
tencent.ses.secret-key=你的SecretKey # ⚠️ 必须配置
|
|
||||||
tencent.ses.region=ap-beijing # 可选,默认beijing
|
|
||||||
tencent.ses.from-email=已验证的发信地址 # ⚠️ 必须配置
|
|
||||||
tencent.ses.from-name=AIGC平台 # 可选
|
|
||||||
tencent.ses.template-id=0 # 0=开发模式,实际模板ID=生产模式
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 当前配置状态检查:
|
|
||||||
- ✅ SecretID: 已配置(`AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA`)
|
|
||||||
- ✅ SecretKey: 已配置
|
|
||||||
- ✅ Region: 已配置(`ap-beijing`)
|
|
||||||
- ✅ From-email: 已配置(`noreply@vionow.com`)
|
|
||||||
- ⚠️ Template-id: 当前为 `0`(开发模式)
|
|
||||||
|
|
||||||
### 5. Maven依赖检查 ✅ **已完成**
|
|
||||||
|
|
||||||
项目已包含腾讯云SDK依赖:
|
|
||||||
```xml
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.tencentcloudapi</groupId>
|
|
||||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
|
||||||
<version>3.1.880</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
✅ 无需额外操作
|
|
||||||
|
|
||||||
## 📋 快速检查清单
|
|
||||||
|
|
||||||
启动前请确认:
|
|
||||||
|
|
||||||
- [ ] ✅ 腾讯云账号已注册
|
|
||||||
- [ ] ✅ 已获取SecretID和SecretKey
|
|
||||||
- [ ] ✅ 已开通SES邮件推送服务
|
|
||||||
- [ ] ✅ 已创建并验证发信地址
|
|
||||||
- [ ] ✅ 配置文件 `application-dev.properties` 已更新正确的凭证
|
|
||||||
- [ ] ✅ 发信地址已配置到 `tencent.ses.from-email`
|
|
||||||
- [ ] ⚠️ 生产环境:已创建邮件模板并获取模板ID
|
|
||||||
|
|
||||||
## 🚀 启动步骤
|
|
||||||
|
|
||||||
### 方式1:开发模式启动(无需模板,推荐先测试)
|
|
||||||
|
|
||||||
**特点**:
|
|
||||||
- 不需要创建邮件模板
|
|
||||||
- 不会实际发送邮件
|
|
||||||
- 验证码会在日志中显示
|
|
||||||
- 适合本地开发测试
|
|
||||||
|
|
||||||
**配置**:
|
|
||||||
```properties
|
|
||||||
tencent.ses.template-id=0 # 保持为0
|
|
||||||
```
|
|
||||||
|
|
||||||
**启动**:
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
./mvnw spring-boot:run
|
|
||||||
# 或
|
|
||||||
mvn spring-boot:run
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试**:
|
|
||||||
```bash
|
|
||||||
# 调用发送验证码接口
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"your-email@example.com"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
**查看日志**:
|
|
||||||
```
|
|
||||||
WARN 未配置邮件模板ID,使用开发模式。验证码: 123456, 邮箱: your-email@example.com
|
|
||||||
INFO 开发模式:邮件验证码发送到: your-email@example.com, 验证码: 123456
|
|
||||||
```
|
|
||||||
|
|
||||||
### 方式2:生产模式启动(需要模板)
|
|
||||||
|
|
||||||
**特点**:
|
|
||||||
- 实际发送邮件
|
|
||||||
- 需要配置模板ID
|
|
||||||
- 需要已验证的发信地址
|
|
||||||
|
|
||||||
**配置**:
|
|
||||||
```properties
|
|
||||||
tencent.ses.template-id=你的模板ID # 例如: 12345
|
|
||||||
```
|
|
||||||
|
|
||||||
**启动**:
|
|
||||||
```bash
|
|
||||||
cd demo
|
|
||||||
./mvnw spring-boot:run
|
|
||||||
```
|
|
||||||
|
|
||||||
**测试**:
|
|
||||||
```bash
|
|
||||||
# 调用发送验证码接口
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"your-email@example.com"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
**查看日志**:
|
|
||||||
```
|
|
||||||
INFO 开始发送邮件,收件人: your-email@example.com, 主题: 验证码, 模板ID: 12345
|
|
||||||
INFO 邮件发送成功,收件人: your-email@example.com, 消息ID: xxx
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 启动后验证
|
|
||||||
|
|
||||||
### 1. 检查服务是否正常启动
|
|
||||||
```bash
|
|
||||||
# 查看启动日志,确认没有错误
|
|
||||||
# 应该看到类似信息:
|
|
||||||
# Started DemoApplication in X.XXX seconds
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 测试邮件发送功能
|
|
||||||
```bash
|
|
||||||
# 方式1:使用curl
|
|
||||||
curl -X POST http://localhost:8080/api/verification/email/send \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"test@example.com"}'
|
|
||||||
|
|
||||||
# 方式2:使用前端页面
|
|
||||||
# 访问注册/登录页面,输入邮箱,点击发送验证码
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 检查日志输出
|
|
||||||
- **开发模式**:应该看到"开发模式"相关日志
|
|
||||||
- **生产模式**:应该看到"邮件发送成功"或错误信息
|
|
||||||
|
|
||||||
## ⚠️ 常见问题排查
|
|
||||||
|
|
||||||
### 问题1:启动时报配置错误
|
|
||||||
```
|
|
||||||
Could not resolve placeholder 'tencent.ses.secret-id'
|
|
||||||
```
|
|
||||||
**解决**:检查 `application-dev.properties` 文件是否存在并配置了所有必需项
|
|
||||||
|
|
||||||
### 问题2:发送失败 - 认证错误
|
|
||||||
```
|
|
||||||
InvalidSecretId.InvalidSignature
|
|
||||||
```
|
|
||||||
**解决**:
|
|
||||||
- 检查SecretID和SecretKey是否正确
|
|
||||||
- 确认没有多余的空格或特殊字符
|
|
||||||
|
|
||||||
### 问题3:发送失败 - 发信地址未验证
|
|
||||||
```
|
|
||||||
InvalidParameter.EmailAddressNotVerified
|
|
||||||
```
|
|
||||||
**解决**:
|
|
||||||
- 确认发信地址已在腾讯云SES控制台验证
|
|
||||||
- 检查 `tencent.ses.from-email` 配置是否正确
|
|
||||||
|
|
||||||
### 问题4:发送失败 - 模板不存在
|
|
||||||
```
|
|
||||||
ResourceNotFound.TemplateNotFound
|
|
||||||
```
|
|
||||||
**解决**:
|
|
||||||
- 确认模板ID是否正确
|
|
||||||
- 检查模板是否在正确的区域创建
|
|
||||||
- 确认模板状态为"已审核通过"
|
|
||||||
|
|
||||||
### 问题5:开发模式下收不到邮件
|
|
||||||
**这是正常的!**
|
|
||||||
开发模式(template-id=0)不会实际发送邮件,只会在日志中显示验证码。
|
|
||||||
|
|
||||||
## 📝 当前配置状态
|
|
||||||
|
|
||||||
根据 `application-dev.properties`:
|
|
||||||
|
|
||||||
| 配置项 | 状态 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| SecretID | ✅ 已配置 | 需要确认是否正确 |
|
|
||||||
| SecretKey | ✅ 已配置 | 需要确认是否正确 |
|
|
||||||
| Region | ✅ 已配置 | ap-beijing |
|
|
||||||
| From-email | ✅ 已配置 | noreply@vionow.com |
|
|
||||||
| Template-id | ⚠️ 开发模式 | 当前为0,如需实际发送需配置模板ID |
|
|
||||||
|
|
||||||
## 🎯 推荐启动流程
|
|
||||||
|
|
||||||
### 第一步:开发模式测试(推荐先做)
|
|
||||||
1. ✅ 确保SecretID和SecretKey已配置
|
|
||||||
2. ✅ 确保from-email已配置(即使未验证也可先测试)
|
|
||||||
3. ✅ 保持template-id=0
|
|
||||||
4. ✅ 启动服务
|
|
||||||
5. ✅ 测试发送验证码接口
|
|
||||||
6. ✅ 查看日志确认功能正常
|
|
||||||
|
|
||||||
### 第二步:配置真实发送(如需要)
|
|
||||||
1. ✅ 在腾讯云SES控制台验证发信地址
|
|
||||||
2. ✅ 创建邮件模板并获取模板ID
|
|
||||||
3. ✅ 更新template-id配置
|
|
||||||
4. ✅ 重启服务
|
|
||||||
5. ✅ 测试实际发送邮件
|
|
||||||
|
|
||||||
## 📚 参考资源
|
|
||||||
|
|
||||||
- 腾讯云SES控制台:https://console.cloud.tencent.com/ses
|
|
||||||
- API密钥管理:https://console.cloud.tencent.com/cam/capi
|
|
||||||
- 腾讯云SES文档:https://cloud.tencent.com/document/product/1288
|
|
||||||
|
|
||||||
## ✅ 总结
|
|
||||||
|
|
||||||
**最小启动要求**:
|
|
||||||
1. ✅ SecretID和SecretKey(已配置)
|
|
||||||
2. ✅ From-email地址(已配置,需确认已验证)
|
|
||||||
3. ✅ Template-id=0(开发模式,已配置)
|
|
||||||
|
|
||||||
**当前状态**:**可以直接启动**(开发模式)
|
|
||||||
|
|
||||||
如果需要实际发送邮件,需要:
|
|
||||||
- 验证发信地址
|
|
||||||
- 创建邮件模板并配置template-id
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,313 +0,0 @@
|
|||||||
# 文生视频API使用指南
|
|
||||||
|
|
||||||
## 📋 **API概述**
|
|
||||||
|
|
||||||
文生视频API提供了完整的文本生成视频功能,包括任务创建、状态查询、进度监控和任务管理等功能。
|
|
||||||
|
|
||||||
## 🔗 **API端点**
|
|
||||||
|
|
||||||
### 基础URL
|
|
||||||
```
|
|
||||||
http://localhost:8080/api/text-to-video
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📚 **API接口详情**
|
|
||||||
|
|
||||||
### 1. 创建文生视频任务
|
|
||||||
|
|
||||||
**接口**: `POST /api/text-to-video/create`
|
|
||||||
|
|
||||||
**描述**: 根据文本描述创建视频生成任务
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer <JWT_TOKEN>
|
|
||||||
Content-Type: application/json
|
|
||||||
```
|
|
||||||
|
|
||||||
**请求参数**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**参数说明**:
|
|
||||||
- `prompt` (必填): 文本描述,最大1000字符
|
|
||||||
- `aspectRatio` (可选): 视频比例,支持 "16:9", "4:3", "1:1", "3:4", "9:16",默认 "16:9"
|
|
||||||
- `duration` (可选): 视频时长(秒),范围1-60,默认5
|
|
||||||
- `hdMode` (可选): 是否高清模式,默认false
|
|
||||||
|
|
||||||
**响应示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "文生视频任务创建成功",
|
|
||||||
"data": {
|
|
||||||
"id": 1,
|
|
||||||
"taskId": "txt2vid_abc123def456",
|
|
||||||
"username": "test_user",
|
|
||||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false,
|
|
||||||
"status": "PENDING",
|
|
||||||
"progress": 0,
|
|
||||||
"costPoints": 30,
|
|
||||||
"createdAt": "2025-01-24T10:00:00",
|
|
||||||
"updatedAt": "2025-01-24T10:00:00"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 获取任务列表
|
|
||||||
|
|
||||||
**接口**: `GET /api/text-to-video/tasks`
|
|
||||||
|
|
||||||
**描述**: 获取用户的所有文生视频任务
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer <JWT_TOKEN>
|
|
||||||
```
|
|
||||||
|
|
||||||
**查询参数**:
|
|
||||||
- `page` (可选): 页码,从0开始,默认0
|
|
||||||
- `size` (可选): 每页数量,最大100,默认10
|
|
||||||
|
|
||||||
**响应示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"taskId": "txt2vid_abc123def456",
|
|
||||||
"username": "test_user",
|
|
||||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false,
|
|
||||||
"status": "COMPLETED",
|
|
||||||
"progress": 100,
|
|
||||||
"resultUrl": "/outputs/txt2vid_abc123def456/video_1737696000000.mp4",
|
|
||||||
"costPoints": 30,
|
|
||||||
"createdAt": "2025-01-24T10:00:00",
|
|
||||||
"updatedAt": "2025-01-24T10:15:00",
|
|
||||||
"completedAt": "2025-01-24T10:15:00"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"total": 1,
|
|
||||||
"page": 0,
|
|
||||||
"size": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 获取任务详情
|
|
||||||
|
|
||||||
**接口**: `GET /api/text-to-video/tasks/{taskId}`
|
|
||||||
|
|
||||||
**描述**: 获取指定任务的详细信息
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer <JWT_TOKEN>
|
|
||||||
```
|
|
||||||
|
|
||||||
**路径参数**:
|
|
||||||
- `taskId`: 任务ID
|
|
||||||
|
|
||||||
**响应示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"id": 1,
|
|
||||||
"taskId": "txt2vid_abc123def456",
|
|
||||||
"username": "test_user",
|
|
||||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"duration": 5,
|
|
||||||
"hdMode": false,
|
|
||||||
"status": "COMPLETED",
|
|
||||||
"progress": 100,
|
|
||||||
"resultUrl": "/outputs/txt2vid_abc123def456/video_1737696000000.mp4",
|
|
||||||
"costPoints": 30,
|
|
||||||
"createdAt": "2025-01-24T10:00:00",
|
|
||||||
"updatedAt": "2025-01-24T10:15:00",
|
|
||||||
"completedAt": "2025-01-24T10:15:00"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 获取任务状态
|
|
||||||
|
|
||||||
**接口**: `GET /api/text-to-video/tasks/{taskId}/status`
|
|
||||||
|
|
||||||
**描述**: 获取任务的当前状态和进度
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer <JWT_TOKEN>
|
|
||||||
```
|
|
||||||
|
|
||||||
**路径参数**:
|
|
||||||
- `taskId`: 任务ID
|
|
||||||
|
|
||||||
**响应示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"taskId": "txt2vid_abc123def456",
|
|
||||||
"status": "PROCESSING",
|
|
||||||
"progress": 65,
|
|
||||||
"resultUrl": null,
|
|
||||||
"errorMessage": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. 取消任务
|
|
||||||
|
|
||||||
**接口**: `POST /api/text-to-video/tasks/{taskId}/cancel`
|
|
||||||
|
|
||||||
**描述**: 取消正在进行的任务
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer <JWT_TOKEN>
|
|
||||||
```
|
|
||||||
|
|
||||||
**路径参数**:
|
|
||||||
- `taskId`: 任务ID
|
|
||||||
|
|
||||||
**响应示例**:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "任务已取消"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 **任务状态说明**
|
|
||||||
|
|
||||||
| 状态 | 描述 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| PENDING | 等待中 | 任务已创建,等待处理 |
|
|
||||||
| PROCESSING | 处理中 | 正在生成视频 |
|
|
||||||
| COMPLETED | 已完成 | 视频生成成功 |
|
|
||||||
| FAILED | 失败 | 视频生成失败 |
|
|
||||||
| CANCELLED | 已取消 | 任务被用户取消 |
|
|
||||||
|
|
||||||
## 💰 **积分消耗规则**
|
|
||||||
|
|
||||||
文生视频的积分消耗计算方式:
|
|
||||||
- **基础消耗**: 15积分
|
|
||||||
- **时长消耗**: 每1秒消耗3积分
|
|
||||||
- **高清模式**: 额外消耗25积分
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
- 5秒普通视频: 15 + (5 × 3) = 30积分
|
|
||||||
- 10秒高清视频: 15 + (10 × 3) + 25 = 70积分
|
|
||||||
|
|
||||||
## 🔧 **前端集成示例**
|
|
||||||
|
|
||||||
### 创建任务
|
|
||||||
```javascript
|
|
||||||
import { textToVideoApi } from '@/api/textToVideo'
|
|
||||||
|
|
||||||
const createTask = async () => {
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
prompt: "一只可爱的小猫在花园里玩耍",
|
|
||||||
aspectRatio: "16:9",
|
|
||||||
duration: 5,
|
|
||||||
hdMode: false
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await textToVideoApi.createTask(params)
|
|
||||||
|
|
||||||
if (response.data.success) {
|
|
||||||
console.log('任务创建成功:', response.data.data)
|
|
||||||
// 开始轮询任务状态
|
|
||||||
startPolling(response.data.data.taskId)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('创建任务失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 轮询任务状态
|
|
||||||
```javascript
|
|
||||||
const startPolling = (taskId) => {
|
|
||||||
const stopPolling = textToVideoApi.pollTaskStatus(
|
|
||||||
taskId,
|
|
||||||
// 进度回调
|
|
||||||
(progressData) => {
|
|
||||||
console.log('进度:', progressData.progress + '%')
|
|
||||||
},
|
|
||||||
// 完成回调
|
|
||||||
(taskData) => {
|
|
||||||
console.log('任务完成:', taskData.resultUrl)
|
|
||||||
},
|
|
||||||
// 错误回调
|
|
||||||
(error) => {
|
|
||||||
console.error('任务失败:', error.message)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// 需要时停止轮询
|
|
||||||
// stopPolling()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛡️ **安全说明**
|
|
||||||
|
|
||||||
1. **认证要求**: 所有API都需要JWT认证
|
|
||||||
2. **权限控制**: 用户只能访问自己的任务
|
|
||||||
3. **参数验证**: 严格的输入参数验证
|
|
||||||
4. **错误处理**: 完善的错误处理和日志记录
|
|
||||||
|
|
||||||
## 📝 **错误码说明**
|
|
||||||
|
|
||||||
| 错误码 | 说明 | 解决方案 |
|
|
||||||
|--------|------|----------|
|
|
||||||
| 400 | 参数错误 | 检查请求参数格式和内容 |
|
|
||||||
| 401 | 未认证 | 提供有效的JWT Token |
|
|
||||||
| 403 | 权限不足 | 确保有访问权限 |
|
|
||||||
| 404 | 任务不存在 | 检查任务ID是否正确 |
|
|
||||||
| 500 | 服务器错误 | 联系技术支持 |
|
|
||||||
|
|
||||||
## 🚀 **最佳实践**
|
|
||||||
|
|
||||||
1. **任务创建**: 创建任务后立即开始轮询状态
|
|
||||||
2. **错误处理**: 实现完善的错误处理和用户提示
|
|
||||||
3. **资源清理**: 页面卸载时停止轮询
|
|
||||||
4. **用户体验**: 提供清晰的进度反馈和状态显示
|
|
||||||
5. **性能优化**: 合理设置轮询间隔,避免频繁请求
|
|
||||||
|
|
||||||
## 📞 **技术支持**
|
|
||||||
|
|
||||||
如有问题,请联系开发团队或查看系统日志获取详细错误信息。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
# 事务配置审计报告
|
|
||||||
|
|
||||||
## 检查时间
|
|
||||||
2025-11-06
|
|
||||||
|
|
||||||
## 检查范围
|
|
||||||
所有服务类中的 `@Transactional` 配置
|
|
||||||
|
|
||||||
## 检查结果
|
|
||||||
|
|
||||||
### ✅ 正确配置的服务
|
|
||||||
|
|
||||||
#### 1. StoryboardVideoService
|
|
||||||
- **类级别**: 无 `@Transactional` ✅
|
|
||||||
- **createTask**: `@Transactional(propagation = Propagation.REQUIRES_NEW)` ✅
|
|
||||||
- 快速保存任务,事务立即提交
|
|
||||||
- **processTaskAsync**: `@Async` + `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 在事务外执行,调用外部API不会占用连接
|
|
||||||
- **其他方法**: 使用独立的事务方法,快速完成 ✅
|
|
||||||
|
|
||||||
#### 2. TaskQueueService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **processPendingTasks**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 覆盖类级别配置,在事务外执行
|
|
||||||
- **processTask**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 在事务外调用外部API
|
|
||||||
- **checkTaskStatuses**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 在事务外轮询外部API状态
|
|
||||||
- **checkTaskStatusInternal**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 在事务外调用外部API
|
|
||||||
- **其他方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
#### 3. TaskStatusPollingService
|
|
||||||
- **类级别**: 无 `@Transactional` ✅
|
|
||||||
- **pollTaskStatus**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 在事务外轮询外部API
|
|
||||||
- **其他方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
### ⚠️ 需要关注的服务
|
|
||||||
|
|
||||||
#### 4. TextToVideoService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **createTask**: 继承类级别事务
|
|
||||||
- ✅ 只做快速数据库操作(保存任务、添加到队列)
|
|
||||||
- ✅ 没有调用外部API
|
|
||||||
- ✅ 没有长时间运行的操作
|
|
||||||
- **结论**: 虽然使用类级别事务,但方法快速完成,应该没问题
|
|
||||||
|
|
||||||
#### 5. ImageToVideoService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **createTask**: 继承类级别事务
|
|
||||||
- ✅ 只做快速数据库操作(保存任务、添加到队列)
|
|
||||||
- ✅ 没有调用外部API
|
|
||||||
- ✅ 没有长时间运行的操作
|
|
||||||
- **结论**: 虽然使用类级别事务,但方法快速完成,应该没问题
|
|
||||||
|
|
||||||
#### 6. UserWorkService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **所有方法**: 都是快速数据库操作
|
|
||||||
- ✅ 没有调用外部API
|
|
||||||
- ✅ 没有长时间运行的操作
|
|
||||||
- **结论**: 应该没问题
|
|
||||||
|
|
||||||
### 📊 总结
|
|
||||||
|
|
||||||
#### 长时间运行的方法(已正确配置)
|
|
||||||
1. ✅ `StoryboardVideoService.processTaskAsync` - `NOT_SUPPORTED` + `@Async`
|
|
||||||
2. ✅ `TaskQueueService.processPendingTasks` - `NOT_SUPPORTED`
|
|
||||||
3. ✅ `TaskQueueService.processTask` - `NOT_SUPPORTED`
|
|
||||||
4. ✅ `TaskQueueService.checkTaskStatuses` - `NOT_SUPPORTED`
|
|
||||||
5. ✅ `TaskQueueService.checkTaskStatusInternal` - `NOT_SUPPORTED`
|
|
||||||
6. ✅ `TaskStatusPollingService.pollTaskStatus` - `NOT_SUPPORTED`
|
|
||||||
|
|
||||||
#### 快速事务方法(已正确配置)
|
|
||||||
- ✅ 所有 `readOnly = true` 的方法
|
|
||||||
- ✅ 所有独立的 `@Transactional` 方法(快速数据库操作)
|
|
||||||
- ✅ `StoryboardVideoService.createTask` - `REQUIRES_NEW`(快速提交)
|
|
||||||
|
|
||||||
#### 潜在问题
|
|
||||||
- ⚠️ `TextToVideoService` 和 `ImageToVideoService` 有类级别 `@Transactional`
|
|
||||||
- 但它们的 `createTask` 方法都是快速操作,应该没问题
|
|
||||||
- 如果未来需要在这些方法中调用外部API,需要添加 `NOT_SUPPORTED`
|
|
||||||
|
|
||||||
## 建议
|
|
||||||
|
|
||||||
### 当前状态
|
|
||||||
✅ **所有事务配置都是正确的,应该能正常关闭**
|
|
||||||
|
|
||||||
### 最佳实践建议
|
|
||||||
1. ✅ 长时间运行的方法都使用了 `NOT_SUPPORTED`
|
|
||||||
2. ✅ 异步方法都正确配置了 `@Async`
|
|
||||||
3. ✅ 快速事务方法都快速完成
|
|
||||||
4. ⚠️ 考虑移除 `TextToVideoService` 和 `ImageToVideoService` 的类级别 `@Transactional`,改为方法级别配置,以提高灵活性
|
|
||||||
|
|
||||||
## 结论
|
|
||||||
**✅ 所有事务都能正常关闭,没有发现连接泄漏风险**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
# 事务使用情况完整报告
|
|
||||||
|
|
||||||
## 检查时间
|
|
||||||
2025-11-06
|
|
||||||
|
|
||||||
## 检查范围
|
|
||||||
所有服务类中的 `@Transactional` 使用情况
|
|
||||||
|
|
||||||
## 检查结果
|
|
||||||
|
|
||||||
### ✅ 已修复的服务
|
|
||||||
|
|
||||||
#### 1. StoryboardVideoService
|
|
||||||
- **类级别**: 无 `@Transactional` ✅
|
|
||||||
- **createTask**: `@Transactional(propagation = Propagation.REQUIRES_NEW)` ✅
|
|
||||||
- **processTaskAsync**: `@Async` + `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- 内部调用使用 `REQUIRES_NEW` 的私有方法:
|
|
||||||
- `loadTaskInfoInNewTransaction` - `REQUIRES_NEW` + `readOnly = true` ✅
|
|
||||||
- `updateTaskStatusInNewTransaction` - `REQUIRES_NEW` ✅
|
|
||||||
- `saveStoryboardImageResultInNewTransaction` - `REQUIRES_NEW` ✅
|
|
||||||
- `updateTaskStatusToFailedInNewTransaction` - `REQUIRES_NEW` ✅
|
|
||||||
- **其他方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
### ⚠️ 需要注意的服务
|
|
||||||
|
|
||||||
#### 2. TextToVideoService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **createTask**: 继承类级别事务
|
|
||||||
- ✅ 只做快速数据库操作,无外部API调用
|
|
||||||
- **processTaskWithRealAPI**: `@Async` + 继承类级别事务 ⚠️
|
|
||||||
- ⚠️ 直接使用 `taskRepository.save(task)`,会继承类级别事务
|
|
||||||
- ⚠️ 在异步方法中调用外部API,可能导致连接泄漏
|
|
||||||
- **状态**: 此方法**未被调用**(任务通过 TaskQueueService 处理),不会导致实际泄漏
|
|
||||||
- **建议**: 如果未来需要使用,应添加 `NOT_SUPPORTED` 并使用 `REQUIRES_NEW` 的私有方法
|
|
||||||
|
|
||||||
#### 3. ImageToVideoService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **createTask**: 继承类级别事务
|
|
||||||
- ✅ 只做快速数据库操作,无外部API调用
|
|
||||||
- **processTaskWithRealAPI**: `@Async` + 继承类级别事务 ⚠️
|
|
||||||
- ⚠️ 直接使用 `taskRepository.save(task)`,会继承类级别事务
|
|
||||||
- ⚠️ 在异步方法中调用外部API,可能导致连接泄漏
|
|
||||||
- **状态**: 此方法**未被调用**(任务通过 TaskQueueService 处理),不会导致实际泄漏
|
|
||||||
- **建议**: 如果未来需要使用,应添加 `NOT_SUPPORTED` 并使用 `REQUIRES_NEW` 的私有方法
|
|
||||||
|
|
||||||
### ✅ 正确配置的服务
|
|
||||||
|
|
||||||
#### 4. TaskQueueService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **processPendingTasks**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- **processTask**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- **checkTaskStatuses**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- **checkTaskStatusInternal**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- **其他方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
#### 5. TaskStatusPollingService
|
|
||||||
- **类级别**: 无 `@Transactional` ✅
|
|
||||||
- **pollTaskStatus**: `@Transactional(propagation = Propagation.NOT_SUPPORTED)` ✅
|
|
||||||
- **其他方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
#### 6. UserWorkService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **所有方法**: 快速数据库操作,无外部API调用 ✅
|
|
||||||
|
|
||||||
#### 7. UserService
|
|
||||||
- **类级别**: 无 `@Transactional` ✅
|
|
||||||
- **所有方法**: 快速数据库操作,使用独立事务 ✅
|
|
||||||
|
|
||||||
#### 8. PaymentService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **所有方法**: 快速数据库操作,无外部API调用 ✅
|
|
||||||
|
|
||||||
#### 9. OrderService
|
|
||||||
- **类级别**: `@Transactional` ⚠️
|
|
||||||
- **所有方法**: 快速数据库操作,无外部API调用 ✅
|
|
||||||
|
|
||||||
## 总结
|
|
||||||
|
|
||||||
### 当前状态
|
|
||||||
✅ **所有实际使用的异步方法都已正确配置,不会导致连接泄漏**
|
|
||||||
|
|
||||||
### 潜在问题(但未实际使用)
|
|
||||||
⚠️ `TextToVideoService.processTaskWithRealAPI` 和 `ImageToVideoService.processTaskWithRealAPI` 有潜在问题,但**未被调用**,不会导致实际泄漏
|
|
||||||
|
|
||||||
### 建议
|
|
||||||
1. ✅ 当前配置正确,无需修改
|
|
||||||
2. ⚠️ 如果未来需要使用 `processTaskWithRealAPI` 方法,应按照 `StoryboardVideoService` 的模式修复:
|
|
||||||
- 在异步方法上添加 `@Transactional(propagation = Propagation.NOT_SUPPORTED)`
|
|
||||||
- 创建使用 `REQUIRES_NEW` 的私有方法进行数据库操作
|
|
||||||
|
|
||||||
## 结论
|
|
||||||
**✅ 所有实际使用的事务配置都是正确的,不会导致连接泄漏**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import kong.unirest.HttpResponse;
|
|
||||||
import kong.unirest.Unirest;
|
|
||||||
import kong.unirest.UnirestException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TestApiConnection {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
String apiBaseUrl = "http://116.62.4.26:8081";
|
|
||||||
String apiKey = "ak_5f13ec469e6047d5b8155c3cc91350e2";
|
|
||||||
|
|
||||||
System.out.println("测试API连接...");
|
|
||||||
System.out.println("API端点: " + apiBaseUrl);
|
|
||||||
System.out.println("API密钥: " + apiKey.substring(0, 10) + "...");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 测试获取模型列表
|
|
||||||
System.out.println("\n1. 测试获取模型列表...");
|
|
||||||
HttpResponse<String> modelsResponse = Unirest.get(apiBaseUrl + "/user/ai/models")
|
|
||||||
.header("Authorization", "Bearer " + apiKey)
|
|
||||||
.asString();
|
|
||||||
|
|
||||||
System.out.println("状态码: " + modelsResponse.getStatus());
|
|
||||||
System.out.println("响应内容: " + modelsResponse.getBody());
|
|
||||||
|
|
||||||
// 测试提交任务
|
|
||||||
System.out.println("\n2. 测试提交文生视频任务...");
|
|
||||||
String requestBody = "{\n" +
|
|
||||||
" \"modelName\": \"sc_sora2_text_landscape_10s_small\",\n" +
|
|
||||||
" \"prompt\": \"一只猫在飞\",\n" +
|
|
||||||
" \"aspectRatio\": \"16:9\",\n" +
|
|
||||||
" \"imageToVideo\": false\n" +
|
|
||||||
"}";
|
|
||||||
|
|
||||||
HttpResponse<String> submitResponse = Unirest.post(apiBaseUrl + "/user/ai/tasks/submit")
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.header("Authorization", "Bearer " + apiKey)
|
|
||||||
.body(requestBody)
|
|
||||||
.asString();
|
|
||||||
|
|
||||||
System.out.println("状态码: " + submitResponse.getStatus());
|
|
||||||
System.out.println("响应内容: " + submitResponse.getBody());
|
|
||||||
|
|
||||||
} catch (UnirestException e) {
|
|
||||||
System.err.println("API调用异常: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("其他异常: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
# 用户作品管理系统
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
用户作品管理系统实现了任务完成后自动保存结果到"我的作品"中的功能,用户可以管理自己的视频作品,包括查看、编辑、删除、分享等操作。
|
|
||||||
|
|
||||||
## 系统特性
|
|
||||||
|
|
||||||
### 🎬 **作品管理**
|
|
||||||
- **自动保存**: 任务完成后自动创建作品记录
|
|
||||||
- **作品分类**: 支持文生视频和图生视频两种类型
|
|
||||||
- **状态管理**: 处理中、已完成、失败、已删除四种状态
|
|
||||||
- **软删除**: 支持作品软删除,保留数据完整性
|
|
||||||
|
|
||||||
### 📊 **作品统计**
|
|
||||||
- **浏览统计**: 记录作品浏览次数
|
|
||||||
- **点赞功能**: 支持作品点赞
|
|
||||||
- **下载统计**: 记录作品下载次数
|
|
||||||
- **积分记录**: 记录作品消耗的积分
|
|
||||||
|
|
||||||
### 🔍 **作品发现**
|
|
||||||
- **公开作品**: 支持作品公开分享
|
|
||||||
- **搜索功能**: 根据提示词搜索作品
|
|
||||||
- **标签系统**: 支持标签分类和搜索
|
|
||||||
- **热门排行**: 按浏览次数排序的热门作品
|
|
||||||
|
|
||||||
## API接口
|
|
||||||
|
|
||||||
### 我的作品管理
|
|
||||||
|
|
||||||
#### 获取我的作品列表
|
|
||||||
```
|
|
||||||
GET /api/works/my-works?page=0&size=10
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 获取作品详情
|
|
||||||
```
|
|
||||||
GET /api/works/{workId}
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 更新作品信息
|
|
||||||
```
|
|
||||||
PUT /api/works/{workId}
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
Content-Type: application/json
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 删除作品
|
|
||||||
```
|
|
||||||
DELETE /api/works/{workId}
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 作品互动
|
|
||||||
|
|
||||||
#### 点赞作品
|
|
||||||
```
|
|
||||||
POST /api/works/{workId}/like
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 下载作品
|
|
||||||
```
|
|
||||||
POST /api/works/{workId}/download
|
|
||||||
Authorization: Bearer <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 公开作品浏览
|
|
||||||
|
|
||||||
#### 获取公开作品列表
|
|
||||||
```
|
|
||||||
GET /api/works/public?page=0&size=10&type=TEXT_TO_VIDEO&sort=popular
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 搜索公开作品
|
|
||||||
```
|
|
||||||
GET /api/works/search?keyword=小猫&page=0&size=10
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 根据标签搜索作品
|
|
||||||
```
|
|
||||||
GET /api/works/tag/可爱?page=0&size=10
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
### 1. 任务完成流程
|
|
||||||
```
|
|
||||||
任务完成 → 扣除积分 → 创建作品 → 更新任务状态
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 作品创建流程
|
|
||||||
```
|
|
||||||
获取任务信息 → 提取作品数据 → 生成作品标题 → 保存作品记录
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 作品管理流程
|
|
||||||
```
|
|
||||||
查看作品 → 编辑信息 → 设置公开 → 分享作品
|
|
||||||
```
|
|
||||||
|
|
||||||
## 集成说明
|
|
||||||
|
|
||||||
### TaskQueueService 集成
|
|
||||||
|
|
||||||
在 `TaskQueueService.updateTaskAsCompleted()` 方法中集成了作品创建:
|
|
||||||
|
|
||||||
```java
|
|
||||||
private void updateTaskAsCompleted(TaskQueue taskQueue, String resultUrl) {
|
|
||||||
// 扣除冻结的积分
|
|
||||||
userService.deductFrozenPoints(taskQueue.getTaskId());
|
|
||||||
|
|
||||||
// 创建用户作品
|
|
||||||
try {
|
|
||||||
UserWork work = userWorkService.createWorkFromTask(taskQueue.getTaskId(), resultUrl);
|
|
||||||
logger.info("创建用户作品成功: {}, 任务ID: {}", work.getId(), taskQueue.getTaskId());
|
|
||||||
} catch (Exception workException) {
|
|
||||||
logger.error("创建用户作品失败: {}", taskQueue.getTaskId(), workException);
|
|
||||||
// 作品创建失败不影响任务完成状态
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新原始任务状态
|
|
||||||
updateOriginalTaskStatus(taskQueue, "COMPLETED", resultUrl, null);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 前端集成示例
|
|
||||||
|
|
||||||
### 获取我的作品列表
|
|
||||||
```javascript
|
|
||||||
const getMyWorks = async (page = 0, size = 10) => {
|
|
||||||
const response = await fetch(`/api/works/my-works?page=${page}&size=${size}`, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### 更新作品信息
|
|
||||||
```javascript
|
|
||||||
const updateWork = async (workId, updateData) => {
|
|
||||||
const response = await fetch(`/api/works/${workId}`, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${token}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify(updateData)
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **数据一致性**: 确保任务状态与作品状态一致
|
|
||||||
2. **异常处理**: 作品创建失败不影响任务完成
|
|
||||||
3. **存储管理**: 定期清理过期的失败作品
|
|
||||||
4. **性能监控**: 监控作品查询和统计性能
|
|
||||||
5. **用户体验**: 提供友好的作品管理界面
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
-- 添加个人简介字段到用户表
|
|
||||||
-- 执行此脚本以更新数据库schema
|
|
||||||
|
|
||||||
ALTER TABLE users ADD COLUMN bio TEXT COMMENT '个人简介';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
52
demo/backend/Dockerfile
Normal file
52
demo/backend/Dockerfile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 多阶段构建:构建阶段
|
||||||
|
FROM maven:3.9-eclipse-temurin-21 AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制 pom.xml 并下载依赖(利用Docker缓存)
|
||||||
|
COPY pom.xml .
|
||||||
|
RUN mvn dependency:go-offline -B || true
|
||||||
|
|
||||||
|
# 复制源码
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# 打包应用(跳过测试)
|
||||||
|
RUN mvn clean package -DskipTests -B
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
|
FROM eclipse-temurin:21-jre
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装时区支持和wget(健康检查)
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
tzdata \
|
||||||
|
wget \
|
||||||
|
curl && \
|
||||||
|
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||||
|
echo "Asia/Shanghai" > /etc/timezone && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 创建非root用户(安全考虑)
|
||||||
|
RUN groupadd -r spring && useradd -r -g spring spring
|
||||||
|
|
||||||
|
# 创建必要的目录并设置权限
|
||||||
|
RUN mkdir -p /app/uploads /app/temp /app/logs && \
|
||||||
|
chown -R spring:spring /app
|
||||||
|
|
||||||
|
# 从构建阶段复制JAR文件(项目生成的JAR文件名:demo-0.0.1-SNAPSHOT.jar)
|
||||||
|
COPY --from=builder --chown=spring:spring /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
|
||||||
|
|
||||||
|
# 切换到非root用户
|
||||||
|
USER spring
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# JVM 参数优化(适配50人并发,建议2-4GB内存)
|
||||||
|
ENV JAVA_OPTS="-Xmx2g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Djava.security.egd=file:/dev/./urandom"
|
||||||
|
|
||||||
|
# 健康检查(检查应用是否响应,不依赖Actuator)
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
||||||
48
demo/backend/Dockerfile.java21
Normal file
48
demo/backend/Dockerfile.java21
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# 多阶段构建:构建阶段(适配Java 21)
|
||||||
|
FROM maven:3.9-eclipse-temurin-21 as builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY pom.xml .
|
||||||
|
# 复制源码
|
||||||
|
COPY src ./src
|
||||||
|
# 打包应用(跳过测试)
|
||||||
|
RUN mvn clean package -DskipTests
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
|
FROM eclipse-temurin:21-jre
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装时区支持和wget(健康检查)
|
||||||
|
# FFmpeg 暂时跳过,可稍后手动安装
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
tzdata \
|
||||||
|
wget \
|
||||||
|
curl && \
|
||||||
|
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||||
|
echo "Asia/Shanghai" > /etc/timezone && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 创建非root用户(安全考虑)
|
||||||
|
RUN groupadd -r spring && useradd -r -g spring spring
|
||||||
|
|
||||||
|
# 创建必要的目录并设置权限
|
||||||
|
RUN mkdir -p /app/uploads /app/temp /app/logs && \
|
||||||
|
chown -R spring:spring /app
|
||||||
|
|
||||||
|
USER spring
|
||||||
|
|
||||||
|
# 从构建阶段复制JAR文件(项目生成的JAR文件名:demo-0.0.1-SNAPSHOT.jar)
|
||||||
|
COPY --from=builder --chown=spring:spring /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# JVM 参数优化(适配50人并发,建议2-4GB内存)
|
||||||
|
ENV JAVA_OPTS="-Xmx2g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Djava.security.egd=file:/dev/./urandom"
|
||||||
|
|
||||||
|
# 健康检查(检查应用是否响应,不依赖Actuator)
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
||||||
|
|
||||||
54
demo/backend/Dockerfile.linux
Normal file
54
demo/backend/Dockerfile.linux
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# 多阶段构建:构建阶段
|
||||||
|
FROM maven:3.9-eclipse-temurin-21 AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制 pom.xml 并下载依赖(利用Docker缓存)
|
||||||
|
COPY pom.xml .
|
||||||
|
RUN mvn dependency:go-offline -B || true
|
||||||
|
|
||||||
|
# 复制源码
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# 打包应用(跳过测试)
|
||||||
|
RUN mvn clean package -DskipTests -B
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
|
FROM eclipse-temurin:21-jre
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 安装时区支持和wget(健康检查)
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
tzdata \
|
||||||
|
wget \
|
||||||
|
curl && \
|
||||||
|
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||||
|
echo "Asia/Shanghai" > /etc/timezone && \
|
||||||
|
apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 创建非root用户(安全考虑)
|
||||||
|
RUN groupadd -r spring && useradd -r -g spring spring
|
||||||
|
|
||||||
|
# 创建必要的目录并设置权限
|
||||||
|
RUN mkdir -p /app/uploads /app/temp /app/logs && \
|
||||||
|
chown -R spring:spring /app
|
||||||
|
|
||||||
|
# 从构建阶段复制JAR文件(项目生成的JAR文件名:demo-0.0.1-SNAPSHOT.jar)
|
||||||
|
COPY --from=builder --chown=spring:spring /app/target/demo-0.0.1-SNAPSHOT.jar app.jar
|
||||||
|
|
||||||
|
# 切换到非root用户
|
||||||
|
USER spring
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# JVM 参数优化(适配50人并发,建议2-4GB内存)
|
||||||
|
ENV JAVA_OPTS="-Xmx2g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -Djava.security.egd=file:/dev/./urandom"
|
||||||
|
|
||||||
|
# 健康检查(检查应用是否响应,不依赖Actuator)
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
|
||||||
|
|
||||||
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
-- 取消图生视频任务: img2vid_1957126e9dbd46e2
|
|
||||||
-- 1. 更新任务队列状态为 CANCELLED
|
|
||||||
UPDATE task_queue
|
|
||||||
SET status = 'CANCELLED',
|
|
||||||
error_message = '用户取消了任务',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2';
|
|
||||||
|
|
||||||
-- 2. 更新图生视频任务状态为 CANCELLED
|
|
||||||
UPDATE image_to_video_tasks
|
|
||||||
SET status = 'CANCELLED',
|
|
||||||
error_message = '用户取消了任务',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2';
|
|
||||||
|
|
||||||
-- 3. 更新用户积分(减少冻结积分)
|
|
||||||
-- 注意:只减少 frozen_points,不增加 points(总积分不变)
|
|
||||||
UPDATE users
|
|
||||||
SET frozen_points = frozen_points - (
|
|
||||||
SELECT COALESCE(freeze_points, 0)
|
|
||||||
FROM points_freeze_records
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2'
|
|
||||||
AND status = 'FROZEN'
|
|
||||||
LIMIT 1
|
|
||||||
),
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE username = (
|
|
||||||
SELECT username
|
|
||||||
FROM task_queue
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2'
|
|
||||||
LIMIT 1
|
|
||||||
)
|
|
||||||
AND EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM points_freeze_records
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2'
|
|
||||||
AND status = 'FROZEN'
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 4. 返还冻结的积分(将冻结记录状态改为 RETURNED)
|
|
||||||
UPDATE points_freeze_records
|
|
||||||
SET status = 'RETURNED',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'img2vid_1957126e9dbd46e2'
|
|
||||||
AND status = 'FROZEN';
|
|
||||||
|
|
||||||
-- 5. 查询任务信息(用于确认)
|
|
||||||
SELECT
|
|
||||||
tq.task_id,
|
|
||||||
tq.status as queue_status,
|
|
||||||
tq.username,
|
|
||||||
tq.error_message,
|
|
||||||
itvt.status as task_status,
|
|
||||||
pfr.freeze_points,
|
|
||||||
pfr.status as freeze_status
|
|
||||||
FROM task_queue tq
|
|
||||||
LEFT JOIN image_to_video_tasks itvt ON tq.task_id = itvt.task_id
|
|
||||||
LEFT JOIN points_freeze_records pfr ON tq.task_id = pfr.task_id
|
|
||||||
WHERE tq.task_id = 'img2vid_1957126e9dbd46e2';
|
|
||||||
|
|
||||||
-- 查询结果
|
|
||||||
SELECT '任务已取消' as result;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
-- 取消任务: txt2vid_512378411b084a07
|
|
||||||
-- 1. 更新任务队列状态为 CANCELLED
|
|
||||||
UPDATE task_queue
|
|
||||||
SET status = 'CANCELLED',
|
|
||||||
error_message = '用户取消了任务',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07';
|
|
||||||
|
|
||||||
-- 2. 更新文生视频任务状态为 CANCELLED
|
|
||||||
UPDATE text_to_video_tasks
|
|
||||||
SET status = 'CANCELLED',
|
|
||||||
error_message = '用户取消了任务',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07';
|
|
||||||
|
|
||||||
-- 3. 更新用户积分(减少冻结积分)
|
|
||||||
-- 注意:只减少 frozen_points,不增加 points(总积分不变)
|
|
||||||
UPDATE users
|
|
||||||
SET frozen_points = frozen_points - (
|
|
||||||
SELECT COALESCE(freeze_points, 0)
|
|
||||||
FROM points_freeze_records
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07'
|
|
||||||
AND status = 'FROZEN'
|
|
||||||
LIMIT 1
|
|
||||||
),
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE username = (
|
|
||||||
SELECT username
|
|
||||||
FROM task_queue
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07'
|
|
||||||
LIMIT 1
|
|
||||||
)
|
|
||||||
AND EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM points_freeze_records
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07'
|
|
||||||
AND status = 'FROZEN'
|
|
||||||
);
|
|
||||||
|
|
||||||
-- 4. 返还冻结的积分(将冻结记录状态改为 RETURNED)
|
|
||||||
UPDATE points_freeze_records
|
|
||||||
SET status = 'RETURNED',
|
|
||||||
updated_at = NOW()
|
|
||||||
WHERE task_id = 'txt2vid_512378411b084a07'
|
|
||||||
AND status = 'FROZEN';
|
|
||||||
|
|
||||||
-- 5. 查询任务信息(用于确认)
|
|
||||||
SELECT
|
|
||||||
tq.task_id,
|
|
||||||
tq.status as queue_status,
|
|
||||||
tq.username,
|
|
||||||
tq.error_message,
|
|
||||||
ttvt.status as task_status,
|
|
||||||
pfr.freeze_points,
|
|
||||||
pfr.status as freeze_status
|
|
||||||
FROM task_queue tq
|
|
||||||
LEFT JOIN text_to_video_tasks ttvt ON tq.task_id = ttvt.task_id
|
|
||||||
LEFT JOIN points_freeze_records pfr ON tq.task_id = pfr.task_id
|
|
||||||
WHERE tq.task_id = 'txt2vid_512378411b084a07';
|
|
||||||
|
|
||||||
-- 查询结果
|
|
||||||
SELECT '任务已取消' as result;
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
-- 检查任务队列状态
|
|
||||||
SELECT
|
|
||||||
'task_queue' as table_name,
|
|
||||||
status,
|
|
||||||
COUNT(*) as count
|
|
||||||
FROM task_queue
|
|
||||||
GROUP BY status
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
'image_to_video_tasks' as table_name,
|
|
||||||
status,
|
|
||||||
COUNT(*) as count
|
|
||||||
FROM image_to_video_tasks
|
|
||||||
GROUP BY status;
|
|
||||||
|
|
||||||
-- 查看最近的任务
|
|
||||||
SELECT
|
|
||||||
'Recent Task Queue' as info,
|
|
||||||
task_id,
|
|
||||||
username,
|
|
||||||
task_type,
|
|
||||||
status,
|
|
||||||
real_task_id,
|
|
||||||
check_count,
|
|
||||||
error_message,
|
|
||||||
created_at
|
|
||||||
FROM task_queue
|
|
||||||
ORDER BY created_at DESC
|
|
||||||
LIMIT 10;
|
|
||||||
|
|
||||||
-- 查看最近的图生视频任务
|
|
||||||
SELECT
|
|
||||||
'Recent Image Tasks' as info,
|
|
||||||
task_id,
|
|
||||||
username,
|
|
||||||
status,
|
|
||||||
progress,
|
|
||||||
real_task_id,
|
|
||||||
error_message,
|
|
||||||
first_frame_url,
|
|
||||||
created_at
|
|
||||||
FROM image_to_video_tasks
|
|
||||||
ORDER BY created_at DESC
|
|
||||||
LIMIT 10;
|
|
||||||
|
|
||||||
-- 查看失败的任务详情
|
|
||||||
SELECT
|
|
||||||
'Failed Tasks' as info,
|
|
||||||
tq.task_id,
|
|
||||||
tq.username,
|
|
||||||
tq.status as queue_status,
|
|
||||||
tq.error_message as queue_error,
|
|
||||||
it.status as task_status,
|
|
||||||
it.error_message as task_error,
|
|
||||||
it.first_frame_url,
|
|
||||||
tq.created_at
|
|
||||||
FROM task_queue tq
|
|
||||||
LEFT JOIN image_to_video_tasks it ON tq.task_id = it.task_id
|
|
||||||
WHERE tq.status = 'FAILED' OR it.status = 'FAILED'
|
|
||||||
ORDER BY tq.created_at DESC;
|
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
-- 清除失败任务的SQL脚本
|
|
||||||
-- 数据库:aigc_platform
|
|
||||||
|
|
||||||
-- 1. 清除任务队列中的失败任务
|
|
||||||
DELETE FROM task_queue WHERE status = 'FAILED';
|
|
||||||
|
|
||||||
-- 2. 清除文生视频任务中的失败任务
|
|
||||||
DELETE FROM text_to_video_tasks WHERE status = 'FAILED';
|
|
||||||
|
|
||||||
-- 3. 清除图生视频任务中的失败任务
|
|
||||||
DELETE FROM image_to_video_tasks WHERE status = 'FAILED';
|
|
||||||
|
|
||||||
-- 4. 清除分镜视频任务中的失败任务
|
|
||||||
DELETE FROM storyboard_video_tasks WHERE status = 'FAILED';
|
|
||||||
|
|
||||||
-- 查看删除结果(可选)
|
|
||||||
-- SELECT COUNT(*) as failed_queue_tasks FROM task_queue WHERE status = 'FAILED';
|
|
||||||
-- SELECT COUNT(*) as failed_text_tasks FROM text_to_video_tasks WHERE status = 'FAILED';
|
|
||||||
-- SELECT COUNT(*) as failed_image_tasks FROM image_to_video_tasks WHERE status = 'FAILED';
|
|
||||||
-- SELECT COUNT(*) as failed_storyboard_tasks FROM storyboard_video_tasks WHERE status = 'FAILED';
|
|
||||||
BIN
demo/database_baota_20251108_160249.zip
Normal file
BIN
demo/database_baota_20251108_160249.zip
Normal file
Binary file not shown.
269
demo/database_baota_deploy/README.md
Normal file
269
demo/database_baota_deploy/README.md
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
# AIGC平台 - 宝塔数据库部署包
|
||||||
|
|
||||||
|
## 📦 部署包内容
|
||||||
|
|
||||||
|
```
|
||||||
|
database_baota_deploy/
|
||||||
|
├── init_database.sql # 完整数据库初始化脚本(推荐)
|
||||||
|
├── update_admin_user.sql # 管理员权限设置脚本
|
||||||
|
├── 数据库完整结构-宝塔导入.sql # 备用完整结构
|
||||||
|
├── 宝塔数据库部署指南.md # 详细部署文档
|
||||||
|
├── deploy_database.sh # Linux自动部署脚本
|
||||||
|
└── README.md # 本文件
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 方法一:使用宝塔面板(推荐,适合新手)
|
||||||
|
|
||||||
|
1. **阅读部署指南**
|
||||||
|
```
|
||||||
|
打开 "宝塔数据库部署指南.md" 查看详细步骤
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **创建数据库**
|
||||||
|
- 登录宝塔面板
|
||||||
|
- 数据库 → 添加数据库
|
||||||
|
- 数据库名: `aigc_platform`
|
||||||
|
- 字符集: `utf8mb4`
|
||||||
|
|
||||||
|
3. **导入SQL文件**
|
||||||
|
- 点击数据库的【管理】进入phpMyAdmin
|
||||||
|
- 导入 → 选择文件 → 选择 `init_database.sql`
|
||||||
|
- 执行导入
|
||||||
|
|
||||||
|
4. **配置应用**
|
||||||
|
- 将数据库信息填入 `application-prod.properties`
|
||||||
|
|
||||||
|
### 方法二:使用自动脚本(适合Linux命令行用户)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 上传整个部署包到服务器
|
||||||
|
scp -r database_baota_deploy root@your-server:/root/
|
||||||
|
|
||||||
|
# 2. SSH登录服务器
|
||||||
|
ssh root@your-server
|
||||||
|
|
||||||
|
# 3. 进入部署目录
|
||||||
|
cd /root/database_baota_deploy
|
||||||
|
|
||||||
|
# 4. 给脚本执行权限
|
||||||
|
chmod +x deploy_database.sh
|
||||||
|
|
||||||
|
# 5. 运行自动部署脚本
|
||||||
|
bash deploy_database.sh
|
||||||
|
|
||||||
|
# 6. 按提示输入MySQL root密码和新数据库密码
|
||||||
|
# 7. 等待部署完成,保存输出的数据库配置信息
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方法三:手动命令行部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 登录MySQL
|
||||||
|
mysql -uroot -p
|
||||||
|
|
||||||
|
# 2. 创建数据库
|
||||||
|
CREATE DATABASE aigc_platform DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
# 3. 创建用户
|
||||||
|
CREATE USER 'aigc_platform'@'localhost' IDENTIFIED BY '你的密码';
|
||||||
|
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_platform'@'localhost';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EXIT;
|
||||||
|
|
||||||
|
# 4. 导入数据库
|
||||||
|
mysql -uaigc_platform -p aigc_platform < init_database.sql
|
||||||
|
|
||||||
|
# 5. 验证
|
||||||
|
mysql -uaigc_platform -p
|
||||||
|
USE aigc_platform;
|
||||||
|
SHOW TABLES;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 数据库表清单
|
||||||
|
|
||||||
|
部署成功后应包含以下13个表:
|
||||||
|
|
||||||
|
| 表名 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `users` | 用户表 |
|
||||||
|
| `payments` | 支付记录表 |
|
||||||
|
| `orders` | 订单表 |
|
||||||
|
| `order_items` | 订单明细表 |
|
||||||
|
| `text_to_video_tasks` | 文生视频任务表 |
|
||||||
|
| `image_to_video_tasks` | 图生视频任务表 |
|
||||||
|
| `storyboard_video_tasks` | 分镜视频任务表 |
|
||||||
|
| `task_queue` | 任务队列表 |
|
||||||
|
| `task_status` | 任务状态表 |
|
||||||
|
| `user_works` | 用户作品表 |
|
||||||
|
| `user_membership` | 用户会员表 |
|
||||||
|
| `user_activity_stats` | 用户活动统计表 |
|
||||||
|
| `failed_tasks_cleanup_log` | 失败任务清理日志表 |
|
||||||
|
|
||||||
|
## ⚙️ 应用配置
|
||||||
|
|
||||||
|
### Spring Boot 配置文件
|
||||||
|
|
||||||
|
**文件**: `src/main/resources/application-prod.properties`
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# 数据库配置
|
||||||
|
spring.datasource.url=jdbc:mysql://localhost:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||||
|
spring.datasource.username=aigc_platform
|
||||||
|
spring.datasource.password=你的数据库密码
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
# 数据库连接池配置
|
||||||
|
spring.datasource.hikari.maximum-pool-size=50
|
||||||
|
spring.datasource.hikari.minimum-idle=10
|
||||||
|
spring.datasource.hikari.idle-timeout=300000
|
||||||
|
spring.datasource.hikari.max-lifetime=1200000
|
||||||
|
spring.datasource.hikari.connection-timeout=30000
|
||||||
|
|
||||||
|
# JPA配置
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.show-sql=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### 宝塔反向代理配置(可选)
|
||||||
|
|
||||||
|
如果使用宝塔的Nginx反向代理:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:8080;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 管理员账号
|
||||||
|
|
||||||
|
### 默认管理员邮箱
|
||||||
|
|
||||||
|
```
|
||||||
|
984523799@qq.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 设置流程
|
||||||
|
|
||||||
|
1. **首次注册**
|
||||||
|
- 使用 `984523799@qq.com` 在前端注册账号
|
||||||
|
- 数据库会自动将此用户设置为管理员
|
||||||
|
|
||||||
|
2. **手动设置**
|
||||||
|
- 如果自动设置未生效,执行 `update_admin_user.sql`
|
||||||
|
|
||||||
|
3. **验证权限**
|
||||||
|
```sql
|
||||||
|
SELECT id, username, email, role, points
|
||||||
|
FROM users
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
|
```
|
||||||
|
- `role` 字段应为 `ROLE_ADMIN`
|
||||||
|
|
||||||
|
## 🛠️ 故障排查
|
||||||
|
|
||||||
|
### 导入失败
|
||||||
|
|
||||||
|
**问题**: 导入SQL时报错
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 确保数据库字符集为 `utf8mb4`
|
||||||
|
2. 检查SQL文件编码为 UTF-8
|
||||||
|
3. 尝试分段导入或使用命令行导入
|
||||||
|
|
||||||
|
### 连接失败
|
||||||
|
|
||||||
|
**问题**: 应用无法连接数据库
|
||||||
|
|
||||||
|
**检查项**:
|
||||||
|
1. MySQL服务是否运行: `systemctl status mysql`
|
||||||
|
2. 用户名密码是否正确
|
||||||
|
3. 数据库名称是否正确
|
||||||
|
4. 防火墙是否开放3306端口(如需远程连接)
|
||||||
|
5. MySQL是否允许远程连接(`bind-address`配置)
|
||||||
|
|
||||||
|
### 权限问题
|
||||||
|
|
||||||
|
**问题**: Access denied
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
```sql
|
||||||
|
-- 重新授权
|
||||||
|
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_platform'@'localhost';
|
||||||
|
GRANT ALL PRIVILEGES ON aigc_platform.* TO 'aigc_platform'@'%';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 数据库维护
|
||||||
|
|
||||||
|
### 定期备份
|
||||||
|
|
||||||
|
**宝塔面板**:
|
||||||
|
- 计划任务 → 添加任务
|
||||||
|
- 任务类型: 备份数据库
|
||||||
|
- 执行周期: 每天凌晨3点
|
||||||
|
- 保留份数: 7-30份
|
||||||
|
|
||||||
|
**命令行备份**:
|
||||||
|
```bash
|
||||||
|
# 手动备份
|
||||||
|
mysqldump -uaigc_platform -p aigc_platform > backup_$(date +%Y%m%d_%H%M%S).sql
|
||||||
|
|
||||||
|
# 定时备份(添加到crontab)
|
||||||
|
0 3 * * * mysqldump -uaigc_platform -p'密码' aigc_platform > /backup/aigc_$(date +\%Y\%m\%d).sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 性能优化
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 查看表大小
|
||||||
|
SELECT
|
||||||
|
table_name,
|
||||||
|
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)"
|
||||||
|
FROM information_schema.TABLES
|
||||||
|
WHERE table_schema = 'aigc_platform'
|
||||||
|
ORDER BY (data_length + index_length) DESC;
|
||||||
|
|
||||||
|
-- 优化表
|
||||||
|
OPTIMIZE TABLE users;
|
||||||
|
OPTIMIZE TABLE text_to_video_tasks;
|
||||||
|
OPTIMIZE TABLE image_to_video_tasks;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
遇到问题?
|
||||||
|
|
||||||
|
1. **查看日志**
|
||||||
|
- 宝塔面板: 数据库 → 日志
|
||||||
|
- 命令行: `/var/log/mysql/error.log`
|
||||||
|
|
||||||
|
2. **查看文档**
|
||||||
|
- 详细部署指南: `宝塔数据库部署指南.md`
|
||||||
|
|
||||||
|
3. **验证数据库**
|
||||||
|
```bash
|
||||||
|
mysql -uaigc_platform -p -e "USE aigc_platform; SHOW TABLES;"
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ 部署检查清单
|
||||||
|
|
||||||
|
- [ ] MySQL服务正在运行
|
||||||
|
- [ ] 数据库 `aigc_platform` 已创建
|
||||||
|
- [ ] 字符集为 `utf8mb4`
|
||||||
|
- [ ] 用户 `aigc_platform` 已创建并授权
|
||||||
|
- [ ] 13个数据表已创建
|
||||||
|
- [ ] 管理员邮箱 `984523799@qq.com` 已配置
|
||||||
|
- [ ] 应用配置文件已更新数据库信息
|
||||||
|
- [ ] 数据库备份计划已设置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**版本**: 1.0
|
||||||
|
**更新日期**: 2025-11-10
|
||||||
|
**适用系统**: 宝塔面板 / Linux / MySQL 8.0+
|
||||||
141
demo/database_baota_deploy/deploy_database.sh
Normal file
141
demo/database_baota_deploy/deploy_database.sh
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 宝塔数据库快速部署脚本
|
||||||
|
# 使用方法:bash deploy_database.sh
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo " AIGC平台 - 宝塔数据库部署脚本"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
DB_NAME="aigc_platform"
|
||||||
|
DB_USER="aigc_platform"
|
||||||
|
DB_CHARSET="utf8mb4"
|
||||||
|
DB_COLLATE="utf8mb4_unicode_ci"
|
||||||
|
|
||||||
|
# 检查是否为root用户
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo -e "${RED}请使用root权限运行此脚本${NC}"
|
||||||
|
echo "使用方法: sudo bash deploy_database.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "步骤 1/5: 检查MySQL服务状态..."
|
||||||
|
if systemctl is-active --quiet mysql || systemctl is-active --quiet mysqld || systemctl is-active --quiet mariadb; then
|
||||||
|
echo -e "${GREEN}✓ MySQL服务正在运行${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ MySQL服务未运行${NC}"
|
||||||
|
echo "正在启动MySQL服务..."
|
||||||
|
systemctl start mysql || systemctl start mysqld || systemctl start mariadb
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "步骤 2/5: 输入MySQL root密码"
|
||||||
|
read -sp "请输入MySQL root密码: " MYSQL_ROOT_PASSWORD
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 测试MySQL连接
|
||||||
|
echo "测试MySQL连接..."
|
||||||
|
mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT 1;" > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e "${RED}✗ MySQL连接失败,请检查root密码${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ MySQL连接成功${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "步骤 3/5: 创建数据库和用户"
|
||||||
|
read -sp "请输入新数据库用户的密码(按回车使用随机密码): " DB_PASSWORD
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -z "$DB_PASSWORD" ]; then
|
||||||
|
# 生成随机密码
|
||||||
|
DB_PASSWORD=$(openssl rand -base64 16)
|
||||||
|
echo -e "${YELLOW}已生成随机密码: $DB_PASSWORD${NC}"
|
||||||
|
echo -e "${YELLOW}请务必保存此密码!${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 创建数据库
|
||||||
|
mysql -uroot -p"$MYSQL_ROOT_PASSWORD" <<EOF
|
||||||
|
-- 删除旧数据库(如果存在)
|
||||||
|
DROP DATABASE IF EXISTS \`$DB_NAME\`;
|
||||||
|
|
||||||
|
-- 创建新数据库
|
||||||
|
CREATE DATABASE \`$DB_NAME\` DEFAULT CHARACTER SET $DB_CHARSET COLLATE $DB_COLLATE;
|
||||||
|
|
||||||
|
-- 创建用户(如果不存在)
|
||||||
|
CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
|
||||||
|
CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASSWORD';
|
||||||
|
|
||||||
|
-- 授权
|
||||||
|
GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_USER'@'localhost';
|
||||||
|
GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_USER'@'%';
|
||||||
|
|
||||||
|
-- 刷新权限
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ 数据库和用户创建成功${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 数据库创建失败${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "步骤 4/5: 导入数据库结构"
|
||||||
|
if [ -f "init_database.sql" ]; then
|
||||||
|
mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < init_database.sql
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ 数据库结构导入成功${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 数据库结构导入失败${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 找不到 init_database.sql 文件${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "步骤 5/5: 验证数据库"
|
||||||
|
TABLE_COUNT=$(mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -sN -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';")
|
||||||
|
echo "已创建 $TABLE_COUNT 个数据表"
|
||||||
|
|
||||||
|
if [ "$TABLE_COUNT" -ge 13 ]; then
|
||||||
|
echo -e "${GREEN}✓ 数据库部署成功!${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠ 表数量少于预期(预期13个,实际$TABLE_COUNT个)${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo " 部署完成!"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "数据库信息:"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo "数据库名: $DB_NAME"
|
||||||
|
echo "用户名: $DB_USER"
|
||||||
|
echo "密码: $DB_PASSWORD"
|
||||||
|
echo "字符集: $DB_CHARSET"
|
||||||
|
echo "排序规则: $DB_COLLATE"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo ""
|
||||||
|
echo "请将以下配置添加到 application-prod.properties:"
|
||||||
|
echo ""
|
||||||
|
echo "spring.datasource.url=jdbc:mysql://localhost:3306/$DB_NAME?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai"
|
||||||
|
echo "spring.datasource.username=$DB_USER"
|
||||||
|
echo "spring.datasource.password=$DB_PASSWORD"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}请务必保存数据库密码!${NC}"
|
||||||
|
echo ""
|
||||||
467
demo/database_baota_deploy/init_database.sql
Normal file
467
demo/database_baota_deploy/init_database.sql
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- 宝塔面板数据库初始化SQL文件
|
||||||
|
-- 适用于MySQL/MariaDB数据库
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 创建数据库(如果不存在,请根据实际情况修改数据库名)
|
||||||
|
-- CREATE DATABASE IF NOT EXISTS `aigc_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
-- USE `aigc_db`;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 基础表结构
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 用户表
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
username VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
email VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
password_hash VARCHAR(100) NOT NULL,
|
||||||
|
role VARCHAR(30) NOT NULL DEFAULT 'ROLE_USER',
|
||||||
|
points INT NOT NULL DEFAULT 50,
|
||||||
|
frozen_points INT NOT NULL DEFAULT 0 COMMENT '冻结积分',
|
||||||
|
phone VARCHAR(20),
|
||||||
|
avatar TEXT COMMENT '头像URL',
|
||||||
|
nickname VARCHAR(100),
|
||||||
|
gender VARCHAR(10),
|
||||||
|
birthday DATE,
|
||||||
|
address TEXT,
|
||||||
|
bio TEXT COMMENT '个人简介',
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
last_login_at TIMESTAMP NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_email (email),
|
||||||
|
INDEX idx_role (role),
|
||||||
|
INDEX idx_is_active (is_active),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
|
||||||
|
|
||||||
|
-- 支付表
|
||||||
|
CREATE TABLE IF NOT EXISTS payments (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
order_id VARCHAR(50) NOT NULL COMMENT '订单号(不唯一,一个订单可以有多次支付尝试)',
|
||||||
|
amount DECIMAL(10,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) NOT NULL DEFAULT 'CNY',
|
||||||
|
payment_method VARCHAR(20) NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '支付状态:PENDING, PROCESSING, SUCCESS, FAILED, CANCELLED',
|
||||||
|
description VARCHAR(500),
|
||||||
|
external_transaction_id VARCHAR(100) COMMENT '外部交易号(支付宝交易号等)',
|
||||||
|
callback_url VARCHAR(1000),
|
||||||
|
return_url VARCHAR(1000),
|
||||||
|
payment_url VARCHAR(2000) COMMENT '支付跳转URL',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
paid_at TIMESTAMP NULL,
|
||||||
|
user_id BIGINT COMMENT '用户ID',
|
||||||
|
order_id_ref BIGINT COMMENT '关联的订单ID(外键)',
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (order_id_ref) REFERENCES orders(id) ON DELETE SET NULL,
|
||||||
|
INDEX idx_order_id (order_id),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_payment_method (payment_method),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付表';
|
||||||
|
|
||||||
|
-- 订单表
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
order_number VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
total_amount DECIMAL(10,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) NOT NULL DEFAULT 'CNY',
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||||||
|
order_type VARCHAR(20) NOT NULL DEFAULT 'PRODUCT',
|
||||||
|
description VARCHAR(500),
|
||||||
|
notes TEXT,
|
||||||
|
shipping_address TEXT,
|
||||||
|
billing_address TEXT,
|
||||||
|
contact_phone VARCHAR(20),
|
||||||
|
contact_email VARCHAR(100),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
paid_at TIMESTAMP NULL,
|
||||||
|
shipped_at TIMESTAMP NULL,
|
||||||
|
delivered_at TIMESTAMP NULL,
|
||||||
|
cancelled_at TIMESTAMP NULL,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
|
INDEX idx_order_number (order_number),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单表';
|
||||||
|
|
||||||
|
-- 订单项表
|
||||||
|
CREATE TABLE IF NOT EXISTS order_items (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
product_name VARCHAR(100) NOT NULL,
|
||||||
|
product_description VARCHAR(500),
|
||||||
|
product_sku VARCHAR(200),
|
||||||
|
unit_price DECIMAL(10,2) NOT NULL,
|
||||||
|
quantity INT NOT NULL,
|
||||||
|
subtotal DECIMAL(10,2) NOT NULL,
|
||||||
|
product_image VARCHAR(100),
|
||||||
|
order_id BIGINT NOT NULL,
|
||||||
|
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
|
||||||
|
INDEX idx_order_id (order_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单项表';
|
||||||
|
|
||||||
|
-- 会员等级表
|
||||||
|
CREATE TABLE IF NOT EXISTS membership_levels (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
name VARCHAR(50) NOT NULL UNIQUE COMMENT '等级名称(内部标识)',
|
||||||
|
display_name VARCHAR(50) NOT NULL COMMENT '显示名称',
|
||||||
|
description TEXT COMMENT '描述',
|
||||||
|
price DECIMAL(10,2) NOT NULL DEFAULT 0 COMMENT '价格(元)',
|
||||||
|
duration_days INT NOT NULL DEFAULT 30 COMMENT '时长(天)',
|
||||||
|
points_bonus INT NOT NULL DEFAULT 0 COMMENT '积分奖励',
|
||||||
|
resource_points INT NOT NULL DEFAULT 0 COMMENT '资源点数量',
|
||||||
|
features JSON COMMENT '功能特性(JSON格式)',
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否启用',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
INDEX idx_name (name),
|
||||||
|
INDEX idx_is_active (is_active)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会员等级表';
|
||||||
|
|
||||||
|
-- 用户会员信息表
|
||||||
|
CREATE TABLE IF NOT EXISTS user_memberships (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
membership_level_id BIGINT NOT NULL,
|
||||||
|
start_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
end_date TIMESTAMP NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
auto_renew BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (membership_level_id) REFERENCES membership_levels(id),
|
||||||
|
UNIQUE KEY unique_active_membership (user_id, status),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_end_date (end_date)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户会员信息表';
|
||||||
|
|
||||||
|
-- 视频生成任务表
|
||||||
|
CREATE TABLE IF NOT EXISTS video_tasks (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
task_id VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL COMMENT 'TEXT_TO_VIDEO, IMAGE_TO_VIDEO, STORYBOARD_VIDEO',
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
input_text TEXT,
|
||||||
|
input_image_url VARCHAR(500),
|
||||||
|
output_video_url VARCHAR(500),
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT 'PENDING, PROCESSING, COMPLETED, FAILED',
|
||||||
|
progress INT NOT NULL DEFAULT 0,
|
||||||
|
error_message TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
completed_at TIMESTAMP NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='视频生成任务表';
|
||||||
|
|
||||||
|
-- 系统配置表
|
||||||
|
CREATE TABLE IF NOT EXISTS system_configs (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
config_key VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
config_value TEXT,
|
||||||
|
description VARCHAR(500),
|
||||||
|
config_type VARCHAR(50) NOT NULL DEFAULT 'STRING' COMMENT 'STRING, NUMBER, BOOLEAN, JSON',
|
||||||
|
is_public BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_config_key (config_key)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表';
|
||||||
|
|
||||||
|
-- 系统设置表(用于存储系统级别的设置)
|
||||||
|
CREATE TABLE IF NOT EXISTS system_settings (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
standard_price_cny INT NOT NULL DEFAULT 0 COMMENT '标准版价格(元)',
|
||||||
|
pro_price_cny INT NOT NULL DEFAULT 0 COMMENT '专业版价格(元)',
|
||||||
|
points_per_generation INT NOT NULL DEFAULT 1 COMMENT '每次生成消耗的资源点',
|
||||||
|
site_name VARCHAR(100) NOT NULL DEFAULT 'AIGC Demo' COMMENT '站点名称',
|
||||||
|
site_subtitle VARCHAR(150) NOT NULL DEFAULT '现代化的Spring Boot应用演示' COMMENT '站点副标题',
|
||||||
|
registration_open BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开放注册',
|
||||||
|
maintenance_mode BOOLEAN NOT NULL DEFAULT FALSE COMMENT '维护模式',
|
||||||
|
enable_alipay BOOLEAN NOT NULL DEFAULT TRUE COMMENT '启用支付宝',
|
||||||
|
enable_paypal BOOLEAN NOT NULL DEFAULT TRUE COMMENT '启用PayPal',
|
||||||
|
contact_email VARCHAR(120) DEFAULT 'support@example.com' COMMENT '联系邮箱'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统设置表';
|
||||||
|
|
||||||
|
-- 用户活跃度统计表
|
||||||
|
CREATE TABLE IF NOT EXISTS user_activity_stats (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '统计ID',
|
||||||
|
activity_date DATE NOT NULL UNIQUE COMMENT '统计日期',
|
||||||
|
daily_active_users INT NOT NULL DEFAULT 0 COMMENT '日活用户数',
|
||||||
|
monthly_active_users INT NOT NULL DEFAULT 0 COMMENT '月活用户数',
|
||||||
|
new_users INT NOT NULL DEFAULT 0 COMMENT '新增用户数',
|
||||||
|
returning_users INT NOT NULL DEFAULT 0 COMMENT '回访用户数',
|
||||||
|
session_count INT NOT NULL DEFAULT 0 COMMENT '会话数',
|
||||||
|
avg_session_duration DECIMAL(10,2) DEFAULT 0 COMMENT '平均会话时长(分钟)',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
UNIQUE KEY uk_activity_date (activity_date),
|
||||||
|
INDEX idx_activity_date (activity_date)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户活跃度统计表';
|
||||||
|
|
||||||
|
-- 文生视频任务表
|
||||||
|
CREATE TABLE IF NOT EXISTS text_to_video_tasks (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '任务ID',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务唯一标识',
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
prompt TEXT COMMENT '文本描述/提示词',
|
||||||
|
aspect_ratio VARCHAR(10) NOT NULL DEFAULT '16:9' COMMENT '宽高比:16:9, 4:3, 1:1, 3:4, 9:16',
|
||||||
|
duration INT NOT NULL DEFAULT 5 COMMENT '视频时长(秒):5, 10, 15, 30',
|
||||||
|
hd_mode BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否高清模式',
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态:PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED',
|
||||||
|
progress INT NOT NULL DEFAULT 0 COMMENT '进度(0-100)',
|
||||||
|
result_url TEXT COMMENT '结果视频URL',
|
||||||
|
real_task_id VARCHAR(100) COMMENT '外部API返回的真实任务ID',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
cost_points INT NOT NULL DEFAULT 0 COMMENT '消耗积分',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_real_task_id (real_task_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='文生视频任务表';
|
||||||
|
|
||||||
|
-- 图生视频任务表
|
||||||
|
CREATE TABLE IF NOT EXISTS image_to_video_tasks (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '任务ID',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务唯一标识',
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
first_frame_url VARCHAR(500) NOT NULL COMMENT '首帧图片URL',
|
||||||
|
last_frame_url VARCHAR(500) COMMENT '末帧图片URL',
|
||||||
|
prompt TEXT COMMENT '文本描述/提示词',
|
||||||
|
aspect_ratio VARCHAR(10) NOT NULL DEFAULT '16:9' COMMENT '宽高比:16:9, 4:3, 1:1, 3:4, 9:16',
|
||||||
|
duration INT NOT NULL DEFAULT 5 COMMENT '视频时长(秒):5, 10, 15, 30',
|
||||||
|
hd_mode BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否高清模式',
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态:PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED',
|
||||||
|
progress INT NOT NULL DEFAULT 0 COMMENT '进度(0-100)',
|
||||||
|
result_url TEXT COMMENT '结果视频URL',
|
||||||
|
real_task_id VARCHAR(100) COMMENT '外部API返回的真实任务ID',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
cost_points INT NOT NULL DEFAULT 0 COMMENT '消耗积分',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_real_task_id (real_task_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='图生视频任务表';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 任务队列相关表
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 任务队列表
|
||||||
|
CREATE TABLE IF NOT EXISTS task_queue (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO', 'STORYBOARD_VIDEO') NOT NULL COMMENT '任务类型',
|
||||||
|
status ENUM('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED', 'TIMEOUT') NOT NULL DEFAULT 'PENDING' COMMENT '队列状态',
|
||||||
|
priority INT NOT NULL DEFAULT 0 COMMENT '优先级,数字越小优先级越高',
|
||||||
|
real_task_id VARCHAR(100) COMMENT '外部API返回的真实任务ID',
|
||||||
|
last_check_time DATETIME COMMENT '最后一次检查时间',
|
||||||
|
check_count INT NOT NULL DEFAULT 0 COMMENT '检查次数',
|
||||||
|
max_check_count INT NOT NULL DEFAULT 30 COMMENT '最大检查次数(30次 * 2分钟 = 60分钟)',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_status_priority (status, priority),
|
||||||
|
INDEX idx_last_check_time (last_check_time),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务队列表';
|
||||||
|
|
||||||
|
-- 积分冻结记录表
|
||||||
|
CREATE TABLE IF NOT EXISTS points_freeze_records (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO', 'STORYBOARD_VIDEO') NOT NULL COMMENT '任务类型',
|
||||||
|
freeze_points INT NOT NULL COMMENT '冻结的积分数量',
|
||||||
|
status ENUM('FROZEN', 'DEDUCTED', 'RETURNED', 'EXPIRED') NOT NULL DEFAULT 'FROZEN' COMMENT '冻结状态',
|
||||||
|
freeze_reason VARCHAR(200) COMMENT '冻结原因',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='积分冻结记录表';
|
||||||
|
|
||||||
|
-- 用户作品表
|
||||||
|
CREATE TABLE IF NOT EXISTS user_works (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
work_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO', 'STORYBOARD_VIDEO') NOT NULL COMMENT '作品类型',
|
||||||
|
title VARCHAR(200) COMMENT '作品标题',
|
||||||
|
description TEXT COMMENT '作品描述',
|
||||||
|
prompt TEXT COMMENT '生成提示词',
|
||||||
|
result_url VARCHAR(500) COMMENT '结果视频URL',
|
||||||
|
thumbnail_url VARCHAR(500) COMMENT '缩略图URL',
|
||||||
|
duration VARCHAR(10) COMMENT '视频时长',
|
||||||
|
aspect_ratio VARCHAR(10) COMMENT '宽高比',
|
||||||
|
quality VARCHAR(20) COMMENT '画质',
|
||||||
|
file_size VARCHAR(20) COMMENT '文件大小',
|
||||||
|
points_cost INT NOT NULL DEFAULT 0 COMMENT '消耗积分',
|
||||||
|
status ENUM('PROCESSING', 'COMPLETED', 'FAILED', 'DELETED') NOT NULL DEFAULT 'PROCESSING' COMMENT '作品状态',
|
||||||
|
is_public BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否公开',
|
||||||
|
view_count INT NOT NULL DEFAULT 0 COMMENT '浏览次数',
|
||||||
|
like_count INT NOT NULL DEFAULT 0 COMMENT '点赞次数',
|
||||||
|
download_count INT NOT NULL DEFAULT 0 COMMENT '下载次数',
|
||||||
|
tags VARCHAR(500) COMMENT '标签',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_work_type (work_type),
|
||||||
|
INDEX idx_is_public_status (is_public, status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_view_count (view_count),
|
||||||
|
INDEX idx_like_count (like_count),
|
||||||
|
INDEX idx_tags (tags),
|
||||||
|
INDEX idx_prompt (prompt(100))
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户作品表';
|
||||||
|
|
||||||
|
-- 任务状态表
|
||||||
|
CREATE TABLE IF NOT EXISTS task_status (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL COMMENT '任务ID',
|
||||||
|
username VARCHAR(255) NOT NULL COMMENT '用户名',
|
||||||
|
task_type VARCHAR(50) NOT NULL COMMENT '任务类型',
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态',
|
||||||
|
progress INT DEFAULT 0 COMMENT '进度百分比',
|
||||||
|
result_url TEXT COMMENT '结果URL',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
external_task_id VARCHAR(255) COMMENT '外部任务ID',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||||||
|
last_polled_at TIMESTAMP NULL COMMENT '最后轮询时间',
|
||||||
|
poll_count INT DEFAULT 0 COMMENT '轮询次数',
|
||||||
|
max_polls INT DEFAULT 60 COMMENT '最大轮询次数(2小时)',
|
||||||
|
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_last_polled (last_polled_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务状态表';
|
||||||
|
|
||||||
|
-- 成功任务归档表
|
||||||
|
CREATE TABLE IF NOT EXISTS completed_tasks_archive (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL,
|
||||||
|
prompt TEXT,
|
||||||
|
aspect_ratio VARCHAR(20),
|
||||||
|
duration INT,
|
||||||
|
hd_mode BOOLEAN DEFAULT FALSE,
|
||||||
|
result_url TEXT,
|
||||||
|
real_task_id VARCHAR(255),
|
||||||
|
progress INT DEFAULT 100,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
completed_at TIMESTAMP NOT NULL,
|
||||||
|
archived_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
points_cost INT DEFAULT 0,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_task_type (task_type),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_completed_at (completed_at),
|
||||||
|
INDEX idx_archived_at (archived_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成功任务归档表';
|
||||||
|
|
||||||
|
-- 失败任务清理日志表
|
||||||
|
CREATE TABLE IF NOT EXISTS failed_tasks_cleanup_log (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL,
|
||||||
|
error_message TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
failed_at TIMESTAMP NOT NULL,
|
||||||
|
cleaned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_task_type (task_type),
|
||||||
|
INDEX idx_cleaned_at (cleaned_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='失败任务清理日志表';
|
||||||
|
|
||||||
|
-- 分镜视频任务表
|
||||||
|
CREATE TABLE IF NOT EXISTS storyboard_video_tasks (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
username VARCHAR(100) NOT NULL,
|
||||||
|
prompt TEXT COMMENT '文本描述/提示词',
|
||||||
|
image_url TEXT COMMENT '上传的参考图片URL(可选)',
|
||||||
|
aspect_ratio VARCHAR(10) NOT NULL COMMENT '宽高比:16:9, 4:3, 1:1, 3:4, 9:16',
|
||||||
|
hd_mode BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否高清模式',
|
||||||
|
status VARCHAR(20) NOT NULL COMMENT '任务状态:PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED',
|
||||||
|
progress INT NOT NULL DEFAULT 0 COMMENT '进度(0-100)',
|
||||||
|
result_url LONGTEXT COMMENT '分镜图URL(Base64编码的图片,可能非常大)- 网格图',
|
||||||
|
storyboard_images LONGTEXT COMMENT '单独的分镜图片(JSON数组,每张图片为Base64格式,带data URI前缀)',
|
||||||
|
real_task_id VARCHAR(255) COMMENT '外部API返回的真实任务ID',
|
||||||
|
video_task_ids TEXT COMMENT '多个视频任务ID(JSON数组,每张图片对应一个视频任务)',
|
||||||
|
video_urls LONGTEXT COMMENT '多个视频URL(JSON数组,用于拼接)',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
cost_points INT NOT NULL DEFAULT 0 COMMENT '消耗积分',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='分镜视频任务表';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 初始化完成
|
||||||
|
-- ============================================
|
||||||
|
-- 所有表结构已创建完成
|
||||||
|
-- 注意:此文件仅创建表结构,不包含初始数据
|
||||||
|
-- 如需初始化数据,请通过系统管理界面或API进行
|
||||||
|
--
|
||||||
|
-- 宝塔面板使用说明:
|
||||||
|
-- 1. 登录宝塔面板,进入"数据库" -> "phpMyAdmin"
|
||||||
|
-- 2. 选择或创建数据库(建议数据库名:aigc_platform)
|
||||||
|
-- 3. 点击"导入" -> 选择此SQL文件 -> 执行
|
||||||
|
-- 4. 或者使用命令行:mysql -u用户名 -p数据库名 < init_database.sql
|
||||||
|
--
|
||||||
|
-- 数据库配置建议:
|
||||||
|
-- - 数据库名:aigc_platform
|
||||||
|
-- - 字符集:utf8mb4
|
||||||
|
-- - 排序规则:utf8mb4_unicode_ci
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 管理员权限设置
|
||||||
|
-- ============================================
|
||||||
|
-- 将 984523799@qq.com 设置为管理员
|
||||||
|
-- 如果该用户存在,则更新其角色为管理员
|
||||||
|
UPDATE users
|
||||||
|
SET role = 'ROLE_ADMIN',
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
|
|
||||||
13
demo/database_baota_deploy/update_admin_user.sql
Normal file
13
demo/database_baota_deploy/update_admin_user.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- 将 984523799@qq.com 设置为管理员
|
||||||
|
-- 执行此脚本前请确保已连接到正确的数据库
|
||||||
|
|
||||||
|
-- 更新用户角色为管理员
|
||||||
|
UPDATE users
|
||||||
|
SET role = 'ROLE_ADMIN',
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
|
|
||||||
|
-- 验证更新结果
|
||||||
|
SELECT id, username, email, role, points, is_active, created_at, updated_at
|
||||||
|
FROM users
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
224
demo/database_baota_deploy/宝塔数据库部署指南.md
Normal file
224
demo/database_baota_deploy/宝塔数据库部署指南.md
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# 宝塔面板数据库部署指南
|
||||||
|
|
||||||
|
## 📋 部署清单
|
||||||
|
|
||||||
|
本部署包包含以下文件:
|
||||||
|
- `init_database.sql` - 完整的数据库初始化脚本(推荐使用)
|
||||||
|
- `update_admin_user.sql` - 管理员权限设置脚本
|
||||||
|
- `数据库完整结构-宝塔导入.sql` - 备用完整结构文件
|
||||||
|
|
||||||
|
## 🚀 快速部署步骤
|
||||||
|
|
||||||
|
### 第一步:创建数据库
|
||||||
|
|
||||||
|
1. 登录宝塔面板
|
||||||
|
2. 进入【数据库】菜单
|
||||||
|
3. 点击【添加数据库】
|
||||||
|
4. 填写以下信息:
|
||||||
|
- **数据库名**: `aigc_platform`
|
||||||
|
- **用户名**: `aigc_platform`(建议与数据库名相同)
|
||||||
|
- **密码**: 自动生成或自定义(请记录下来)
|
||||||
|
- **字符集**: `utf8mb4`
|
||||||
|
- **排序规则**: `utf8mb4_unicode_ci`
|
||||||
|
5. 点击【提交】创建数据库
|
||||||
|
|
||||||
|
### 第二步:导入数据库结构
|
||||||
|
|
||||||
|
#### 方式一:使用phpMyAdmin(推荐)
|
||||||
|
|
||||||
|
1. 在宝塔面板【数据库】列表中,找到 `aigc_platform` 数据库
|
||||||
|
2. 点击右侧的【管理】按钮,进入 phpMyAdmin
|
||||||
|
3. 点击顶部菜单【导入】
|
||||||
|
4. 点击【选择文件】,选择 `init_database.sql`
|
||||||
|
5. 确保以下设置:
|
||||||
|
- 字符集:`utf8mb4`
|
||||||
|
- 格式:`SQL`
|
||||||
|
6. 点击页面底部【执行】按钮
|
||||||
|
7. 等待导入完成,显示成功提示
|
||||||
|
|
||||||
|
#### 方式二:使用命令行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH登录服务器后执行
|
||||||
|
mysql -u aigc_platform -p aigc_platform < init_database.sql
|
||||||
|
# 输入数据库密码后回车
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第三步:设置管理员权限
|
||||||
|
|
||||||
|
导入完成后,需要设置管理员账号权限:
|
||||||
|
|
||||||
|
#### 方式一:自动设置(已包含在init_database.sql中)
|
||||||
|
|
||||||
|
如果使用 `init_database.sql` 导入,管理员权限已自动设置,无需额外操作。
|
||||||
|
|
||||||
|
#### 方式二:手动设置
|
||||||
|
|
||||||
|
如果需要手动设置或更改管理员,可以执行 `update_admin_user.sql`:
|
||||||
|
|
||||||
|
1. 在 phpMyAdmin 中点击【SQL】标签
|
||||||
|
2. 将 `update_admin_user.sql` 的内容粘贴到文本框
|
||||||
|
3. 点击【执行】
|
||||||
|
|
||||||
|
或者直接在SQL中执行:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
UPDATE users
|
||||||
|
SET role = 'ROLE_ADMIN',
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第四步:验证数据库
|
||||||
|
|
||||||
|
在 phpMyAdmin 或命令行中执行以下查询,验证表结构是否正确:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 查看所有表
|
||||||
|
SHOW TABLES;
|
||||||
|
|
||||||
|
-- 验证管理员用户(如果已注册)
|
||||||
|
SELECT id, username, email, role, points, created_at
|
||||||
|
FROM users
|
||||||
|
WHERE email = '984523799@qq.com';
|
||||||
|
```
|
||||||
|
|
||||||
|
应该看到以下表:
|
||||||
|
- `users` - 用户表
|
||||||
|
- `payments` - 支付表
|
||||||
|
- `orders` - 订单表
|
||||||
|
- `order_items` - 订单项表
|
||||||
|
- `text_to_video_tasks` - 文生视频任务表
|
||||||
|
- `image_to_video_tasks` - 图生视频任务表
|
||||||
|
- `storyboard_video_tasks` - 分镜视频任务表
|
||||||
|
- `task_queue` - 任务队列表
|
||||||
|
- `task_status` - 任务状态表
|
||||||
|
- `user_works` - 用户作品表
|
||||||
|
- `user_membership` - 会员表
|
||||||
|
- `user_activity_stats` - 用户活动统计表
|
||||||
|
- `failed_tasks_cleanup_log` - 失败任务清理日志表
|
||||||
|
|
||||||
|
## 📝 数据库配置信息
|
||||||
|
|
||||||
|
部署完成后,需要在应用配置文件中填写数据库信息:
|
||||||
|
|
||||||
|
**文件位置**: `src/main/resources/application-prod.properties`
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# 数据库配置
|
||||||
|
spring.datasource.url=jdbc:mysql://服务器IP:3306/aigc_platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||||
|
spring.datasource.username=aigc_platform
|
||||||
|
spring.datasource.password=你的数据库密码
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
```
|
||||||
|
|
||||||
|
**重要参数说明**:
|
||||||
|
- `服务器IP`:
|
||||||
|
- 如果应用与数据库在同一服务器:使用 `localhost` 或 `127.0.0.1`
|
||||||
|
- 如果数据库在其他服务器:使用数据库服务器的IP地址
|
||||||
|
- `你的数据库密码`: 第一步创建数据库时设置的密码
|
||||||
|
|
||||||
|
## 🔒 安全建议
|
||||||
|
|
||||||
|
### 1. 数据库访问权限
|
||||||
|
|
||||||
|
- 在宝塔面板【数据库】中,点击数据库的【权限】
|
||||||
|
- 如果应用和数据库在同一服务器,设置为【本地服务器】
|
||||||
|
- 如果需要远程访问,设置【所有人】或指定IP,但要确保密码强度足够
|
||||||
|
|
||||||
|
### 2. 数据库密码强度
|
||||||
|
|
||||||
|
- 使用包含大小写字母、数字、特殊字符的强密码
|
||||||
|
- 密码长度建议16位以上
|
||||||
|
|
||||||
|
### 3. 定期备份
|
||||||
|
|
||||||
|
在宝塔面板设置自动备份:
|
||||||
|
1. 进入【计划任务】
|
||||||
|
2. 添加【备份数据库】任务
|
||||||
|
3. 选择 `aigc_platform` 数据库
|
||||||
|
4. 设置备份周期(建议每天备份)
|
||||||
|
5. 设置保留份数(建议保留7-30份)
|
||||||
|
|
||||||
|
## ⚙️ 数据库性能优化
|
||||||
|
|
||||||
|
### 1. 连接池配置(已包含在application配置中)
|
||||||
|
|
||||||
|
```properties
|
||||||
|
# 连接池配置(支持50-100人并发)
|
||||||
|
spring.datasource.hikari.maximum-pool-size=50
|
||||||
|
spring.datasource.hikari.minimum-idle=10
|
||||||
|
spring.datasource.hikari.idle-timeout=300000
|
||||||
|
spring.datasource.hikari.max-lifetime=1200000
|
||||||
|
spring.datasource.hikari.connection-timeout=30000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. MySQL配置优化
|
||||||
|
|
||||||
|
在宝塔面板【软件商店】->【MySQL】->【设置】->【配置修改】中调整:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# 根据服务器内存调整(示例为4GB内存)
|
||||||
|
innodb_buffer_pool_size = 1G
|
||||||
|
max_connections = 500
|
||||||
|
query_cache_size = 128M
|
||||||
|
tmp_table_size = 64M
|
||||||
|
max_heap_table_size = 64M
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 常见问题
|
||||||
|
|
||||||
|
### 1. 导入失败:字符集错误
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
- 确保数据库字符集为 `utf8mb4`
|
||||||
|
- 在导入时选择字符集为 `utf8mb4`
|
||||||
|
|
||||||
|
### 2. 连接失败:Access denied
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
- 检查数据库用户名和密码是否正确
|
||||||
|
- 检查数据库访问权限设置
|
||||||
|
|
||||||
|
### 3. 表已存在错误
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
- 如果是重新部署,先删除旧数据库或清空所有表
|
||||||
|
- 在 phpMyAdmin 中选择数据库,点击【操作】->【清空数据库】
|
||||||
|
|
||||||
|
### 4. 管理员权限未生效
|
||||||
|
|
||||||
|
**原因**:用户还未注册
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 先在前端使用 `984523799@qq.com` 注册账号
|
||||||
|
2. 注册完成后,数据库会自动将该用户设置为管理员(因为 `data.sql` 中有自动更新脚本)
|
||||||
|
3. 或者注册后手动执行 `update_admin_user.sql`
|
||||||
|
|
||||||
|
## 📊 数据库监控
|
||||||
|
|
||||||
|
在宝塔面板可以监控数据库状态:
|
||||||
|
1. 进入【数据库】菜单
|
||||||
|
2. 点击数据库名称右侧的【监控】
|
||||||
|
3. 查看:
|
||||||
|
- 查询次数
|
||||||
|
- 慢查询
|
||||||
|
- 连接数
|
||||||
|
- 缓存命中率
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
如遇到问题,请检查:
|
||||||
|
1. 宝塔面板【日志】中的 MySQL 错误日志
|
||||||
|
2. 应用日志中的数据库连接错误
|
||||||
|
3. 确保 MySQL 服务正在运行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**部署完成标志**:
|
||||||
|
- ✅ 数据库创建成功
|
||||||
|
- ✅ 表结构导入成功(13个表)
|
||||||
|
- ✅ 管理员权限设置完成
|
||||||
|
- ✅ 应用能够成功连接数据库
|
||||||
|
|
||||||
|
祝部署顺利!🎉
|
||||||
370
demo/database_baota_deploy/数据库完整结构-宝塔导入.sql
Normal file
370
demo/database_baota_deploy/数据库完整结构-宝塔导入.sql
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- AIGC平台数据库完整结构
|
||||||
|
-- 适用于宝塔面板部署
|
||||||
|
-- 创建时间:2025
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 设置字符集
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 1. 基础表结构(schema.sql)
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 用户表
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
username VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
email VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
password_hash VARCHAR(100) NOT NULL,
|
||||||
|
role VARCHAR(30) NOT NULL DEFAULT 'ROLE_USER',
|
||||||
|
points INT NOT NULL DEFAULT 50,
|
||||||
|
frozen_points INT NOT NULL DEFAULT 0 COMMENT '冻结积分',
|
||||||
|
phone VARCHAR(20),
|
||||||
|
avatar VARCHAR(500),
|
||||||
|
nickname VARCHAR(100),
|
||||||
|
gender VARCHAR(10),
|
||||||
|
birthday DATE,
|
||||||
|
address TEXT,
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
last_login_at TIMESTAMP NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_email (email),
|
||||||
|
INDEX idx_username (username)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
|
||||||
|
|
||||||
|
-- 支付表
|
||||||
|
CREATE TABLE IF NOT EXISTS payments (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
order_id VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
amount DECIMAL(10,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) NOT NULL DEFAULT 'CNY',
|
||||||
|
payment_method VARCHAR(20) NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||||||
|
description VARCHAR(500),
|
||||||
|
external_transaction_id VARCHAR(100),
|
||||||
|
callback_url VARCHAR(1000),
|
||||||
|
return_url VARCHAR(1000),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
paid_at TIMESTAMP NULL,
|
||||||
|
user_id BIGINT,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
|
INDEX idx_order_id (order_id),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付表';
|
||||||
|
|
||||||
|
-- 订单表
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
order_number VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
total_amount DECIMAL(10,2) NOT NULL,
|
||||||
|
currency VARCHAR(3) NOT NULL DEFAULT 'CNY',
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||||||
|
order_type VARCHAR(20) NOT NULL DEFAULT 'PRODUCT',
|
||||||
|
description VARCHAR(500),
|
||||||
|
notes TEXT,
|
||||||
|
shipping_address TEXT,
|
||||||
|
billing_address TEXT,
|
||||||
|
contact_phone VARCHAR(20),
|
||||||
|
contact_email VARCHAR(100),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
paid_at TIMESTAMP NULL,
|
||||||
|
shipped_at TIMESTAMP NULL,
|
||||||
|
delivered_at TIMESTAMP NULL,
|
||||||
|
cancelled_at TIMESTAMP NULL,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||||
|
INDEX idx_order_number (order_number),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单表';
|
||||||
|
|
||||||
|
-- 订单项表
|
||||||
|
CREATE TABLE IF NOT EXISTS order_items (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
product_name VARCHAR(100) NOT NULL,
|
||||||
|
product_description VARCHAR(500),
|
||||||
|
product_sku VARCHAR(200),
|
||||||
|
unit_price DECIMAL(10,2) NOT NULL,
|
||||||
|
quantity INT NOT NULL,
|
||||||
|
subtotal DECIMAL(10,2) NOT NULL,
|
||||||
|
product_image VARCHAR(100),
|
||||||
|
order_id BIGINT NOT NULL,
|
||||||
|
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
|
||||||
|
INDEX idx_order_id (order_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单项表';
|
||||||
|
|
||||||
|
-- 会员等级表
|
||||||
|
CREATE TABLE IF NOT EXISTS membership_levels (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
name VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
display_name VARCHAR(50) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
price DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||||
|
duration_days INT NOT NULL DEFAULT 30,
|
||||||
|
points_bonus INT NOT NULL DEFAULT 0,
|
||||||
|
features JSON,
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_name (name)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会员等级表';
|
||||||
|
|
||||||
|
-- 用户会员信息表
|
||||||
|
CREATE TABLE IF NOT EXISTS user_memberships (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
membership_level_id BIGINT NOT NULL,
|
||||||
|
start_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
end_date TIMESTAMP NOT NULL,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
auto_renew BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (membership_level_id) REFERENCES membership_levels(id),
|
||||||
|
UNIQUE KEY unique_active_membership (user_id, status),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户会员信息表';
|
||||||
|
|
||||||
|
-- 视频生成任务表(基础表)
|
||||||
|
CREATE TABLE IF NOT EXISTS video_tasks (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
task_id VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL,
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
input_text TEXT,
|
||||||
|
input_image_url VARCHAR(500),
|
||||||
|
output_video_url VARCHAR(500),
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||||||
|
progress INT NOT NULL DEFAULT 0,
|
||||||
|
error_message TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
completed_at TIMESTAMP NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='视频生成任务表';
|
||||||
|
|
||||||
|
-- 用户作品表(基础版)
|
||||||
|
CREATE TABLE IF NOT EXISTS user_works_base (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
work_type VARCHAR(50) NOT NULL,
|
||||||
|
cover_image VARCHAR(500),
|
||||||
|
video_url VARCHAR(500),
|
||||||
|
tags VARCHAR(500),
|
||||||
|
is_public BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
view_count INT NOT NULL DEFAULT 0,
|
||||||
|
like_count INT NOT NULL DEFAULT 0,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
INDEX idx_user_id (user_id),
|
||||||
|
INDEX idx_work_type (work_type)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户作品表(基础版)';
|
||||||
|
|
||||||
|
-- 系统配置表
|
||||||
|
CREATE TABLE IF NOT EXISTS system_configs (
|
||||||
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
config_key VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
config_value TEXT,
|
||||||
|
description VARCHAR(500),
|
||||||
|
config_type VARCHAR(50) NOT NULL DEFAULT 'STRING',
|
||||||
|
is_public BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_config_key (config_key)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 2. 迁移表结构(Flyway Migration)
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- V3: 任务队列表
|
||||||
|
CREATE TABLE IF NOT EXISTS task_queue (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO') NOT NULL COMMENT '任务类型',
|
||||||
|
status ENUM('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED', 'TIMEOUT') NOT NULL DEFAULT 'PENDING' COMMENT '队列状态',
|
||||||
|
priority INT NOT NULL DEFAULT 0 COMMENT '优先级,数字越小优先级越高',
|
||||||
|
real_task_id VARCHAR(100) COMMENT '外部API返回的真实任务ID',
|
||||||
|
last_check_time DATETIME COMMENT '最后一次检查时间',
|
||||||
|
check_count INT NOT NULL DEFAULT 0 COMMENT '检查次数',
|
||||||
|
max_check_count INT NOT NULL DEFAULT 30 COMMENT '最大检查次数(30次 * 2分钟 = 60分钟)',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_status_priority (status, priority),
|
||||||
|
INDEX idx_last_check_time (last_check_time),
|
||||||
|
INDEX idx_created_at (created_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='任务队列表';
|
||||||
|
|
||||||
|
-- V4: 积分冻结记录表
|
||||||
|
CREATE TABLE IF NOT EXISTS points_freeze_records (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
task_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO') NOT NULL COMMENT '任务类型',
|
||||||
|
freeze_points INT NOT NULL COMMENT '冻结的积分数量',
|
||||||
|
status ENUM('FROZEN', 'DEDUCTED', 'RETURNED', 'EXPIRED') NOT NULL DEFAULT 'FROZEN' COMMENT '冻结状态',
|
||||||
|
freeze_reason VARCHAR(200) COMMENT '冻结原因',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_status (status)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='积分冻结记录表';
|
||||||
|
|
||||||
|
-- V5: 用户作品表(详细版)
|
||||||
|
CREATE TABLE IF NOT EXISTS user_works (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT '用户名',
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE COMMENT '任务ID',
|
||||||
|
work_type ENUM('TEXT_TO_VIDEO', 'IMAGE_TO_VIDEO') NOT NULL COMMENT '作品类型',
|
||||||
|
title VARCHAR(200) COMMENT '作品标题',
|
||||||
|
description TEXT COMMENT '作品描述',
|
||||||
|
prompt TEXT COMMENT '生成提示词',
|
||||||
|
result_url VARCHAR(500) COMMENT '结果视频URL',
|
||||||
|
thumbnail_url VARCHAR(500) COMMENT '缩略图URL',
|
||||||
|
duration VARCHAR(10) COMMENT '视频时长',
|
||||||
|
aspect_ratio VARCHAR(10) COMMENT '宽高比',
|
||||||
|
quality VARCHAR(20) COMMENT '画质',
|
||||||
|
file_size VARCHAR(20) COMMENT '文件大小',
|
||||||
|
points_cost INT NOT NULL DEFAULT 0 COMMENT '消耗积分',
|
||||||
|
status ENUM('PROCESSING', 'COMPLETED', 'FAILED', 'DELETED') NOT NULL DEFAULT 'PROCESSING' COMMENT '作品状态',
|
||||||
|
is_public BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否公开',
|
||||||
|
view_count INT NOT NULL DEFAULT 0 COMMENT '浏览次数',
|
||||||
|
like_count INT NOT NULL DEFAULT 0 COMMENT '点赞次数',
|
||||||
|
download_count INT NOT NULL DEFAULT 0 COMMENT '下载次数',
|
||||||
|
tags VARCHAR(500) COMMENT '标签',
|
||||||
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at DATETIME COMMENT '完成时间',
|
||||||
|
INDEX idx_username_status (username, status),
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_work_type (work_type),
|
||||||
|
INDEX idx_is_public_status (is_public, status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_view_count (view_count),
|
||||||
|
INDEX idx_like_count (like_count),
|
||||||
|
INDEX idx_tags (tags),
|
||||||
|
INDEX idx_prompt (prompt(100))
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户作品表';
|
||||||
|
|
||||||
|
-- V6: 任务状态表
|
||||||
|
CREATE TABLE IF NOT EXISTS task_status (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL COMMENT '任务ID',
|
||||||
|
username VARCHAR(255) NOT NULL COMMENT '用户名',
|
||||||
|
task_type VARCHAR(50) NOT NULL COMMENT '任务类型',
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态',
|
||||||
|
progress INT DEFAULT 0 COMMENT '进度百分比',
|
||||||
|
result_url TEXT COMMENT '结果URL',
|
||||||
|
error_message TEXT COMMENT '错误信息',
|
||||||
|
external_task_id VARCHAR(255) COMMENT '外部任务ID',
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
completed_at TIMESTAMP NULL COMMENT '完成时间',
|
||||||
|
last_polled_at TIMESTAMP NULL COMMENT '最后轮询时间',
|
||||||
|
poll_count INT DEFAULT 0 COMMENT '轮询次数',
|
||||||
|
max_polls INT DEFAULT 60 COMMENT '最大轮询次数(2小时)',
|
||||||
|
INDEX idx_task_id (task_id),
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_last_polled (last_polled_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务状态表';
|
||||||
|
|
||||||
|
-- V7: 任务清理表
|
||||||
|
-- 成功任务归档表
|
||||||
|
CREATE TABLE IF NOT EXISTS completed_tasks_archive (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL,
|
||||||
|
prompt TEXT,
|
||||||
|
aspect_ratio VARCHAR(20),
|
||||||
|
duration INT,
|
||||||
|
hd_mode BOOLEAN DEFAULT FALSE,
|
||||||
|
result_url TEXT,
|
||||||
|
real_task_id VARCHAR(255),
|
||||||
|
progress INT DEFAULT 100,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
completed_at TIMESTAMP NOT NULL,
|
||||||
|
archived_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
points_cost INT DEFAULT 0,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_task_type (task_type),
|
||||||
|
INDEX idx_created_at (created_at),
|
||||||
|
INDEX idx_completed_at (completed_at),
|
||||||
|
INDEX idx_archived_at (archived_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成功任务归档表';
|
||||||
|
|
||||||
|
-- 失败任务清理日志表
|
||||||
|
CREATE TABLE IF NOT EXISTS failed_tasks_cleanup_log (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(255) NOT NULL,
|
||||||
|
username VARCHAR(255) NOT NULL,
|
||||||
|
task_type VARCHAR(50) NOT NULL,
|
||||||
|
error_message TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
failed_at TIMESTAMP NOT NULL,
|
||||||
|
cleaned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_task_type (task_type),
|
||||||
|
INDEX idx_cleaned_at (cleaned_at)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='失败任务清理日志表';
|
||||||
|
|
||||||
|
-- V8: 分镜视频任务表
|
||||||
|
CREATE TABLE IF NOT EXISTS storyboard_video_tasks (
|
||||||
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
task_id VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
username VARCHAR(100) NOT NULL,
|
||||||
|
prompt TEXT,
|
||||||
|
image_url VARCHAR(500),
|
||||||
|
aspect_ratio VARCHAR(10) NOT NULL,
|
||||||
|
hd_mode BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
status VARCHAR(20) NOT NULL,
|
||||||
|
progress INT NOT NULL DEFAULT 0,
|
||||||
|
result_url VARCHAR(500),
|
||||||
|
real_task_id VARCHAR(255),
|
||||||
|
error_message TEXT,
|
||||||
|
cost_points INT NOT NULL DEFAULT 0,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
updated_at TIMESTAMP NOT NULL,
|
||||||
|
completed_at TIMESTAMP,
|
||||||
|
INDEX idx_username (username),
|
||||||
|
INDEX idx_status (status),
|
||||||
|
INDEX idx_task_id (task_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分镜视频任务表';
|
||||||
|
|
||||||
|
-- ============================================
|
||||||
|
-- 完成
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
||||||
|
-- 显示所有表
|
||||||
|
SHOW TABLES;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
227
demo/database_baota_deploy/部署检查清单.md
Normal file
227
demo/database_baota_deploy/部署检查清单.md
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
# 宝塔数据库部署检查清单
|
||||||
|
|
||||||
|
部署日期: _______________
|
||||||
|
操作人员: _______________
|
||||||
|
|
||||||
|
## 📋 部署前准备
|
||||||
|
|
||||||
|
### 1. 服务器环境检查
|
||||||
|
- [ ] 服务器已安装宝塔面板(版本: ______)
|
||||||
|
- [ ] MySQL/MariaDB已安装(版本: ______)
|
||||||
|
- [ ] MySQL服务运行正常
|
||||||
|
- [ ] 服务器内存 >= 2GB(推荐4GB+)
|
||||||
|
- [ ] 磁盘空间 >= 10GB
|
||||||
|
|
||||||
|
### 2. 部署包确认
|
||||||
|
- [ ] 已下载 `database_baota_deploy.zip`
|
||||||
|
- [ ] 已解压到服务器
|
||||||
|
- [ ] 包含以下文件:
|
||||||
|
- [ ] init_database.sql
|
||||||
|
- [ ] update_admin_user.sql
|
||||||
|
- [ ] 数据库完整结构-宝塔导入.sql
|
||||||
|
- [ ] 宝塔数据库部署指南.md
|
||||||
|
- [ ] README.md
|
||||||
|
- [ ] deploy_database.sh
|
||||||
|
|
||||||
|
## 🚀 部署步骤
|
||||||
|
|
||||||
|
### 第一步:创建数据库
|
||||||
|
- [ ] 登录宝塔面板
|
||||||
|
- [ ] 进入【数据库】菜单
|
||||||
|
- [ ] 点击【添加数据库】
|
||||||
|
- [ ] 数据库名: `aigc_platform`
|
||||||
|
- [ ] 用户名: `aigc_platform`
|
||||||
|
- [ ] 密码: ___________________________(请记录)
|
||||||
|
- [ ] 字符集: `utf8mb4`
|
||||||
|
- [ ] 排序规则: `utf8mb4_unicode_ci`
|
||||||
|
- [ ] 创建成功
|
||||||
|
|
||||||
|
### 第二步:导入数据库
|
||||||
|
- [ ] 点击数据库【管理】按钮
|
||||||
|
- [ ] 进入phpMyAdmin
|
||||||
|
- [ ] 点击【导入】标签
|
||||||
|
- [ ] 选择 `init_database.sql` 文件
|
||||||
|
- [ ] 字符集选择 `utf8mb4`
|
||||||
|
- [ ] 点击【执行】
|
||||||
|
- [ ] 导入成功(显示成功消息)
|
||||||
|
|
||||||
|
### 第三步:验证数据库
|
||||||
|
- [ ] 在phpMyAdmin中点击左侧数据库名
|
||||||
|
- [ ] 查看表列表
|
||||||
|
- [ ] 确认包含13个表:
|
||||||
|
- [ ] users
|
||||||
|
- [ ] payments
|
||||||
|
- [ ] orders
|
||||||
|
- [ ] order_items
|
||||||
|
- [ ] text_to_video_tasks
|
||||||
|
- [ ] image_to_video_tasks
|
||||||
|
- [ ] storyboard_video_tasks
|
||||||
|
- [ ] task_queue
|
||||||
|
- [ ] task_status
|
||||||
|
- [ ] user_works
|
||||||
|
- [ ] user_membership
|
||||||
|
- [ ] user_activity_stats
|
||||||
|
- [ ] failed_tasks_cleanup_log
|
||||||
|
|
||||||
|
### 第四步:配置管理员
|
||||||
|
- [ ] 管理员邮箱: `984523799@qq.com`
|
||||||
|
- [ ] 已在 `init_database.sql` 中自动配置
|
||||||
|
- [ ] 或手动执行 `update_admin_user.sql`
|
||||||
|
|
||||||
|
## ⚙️ 应用配置
|
||||||
|
|
||||||
|
### 更新配置文件
|
||||||
|
- [ ] 找到文件: `src/main/resources/application-prod.properties`
|
||||||
|
- [ ] 更新以下配置:
|
||||||
|
|
||||||
|
```properties
|
||||||
|
spring.datasource.url=jdbc:mysql://localhost:3306/aigc_platform?...
|
||||||
|
spring.datasource.username=aigc_platform
|
||||||
|
spring.datasource.password=你的数据库密码
|
||||||
|
```
|
||||||
|
|
||||||
|
配置信息记录:
|
||||||
|
```
|
||||||
|
数据库地址: _______________________________
|
||||||
|
数据库端口: 3306
|
||||||
|
数据库名: aigc_platform
|
||||||
|
用户名: aigc_platform
|
||||||
|
密码: _______________________________
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 安全配置
|
||||||
|
|
||||||
|
### 数据库访问权限
|
||||||
|
- [ ] 设置访问权限(本地服务器/所有人/指定IP)
|
||||||
|
- [ ] 权限类型: _______________________
|
||||||
|
|
||||||
|
### 防火墙配置(如需远程连接)
|
||||||
|
- [ ] 开放3306端口
|
||||||
|
- [ ] 或使用SSH隧道
|
||||||
|
|
||||||
|
### 备份配置
|
||||||
|
- [ ] 在宝塔面板设置自动备份
|
||||||
|
- [ ] 备份周期: 每天 / 每周(选择一个)
|
||||||
|
- [ ] 保留份数: _______ 份
|
||||||
|
- [ ] 备份位置: _______________________
|
||||||
|
|
||||||
|
## ✅ 功能测试
|
||||||
|
|
||||||
|
### 数据库连接测试
|
||||||
|
- [ ] 使用命令行测试连接:
|
||||||
|
```bash
|
||||||
|
mysql -uaigc_platform -p aigc_platform
|
||||||
|
```
|
||||||
|
- [ ] 连接成功
|
||||||
|
|
||||||
|
### 表查询测试
|
||||||
|
- [ ] 执行查询:
|
||||||
|
```sql
|
||||||
|
SHOW TABLES;
|
||||||
|
SELECT COUNT(*) FROM users;
|
||||||
|
```
|
||||||
|
- [ ] 查询成功
|
||||||
|
|
||||||
|
### 管理员账号验证(注册后执行)
|
||||||
|
- [ ] 使用 `984523799@qq.com` 注册账号
|
||||||
|
- [ ] 执行查询验证角色:
|
||||||
|
```sql
|
||||||
|
SELECT id, username, email, role FROM users WHERE email = '984523799@qq.com';
|
||||||
|
```
|
||||||
|
- [ ] role = 'ROLE_ADMIN' ✓
|
||||||
|
|
||||||
|
### 应用连接测试
|
||||||
|
- [ ] 启动Spring Boot应用
|
||||||
|
- [ ] 查看日志,确认数据库连接成功
|
||||||
|
- [ ] 无数据库连接错误
|
||||||
|
|
||||||
|
## 📊 性能优化(可选)
|
||||||
|
|
||||||
|
### MySQL配置优化
|
||||||
|
- [ ] 调整 `innodb_buffer_pool_size`
|
||||||
|
- [ ] 调整 `max_connections`
|
||||||
|
- [ ] 调整 `query_cache_size`
|
||||||
|
|
||||||
|
### 连接池配置
|
||||||
|
- [ ] 已配置HikariCP连接池
|
||||||
|
- [ ] maximum-pool-size: 50
|
||||||
|
- [ ] minimum-idle: 10
|
||||||
|
|
||||||
|
## 🐛 问题记录
|
||||||
|
|
||||||
|
遇到的问题及解决方案:
|
||||||
|
|
||||||
|
| 问题描述 | 解决方案 | 解决时间 |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
|
||||||
|
## 📝 部署总结
|
||||||
|
|
||||||
|
### 部署结果
|
||||||
|
- [ ] 部署成功 ✅
|
||||||
|
- [ ] 部署失败 ❌(原因: _____________)
|
||||||
|
|
||||||
|
### 部署时间记录
|
||||||
|
- 开始时间: _______________
|
||||||
|
- 结束时间: _______________
|
||||||
|
- 总耗时: _______________
|
||||||
|
|
||||||
|
### 资源使用
|
||||||
|
- 数据库大小: _______ MB
|
||||||
|
- 表数量: 13
|
||||||
|
- 索引数量: _______
|
||||||
|
|
||||||
|
### 后续工作
|
||||||
|
- [ ] 监控数据库性能
|
||||||
|
- [ ] 设置定期备份
|
||||||
|
- [ ] 配置数据库监控告警
|
||||||
|
- [ ] 文档归档
|
||||||
|
|
||||||
|
## 📞 联系信息
|
||||||
|
|
||||||
|
### 技术支持
|
||||||
|
- 部署文档: README.md
|
||||||
|
- 详细指南: 宝塔数据库部署指南.md
|
||||||
|
|
||||||
|
### 应急联系
|
||||||
|
- 运维人员: _______________
|
||||||
|
- 联系电话: _______________
|
||||||
|
- 备用联系: _______________
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**部署负责人签名**: _______________
|
||||||
|
**审核人签名**: _______________
|
||||||
|
**日期**: _______________
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看MySQL状态
|
||||||
|
systemctl status mysql
|
||||||
|
|
||||||
|
# 重启MySQL
|
||||||
|
systemctl restart mysql
|
||||||
|
|
||||||
|
# 查看数据库列表
|
||||||
|
mysql -uroot -p -e "SHOW DATABASES;"
|
||||||
|
|
||||||
|
# 备份数据库
|
||||||
|
mysqldump -uaigc_platform -p aigc_platform > backup.sql
|
||||||
|
|
||||||
|
# 恢复数据库
|
||||||
|
mysql -uaigc_platform -p aigc_platform < backup.sql
|
||||||
|
|
||||||
|
# 查看表大小
|
||||||
|
SELECT table_name, ROUND(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)"
|
||||||
|
FROM information_schema.TABLES
|
||||||
|
WHERE table_schema = 'aigc_platform'
|
||||||
|
ORDER BY (data_length + index_length) DESC;
|
||||||
|
```
|
||||||
|
|
||||||
|
**部署清单版本**: 1.0
|
||||||
|
**更新日期**: 2025-11-10
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user