This commit is contained in:
347
doc/schedule/archive/schedule-backend-implementation-summary.md
Normal file
347
doc/schedule/archive/schedule-backend-implementation-summary.md
Normal file
@@ -0,0 +1,347 @@
|
||||
# 赛程编排后端实现总结
|
||||
|
||||
## 实施概览
|
||||
|
||||
本次实现了赛程编排系统的三个核心后端API接口,完全按照 `schedule-backend-api-spec.md` 文档的规范进行开发。
|
||||
|
||||
## 实现的文件列表
|
||||
|
||||
### 1. DTO类 (数据传输对象)
|
||||
|
||||
#### 1.1 ScheduleResultDTO.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/pojo/dto/ScheduleResultDTO.java`
|
||||
- **作用**: 赛程编排结果的响应数据结构
|
||||
- **字段**:
|
||||
- `isDraft`: 是否为草稿状态
|
||||
- `isCompleted`: 是否已完成编排
|
||||
- `competitionGroups`: 竞赛分组列表
|
||||
|
||||
#### 1.2 CompetitionGroupDTO.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/pojo/dto/CompetitionGroupDTO.java`
|
||||
- **作用**: 竞赛分组数据结构
|
||||
- **字段**:
|
||||
- `id`: 分组ID
|
||||
- `title`: 分组标题
|
||||
- `type`: 类型(集体/单人/双人)
|
||||
- `count`: 队伍数量
|
||||
- `code`: 分组编号
|
||||
- `venueId`: 场地ID
|
||||
- `venueName`: 场地名称
|
||||
- `timeSlot`: 时间段
|
||||
- `timeSlotIndex`: 时间段索引
|
||||
- `participants`: 参赛人员列表
|
||||
|
||||
#### 1.3 ParticipantDTO.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/pojo/dto/ParticipantDTO.java`
|
||||
- **作用**: 参赛人员数据结构
|
||||
- **字段**:
|
||||
- `id`: 参赛人员ID
|
||||
- `schoolUnit`: 学校/单位
|
||||
- `status`: 状态(未签到/已签到/异常)
|
||||
- `sortOrder`: 排序
|
||||
|
||||
#### 1.4 SaveScheduleDraftDTO.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/pojo/dto/SaveScheduleDraftDTO.java`
|
||||
- **作用**: 保存编排草稿的请求数据结构
|
||||
- **字段**:
|
||||
- `competitionId`: 赛事ID
|
||||
- `isDraft`: 是否为草稿
|
||||
- `competitionGroups`: 竞赛分组数据
|
||||
|
||||
### 2. 实体类修改
|
||||
|
||||
#### 2.1 MartialScheduleParticipant.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/pojo/entity/MartialScheduleParticipant.java`
|
||||
- **修改内容**: 添加了两个新字段
|
||||
- `status`: 参赛人员状态(未签到/已签到/异常)
|
||||
- `scheduleStatus`: 编排状态(draft/completed)
|
||||
|
||||
### 3. 服务接口
|
||||
|
||||
#### 3.1 IMartialScheduleService.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/service/IMartialScheduleService.java`
|
||||
- **新增方法**:
|
||||
- `getScheduleResult(Long competitionId)`: 获取赛程编排结果
|
||||
- `saveDraftSchedule(SaveScheduleDraftDTO dto)`: 保存编排草稿
|
||||
- `saveAndLockSchedule(Long competitionId)`: 完成编排并锁定
|
||||
|
||||
### 4. 服务实现
|
||||
|
||||
#### 4.1 MartialScheduleServiceImpl.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/service/impl/MartialScheduleServiceImpl.java`
|
||||
- **新增依赖注入**:
|
||||
- `MartialScheduleGroupMapper`: 分组数据访问
|
||||
- `MartialScheduleDetailMapper`: 编排明细数据访问
|
||||
- `MartialScheduleParticipantMapper`: 参赛者数据访问
|
||||
|
||||
- **实现的方法**:
|
||||
|
||||
##### 4.1.1 getScheduleResult(Long competitionId)
|
||||
**功能**: 查询并返回赛事的编排结果
|
||||
|
||||
**实现逻辑**:
|
||||
1. 查询所有竞赛分组(按display_order排序)
|
||||
2. 查询所有编排明细
|
||||
3. 查询所有参赛者(按performance_order排序)
|
||||
4. 根据scheduleStatus判断是否已完成编排
|
||||
5. 组装DTO数据返回
|
||||
|
||||
**关键代码**:
|
||||
```java
|
||||
// 检查编排状态
|
||||
boolean isCompleted = participants.stream()
|
||||
.anyMatch(p -> "completed".equals(p.getScheduleStatus()));
|
||||
boolean isDraft = !isCompleted;
|
||||
|
||||
// 设置项目类型
|
||||
switch (group.getProjectType()) {
|
||||
case 1: groupDTO.setType("单人"); break;
|
||||
case 2: groupDTO.setType("集体"); break;
|
||||
default: groupDTO.setType("其他"); break;
|
||||
}
|
||||
```
|
||||
|
||||
##### 4.1.2 saveDraftSchedule(SaveScheduleDraftDTO dto)
|
||||
**功能**: 保存编排草稿数据
|
||||
|
||||
**实现逻辑**:
|
||||
1. 遍历所有竞赛分组
|
||||
2. 更新或创建编排明细(MartialScheduleDetail)
|
||||
3. 更新参赛者的状态和排序
|
||||
4. 将scheduleStatus设置为"draft"
|
||||
5. 使用事务确保数据一致性
|
||||
|
||||
**关键代码**:
|
||||
```java
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveDraftSchedule(SaveScheduleDraftDTO dto) {
|
||||
// 更新编排明细
|
||||
detail.setVenueId(groupDTO.getVenueId());
|
||||
detail.setVenueName(groupDTO.getVenueName());
|
||||
detail.setTimeSlot(groupDTO.getTimeSlot());
|
||||
|
||||
// 更新参赛者信息
|
||||
participant.setStatus(participantDTO.getStatus());
|
||||
participant.setPerformanceOrder(participantDTO.getSortOrder());
|
||||
participant.setScheduleStatus("draft");
|
||||
}
|
||||
```
|
||||
|
||||
##### 4.1.3 saveAndLockSchedule(Long competitionId)
|
||||
**功能**: 完成编排并锁定,不允许再次编辑
|
||||
|
||||
**实现逻辑**:
|
||||
1. 查询赛事的所有分组
|
||||
2. 查询所有参赛者
|
||||
3. 将所有参赛者的scheduleStatus更新为"completed"
|
||||
4. 使用事务确保数据一致性
|
||||
|
||||
**关键代码**:
|
||||
```java
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveAndLockSchedule(Long competitionId) {
|
||||
for (MartialScheduleParticipant participant : participants) {
|
||||
participant.setScheduleStatus("completed");
|
||||
scheduleParticipantMapper.updateById(participant);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 控制器
|
||||
|
||||
#### 5.1 MartialScheduleController.java
|
||||
- **路径**: `martial-master/src/main/java/org/springblade/modules/martial/controller/MartialScheduleController.java`
|
||||
- **新增端点**:
|
||||
|
||||
##### 5.1.1 GET /martial/schedule/result
|
||||
**功能**: 获取赛程编排结果
|
||||
|
||||
**请求参数**:
|
||||
- `competitionId` (Long): 赛事ID
|
||||
|
||||
**响应示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"isDraft": true,
|
||||
"isCompleted": false,
|
||||
"competitionGroups": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### 5.1.2 POST /martial/schedule/save-draft
|
||||
**功能**: 保存编排草稿
|
||||
|
||||
**请求体**: SaveScheduleDraftDTO
|
||||
|
||||
**响应示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "草稿保存成功"
|
||||
}
|
||||
```
|
||||
|
||||
##### 5.1.3 POST /martial/schedule/save-and-lock
|
||||
**功能**: 完成编排并锁定
|
||||
|
||||
**请求体**: 包含competitionId的SaveScheduleDraftDTO
|
||||
|
||||
**响应示例**:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "编排已完成并锁定"
|
||||
}
|
||||
```
|
||||
|
||||
## 数据库设计说明
|
||||
|
||||
### 涉及的表
|
||||
|
||||
1. **martial_schedule_group** (赛程编排分组)
|
||||
- 存储竞赛分组信息
|
||||
- 字段: competition_id, group_name, project_type, display_order等
|
||||
|
||||
2. **martial_schedule_detail** (赛程编排明细)
|
||||
- 存储场地和时间段分配信息
|
||||
- 字段: schedule_group_id, venue_id, venue_name, schedule_date, time_slot等
|
||||
|
||||
3. **martial_schedule_participant** (赛程编排参赛者关联)
|
||||
- 存储参赛者信息
|
||||
- **新增字段**:
|
||||
- `status`: VARCHAR - 参赛人员状态(未签到/已签到/异常)
|
||||
- `schedule_status`: VARCHAR - 编排状态(draft/completed)
|
||||
|
||||
### 数据库迁移建议
|
||||
|
||||
需要在 `martial_schedule_participant` 表中添加以下字段:
|
||||
|
||||
```sql
|
||||
ALTER TABLE martial_schedule_participant
|
||||
ADD COLUMN status VARCHAR(20) DEFAULT '未签到' COMMENT '状态:未签到/已签到/异常',
|
||||
ADD COLUMN schedule_status VARCHAR(20) DEFAULT 'draft' COMMENT '编排状态:draft/completed';
|
||||
```
|
||||
|
||||
## 业务逻辑说明
|
||||
|
||||
### 编排状态管理
|
||||
|
||||
1. **草稿状态** (draft):
|
||||
- 用户可以多次保存和修改
|
||||
- 不影响其他功能
|
||||
- scheduleStatus = "draft"
|
||||
|
||||
2. **完成状态** (completed):
|
||||
- 编排锁定,前端禁用所有编辑功能
|
||||
- 显示"导出"按钮
|
||||
- scheduleStatus = "completed"
|
||||
|
||||
### 首次分配规则
|
||||
|
||||
根据API规范,后端需要按照"先集体,后个人"的顺序进行第一次场地分配:
|
||||
- 集体项目 (projectType = 2) 优先分配
|
||||
- 个人项目 (projectType = 1) 后分配
|
||||
- 使用 display_order 字段控制顺序
|
||||
|
||||
### 状态字段说明
|
||||
|
||||
参赛人员状态 (status):
|
||||
- **未签到**: 默认状态
|
||||
- **已签到**: 参赛人员已签到
|
||||
- **异常**: 被标记为异常的参赛人员
|
||||
|
||||
## 前后端对接说明
|
||||
|
||||
### API路径映射
|
||||
|
||||
前端API配置 (`src/api/martial/activitySchedule.js`):
|
||||
```javascript
|
||||
// 获取赛程编排结果
|
||||
GET /api/martial/schedule/result
|
||||
|
||||
// 保存编排草稿
|
||||
POST /api/martial/schedule/save-draft
|
||||
|
||||
// 完成编排并锁定
|
||||
POST /api/martial/schedule/save-and-lock
|
||||
```
|
||||
|
||||
后端Controller路径 (`MartialScheduleController.java`):
|
||||
```java
|
||||
@RequestMapping("/martial/schedule")
|
||||
|
||||
@GetMapping("/result")
|
||||
@PostMapping("/save-draft")
|
||||
@PostMapping("/save-and-lock")
|
||||
```
|
||||
|
||||
### 数据格式兼容性
|
||||
|
||||
- 后端使用驼峰命名 (camelCase)
|
||||
- 前端已做兼容处理,同时支持驼峰和下划线命名
|
||||
- DTO中的字段名与前端API规范完全一致
|
||||
|
||||
## 测试建议
|
||||
|
||||
### 单元测试
|
||||
|
||||
1. 测试getScheduleResult方法:
|
||||
- 测试空数据情况
|
||||
- 测试草稿状态
|
||||
- 测试完成状态
|
||||
- 测试数据组装正确性
|
||||
|
||||
2. 测试saveDraftSchedule方法:
|
||||
- 测试新建编排明细
|
||||
- 测试更新编排明细
|
||||
- 测试参赛者状态更新
|
||||
- 测试事务回滚
|
||||
|
||||
3. 测试saveAndLockSchedule方法:
|
||||
- 测试状态更新
|
||||
- 测试锁定后的查询结果
|
||||
|
||||
### 集成测试
|
||||
|
||||
1. 测试完整的编排流程:
|
||||
- 首次获取编排结果
|
||||
- 多次保存草稿
|
||||
- 完成编排并锁定
|
||||
- 再次查询验证状态
|
||||
|
||||
2. 测试异常场景:
|
||||
- 赛事不存在
|
||||
- 分组不存在
|
||||
- 参赛者不存在
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **性能优化**:
|
||||
- 对于大量参赛者的情况,考虑使用批量更新
|
||||
- 添加缓存机制减少数据库查询
|
||||
|
||||
2. **功能增强**:
|
||||
- 添加编排历史记录
|
||||
- 实现编排版本管理
|
||||
- 添加编排冲突检测
|
||||
|
||||
3. **安全性**:
|
||||
- 添加权限验证
|
||||
- 添加操作日志
|
||||
- 实现并发控制
|
||||
|
||||
## 总结
|
||||
|
||||
本次实现完全按照前端API规范进行开发,实现了:
|
||||
- ✅ 3个核心API接口
|
||||
- ✅ 4个DTO类
|
||||
- ✅ 实体类字段扩展
|
||||
- ✅ 完整的服务层逻辑
|
||||
- ✅ 事务管理
|
||||
- ✅ Swagger文档注解
|
||||
|
||||
所有代码遵循项目现有的代码风格和架构规范,可以直接集成到现有系统中使用。
|
||||
Reference in New Issue
Block a user