const utils = require("../../../utils/utils"); Page({ data: { title: "音乐", data: {}, playlist: [], currentIndex: 0, value: "00:00", duration: "00:00", percent: 0, isPlay: false, isSingleLoop: false, isShow: false, isClosing: false }, onLoad(options) { let current = {}; try { current = JSON.parse(decodeURIComponent(options.data || "{}")); } catch (error) { console.error("资源参数解析失败", error); } this.setData({ data: current, playlist: current.resourceUrl ? [current] : [], title: current.id == 1 ? "口令" : "音乐" }); this.createAudioContext(); if (current.resourceUrl) { this.loadTrack(current, false); } const eventChannel = this.getOpenerEventChannel && this.getOpenerEventChannel(); if (eventChannel && eventChannel.on) { eventChannel.on("setPlaylist", ({ playlist = [], currentIndex = 0 }) => { if (!playlist.length) return; const safeIndex = Math.min(Math.max(Number(currentIndex) || 0, 0), playlist.length - 1); this.setData({ playlist, currentIndex: safeIndex, data: playlist[safeIndex] }); }); } }, createAudioContext() { this.audioCtx = wx.createInnerAudioContext(); this.audioCtx.obeyMuteSwitch = false; this.audioCtx.onCanplay(() => this.updateProgress()); this.audioCtx.onTimeUpdate(() => this.updateProgress()); this.audioCtx.onPlay(() => this.setData({ isPlay: true })); this.audioCtx.onPause(() => this.setData({ isPlay: false })); this.audioCtx.onStop(() => this.setData({ isPlay: false })); this.audioCtx.onEnded(() => { if (!this.data.isSingleLoop) this.changeTrack(1, true); }); this.audioCtx.onError((error) => { console.error("音频播放失败", error); this.setData({ isPlay: false }); wx.showToast({ title: "音频加载失败,请稍后重试", icon: "none" }); }); }, loadTrack(track, autoplay = true) { if (!track || !track.resourceUrl || !this.audioCtx) return; this.audioCtx.stop(); this.audioCtx.loop = this.data.isSingleLoop; this.audioCtx.src = track.resourceUrl; this.setData({ data: track, value: "00:00", duration: "00:00", percent: 0, isPlay: autoplay }); if (autoplay) this.audioCtx.play(); }, updateProgress() { if (!this.audioCtx) return; const currentTime = Number(this.audioCtx.currentTime) || 0; const duration = Number(this.audioCtx.duration) || 0; this.setData({ value: utils.formatTimeStr(currentTime), duration: utils.formatTimeStr(duration), percent: duration ? Math.min((currentTime / duration) * 100, 100) : 0 }); }, btnCilck() { if (!this.audioCtx || !this.data.data.resourceUrl) return; this.data.isPlay ? this.audioCtx.pause() : this.audioCtx.play(); }, playPrevious() { this.changeTrack(-1, true); }, playNext() { this.changeTrack(1, true); }, changeTrack(step, autoplay) { const { playlist, currentIndex } = this.data; if (!playlist.length) return; const nextIndex = (currentIndex + step + playlist.length) % playlist.length; this.setData({ currentIndex: nextIndex }, () => this.loadTrack(playlist[nextIndex], autoplay)); }, selectTrack(e) { const index = Number(e.currentTarget.dataset.index); if (!Number.isInteger(index) || !this.data.playlist[index]) return; this.setData({ currentIndex: index }, () => { this.loadTrack(this.data.playlist[index], true); this.hideList(); }); }, toggleLoop() { const isSingleLoop = !this.data.isSingleLoop; if (this.audioCtx) this.audioCtx.loop = isSingleLoop; this.setData({ isSingleLoop }); wx.showToast({ title: isSingleLoop ? "单曲循环" : "列表循环", icon: "none" }); }, seekAudio(e) { if (!this.audioCtx || !this.audioCtx.duration) return; wx.createSelectorQuery().in(this).select("#audio-progress").boundingClientRect((rect) => { if (!rect || !rect.width) return; const ratio = Math.min(Math.max((e.detail.x - rect.left) / rect.width, 0), 1); this.audioCtx.seek(this.audioCtx.duration * ratio); }).exec(); }, showList() { if (this.closeTimer) { clearTimeout(this.closeTimer); this.closeTimer = null; } this.setData({ isShow: true, isClosing: false }); }, hideList() { if (!this.data.isShow || this.data.isClosing) return; this.setData({ isClosing: true }); this.closeTimer = setTimeout(() => { this.setData({ isShow: false, isClosing: false }); this.closeTimer = null; }, 240); }, preventClose() {}, onUnload() { if (this.closeTimer) clearTimeout(this.closeTimer); if (this.audioCtx) { this.audioCtx.stop(); if (this.audioCtx.destroy) this.audioCtx.destroy(); this.audioCtx = null; } } });