# 赛程编排后端API数据格式规范

## 1. 获取赛程编排结果 - getScheduleResult

**接口地址**: `GET /api/martial/schedule/result`

**请求参数**:
```javascript
{
  competitionId: Number  // 赛事ID
}
```

**返回数据格式**:
```javascript
{
  "code": 200,
  "msg": "success",
  "data": {
    "isDraft": true,          // 是否为草稿状态
    "isCompleted": false,     // 是否已完成编排
    "competitionGroups": [    // 竞赛分组列表
      {
        "id": 1,                        // 分组ID
        "title": "1. 小学组小组赛男女类",  // 分组标题
        "type": "集体",                  // 类型：集体/单人/双人
        "count": "2队",                  // 队伍数量
        "code": "1101",                 // 分组编号
        "venueId": 1,                   // 当前所属场地ID
        "venueName": "一号场地",         // 场地名称
        "timeSlot": "2025年11月6日 上午8:30",  // 时间段
        "timeSlotIndex": 0,             // 时间段索引
        "participants": [               // 参赛人员列表
          {
            "id": 101,                  // 参赛人员ID
            "schoolUnit": "清河小学",    // 学校/单位
            "status": "未签到",          // 状态：未签到/已签到/异常
            "sortOrder": 1              // 排序
          },
          {
            "id": 102,
            "schoolUnit": "访河社区",
            "status": "未签到",
            "sortOrder": 2
          }
        ]
      },
      {
        "id": 2,
        "title": "1. 小学组小组赛男女类",
        "type": "单人",
        "count": "3队",
        "code": "1组",
        "venueId": 2,
        "venueName": "二号场地",
        "timeSlot": "2025年11月6日 上午8:30",
        "timeSlotIndex": 0,
        "participants": [
          {
            "id": 103,
            "schoolUnit": "少林寺武校",
            "status": "未签到",
            "sortOrder": 1
          },
          {
            "id": 104,
            "schoolUnit": "访河社区",
            "status": "已签到",
            "sortOrder": 2
          },
          {
            "id": 105,
            "schoolUnit": "武当派",
            "status": "异常",
            "sortOrder": 3
          }
        ]
      }
    ]
  }
}
```

**重要说明**:
1. **首次分配规则**: 系统后台需要按照"先集体，后个人"的顺序进行第一次场地分配
2. **状态字段**:
   - `未签到`: 默认状态
   - `已签到`: 参赛人员已签到
   - `异常`: 被标记为异常的参赛人员
3. **timeSlotIndex**: 对应前端动态生成的时间段数组索引，从0开始
4. **sortOrder**: 参赛人员在分组内的排序，用于上移/下移功能

## 2. 保存编排草稿 - saveDraftSchedule

**接口地址**: `POST /api/martial/schedule/save-draft`

**请求数据格式**:
```javascript
{
  "competitionId": 1,           // 赛事ID
  "isDraft": true,              // 是否为草稿
  "competitionGroups": [        // 竞赛分组数据
    {
      "id": 1,                  // 分组ID（如果是新建则为null）
      "title": "1. 小学组小组赛男女类",
      "type": "集体",
      "count": "2队",
      "code": "1101",
      "venueId": 1,             // 场地ID
      "venueName": "一号场地",
      "timeSlot": "2025年11月6日 上午8:30",
      "timeSlotIndex": 0,
      "participants": [
        {
          "id": 101,
          "schoolUnit": "清河小学",
          "status": "未签到",
          "sortOrder": 1
        },
        {
          "id": 102,
          "schoolUnit": "访河社区",
          "status": "异常",
          "sortOrder": 2
        }
      ]
    }
  ]
}
```

**返回数据格式**:
```javascript
{
  "code": 200,
  "msg": "草稿保存成功",
  "data": null
}
```

**重要说明**:
1. 草稿可以被多次保存和更新
2. 保存草稿不会锁定数据，用户可以继续编辑
3. 下次打开页面时，如果`isCompleted`为false，则加载草稿数据

## 3. 完成编排并锁定 - saveAndLockSchedule

**接口地址**: `POST /api/martial/schedule/save-and-lock`

**请求数据格式**:
```javascript
{
  "competitionId": 1  // 赛事ID
}
```

**返回数据格式**:
```javascript
{
  "code": 200,
  "msg": "编排已完成并锁定",
  "data": null
}
```

**重要说明**:
1. 完成编排后，`isCompleted`标记为true
2. 编排完成后，前端将禁用所有编辑功能（上移、下移、标记异常、移动分组等）
3. 只有在`isCompleted`为true时，才显示"导出"按钮

## 4. 前端页面功能说明

### 4.1 移动分组功能
- 用户可以将整个竞赛分组移动到不同的场地和时间段
- 移动后需要更新分组的`venueId`、`venueName`、`timeSlot`、`timeSlotIndex`字段
- 移动操作在保存草稿时提交到后端

### 4.2 异常组功能
- 只有状态为"未签到"的参赛人员才显示"异常"按钮
- 点击"异常"按钮后，参赛人员状态变为"异常"
- 异常参赛人员会在"异常组"弹窗中显示
- 可以从异常组移除，状态恢复为"未签到"

### 4.3 上移/下移功能
- 调整参赛人员在分组内的顺序
- 修改后会更新`sortOrder`字段
- 在保存草稿时提交到后端

### 4.4 保存草稿与完成编排
- **保存草稿**: 保存当前编排状态，不锁定，可继续编辑
- **完成编排**: 锁定编排，禁用所有编辑功能，显示导出按钮

## 5. 字段映射说明

| 前端字段 | 后端字段（可能的命名） | 说明 |
|---------|---------------------|------|
| schoolUnit | school_unit / schoolUnit | 学校/单位名称 |
| venueName | venue_name / venueName | 场地名称 |
| venueId | venue_id / venueId | 场地ID |
| timeSlot | time_slot / timeSlot | 时间段文本 |
| timeSlotIndex | time_slot_index / timeSlotIndex | 时间段索引 |
| sortOrder | sort_order / sortOrder | 排序 |

**提示**: 后端可以使用下划线命名（snake_case）或驼峰命名（camelCase），前端已做兼容处理。
