// utils.js — 工具函数 const DEV = new URLSearchParams(location.search).has('dev'); const TEST = new URLSearchParams(location.search).has('test'); const sleep = ms => new Promise(r => setTimeout(r, ms)); function dbg(msg) { const el = document.getElementById('dbg'); if (el && el.style.display !== 'none') el.textContent = msg; } // TTS — 仅用于朗读文字消息内容,不用于任何 UI 反馈 const TTS = { _voices: [], init() { if (!window.speechSynthesis) return; const load = () => { this._voices = speechSynthesis.getVoices(); }; load(); speechSynthesis.onvoiceschanged = load; }, _pick() { return this._voices.find(v => v.lang.startsWith('zh') || v.name.includes('Chinese')) || this._voices[0] || null; }, get available() { return !!window.speechSynthesis; }, speak(text, { rate = 0.85, volume = 0.8 } = {}) { return new Promise(resolve => { if (!window.speechSynthesis) { resolve(false); return; } speechSynthesis.cancel(); const u = new SpeechSynthesisUtterance(text); u.lang = 'zh-CN'; u.rate = rate; u.volume = volume; const v = this._pick(); if (v) u.voice = v; u.onend = () => resolve(true); u.onerror = () => resolve(false); speechSynthesis.speak(u); }); }, stop() { if (window.speechSynthesis) speechSynthesis.cancel(); }, };