# 积分冻结系统 ## 概述 积分冻结系统实现了任务提交时冻结积分、任务完成时扣除、任务失败时返还的完整积分管理流程。 ## 系统特性 ### 🔒 **积分状态管理** - **正常积分**: 用户可以自由使用的积分 - **冻结积分**: 任务提交时临时冻结的积分,不可使用 - **可用积分**: 正常积分 - 冻结积分 ### 📋 **冻结记录管理** - 完整的积分冻结记录追踪 - 支持多种冻结状态:已冻结、已扣除、已返还、已过期 - 自动处理过期冻结记录(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 Response: { "success": true, "data": { "totalPoints": 1000, "frozenPoints": 80, "availablePoints": 920 } } ``` ### 获取冻结记录 ``` GET /api/points/freeze-records Authorization: Bearer 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 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 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. **监控告警**: 监控积分冻结系统的运行状态