feat: 完成代码逻辑错误修复和任务清理系统实现
主要更新: - 修复了所有主要的代码逻辑错误 - 实现了完整的任务清理系统 - 添加了系统设置页面的任务清理管理功能 - 修复了API调用认证问题 - 优化了密码加密和验证机制 - 统一了错误处理模式 - 添加了详细的文档和测试工具 新增功能: - 任务清理管理界面 - 任务归档和清理日志 - API监控和诊断工具 - 完整的测试套件 技术改进: - 修复了Repository方法调用错误 - 统一了模型方法调用 - 改进了类型安全性 - 优化了代码结构和可维护性
This commit is contained in:
200
demo/frontend/src/api/imageToVideo.js
Normal file
200
demo/frontend/src/api/imageToVideo.js
Normal file
@@ -0,0 +1,200 @@
|
||||
import request from './request'
|
||||
|
||||
/**
|
||||
* 图生视频API服务
|
||||
*/
|
||||
export const imageToVideoApi = {
|
||||
/**
|
||||
* 创建图生视频任务
|
||||
* @param {Object} params - 任务参数
|
||||
* @param {File} params.firstFrame - 首帧图片
|
||||
* @param {File} params.lastFrame - 尾帧图片(可选)
|
||||
* @param {string} params.prompt - 描述文字
|
||||
* @param {string} params.aspectRatio - 视频比例
|
||||
* @param {number} params.duration - 视频时长
|
||||
* @param {boolean} params.hdMode - 是否高清模式
|
||||
* @returns {Promise} API响应
|
||||
*/
|
||||
createTask(params) {
|
||||
// 参数验证
|
||||
if (!params) {
|
||||
throw new Error('参数不能为空')
|
||||
}
|
||||
if (!params.firstFrame) {
|
||||
throw new Error('首帧图片不能为空')
|
||||
}
|
||||
if (!params.prompt || params.prompt.trim() === '') {
|
||||
throw new Error('描述文字不能为空')
|
||||
}
|
||||
if (!params.aspectRatio) {
|
||||
throw new Error('视频比例不能为空')
|
||||
}
|
||||
if (!params.duration || params.duration < 1 || params.duration > 60) {
|
||||
throw new Error('视频时长必须在1-60秒之间')
|
||||
}
|
||||
|
||||
const formData = new FormData()
|
||||
|
||||
// 添加必填参数
|
||||
formData.append('firstFrame', params.firstFrame)
|
||||
formData.append('prompt', params.prompt.trim())
|
||||
formData.append('aspectRatio', params.aspectRatio)
|
||||
formData.append('duration', params.duration.toString())
|
||||
formData.append('hdMode', params.hdMode.toString())
|
||||
|
||||
// 添加可选参数
|
||||
if (params.lastFrame) {
|
||||
formData.append('lastFrame', params.lastFrame)
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/image-to-video/create',
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户任务列表
|
||||
* @param {number} page - 页码
|
||||
* @param {number} size - 每页数量
|
||||
* @returns {Promise} API响应
|
||||
*/
|
||||
getTasks(page = 0, size = 10) {
|
||||
return request({
|
||||
url: '/image-to-video/tasks',
|
||||
method: 'GET',
|
||||
params: { page, size }
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取任务详情
|
||||
* @param {string} taskId - 任务ID
|
||||
* @returns {Promise} API响应
|
||||
*/
|
||||
getTaskDetail(taskId) {
|
||||
return request({
|
||||
url: `/image-to-video/tasks/${taskId}`,
|
||||
method: 'GET'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取任务状态
|
||||
* @param {string} taskId - 任务ID
|
||||
* @returns {Promise} API响应
|
||||
*/
|
||||
getTaskStatus(taskId) {
|
||||
return request({
|
||||
url: `/image-to-video/tasks/${taskId}/status`,
|
||||
method: 'GET'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 取消任务
|
||||
* @param {string} taskId - 任务ID
|
||||
* @returns {Promise} API响应
|
||||
*/
|
||||
cancelTask(taskId) {
|
||||
return request({
|
||||
url: `/image-to-video/tasks/${taskId}/cancel`,
|
||||
method: 'POST'
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 轮询任务状态
|
||||
* @param {string} taskId - 任务ID
|
||||
* @param {Function} onProgress - 进度回调
|
||||
* @param {Function} onComplete - 完成回调
|
||||
* @param {Function} onError - 错误回调
|
||||
* @returns {Function} 停止轮询的函数
|
||||
*/
|
||||
pollTaskStatus(taskId, onProgress, onComplete, onError) {
|
||||
let isPolling = true
|
||||
let pollCount = 0
|
||||
const maxPolls = 30 // 最大轮询次数(1小时,每2分钟一次)
|
||||
|
||||
const poll = async () => {
|
||||
if (!isPolling || pollCount >= maxPolls) {
|
||||
if (pollCount >= maxPolls) {
|
||||
onError && onError(new Error('任务超时'))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await request({
|
||||
url: `/image-to-video/tasks/${taskId}/status`,
|
||||
method: 'GET'
|
||||
})
|
||||
|
||||
// 检查响应是否有效
|
||||
if (!response || !response.data || !response.data.success) {
|
||||
onError && onError(new Error('获取任务状态失败'))
|
||||
isPolling = false
|
||||
return
|
||||
}
|
||||
|
||||
const taskData = response.data.data
|
||||
|
||||
// 检查taskData是否有效
|
||||
if (!taskData || !taskData.status) {
|
||||
onError && onError(new Error('无效的任务数据'))
|
||||
isPolling = false
|
||||
return
|
||||
}
|
||||
|
||||
if (taskData.status === 'COMPLETED') {
|
||||
onComplete && onComplete(taskData)
|
||||
isPolling = false
|
||||
return
|
||||
}
|
||||
|
||||
if (taskData.status === 'FAILED' || taskData.status === 'CANCELLED') {
|
||||
console.error('任务失败:', {
|
||||
taskId: taskId,
|
||||
status: taskData.status,
|
||||
errorMessage: taskData.errorMessage,
|
||||
pollCount: pollCount
|
||||
})
|
||||
onError && onError(new Error(taskData.errorMessage || '任务失败'))
|
||||
isPolling = false
|
||||
return
|
||||
}
|
||||
|
||||
// 调用进度回调
|
||||
onProgress && onProgress({
|
||||
status: taskData.status,
|
||||
progress: taskData.progress || 0,
|
||||
resultUrl: taskData.resultUrl
|
||||
})
|
||||
|
||||
pollCount++
|
||||
|
||||
// 继续轮询
|
||||
setTimeout(poll, 120000) // 每2分钟轮询一次
|
||||
|
||||
} catch (error) {
|
||||
console.error('轮询任务状态失败:', error)
|
||||
onError && onError(error)
|
||||
isPolling = false
|
||||
}
|
||||
}
|
||||
|
||||
// 开始轮询
|
||||
poll()
|
||||
|
||||
// 返回停止轮询的函数
|
||||
return () => {
|
||||
isPolling = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default imageToVideoApi
|
||||
Reference in New Issue
Block a user