# 赛程编排功能实施完成文档 ## 📋 实施概述 **实施日期**: 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