找回密码
 立即注册
首页 业界区 安全 搭建产品原型

搭建产品原型

幌斛者 4 小时前
本人使用Claude Code制作了一个羽毛球轮转系统。然后让Claude Code生成了一个系统架构文档。文档内容如下:
羽毛球轮转管理系统 - 系统架构文档

一、项目概述

1.1 项目简介

羽毛球轮转管理系统是一个基于纯前端技术实现的单页应用(SPA),用于羽毛球活动的组织、轮转管理和比赛统计。系统支持从人员录入、分组管理、轮转生成到比赛进行和报表统计的完整流程。
1.2 技术栈


  • 前端框架:原生 HTML5 + CSS3 + JavaScript(无依赖库)
  • 数据存储:LocalStorage(客户端持久化存储)
  • 架构模式:单页应用(SPA) + MVC 模式
  • 分享机制:URL Hash + Base64 编码
二、整体架构设计

2.1 架构层次
  1. ┌─────────────────────────────────────────────────────────────┐
  2. │                     用户界面层(View)                       │
  3. │  ├─ 页面模块(6个主要页面)                                    │
  4. │  ├─ 响应式布局(桌面/移动端)                                  │
  5. │  ├─ 组件化UI(卡片、表单、表格、按钮等)                       │
  6. └─────────────────────────────────────────────────────────────┘
  7.                             ↓
  8. ┌─────────────────────────────────────────────────────────────┐
  9. │                   控制层(Controller)                        │
  10. │  ├─ 页面导航管理                                              │
  11. │  ├─ 事件处理与验证                                            │
  12. │  ├─ 业务逻辑协调                                              │
  13. └─────────────────────────────────────────────────────────────┘
  14.                             ↓
  15. ┌─────────────────────────────────────────────────────────────┐
  16. │                    数据层(Model)                            │
  17. │  ├─ 核心数据对象(people, groups, config, schedule)         │
  18. │  ├─ LocalStorage 存储                                       │
  19. │  └─ 数据迁移与版本管理                                        │
  20. └─────────────────────────────────────────────────────────────┘
复制代码
2.2 核心数据结构
  1. data = {
  2.     people: [                      // 人员列表
  3.         { id, name, gender, level, isFreeAgent }
  4.     ],
  5.     groups: [                      // 圈子(分组)列表
  6.         { id, name, memberIds[] }
  7.     ],
  8.     config: {                      // 配置参数
  9.         courtCount,                // 场地数量
  10.         matchDuration,             // 每场比赛时长(分钟)
  11.         totalDuration,             // 总时长(分钟)
  12.         totalRounds,               // 总轮次
  13.         allowIntraGroup,           // 允许同圈子比赛
  14.         maximizeCross,             // 最大化跨圈子比赛
  15.         balancePlayTime            // 均衡上场次数
  16.     },
  17.     schedule: [                    // 轮转表
  18.         {
  19.             round,                  // 轮次
  20.             courts: [
  21.                 { team1, team2, score1, score2, confirmed }
  22.             ]
  23.         }
  24.     ],
  25.     rankings: [                    // 排名数据(动态计算)
  26.         { personId, gamesWon, gamesLost, netScore, netGames }
  27.     ],
  28.     playCount: {},                 // 每人上场次数统计
  29.     partnerCount: {}               // 搭档次数统计
  30. }
复制代码
三、功能模块详解

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. 1. 预处理阶段:
  2.    - 构建 personToGroups 映射(人员→圈子)
  3.    - 识别自由人列表
  4.    - 生成所有合法搭档对(validPairs)
  5. 2. 逐轮生成(for round = 1 to totalRounds):
  6.    - 初始化 usedThisRound(已使用人员集合)
  7.    - 对每个场地:
  8.      a. 从可用搭档对中筛选(双方都未使用)
  9.      b. 尝试组合两对(4人互不相同)
  10.      c. 计算综合得分:
  11.         - crossScore:跨圈分数(0/5/10)
  12.         - balanceScore:平衡惩罚(基于历史出场次数)
  13.         - diversityPenalty:搭档多样性惩罚
  14.         totalScore = crossScore*10 + balanceScore - diversityPenalty
  15.      d. 选择最高分的组合
  16.      e. 更新 playCount 和 partnerCount
  17.      f. 标记4人为已使用
  18. 3. 输出 schedule 和统计信息
复制代码
合法搭档判定

  • 任意一方是自由人 ✅
  • 双方有共同圈子 ✅
  • 否则 ❌
评分函数详解
  1. crossScore:
  2.   完全跨圈(无共同圈子) → 10分
  3.   部分重叠(有自由人) → 5分
  4.   完全同圈 → 0分
  5. balanceScore:
  6.   avgPlayCount = 当前总出场次数平均值
  7.   totalPlayCount = 这4人的总出场次数
  8.   balanceScore = (avgPlayCount * 4 - totalPlayCount) * 2
  9.   // 低于平均时得正分,高于平均时得负分
  10. diversityPenalty:
  11.   = (搭档历史次数 + 另一对的搭档历史次数) * 1
  12.   // 鼓励与不同人搭档
复制代码
算法复杂度

  • 配对生成:O(n²),n为人数
  • 每轮每场地:O(m²),m为合法搭档对数(限制为50对)
  • 总体:O(rounds × courts × 50²)
3.6 比赛进行模块

界面布局

  • 顶部显示总轮次
  • 所有轮次/场地卡片化展示
  • 每个场地卡片包含:

    • 场地编号和状态(已确定/待录入)
    • 两队人员列表
    • 两队得分输入框
    • 快速填入按钮(10、16、21分)
    • 确定按钮(比赛完成后点击)

工作流程

  • 录入比分(两队都输入后,确定按钮才可用)
  • 点击确定 → 验证比分有效性(21分制规则或30:29)
  • 确认后该场比赛锁定(不能再修改,除非点击"修改"按钮)
  • 实时更新积分排名
比分验证规则
  1. 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
    1. #/share/{base64(data)}
    复制代码
  • 复制Markdown报表:格式化为Markdown表格,复制到剪贴板
  • 导出JSON数据:下载完整数据备份文件
四、UI/UX设计系统

4.1 设计规范

色彩系统(CSS变量):
  1. --primary: #0EA5E9          /* 主色调:天空蓝 */
  2. --primary-dark: #0284C7     /* 深色主色调 */
  3. --secondary: #14B8A6        /* 次要色:青绿 */
  4. --background: #F8FAFC       /* 背景色 */
  5. --surface: #FFFFFF          /* 卡片/表面色 */
  6. --text: #1E293B             /* 主要文字 */
  7. --text-light: #64748B       /* 次要文字 */
  8. --success: #22C55E          /* 成功色 */
  9. --warning: #F59E0B          /* 警告色 */
  10. --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 数据持久化

存储机制
  1. STORAGE_KEY = 'badminton_data'
  2. localStorage.setItem(STORAGE_KEY, JSON.stringify(data))
复制代码
数据加载

  • 页面加载时自动从LocalStorage恢复
  • 支持URL分享链接直接加载数据
  • 数据迁移(migrateData)确保向后兼容
自动保存策略

  • 每次数据变更立即保存(saveData())
  • 页面刷新后自动恢复状态
5.2 状态同步

关键状态同步点

  • 添加/删除/修改人员 → 更新人员表和分组页
  • 圈子变更 → 更新分组页和未分配列表
  • 比分录入 → 更新实时排名
  • 比赛确认 → 锁定比赛,更新排名
六、核心算法深度分析

6.1 轮转生成的优化目标

系统通过加权评分机制实现多目标优化:
  1. 总得分 = crossScore × 10 + balanceScore - diversityPenalty
复制代码
目标优先级

  • 最大化跨圈(权重10):确保不同圈子人员尽可能对战
  • 平衡上场(权重2):避免某些人上场过多/过少
  • 搭档多样性(权重1):避免同一对人反复搭档
6.2 贪心算法的局限性

当前实现的问题

  • ❌ 每轮独立决策,缺乏全局规划
  • ❌ 可能在某些轮次出现配对困难(场地空闲)
  • ❌ 仅考虑当前场地的局部最优,未考虑整体公平性
可改进方向

  • ✅ 引入回溯机制,当当前轮次无解时重新分配
  • ✅ 使用模拟退火或遗传算法进行全局优化
  • ✅ 增加约束条件:性别平衡、水平平衡等
七、系统扩展建议

7.1 功能增强

短期优化(无需重大重构):

  • 导入导出增强

    • 支持Excel/CSV批量导入人员
    • 导出PDF报表
    • 导出图片格式的轮转表

  • 规则扩展

    • 支持混双规则(男女混合)
    • 支持水平平衡约束(每队水平总和接近)
    • 支持性别平衡约束(每队男女比例)

  • 交互优化

    • 拖拽分配人员到圈子
    • 比赛进行时自动跳转到下一个未确认比赛
    • 键盘快捷键支持(如Enter快速添加)

中期重构(需要模块化):

  • 后端集成

    • 保存到云端数据库
    • 多用户协作
    • 历史活动记录

  • 实时协作

    • WebSocket实现多端同步
    • 扫码加入活动

  • 智能调度

    • 多种调度算法可选(贪心、匈牙利、模拟退火)
    • 算法可视化展示决策过程
    • A/B测试不同算法效果

7.2 代码质量提升

当前问题

  • 单文件2522行,难以维护
  • 函数过长,缺乏模块化
  • 硬编码的配置值(如maxPairs=50)
  • 缺少单元测试
重构建议
  1. badminton-system/
  2. ├── src/
  3. │   ├── models/          # 数据模型
  4. │   ├── views/           # 页面视图
  5. │   ├── controllers/     # 控制器
  6. │   ├── services/        # 业务服务(轮转算法、排名计算)
  7. │   ├── utils/           # 工具函数
  8. │   └── styles/          # CSS模块
  9. ├── tests/
  10. └── index.html
复制代码
八、使用场景与流程

8.1 典型使用流程
  1. 1. 人员管理
  2.    └─> 添加所有参与者(或批量导入)
  3.    └─> 标记自由人(如教练、替补)
  4. 2. 分组管理
  5.    └─> 创建圈子(如:A组、B组、俱乐部1、俱乐部2)
  6.    └─> 将人员分配到对应圈子
  7.    └─> 确保所有非自由人已分配
  8. 3. 配置设置
  9.    └─> 设置场地数量、时长、总时长
  10.    └─> 选择轮转策略(建议全选)
  11.    └─> 查看自动计算的轮次
  12. 4. 生成轮转
  13.    └─> 点击"生成轮转表"
  14.    └─> 算法自动计算所有轮次的配对
  15.    └─> 预览并确认
  16. 5. 比赛进行
  17.    └─> 逐场录入比分
  18.    └─> 确认比赛结果(锁定)
  19.    └─> 实时查看积分排名
  20. 6. 报表统计
  21.    └─> 查看最终排名、搭档统计、对阵历史
  22.    └─> 生成分享链接或导出数据
复制代码
8.2 适用场景


  • ✅ 业余羽毛球活动组织(4-40人)
  • ✅ 俱乐部内部循环赛
  • ✅ 训练课的轮转练习
  • ✅ 双打配对优化
不适用场景

  • ❌ 单打比赛(系统为双打设计)
  • ❌ 淘汰赛制(仅支持循环赛)
  • ❌ 超过40人的大型赛事(算法复杂度较高)
九、关键技术实现

9.1 分享链接原理
  1. // 编码
  2. const shareData = { people, groups, config, schedule, rankings }
  3. const jsonStr = JSON.stringify(shareData)
  4. const encoded = btoa(unescape(encodeURIComponent(jsonStr)))  // UTF-8 + Base64
  5. const url = window.location.origin + window.location.pathname + '#/share/' + encoded
  6. // 解码
  7. const hash = window.location.hash
  8. const encoded = hash.replace('#/share/', '')
  9. const decoded = JSON.parse(atob(encoded))
复制代码
优点:无服务器支持即可分享完整数据
缺点:URL可能过长(超过2000字符限制)
9.2 本地存储策略


  • 键名:badminton_data
  • 存储内容:完整数据对象
  • 容量:约几KB到几十KB(取决于人数和轮次)
  • 生命周期:永久存储,除非用户清除浏览器数据
9.3 数据迁移机制
  1. function migrateData() {
  2.     // 版本升级时确保数据结构兼容
  3.     if (data.schedule) {
  4.         data.schedule.forEach(round => {
  5.             round.courts.forEach(court => {
  6.                 if (court.confirmed === undefined) {
  7.                     court.confirmed = false;
  8.                 }
  9.             });
  10.         });
  11.     }
  12. }
复制代码
十、总结与评价

10.1 系统优点


  • 零依赖:无需安装任何库,打开即用
  • 数据安全:完全本地存储,隐私无忧
  • 响应式设计:完美支持手机和电脑
  • 算法实用:贪心算法速度快,适合中小规模活动
  • 功能完整:覆盖活动组织全流程
10.2 局限性与改进方向


  • 算法局限性

    • 贪心算法可能陷入局部最优
    • 无解时无fallback机制(直接停止生成)

  • 扩展性不足

    • 单文件架构难以维护
    • 规则硬编码,不支持自定义排名规则
    • 缺少插件机制

  • 用户体验

    • 缺少撤销/重做功能
    • 轮转表生成时UI阻塞(虽用setTimeout但仍有卡顿)
    • 无数据导入导出格式验证

10.3 适用度评分

维度评分说明易用性⭐⭐⭐⭐⭐界面简洁,操作直观性能⭐⭐⭐⭐50人以下流畅,100人以上开始卡顿稳定性⭐⭐⭐⭐⭐纯前端无服务器故障风险扩展性⭐⭐单文件架构难以扩展算法质量⭐⭐⭐满足基本需求,但非最优解附录

附录A:数据格式参考
  1. {
  2.   "people": [
  3.     { "id": 1, "name": "张三", "gender": "男", "level": "L2", "isFreeAgent": false }
  4.   ],
  5.   "groups": [
  6.     { "id": "group_123", "name": "A组", "memberIds": [1, 2, 3] }
  7.   ],
  8.   "schedule": [
  9.     {
  10.       "round": 1,
  11.       "courts": [
  12.         { "team1": [1, 2], "team2": [3, 4], "score1": 21, "score2": 18, "confirmed": true }
  13.       ]
  14.     }
  15.   ]
  16. }
复制代码
附录B:快速开始


  • 在浏览器中打开 badminton.html
  • 按页面顺序逐步操作
  • 数据自动保存,关闭后重新打开即可恢复
附录C:浏览器兼容性


  • ✅ Chrome 90+
  • ✅ Firefox 88+
  • ✅ Safari 14+
  • ✅ Edge 90+
  • ⚠️ 需要支持 ES6、localStorage、Clipboard API
文档生成时间:2026-03-24
代码行数:2522行

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册