# 后端接口开发清单 > **项目**: 武术评分系统小程序 > **前端项目**: martial-admin-mini > **后端框架**: BladeX (Spring Boot + MyBatis Plus) > **创建时间**: 2025-12-12 > **状态**: 待开发 --- ## 📋 接口开发总览 ### 接口统计 | 类型 | 数量 | 状态 | |------|------|------| | **需要新增的接口** | 5个 | ⚠️ 待开发 | | **可以复用的接口** | 4个 | ✅ 已有 | | **总计** | 9个 | 56% 待开发 | ### 开发优先级 | 优先级 | 接口数量 | 预计工作量 | |--------|---------|-----------| | 🔴 **高优先级** | 2个 | 3天 | | 🟡 **中优先级** | 3个 | 3天 | | **总计** | 5个 | **6人天** | --- ## 🔴 高优先级接口(必须先实现) ### 1. 登录验证接口 **接口信息**: ``` POST /api/mini/login ``` **功能描述**: 通过比赛编码和邀请码进行登录验证,返回Token和用户信息。 **请求参数**: ```json { "matchCode": "123", "inviteCode": "pub" } ``` **响应数据**: ```json { "code": 200, "success": true, "msg": "登录成功", "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "userRole": "pub", "matchId": "123", "matchName": "2025年全国武术散打锦标赛暨第十七届世界武术锦标赛选拔赛", "matchTime": "2025年6月25日 9:00", "judgeId": "456", "judgeName": "欧阳丽娜", "venueId": "1", "venueName": "第一场地", "projects": ["女子组长拳", "男子组陈氏太极拳"] } } ``` **实现逻辑**: 1. 验证 `matchCode` 是否存在且有效 2. 验证 `inviteCode` 是否存在且未过期 3. 查询 `martial_judge_invite` 表获取评委信息 4. 生成 JWT Token(使用 BladeX 的 Token 生成机制) 5. 更新邀请码使用状态(`is_used=1`, `use_time=now()`) 6. 返回用户信息和Token **SQL示例**: ```sql -- 验证邀请码 SELECT ji.id, ji.judge_id AS judgeId, ji.role, ji.venue_id AS venueId, ji.projects, j.judge_name AS judgeName, c.id AS matchId, c.competition_name AS matchName, c.start_time AS matchTime, v.venue_name AS venueName FROM martial_judge_invite ji LEFT JOIN martial_judge j ON ji.judge_id = j.id LEFT JOIN martial_competition c ON ji.competition_id = c.id LEFT JOIN martial_venue v ON ji.venue_id = v.id WHERE ji.invite_code = #{inviteCode} AND c.competition_code = #{matchCode} AND ji.is_used = 0 AND ji.expire_time > NOW() AND ji.is_deleted = 0 ``` **错误处理**: - 比赛编码不存在: `{ code: 400, msg: "比赛编码不存在" }` - 邀请码错误: `{ code: 401, msg: "邀请码错误或已失效" }` - 邀请码已使用: `{ code: 401, msg: "邀请码已被使用" }` - 邀请码已过期: `{ code: 401, msg: "邀请码已过期" }` **预计工作量**: 2天 --- ### 2. 获取评委的选手列表(普通评委) **接口信息**: ``` GET /api/mini/athletes ``` **功能描述**: 获取当前评委分配的选手列表,包含评分状态。 **请求参数**: ``` judgeId=456&venueId=1&projectId=5 ``` **响应数据**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": [ { "athleteId": "1", "name": "张三", "idCard": "123456789000000000", "team": "少林寺武术大学院", "number": "123-4567898275", "myScore": 8.906, "totalScore": 8.907, "scored": true, "scoreTime": "2025-06-25 09:15:00" } ] } ``` **实现逻辑**: 1. 根据 `venueId` 和 `projectId` 查询选手列表 2. 左连接 `martial_score` 表,获取当前评委的评分状态 3. 按出场顺序排序 **SQL示例**: ```sql SELECT a.id AS athleteId, a.player_name AS name, a.id_card AS idCard, a.team_name AS team, a.player_no AS number, a.total_score AS totalScore, s.score AS myScore, CASE WHEN s.id IS NOT NULL THEN 1 ELSE 0 END AS scored, s.score_time AS scoreTime FROM martial_athlete a LEFT JOIN martial_score s ON a.id = s.athlete_id AND s.judge_id = #{judgeId} WHERE a.venue_id = #{venueId} AND a.project_id = #{projectId} AND a.is_deleted = 0 ORDER BY a.order_num ASC ``` **预计工作量**: 1天 --- ## 🟡 中优先级接口(核心功能) ### 3. 获取选手列表(裁判长) **接口信息**: ``` GET /api/mini/athletes/admin ``` **功能描述**: 裁判长查看所有选手的评分统计情况。 **请求参数**: ``` competitionId=123&venueId=1&projectId=5 ``` **响应数据**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": [ { "athleteId": "1", "name": "张三", "idCard": "123456789000000000", "team": "少林寺武术大学院", "number": "123-4567898275", "totalScore": 8.907, "judgeCount": 6, "totalJudges": 6, "canModify": true } ] } ``` **实现逻辑**: 1. 查询选手列表 2. 统计每个选手的评分人数 3. 查询该项目的总评委数 4. 判断是否可以修改(所有评委都已评分) **SQL示例**: ```sql SELECT a.id AS athleteId, a.player_name AS name, a.id_card AS idCard, a.team_name AS team, a.player_no AS number, a.total_score AS totalScore, COUNT(s.id) AS judgeCount, (SELECT COUNT(*) FROM martial_judge_project jp WHERE jp.project_id = #{projectId} AND jp.is_deleted = 0) AS totalJudges, CASE WHEN COUNT(s.id) = (SELECT COUNT(*) FROM martial_judge_project jp WHERE jp.project_id = #{projectId} AND jp.is_deleted = 0) THEN 1 ELSE 0 END AS canModify FROM martial_athlete a LEFT JOIN martial_score s ON a.id = s.athlete_id WHERE a.venue_id = #{venueId} AND a.project_id = #{projectId} AND a.is_deleted = 0 GROUP BY a.id ORDER BY a.order_num ASC ``` **预计工作量**: 1天 --- ### 4. 获取评分详情(裁判长查看) **接口信息**: ``` GET /api/mini/score/detail/{athleteId} ``` **功能描述**: 裁判长查看某个选手的所有评委评分详情。 **请求参数**: ``` 路径参数: athleteId=1 ``` **响应数据**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": { "athleteInfo": { "athleteId": "1", "name": "张三", "idCard": "123456789000000000", "team": "少林寺武术大学院", "number": "123-4567898275", "totalScore": 8.907 }, "judgeScores": [ { "judgeId": "1", "judgeName": "欧阳丽娜", "score": 8.907, "scoreTime": "2025-06-25 09:15:00", "note": "" } ], "modification": { "originalScore": 8.907, "modifiedScore": 8.910, "modifyReason": "修改原因", "modifyTime": "2025-06-25 10:00:00", "modifierName": "裁判长" } } } ``` **实现逻辑**: 1. 查询选手基本信息 2. 查询所有评委的评分记录 3. 查询修改记录(如果有) **SQL示例**: ```sql -- 选手信息 SELECT a.id AS athleteId, a.player_name AS name, a.id_card AS idCard, a.team_name AS team, a.player_no AS number, a.total_score AS totalScore FROM martial_athlete a WHERE a.id = #{athleteId} -- 评委评分 SELECT s.judge_id AS judgeId, s.judge_name AS judgeName, s.score, s.score_time AS scoreTime, s.note FROM martial_score s WHERE s.athlete_id = #{athleteId} ORDER BY s.score_time ASC -- 修改记录(如果 original_score 不为空) SELECT s.original_score AS originalScore, s.score AS modifiedScore, s.modify_reason AS modifyReason, s.modify_time AS modifyTime, j.judge_name AS modifierName FROM martial_score s LEFT JOIN martial_judge j ON s.updated_by = j.id WHERE s.athlete_id = #{athleteId} AND s.original_score IS NOT NULL LIMIT 1 ``` **预计工作量**: 1天 --- ### 5. 修改评分(裁判长) **接口信息**: ``` PUT /api/mini/score/modify ``` **功能描述**: 裁判长修改选手的总分。 **请求参数**: ```json { "athleteId": "1", "modifierId": "789", "modifiedScore": 8.910, "note": "修改原因" } ``` **响应数据**: ```json { "code": 200, "success": true, "msg": "修改成功", "data": { "athleteId": "1", "originalScore": 8.907, "modifiedScore": 8.910, "modifyTime": "2025-06-25 10:00:00" } } ``` **实现逻辑**: 1. 验证权限(只有裁判长可以修改) 2. 查询当前总分 3. 如果是第一次修改,保存 `original_score` 4. 更新 `total_score` 5. 记录 `modify_reason` 和 `modify_time` 6. 更新 `martial_athlete` 表的 `total_score` **SQL示例**: ```sql -- 更新选手总分(第一次修改) UPDATE martial_athlete SET total_score = #{modifiedScore}, updated_by = #{modifierId}, update_time = NOW() WHERE id = #{athleteId} -- 记录修改信息(可以在 martial_score 表中添加一条特殊记录) -- 或者在 martial_athlete 表中添加字段记录修改历史 ``` **权限验证**: ```sql -- 验证是否为裁判长 SELECT role FROM martial_judge_invite WHERE judge_id = #{modifierId} AND role = 'chief_judge' AND is_deleted = 0 ``` **预计工作量**: 1天 --- ## ✅ 可以复用的现有接口 ### 6. 获取场地列表 **接口信息**: ``` GET /martial/venue/list ``` **状态**: ✅ 后端已实现,可直接使用 **请求参数**: ``` competitionId=123¤t=1&size=100 ``` **响应格式**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": { "records": [ { "id": "1", "venueName": "第一场地" } ] } } ``` **前端适配**: 需要从 `data.records` 中提取数据 --- ### 7. 获取项目列表 **接口信息**: ``` GET /martial/project/list ``` **状态**: ✅ 后端已实现,可直接使用 **请求参数**: ``` competitionId=123¤t=1&size=100 ``` **响应格式**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": { "records": [ { "id": "5", "projectName": "女子组长拳" } ] } } ``` **前端适配**: 需要从 `data.records` 中提取数据 --- ### 8. 获取扣分项列表 **接口信息**: ``` GET /martial/deductionItem/list ``` **状态**: ✅ 后端已实现,可直接使用 **请求参数**: ``` projectId=5¤t=1&size=100 ``` **响应格式**: ```json { "code": 200, "success": true, "msg": "操作成功", "data": { "records": [ { "id": "1", "itemName": "动作不到位", "deductionPoint": -0.1 } ] } } ``` **前端适配**: 需要从 `data.records` 中提取数据 --- ### 9. 提交评分 **接口信息**: ``` POST /martial/score/submit ``` **状态**: ✅ 后端已实现,可直接使用 **请求参数**: ```json { "athleteId": "1", "judgeId": "456", "score": 8.907, "deductionItems": "[{\"id\":\"1\",\"text\":\"动作不到位\",\"score\":-0.1}]", "note": "表现优秀" } ``` **响应格式**: ```json { "code": 200, "success": true, "msg": "提交成功", "data": null } ``` --- ## 🔧 后端开发建议 ### 1. 创建专用Controller 建议创建 `MartialMiniController` 来统一管理小程序接口: ```java package org.springblade.modules.martial.controller; import org.springblade.core.tool.api.R; import org.springframework.web.bind.annotation.*; /** * 武术评分系统 - 小程序专用接口 */ @RestController @RequestMapping("/api/mini") public class MartialMiniController { @PostMapping("/login") public R login(@RequestBody LoginDTO dto) { // 实现登录逻辑 } @GetMapping("/athletes") public R> getMyAthletes( @RequestParam Long judgeId, @RequestParam Long venueId, @RequestParam Long projectId ) { // 实现获取选手列表逻辑 } @GetMapping("/athletes/admin") public R> getAthletesForAdmin( @RequestParam Long competitionId, @RequestParam Long venueId, @RequestParam Long projectId ) { // 实现裁判长选手列表逻辑 } @GetMapping("/score/detail/{athleteId}") public R getScoreDetail(@PathVariable Long athleteId) { // 实现评分详情逻辑 } @PutMapping("/score/modify") public R modifyScore(@RequestBody ModifyScoreDTO dto) { // 实现修改评分逻辑 } } ``` ### 2. 创建专用VO类 ```java // LoginVO.java public class LoginVO { private String token; private String userRole; private String matchId; private String matchName; private String matchTime; private String judgeId; private String judgeName; private String venueId; private String venueName; private List projects; } // AthleteScoreVO.java public class AthleteScoreVO { private String athleteId; private String name; private String idCard; private String team; private String number; private BigDecimal myScore; private BigDecimal totalScore; private Boolean scored; private String scoreTime; } // AthleteAdminVO.java public class AthleteAdminVO { private String athleteId; private String name; private String idCard; private String team; private String number; private BigDecimal totalScore; private Integer judgeCount; private Integer totalJudges; private Boolean canModify; } ``` ### 3. Token认证配置 确保使用 `Blade-Auth` 头部: ```java // 在拦截器中获取Token String token = request.getHeader("Blade-Auth"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); // 验证Token } ``` ### 4. 响应格式统一 使用 BladeX 的标准响应格式: ```java // 成功 return R.success(data); // 失败 return R.fail("错误信息"); // 自定义状态码 return R.status(401).msg("未授权").build(); ``` --- ## 📝 开发检查清单 ### 后端开发 - [ ] 创建 `MartialMiniController` - [ ] 实现登录接口 `POST /api/mini/login` - [ ] 实现获取选手列表接口 `GET /api/mini/athletes` - [ ] 实现裁判长选手列表接口 `GET /api/mini/athletes/admin` - [ ] 实现评分详情接口 `GET /api/mini/score/detail/{id}` - [ ] 实现修改评分接口 `PUT /api/mini/score/modify` - [ ] 创建对应的VO类 - [ ] 编写单元测试 - [ ] 更新Swagger文档 ### 数据准备 - [ ] 创建测试比赛数据 - [ ] 创建测试评委数据 - [ ] 生成邀请码(pub 和 admin) - [ ] 创建测试选手数据 - [ ] 配置场地和项目数据 - [ ] 配置扣分项数据 ### 联调测试 - [ ] 测试登录接口(pub角色) - [ ] 测试登录接口(admin角色) - [ ] 测试获取选手列表 - [ ] 测试提交评分 - [ ] 测试评分详情查看 - [ ] 测试修改评分 - [ ] 测试Token过期处理 - [ ] 测试权限验证 --- ## 🎯 开发时间表 | 阶段 | 任务 | 工作量 | 负责人 | 状态 | |------|------|--------|--------|------| | **第1天** | 创建Controller和VO类 | 0.5天 | 后端 | ⚪ 待开始 | | **第1-2天** | 实现登录接口 | 1.5天 | 后端 | ⚪ 待开始 | | **第3天** | 实现选手列表接口(2个) | 1天 | 后端 | ⚪ 待开始 | | **第4天** | 实现评分详情接口 | 1天 | 后端 | ⚪ 待开始 | | **第5天** | 实现修改评分接口 | 1天 | 后端 | ⚪ 待开始 | | **第6天** | 单元测试和文档 | 1天 | 后端 | ⚪ 待开始 | | **第7天** | 前后端联调 | 1天 | 前后端 | ⚪ 待开始 | **总计**: 7个工作日 --- ## 📞 联系方式 如有问题,请联系: - **前端负责人**: [待填写] - **后端负责人**: [待填写] - **项目经理**: [待填写] --- **文档版本**: v1.0 **最后更新**: 2025-12-12 **下次更新**: 开发完成后