385 lines
9.0 KiB
Markdown
385 lines
9.0 KiB
Markdown
# 完成图片保存功能说明
|
||
|
||
## 📋 功能概述
|
||
|
||
当游戏任务完成时,系统会自动保存4张关键截图到本地文件系统,并保留24小时。这些图片可以作为任务完成的证明和记录。
|
||
|
||
## 🎯 保存的图片
|
||
|
||
任务完成时会保存以下4张图片:
|
||
|
||
1. **首次主页.png** (homepage)
|
||
2. **首次赏金.png** (first-reward)
|
||
3. **中途赏金.png** (mid-reward)
|
||
4. **结束赏金.png** (end-reward)
|
||
|
||
## 🔧 技术实现
|
||
|
||
### 1. 核心服务组件
|
||
|
||
#### **CompletionImageService**
|
||
- 负责从脚本端下载图片并保存到本地文件系统
|
||
- 并发下载4张图片,提高效率
|
||
- 提供图片访问和清理功能
|
||
|
||
#### **GameCompletionDetectionService**
|
||
- 在任务完成时触发图片保存
|
||
- 异步执行,不阻塞主流程
|
||
- 保存成功后更新数据库记录
|
||
|
||
#### **CompletionImageController**
|
||
- 提供HTTP接口访问已保存的图片
|
||
- 支持单张图片访问和批量URL获取
|
||
|
||
#### **CompletionImageCleanupTask**
|
||
- 定时清理任务(每小时执行)
|
||
- 自动删除超过24小时的图片文件夹
|
||
|
||
### 2. 文件存储结构
|
||
|
||
```
|
||
completion-images/
|
||
├── 20251103/ # 日期文件夹(yyyyMMdd)
|
||
│ ├── ABC123XYZ/ # 链接编号(codeNo)
|
||
│ │ ├── homepage.png
|
||
│ │ ├── first-reward.png
|
||
│ │ ├── mid-reward.png
|
||
│ │ └── end-reward.png
|
||
│ └── DEF456UVW/
|
||
│ └── ...
|
||
└── 20251104/
|
||
└── ...
|
||
```
|
||
|
||
### 3. 数据库字段
|
||
|
||
在 `link_task` 表中新增两个字段:
|
||
|
||
| 字段名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| `completion_images` | TEXT | JSON格式存储图片信息 |
|
||
| `completion_images_saved_at` | DATETIME | 图片保存时间 |
|
||
|
||
**completion_images JSON 示例:**
|
||
```json
|
||
{
|
||
"saveTime": "2025-11-03T10:30:45",
|
||
"codeNo": "ABC123XYZ",
|
||
"machineId": "f1",
|
||
"dateFolder": "20251103",
|
||
"images": {
|
||
"homepage": "20251103/ABC123XYZ/homepage.png",
|
||
"first-reward": "20251103/ABC123XYZ/first-reward.png",
|
||
"mid-reward": "20251103/ABC123XYZ/mid-reward.png",
|
||
"end-reward": "20251103/ABC123XYZ/end-reward.png"
|
||
},
|
||
"totalCount": 4
|
||
}
|
||
```
|
||
|
||
## 📡 API 接口
|
||
|
||
### 1. 获取单张图片
|
||
|
||
**首次主页图片**
|
||
```http
|
||
GET /api/link/completion/{codeNo}/homepage.png
|
||
```
|
||
|
||
**首次赏金图片**
|
||
```http
|
||
GET /api/link/completion/{codeNo}/first-reward.png
|
||
```
|
||
|
||
**中途赏金图片**
|
||
```http
|
||
GET /api/link/completion/{codeNo}/mid-reward.png
|
||
```
|
||
|
||
**结束赏金图片**
|
||
```http
|
||
GET /api/link/completion/{codeNo}/end-reward.png
|
||
```
|
||
|
||
**响应示例:**
|
||
- 成功:返回图片数据(image/png)
|
||
- 失败:404 Not Found
|
||
|
||
### 2. 获取所有图片URL列表
|
||
|
||
```http
|
||
GET /api/link/completion/{codeNo}/images
|
||
```
|
||
|
||
**响应示例:**
|
||
```json
|
||
{
|
||
"homepage": "https://uzi1.cn/api/link/completion/ABC123XYZ/homepage.png",
|
||
"firstReward": "https://uzi1.cn/api/link/completion/ABC123XYZ/first-reward.png",
|
||
"midReward": "https://uzi1.cn/api/link/completion/ABC123XYZ/mid-reward.png",
|
||
"endReward": "https://uzi1.cn/api/link/completion/ABC123XYZ/end-reward.png"
|
||
}
|
||
```
|
||
|
||
## ⚙️ 配置说明
|
||
|
||
在 `application.yml` 中配置:
|
||
|
||
```yaml
|
||
# 完成图片存储配置
|
||
completion:
|
||
image:
|
||
storage:
|
||
path: "./completion-images" # 图片存储路径
|
||
retention-hours: 24 # 图片保留时间(小时)
|
||
```
|
||
|
||
### 配置项说明
|
||
|
||
| 配置项 | 说明 | 默认值 |
|
||
|--------|------|--------|
|
||
| `path` | 图片存储路径,支持相对路径和绝对路径 | `./completion-images` |
|
||
| `retention-hours` | 图片保留时间(小时) | 24 |
|
||
|
||
### 生产环境建议
|
||
|
||
**推荐配置绝对路径:**
|
||
```yaml
|
||
completion:
|
||
image:
|
||
storage:
|
||
path: "/data/gameplatform/completion-images"
|
||
```
|
||
|
||
**磁盘空间预估:**
|
||
- 单个任务:4张图片,约 800KB - 2MB
|
||
- 每天100个任务:约 80MB - 200MB
|
||
- 24小时滚动:约 80MB - 200MB
|
||
|
||
## 🔄 执行流程
|
||
|
||
### 1. 图片保存流程
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Detection as 完成检测服务
|
||
participant ImageService as 图片服务
|
||
participant ScriptClient as 脚本客户端
|
||
participant FileSystem as 文件系统
|
||
participant Database as 数据库
|
||
|
||
Detection->>Detection: 检测到任务完成
|
||
Detection->>ImageService: 异步保存图片
|
||
ImageService->>ScriptClient: 并发下载4张图片
|
||
ScriptClient-->>ImageService: 返回图片数据
|
||
ImageService->>FileSystem: 保存到本地
|
||
FileSystem-->>ImageService: 保存成功
|
||
ImageService->>Database: 更新图片信息
|
||
Database-->>ImageService: 更新完成
|
||
```
|
||
|
||
### 2. 清理流程
|
||
|
||
```
|
||
每小时第5分钟执行
|
||
↓
|
||
计算过期时间(当前时间 - 24小时)
|
||
↓
|
||
查找过期的日期文件夹
|
||
↓
|
||
递归删除过期文件夹
|
||
↓
|
||
记录清理日志
|
||
```
|
||
|
||
## 🔒 安全配置
|
||
|
||
在 `SecurityConfig.java` 中已配置公开访问权限:
|
||
|
||
```java
|
||
.pathMatchers(HttpMethod.GET, "/api/link/completion/**").permitAll()
|
||
.pathMatchers(HttpMethod.HEAD, "/api/link/completion/**").permitAll()
|
||
```
|
||
|
||
**说明:**
|
||
- 完成图片可以公开访问(无需认证)
|
||
- 图片URL包含链接编号,具有一定的私密性
|
||
- 24小时后自动删除,减少泄露风险
|
||
|
||
## 📊 监控和日志
|
||
|
||
### 关键日志
|
||
|
||
**图片保存成功:**
|
||
```
|
||
INFO - 完成图片保存成功: codeNo=ABC123XYZ, imageInfo={...}
|
||
```
|
||
|
||
**图片保存失败:**
|
||
```
|
||
ERROR - 完成图片保存失败: codeNo=ABC123XYZ, error=...
|
||
```
|
||
|
||
**定时清理:**
|
||
```
|
||
INFO - === 完成图片清理任务完成:删除文件夹数=5, 耗时=234ms ===
|
||
```
|
||
|
||
### 监控指标
|
||
|
||
- 图片保存成功率
|
||
- 图片下载耗时
|
||
- 磁盘空间使用
|
||
- 清理任务执行情况
|
||
|
||
## 🚀 部署步骤
|
||
|
||
### 1. 数据库迁移
|
||
|
||
执行迁移脚本:
|
||
```bash
|
||
# 文件位置: src/main/resources/db/migration/V20251103__add_completion_images_saved_at.sql
|
||
mysql -u username -p database_name < V20251103__add_completion_images_saved_at.sql
|
||
```
|
||
|
||
或者使用 Flyway 自动迁移(推荐)。
|
||
|
||
### 2. 创建存储目录
|
||
|
||
```bash
|
||
# 创建图片存储目录
|
||
mkdir -p /data/gameplatform/completion-images
|
||
|
||
# 设置权限
|
||
chown -R app_user:app_group /data/gameplatform/completion-images
|
||
chmod 755 /data/gameplatform/completion-images
|
||
```
|
||
|
||
### 3. 更新配置文件
|
||
|
||
修改 `application.yml`:
|
||
```yaml
|
||
completion:
|
||
image:
|
||
storage:
|
||
path: "/data/gameplatform/completion-images"
|
||
```
|
||
|
||
### 4. 重启应用
|
||
|
||
```bash
|
||
systemctl restart gameplatform-server
|
||
```
|
||
|
||
### 5. 验证功能
|
||
|
||
查看日志确认功能正常:
|
||
```bash
|
||
tail -f logs/server.log | grep "完成图片"
|
||
```
|
||
|
||
## 🔍 故障排查
|
||
|
||
### 问题1:图片保存失败
|
||
|
||
**可能原因:**
|
||
1. 存储目录不存在或无写权限
|
||
2. 脚本端图片不存在
|
||
3. 网络连接问题
|
||
|
||
**排查步骤:**
|
||
```bash
|
||
# 1. 检查目录权限
|
||
ls -la /data/gameplatform/completion-images
|
||
|
||
# 2. 检查磁盘空间
|
||
df -h
|
||
|
||
# 3. 查看详细日志
|
||
grep "完成图片保存失败" logs/server.log
|
||
```
|
||
|
||
### 问题2:图片无法访问
|
||
|
||
**可能原因:**
|
||
1. 图片已被清理(超过24小时)
|
||
2. 图片保存时失败
|
||
3. 文件路径错误
|
||
|
||
**排查步骤:**
|
||
```bash
|
||
# 查找特定任务的图片
|
||
find /data/gameplatform/completion-images -name "*ABC123XYZ*"
|
||
|
||
# 检查数据库记录
|
||
SELECT code_no, completion_images, completion_images_saved_at
|
||
FROM link_task
|
||
WHERE code_no = 'ABC123XYZ';
|
||
```
|
||
|
||
### 问题3:磁盘空间不足
|
||
|
||
**解决方案:**
|
||
1. 调整保留时间(减少到12小时)
|
||
2. 增加磁盘空间
|
||
3. 配置日志轮转和压缩
|
||
|
||
## 📝 注意事项
|
||
|
||
1. **异步执行**:图片保存是异步的,不会阻塞任务完成流程
|
||
2. **容错机制**:单张图片下载失败不影响其他图片
|
||
3. **自动清理**:超过24小时的图片会自动删除,无需手动维护
|
||
4. **并发安全**:使用日期文件夹隔离,避免并发冲突
|
||
5. **存储规划**:建议预留至少 500MB 磁盘空间
|
||
|
||
## 🎓 使用示例
|
||
|
||
### 前端获取完成图片
|
||
|
||
```javascript
|
||
// 获取所有图片URL
|
||
fetch('/api/link/completion/ABC123XYZ/images')
|
||
.then(res => res.json())
|
||
.then(urls => {
|
||
console.log('首次主页:', urls.homepage);
|
||
console.log('首次赏金:', urls.firstReward);
|
||
console.log('中途赏金:', urls.midReward);
|
||
console.log('结束赏金:', urls.endReward);
|
||
});
|
||
|
||
// 直接显示图片
|
||
<img src="/api/link/completion/ABC123XYZ/homepage.png" alt="首次主页" />
|
||
```
|
||
|
||
### 查询数据库中的图片信息
|
||
|
||
```sql
|
||
-- 查询最近完成且有图片的任务
|
||
SELECT
|
||
code_no,
|
||
status,
|
||
completed_points,
|
||
completion_images_saved_at,
|
||
JSON_EXTRACT(completion_images, '$.totalCount') as image_count
|
||
FROM link_task
|
||
WHERE status = 'COMPLETED'
|
||
AND completion_images IS NOT NULL
|
||
AND completion_images_saved_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
|
||
ORDER BY completion_images_saved_at DESC
|
||
LIMIT 10;
|
||
```
|
||
|
||
## 🔮 未来优化方向
|
||
|
||
1. **CDN 集成**:将图片上传到 CDN,提高访问速度
|
||
2. **压缩优化**:自动压缩图片,减少存储空间
|
||
3. **备份机制**:定期备份重要图片到对象存储
|
||
4. **统计分析**:添加图片访问统计和热度分析
|
||
5. **批量下载**:支持批量导出完成图片
|
||
|
||
---
|
||
|
||
**最后更新时间:** 2025-11-03
|
||
**版本:** v1.0.0
|
||
|