/** * 音频管理工具 * 负责语音播放、音频队列管理等功能 */ export class AudioManager { constructor() { this.audioContext = null; this.audioTimer = null; this.audioInterval = 3000; this.isAudioPlaying = false; this.audioQueue = []; this.audioPlayEnabled = true; this.language = 'zh'; // 多语言语音文件配置 this.audioFiles = { zh: { red: '/static/chvoice/voice2/red.mp3', yellow: '/static/chvoice/voice2/yellow.mp3', green: '/static/chvoice/voice2/green.mp3' }, en: { red: '/static/envoice/voice2/red.mp3', yellow: '/static/envoice/voice2/yellow.mp3', green: '/static/envoice/voice2/green.mp3' }, ru: { red: '/static/pyvoice/voice2/red.mp3', yellow: '/static/pyvoice/voice2/yellow.mp3', green: '/static/pyvoice/voice2/green.mp3' } }; } /** * 初始化音频上下文 */ initAudioContext() { try { this.audioContext = uni.createInnerAudioContext(); this.audioContext.onError((res) => { console.error('音频播放失败:', res); this.isAudioPlaying = false; this.playNextInQueue(); }); this.audioContext.onEnded(() => { this.isAudioPlaying = false; this.playNextInQueue(); }); console.log('音频上下文初始化成功'); } catch (error) { console.error('音频上下文初始化失败:', error); } } /** * 检查音频播放状态 */ checkAudioPlaybackStatus() { try { if (this.audioContext) { this.audioContext.destroy(); } this.initAudioContext(); } catch (error) { console.error('检查音频播放状态失败:', error); } } /** * 播放语音 */ playVoice(layer, language = null) { if (!this.audioPlayEnabled || this.isAudioPlaying) { return; } const lang = language || this.language; const audioFile = this.audioFiles[lang]?.[layer]; if (!audioFile) { console.error('语音文件不存在:', layer, lang); return; } this.playAudioFile(audioFile); } /** * 播放音频文件 */ playAudioFile(audioFile) { if (!this.audioContext || this.isAudioPlaying) { return; } try { this.isAudioPlaying = true; this.audioContext.src = audioFile; this.audioContext.play(); console.log('开始播放音频:', audioFile); } catch (error) { console.error('播放音频失败:', error); this.isAudioPlaying = false; } } /** * 添加音频到播放队列 */ addToAudioQueue(layer, language = null) { if (!this.audioPlayEnabled) return; const lang = language || this.language; const audioFile = this.audioFiles[lang]?.[layer]; if (audioFile) { this.audioQueue.push(audioFile); console.log('添加音频到队列:', audioFile); if (!this.isAudioPlaying) { this.playNextInQueue(); } } } /** * 播放队列中的下一个音频 */ playNextInQueue() { if (this.audioQueue.length === 0 || this.isAudioPlaying) { return; } const nextAudio = this.audioQueue.shift(); this.playAudioFile(nextAudio); } /** * 清空音频队列 */ clearAudioQueue() { this.audioQueue = []; console.log('音频队列已清空'); } /** * 停止音频播放 */ stopAudio() { if (this.audioContext) { this.audioContext.stop(); this.isAudioPlaying = false; } this.clearAudioQueue(); } /** * 设置语言 */ setLanguage(language) { this.language = language; console.log('音频语言已设置为:', language); } /** * 设置音频播放开关 */ setAudioEnabled(enabled) { this.audioPlayEnabled = enabled; if (!enabled) { this.stopAudio(); } console.log('音频播放开关:', enabled ? '开启' : '关闭'); } /** * 设置音频播放间隔 */ setAudioInterval(interval) { this.audioInterval = interval; console.log('音频播放间隔已设置为:', interval, 'ms'); } /** * 销毁音频上下文 */ destroy() { if (this.audioContext) { this.audioContext.destroy(); this.audioContext = null; } this.isAudioPlaying = false; this.clearAudioQueue(); console.log('音频管理器已销毁'); } } /** * 扇形状态管理工具类 */ export class SectorStateManager { constructor() { this.activeSectors = new Map(); this.updateTimer = null; this.updateInterval = APP_CONFIG.SECTOR.UPDATE_INTERVAL; } /** * 启动扇形更新定时器 */ startSectorUpdateTimer() { // 清除之前的定时器 if (this.updateTimer) { clearInterval(this.updateTimer); } // 启动扇形更新定时器 this.updateTimer = setInterval(() => { this.updateSectorDisplay(); }, this.updateInterval); console.log('扇形更新定时器已启动'); } /** * 更新活跃扇形状态 * @param {Map} newSectors - 新的扇形状态 */ updateActiveSectors(newSectors) { // 清空当前活跃扇形 this.activeSectors.clear(); // 添加新的活跃扇形 newSectors.forEach((sectorInfo, sectorKey) => { this.activeSectors.set(sectorKey, sectorInfo); }); console.log('活跃扇形状态已更新,当前活跃扇形数量:', this.activeSectors.size); } /** * 更新扇形显示 * @param {Array} circleColors - 扇形颜色数组 * @param {boolean} isOffline - 是否离线 * @param {Function} updateCallback - 更新回调函数 */ updateSectorDisplay(circleColors, isOffline, updateCallback) { // 先重置所有扇形为灰色 this.resetAllColors(circleColors); // 如果处于离线状态,保持灰色 if (isOffline) { console.log('离线状态,保持扇形灰色'); return; } // 显示当前活跃的扇形 let updatedCount = 0; this.activeSectors.forEach((sectorInfo, sectorKey) => { const { layerIndex, sectorIndex, color } = sectorInfo; // 验证索引有效性 if (layerIndex >= 0 && layerIndex < circleColors.length && sectorIndex >= 0 && sectorIndex < circleColors[layerIndex].length) { // 更新扇形颜色 updateCallback(layerIndex, sectorIndex, color); updatedCount++; } else { console.warn('扇形索引无效:', { layerIndex, sectorIndex, sectorKey }); } }); if (updatedCount > 0) { console.log(`扇形显示已更新,更新了${updatedCount}个扇形`); } } /** * 重置所有扇形为灰色 * @param {Array} circleColors - 扇形颜色数组 */ resetAllColors(circleColors) { for (let layerIndex = 0; layerIndex < circleColors.length; layerIndex++) { for (let sectorIndex = 0; sectorIndex < circleColors[layerIndex].length; sectorIndex++) { circleColors[layerIndex][sectorIndex] = APP_CONFIG.COLORS.DEFAULT_SECTOR; } } } /** * 清空所有扇形 */ clearAllSectors() { // 清空活跃扇形状态 this.activeSectors.clear(); console.log('所有扇形已清空'); } /** * 强制触发扇形更新 * @param {Array} circleColors - 扇形颜色数组 * @param {boolean} isOffline - 是否离线 * @param {Function} updateCallback - 更新回调函数 */ forceUpdateSectors(circleColors, isOffline, updateCallback) { console.log('强制触发扇形更新'); this.updateSectorDisplay(circleColors, isOffline, updateCallback); } /** * 销毁扇形状态管理器 */ destroy() { if (this.updateTimer) { clearInterval(this.updateTimer); this.updateTimer = null; } this.activeSectors.clear(); } } /** * 离线检测管理工具类 */ export class OfflineDetectionManager { constructor() { this.lastDataTime = 0; this.offlineTimer = null; this.offlineTimeout = APP_CONFIG.OFFLINE.TIMEOUT; this.checkInterval = APP_CONFIG.OFFLINE.CHECK_INTERVAL; this.isOffline = false; } /** * 启动离线检测机制 */ startOfflineDetection() { // 清除之前的定时器 if (this.offlineTimer) { clearInterval(this.offlineTimer); } // 启动离线检测定时器 this.offlineTimer = setInterval(() => { const currentTime = Date.now(); const timeSinceLastData = currentTime - this.lastDataTime; // 如果超过超时时间没有收到数据,判定为离线 if (timeSinceLastData > this.offlineTimeout && !this.isOffline) { console.log('检测到离线状态,清空所有扇形'); this.isOffline = true; this.onOfflineDetected(); } }, this.checkInterval); console.log('离线检测机制已启动'); } /** * 更新最后数据接收时间 */ updateLastDataTime() { this.lastDataTime = Date.now(); this.isOffline = false; } /** * 离线检测回调 * @param {Function} callback - 离线检测回调函数 */ setOfflineCallback(callback) { this.onOfflineDetected = callback; } /** * 重置离线状态 */ resetOfflineState() { this.isOffline = false; this.lastDataTime = Date.now(); } /** * 销毁离线检测管理器 */ destroy() { if (this.offlineTimer) { clearInterval(this.offlineTimer); this.offlineTimer = null; } } } /** * 获取当前时间字符串 * @returns {string} 时间字符串 */ export function getTime() { const now = new Date(); const hour = String(now.getHours()).padStart(2, '0'); const minute = String(now.getMinutes()).padStart(2, '0'); const second = String(now.getSeconds()).padStart(2, '0'); return `${hour}:${minute}:${second}`; }