<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数字闹钟</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#165DFF',
secondary: '#E8F3FF',
accent: '#4080FF',
neutral: {
100: '#F5F7FA',
200: '#E4E7EB',
300: '#CBD2D9',
400: '#9AA5B1',
500: '#7B8794',
600: '#616E7C',
700: '#52606D',
800: '#3E4C59',
900: '#1F2933'
}
},
fontFamily: {
inter: ['Inter', 'sans-serif'],
},
boxShadow: {
'soft': '0 2px 12px rgba(22, 93, 255, 0.1)',
'hover': '0 4px 16px rgba(22, 93, 255, 0.2)',
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.bg-gradient-blue {
background: linear-gradient(135deg, #E8F3FF 20%, #FFFFFF 80%);
}
.transition-all-300 {
transition: all 0.3s ease;
}
.scale-hover {
transition: transform 0.3s ease;
}
.scale-hover:hover {
transform: translateY(-5px);
}
.time-input {
@apply w-16 h-12 text-center text-xl font-medium border border-secondary rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50;
}
.alarm-item {
@apply flex items-center justify-between p-4 bg-white rounded-xl shadow-soft mb-3 transition-all-300 hover:shadow-hover;
}
.alarm-active {
@apply border-l-4 border-primary;
}
.btn-primary {
@apply bg-primary hover:bg-accent text-white px-6 py-3 rounded-lg font-medium transition-all-300 shadow-soft hover:shadow-hover flex items-center gap-2;
}
.btn-secondary {
@apply bg-white hover:bg-secondary text-primary border border-secondary px-6 py-3 rounded-lg font-medium transition-all-300 shadow-soft hover:shadow-hover flex items-center gap-2;
}
.btn-danger {
@apply bg-red-50 hover:bg-red-100 text-red-600 border border-red-200 px-4 py-2 rounded-lg font-medium transition-all-300;
}
}
</style>
</head>
<body class="font-inter bg-gradient-blue min-h-screen flex flex-col">
<!-- 导航栏 -->
<nav class="w-full py-6 px-4 md:px-8">
<div class="max-w-7xl mx-auto flex justify-between items-center">
<div class="flex items-center space-x-2">
<i class="fa fa-clock-o text-primary text-3xl"></i>
<h1 class="text-2xl font-bold text-neutral-800">数字<span class="text-primary">闹钟</span></h1>
</div>
<div class="hidden md:flex space-x-8">
<a href="#features" class="text-neutral-600 hover:text-primary transition-all-300 font-medium">功能</a>
<a href="#settings" class="text-neutral-600 hover:text-primary transition-all-300 font-medium">设置</a>
<a href="#about" class="text-neutral-600 hover:text-primary transition-all-300 font-medium">关于</a>
</div>
<button class="md:hidden text-neutral-800">
<i class="fa fa-bars text-xl"></i>
</button>
</div>
</nav>
<!-- 主内容区 -->
<main class="flex-grow w-full px-4 md:px-8 pb-16">
<div class="max-w-7xl mx-auto">
<!-- 当前时间显示 -->
<section class="py-12 md:py-20 text-center">
<h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-neutral-800 leading-tight">
现在时间: <span id="current-time" class="text-primary">00:00:00</span>
</h1>
<p class="text-lg text-neutral-600 mt-4">
设置闹钟,不错过任何重要时刻
</p>
</section>
<!-- 闹钟设置区域 -->
<section class="mt-16 md:mt-24 bg-white rounded-2xl shadow-soft p-8 md:p-12">
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- 左侧:添加闹钟表单 -->
<div class="bg-neutral-50 rounded-xl p-6 border border-neutral-200">
<h2 class="text-xl font-semibold text-neutral-800 mb-6 flex items-center">
<i class="fa fa-plus-circle text-primary mr-2"></i> 添加新闹钟
</h2>
<form id="alarm-form" class="space-y-6">
<div class="flex items-center justify-center gap-4">
<input type="number" id="hour" min="0" max="23" value="09" class="time-input">
<span class="text-2xl text-neutral-400">:</span>
<input type="number" id="minute" min="0" max="59" value="00" class="time-input">
<span class="text-2xl text-neutral-400">:</span>
<input type="number" id="second" min="0" max="59" value="00" class="time-input">
</div>
<div>
<label for="alarm-name" class="block text-neutral-700 font-medium mb-2">闹钟名称</label>
<input type="text" id="alarm-name" placeholder="例如:早上起床" class="w-full px-4 py-3 rounded-lg border border-secondary focus:outline-none focus:ring-2 focus:ring-primary/50">
</div>
<div>
<label for="alarm-sound" class="block text-neutral-700 font-medium mb-2">闹钟铃声</label>
<select id="alarm-sound" class="w-full px-4 py-3 rounded-lg border border-secondary focus:outline-none focus:ring-2 focus:ring-primary/50">
<option value="default">默认铃声</option>
<option value="bird">鸟鸣声</option>
<option value="waves">海浪声</option>
<option value="rain">雨声</option>
<option value="beep">蜂鸣声</option>
</select>
</div>
<button type="submit" class="btn-primary justify-center w-full">
<i class="fa fa-clock-o"></i>
<span>设置闹钟</span>
</button>
</form>
</div>
<!-- 右侧:闹钟列表 -->
<div>
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-semibold text-neutral-800 flex items-center">
<i class="fa fa-list-ul text-primary mr-2"></i> 我的闹钟
</h2>
<span id="active-count" class="bg-primary/10 text-primary px-3 py-1 rounded-full text-sm font-medium">
0 个活跃
</span>
</div>
<div id="alarm-list" class="space-y-3 max-h-[400px] overflow-y-auto pr-2">
<!-- 闹钟项目将通过JavaScript动态添加 -->
<div class="text-center text-neutral-500 py-10">
<i class="fa fa-clock-o text-4xl mb-4 text-neutral-300"></i>
<p>暂无闹钟,请添加新闹钟</p>
</div>
</div>
</div>
</div>
</section>
</div>
</main>
<!-- 闹钟提醒弹窗 -->
<div id="alarm-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-2xl p-8 max-w-md w-full mx-4 transform transition-all duration-300 scale-100">
<div class="text-center">
<div class="text-5xl text-primary mb-4 animate-pulse">
<i class="fa fa-bell"></i>
</div>
<h3 class="text-2xl font-bold text-neutral-800 mb-2" id="ringing-name">闹钟时间到!</h3>
<p class="text-neutral-600 mb-6" id="ringing-time">09:00:00</p>
<div class="flex justify-center gap-4">
<button id="snooze-btn" class="btn-secondary">
<i class="fa fa-clock-o"></i>
<span>稍后提醒</span>
</button>
<button id="stop-btn" class="btn-primary">
<i class="fa fa-stop"></i>
<span>停止</span>
</button>
</div>
</div>
</div>
</div>
<!-- 页脚 -->
<footer class="bg-neutral-800 text-white py-12 px-4 md:px-8">
<div class="max-w-7xl mx-auto">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<div class="flex items-center space-x-2 mb-6">
<i class="fa fa-clock-o text-primary text-2xl"></i>
<h2 class="text-xl font-bold">数字<span class="text-primary">闹钟</span></h2>
</div>
<p class="text-neutral-400 mb-6">简单而强大的网页闹钟,帮助您管理时间。</p>
</div>
<div>
<h3 class="text-lg font-semibold mb-6">功能</h3>
<ul class="space-y-3">
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">多闹钟管理</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">自定义铃声</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">稍后提醒</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">响应式设计</a></li>
</ul>
</div>
<div>
<h3 class="text-lg font-semibold mb-6">支持</h3>
<ul class="space-y-3">
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">帮助中心</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">常见问题</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">联系我们</a></li>
</ul>
</div>
<div>
<h3 class="text-lg font-semibold mb-6">法律</h3>
<ul class="space-y-3">
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">隐私政策</a></li>
<li><a href="#" class="text-neutral-400 hover:text-primary transition-all-300">服务条款</a></li>
</ul>
</div>
</div>
<div class="mt-12 pt-8 border-t border-neutral-700 text-center text-neutral-400 text-sm">
<p>© 2023 数字闹钟. 保留所有权利.</p>
</div>
</div>
</footer>
<script>
// 音频资源
const alarmSounds = {
'default': 'https://assets.mixkit.co/sfx/preview/mixkit-alarm-digital-clock-beep-989.mp3',
'bird': 'https://assets.mixkit.co/sfx/preview/mixkit-birds-chirping-in-the-forest-529.mp3',
'waves': 'https://assets.mixkit.co/sfx/preview/mixkit-waves-in-the-distance-1690.mp3',
'rain': 'https://assets.mixkit.co/sfx/preview/mixkit-rain-falling-on-the-water-of-a-lake-1959.mp3',
'beep': 'https://assets.mixkit.co/sfx/preview/mixkit-short-tone-alarm-990.mp3'
};
// 全局变量
let alarms = [];
let currentAudio = null;
let alarmInterval = null;
// DOM 元素
const currentTimeEl = document.getElementById('current-time');
const alarmListEl = document.getElementById('alarm-list');
const activeCountEl = document.getElementById('active-count');
const alarmForm = document.getElementById('alarm-form');
const hourInput = document.getElementById('hour');
const minuteInput = document.getElementById('minute');
const secondInput = document.getElementById('second');
const alarmNameInput = document.getElementById('alarm-name');
const alarmSoundSelect = document.getElementById('alarm-sound');
const alarmModal = document.getElementById('alarm-modal');
const ringingNameEl = document.getElementById('ringing-name');
const ringingTimeEl = document.getElementById('ringing-time');
const snoozeBtn = document.getElementById('snooze-btn');
const stopBtn = document.getElementById('stop-btn');
// 初始化
function init() {
// 加载本地存储的闹钟
loadAlarms();
// 更新当前时间
updateCurrentTime();
setInterval(updateCurrentTime, 1000);
// 更新闹钟状态
startAlarmCheck();
// 事件监听
alarmForm.addEventListener('submit', addAlarm);
snoozeBtn.addEventListener('click', snoozeAlarm);
stopBtn.addEventListener('click', stopAlarm);
}
// 加载本地存储的闹钟
function loadAlarms() {
const savedAlarms = localStorage.getItem('alarms');
if (savedAlarms) {
alarms = JSON.parse(savedAlarms);
renderAlarms();
}
}
// 保存闹钟到本地存储
function saveAlarms() {
localStorage.setItem('alarms', JSON.stringify(alarms));
}
// 更新当前时间显示
function updateCurrentTime() {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
currentTimeEl.textContent = `${hours}:${minutes}:${seconds}`;
}
// 添加闹钟
function addAlarm(e) {
e.preventDefault();
const hour = parseInt(hourInput.value);
const minute = parseInt(minuteInput.value);
const second = parseInt(secondInput.value);
const name = alarmNameInput.value.trim() || `闹钟 ${alarms.length + 1}`;
const sound = alarmSoundSelect.value;
// 验证输入
if (isNaN(hour) || hour < 0 || hour > 23) {
showToast('小时必须在0-23之间');
return;
}
if (isNaN(minute) || minute < 0 || minute > 59) {
showToast('分钟必须在0-59之间');
return;
}
if (isNaN(second) || second < 0 || second > 59) {
showToast('秒钟必须在0-59之间');
return;
}
// 创建闹钟对象
const now = new Date();
const alarmTime = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
hour,
minute,
second
);
// 如果设置的时间已经过去,则设置为明天
if (alarmTime <= now) {
alarmTime.setDate(alarmTime.getDate() + 1);
}
const alarm = {
id: Date.now().toString(),
time: alarmTime.toISOString(),
name,
sound,
active: true
};
// 添加到闹钟列表
alarms.push(alarm);
saveAlarms();
renderAlarms();
// 重置表单
alarmNameInput.value = '';
// 显示成功提示
showToast('闹钟已设置');
}
// 渲染闹钟列表
function renderAlarms() {
if (alarms.length === 0) {
alarmListEl.innerHTML = `
<div class="text-center text-neutral-500 py-10">
<i class="fa fa-clock-o text-4xl mb-4 text-neutral-300"></i>
<p>暂无闹钟,请添加新闹钟</p>
</div>
`;
updateActiveCount();
return;
}
// 按时间排序
alarms.sort((a, b) => new Date(a.time) - new Date(b.time));
alarmListEl.innerHTML = '';
alarms.forEach(alarm => {
const alarmTime = new Date(alarm.time);
const hours = String(alarmTime.getHours()).padStart(2, '0');
const minutes = String(alarmTime.getMinutes()).padStart(2, '0');
const seconds = String(alarmTime.getSeconds()).padStart(2, '0');
const alarmItem = document.createElement('div');
alarmItem.className = `alarm-item ${alarm.active ? 'alarm-active' : ''}`;
alarmItem.innerHTML = `
<div class="flex items-center gap-4">
<div class="w-12 h-12 bg-primary/10 rounded-lg flex items-center justify-center">
<i class="fa fa-clock-o text-primary text-xl"></i>
</div>
<div>
<h4 class="font-medium text-neutral-800">${alarm.name}</h4>
<p class="text-sm text-neutral-500">${hours}:${minutes}:${seconds}</p>
</div>
</div>
<div class="flex items-center gap-2">
<button class="toggle-alarm ${alarm.active ? 'text-primary' : 'text-neutral-400'}" data-id="${alarm.id}">
<i class="fa fa-toggle-${alarm.active ? 'on' : 'off'} text-xl"></i>
</button>
<button class="delete-alarm btn-danger" data-id="${alarm.id}">
<i class="fa fa-trash"></i>
</button>
</div>
`;
// 添加事件监听
alarmItem.querySelector('.toggle-alarm').addEventListener('click', toggleAlarm);
alarmItem.querySelector('.delete-alarm').addEventListener('click', deleteAlarm);
alarmListEl.appendChild(alarmItem);
});
// 更新活跃闹钟计数
updateActiveCount();
}
// 切换闹钟状态
function toggleAlarm(e) {
const id = e.currentTarget.getAttribute('data-id');
const alarm = alarms.find(a => a.id === id);
if (alarm) {
alarm.active = !alarm.active;
saveAlarms();
renderAlarms();
const message = alarm.active ? '闹钟已激活' : '闹钟已停用';
showToast(message);
}
}
// 删除闹钟
function deleteAlarm(e) {
const id = e.currentTarget.getAttribute('data-id');
alarms = alarms.filter(a => a.id !== id);
saveAlarms();
renderAlarms();
showToast('闹钟已删除');
}
// 更新活跃闹钟计数
function updateActiveCount() {
const activeCount = alarms.filter(a => a.active).length;
activeCountEl.textContent = `${activeCount} 个活跃`;
}
// 开始检查闹钟
function startAlarmCheck() {
if (alarmInterval) {
clearInterval(alarmInterval);
}
alarmInterval = setInterval(checkAlarms, 1000);
}
// 检查闹钟是否应该响铃
function checkAlarms() {
const now = new Date();
alarms.forEach(alarm => {
if (alarm.active) {
const alarmTime = new Date(alarm.time);
// 如果当前时间等于闹钟时间,并且还没有处理过
if (
now.getHours() === alarmTime.getHours() &&
now.getMinutes() === alarmTime.getMinutes() &&
now.getSeconds() === alarmTime.getSeconds()
) {
triggerAlarm(alarm);
// 将闹钟设置为明天
const nextAlarmTime = new Date(alarmTime);
nextAlarmTime.setDate(nextAlarmTime.getDate() + 1);
alarm.time = nextAlarmTime.toISOString();
saveAlarms();
}
}
});
}
// 触发闹钟
function triggerAlarm(alarm) {
// 显示闹钟弹窗
const alarmTime = new Date(alarm.time);
const hours = String(alarmTime.getHours()).padStart(2, '0');
const minutes = String(alarmTime.getMinutes()).padStart(2, '0');
const seconds = String(alarmTime.getSeconds()).padStart(2, '0');
ringingNameEl.textContent = alarm.name;
ringingTimeEl.textContent = `${hours}:${minutes}:${seconds}`;
// 播放闹钟声音
if (currentAudio) {
currentAudio.pause();
}
currentAudio = new Audio(alarmSounds[alarm.sound]);
currentAudio.loop = true;
currentAudio.play().catch(e => {
console.error('播放声音失败:', e);
showToast('播放声音失败,请确保浏览器允许播放声音');
});
// 显示弹窗
alarmModal.classList.remove('hidden');
}
// 稍后提醒
function snoozeAlarm() {
// 停止当前闹钟声音
if (currentAudio) {
currentAudio.pause();
}
// 隐藏弹窗
alarmModal.classList.add('hidden');
// 添加一个5分钟后的新闹钟
const now = new Date();
now.setMinutes(now.getMinutes() + 5);
const snoozeAlarm = {
id: Date.now().toString(),
time: now.toISOString(),
name: '稍后提醒',
sound: alarmSoundSelect.value,
active: true
};
alarms.push(snoozeAlarm);
saveAlarms();
renderAlarms();
showToast('已设置5分钟后提醒');
}
// 停止闹钟
function stopAlarm() {
// 停止当前闹钟声音
if (currentAudio) {
currentAudio.pause();
}
// 隐藏弹窗
alarmModal.classList.add('hidden');
showToast('闹钟已停止');
}
// 显示提示消息
function showToast(message) {
// 创建提示元素
const toast = document.createElement('div');
toast.className = 'fixed bottom-4 right-4 bg-neutral-800 text-white px-4 py-2 rounded-lg shadow-lg z-50 transform transition-all duration-300 translate-y-20 opacity-0';
toast.textContent = message;
// 添加到页面
document.body.appendChild(toast);
// 显示提示
setTimeout(() => {
toast.classList.remove('translate-y-20', 'opacity-0');
}, 10);
// 3秒后隐藏提示
setTimeout(() => {
toast.classList.add('translate-y-20', 'opacity-0');
setTimeout(() => {
document.body.removeChild(toast);
}, 300);
}, 3000);
}
// 初始化应用
init();
</script>
</body>
</html>
数字闹钟源码网页版
最新推荐文章于 2025-05-20 11:57:34 发布