| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- // 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')}`;
- }
- });
|