-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclock2.html
More file actions
424 lines (350 loc) · 16.7 KB
/
Copy pathclock2.html
File metadata and controls
424 lines (350 loc) · 16.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.clock-card{
position: fixed;
top:50%;
left:50%;
transform: translate(-50%, -50%);/* 让卡片中心点对齐屏幕中心*/
background: rgba(0, 0, 0, 0.75);/* 半透明黑色背景 */
color: #00ffcc;/* 青色数码管字体 */
padding: 30px 40px;
border-radius:20px;
font-family: 'Courier New', monospace;/* 等宽字体,更像电子表 */
box-shadow: 0 8px 32px rgba(0,0,0,0.5);
user-select: none;/* 防止鼠标拖动时选中文字 */
min-width: 300px;
}
.time{
font-size: 72px;
font-weight: bold;
text-align: center;
letter-spacing: 4px;
}
.controls{
margin-top: 20px;
display :flex;
gap: 15px;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
/* ========== 通用按钮样式 ========== */
.btn{
background: #2a2a2a;
color:#fff;
border: 1px solid #555; /* 边框:1像素宽,实线,深灰色 */
padding: 10px 20px;/* 内边距:上下10px,左右20px,让按钮看起来饱满 */
border-radius: 30px; /* 大圆角(30px),几乎变成胶囊形状 */
cursor: pointer;
font-size: 16px;
transition: 0.2s;
}
/* ========== 按钮的“悬停状态”========== */
.btn:hover{
background: #444;
border-color: #00ffcc;
}
/* ========== 计数器徽章 ========== */
.count-badge{
background: #ff6b6b; /* 亮红色背景(#ff6b6b 是珊瑚红) */
color:#fff;
padding: 5px 15px;
border-radius: 40px;
font-weight: bold;
}
.count-badge.gold{
background:#ffd700; /* 金色背景 */
color:#222; /* 黑色字体 */
box-shadow: 0 0 20px rgba(255, 215, 0, 0.8); /* 金色光晕 */
transition: 0.1s;
}
</style>
</head>
<body>
<!-- Clock Card -->
<div class="clock-card">
<!-- 显示时分秒 -->
<div class="time" id="displayTime">00:00:00</div>
<div class="controls">
<!-- 点击计数按钮 -->
<button class="btn" id="countBtn">👆 点击</button>
<span class="count-badge" id = "countNum">0</span>
<!-- 上传音频 -->
<input type="file" id = audioUpload accept="audio/*" style="color:#fff; width:140px;">
<!-- 倒计时区域(加在 controls 内部,放在“上传音频”的后面) -->
<div style="display: flex; gap: 10px; align-items: center; border-left: 1px solid #444; padding-left: 15px;">
<span style="color:#888; font-size:14px;">⏱</span>
<input type="number" id="cdInput" value="60" min="1" style="width:70px; padding:8px; border-radius:8px; border:1px solid #555; background:#222; color:#fff; text-align:center;">
<button class="btn" id="cdStartBtn" style="padding:8px 16px;">开始</button>
<button class="btn" id="cdResetBtn" style="padding:8px 16px;">重置</button>
<button class="btn" id="cdPauseBtn" style="padding:8px 16px;">暂停</button>
<span id="cdDisplay" style="font-size:28px; font-weight:bold; color:#ffaa00; min-width:80px; text-align:center;">00:00</span>
</div>
</div>
<!-- 简单状态提示 -->
<div style="margin-top: 15px;font-size: 14px;color:#888;text-align: center;" id="statusMsg">等待上传音频...</div>
</div>
<!-- ========== 自定义弹窗(默认隐藏) ========== -->
<div id="customAlert" style="display: none; position: fixed; top: 100px; left: 100px; min-width: 280px; background: rgba(20, 20, 30, 0.92); border: 1px solid #00ffcc; border-radius: 16px; box-shadow: 0 12px 48px rgba(0,0,0,0.7); backdrop-filter: blur(8px); padding: 0; z-index: 9999; user-select: none; font-family: 'Courier New', monospace; color: #e0e0e0;">
<!-- 标题栏(拖拽手柄) -->
<div id="alertHeader" style="padding: 14px 20px 8px 20px; cursor: grab; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(255,255,255,0.08);">
<span style="font-size: 18px; font-weight: bold; color: #00ffcc;">⏰ 提醒</span>
<button id="alertCloseBtn" style="background: transparent; border: none; color: #888; font-size: 24px; cursor: pointer; padding: 0 8px; transition: 0.2s;">✕</button>
</div>
<!-- 正文内容 -->
<div id="alertBody" style="padding: 20px 24px 28px 24px; font-size: 20px; line-height: 1.6;">
⏰ 倒计时结束!该做事了!
</div>
</div>
<script>
// ---------- 初始化变量 ----------
let clickCount = 0; // 点击次数
let audioUrl = null; // 上传的音频文件 URL
// 获取页面上的“元素句柄”
const timeEl = document.getElementById('displayTime');
const countEl = document.getElementById('countNum');
const statusEl = document.getElementById('statusMsg');
const audioInput = document.getElementById('audioUpload');
// ---------- 时钟核心 ----------
// setInterval(函数, 间隔毫秒) —— 每隔 1000 毫秒(1秒)执行一次括号里的函数
setInterval(() =>{
// new Date() 获取此刻的电脑系统时间
const now = new Date();
// toLocaleTimeString() 自动转成 "上午/下午 时:分:秒" 格式
// 这里toTimeString() 截取前 8 位 (HH:MM:SS)
const timeStr = now.toTimeString().slice(0,8);
// .innerText 就是修改 HTML 标签中间显示的文字
timeEl.innerText = timeStr;
},1000);
// ---------- 点击计数 ----------
document.getElementById('countBtn').onclick =() =>{
clickCount++;
countEl.innerText = clickCount;
// 当计数达到 10 次时,在控制台(F12)打印一条消息
if(clickCount === 10){
console.log('点击次数已达到 10 次!');
}
if(clickCount % 5 === 0 && clickCount !== 0){
countEl.classList.add('gold');
// 设置一个定时器:500 毫秒(0.5秒)后,移除金色类,回到红色
setTimeout(() => {
countEl.classList.remove('gold');
}, 500); // 0.5秒后移除金色样式
}
};
// ----------音频上传(处理文件输入) ----------
audioInput.onchange = (event) => {
const file = event.target.files[0];
if(!file){
statusEl.innerText = '❌ 未选择文件!';
return;
}
if(!file.type.startsWith('audio/')){
statusEl.innerText = '❌ 请选择音频文件!';
return;
}
audioUrl = URL.createObjectURL(file);
// 更新状态提示
statusEl.innerText = '✅ 音频上传成功!';
console.log('上传的音频文件 URL:', audioUrl);
}
console.log('页面加载完成,时钟已启动。');
// ==========================================
// ⏰ 闹钟模块(绝对时间触发)
// ==========================================
// ---------- 1. 状态变量 ----------
let alarmHour = null; // 设定的小时 (0-23)
let alarmMinute = null; // 设定的分钟 (0-59)
let alarmMessage = ''; // 提醒文字
let alarmIsSet = false; // 是否有闹钟待触发
let alarmTriggered = false; // 今天/本次是否已触发(防止重复弹窗)
// ---------- 2. DOM 引用 ----------
const alarmHourInput = document.getElementById('alarmHour');
const alarmMinuteInput = document.getElementById('alarmMinute');
const alarmMessageInput = document.getElementById('alarmMessage');
const alarmSetBtn = document.getElementById('alarmSetBtn');
const alarmCancelBtn = document.getElementById('alarmCancelBtn');
const alarmStatus = document.getElementById('alarmStatus');
// ---------- 3. 更新状态显示 ----------
function updateAlarmStatus() {
if (alarmIsSet) {
// 用 padStart 补零,保证显示 08:00 而不是 8:0
const h = String(alarmHour).padStart(2, '0');
const m = String(alarmMinute).padStart(2, '0');
alarmStatus.innerText = `⏰ 闹钟已设:${h}:${m}(${alarmMessage || '无提醒事项'})`;
alarmStatus.style.color = '#00ffcc';
} else {
alarmStatus.innerText = '⏸️ 未设置';
alarmStatus.style.color = '#ffaa00';
}
}
// ---------- 4. 设置闹钟 ----------
alarmSetBtn.onclick = () => {
// 读取并校验小时
const hour = parseInt(alarmHourInput.value);
const minute = parseInt(alarmMinuteInput.value);
if (isNaN(hour) || hour < 0 || hour > 23) {
alert('小时必须是 0-23 之间的数字!');
return;
}
if (isNaN(minute) || minute < 0 || minute > 59) {
alert('分钟必须是 0-59 之间的数字!');
return;
}
// 保存设定值
alarmHour = hour;
alarmMinute = minute;
alarmMessage = alarmMessageInput.value.trim() || '闹钟响了!';
alarmIsSet = true;
alarmTriggered = false; // 重置触发标记,允许重新触发
updateAlarmStatus();
console.log(`⏰ 闹钟已设置:${String(hour).padStart(2,'0')}:${String(minute).padStart(2,'0')} - ${alarmMessage}`);
};
// ---------- 5. 取消闹钟 ----------
alarmCancelBtn.onclick = () => {
alarmIsSet = false;
alarmTriggered = false;
updateAlarmStatus();
console.log('⏰ 闹钟已取消');
};
// ----------:在主时钟心跳里添加检查 -----------------
// ==========================================
// 🪟 自定义弹窗模块(可拖拽)
// ==========================================
// ---------- 1. 获取元素 ----------
const alertEl = document.getElementById('customAlert');
const alertHeader = document.getElementById('alertHeader');
const alertBody = document.getElementById('alertBody');
const alertCloseBtn = document.getElementById('alertCloseBtn');
// ---------- 2. 显示弹窗(替代 alert) ----------
function showCustomAlert(message = '⏰ 倒计时结束!该做事了!') {
alertBody.innerText = message; // 设置文本
alertEl.style.display = 'block'; // 显示
}
// ---------- 3. 关闭弹窗 ----------
function hideCustomAlert() {
alertEl.style.display = 'none';
}
// 点击关闭按钮
alertCloseBtn.onclick = hideCustomAlert;
// ---------- 4. 拖拽逻辑(核心!) ----------
let isDragging = false;
let offsetX = 0, offsetY = 0;
alertHeader.onmousedown = (e) => {
isDragging = true;
// 计算鼠标相对于弹窗左上角的偏移
const rect = alertEl.getBoundingClientRect();
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
alertHeader.style.cursor = 'grabbing';
e.preventDefault(); // 防止选中文字
};
document.onmousemove = (e) => {
if (!isDragging) return;
// 新位置 = 鼠标坐标 - 偏移量
alertEl.style.left = (e.clientX - offsetX) + 'px';
alertEl.style.top = (e.clientY - offsetY) + 'px';
};
document.onmouseup = () => {
if (isDragging) {
isDragging = false;
alertHeader.style.cursor = 'grab';
}
};
// ----------- 倒计时模块 ------------
let countdownTotal = 0; // 用户设定的总秒数(比如 60)
let countdownCurrent = 0; // 当前剩余的秒数(从 60 往下减)
let cdInterval = null; // 存储定时器的“句柄”
let isPaused = false; // 是否暂停状态(true 表示暂停,false 表示运行中)
// 获取 DOM 元素引用
const cdInput = document.getElementById('cdInput');
const cdStartBtn = document.getElementById('cdStartBtn');
const cdResetBtn = document.getElementById('cdResetBtn');
const cdDisplay = document.getElementById('cdDisplay');
const cdPauseBtn = document.getElementById('cdPauseBtn');
// ----------辅助函数:把“秒数”格式化成“分:秒” ----------
function formatTime(totalSeconds){
const mins = Math.floor(totalSeconds / 60);
const secs = totalSeconds % 60;
return `${String(mins).padStart(2,'0')}:${String(secs).padStart(2,'0')}`;
}
// ---------- 更新显示(将当前秒数渲染到屏幕上) ----------
function stopCountdown(){
if(cdInterval != null){
clearInterval(cdInterval);// 清除定时器句柄
cdInterval = null; // 置空,表示“当前没有正在运行的定时器”
}
isPaused = false; // 加上这行
if (cdPauseBtn) {
cdPauseBtn.innerText = '暂停';
cdPauseBtn.style.borderColor = '#555';
}
}
function updateDisplay() {
cdDisplay.innerText = formatTime(countdownCurrent);
}
cdPauseBtn.onclick = () => {
// 如果倒计时还没开始(当前秒数等于总秒数,且定时器没在跑),点了无效
if (cdInterval === null && countdownCurrent === countdownTotal) {
return;
}
// 切换状态:运行 -> 暂停,暂停 -> 运行
isPaused = !isPaused;
cdPauseBtn.innerText = isPaused ? '继续' : '暂停';
// 如果暂停了,把按钮颜色变一下(给用户视觉反馈)
if (isPaused) {
cdPauseBtn.style.borderColor = '#ffaa00';
} else {
cdPauseBtn.style.borderColor = '#555';
}
};
cdStartBtn.onclick = () => {
stopCountdown();
// 从输入框读取数值,并转成整数
// 容错:如果用户删光了输入框,或者输入负数,默认给 60
const inputVal = parseInt(cdInput.value);
if (isNaN(inputVal) || inputVal <= 0) {
cdInput.value = 60;
countdownTotal = 60;
}
else {
countdownTotal = inputVal;
}
// 把当前剩余秒数设为总秒数,并刷新显示
countdownCurrent = countdownTotal;
updateDisplay();
// 启动倒计时定时器(每 1000 毫秒执行一次)
cdInterval = setInterval(() => {
// 如果处于暂停状态,这次循环直接跳过,不减秒数
if (isPaused) {
return; // 直接结束本次执行,啥也不干
}
// 下面的代码(减1、更新、归零检查)原封不动
countdownCurrent = countdownCurrent - 1;
// ... 后面全都不动 ...
updateDisplay();
// -------------- 归零检查 --------------
if (countdownCurrent <= 0) {
// 归零了:停掉定时器,并弹窗提醒
stopCountdown(); // 重要:立即销毁定时器,防止变成负数
// 发出声音
if (audioUrl) {
// 用你上传的音频播放提示音
const audio = new Audio(audioUrl);
audio.play().catch(err => console.log('音频播放被浏览器拦截(需要用户交互)', err));
}
// 桌面弹窗(用户能看到的大提示)
showCustomAlert('⏰ 倒计时结束!该做事了!');
// 额外把屏幕上的数字置为 "00:00" 显示
cdDisplay.innerText = '00:00';
}
}, 1000);
};
</script>
</body>
</html>