feat: 完成代码逻辑错误修复和任务清理系统实现
主要更新: - 修复了所有主要的代码逻辑错误 - 实现了完整的任务清理系统 - 添加了系统设置页面的任务清理管理功能 - 修复了API调用认证问题 - 优化了密码加密和验证机制 - 统一了错误处理模式 - 添加了详细的文档和测试工具 新增功能: - 任务清理管理界面 - 任务归档和清理日志 - API监控和诊断工具 - 完整的测试套件 技术改进: - 修复了Repository方法调用错误 - 统一了模型方法调用 - 改进了类型安全性 - 优化了代码结构和可维护性
This commit is contained in:
307
demo/TASK_TO_WORK_FLOW.md
Normal file
307
demo/TASK_TO_WORK_FLOW.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# 任务完成后作品保存流程说明
|
||||
|
||||
## 🎯 **功能概述**
|
||||
|
||||
当任务执行成功后,系统会自动将结果保存到用户的"我的作品"中,并将相关信息添加到数据库中。用户可以通过API接口查看、管理自己的作品。
|
||||
|
||||
## 📋 **完整流程**
|
||||
|
||||
### 1. **任务执行成功触发**
|
||||
```
|
||||
外部API返回结果 → TaskQueueService.updateTaskAsCompleted()
|
||||
```
|
||||
|
||||
### 2. **任务队列状态更新**
|
||||
```java
|
||||
// TaskQueueService.updateTaskAsCompleted()
|
||||
taskQueue.updateStatus(TaskQueue.QueueStatus.COMPLETED);
|
||||
taskQueueRepository.save(taskQueue);
|
||||
```
|
||||
|
||||
### 3. **积分处理**
|
||||
```java
|
||||
// 扣除冻结的积分
|
||||
userService.deductFrozenPoints(taskQueue.getTaskId());
|
||||
```
|
||||
|
||||
### 4. **作品创建**
|
||||
```java
|
||||
// 创建用户作品
|
||||
UserWork work = userWorkService.createWorkFromTask(taskQueue.getTaskId(), resultUrl);
|
||||
```
|
||||
|
||||
### 5. **作品数据提取**
|
||||
```java
|
||||
// UserWorkService.createWorkFromTask()
|
||||
// 检查是否已存在作品(防重复)
|
||||
Optional<UserWork> existingWork = userWorkRepository.findByTaskId(taskId);
|
||||
if (existingWork.isPresent()) {
|
||||
return existingWork.get(); // 返回已存在的作品
|
||||
}
|
||||
|
||||
// 从原始任务中提取数据
|
||||
TextToVideoTask task = textToVideoTaskRepository.findByTaskId(taskId);
|
||||
// 或
|
||||
ImageToVideoTask task = imageToVideoTaskRepository.findByTaskId(taskId);
|
||||
```
|
||||
|
||||
### 6. **作品信息设置**
|
||||
```java
|
||||
// UserWorkService.createTextToVideoWork() 或 createImageToVideoWork()
|
||||
UserWork work = new UserWork();
|
||||
work.setUsername(task.getUsername()); // 用户名
|
||||
work.setTaskId(task.getTaskId()); // 任务ID
|
||||
work.setWorkType(UserWork.WorkType.TEXT_TO_VIDEO); // 作品类型
|
||||
work.setTitle(generateTitle(task.getPrompt())); // 自动生成标题
|
||||
work.setDescription("文生视频作品"); // 作品描述
|
||||
work.setPrompt(task.getPrompt()); // 原始提示词
|
||||
work.setResultUrl(resultUrl); // 结果视频URL
|
||||
work.setDuration(String.valueOf(task.getDuration()) + "s"); // 视频时长
|
||||
work.setAspectRatio(task.getAspectRatio()); // 宽高比
|
||||
work.setQuality(task.isHdMode() ? "HD" : "SD"); // 画质
|
||||
work.setPointsCost(task.getCostPoints()); // 消耗积分
|
||||
work.setStatus(UserWork.WorkStatus.COMPLETED); // 作品状态
|
||||
work.setCompletedAt(LocalDateTime.now()); // 完成时间
|
||||
```
|
||||
|
||||
### 7. **数据库保存**
|
||||
```java
|
||||
// 保存到数据库
|
||||
work = userWorkRepository.save(work);
|
||||
```
|
||||
|
||||
### 8. **原始任务状态更新**
|
||||
```java
|
||||
// 更新原始任务状态
|
||||
updateOriginalTaskStatus(taskQueue, "COMPLETED", resultUrl, null);
|
||||
```
|
||||
|
||||
## 🗄️ **数据库表结构**
|
||||
|
||||
### user_works 表
|
||||
```sql
|
||||
CREATE TABLE 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 '完成时间'
|
||||
);
|
||||
```
|
||||
|
||||
## 🔌 **API接口**
|
||||
|
||||
### 获取我的作品列表
|
||||
```
|
||||
GET /api/works/my-works?page=0&size=10
|
||||
Authorization: Bearer <token>
|
||||
|
||||
Response:
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"username": "user1",
|
||||
"taskId": "txt2vid_123",
|
||||
"workType": "TEXT_TO_VIDEO",
|
||||
"title": "一只可爱的小猫...",
|
||||
"description": "文生视频作品",
|
||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
||||
"resultUrl": "https://example.com/video.mp4",
|
||||
"duration": "10s",
|
||||
"aspectRatio": "16:9",
|
||||
"quality": "HD",
|
||||
"pointsCost": 80,
|
||||
"status": "COMPLETED",
|
||||
"isPublic": false,
|
||||
"viewCount": 0,
|
||||
"likeCount": 0,
|
||||
"downloadCount": 0,
|
||||
"createdAt": "2024-01-01T10:00:00",
|
||||
"completedAt": "2024-01-01T10:05:00"
|
||||
}
|
||||
],
|
||||
"totalElements": 1,
|
||||
"totalPages": 1,
|
||||
"currentPage": 0,
|
||||
"size": 10,
|
||||
"stats": {
|
||||
"completedCount": 1,
|
||||
"processingCount": 0,
|
||||
"failedCount": 0,
|
||||
"totalPointsCost": 80,
|
||||
"totalCount": 1,
|
||||
"publicCount": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 获取作品详情
|
||||
```
|
||||
GET /api/works/{workId}
|
||||
Authorization: Bearer <token>
|
||||
|
||||
Response:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"id": 1,
|
||||
"username": "user1",
|
||||
"taskId": "txt2vid_123",
|
||||
"workType": "TEXT_TO_VIDEO",
|
||||
"title": "一只可爱的小猫...",
|
||||
"description": "文生视频作品",
|
||||
"prompt": "一只可爱的小猫在花园里玩耍",
|
||||
"resultUrl": "https://example.com/video.mp4",
|
||||
"duration": "10s",
|
||||
"aspectRatio": "16:9",
|
||||
"quality": "HD",
|
||||
"pointsCost": 80,
|
||||
"status": "COMPLETED",
|
||||
"isPublic": false,
|
||||
"viewCount": 1,
|
||||
"likeCount": 0,
|
||||
"downloadCount": 0,
|
||||
"createdAt": "2024-01-01T10:00:00",
|
||||
"completedAt": "2024-01-01T10:05:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ **安全特性**
|
||||
|
||||
### 1. **防重复创建**
|
||||
- 检查是否已存在相同任务ID的作品
|
||||
- 如果存在则返回已存在的作品,不创建新作品
|
||||
|
||||
### 2. **权限控制**
|
||||
- 只有作品所有者可以查看、编辑、删除作品
|
||||
- 通过JWT Token验证用户身份
|
||||
|
||||
### 3. **数据完整性**
|
||||
- 事务保证数据一致性
|
||||
- 作品创建失败不影响任务完成状态
|
||||
|
||||
### 4. **异常处理**
|
||||
- 完善的错误处理机制
|
||||
- 详细的日志记录
|
||||
|
||||
## 📊 **作品管理功能**
|
||||
|
||||
### 1. **作品查看**
|
||||
- 分页获取用户作品列表
|
||||
- 获取作品详细信息
|
||||
- 作品统计信息
|
||||
|
||||
### 2. **作品编辑**
|
||||
- 修改作品标题
|
||||
- 修改作品描述
|
||||
- 设置作品标签
|
||||
- 设置作品公开状态
|
||||
|
||||
### 3. **作品互动**
|
||||
- 作品点赞
|
||||
- 作品下载记录
|
||||
- 浏览次数统计
|
||||
|
||||
### 4. **作品删除**
|
||||
- 软删除作品
|
||||
- 保留数据完整性
|
||||
|
||||
## 🔄 **定时任务**
|
||||
|
||||
### 清理过期失败作品
|
||||
```java
|
||||
@Scheduled(cron = "0 0 3 * * ?") // 每天凌晨3点执行
|
||||
public void cleanupExpiredFailedWorks() {
|
||||
// 清理超过30天的失败作品
|
||||
int cleanedCount = userWorkService.cleanupExpiredFailedWorks();
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 **测试验证**
|
||||
|
||||
系统包含完整的集成测试,验证:
|
||||
- 文生视频任务完成后作品创建
|
||||
- 图生视频任务完成后作品创建
|
||||
- 重复作品创建处理
|
||||
- 作品标题生成
|
||||
- 用户作品列表获取
|
||||
- 作品统计信息
|
||||
|
||||
## 📝 **使用示例**
|
||||
|
||||
### 前端调用示例
|
||||
```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;
|
||||
};
|
||||
|
||||
// 获取作品详情
|
||||
const getWorkDetail = async (workId) => {
|
||||
const response = await fetch(`/api/works/${workId}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
return data;
|
||||
};
|
||||
|
||||
// 更新作品信息
|
||||
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. **✅ 我的作品API接口完整**
|
||||
5. **✅ 权限控制和安全验证**
|
||||
6. **✅ 防重复创建机制**
|
||||
7. **✅ 异常处理和日志记录**
|
||||
8. **✅ 完整的测试覆盖**
|
||||
|
||||
用户现在可以在任务完成后,通过"我的作品"功能查看和管理自己生成的所有视频作品。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user