☰
用华为云码道 CodeArts 开发了一款「咩咩计时」工具,专注收集羊羊图鉴!从需求到上线的完整复盘
2026/10/6 8:07:28 网站建设 项目流程

> [一键开通华为云码道 CodeArts 代码智能体]Developer Events_Developer Alliance-Huawei Cloud

一、项目背景

在当今快节奏的工作生活中,专注力成为了一种稀缺资源。作为一名开发者,我一直在寻找提升专注力的方法。试过番茄钟、Forest、潮汐……但总觉得少了点什么。直到有一天,我看到“羊了个羊”的游戏机制——那种“收集图鉴、解锁成就”的快感,让我突然想到:为什么不把这种游戏化机制融入专注工具呢?

于是,咩咩计时(SheepFocus)诞生了。

更让我兴奋的是,这次开发完全使用华为云码道 CodeArts 代码智能体完成。从需求确认到代码实现,AI 智能体全程辅助,让我对“AI 辅助开发”有了全新的认识。

核心理念

完成专注时间,获得不同品种的羊,收集进自己的羊圈。

听起来简单,但背后是一套完整的游戏化设计:

- 21 个品种、4 级稀有度(普通 / 稀有 / 史诗 / 传说)

- 时长越长,稀有度概率越高

- 新手保护:首个 15 分钟档必得「白团团」

- 成就系统:10 个勋章,记录你的专注旅程

技术栈

- 纯前端:HTML5 + CSS3 + JavaScript (ES6+)

- 零依赖:无框架、无库,clone 即跑

- SVG 渲染:动态生成卡通羊

- Web Audio:合成音效,零外部文件

- localStorage:数据持久化

二、从需求到上线:开发全流程

第一阶段:需求确认(30 分钟)

用户提出需求后,智能体并没有直接开始写代码,而是先确认了几个关键问题:

1. 目标用户:学生、上班族、自由职业者

2. 核心场景:学习、工作、阅读

3. 功能边界:专注计时 + 收集羊,不做社交、不做付费

这个阶段让我意识到:需求确认比代码实现更重要。智能体通过提问,帮我把模糊的想法变成了清晰的需求文档。

第二阶段:设计文档(1 小时)

智能体生成了一份详细的设计文档,包括:

- 数据结构:羊数据、稀有度配置、用户数据

- 概率公式:15 / 60 / 120 分钟锚点,线性插值

- 接口契约:每个函数的输入输出、错误处理

- UI 设计:三 Tab 布局、进度圆环、羊圈网格

这份设计文档成为后续开发的"宪法",所有代码都严格遵循设计契约。

第三阶段:实现计划(30 分钟)

智能体将开发任务分解为 10 个步骤:

都有明确的验收标准,确保开发过程可控、可验证。

第四阶段:代码编写(3 小时)

智能体按计划编写代码,每个函数都有清晰的注释和类型标注。

代码质量亮点:

1. 纯函数设计:核心逻辑全部写成纯函数,易于测试

2. 模块化:四个 JS 文件职责清晰,互不依赖

3. 错误处理:所有可能失败的操作都有 try-catch

4. 性能优化:DocumentFragment、CSS 动画、Web Audio 合成

第五阶段:测试验证(1 小时)

智能体自动生成了 4 个单元测试和 5 个端到端测试:

单元测试:

- sheep-data.test.js:21 只羊数据验证

- storage.test.js:localStorage 读写测试

- roll.test.js:抽羊概率测试

- timer.test.js:计时器功能测试

端到端测试:

- 三个 Tab 可切换

- 选择预设档位并开始

- 自定义输入超限被钳制

- 暂停后剩余时间冻结

- 退出需确认

测试结果:20/20 全绿,零回归。

三、实现功能

专注计时

- 预设档位:15 / 25 / 45 / 60 分钟

- 自定义时长:1~180 分钟

- 支持暂停/继续/退出确认

- 时间戳差值计时器,切 Tab / 后台挂起也不会漂移

获得羊系统

- 21 个品种、4 级稀有度(普通 / 稀有 / 史诗 / 传说)

- 时长越长,稀有度概率越高

- 新手保护:首个 15 分钟档必得「普通-白团团」

- 概率表:

稀有度15 分钟60 分钟120 分钟
普通78%45%20%
稀有18%35%40%
史诗4%16%28%
传说0%4%12%

羊圈图鉴

- 21 张原创 SVG 卡通羊卡片

- 已解锁:彩色、有稀有度边框、有数量徽章

- 未解锁:灰度、灰色轮廓预览

- 稀有度光效:普通=草地绿 / 稀有=天蓝 / 史诗=紫色发光 / 传说=金色强发光

获得动画

- 专注完成播咩咩音效(Web Audio 合成)

- 羊从天而降弹窗(含名字、稀有度、图鉴描述)

- 点击收进羊圈

牧羊统计

- 今日 / 本周专注分钟

- 完成次数、获得羊数

- 累计专注满 10 小时解锁「牧羊人勋章」

- 10 个成就勋章:新手牧羊人、专注达人、早起鸟、夜猫子、连续 3 天、连续 7 天、羊圈收藏家、羊圈大师、传说猎人、牧羊人

数据持久化

- 全部数据存浏览器 localStorage

- 刷新页面可恢复进行中的专注

- 多标签页自动进入只读保护

四、项目运行效果

专注界面

- 进度圆环:绿色发光,呼吸动画

- 时间显示:大字号,居中显示

- 预设按钮:渐变绿色,悬停阴影

- 开始按钮:渐变背景,阴影效果

开始界面

羊圈界面

- 已解锁羊:彩色、有稀有度边框、有数量徽章

- 未解锁羊:灰度、灰色轮廓预览

- 统计卡片:显示解锁进度、获得数量、累计专注

获得羊弹窗

- 羊从天而降动画

- 名字、稀有度、描述

- 点击任意处收进羊圈

五、项目架构

miemie/ ├── index.html # 页面骨架 ├── css/style.css # 样式文件 ├── js/ │ ├── sheep-data.js # 21 只羊数据 + 稀有度配置 │ ├── pasture.js # localStorage 数据层 + 抽羊概率引擎 │ ├── timer.js # 时间戳差值计时器核心 │ └── app.js # 入口:Tab 切换、计时 UI、结算、羊圈、统计、弹窗音效 ├── tests/ │ ├── sheep-data.test.js # 羊数据测试 │ ├── storage.test.js # 存储测试 │ ├── roll.test.js # 抽羊概率测试 │ ├── timer.test.js # 计时器测试 │ └── e2e/ │ ├── focus.spec.js # 端到端测试 │ └── playwright.config.js ├── package.json

核心设计

时间戳差值计时器

不依赖 setInterval 的减法计数,切 Tab / 后台挂起也不会漂移:

function createTimer({ totalMs, now = Date.now }) { let status = "idle"; let remainingMs = totalMs; let startTs = 0; return { start() { if (status === "idle") { startTs = now(); status = "running"; } }, pause() { if (status === "running") { remainingMs = Math.max(0, remainingMs - (now() - startTs)); status = "paused"; } }, remaining() { if (status === "running") { return Math.max(0, remainingMs - (now() - startTs)); } return remainingMs; }, isDone() { return this.remaining() <= 0; }, }; }
抽羊概率引擎

15 / 60 / 120 分钟锚点,线性插值平滑过渡:

const RARITY_ANCHORS = { common: [[15, 0.78], [60, 0.45], [120, 0.20]], rare: [[15, 0.18], [60, 0.35], [120, 0.40]], epic: [[15, 0.04], [60, 0.16], [120, 0.28]], legendary: [[15, 0.00], [60, 0.04], [120, 0.12]], };
SVG 羊渲染器

动态生成卡通羊,支持多种角型、表情、配饰:

  • 角型:圆、螺旋、剑、皇冠
  • 表情:睡、笑、酷、眨眼
  • 配饰:蝴蝶结、围巾、铃铛、星星

六、开发过程中踩的坑

坑一:四个 JS 文件同名变量冲突

症状:页面加载后,所有按钮都点不动。

排查:打开浏览器控制台,发现报错:

SyntaxError: Identifier 'SheepFocus' has already been declared

根因:四个 JS 文件都在全局作用域声明了 const SheepFocus = {},浏览器加载第二个脚本就报重复声明错误。

解决:所有 JS 文件包进 IIFE,命名空间挂到 window.SheepFocus:

(function (global) { const SheepFocus = global.SheepFocus = global.SheepFocus || {}; // ... 代码 ... })(typeof window !== "undefined" ? window : globalThis);

教训:模块化开发中,全局变量命名冲突是常见陷阱。IIFE 或 ES Module 是必备技能。

坑二:弹窗点击事件被拦截

症状:专注完成后,弹窗显示正常,但点击任意处无法关闭。

排查:检查 CSS,发现#modal-root设置了 pointer-events: none。

根因:pointer-events: none会阻止所有子元素的点击事件,即使子元素设置了 pointer-events: auto也无法覆盖。

解决:

#modal-root { position: fixed; inset: 0; z-index: 50; pointer-events: none; /* 空时透明穿透 */ } .award-modal { position: absolute; inset: 0; pointer-events: auto; /* 弹窗显示时可点击 */ } .award-modal::before { pointer-events: none; /* 伪元素背景穿透 */ }

教训:pointer-events 的继承规则需要特别注意。子元素的 auto 无法覆盖父元素的 none。

坑三:计时器在后台挂起时漂移

症状:用户切换到其他标签页后,计时器变慢。

根因:现代浏览器会降低后台标签页的 setInterval 执行频率(最低 1 秒)。

解决:使用时间戳差值计时器,不依赖 setInterval 的减法计数:

function createTimer({ totalMs, now = Date.now }) { let status = "idle"; let remainingMs = totalMs; let startTs = 0; return { start() { if (status === "idle") { startTs = now(); status = "running"; } }, pause() { if (status === "running") { remainingMs = Math.max(0, remainingMs - (now() - startTs)); status = "paused"; } }, remaining() { if (status === "running") { return Math.max(0, remainingMs - (now() - startTs)); } return remainingMs; }, isDone() { return this.remaining() <= 0; }, }; }

教训:Web 开发中,计时器问题是一个经典陷阱。时间戳差值方案是最可靠的解决方案。

坑四:SVG 选择器错误

症状:获得羊弹窗显示后,羊的 SVG 没有正确渲染。

根因:HTML 中 SVG 类名是 sheep-award-svg,但 JS 选择器用的是 .award-svg。

解决:

// 错误 const svgEl = root.querySelector(".award-svg"); // 正确 const svgEl = root.querySelector(".sheep-award-svg");

教训:代码审查很重要。一个简单的拼写错误,可能导致功能完全失效。

七、性能优化实践

优化一:减少 DOM 操作

羊圈图鉴有 21 张卡片,每次渲染都要创建 21 个 DOM 元素。使用 DocumentFragment 批量插入,减少重排:

const fragment = document.createDocumentFragment(); for (const sheep of SH.SHEEP) { const card = document.createElement("div"); // ... 创建卡片 ... fragment.appendChild(card); } containerEl.appendChild(fragment);

优化二:CSS 动画代替 JavaScript 动画

进度圆环的呼吸动画使用 CSS @keyframes,利用 GPU 加速:

#ring-fg { animation: ringBreath 2.4s ease-in-out infinite; } @keyframes ringBreath { 0%, 100% { filter: drop-shadow(0 0 4px rgba(124, 179, 66, 0.4)); } 50% { filter: drop-shadow(0 0 12px rgba(124, 179, 66, 0.8)); } }

优化三:Web Audio 合成代替外部音频文件

使用 Web Audio API 合成音效,零外部依赖:

function tone(freq, t0, dur, type = "sine", vol = 0.15) { const o = ctx.createOscillator(); const g = ctx.createGain(); o.type = type; o.frequency.value = freq; g.gain.setValueAtTime(vol, t0); g.gain.exponentialRampToValueAtTime(0.0001, t0 + dur); o.connect(g); g.connect(ctx.destination); o.start(t0); o.stop(t0 + dur); }

八、个人心得体会

借助AtomGit完成咩咩计时项目开发,我认识到AI只是辅助工具。AI生成代码会存在各类bug,需要人工调试校验。开发过程要做到小步提交版本,做好版本管控。合理利用AI提高效率,但核心逻辑、项目把控仍要依靠开发者自身。

本项目已托管到 AtomGit 公开仓库:sheep-focus:SheepFocus(咩咩计时)是一款浏览器端游戏化专注计时工具。灵感来源于羊了个羊与 Forest,把专注变成收集小游戏。完成专注时长,随机获取不同稀有度小羊,集齐图鉴、解锁成就,提升专注的趣味性。全部数据保存在浏览器本地,无需后端服务。 - AtomGit

总结

通过华为云码道 CodeArts 代码智能体,我快速完成了这款游戏化专注计时工具的开发。从需求到实现,智能体提供了全方位的辅助,大大提升了开发效率。

如果你也想体验这种 AI 辅助开发的效率,欢迎一键开通华为云码道 CodeArts 代码智能体!

关键词:#华为云码道 #CodeArts #代码智能体 #AI辅助开发 #专注计时 #游戏化 #羊了个羊 #前端开发

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询