Appearance
实战案例:从零做一个番茄钟应用
难度:⭐ 入门 | 工具:Codex | 耗时:约 20 分钟 | 技术栈:HTML + CSS + JS
项目背景
番茄钟(Pomodoro Timer)是一个经典的效率工具:工作 25 分钟,休息 5 分钟,循环往复。这个项目非常适合 Vibe Coding 入门——功能明确、交互简单、但成品够好看。做之前,建议先看 项目管理思维:MVP 与迭代开发。
本文记录了完整的开发过程,包括每一步的提示词、AI 的输出情况、遇到的问题和解决方式。你可以跟着一步一步来。
第一阶段:需求规划(先想清楚再动手)
在打开 Codex 之前,我先花了 2 分钟想清楚要做什么:
核心功能(MVP):
- 25 分钟倒计时
- 开始 / 暂停 / 重置
- 计时结束有提示
第二版再加:
- 工作/休息模式自动切换
- 今日完成统计
- 自定义时间
视觉风格:
- 深色背景,大圆形进度环
- 工作时红色,休息时绿色
- 科技感但简洁
💡 经验:不要跳过规划。直接跟 AI 说"做个番茄钟",你会得到一个平庸的、可能到处是问题的结果。花 2 分钟想清楚,能省 20 分钟改 bug。
第二阶段:MVP 版本(第一轮对话)
提示词 #1:创建基础版本
text
帮我创建一个番茄钟(Pomodoro Timer)网页应用。
这是 MVP 版本,只做核心功能:
【功能】
1. 一个 25 分钟的倒计时器
2. 三个按钮:开始、暂停、重置
3. 计时结束时用 Web Audio API 播放一段简短的提示音(不需要音频文件,用代码生成一段 beep 声)
4. 页面标题(浏览器 tab)实时显示剩余时间
【界面设计】
- 页面正中央放一个大的圆形进度环(用 SVG 实现)
- 圆环内显示剩余时间,格式 MM:SS,字号至少 60px
- 圆环下方是三个按钮,水平排列
- 进度环随时间减少而变化(顺时针减少)
- 背景色:#1a1a2e
- 进度环颜色:#e74c3c(番茄红)
- 进度环轨道(底层):#2d2d44
- 按钮样式:圆角胶囊形,半透明白色背景
- 字体:系统默认无衬线字体
【技术要求】
- 纯 HTML + CSS + JavaScript
- 全部代码放在一个 index.html 文件中
- 响应式设计,手机上也能正常使用
请生成完整代码。AI 的输出
Codex 生成了一个完整的 index.html 文件,大约 200 行代码。包含了:
- SVG 圆形进度环
- 倒计时逻辑
- 三个控制按钮
- Web Audio API 提示音
- 基本的响应式处理
效果检查
在浏览器打开后,我逐项检查:
| 检查项 | 结果 | 备注 |
|---|---|---|
| 页面能打开 | ✅ | 无控制台报错 |
| 进度环显示 | ✅ | 但进度环是逆时针减少 |
| 开始按钮 | ✅ | 点击后开始倒计时 |
| 暂停按钮 | ✅ | 正常暂停 |
| 重置按钮 | ✅ | 恢复到 25:00 |
| 提示音 | ⚠️ | 太刺耳,需要调 |
| 标题显示时间 | ✅ | 正常 |
| 手机端 | ⚠️ | 按钮稍小 |
💡 经验:AI 的第一版输出 80% 可用是很正常的。关键是快速测试,找出需要改的点,进入迭代。
第三阶段:修复和优化(第二轮到第四轮对话)
提示词 #2:修复进度环方向 + 调整提示音
text
有两个问题需要修复:
1. 进度环的减少方向不对。现在是逆时针减少的,我需要顺时针减少(从12点钟方向开始,顺时针走)。请检查 SVG 的 stroke-dasharray 和 stroke-dashoffset 的计算逻辑,以及 transform 旋转角度。
2. 计时结束的提示音太刺耳了。请把频率从 800Hz 改成 520Hz,持续时间从 1 秒改成 0.3 秒,播放 3 次(间隔 0.4 秒),音量降低到 0.3。
其他部分不要改动。AI 回应:修复了 SVG 的 transform: rotate(-90deg) 和 stroke-dashoffset 计算方向。提示音也调整为 3 声短促的 beep。
提示词 #3:美化界面
text
现在界面能用了,我想让它更好看一些:
1. 给整个页面添加一个微妙的径向渐变背景:
从中心 #1a1a2e 渐变到边缘 #0f0f1a
2. 进度环添加发光效果:
- 给进度环(红色的那个)加一个 filter: drop-shadow,颜色用 rgba(231, 76, 60, 0.4),模糊半径 10px
- 计时结束最后 10 秒时,发光效果变强(脉冲闪烁)
3. 按钮优化:
- 默认状态:背景 rgba(255,255,255,0.1),文字白色
- hover:背景 rgba(255,255,255,0.2),有 transform: scale(1.05) 的放大效果
- active:transform: scale(0.95) 的按下效果
- 按钮之间间距 12px
- 按钮的 padding 改大一点:12px 32px
4. 时间数字用等宽字体,推荐 'Courier New' 或 monospace
字号改成 72px,字重 bold
5. 在进度环上方加一行小字:"专注时间",字号 14px,颜色 #666
不要改动任何功能逻辑,只改样式。AI 回应:所有样式修改都正确应用了。最后 10 秒的脉冲效果使用了 CSS animation + @keyframes。
提示词 #4:添加功能——工作/休息切换
text
现在要添加工作/休息模式自动切换:
1. 新增三种模式:
- 工作:25 分钟,进度环红色 #e74c3c,发光也是红色
- 短休息:5 分钟,进度环绿色 #2ecc71,发光也是绿色
- 长休息:15 分钟,进度环蓝色 #3498db,发光蓝色
2. 自动切换逻辑:
- 工作结束 → 自动进入短休息
- 短休息结束 → 自动进入下一轮工作
- 每完成 4 个工作周期后 → 进入长休息而非短休息
3. 界面更新:
- "专注时间"那行小字,根据当前模式显示"专注时间"/"短休息"/"长休息"
- 在按钮行上方显示当前是第几个番茄钟(例如:🍅🍅🍅○ 表示完成了3个)
- 模式切换时有一个平滑的颜色过渡动画(transition 0.5s)
4. 模式切换时播放不同的提示音:
- 工作结束:3声高音 beep(提示去休息)
- 休息结束:2声低音 beep(提示回来工作)
请在现有代码基础上添加这些功能,不要重写已有的部分。踩坑记录
这一轮 AI 的输出有一个 bug:完成 4 个番茄钟后没有自动切换到长休息,而是继续短休息。
我的调试过程:
text
完成 4 个工作周期后,应该进入长休息,但实际还是进入了短休息。
请检查 pomodoroCount 的计数逻辑和切换判断条件。
pomodoroCount 应该在每次工作结束后 +1,当 pomodoroCount % 4 === 0 时切换到长休息。AI 检查后发现是 pomodoroCount 的递增位置不对(在切换模式之后才递增,导致判断时用的是旧值)。修复后正常。
💡 踩坑经验:状态管理相关的 bug 最常见。当你发现"逻辑不对"但不知道哪里不对时,把你的预期逻辑描述清楚告诉 AI,让它去对照检查。
第四阶段:锦上添花(第五轮对话)
提示词 #5:添加今日统计 + 数据持久化
text
添加今日统计功能:
1. 在页面底部(按钮下方)添加统计区域:
- 今日完成的番茄钟数量(数字 + 🍅 图标)
- 今日总专注时间(格式:X小时X分钟)
- 统计区域用一个半透明卡片包裹,圆角 12px
2. 数据持久化:
- 使用 localStorage 保存:今日完成数、今日专注总秒数、日期
- 每次页面加载时检查日期,如果不是今天就自动清零
- 每次工作周期结束时更新数据
3. 在按钮行旁边加一个"设置"图标按钮(⚙️),点击弹出设置面板:
- 可以修改工作时长(默认25,范围1-60)
- 可以修改短休息时长(默认5,范围1-30)
- 可以修改长休息时长(默认15,范围1-60)
- 设置面板是一个从底部滑入的半透明卡片
- 设置保存到 localStorage
- 修改后立即生效(如果当前没有在计时中的话)
保持现有所有功能不变。第五阶段:最终检查
完成所有迭代后,做最终检查:
功能检查清单
- [x] 25 分钟倒计时正常
- [x] 开始/暂停/重置正常
- [x] 工作→短休息自动切换
- [x] 4 轮后→长休息
- [x] 提示音正常
- [x] 页面标题显示时间
- [x] 进度环颜色随模式变化
- [x] 最后 10 秒闪烁效果
- [x] 番茄计数图标正确
- [x] 今日统计正确
- [x] 数据持久化(刷新不丢)
- [x] 跨日自动清零
- [x] 自定义时间设置
- [x] 手机端正常显示
最终代码结构
一个 index.html 文件,约 450 行,包含:
- HTML 结构:SVG 进度环 + 控制区域 + 统计区域 + 设置面板
- CSS 样式:暗色主题、响应式、动画效果(内联在
<style>中) - JavaScript:计时器逻辑、模式切换、音效、localStorage(内联在
<script>中)
开发总结
时间花费
| 阶段 | 耗时 | 说明 |
|---|---|---|
| 需求规划 | 2 分钟 | 想清楚要做什么 |
| MVP 版本 | 3 分钟 | 第一轮提示词 + AI 生成 |
| 修复优化 | 8 分钟 | 3 轮迭代对话 |
| 锦上添花 | 5 分钟 | 统计 + 设置功能 |
| 最终检查 | 2 分钟 | 逐项验证 |
| 总计 | ~20 分钟 |
关键经验
- 先 MVP 再迭代:第一版只做核心功能,确认能跑了再加东西
- 提示词要具体到数值:不要说"好看一点",要说"间距改成 12px,颜色改成 #e74c3c"
- 每轮只改 2-3 个点:不要一次堆太多修改,AI 容易顾此失彼
- 说清楚"不要改已有的":每轮提示词都强调"保持现有功能不变"
- 状态逻辑要描述清楚:复杂逻辑(模式切换)要把预期的行为写明白
踩坑汇总
| 问题 | 原因 | 解决方式 |
|---|---|---|
| 进度环方向反了 | SVG rotate 角度和 offset 方向 | 明确描述"顺时针从 12 点方向" |
| 长休息没触发 | 计数器递增时机不对 | 描述清楚预期逻辑让 AI 对照检查 |
| 提示音太刺耳 | 默认频率和音量太高 | 给具体参数:520Hz、音量 0.3 |
| 手机端按钮太小 | 没有设置最小点击区域 | 要求 padding 改大 + min-height 44px |
给你的挑战
跟着上面的过程做完后,试着继续添加:
- 键盘快捷键:空格开始/暂停,R 重置
- 历史记录:过去 7 天的专注时间柱状图
- 白噪音:工作时播放雨声(Web Audio API 生成)
- 全屏模式:隐藏所有 UI 只留计时器
每个功能用一轮对话完成,体验"增量开发"的感觉。
