如何设计一个高效的产品原型?

摘要:本人使用Claude Code制作了一个羽毛球轮转系统。然后让Claude Code生成了一个系统架构文档。文档内容如下: 羽毛球轮转管理系统 - 系统架构文档 一、项目概述 1.1 项目简介 羽毛球轮转管理系统是一个基于纯前端技术实现的单
本人使用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": [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行