# 积分冻结系统

## 概述

积分冻结系统实现了任务提交时冻结积分、任务完成时扣除、任务失败时返还的完整积分管理流程。

## 系统特性

### 🔒 **积分状态管理**
- **正常积分**: 用户可以自由使用的积分
- **冻结积分**: 任务提交时临时冻结的积分，不可使用
- **可用积分**: 正常积分 - 冻结积分

### 📋 **冻结记录管理**
- 完整的积分冻结记录追踪
- 支持多种冻结状态：已冻结、已扣除、已返还、已过期
- 自动处理过期冻结记录（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. **监控告警**: 监控积分冻结系统的运行状态








