# 赛程编排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> getScheduleResult(@RequestParam Long competitionId) { Map result = scheduleArrangeService.getScheduleResult(competitionId); return R.data(result); } ``` **修改后**: ```java public R 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 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端点清晰明确,没有冲突。