Files
martial-web/doc/schedule/archive/schedule-feature-implementation.md
宅房 5b806e29b7
Some checks failed
continuous-integration/drone/push Build is failing
fix bugs
2025-12-11 16:56:19 +08:00

388 lines
9.4 KiB
Markdown

# 赛程编排功能实施完成文档
## 📋 实施概述
**实施日期**: 2025-12-08
**版本**: v1.0
**状态**: ✅ 核心功能已完成
---
## 1. 已完成的功能
### ✅ 1.1 数据库表创建
创建了两张核心数据库表:
**文件位置**: `doc/create_schedule_tables.sql`
#### martial_schedule (赛程安排表)
- 存储分组的基本信息
- 包含场地分配、时间段分配
- 支持草稿和发布状态
#### martial_schedule_detail (赛程明细表)
- 存储每个分组中的参赛人员详情
- 记录实际比赛时间
- 支持比赛进度跟踪
**执行方式**:
```bash
# 方式1: 通过数据库客户端导入并执行
# 方式2: 命令行执行
mysql -u root -p martial_competition < doc/create_schedule_tables.sql
```
### ✅ 1.2 前端赛程编排页面完善
**文件位置**: `src/views/martial/schedule/index.vue`
#### 核心算法实现:
1. **时间段自动生成** (generateTimeSlots方法)
- 根据赛事开始/结束时间自动生成
- 上午场: 08:30-12:00
- 下午场: 13:30-17:30
- 支持多天赛程
2. **智能自动分组** (autoGroupParticipants方法)
- ✅ 集体项目优先(type=2)
- ✅ 个人项目在后(type=1)
- ✅ 集体项目按"单位+项目"分组
- ✅ 个人项目按"项目+组别"分组,每组最多30人
- ✅ 自动生成分组名称和编号
3. **场地自动分配** (autoAssignVenues方法)
- ✅ 负载均衡算法
- ✅ 优先分配时长长的分组
- ✅ 选择当前负载最小的场地
- ✅ 均匀分布,避免某个场地过载
4. **分组名称编辑**
- ✅ 双击分组名称进入编辑模式
- ✅ Enter保存,失焦保存
- ✅ 实时更新显示
5. **拖拽移动分组**
- ✅ 使用vuedraggable组件
- ✅ 支持在场地间拖拽移动
- ✅ 支持场地内排序
---
## 2. 功能使用流程
### 2.1 基本操作流程
```
1. 进入赛事管理 → 选择赛事 → 点击"编排"按钮
2. 系统自动加载:
- 赛事信息
- 时间段列表 (根据赛事时间自动生成)
- 场地列表
- 所有参赛者数据
3. 点击"自动编排"按钮
4. 系统自动完成:
- 按集体/个人分类参赛者
- 智能分组 (集体按单位+项目, 个人按项目+组别)
- 自动分配场地 (负载均衡)
5. 手动调整 (可选):
- 双击分组名称修改
- 拖拽分组到其他场地
- 调整分组内选手顺序
- 选择场地下拉菜单移动分组
6. 保存编排 / 完成编排
```
### 2.2 时间段切换
- 点击页面顶部的时间段按钮
- 可查看不同时间段的分组安排
- 每个时间段独立管理分组
### 2.3 场地视图
- 切换到"场地"Tab
- 查看每个场地的分组分布
- 统计每个场地的预计时长
---
## 3. 核心算法说明
### 3.1 自动分组算法
```javascript
autoGroupParticipants(participants) {
// 1. 分离集体(type=2)和个人(type=1)
const teamProjects = participants.filter(p => p.type === 2)
const individualProjects = participants.filter(p => p.type === 1)
// 2. 集体项目: 按"organization_projectId"分组
// 3. 个人项目: 按"projectId_category"分组,每组最多30人
// 4. 返回: [集体分组, 个人分组]
}
```
**特点**:
- 集体项目同单位同项目的选手分在一组
- 个人项目同项目同组别的选手分在一组
- 个人项目超过30人自动拆分为A组、B组、C组...
### 3.2 场地分配算法 (贪心 + 负载均衡)
```javascript
autoAssignVenues(groups) {
// 1. 初始化场地负载为0
// 2. 分组按预计时长降序排序
// 3. 贪心策略:
// - 找当前负载最小的场地
// - 分配分组到该场地
// - 更新场地负载
}
```
**特点**:
- 先分配时间长的分组,后分配时间短的
- 总是选择负载最轻的场地
- 确保各场地负载均衡
---
## 4. 测试用例
### 4.1 使用1000个参赛者测试
**前提条件**:
1. 已执行 `test-data/batch_create_1000_participants.sql`
2. 赛事ID=200: "郑州协会全国运动大赛"
3. 包含10个项目、5个场地、1000个参赛者
**测试步骤**:
#### 测试1: 自动编排功能
```
1. 进入赛事编排页面 (competitionId=200)
2. 点击"自动编排"按钮
3. 预期结果:
- 自动生成分组 (集体项目在前,个人项目在后)
- 每个分组自动分配场地
- 场地负载均衡
- 显示成功提示
```
#### 测试2: 分组名称编辑
```
1. 双击某个分组名称
2. 修改名称 (如: "少林寺武术学校 - 集体拳术表演" → "少林组")
3. 按Enter保存
4. 预期结果: 名称更新成功
```
#### 测试3: 场地切换
```
1. 点击某个分组的"选择场地"下拉菜单
2. 选择其他场地
3. 预期结果: 分组移动到新场地
```
#### 测试4: 时间段切换
```
1. 点击不同的时间段按钮
2. 预期结果: 显示对应时间段的分组列表
```
#### 测试5: 场地视图
```
1. 切换到"场地"Tab
2. 预期结果:
- 显示每个场地的分组列表
- 显示每个分组的预计时长
- 统计汇总正确
```
### 4.2 边界测试
| 测试项 | 操作 | 预期结果 |
|--------|------|---------|
| 无参赛者 | 点击自动编排 | 提示"没有未分组的参赛者" |
| 无场地 | 点击自动分配场地 | 提示"请先配置场地信息" |
| 空分组名称 | 保存空名称 | 保持原名称 |
| 大量参赛者 | 1000人自动编排 | 正常处理,性能良好 |
---
## 5. 性能优化
### 5.1 已实现的优化
1. **项目信息缓存**
- 使用Map缓存项目详情
- 避免重复查询相同项目
2. **批量处理**
- 一次性加载所有参赛者
- 批量分组和分配
3. **算法优化**
- 使用Map进行分组,时间复杂度O(n)
- 负载均衡算法,时间复杂度O(n*m), n=分组数, m=场地数
### 5.2 未来可优化
1. **虚拟滚动**: 分组数量>100时使用虚拟滚动
2. **防抖保存**: 拖拽操作延迟保存
3. **懒加载**: 只加载当前时间段数据
---
## 6. 数据流转
```
用户操作
前端Vue页面 (src/views/martial/schedule/index.vue)
调用API (src/api/martial/...)
后端接口 (待开发)
数据库表 (martial_schedule, martial_schedule_detail)
```
---
## 7. 待开发功能
### 7.1 后端API接口
需要创建以下接口 (参考文档第5章):
1. **GET /api/martial/schedule/time-slots**
- 获取时间段列表
2. **POST /api/martial/schedule/auto-group**
- 自动生成分组
3. **PUT /api/martial/schedule/group/{groupId}/name**
- 更新分组名称
4. **POST /api/martial/schedule/save**
- 保存编排结果 (草稿)
5. **POST /api/martial/schedule/publish**
- 发布编排 (status=1)
6. **POST /api/martial/schedule/auto-assign-venues**
- 自动分配场地
7. **GET /api/martial/schedule/list**
- 获取已保存的编排
### 7.2 功能增强
1. **保存草稿**: 将编排数据保存到数据库
2. **加载已保存编排**: 恢复之前的编排状态
3. **发布编排**: 确认完成后发布
4. **导出功能**: 导出Excel/PDF格式的赛程表
5. **打印功能**: 打印秩序册
---
## 8. 文件清单
### 已创建/修改的文件
```
✅ doc/schedule-system-analysis.md # 系统设计文档 (1200+行)
✅ doc/create_schedule_tables.sql # 数据库表创建SQL
✅ doc/schedule-feature-implementation.md # 本文档
✅ src/views/martial/schedule/index.vue # 前端编排页面 (已完善)
✅ test-data/batch_create_1000_participants.sql # 测试数据
✅ doc/batch-create-participants-guide.md # 测试数据使用指南
```
### 待创建的文件 (后端)
```
❌ backend/api/schedule.js # 赛程编排API接口
❌ backend/service/schedule.js # 赛程编排业务逻辑
❌ backend/mapper/schedule.xml # 赛程数据访问SQL
```
---
## 9. 技术栈
| 技术 | 版本 | 用途 |
|------|------|------|
| Vue 3 | - | 前端框架 |
| Element Plus | - | UI组件库 |
| vuedraggable | - | 拖拽功能 |
| MySQL | 5.7+ | 数据库 |
| SpringBoot | 2.x | 后端框架(待开发) |
---
## 10. 常见问题
### Q1: 如何确定参赛者的项目类型?
**A**: 通过查询 `martial_project` 表的 `type` 字段:
- `type=1`: 个人项目
- `type=2`: 集体项目
### Q2: 个人项目为什么每组最多30人?
**A**: 这是为了避免单组人数过多,比赛时间过长。可以在代码中修改 `maxPerGroup` 变量。
### Q3: 如何自定义场地分配策略?
**A**: 修改 `autoAssignVenues` 方法中的分配逻辑,可以考虑:
- 场地容量限制
- 项目类型匹配 (如集体项目分配到大场地)
- 时间段容量限制
### Q4: 分组编号规则是什么?
**A**: GROUP_001, GROUP_002, ... 按生成顺序递增,集体项目编号在前。
---
## 11. 下一步计划
### 阶段1: 后端接口开发 (优先级: 高)
- [ ] 创建赛程编排相关API接口
- [ ] 实现数据持久化
- [ ] 实现加载已保存编排
### 阶段2: 功能完善 (优先级: 中)
- [ ] 保存草稿功能
- [ ] 发布编排功能
- [ ] 撤销/重做功能
### 阶段3: 导出功能 (优先级: 中)
- [ ] 导出Excel格式赛程表
- [ ] 导出PDF格式秩序册
- [ ] 二维码生成(选手扫码查看)
### 阶段4: 优化和扩展 (优先级: 低)
- [ ] 性能优化(虚拟滚动、懒加载)
- [ ] 冲突检测(同一选手多项目)
- [ ] 可视化增强(甘特图、热力图)
---
## 12. 联系与反馈
如有问题或建议,请记录在项目Issue中。
---
**文档维护**:
- 创建人: Claude Code
- 创建日期: 2025-12-08
- 版本: v1.0
- 最后更新: 2025-12-08