/** * 播放器详情页 * 大封面、进度条、倍速切换、播放控制 * 从 globalData.activeContent 获取当前节目 */ const app = getApp() const api = require('../../utils/api') const util = require('../../utils/util') Page({ data: { domain: {}, activeContent: null, isPlaying: false, isVip: false, currentTime: 0, duration: 0, currentTimeText: '00:00', durationText: '00:00', displayDate: '', playbackRate: 1.0, statusBarHeight: 0, showTranscript: false, // 封面 ⇔ 文案切换 showSpeedSheet: false, speedItems: [ { label: '0.5x' }, { label: '0.75x' }, { label: '1.0x' }, { label: '1.25x' }, { label: '1.5x' }, { label: '2.0x' } ] }, _isSeeking: false, onLoad() { }, onShow() { this._syncState() // 监听播放状态 this._onPlayerChange = (state) => { if (this._isSeeking) return this.setData({ activeContent: state.activeContent, isPlaying: state.isPlaying, playbackRate: state.playbackRate }) this._updateDomain() } // 监听时间更新 this._onTimeUpdate = (data) => { if (this._isSeeking) return this.setData({ currentTime: data.currentTime, duration: data.duration || this.data.duration, currentTimeText: util.formatTime(data.currentTime), durationText: util.formatTime(data.duration || this.data.duration) }) } app.on('playerStateChange', this._onPlayerChange) app.on('timeUpdate', this._onTimeUpdate) }, onHide() { if (this._onPlayerChange) app.off('playerStateChange', this._onPlayerChange) if (this._onTimeUpdate) app.off('timeUpdate', this._onTimeUpdate) }, /** * 同步当前状态 */ _syncState() { const gd = app.globalData const content = gd.activeContent if (!content) { wx.navigateBack() return } var dateStr = '' if (content.createdAt) { dateStr = content.createdAt.substring(0, 10).replace(/-/g, '.') } else if (content.date) { dateStr = util.dateToDot(content.date) } this.setData({ activeContent: content, isPlaying: gd.isPlaying, isVip: gd.isVip, currentTime: gd.currentTime, duration: gd.duration || content.duration, currentTimeText: util.formatTime(gd.currentTime), durationText: util.formatTime(gd.duration || content.duration), displayDate: dateStr, playbackRate: gd.playbackRate, statusBarHeight: gd.statusBarHeight || 0 }) this._updateDomain() }, /** * 获取频道信息 — 从后端 API 获取 */ _updateDomain() { const content = this.data.activeContent if (!content) return var channelId = content.channelId || (content.channel && content.channel.id) if (!channelId) { // 如果节目数据中直接包含 channel 信息 if (content.channel) { this.setData({ domain: content.channel }) } return } // 如果已经加载过且 channelId 没变,跳过 if (this.data.domain && this.data.domain.id === channelId) return var self = this api.getChannelDetail(channelId).then(function (res) { if (res.code === 200 && res.data) { self.setData({ domain: res.data }) } }).catch(function (err) { console.error('[Player] 获取频道信息失败:', err) }) }, /** * 播放/暂停 */ onTogglePlay() { app.togglePlay() }, /** * 进度条拖动中 */ onSliderChanging(e) { this._isSeeking = true this.setData({ currentTime: e.detail.value, currentTimeText: util.formatTime(e.detail.value) }) }, /** * 进度条拖动完成 → 跳转播放 */ onSliderChange(e) { this._isSeeking = false app.seekTo(e.detail.value) }, /** * 快退 15 秒 */ onBackward() { const newTime = Math.max(0, this.data.currentTime - 15) app.seekTo(newTime) }, /** * 快进 15 秒 */ onForward() { const newTime = Math.min(this.data.duration, this.data.currentTime + 15) app.seekTo(newTime) }, /** * 倍速设置(VIP 功能) */ onSpeed() { if (!this.data.isVip) { wx.showModal({ title: '会员提示', content: '倍速播放是会员专属功能,是否前往开通?', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/vip/index' }) } } }) } else { this.setData({ showSpeedSheet: true }) } }, onSpeedSelect(e) { const label = this.data.speedItems[e.detail.index].label const rate = parseFloat(label) app.setPlaybackRate(rate) this.setData({ showSpeedSheet: false, playbackRate: rate }) }, onSpeedCancel() { this.setData({ showSpeedSheet: false }) }, /** * 下载(VIP 功能) */ onDownload() { if (!this.data.isVip) { wx.showModal({ title: '会员提示', content: '音频下载是会员专属功能,是否前往开通?', success: (res) => { if (res.confirm) { wx.navigateTo({ url: '/pages/vip/index' }) } } }) } else { wx.showToast({ title: '下载功能开发中', icon: 'none' }) } }, /** * 查看文案 */ onTranscript() { const content = this.data.activeContent if (content && content.content) { wx.showModal({ title: '完整文案', content: content.content, showCancel: false }) } }, /** * 点击中央 Banner:封面 ⇔ 文案切换 */ onBannerTap() { this.setData({ showTranscript: !this.data.showTranscript }) }, onLike() { const content = this.data.activeContent if (!content) return api.toggleLike({ contentId: content.id }).then(function (res) { wx.showToast({ title: res.code === 200 ? '已收藏 ♥' : '操作失败', icon: 'none' }) }).catch(function () { wx.showToast({ title: '网络异常', icon: 'none' }) }) }, onShare() { wx.showToast({ title: '分享功能开发中', icon: 'none' }) }, goBack() { wx.navigateBack() } })