正计时 added temporary by AI
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
_cdModalMode: false, // true = countdown modal, false = alarm modal
|
||||
_editingCountdown: null,
|
||||
timezone: 'Asia/Shanghai', // 账户独立时区(来自 /api/display/state)
|
||||
countUp: { status: 'idle', startedAtMs: null, baseSec: 0, frozenSec: 0 },
|
||||
};
|
||||
|
||||
// ─── DOM refs ─────────────────────────────
|
||||
@@ -107,6 +108,10 @@
|
||||
if (name === 'pomodoro') {
|
||||
fetchPomodoro();
|
||||
}
|
||||
// Immediately render count-up when switching back to time panel
|
||||
if (name === 'time') {
|
||||
renderCountUpPanel();
|
||||
}
|
||||
}
|
||||
|
||||
cards.forEach(function (card) {
|
||||
@@ -1298,6 +1303,108 @@
|
||||
n.y + '年' + n.mo + '月' + n.d + '日 星期' + days[n.wd];
|
||||
}
|
||||
|
||||
function _calcCountUpElapsed() {
|
||||
var c = state.countUp;
|
||||
if (!c) return 0;
|
||||
if (c.status !== 'running') return c.frozenSec || 0;
|
||||
try {
|
||||
if (c.startedAtMs == null) return c.frozenSec || 0;
|
||||
return (c.baseSec || 0) + Math.floor((Date.now() - c.startedAtMs) / 1000);
|
||||
} catch (_) {
|
||||
return c.frozenSec || 0;
|
||||
}
|
||||
}
|
||||
|
||||
function _formatCountUp(totalSec) {
|
||||
if (typeof totalSec !== 'number' || !isFinite(totalSec) || totalSec < 0) {
|
||||
return '00:00:00';
|
||||
}
|
||||
var h = Math.floor(totalSec / 3600);
|
||||
var m = Math.floor((totalSec % 3600) / 60);
|
||||
var s = totalSec % 60;
|
||||
return _pad2(h) + ':' + _pad2(m) + ':' + _pad2(s);
|
||||
}
|
||||
|
||||
function renderCountUpPanel() {
|
||||
try {
|
||||
var c = state.countUp || {};
|
||||
var el = $('countup-value');
|
||||
if (!el) return;
|
||||
el.textContent = _formatCountUp(_calcCountUpElapsed());
|
||||
var btnStart = $('countup-start');
|
||||
var btnStop = $('countup-stop');
|
||||
var btnReset = $('countup-reset');
|
||||
var running = c.status === 'running';
|
||||
if (btnStart) btnStart.style.display = running ? 'none' : '';
|
||||
if (btnReset) btnReset.style.display = running ? 'none' : '';
|
||||
if (btnStop) btnStop.style.display = running ? '' : 'none';
|
||||
} catch (e) {
|
||||
console.warn('countUp render failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function countUpStart() {
|
||||
try {
|
||||
var c = state.countUp;
|
||||
if (c.status === 'running') return;
|
||||
c.baseSec = 0;
|
||||
c.startedAtMs = Date.now();
|
||||
c.status = 'running';
|
||||
renderCountUpPanel();
|
||||
} catch (e) {
|
||||
console.warn('countUp start failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function countUpStop() {
|
||||
try {
|
||||
var c = state.countUp;
|
||||
if (c.status !== 'running') return;
|
||||
c.frozenSec = _calcCountUpElapsed();
|
||||
c.startedAtMs = null;
|
||||
c.status = 'idle';
|
||||
renderCountUpPanel();
|
||||
} catch (e) {
|
||||
console.warn('countUp stop failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function countUpReset() {
|
||||
try {
|
||||
var c = state.countUp;
|
||||
c.frozenSec = 0;
|
||||
c.startedAtMs = null;
|
||||
c.status = 'idle';
|
||||
renderCountUpPanel();
|
||||
} catch (e) {
|
||||
console.warn('countUp reset failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
function setupCountUpControls() {
|
||||
var btnStart = $('countup-start');
|
||||
var btnStop = $('countup-stop');
|
||||
var btnReset = $('countup-reset');
|
||||
if (btnStart) {
|
||||
btnStart.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
countUpStart();
|
||||
});
|
||||
}
|
||||
if (btnStop) {
|
||||
btnStop.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
countUpStop();
|
||||
});
|
||||
}
|
||||
if (btnReset) {
|
||||
btnReset.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
countUpReset();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function renderWeatherPanel() {
|
||||
var w = state.weather || {};
|
||||
if (w.temp === undefined) {
|
||||
@@ -1621,6 +1728,7 @@
|
||||
renderCountdownCard();
|
||||
renderPomodoroCard();
|
||||
if (state.activePanel === 'time') renderTimePanel();
|
||||
if (state.activePanel === 'time') renderCountUpPanel();
|
||||
if (state.activePanel === 'pomodoro') renderPomodoro();
|
||||
if (state.activePanel === 'countdown') renderCountdownPanel();
|
||||
// Refresh update schedule info every 10s to keep next-update times current
|
||||
@@ -1648,5 +1756,13 @@
|
||||
fetchState();
|
||||
connectSSE();
|
||||
switchPanel('time');
|
||||
setupCountUpControls();
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
try {
|
||||
if (document.visibilityState === 'visible' && state.activePanel === 'time') {
|
||||
renderCountUpPanel();
|
||||
}
|
||||
} catch (_) {}
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user