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

15 KiB
Raw Blame History

后端接口开发清单

项目: 武术评分系统小程序 前端项目: 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和用户信息。

请求参数:

{
  "matchCode": "123",
  "inviteCode": "pub"
}

响应数据:

{
  "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示例:

-- 验证邀请码
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

响应数据:

{
  "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. 根据 venueIdprojectId 查询选手列表
  2. 左连接 martial_score 表,获取当前评委的评分状态
  3. 按出场顺序排序

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

响应数据:

{
  "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示例:

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

响应数据:

{
  "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示例:

-- 选手信息
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

功能描述: 裁判长修改选手的总分。

请求参数:

{
  "athleteId": "1",
  "modifierId": "789",
  "modifiedScore": 8.910,
  "note": "修改原因"
}

响应数据:

{
  "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_reasonmodify_time
  6. 更新 martial_athlete 表的 total_score

SQL示例:

-- 更新选手总分(第一次修改)
UPDATE martial_athlete
SET
  total_score = #{modifiedScore},
  updated_by = #{modifierId},
  update_time = NOW()
WHERE id = #{athleteId}

-- 记录修改信息(可以在 martial_score 表中添加一条特殊记录)
-- 或者在 martial_athlete 表中添加字段记录修改历史

权限验证:

-- 验证是否为裁判长
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

响应格式:

{
  "code": 200,
  "success": true,
  "msg": "操作成功",
  "data": {
    "records": [
      { "id": "1", "venueName": "第一场地" }
    ]
  }
}

前端适配: 需要从 data.records 中提取数据


7. 获取项目列表

接口信息:

GET /martial/project/list

状态: 后端已实现,可直接使用

请求参数:

competitionId=123&current=1&size=100

响应格式:

{
  "code": 200,
  "success": true,
  "msg": "操作成功",
  "data": {
    "records": [
      { "id": "5", "projectName": "女子组长拳" }
    ]
  }
}

前端适配: 需要从 data.records 中提取数据


8. 获取扣分项列表

接口信息:

GET /martial/deductionItem/list

状态: 后端已实现,可直接使用

请求参数:

projectId=5&current=1&size=100

响应格式:

{
  "code": 200,
  "success": true,
  "msg": "操作成功",
  "data": {
    "records": [
      {
        "id": "1",
        "itemName": "动作不到位",
        "deductionPoint": -0.1
      }
    ]
  }
}

前端适配: 需要从 data.records 中提取数据


9. 提交评分

接口信息:

POST /martial/score/submit

状态: 后端已实现,可直接使用

请求参数:

{
  "athleteId": "1",
  "judgeId": "456",
  "score": 8.907,
  "deductionItems": "[{\"id\":\"1\",\"text\":\"动作不到位\",\"score\":-0.1}]",
  "note": "表现优秀"
}

响应格式:

{
  "code": 200,
  "success": true,
  "msg": "提交成功",
  "data": null
}

🔧 后端开发建议

1. 创建专用Controller

建议创建 MartialMiniController 来统一管理小程序接口:

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类

// 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 头部:

// 在拦截器中获取Token
String token = request.getHeader("Blade-Auth");
if (token != null && token.startsWith("Bearer ")) {
    token = token.substring(7);
    // 验证Token
}

4. 响应格式统一

使用 BladeX 的标准响应格式:

// 成功
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 下次更新: 开发完成后