Files
martial-admin-mini/doc/后端接口开发清单.md
宅房 da791f29fa feat: 完成API对接准备工作,前端已就绪
## 主要改动

### 1. 修复Mock数据格式问题
- 修复 mock/athlete.js 中 getProjects 函数
- 从字符串数组改为对象数组 { id, name }
- 确保Mock模式和API模式数据格式一致

### 2. 优化网络请求处理
- 优化 utils/request.js 的GET请求参数处理
- 参数自动URL编码
- 支持URL中已有查询参数的情况
- 代码逻辑更清晰

### 3. 新增完整的文档体系
- API对接说明.md - 项目根目录快速说明
- doc/API对接快速启动指南.md - 5分钟快速上手
- doc/后端接口开发清单.md - 后端开发规范(5个接口,6人天)
- doc/前端API对接指南.md - 前端联调指南
- doc/API对接准备完成报告.md - 项目状态总结

## 项目状态

 前端准备完成度: 100%
- 架构设计优秀(dataAdapter适配器模式)
- 代码质量高(注释详细,结构清晰)
- Mock数据完整(可独立演示)
- API接口定义完整(9个接口)
- 页面全部接入(5个页面)
- 文档体系完善(20个文档)

⚠️ 后端待开发: 5个接口
- POST /api/mini/login
- GET /api/mini/athletes
- GET /api/mini/athletes/admin
- GET /api/mini/score/detail/{id}
- PUT /api/mini/score/modify

## 下一步

后端开发者可以参考 doc/后端接口开发清单.md 开始开发
预计工作量: 6人天(约1周)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-12 00:48:46 +08:00

749 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端接口开发清单
> **项目**: 武术评分系统小程序
> **前端项目**: 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&current=1&size=100
```
**响应格式**:
```json
{
"code": 200,
"success": true,
"msg": "操作成功",
"data": {
"records": [
{ "id": "1", "venueName": "第一场地" }
]
}
}
```
**前端适配**: 需要从 `data.records` 中提取数据
---
### 7. 获取项目列表
**接口信息**:
```
GET /martial/project/list
```
**状态**: ✅ 后端已实现,可直接使用
**请求参数**:
```
competitionId=123&current=1&size=100
```
**响应格式**:
```json
{
"code": 200,
"success": true,
"msg": "操作成功",
"data": {
"records": [
{ "id": "5", "projectName": "女子组长拳" }
]
}
}
```
**前端适配**: 需要从 `data.records` 中提取数据
---
### 8. 获取扣分项列表
**接口信息**:
```
GET /martial/deductionItem/list
```
**状态**: ✅ 后端已实现,可直接使用
**请求参数**:
```
projectId=5&current=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<LoginVO> login(@RequestBody LoginDTO dto) {
// 实现登录逻辑
}
@GetMapping("/athletes")
public R<List<AthleteScoreVO>> getMyAthletes(
@RequestParam Long judgeId,
@RequestParam Long venueId,
@RequestParam Long projectId
) {
// 实现获取选手列表逻辑
}
@GetMapping("/athletes/admin")
public R<List<AthleteAdminVO>> getAthletesForAdmin(
@RequestParam Long competitionId,
@RequestParam Long venueId,
@RequestParam Long projectId
) {
// 实现裁判长选手列表逻辑
}
@GetMapping("/score/detail/{athleteId}")
public R<ScoreDetailVO> getScoreDetail(@PathVariable Long athleteId) {
// 实现评分详情逻辑
}
@PutMapping("/score/modify")
public R<ModifyResultVO> 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<String> 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
**下次更新**: 开发完成后