> [一键开通华为云码道 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辅助开发 #专注计时 #游戏化 #羊了个羊 #前端开发
网硕互联帮助中心







评论前必须登录!
注册