# 卡片系统 API 文档

本文档详细说明卡片系统的API接口，包括卡片模板、批次管理、卡片生成和使用功能。

## 接口基础信息

- **基础路径**: `/api/card/`
- **认证方式**: Token 认证
- **返回格式**: JSON

## API 概览

| 接口路径 | 方法 | 描述 |
|---------|------|------|
| `/api/card/templates/` | GET, POST | 卡片模板管理 |
| `/api/card/templates/{id}/` | GET, PUT, DELETE | 卡片模板详情操作 |
| `/api/card/batches/` | GET, POST | 卡片批次管理 |
| `/api/card/batches/{id}/` | GET, PUT, DELETE | 卡片批次详情操作 |
| `/api/card/cards/` | GET, POST | 卡片管理 |
| `/api/card/cards/{id}/` | GET, PUT, DELETE | 卡片详情操作 |
| `/api/card/user/cards/` | GET | 用户卡片列表 |
| `/api/card/category/{category}/` | GET | 按类别查询模板 |

## 1. 卡片模板管理

### 1.1 获取模板列表

获取所有卡片模板的列表。

- **URL**: `/api/card/templates/`
- **方法**: `GET`
- **认证**: 需要
- **查询参数**:

| 参数名 | 类型 | 描述 |
|-------|-----|------|
| category | string | 按类别筛选 |
| is_active | boolean | 按激活状态筛选 |
| page | integer | 页码 |
| page_size | integer | 每页数量 |

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "count": 50,
    "next": "http://localhost:8000/api/card/templates/?page=2",
    "previous": null,
    "results": [
      {
        "id": 1,
        "name": "舞蹈卡片模板",
        "category": "dance",
        "description": "用于舞蹈技能学习的卡片",
        "image": "https://example.com/card_templates/dance_template.jpg",
        "attributes": {
          "difficulty": "初级",
          "duration": "30分钟",
          "style": "现代舞"
        },
        "rarity": "common",
        "is_active": true,
        "created_at": "2023-01-01T00:00:00Z",
        "updated_at": "2023-01-01T00:00:00Z"
      }
    ]
  }
}
```

### 1.2 创建卡片模板

创建新的卡片模板。

- **URL**: `/api/card/templates/`
- **方法**: `POST`
- **认证**: 需要（管理员权限）
- **请求体**:

```json
{
  "name": "唱歌卡片模板",
  "category": "song",
  "description": "用于音乐技能学习的卡片",
  "image": "https://example.com/card_templates/song_template.jpg",
  "attributes": {
    "genre": "流行",
    "difficulty": "中级",
    "bpm": 120,
    "language": "中文"
  },
  "rarity": "rare",
  "is_active": true
}
```

**请求参数说明：**

| 参数名 | 类型 | 必填 | 描述 |
|-------|-----|------|-----|
| name | string | 是 | 模板名称 |
| category | string | 是 | 卡片类别 |
| description | string | 否 | 模板描述 |
| image | string | 否 | 模板图片URL |
| attributes | object | 否 | 模板属性（根据类别不同） |
| rarity | string | 否 | 稀有度(common/rare/epic/legendary) |
| is_active | boolean | 否 | 是否激活，默认true |

**支持的卡片类别：**

- **dance**: 舞蹈卡片
- **song**: 音乐卡片  
- **clothing**: 服装卡片
- **game**: 游戏卡片

**响应示例：**

```json
{
  "status": "success",
  "code": 201,
  "data": {
    "id": 2,
    "name": "唱歌卡片模板",
    "category": "song",
    "description": "用于音乐技能学习的卡片",
    "image": "https://example.com/card_templates/song_template.jpg",
    "attributes": {
      "genre": "流行",
      "difficulty": "中级",
      "bpm": 120,
      "language": "中文"
    },
    "rarity": "rare",
    "is_active": true,
    "created_at": "2023-01-02T10:00:00Z",
    "updated_at": "2023-01-02T10:00:00Z"
  }
}
```

### 1.3 获取模板详情

- **URL**: `/api/card/templates/{id}/`
- **方法**: `GET`
- **参数**:
  - `id` (路径参数): 模板ID

### 1.4 更新模板

- **URL**: `/api/card/templates/{id}/`
- **方法**: `PUT`
- **认证**: 需要（管理员权限）

### 1.5 删除模板

- **URL**: `/api/card/templates/{id}/`
- **方法**: `DELETE`
- **认证**: 需要（管理员权限）

## 2. 卡片批次管理

### 2.1 获取批次列表

- **URL**: `/api/card/batches/`
- **方法**: `GET`
- **认证**: 需要

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "count": 10,
    "next": null,
    "previous": null,
    "results": [
      {
        "id": 1,
        "name": "2023年第一批舞蹈卡片",
        "template": 1,
        "template_name": "舞蹈卡片模板",
        "category": "dance",
        "total_quantity": 1000,
        "generated_quantity": 1000,
        "used_quantity": 150,
        "start_id": 1001,
        "end_id": 2000,
        "batch_code": "DANCE_20230101_001",
        "is_published": true,
        "expiry_date": "2023-12-31",
        "qr_code_base_url": "https://example.com/cards/",
        "created_at": "2023-01-01T00:00:00Z",
        "updated_at": "2023-01-01T00:00:00Z"
      }
    ]
  }
}
```

### 2.2 创建卡片批次

创建新的卡片批次并自动生成指定数量的卡片。

- **URL**: `/api/card/batches/`
- **方法**: `POST`
- **认证**: 需要（管理员权限）
- **请求体**:

```json
{
  "name": "2023年第二批音乐卡片",
  "template": 2,
  "total_quantity": 500,
  "expiry_date": "2023-12-31",
  "batch_code": "SONG_20230201_001"
}
```

**请求参数说明：**

| 参数名 | 类型 | 必填 | 描述 |
|-------|-----|------|-----|
| name | string | 是 | 批次名称 |
| template | integer | 是 | 卡片模板ID |
| total_quantity | integer | 是 | 生成卡片数量 |
| expiry_date | string | 否 | 过期日期 (YYYY-MM-DD) |
| batch_code | string | 否 | 批次编码（自动生成） |

**响应示例：**

```json
{
  "status": "success",
  "code": 201,
  "data": {
    "id": 2,
    "name": "2023年第二批音乐卡片",
    "template": 2,
    "template_name": "唱歌卡片模板",
    "category": "song",
    "total_quantity": 500,
    "generated_quantity": 500,
    "used_quantity": 0,
    "start_id": 2001,
    "end_id": 2500,
    "batch_code": "SONG_20230201_001",
    "is_published": false,
    "expiry_date": "2023-12-31",
    "qr_code_base_url": "https://example.com/cards/",
    "created_at": "2023-02-01T10:00:00Z",
    "updated_at": "2023-02-01T10:00:00Z"
  }
}
```

## 3. 卡片管理

### 3.1 获取卡片列表

- **URL**: `/api/card/cards/`
- **方法**: `GET`
- **认证**: 需要
- **查询参数**:

| 参数名 | 类型 | 描述 |
|-------|-----|------|
| batch | integer | 按批次筛选 |
| category | string | 按类别筛选 |
| is_used | boolean | 按使用状态筛选 |
| user | integer | 按使用用户筛选 |

**响应示例：**

```json
{
  "status": "success", 
  "code": 200,
  "data": {
    "count": 1000,
    "next": "http://localhost:8000/api/card/cards/?page=2",
    "previous": null,
    "results": [
      {
        "id": 1001,
        "batch": 1,
        "batch_name": "2023年第一批舞蹈卡片",
        "template": 1,
        "template_name": "舞蹈卡片模板",
        "category": "dance",
        "card_code": "DANCE_20230101_001_1001",
        "qr_code": "https://example.com/cards/DANCE_20230101_001_1001",
        "qr_code_image": "https://example.com/qr/DANCE_20230101_001_1001.png",
        "is_used": false,
        "used_by": null,
        "used_at": null,
        "expires_at": "2023-12-31T23:59:59Z",
        "created_at": "2023-01-01T00:00:00Z"
      }
    ]
  }
}
```

### 3.2 获取卡片详情

- **URL**: `/api/card/cards/{id}/`
- **方法**: `GET`
- **参数**:
  - `id` (路径参数): 卡片ID

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "id": 1001,
    "batch": {
      "id": 1,
      "name": "2023年第一批舞蹈卡片",
      "category": "dance"
    },
    "template": {
      "id": 1,
      "name": "舞蹈卡片模板",
      "category": "dance",
      "attributes": {
        "difficulty": "初级",
        "duration": "30分钟",
        "style": "现代舞"
      },
      "rarity": "common"
    },
    "card_code": "DANCE_20230101_001_1001",
    "qr_code": "https://example.com/cards/DANCE_20230101_001_1001",
    "qr_code_image": "https://example.com/qr/DANCE_20230101_001_1001.png",
    "is_used": false,
    "used_by": null,
    "used_at": null,
    "expires_at": "2023-12-31T23:59:59Z",
    "created_at": "2023-01-01T00:00:00Z"
  }
}
```

### 3.3 使用卡片

用户扫描或输入卡片码来使用卡片。

- **URL**: `/api/card/cards/use/`
- **方法**: `POST`
- **认证**: 需要
- **请求体**:

```json
{
  "card_code": "DANCE_20230101_001_1001"
}
```

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "card": {
      "id": 1001,
      "card_code": "DANCE_20230101_001_1001",
      "template": {
        "name": "舞蹈卡片模板",
        "category": "dance",
        "attributes": {
          "difficulty": "初级",
          "duration": "30分钟",
          "style": "现代舞"
        }
      }
    },
    "usage_log": {
      "id": 1,
      "card": 1001,
      "user": 1,
      "used_at": "2023-01-02T14:30:00Z",
      "ip_address": "192.168.1.100",
      "user_agent": "Mozilla/5.0..."
    },
    "message": "卡片使用成功！您获得了舞蹈技能：现代舞(初级)"
  }
}
```

### 3.4 批量生成卡片二维码

为指定批次生成二维码图片。

- **URL**: `/api/card/batches/{batch_id}/generate_qrcodes/`
- **方法**: `POST`
- **认证**: 需要（管理员权限）
- **响应示例**:

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "batch_id": 1,
    "generated_count": 1000,
    "zip_download_url": "https://example.com/downloads/batch_1_qrcodes.zip",
    "expires_at": "2023-01-03T00:00:00Z"
  }
}
```

## 4. 用户卡片

### 4.1 获取用户卡片列表

获取当前用户使用过的卡片列表。

- **URL**: `/api/card/user/cards/`
- **方法**: `GET`
- **认证**: 需要
- **查询参数**:

| 参数名 | 类型 | 描述 |
|-------|-----|------|
| category | string | 按类别筛选 |
| start_date | string | 使用开始日期 |
| end_date | string | 使用结束日期 |

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "count": 5,
    "next": null,
    "previous": null,
    "results": [
      {
        "usage_log_id": 1,
        "card": {
          "id": 1001,
          "card_code": "DANCE_20230101_001_1001",
          "template": {
            "name": "舞蹈卡片模板",
            "category": "dance",
            "attributes": {
              "difficulty": "初级",
              "duration": "30分钟",
              "style": "现代舞"
            },
            "rarity": "common"
          }
        },
        "used_at": "2023-01-02T14:30:00Z",
        "ip_address": "192.168.1.100"
      }
    ]
  }
}
```

## 5. 按类别查询

### 5.1 按类别获取模板

- **URL**: `/api/card/category/{category}/`
- **方法**: `GET`
- **参数**:
  - `category` (路径参数): 卡片类别
- **认证**: 需要

**支持的类别：**
- `dance` - 舞蹈类
- `song` - 音乐类
- `clothing` - 服装类
- `game` - 游戏类

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "category": "dance",
    "templates": [
      {
        "id": 1,
        "name": "舞蹈卡片模板",
        "description": "用于舞蹈技能学习的卡片",
        "attributes": {
          "difficulty": "初级",
          "duration": "30分钟",
          "style": "现代舞"
        },
        "rarity": "common",
        "available_batches": [
          {
            "id": 1,
            "name": "2023年第一批舞蹈卡片",
            "available_quantity": 850
          }
        ]
      }
    ]
  }
}
```

## 6. 卡片属性系统

### 6.1 舞蹈卡片属性

```json
{
  "difficulty": "初级/中级/高级",
  "duration": "时长(分钟)",
  "style": "舞蹈风格",
  "choreographer": "编舞师",
  "music_bpm": "音乐BPM"
}
```

### 6.2 音乐卡片属性

```json
{
  "genre": "音乐风格",
  "difficulty": "难度等级",
  "bpm": "节拍",
  "language": "语言",
  "artist": "艺术家",
  "duration": "时长",
  "key": "调性",
  "audio_file": "音频文件URL"
}
```

### 6.3 服装卡片属性

```json
{
  "color": "颜色",
  "size": "尺码",
  "style": "风格",
  "season": "适用季节",
  "material": "材质",
  "brand": "品牌"
}
```

## 7. 统计和报告

### 7.1 获取卡片使用统计

- **URL**: `/api/card/statistics/`
- **方法**: `GET`
- **认证**: 需要（管理员权限）
- **查询参数**:

| 参数名 | 类型 | 描述 |
|-------|-----|------|
| start_date | string | 统计开始日期 |
| end_date | string | 统计结束日期 |
| category | string | 按类别筛选 |

**响应示例：**

```json
{
  "status": "success",
  "code": 200,
  "data": {
    "period": {
      "start_date": "2023-01-01",
      "end_date": "2023-01-31"
    },
    "summary": {
      "total_cards": 2000,
      "used_cards": 350,
      "usage_rate": 17.5,
      "unique_users": 125
    },
    "by_category": {
      "dance": {
        "total": 1000,
        "used": 200,
        "usage_rate": 20.0
      },
      "song": {
        "total": 500,
        "used": 100,
        "usage_rate": 20.0
      },
      "clothing": {
        "total": 300,
        "used": 30,
        "usage_rate": 10.0
      },
      "game": {
        "total": 200,
        "used": 20,
        "usage_rate": 10.0
      }
    },
    "daily_usage": [
      {
        "date": "2023-01-01",
        "count": 15
      },
      {
        "date": "2023-01-02", 
        "count": 23
      }
    ]
  }
}
```

## 8. 错误响应

### 8.1 常见错误码

| 错误码 | HTTP状态码 | 描述 |
|-------|-----------|------|
| CARD_NOT_FOUND | 404 | 卡片不存在 |
| CARD_EXPIRED | 400 | 卡片已过期 |
| CARD_ALREADY_USED | 400 | 卡片已被使用 |
| BATCH_FULL | 400 | 批次已满 |
| INSUFFICIENT_PERMISSION | 403 | 权限不足 |

### 8.2 错误响应示例

```json
{
  "status": "error",
  "code": 400,
  "message": "卡片已被使用",
  "error_code": "CARD_ALREADY_USED",
  "details": {
    "card_code": "DANCE_20230101_001_1001",
    "used_by": "user123",
    "used_at": "2023-01-02T14:30:00Z"
  }
}
```

## 9. 使用示例

### 9.1 Python 客户端示例

```python
import requests

class CardClient:
    def __init__(self, base_url, token):
        self.base_url = base_url
        self.headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
    
    def create_template(self, name, category, **kwargs):
        """创建卡片模板"""
        data = {
            'name': name,
            'category': category,
            **kwargs
        }
        response = requests.post(
            f'{self.base_url}/templates/',
            headers=self.headers,
            json=data
        )
        return response.json()
    
    def create_batch(self, template_id, quantity, name):
        """创建卡片批次"""
        data = {
            'template': template_id,
            'total_quantity': quantity,
            'name': name
        }
        response = requests.post(
            f'{self.base_url}/batches/',
            headers=self.headers,
            json=data
        )
        return response.json()
    
    def use_card(self, card_code):
        """使用卡片"""
        data = {'card_code': card_code}
        response = requests.post(
            f'{self.base_url}/cards/use/',
            headers=self.headers,
            json=data
        )
        return response.json()
    
    def get_user_cards(self):
        """获取用户卡片"""
        response = requests.get(
            f'{self.base_url}/user/cards/',
            headers=self.headers
        )
        return response.json()

# 使用示例
client = CardClient('http://localhost:8000/api/card', 'your-token')

# 创建舞蹈卡片模板
template = client.create_template(
    name='爵士舞模板',
    category='dance',
    attributes={
        'difficulty': '中级',
        'style': '爵士舞',
        'duration': '45分钟'
    },
    rarity='rare'
)

# 创建卡片批次
batch = client.create_batch(
    template_id=template['data']['id'],
    quantity=100,
    name='爵士舞卡片第一批'
)

# 使用卡片
result = client.use_card('DANCE_20230101_001_1001')
```

## 10. 最佳实践

### 10.1 卡片码格式
推荐的卡片码格式：`{CATEGORY}_{DATE}_{BATCH}_{ID}`
- 示例：`DANCE_20230101_001_1001`

### 10.2 批次管理
- 建议按月或季度创建批次
- 每个批次的数量不超过10000张
- 定期清理过期未使用的卡片

### 10.3 安全考虑
- 卡片码应足够复杂，避免被猜测
- 实施速率限制防止恶意扫描
- 记录使用日志用于审计

### 10.4 性能优化
- 对于高频查询的字段建立数据库索引
- 使用Redis缓存热门卡片信息
- 批量操作时使用数据库事务