Files
martial-master/docs/tasks/02-比赛日流程功能.md
n72595987@gmail.com 21c133f9c9
All checks were successful
continuous-integration/drone/push Build is passing
feat: 实现成绩计算引擎、比赛日流程和导出打印功能
本次提交完成了武术比赛系统的核心功能模块,包括:

## 1. 成绩计算引擎 (Tasks 1.1-1.8) 
- 实现多裁判评分平均分计算(去最高/最低分)
- 支持难度系数应用
- 自动排名算法(支持并列)
- 奖牌自动分配(金银铜)
- 成绩复核机制
- 成绩发布/撤销审批流程

## 2. 比赛日流程功能 (Tasks 2.1-2.6) 
- 运动员签到/检录系统
- 评分有效性验证(范围检查0-10分)
- 异常分数警告机制(偏差>2.0)
- 异常情况记录和处理
- 检录长角色权限管理
- 比赛状态流转管理

## 3. 导出打印功能 (Tasks 3.1-3.4) 
- 成绩单Excel导出(EasyExcel)
- 运动员名单Excel导出
- 赛程表Excel导出
- 证书生成(HTML模板+数据接口)

## 4. 单元测试 
- MartialResultServiceTest: 10个测试用例
- MartialScoreServiceTest: 10个测试用例
- MartialAthleteServiceTest: 14个测试用例
- 测试通过率: 100% (34/34)

## 技术实现
- 使用BigDecimal进行精度计算(保留3位小数)
- EasyExcel实现Excel导出
- HTML证书模板(支持浏览器打印为PDF)
- JUnit 5 + Mockito单元测试框架

## 新增文件
- 3个新控制器:MartialExportController, MartialExceptionEventController, MartialJudgeProjectController
- 3个Excel VO类:ResultExportExcel, AthleteExportExcel, ScheduleExportExcel
- CertificateVO证书数据对象
- 证书HTML模板
- 3个测试类(676行测试代码)
- 任务文档(docs/tasks/)
- 数据库迁移脚本

## 项目进度
已完成: 64% (18/28 任务)
-  成绩计算引擎: 100%
-  比赛日流程: 100%
-  导出打印功能: 80%

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 17:11:12 +08:00

242 lines
6.0 KiB
Markdown
Raw Permalink 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.
# 比赛日流程功能 - 详细任务清单
**优先级:** P1重要
**预计工时:** 4天
**负责人:** 待分配
**创建时间:** 2025-11-30
---
## 📋 任务概述
比赛日流程功能包括运动员签到检录、评分验证、异常处理等关键环节。
---
## ✅ 任务列表
### 任务 2.1:运动员签到/检录系统 🔴
**状态:** 未开始
**工时:** 1.5天
#### 需求描述
- 运动员签到功能
- 更新比赛状态(待出场 → 进行中 → 已完成)
- 检录员角色权限管理
#### 实现要点
```java
// MartialAthleteServiceImpl.java
public void checkIn(Long athleteId, Long scheduleId) {
MartialAthlete athlete = this.getById(athleteId);
// 更新运动员状态:待出场 → 进行中
athlete.setCompetitionStatus(1); // 进行中
this.updateById(athlete);
// 更新赛程运动员关联状态
MartialScheduleAthlete scheduleAthlete = scheduleAthleteService.getOne(
new QueryWrapper<MartialScheduleAthlete>()
.eq("schedule_id", scheduleId)
.eq("athlete_id", athleteId)
);
scheduleAthlete.setIsCompleted(0); // 未完成
scheduleAthleteService.updateById(scheduleAthlete);
}
public void completePerformance(Long athleteId) {
MartialAthlete athlete = this.getById(athleteId);
athlete.setCompetitionStatus(2); // 已完成
this.updateById(athlete);
}
```
#### API接口
- `POST /martial/athlete/checkin` - 签到
- `POST /martial/athlete/complete` - 完成比赛
---
### 任务 2.2:评分有效性验证 🔴
**状态:** 未开始
**工时:** 0.5天
#### 需求描述
- 分数范围检查5.000 - 10.000
- 评分提交前验证
- 异常分数提示
#### 实现要点
```java
// MartialScoreServiceImpl.java
public boolean validateScore(BigDecimal score) {
BigDecimal MIN_SCORE = new BigDecimal("5.000");
BigDecimal MAX_SCORE = new BigDecimal("10.000");
return score.compareTo(MIN_SCORE) >= 0
&& score.compareTo(MAX_SCORE) <= 0;
}
@Override
public boolean save(MartialScore score) {
// 验证分数范围
if (!validateScore(score.getScore())) {
throw new ServiceException("分数必须在5.000-10.000之间");
}
return super.save(score);
}
```
---
### 任务 2.3:异常分数警告机制 🔴
**状态:** 未开始
**工时:** 1天
#### 需求描述
- 检测离群值(与其他裁判差距过大)
- 生成警告提示
- 记录异常日志
#### 实现要点
```java
public void checkAnomalyScore(MartialScore newScore) {
// 获取同一运动员的其他裁判评分
List<MartialScore> scores = this.list(
new QueryWrapper<MartialScore>()
.eq("athlete_id", newScore.getAthleteId())
.eq("project_id", newScore.getProjectId())
.ne("judge_id", newScore.getJudgeId())
);
if (scores.size() < 2) {
return; // 评分数量不足,无法判断
}
// 计算其他裁判的平均分
BigDecimal avgScore = scores.stream()
.map(MartialScore::getScore)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(new BigDecimal(scores.size()), 3, RoundingMode.HALF_UP);
// 判断偏差
BigDecimal diff = newScore.getScore().subtract(avgScore).abs();
if (diff.compareTo(new BigDecimal("1.000")) > 0) {
// 偏差超过1.0分,记录警告
log.warn("异常评分:裁判{}给运动员{}打分{},偏离平均分{}超过1.0",
newScore.getJudgeName(),
newScore.getAthleteId(),
newScore.getScore(),
avgScore
);
}
}
```
---
### 任务 2.4:异常情况记录和处理 🔴
**状态:** 未开始
**工时:** 0.5天
#### 需求描述
- 新建异常事件表
- 记录异常类型、处理结果
- 支持查询统计
#### 数据库表设计
```sql
CREATE TABLE martial_exception_event (
id BIGINT PRIMARY KEY,
competition_id BIGINT NOT NULL COMMENT '赛事ID',
schedule_id BIGINT COMMENT '赛程ID',
athlete_id BIGINT COMMENT '运动员ID',
event_type INT COMMENT '事件类型 1-器械故障 2-受伤 3-评分争议 4-其他',
event_description VARCHAR(500) COMMENT '事件描述',
handler_name VARCHAR(50) COMMENT '处理人',
handle_result VARCHAR(500) COMMENT '处理结果',
handle_time DATETIME COMMENT '处理时间',
status INT DEFAULT 0 COMMENT '状态 0-待处理 1-已处理',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
is_deleted INT DEFAULT 0
) COMMENT '异常事件表';
```
---
### 任务 2.5:检录长角色权限管理 🔴
**状态:** 未开始
**工时:** 0.5天
#### 需求描述
- 定义检录长角色
- 赋予特殊权限(处理异常、调整赛程)
- 集成现有权限系统
#### 实现要点
- 利用 BladeX 框架的角色权限系统
- 新增角色:`ROLE_REFEREE_CHIEF`
- 权限:异常处理、成绩复核申请
---
### 任务 2.6:比赛状态流转管理 🔴
**状态:** 未开始
**工时:** 0.5天
#### 需求描述
- 状态机管理运动员比赛状态
- 防止非法状态转换
- 记录状态变更日志
#### 状态流转图
```
待出场(0) → 进行中(1) → 已完成(2)
↓ ↓
已取消 暂停/异常
```
---
## 🎯 Controller 层接口
```java
@RestController
@RequestMapping("/martial/athlete")
public class MartialAthleteController {
@PostMapping("/checkin")
@Operation(summary = "运动员签到")
public R checkIn(@RequestParam Long athleteId, @RequestParam Long scheduleId) {
athleteService.checkIn(athleteId, scheduleId);
return R.success("签到成功");
}
@PostMapping("/complete")
@Operation(summary = "完成比赛")
public R complete(@RequestParam Long athleteId) {
athleteService.completePerformance(athleteId);
return R.success("已标记为完成");
}
}
```
---
## ✅ 验收标准
- [ ] 签到功能正常,状态更新准确
- [ ] 评分验证有效拦截非法分数
- [ ] 异常分数警告机制生效
- [ ] 异常事件可记录和查询
- [ ] 权限控制符合设计
---