Перейти к основному содержимому
claw
am
tools
Инструменты
Документы
Daoark
EN
Главная
Главная
/
Быт и полезное
›
Главная
manifest.json
0; }); var arr = []; for (var i = 0; i < lines.length; i++) { var line = lines[i]; // 拆分备注 var parts = line.split('#'); var head = parts[0].trim(); var note = parts.length > 1 ? parts.slice(1).join('#').trim() : ''; // head 末尾数字 = 时长 var m = head.match(/^(.+?)\s+(\d+(?:\.\d+)?)\s*$/); if (m) arr.push({ name: m[1].trim(), minutes: parseFloat(m[2]), note: note }); } return arr; } function fmtTime(s) { if (s < 0) s = 0; var m = Math.floor(s / 60); var ss = Math.floor(s % 60); return String(m).padStart(2, '0') + ':' + String(ss).padStart(2, '0'); } var audioCtx = null; function beep(freq, dur) { if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); var o = audioCtx.createOscillator(); var g = audioCtx.createGain(); o.connect(g); g.connect(audioCtx.destination); o.frequency.value = freq; var t = audioCtx.currentTime; g.gain.setValueAtTime(0.3, t); g.gain.linearRampToValueAtTime(0, t + dur); o.start(t); o.stop(t + dur); } function renderTimer() { if (!state.agenda || state.agenda.length === 0) return; var cur = state.agenda[state.idx]; var remain = state.remainSec; var total = cur.minutes * 60; var pct = Math.max(0, Math.min(100, (remain / total) * 100)); var overTime = total - remain; var html = '
' + '
议程 ' + (state.idx + 1) + ' / ' + state.agenda.length + ' · 已用 ' + fmtTime(state.usedSec + (state.running ? 0 : 0)) + '
' + '
' + (overTime > 0 ? '+' + fmtTime(overTime) : fmtTime(remain)) + '
' + '
' + escapeHtml(cur.name) + '
' + (cur.note ? '
' + escapeHtml(cur.note) + '
' : '') + '
' + '
' + '
' + '
总进度:
' + (state.idx + 1) + '/' + state.agenda.length + ' 议程完成
'; showResult(html, '会议进行中...'); } function escapeHtml(s) { return String(s).replace(/[&<>"']/g, function(c) { return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]; }); } function totalPlanned() { return state.agenda.reduce(function(s, a) { return s + a.minutes; }, 0); } var state = { agenda: [], idx: 0, remainSec: 0, usedSec: 0, timer: null, running: false, warned: false }; function tick() { state.remainSec--; if (state.remainSec <= 0) { // 议程超时 beep(880, 0.3); setTimeout(function() { beep(880, 0.3); }, 400); setTimeout(function() { beep(1320, 0.5); }, 800); } else { var warn = parseFloat($('warn').value) * 60; if (state.remainSec <= warn && !state.warned) { state.warned = true; beep(660, 0.2); } } renderTimer(); } function start() { var text = getVal('text-a'); var agenda = parseAgenda(text); if (agenda.length === 0) { showError('议程格式:每行 "名称 时长",如 "议题 10"'); return; } state.agenda = agenda; state.idx = 0; state.remainSec = agenda[0].minutes * 60; state.usedSec = 0; state.warned = false; if (state.timer) clearInterval(state.timer); state.timer = setInterval(tick, 1000); state.running = true; renderTimer(); } function pause() { if (state.timer) { clearInterval(state.timer); state.timer = null; state.running = false; } else { state.timer = setInterval(tick, 1000); state.running = true; } renderTimer(); } function next() { if (state.idx < state.agenda.length - 1) { state.idx++; state.remainSec = state.agenda[state.idx].minutes * 60; state.warned = false; beep(1100, 0.15); renderTimer(); } else { showResult('
所有议程完成!总用时 ' + state.usedSec + ' 秒
', '会议结束'); clearInterval(state.timer); } } function reset() { if (state.timer) clearInterval(state.timer); state.agenda = []; state.idx = 0; state.remainSec = 0; state.usedSec = 0; state.running = false; var ra = $('result-area'); ra.hidden = true; ra.style.display = 'none'; } $('btn-start').addEventListener('click', start); $('btn-pause').addEventListener('click', pause); $('btn-next').addEventListener('click', next); $('btn-reset').addEventListener('click', reset); })();