// pages/audio/audio.js const chapterApi = require('../../api/chapter'); const historyApi = require('../../api/history'); const userUtil = require('../../utils/user'); Page({ data: { contentId: null, audioId: null, audio: null, chapters: [], currentIndex: 0, playing: false, currentTime: 0, duration: 0, speed: 1.0, // 播放速度 loading: true, audioContext: null }, onLoad(options) { const contentId = parseInt(options.contentId); const audioId = parseInt(options.audioId); if (!contentId || !audioId) { wx.showToast({ title: '参数错误', icon: 'none' }); setTimeout(() => { wx.navigateBack(); }, 1500); return; } this.setData({ contentId, audioId }); this.loadChapters(); this.loadAudio(); this.initAudio(); }, onUnload() { // 页面卸载时停止播放 if (this.data.audioContext) { this.data.audioContext.stop(); } }, // 初始化音频上下文 initAudio() { const audioContext = wx.createInnerAudioContext(); audioContext.onPlay(() => { this.setData({ playing: true }); }); audioContext.onPause(() => { this.setData({ playing: false }); }); audioContext.onTimeUpdate(() => { this.setData({ currentTime: audioContext.currentTime, duration: audioContext.duration }); }); audioContext.onEnded(() => { this.setData({ playing: false }); // 自动播放下一章 this.nextChapter(); }); audioContext.onError((err) => { wx.showToast({ title: '播放出错', icon: 'none' }); console.error('音频播放错误:', err); }); this.setData({ audioContext }); }, // 加载章节列表 async loadChapters() { try { const chapters = await chapterApi.getAudioChapterList(this.data.contentId); const currentIndex = chapters.findIndex(c => c.audioId === this.data.audioId); this.setData({ chapters, currentIndex: currentIndex >= 0 ? currentIndex : 0 }); } catch (error) { console.error('加载章节列表失败:', error); } }, // 加载音频信息 async loadAudio() { this.setData({ loading: true }); try { const audio = await chapterApi.getAudioChapter(this.data.audioId); this.setData({ audio }); // 设置音频源 if (this.data.audioContext && audio.audioUrl) { this.data.audioContext.src = audio.audioUrl; this.data.audioContext.playbackRate = this.data.speed; } wx.setNavigationBarTitle({ title: audio.chapterTitle || '听书' }); } catch (error) { wx.showToast({ title: error || '加载失败', icon: 'none' }); } finally { this.setData({ loading: false }); } }, // 播放/暂停 togglePlay() { if (!this.data.audioContext) return; if (this.data.playing) { this.data.audioContext.pause(); } else { this.data.audioContext.play(); } }, // 上一章 prevChapter() { if (this.data.currentIndex > 0) { const prevChapter = this.data.chapters[this.data.currentIndex - 1]; this.setData({ audioId: prevChapter.audioId, currentIndex: this.data.currentIndex - 1, playing: false, currentTime: 0 }); if (this.data.audioContext) { this.data.audioContext.stop(); } this.loadAudio(); } else { wx.showToast({ title: '已经是第一章了', icon: 'none' }); } }, // 下一章 nextChapter() { if (this.data.currentIndex < this.data.chapters.length - 1) { const nextChapter = this.data.chapters[this.data.currentIndex + 1]; this.setData({ audioId: nextChapter.audioId, currentIndex: this.data.currentIndex + 1, playing: false, currentTime: 0 }); if (this.data.audioContext) { this.data.audioContext.stop(); } this.loadAudio(); } else { wx.showToast({ title: '已经是最后一章了', icon: 'none' }); } }, // 调整播放进度 onSeek(e) { const time = e.detail.value; if (this.data.audioContext) { this.data.audioContext.seek(time); this.setData({ currentTime: time }); } }, // 调整播放速度 changeSpeed(e) { const speed = parseFloat(e.detail.value); this.setData({ speed }); if (this.data.audioContext) { this.data.audioContext.playbackRate = speed; } }, // 显示章节列表 showChapterList() { const itemList = this.data.chapters.map((item, index) => `${index + 1}. ${item.chapterTitle}` ); wx.showActionSheet({ itemList, success: (res) => { const chapter = this.data.chapters[res.tapIndex]; this.setData({ audioId: chapter.audioId, currentIndex: res.tapIndex, playing: false, currentTime: 0 }); if (this.data.audioContext) { this.data.audioContext.stop(); } this.loadAudio(); } }); }, // 格式化时间 formatTime(seconds) { if (!seconds || isNaN(seconds)) return '00:00'; const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; } });