本人使用Claude Code制作了一个羽毛球轮转系统。然后让Claude Code生成了一个系统架构文档。文档内容如下:
羽毛球轮转管理系统 - 系统架构文档
一、项目概述
1.1 项目简介
羽毛球轮转管理系统是一个基于纯前端技术实现的单页应用(SPA),用于羽毛球活动的组织、轮转管理和比赛统计。系统支持从人员录入、分组管理、轮转生成到比赛进行和报表统计的完整流程。
1.2 技术栈
- 前端框架:原生 HTML5 + CSS3 + JavaScript(无依赖库)
- 数据存储:LocalStorage(客户端持久化存储)
- 架构模式:单页应用(SPA) + MVC 模式
- 分享机制:URL Hash + Base64 编码
二、整体架构设计
2.1 架构层次
- ┌─────────────────────────────────────────────────────────────┐
- │ 用户界面层(View) │
- │ ├─ 页面模块(6个主要页面) │
- │ ├─ 响应式布局(桌面/移动端) │
- │ ├─ 组件化UI(卡片、表单、表格、按钮等) │
- └─────────────────────────────────────────────────────────────┘
- ↓
- ┌─────────────────────────────────────────────────────────────┐
- │ 控制层(Controller) │
- │ ├─ 页面导航管理 │
- │ ├─ 事件处理与验证 │
- │ ├─ 业务逻辑协调 │
- └─────────────────────────────────────────────────────────────┘
- ↓
- ┌─────────────────────────────────────────────────────────────┐
- │ 数据层(Model) │
- │ ├─ 核心数据对象(people, groups, config, schedule) │
- │ ├─ LocalStorage 存储 │
- │ └─ 数据迁移与版本管理 │
- └─────────────────────────────────────────────────────────────┘
复制代码 2.2 核心数据结构
- data = {
- people: [ // 人员列表
- { id, name, gender, level, isFreeAgent }
- ],
- groups: [ // 圈子(分组)列表
- { id, name, memberIds[] }
- ],
- config: { // 配置参数
- courtCount, // 场地数量
- matchDuration, // 每场比赛时长(分钟)
- totalDuration, // 总时长(分钟)
- totalRounds, // 总轮次
- allowIntraGroup, // 允许同圈子比赛
- maximizeCross, // 最大化跨圈子比赛
- balancePlayTime // 均衡上场次数
- },
- schedule: [ // 轮转表
- {
- round, // 轮次
- courts: [
- { team1, team2, score1, score2, confirmed }
- ]
- }
- ],
- rankings: [ // 排名数据(动态计算)
- { personId, gamesWon, gamesLost, netScore, netGames }
- ],
- playCount: {}, // 每人上场次数统计
- partnerCount: {} // 搭档次数统计
- }
复制代码 三、功能模块详解
3.1 页面导航系统
6个主要页面:
页面ID页面名称功能描述people人员管理添加、编辑、删除人员,支持批量导入groups分组管理创建圈子,分配人员到圈子config配置设置场地、时间配置,轮转策略schedule轮转预览预览生成的轮转表,确认后进入比赛play比赛进行实时录入比分,确认每场比赛report报表统计查看最终排名、搭档统计、对阵历史导航机制:
- 页面切换通过 nextPage(pageName) 函数实现
- 支持前进验证(validatePage),确保数据完整性
- 自动生成桌面端和移动端导航栏
- 页面状态通过 CSS class .active 控制显示/隐藏
3.2 人员管理模块
主要功能:
- ✅ 添加单个人员(姓名、性别、水平等级、自由人标志)
- ✅ 批量导入(CSV格式:姓名,性别,等级)
- ✅ 编辑人员信息(弹窗编辑)
- ✅ 删除人员(级联删除)
- ✅ 自由人标记(可与其他任何人在同一圈子)
- ✅ 排序功能(按性别、等级排序)
- ✅ 重复检查(姓名+性别必须唯一)
水平等级系统:L0.5 ~ L6(共12个等级,递增)
数据验证:
- 姓名必填
- 性别必须为"男"或"女"
- 等级必须在预设列表中
3.3 分组管理模块
核心概念:
- 圈子:人员分组,用于约束合法的搭档组合
- 自由人:标记为自由人的人员可以与任何其他人员搭档,不受圈子限制
- 分配规则:非自由人必须被分配到至少一个圈子
主要功能:
- ✅ 创建圈子(名称唯一性校验)
- ✅ 删除圈子
- ✅ 展开/折叠圈子查看成员
- ✅ 从圈子中移除成员
- ✅ 批量分配未分配人员到指定圈子
- ✅ 可视化显示未分配人员列表
分配流程:
- 左侧显示未分配人员(可多选)
- 中间选择目标圈子(下拉框)
- 点击"加入选中圈子"完成分配
3.4 配置设置模块
场地与时间配置:
- 场地数量:1-10个
- 每场比赛时长:5-60分钟
- 总时长:30-600分钟
- 自动计算轮次:轮次 = floor(总时长 / 比赛时长) / 场地数量(向上取整)
轮转策略(3个核心策略):
策略说明影响allowIntraGroup允许同圈子比赛无法跨圈时的fallback方案maximizeCross最大化跨圈子比赛优先安排不同圈子的人员对垒balancePlayTime均衡每个人上场次数避免有人长时间轮空3.5 轮转生成算法(核心)
算法类型:贪心启发式算法 + 多目标优化
算法流程:- 1. 预处理阶段:
- - 构建 personToGroups 映射(人员→圈子)
- - 识别自由人列表
- - 生成所有合法搭档对(validPairs)
- 2. 逐轮生成(for round = 1 to totalRounds):
- - 初始化 usedThisRound(已使用人员集合)
- - 对每个场地:
- a. 从可用搭档对中筛选(双方都未使用)
- b. 尝试组合两对(4人互不相同)
- c. 计算综合得分:
- - crossScore:跨圈分数(0/5/10)
- - balanceScore:平衡惩罚(基于历史出场次数)
- - diversityPenalty:搭档多样性惩罚
- totalScore = crossScore*10 + balanceScore - diversityPenalty
- d. 选择最高分的组合
- e. 更新 playCount 和 partnerCount
- f. 标记4人为已使用
- 3. 输出 schedule 和统计信息
复制代码 合法搭档判定:
- 任意一方是自由人 ✅
- 双方有共同圈子 ✅
- 否则 ❌
评分函数详解:- crossScore:
- 完全跨圈(无共同圈子) → 10分
- 部分重叠(有自由人) → 5分
- 完全同圈 → 0分
- balanceScore:
- avgPlayCount = 当前总出场次数平均值
- totalPlayCount = 这4人的总出场次数
- balanceScore = (avgPlayCount * 4 - totalPlayCount) * 2
- // 低于平均时得正分,高于平均时得负分
- diversityPenalty:
- = (搭档历史次数 + 另一对的搭档历史次数) * 1
- // 鼓励与不同人搭档
复制代码 算法复杂度:
- 配对生成:O(n²),n为人数
- 每轮每场地:O(m²),m为合法搭档对数(限制为50对)
- 总体:O(rounds × courts × 50²)
3.6 比赛进行模块
界面布局:
- 顶部显示总轮次
- 所有轮次/场地卡片化展示
- 每个场地卡片包含:
- 场地编号和状态(已确定/待录入)
- 两队人员列表
- 两队得分输入框
- 快速填入按钮(10、16、21分)
- 确定按钮(比赛完成后点击)
工作流程:
- 录入比分(两队都输入后,确定按钮才可用)
- 点击确定 → 验证比分有效性(21分制规则或30:29)
- 确认后该场比赛锁定(不能再修改,除非点击"修改"按钮)
- 实时更新积分排名
比分验证规则:- isGameOver = (maxScore >= 21 && diff >= 2) || (maxScore === 30 && minScore === 29)
复制代码 3.7 报表统计模块
3.7.1 最终排名
- 排名规则(优先级从高到低):
- 胜场数(gamesWon)↓
- 负场数(gamesLost)↑(越少越好)
- 总净胜分(netScore)↓
- 并列排名处理:三项指标完全相同则并列
3.7.2 搭档统计
- 显示每个人与所有搭档的组合次数
- 按搭档次数降序排列
- 格式:搭档A(3), 搭档B(2), 搭档C(1)
3.7.3 对阵历史
- 按轮次排序,每轮内按场地排序
- 显示完整比分和胜方标识
3.7.4 分享与导出
- 生成分享链接:将数据序列化为Base64编码到URL Hash
- 复制Markdown报表:格式化为Markdown表格,复制到剪贴板
- 导出JSON数据:下载完整数据备份文件
四、UI/UX设计系统
4.1 设计规范
色彩系统(CSS变量):- --primary: #0EA5E9 /* 主色调:天空蓝 */
- --primary-dark: #0284C7 /* 深色主色调 */
- --secondary: #14B8A6 /* 次要色:青绿 */
- --background: #F8FAFC /* 背景色 */
- --surface: #FFFFFF /* 卡片/表面色 */
- --text: #1E293B /* 主要文字 */
- --text-light: #64748B /* 次要文字 */
- --success: #22C55E /* 成功色 */
- --warning: #F59E0B /* 警告色 */
- --danger: #EF4444 /* 危险色 */
复制代码 间距与圆角:
- 卡片圆角:12px
- 按钮圆角:8px
- 标签圆角:999px(胶囊形)
- 阴影:轻微多层阴影 0 1px 3px rgba(0,0,0,0.1)
字体:
- 系统字体栈:-apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei'
- 移动端强制16px防止iOS缩放
4.2 响应式设计
桌面端(>768px):
- 顶部横向导航栏
- 两栏布局(分组管理页面)
- 表格完整显示
移动端(≤768px):
- 横向滚动导航条
- 单栏堆叠布局
- 按钮最小高度44px(触控友好)
- 表格横向滚动
- 字体和间距优化
五、数据流与状态管理
5.1 数据持久化
存储机制:- STORAGE_KEY = 'badminton_data'
- localStorage.setItem(STORAGE_KEY, JSON.stringify(data))
复制代码 数据加载:
- 页面加载时自动从LocalStorage恢复
- 支持URL分享链接直接加载数据
- 数据迁移(migrateData)确保向后兼容
自动保存策略:
- 每次数据变更立即保存(saveData())
- 页面刷新后自动恢复状态
5.2 状态同步
关键状态同步点:
- 添加/删除/修改人员 → 更新人员表和分组页
- 圈子变更 → 更新分组页和未分配列表
- 比分录入 → 更新实时排名
- 比赛确认 → 锁定比赛,更新排名
六、核心算法深度分析
6.1 轮转生成的优化目标
系统通过加权评分机制实现多目标优化:- 总得分 = crossScore × 10 + balanceScore - diversityPenalty
复制代码 目标优先级:
- 最大化跨圈(权重10):确保不同圈子人员尽可能对战
- 平衡上场(权重2):避免某些人上场过多/过少
- 搭档多样性(权重1):避免同一对人反复搭档
6.2 贪心算法的局限性
当前实现的问题:
- ❌ 每轮独立决策,缺乏全局规划
- ❌ 可能在某些轮次出现配对困难(场地空闲)
- ❌ 仅考虑当前场地的局部最优,未考虑整体公平性
可改进方向:
- ✅ 引入回溯机制,当当前轮次无解时重新分配
- ✅ 使用模拟退火或遗传算法进行全局优化
- ✅ 增加约束条件:性别平衡、水平平衡等
七、系统扩展建议
7.1 功能增强
短期优化(无需重大重构):
- 导入导出增强:
- 支持Excel/CSV批量导入人员
- 导出PDF报表
- 导出图片格式的轮转表
- 规则扩展:
- 支持混双规则(男女混合)
- 支持水平平衡约束(每队水平总和接近)
- 支持性别平衡约束(每队男女比例)
- 交互优化:
- 拖拽分配人员到圈子
- 比赛进行时自动跳转到下一个未确认比赛
- 键盘快捷键支持(如Enter快速添加)
中期重构(需要模块化):
- 后端集成:
- 实时协作:
- 智能调度:
- 多种调度算法可选(贪心、匈牙利、模拟退火)
- 算法可视化展示决策过程
- A/B测试不同算法效果
7.2 代码质量提升
当前问题:
- 单文件2522行,难以维护
- 函数过长,缺乏模块化
- 硬编码的配置值(如maxPairs=50)
- 缺少单元测试
重构建议:- badminton-system/
- ├── src/
- │ ├── models/ # 数据模型
- │ ├── views/ # 页面视图
- │ ├── controllers/ # 控制器
- │ ├── services/ # 业务服务(轮转算法、排名计算)
- │ ├── utils/ # 工具函数
- │ └── styles/ # CSS模块
- ├── tests/
- └── index.html
复制代码 八、使用场景与流程
8.1 典型使用流程
- 1. 人员管理
- └─> 添加所有参与者(或批量导入)
- └─> 标记自由人(如教练、替补)
- 2. 分组管理
- └─> 创建圈子(如:A组、B组、俱乐部1、俱乐部2)
- └─> 将人员分配到对应圈子
- └─> 确保所有非自由人已分配
- 3. 配置设置
- └─> 设置场地数量、时长、总时长
- └─> 选择轮转策略(建议全选)
- └─> 查看自动计算的轮次
- 4. 生成轮转
- └─> 点击"生成轮转表"
- └─> 算法自动计算所有轮次的配对
- └─> 预览并确认
- 5. 比赛进行
- └─> 逐场录入比分
- └─> 确认比赛结果(锁定)
- └─> 实时查看积分排名
- 6. 报表统计
- └─> 查看最终排名、搭档统计、对阵历史
- └─> 生成分享链接或导出数据
复制代码 8.2 适用场景
- ✅ 业余羽毛球活动组织(4-40人)
- ✅ 俱乐部内部循环赛
- ✅ 训练课的轮转练习
- ✅ 双打配对优化
不适用场景:
- ❌ 单打比赛(系统为双打设计)
- ❌ 淘汰赛制(仅支持循环赛)
- ❌ 超过40人的大型赛事(算法复杂度较高)
九、关键技术实现
9.1 分享链接原理
- // 编码
- const shareData = { people, groups, config, schedule, rankings }
- const jsonStr = JSON.stringify(shareData)
- const encoded = btoa(unescape(encodeURIComponent(jsonStr))) // UTF-8 + Base64
- const url = window.location.origin + window.location.pathname + '#/share/' + encoded
- // 解码
- const hash = window.location.hash
- const encoded = hash.replace('#/share/', '')
- const decoded = JSON.parse(atob(encoded))
复制代码 优点:无服务器支持即可分享完整数据
缺点:URL可能过长(超过2000字符限制)
9.2 本地存储策略
- 键名:badminton_data
- 存储内容:完整数据对象
- 容量:约几KB到几十KB(取决于人数和轮次)
- 生命周期:永久存储,除非用户清除浏览器数据
9.3 数据迁移机制
- function migrateData() {
- // 版本升级时确保数据结构兼容
- if (data.schedule) {
- data.schedule.forEach(round => {
- round.courts.forEach(court => {
- if (court.confirmed === undefined) {
- court.confirmed = false;
- }
- });
- });
- }
- }
复制代码 十、总结与评价
10.1 系统优点
- 零依赖:无需安装任何库,打开即用
- 数据安全:完全本地存储,隐私无忧
- 响应式设计:完美支持手机和电脑
- 算法实用:贪心算法速度快,适合中小规模活动
- 功能完整:覆盖活动组织全流程
10.2 局限性与改进方向
- 算法局限性:
- 贪心算法可能陷入局部最优
- 无解时无fallback机制(直接停止生成)
- 扩展性不足:
- 单文件架构难以维护
- 规则硬编码,不支持自定义排名规则
- 缺少插件机制
- 用户体验:
- 缺少撤销/重做功能
- 轮转表生成时UI阻塞(虽用setTimeout但仍有卡顿)
- 无数据导入导出格式验证
10.3 适用度评分
维度评分说明易用性⭐⭐⭐⭐⭐界面简洁,操作直观性能⭐⭐⭐⭐50人以下流畅,100人以上开始卡顿稳定性⭐⭐⭐⭐⭐纯前端无服务器故障风险扩展性⭐⭐单文件架构难以扩展算法质量⭐⭐⭐满足基本需求,但非最优解附录
附录A:数据格式参考
- {
- "people": [
- { "id": 1, "name": "张三", "gender": "男", "level": "L2", "isFreeAgent": false }
- ],
- "groups": [
- { "id": "group_123", "name": "A组", "memberIds": [1, 2, 3] }
- ],
- "schedule": [
- {
- "round": 1,
- "courts": [
- { "team1": [1, 2], "team2": [3, 4], "score1": 21, "score2": 18, "confirmed": true }
- ]
- }
- ]
- }
复制代码 附录B:快速开始
- 在浏览器中打开 badminton.html
- 按页面顺序逐步操作
- 数据自动保存,关闭后重新打开即可恢复
附录C:浏览器兼容性
- ✅ Chrome 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Edge 90+
- ⚠️ 需要支持 ES6、localStorage、Clipboard API
文档生成时间:2026-03-24
代码行数:2522行
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |