export default { // 音频播放器实例 player: null, // 当前运行环境检测 isApp: null, // 初始化方法 init() { // 检测运行环境 const systemInfo = uni.getSystemInfoSync(); this.isApp = systemInfo.platform === 'ios' || systemInfo.platform === 'android'; // 初始化播放器 if (!this.player) { this.player = uni.createInnerAudioContext(); this.player.obeyMuteSwitch = false; // iOS静音模式下也可播放 this.player.onError((err) => { console.error('音频播放器错误:', err); uni.showToast({ title: '播放失败,请稍后再试', icon: 'none', duration: 2000 }); }); } }, // 从单词数据中提取所有音频信息(完整实现) extractAudioInfo(wordData) { if (!wordData || typeof wordData !== 'object') { console.error('无效的单词数据'); return { main: null, syllables: [], frequencies: [] }; } const audioInfo = { main: null, syllables: [], frequencies: [] }; // 处理主音频 if (wordData.yinpin && typeof wordData.yinpin === 'string') { audioInfo.main = { id: `word_${wordData.id}_main`, url: this.normalizeAudioUrl(wordData.yinpin), type: 'main', text: wordData.name || '未知单词', lastCached: 0 // 最后缓存时间戳 }; } // 处理音节音频 if (Array.isArray(wordData.yinjie)) { audioInfo.syllables = wordData.yinjie .filter(item => item && typeof item === 'object') .map((item, index) => ({ id: `word_${wordData.id}_syllable_${index}`, url: this.normalizeAudioUrl(item.yinpin), type: 'syllable', text: item.cigen || `音节${index + 1}`, index, lastCached: 0 })) .filter(item => item.url); } // 处理频度音频 if (Array.isArray(wordData.pindu)) { audioInfo.frequencies = wordData.pindu .filter(item => item && typeof item === 'object') .map((item, index) => ({ id: `word_${wordData.id}_frequency_${index}`, url: this.normalizeAudioUrl(item.yinpin), type: 'frequency', text: item.cigen || `频度${index + 1}`, index, lastCached: 0 })) .filter(item => item.url); } return audioInfo; }, // 标准化音频URL(完整实现) normalizeAudioUrl(url) { if (!url || typeof url !== 'string') return null; // 已经是完整URL if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('blob:')) { return url; } // 处理相对路径(根据实际项目配置) const baseUrl = 'https://your-audio-server.com/'; // 替换为你的音频服务器地址 return baseUrl + url.replace(/^\//, ''); }, // 缓存单词的所有音频(完整实现) async cacheWordAudios(wordData) { try { if (!wordData || !wordData.id) { throw new Error('无效的单词数据'); } // 提取音频信息 const audioInfo = this.extractAudioInfo(wordData); const allAudios = []; if (audioInfo.main) allAudios.push(audioInfo.main); if (audioInfo.syllables.length) allAudios.push(...audioInfo.syllables); if (audioInfo.frequencies.length) allAudios.push(...audioInfo.frequencies); // 真实下载音频文件(仅App环境) if (this.isApp) { await this.downloadAudioFiles(allAudios); } // 保存音频信息到缓存 this.saveAudioInfoToStorage(wordData.id, audioInfo); return true; } catch (error) { console.error('缓存单词音频失败:', error); return false; } }, // 下载音频文件(完整实现) async downloadAudioFiles(audioList) { if (!Array.isArray(audioList)) return; const downloadTasks = audioList.map(audio => { return new Promise((resolve, reject) => { // 检查是否已有缓存 const cacheInfo = this.getAudioCacheInfo(audio.id); if (cacheInfo && cacheInfo.cached) { audio.lastCached = cacheInfo.timestamp; return resolve(); } // 开始下载 uni.downloadFile({ url: audio.url, success: (res) => { if (res.statusCode === 200) { // 保存到缓存 uni.setStorageSync(`audio_file_${audio.id}`, res.tempFilePath); uni.setStorageSync(`audio_cache_time_${audio.id}`, Date.now()); audio.lastCached = Date.now(); console.log(`音频缓存成功: ${audio.id}`); resolve(); } else { reject(new Error(`下载失败,状态码: ${res.statusCode}`)); } }, fail: (err) => { reject(new Error(`下载失败: ${err.errMsg}`)); } }); }).catch(err => { console.warn(`音频下载失败 ${audio.id}:`, err); // 单个失败不影响其他 }); }); await Promise.all(downloadTasks); }, // 获取音频缓存信息(完整实现) getAudioCacheInfo(audioId) { if (!audioId) return null; const cachedPath = uni.getStorageSync(`audio_file_${audioId}`); if (!cachedPath) return null; return { cached: true, path: cachedPath, timestamp: uni.getStorageSync(`audio_cache_time_${audioId}`) || 0 }; }, // 保存音频信息到Storage(完整实现) saveAudioInfoToStorage(wordId, audioInfo) { if (!wordId || !audioInfo) return; const cacheKey = `word_audio_${wordId}`; const cacheData = { ...audioInfo, timestamp: Date.now(), wordId: wordId }; try { uni.setStorageSync(cacheKey, cacheData); } catch (e) { console.error('存储音频信息失败:', e); } }, // 从Storage获取音频信息(完整实现) getAudioInfoFromStorage(wordId) { if (!wordId) return null; const cacheKey = `word_audio_${wordId}`; try { return uni.getStorageSync(cacheKey) || null; } catch (e) { console.error('读取音频信息失败:', e); return null; } }, // 播放音频(完整实现) playAudio(audioInfo) { if (!audioInfo || !audioInfo.url) { console.error('无效的音频信息'); return null; } // 确保播放器初始化 this.init(); // 停止当前播放 this.player.stop(); // 在App环境下优先使用缓存 if (this.isApp) { const cacheInfo = this.getAudioCacheInfo(audioInfo.id); if (cacheInfo && cacheInfo.cached) { console.log(`使用缓存播放: ${audioInfo.id}`); this.player.src = cacheInfo.path; this.player.play(); return this.player; } } // 无缓存或非App环境,使用网络播放 console.log(`使用网络播放: ${audioInfo.id}`); this.player.src = audioInfo.url; this.player.play(); // App环境下后台尝试缓存 if (this.isApp) { this.downloadAudioFiles([audioInfo]).then(() => { console.log(`音频后台缓存成功: ${audioInfo.id}`); }).catch(err => { console.warn(`音频后台缓存失败: ${audioInfo.id}`, err); }); } return this.player; }, // // 清理指定单词的缓存(完整实现) // clearWordCache(wordId) { // if (!wordId) return; // // 清理音频信息 // uni.removeStorageSync(`word_audio_${wordId}`); // // 清理所有相关音频文件 // const prefix = `word_${wordId}_`; // const keys = uni.getStorageInfoSync().keys; // keys.forEach(key => { // if (key.startsWith('audio_file_') && key.includes(prefix)) { // uni.removeStorageSync(key); // } // if (key.startsWith('audio_cache_time_') && key.includes(prefix)) { // uni.removeStorageSync(key); // } // }); // }, // 清理所有缓存(完整实现) clearAllCache() { const keys = uni.getStorageInfoSync().keys; // 清理所有单词音频信息 keys.filter(key => key.startsWith('word_audio_')) .forEach(key => uni.removeStorageSync(key)); // 清理所有音频文件 keys.filter(key => key.startsWith('audio_file_')) .forEach(key => uni.removeStorageSync(key)); }, // // 获取缓存大小(完整实现) // getCacheSize() { // const keys = uni.getStorageInfoSync().keys; // let size = 0; // keys.filter(key => key.startsWith('audio_file_')) // .forEach(key => { // try { // const filePath = uni.getStorageSync(key); // if (filePath && typeof filePath === 'string') { // // 注意:uni-app中无法直接获取文件大小,这里返回文件数量 // size += 1; // } // } catch (e) { // console.error(`获取缓存大小失败: ${key}`, e); // } // }); // return { // fileCount: size, // // 实际项目中可以添加更精确的大小计算 // estimatedSize: size * 1024 * 100 // 假设每个文件约100KB // }; // } };