| 
						 | 
						- /**
 -  * 统一音频管理器
 -  * 实现单实例音频管理,避免多个音频同时播放造成的冲突
 -  */
 - class AudioManager {
 -   constructor() {
 -     // 当前音频实例
 -     this.currentAudio = null;
 -     // 音频类型:'sentence' | 'word'
 -     this.currentAudioType = null;
 -     // 音频状态
 -     this.isPlaying = false;
 -     // 复用的音频实例池
 -     this.audioInstance = null;
 -     // 事件监听器
 -     this.listeners = {
 -       play: [],
 -       pause: [],
 -       ended: [],
 -       error: [],
 -       timeupdate: [],
 -       canplay: []
 -     };
 -     // 播放速度支持检测
 -     this.playbackRateSupported = true;
 -     
 -     // 统一音频配置
 -     this.globalPlaybackRate = 1.0; // 全局播放速度
 -     this.globalVoiceId = ''; // 全局音色ID
 -     this.speedOptions = [0.5, 0.8, 1.0, 1.25, 1.5, 2.0]; // 支持的播放速度选项
 -   }
 - 
 -   /**
 -    * 创建HTML5 Audio实例并包装为uni-app兼容接口
 -    */
 -   createHTML5Audio() {
 -     const audio = new Audio();
 -     
 -     // 包装为uni-app兼容的接口
 -     const wrappedAudio = {
 -       // 原生HTML5 Audio实例
 -       _nativeAudio: audio,
 -       
 -       // 基本属性
 -       get src() { return audio.src; },
 -       set src(value) { audio.src = value; },
 -       
 -       get duration() { return audio.duration || 0; },
 -       get currentTime() { return audio.currentTime || 0; },
 -       
 -       get paused() { return audio.paused; },
 -       
 -       // 支持倍速的关键属性
 -       get playbackRate() { return audio.playbackRate; },
 -       set playbackRate(value) { 
 -         try {
 -           audio.playbackRate = value;
 -           console.log(`🎵 HTML5 Audio倍速设置成功: ${value}x`);
 -         } catch (error) {
 -           console.error('❌ HTML5 Audio倍速设置失败:', error);
 -         }
 -       },
 -       
 -       // 基本方法
 -       play() {
 -         return audio.play().catch(error => {
 -           console.error('HTML5 Audio播放失败:', error);
 -         });
 -       },
 -       
 -       pause() {
 -         audio.pause();
 -       },
 -       
 -       stop() {
 -         audio.pause();
 -         audio.currentTime = 0;
 -       },
 -       
 -       seek(time) {
 -         audio.currentTime = time;
 -       },
 -       
 -       destroy() {
 -         audio.pause();
 -         audio.src = '';
 -         audio.load();
 -       },
 -       
 -       // 事件绑定方法
 -       onCanplay(callback) {
 -         audio.addEventListener('canplay', callback);
 -       },
 -       
 -       onPlay(callback) {
 -         audio.addEventListener('play', callback);
 -       },
 -       
 -       onPause(callback) {
 -         audio.addEventListener('pause', callback);
 -       },
 -       
 -       onEnded(callback) {
 -         audio.addEventListener('ended', callback);
 -       },
 -       
 -       onTimeUpdate(callback) {
 -         audio.addEventListener('timeupdate', callback);
 -       },
 -       
 -       onError(callback) {
 -         // 包装错误事件,过滤掉非关键错误
 -         const wrappedCallback = (error) => {
 -           // 只在有src且音频正在播放时才传递错误事件
 -           if (audio.src && audio.src.trim() !== '' && !audio.paused) {
 -             callback(error);
 -           } else {
 -             console.log('🔇 HTML5 Audio错误(已忽略):', {
 -               hasSrc: !!audio.src,
 -               paused: audio.paused,
 -               errorType: error.type || 'unknown'
 -             });
 -           }
 -         };
 -         audio.addEventListener('error', wrappedCallback);
 -       },
 -       
 -       // 移除事件监听
 -       offCanplay(callback) {
 -         audio.removeEventListener('canplay', callback);
 -       },
 -       
 -       offPlay(callback) {
 -         audio.removeEventListener('play', callback);
 -       },
 -       
 -       offPause(callback) {
 -         audio.removeEventListener('pause', callback);
 -       },
 -       
 -       offEnded(callback) {
 -         audio.removeEventListener('ended', callback);
 -       },
 -       
 -       offTimeUpdate(callback) {
 -         audio.removeEventListener('timeupdate', callback);
 -       },
 -       
 -       offError(callback) {
 -         audio.removeEventListener('error', callback);
 -       }
 -     };
 - 
 -     return wrappedAudio;
 -   }
 - 
 -   /**
 -    * 创建音频实例
 -    * 优先使用HTML5 Audio(支持倍速),降级到uni.createInnerAudioContext
 -    * 复用已存在的音频实例以提高性能
 -    */
 -   createAudioInstance() {
 -     // 如果已有音频实例,直接复用
 -     if (this.audioInstance) {
 -       console.log('🔄 复用现有音频实例');
 -       return this.audioInstance;
 -     }
 -     
 -     // 在H5环境下优先使用HTML5 Audio
 -     // #ifdef H5
 -     try {
 -       this.audioInstance = this.createHTML5Audio();
 -       console.log('🎵 创建新的HTML5 Audio实例');
 -     } catch (error) {
 -       console.warn('⚠️ HTML5 Audio创建失败,降级到uni音频:', error);
 -       audio = uni.createInnerAudioContext();
 -       this.playbackRateSupported = false;
 -     }
 -     // #endif
 -     
 -     // 在非H5环境下使用uni音频
 -     // #ifndef H5
 -     this.audioInstance = uni.createInnerAudioContext();
 -     this.playbackRateSupported = false;
 -     console.log('🎵 创建新的uni音频实例');
 -     // #endif
 -     
 -     return this.audioInstance;
 -   }
 - 
 -   /**
 -    * 停止当前音频
 -    */
 -   stopCurrentAudio() {
 -     if (this.currentAudio) {
 -       console.log(`🛑 停止当前音频 (类型: ${this.currentAudioType})`);
 -       
 -       try {
 -         this.currentAudio.pause();
 -         // 不销毁音频实例,保留以供复用
 -         // this.currentAudio.destroy();
 -       } catch (error) {
 -         console.error('⚠️ 停止音频时出错:', error);
 -       }
 -       
 -       this.currentAudio = null;
 -       this.currentAudioType = null;
 -       this.isPlaying = false;
 -       
 -       // 触发暂停事件
 -       this.emit('pause');
 -     }
 -   }
 - 
 -   /**
 -    * 播放音频
 -    * @param {string} audioUrl - 音频URL
 -    * @param {string} audioType - 音频类型 ('sentence' | 'word')
 -    * @param {Object} options - 播放选项
 -    */
 -   async playAudio(audioUrl, audioType = 'word', options = {}) {
 -     try {
 -       console.log(`🎵 开始播放${audioType}音频:`, audioUrl);
 -       
 -       // 停止当前播放的音频
 -       this.stopCurrentAudio();
 -       
 -       // 创建新的音频实例
 -       const audio = this.createAudioInstance();
 -       audio.src = audioUrl;
 -       
 -       // 设置播放选项,优先使用全局播放速度
 -       const playbackRate = options.playbackRate || this.globalPlaybackRate;
 -       if (playbackRate && this.playbackRateSupported) {
 -         audio.playbackRate = playbackRate;
 -         console.log(`🎵 设置音频播放速度: ${playbackRate}x`);
 -       }
 -       
 -       // 绑定事件监听器
 -       this.bindAudioEvents(audio, audioType);
 -       
 -       // 保存当前音频实例
 -       this.currentAudio = audio;
 -       this.currentAudioType = audioType;
 -       
 -       // 延迟播放,确保音频实例完全准备好
 -       setTimeout(() => {
 -         if (this.currentAudio === audio) {
 -           try {
 -             audio.play();
 -             console.log(`✅ ${audioType}音频开始播放`);
 -           } catch (playError) {
 -             console.error('❌ 播放命令失败:', playError);
 -             this.emit('error', playError);
 -           }
 -         }
 -       }, 100);
 -       
 -       return audio;
 -     } catch (error) {
 -       console.error('❌ 播放音频异常:', error);
 -       this.emit('error', error);
 -       throw error;
 -     }
 -   }
 - 
 -   /**
 -    * 绑定音频事件监听器
 -    */
 -   bindAudioEvents(audio, audioType) {
 -     // 播放开始
 -     audio.onPlay(() => {
 -       console.log(`🎵 ${audioType}音频播放开始`);
 -       this.isPlaying = true;
 -       this.emit('play', { audioType, audio });
 -     });
 - 
 -     // 播放暂停
 -     audio.onPause(() => {
 -       console.log(`⏸️ ${audioType}音频播放暂停`);
 -       this.isPlaying = false;
 -       this.emit('pause', { audioType, audio });
 -     });
 - 
 -     // 播放结束
 -     audio.onEnded(() => {
 -       console.log(`🏁 ${audioType}音频播放结束`);
 -       this.isPlaying = false;
 -       
 -       // 不销毁音频实例,保留以供复用
 -       // 只清理当前播放状态
 -       if (this.currentAudio === audio) {
 -         this.currentAudio = null;
 -         this.currentAudioType = null;
 -       }
 -       
 -       this.emit('ended', { audioType, audio });
 -     });
 - 
 -     // 播放错误
 -     audio.onError((error) => {
 -       console.error(`❌ ${audioType}音频播放失败:`, error);
 -       this.isPlaying = false;
 -       
 -       // 发生错误时才销毁音频实例
 -       try {
 -         audio.destroy();
 -       } catch (destroyError) {
 -         console.error('⚠️ 销毁音频实例时出错:', destroyError);
 -       }
 -       
 -       if (this.currentAudio === audio) {
 -         this.currentAudio = null;
 -         this.currentAudioType = null;
 -       }
 -       
 -       // 清理复用的音频实例引用
 -       if (this.audioInstance === audio) {
 -         this.audioInstance = null;
 -       }
 -       
 -       this.emit('error', { error, audioType, audio });
 -     });
 - 
 -     // 时间更新
 -     audio.onTimeUpdate(() => {
 -       this.emit('timeupdate', { 
 -         currentTime: audio.currentTime, 
 -         duration: audio.duration,
 -         audioType, 
 -         audio 
 -       });
 -     });
 - 
 -     // 可以播放
 -     audio.onCanplay(() => {
 -       this.emit('canplay', { audioType, audio });
 -     });
 -   }
 - 
 -   /**
 -    * 暂停当前音频
 -    */
 -   pause() {
 -     if (this.currentAudio && this.isPlaying) {
 -       this.currentAudio.pause();
 -     }
 -   }
 - 
 -   /**
 -    * 恢复播放
 -    */
 -   resume() {
 -     if (this.currentAudio && !this.isPlaying) {
 -       this.currentAudio.play();
 -     }
 -   }
 - 
 -   /**
 -    * 设置播放速度
 -    */
 -   setPlaybackRate(rate) {
 -     if (this.currentAudio && this.playbackRateSupported) {
 -       this.currentAudio.playbackRate = rate;
 -       return true;
 -     }
 -     return false;
 -   }
 - 
 -   /**
 -    * 设置全局播放速度
 -    * @param {number} rate - 播放速度 (0.5 - 2.0)
 -    */
 -   setGlobalPlaybackRate(rate) {
 -     if (rate < 0.5 || rate > 2.0) {
 -       console.warn('⚠️ 播放速度超出支持范围 (0.5-2.0):', rate);
 -       return false;
 -     }
 -     
 -     this.globalPlaybackRate = rate;
 -     console.log(`🎵 设置全局播放速度: ${rate}x`);
 -     
 -     // 如果当前有音频在播放,立即应用新的播放速度
 -     if (this.currentAudio && this.playbackRateSupported) {
 -       try {
 -         this.currentAudio.playbackRate = rate;
 -         console.log(`✅ 当前音频播放速度已更新: ${rate}x`);
 -       } catch (error) {
 -         console.error('❌ 更新当前音频播放速度失败:', error);
 -       }
 -     }
 -     
 -     return true;
 -   }
 - 
 -   /**
 -    * 获取全局播放速度
 -    */
 -   getGlobalPlaybackRate() {
 -     return this.globalPlaybackRate;
 -   }
 - 
 -   /**
 -    * 设置全局音色ID
 -    * @param {string|number} voiceId - 音色ID
 -    */
 -   setGlobalVoiceId(voiceId) {
 -     this.globalVoiceId = String(voiceId);
 -     console.log(`🎵 设置全局音色ID: ${this.globalVoiceId}`);
 -   }
 - 
 -   /**
 -    * 获取全局音色ID
 -    */
 -   getGlobalVoiceId() {
 -     return this.globalVoiceId;
 -   }
 - 
 -   /**
 -    * 获取支持的播放速度选项
 -    */
 -   getSpeedOptions() {
 -     return [...this.speedOptions];
 -   }
 - 
 -   /**
 -    * 切换到下一个播放速度
 -    */
 -   togglePlaybackRate() {
 -     const currentIndex = this.speedOptions.indexOf(this.globalPlaybackRate);
 -     const nextIndex = (currentIndex + 1) % this.speedOptions.length;
 -     const nextRate = this.speedOptions[nextIndex];
 -     
 -     this.setGlobalPlaybackRate(nextRate);
 -     return nextRate;
 -   }
 - 
 -   /**
 -    * 获取当前播放状态
 -    */
 -   getPlaybackState() {
 -     return {
 -       isPlaying: this.isPlaying,
 -       currentAudioType: this.currentAudioType,
 -       hasAudio: !!this.currentAudio,
 -       playbackRateSupported: this.playbackRateSupported,
 -       currentTime: this.currentAudio ? this.currentAudio.currentTime : 0,
 -       duration: this.currentAudio ? this.currentAudio.duration : 0
 -     };
 -   }
 - 
 -   /**
 -    * 添加事件监听器
 -    */
 -   on(event, callback) {
 -     if (this.listeners[event]) {
 -       // 检查是否已经绑定过相同的回调函数,避免重复绑定
 -       if (this.listeners[event].indexOf(callback) === -1) {
 -         this.listeners[event].push(callback);
 -         console.log(`🎵 添加事件监听器: ${event}, 当前监听器数量: ${this.listeners[event].length}`);
 -       } else {
 -         console.warn(`⚠️ 事件监听器已存在,跳过重复绑定: ${event}`);
 -       }
 -     }
 -   }
 - 
 -   /**
 -    * 移除事件监听器
 -    */
 -   off(event, callback) {
 -     if (this.listeners[event]) {
 -       const index = this.listeners[event].indexOf(callback);
 -       if (index > -1) {
 -         this.listeners[event].splice(index, 1);
 -       }
 -     }
 -   }
 - 
 -   /**
 -    * 触发事件
 -    */
 -   emit(event, data) {
 -     if (this.listeners[event]) {
 -       this.listeners[event].forEach(callback => {
 -         try {
 -           callback(data);
 -         } catch (error) {
 -           console.error(`事件监听器执行错误 (${event}):`, error);
 -         }
 -       });
 -     }
 -   }
 - 
 -   /**
 -    * 销毁音频管理器
 -    */
 -   destroy() {
 -     this.stopCurrentAudio();
 -     
 -     // 销毁复用的音频实例
 -     // if (this.audioInstance) {
 -     //   try {
 -     //     this.audioInstance.destroy();
 -     //   } catch (error) {
 -     //     console.error('⚠️ 销毁音频实例时出错:', error);
 -     //   }
 -     //   this.audioInstance = null;
 -     // }
 -     
 -     this.listeners = {
 -       play: [],
 -       pause: [],
 -       ended: [],
 -       error: [],
 -       timeupdate: [],
 -       canplay: []
 -     };
 -   }
 - }
 - 
 - // 创建全局单例
 - const audioManager = new AudioManager();
 - 
 - export default audioManager;
 
 
  |