# 赛程编排API冲突修复说明

## 问题描述

在实现赛程编排后端API时，发现项目中已经存在 `MartialScheduleArrangeController` 控制器，该控制器已经定义了相同的路径：
- `GET /martial/schedule/result`
- `POST /martial/schedule/save-and-lock`

这导致Spring Boot启动时报错：
```
Ambiguous mapping. Cannot map 'martialScheduleController' method to {POST [/martial/schedule/save-and-lock]}:
There is already 'martialScheduleArrangeController' bean method mapped.
```

## 解决方案

### 1. 删除重复的控制器端点

从新创建的 `MartialScheduleController` 中删除了冲突的3个端点：
- `/result`
- `/save-draft`
- `/save-and-lock`

保留原有的基础CRUD端点（detail, list, submit, remove）。

### 2. 更新现有控制器

修改 `MartialScheduleArrangeController`，使其使用新创建的Service和DTO：

**文件**: [MartialScheduleArrangeController.java](d:\workspace\31.比赛项目\project\martial-master\src\main\java\org\springblade\modules\martial\controller\MartialScheduleArrangeController.java)

#### 2.1 添加依赖注入

```java
private final IMartialScheduleArrangeService scheduleArrangeService;
private final IMartialScheduleService scheduleService; // 新增
```

#### 2.2 更新 GET /result 端点

**修改前**:
```java
public R<Map<String, Object>> getScheduleResult(@RequestParam Long competitionId) {
    Map<String, Object> result = scheduleArrangeService.getScheduleResult(competitionId);
    return R.data(result);
}
```

**修改后**:
```java
public R<ScheduleResultDTO> getScheduleResult(@RequestParam Long competitionId) {
    ScheduleResultDTO result = scheduleService.getScheduleResult(competitionId);
    return R.data(result);
}
```

**改进**:
- 使用结构化的DTO替代Map
- 返回类型更加明确
- 符合前端API规范

#### 2.3 新增 POST /save-draft 端点

```java
@PostMapping("/save-draft")
@Operation(summary = "保存编排草稿", description = "传入编排草稿数据")
public R saveDraftSchedule(@RequestBody SaveScheduleDraftDTO dto) {
    try {
        boolean success = scheduleService.saveDraftSchedule(dto);
        return success ? R.success("草稿保存成功") : R.fail("草稿保存失败");
    } catch (Exception e) {
        log.error("保存编排草稿失败", e);
        return R.fail("保存编排草稿失败: " + e.getMessage());
    }
}
```

#### 2.4 更新 POST /save-and-lock 端点

**修改前**:
```java
public R saveAndLock(@RequestBody Map<String, Object> params) {
    Long competitionId = Long.valueOf(String.valueOf(params.get("competitionId")));
    scheduleArrangeService.saveAndLock(competitionId, userId);
    return R.success("编排已保存并锁定");
}
```

**修改后**:
```java
public R saveAndLock(@RequestBody SaveScheduleDraftDTO dto) {
    BladeUser user = AuthUtil.getUser();
    String userId = user != null ? user.getUserName() : "system";

    boolean success = scheduleService.saveAndLockSchedule(dto.getCompetitionId());
    if (success) {
        // 调用原有的锁定逻辑
        scheduleArrangeService.saveAndLock(dto.getCompetitionId(), userId);
        return R.success("编排已完成并锁定");
    } else {
        return R.fail("编排锁定失败");
    }
}
```

**改进**:
1. 使用DTO替代Map，类型安全
2. 结合新旧两个Service的功能
3. 先更新参赛者状态，再执行原有的锁定逻辑

## 最终API结构

### MartialScheduleArrangeController
**基础路径**: `/martial/schedule`

| 方法 | 路径 | 功能 | 请求类型 | 响应类型 |
|------|------|------|----------|----------|
| GET | `/result` | 获取编排结果 | competitionId | ScheduleResultDTO |
| POST | `/save-draft` | 保存编排草稿 | SaveScheduleDraftDTO | R |
| POST | `/save-and-lock` | 完成编排并锁定 | SaveScheduleDraftDTO | R |
| POST | `/auto-arrange` | 手动触发自动编排 | Map | R |

### MartialScheduleController
**基础路径**: `/martial/schedule`

| 方法 | 路径 | 功能 | 请求类型 | 响应类型 |
|------|------|------|----------|----------|
| GET | `/detail` | 获取详情 | id | MartialSchedule |
| GET | `/list` | 分页列表 | MartialSchedule, Query | IPage |
| POST | `/submit` | 新增或修改 | MartialSchedule | R |
| POST | `/remove` | 删除 | ids | R |

## 字段冲突修复

### 问题
实体类 `MartialScheduleParticipant` 的 `status` 字段与基础类 `TenantEntity` 冲突。

### 解决方案
将 `status` 字段重命名为 `checkInStatus`（签到状态）：

**文件**: [MartialScheduleParticipant.java:86-90](d:\workspace\31.比赛项目\project\martial-master\src\main\java\org\springblade\modules\martial\pojo\entity\MartialScheduleParticipant.java#L86-L90)

```java
/**
 * 签到状态：未签到/已签到/异常
 */
@Schema(description = "签到状态：未签到/已签到/异常")
private String checkInStatus;
```

### 相应更新

**Service层** ([MartialScheduleServiceImpl.java](d:\workspace\31.比赛项目\project\martial-master\src\main\java\org\springblade\modules\martial\service\impl\MartialScheduleServiceImpl.java)):

1. **读取时**:
```java
dto.setStatus(p.getCheckInStatus() != null ? p.getCheckInStatus() : "未签到");
```

2. **保存时**:
```java
participant.setCheckInStatus(participantDTO.getStatus());
```

前端仍然使用 `status` 字段，在Service层进行映射转换。

## 数据库字段名建议

```sql
ALTER TABLE martial_schedule_participant
ADD COLUMN check_in_status VARCHAR(20) DEFAULT '未签到' COMMENT '签到状态：未签到/已签到/异常',
ADD COLUMN schedule_status VARCHAR(20) DEFAULT 'draft' COMMENT '编排状态：draft/completed';
```

## 前后端对接

前端API配置无需修改，仍然使用原有路径：
```javascript
// 获取赛程编排结果
GET /api/martial/schedule/result

// 保存编排草稿
POST /api/martial/schedule/save-draft

// 完成编排并锁定
POST /api/martial/schedule/save-and-lock
```

所有端点都通过 `MartialScheduleArrangeController` 处理。

## 总结

通过以下措施解决了API冲突问题：

1. ✅ 删除重复的控制器端点
2. ✅ 更新现有控制器使用新的DTO和Service
3. ✅ 修复字段名冲突
4. ✅ 保持前端API路径不变
5. ✅ 结合新旧Service功能，确保业务逻辑完整

现在系统可以正常启动，API端点清晰明确，没有冲突。
