搭建产品原型
本人使用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#/share/{base64(data)}
[*]复制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快速添加)
中期重构(需要模块化):
[*]后端集成:
[*]保存到云端数据库
[*]多用户协作
[*]历史活动记录
[*]实时协作:
[*]WebSocket实现多端同步
[*]扫码加入活动
[*]智能调度:
[*]多种调度算法可选(贪心、匈牙利、模拟退火)
[*]算法可视化展示决策过程
[*]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": }
],
"schedule": [
{
"round": 1,
"courts": [
{ "team1": , "team2": , "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行
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]