从需求到上线:我用 AI 辅助开发了一个在线倒计时器

最近在处理一个项目排期的时候,发现一个很实际的问题:团队里经常需要知道"距离某个截止日期还有多少天",但每次都要打开日历数日子,或者用命令行算时间差,实在不够直观。

问题背景

作为独立开发者,我经常需要跟踪各种截止日期------项目交付、域名续费、服务器证书到期等等。市面上确实有不少倒计时工具,但大多存在几个问题:

  1. 要么功能太复杂,打开页面就被各种设置项淹没
  2. 要么需要安装应用,杀鸡用牛刀
  3. 有的还带广告,体验很糟糕

我就是想要一个打开即用、设置目标时间就能看剩余时间的轻量工具。而且作为开发者,我希望能完全掌控代码,方便后续按需定制。

技术选型思考

一开始考虑过几个方案:

  • 用现成的 npm 包 :比如 countdown 库,但为了一个倒计时引入依赖,感觉有点重
  • 写个命令行脚本:能用,但不方便给团队其他人用
  • 做个网页工具:跨平台、无需安装、分享方便,但需要处理前端的一堆细节

最后决定做个单文件 HTML,纯 vanilla JS 实现。理由很简单:不需要构建工具,不需要服务器,双击就能打开,这符合"工具就该轻量"的原则。

AI 辅助开发过程

说实话,一开始我连 datetime-local 输入框的兼容性问题都懒得查,直接打开了 Claude 开始对话。

第一轮:需求描述

我给的 prompt 大概是这样的:

帮我写一个单文件 HTML 倒计时器,支持设置目标日期和时间、自定义事件名称、实时显示剩余天时分秒、每秒刷新,支持深色模式,中英文切换。

AI 很快就生成了一版,整体结构不错,但我发现几个问题:

问题 1:时间计算有 bug

AI 第一次用的是 Date.now()new Date(targetStr) 直接相减,这在跨时区时会出问题。比如用户在东八区设置了一个 UTC 时间,显示的剩余时间会差 8 小时。

javascript 复制代码
// AI 第一次的写法(有 bug)
var ms = new Date(targetStr) - new Date();

我的修正方案 :用 datetime-local 输入的值是本地时间字符串,直接 new Date(targetStr) 解析即可,但要注意 new Date('2024-01-01T00:00') 在不同浏览器解析行为可能不同,最好手动解析:

javascript 复制代码
function parseLocalDateTime(str) {
  var parts = str.split('T');
  var dateParts = parts[0].split('-');
  var timeParts = parts[1].split(':');
  return new Date(
    +dateParts[0], +dateParts[1] - 1, +dateParts[2],
    +timeParts[0], +timeParts[1]
  );
}

问题 2:i18n 实现太笨重

AI 第一次的国际化方案是每个元素都写 if (lang === 'zh') ... else ...,代码重复不说,还容易漏。我让它改成 key-value 映射 + t() 函数的方式,清爽多了。

问题 3:进度条逻辑没考虑边界

AI 写的进度条在"起始日期晚于目标日期"时会算出负百分比,需要 clamp 到 0-100。

第二轮:交互细节打磨

我发现 AI 生成的版本有几个交互问题:

  1. 页面标题不会更新 :我让它把倒计时同步到 document.title,这样浏览器标签页上就能直接看到剩余时间
  2. 快捷预设按钮是写死的 :比如"新年"预设,如果写死 2025-01-01,明年就失效了。我让 AI 改成动态计算:
javascript 复制代码
// 动态计算下一个新年
function getNextNewYear() {
  var now = new Date();
  return new Date(now.getFullYear() + 1, 0, 1); // 明年1月1日
}
  1. 到期后的表现:我要求到期后切换为正计时(显示已过去多久),并变红提示。AI 一开始只是显示"已过期",不够直观。

第三轮:视觉和细节

设计上我提了几个要求:

  • 数字用等宽字体(monospace),避免每秒跳动时宽度变化导致布局抖动
  • 数字切换时有简单的动画效果(用 CSS transition
  • 深色模式下所有颜色都要重新适配

AI 在这轮表现不错,CSS 变量切换深色模式的方式很干净:

css 复制代码
:root {
  --bg: #fff;
  --text: #111827;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a2e;
    --text: #e2e8f0;
  }
}

核心实现细节

时间差计算

这是倒计时的核心,要注意:

  • 不能用 Math.abs() 直接取绝对值,因为天、时、分、秒需要分别计算
  • Math.floor() 而不是 Math.round(),否则会出现"59秒显示为60秒"的问题
javascript 复制代码
function calcDiff(from, to) {
  var ms = to - from;
  var isPast = ms < 0;
  ms = Math.abs(ms);
  var d = Math.floor(ms / 86400000);
  ms -= d * 86400000;
  var h = Math.floor(ms / 3600000);
  ms -= h * 3600000;
  var m = Math.floor(ms / 60000);
  ms -= m * 60000;
  var s = Math.floor(ms / 1000);
  return { d, h, m, s, isPast };
}

每秒刷新

setInterval(tick, 1000),但要注意:如果用户切换到其他标签页,浏览器会节流 setInterval,导致时间不准。不过对于倒计时场景,1秒的误差完全可以接受,不需要用 requestAnimationFrame 或 Web Worker 来保证精度。

快捷预设

这里有个细节:周末的判定。如果今天是周六,那"本周末"应该是明天(周日),而不是今天。我用了个小技巧:

javascript 复制代码
var daysUntilSat = (6 - day + 7) % 7;
if (daysUntilSat === 0) daysUntilSat = 7; // 如果是周六,跳到下周六

踩坑记录

  1. datetime-local 的兼容性:Safari 15 以下不支持,需要 fallback。不过我做了渐进增强------不支持的浏览器会降级为文本输入框,用户手动输入日期格式。

  2. XSS 风险 :事件名称是用户输入,直接插到 innerHTML 里会有 XSS 风险。必须用 escapeHtml() 转义:

javascript 复制代码
function escapeHtml(s) {
  var d = document.createElement('div');
  d.textContent = s;
  return d.innerHTML;
}
  1. 移动端布局 :4 个数字盒子在 320px 宽度下会挤在一起。用 flex-wrapmin-width 解决,同时在小屏下减小字号。

对 AI 辅助编程的感受

这次开发过程最大的感受是:AI 是很好的结对编程伙伴,但你不能完全放手

  • AI 擅长:快速搭框架、写重复性代码、查 API 用法
  • AI 不擅长:理解业务边界条件、处理浏览器兼容性、做交互细节的取舍

比如 AI 第一次生成的代码完全没有考虑"用户没设置日期就点击开始"的情况,是我在测试时发现的。这种边界情况,需要开发者自己把关。

另外,给 AI 的 prompt 越具体,输出质量越高。比如"进度条需要 clamp 到 0-100"、"到期后切换为正计时并显示红色",比"加个进度条"要好得多。

适用场景

这个工具适合:

  • 团队项目截止日期追踪
  • 个人目标倒计时(考试、旅行、健身计划)
  • 产品上线倒计时(配合全屏模式投屏)
  • 日常提醒(比如服务器证书到期)

如果你也有类似需求,可以直接在线使用:倒计时器 - 在线日期倒计时计算工具

代码已经完整放在页面上,纯前端实现,所有计算都在浏览器本地完成,不会上传任何数据。你也可以直接右键查看源码,或者 F12 拷贝下来自己改。


相关推荐
AlienZHOU8 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc11 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师13 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen13 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒13 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow14 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林81814 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang8007814 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明14 小时前
第 6 章 组件进阶
前端·vue.js
江华森14 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端