Files
2026-04-28 10:32:19 +08:00

256 lines
8.5 KiB
JavaScript

/**
* 频道详情 — 从后端获取频道信息 + 节目列表
*
* 性能优化:
* - 使用 channel detail 返回的 hasSubscribed 字段,不再单独请求订阅列表
* - 展示 expiredAt 字段标记订阅到期时间
*/
const app = getApp()
const api = require('../../utils/api')
const util = require('../../utils/util')
Page({
data: {
domain: {},
isSubscribed: false,
isExpired: false,
expiredAt: '',
isFree: false,
isVipOnly: false,
isVip: false,
canPlay: false,
domainContents: [],
isPlaying: false,
loading: true
},
onLoad(options) {
const id = options.id
this._domainId = id
this._loadChannelDetail()
},
onShow() {
this._loadPrograms()
this._onPlayerChange = () => this._updatePlayState()
this._onSubChange = () => this._loadChannelDetail()
this._onVipChange = () => this._loadChannelDetail()
app.on('playerStateChange', this._onPlayerChange)
app.on('subscriptionChange', this._onSubChange)
app.on('vipChange', this._onVipChange)
},
onHide() {
if (this._onPlayerChange) app.off('playerStateChange', this._onPlayerChange)
if (this._onSubChange) app.off('subscriptionChange', this._onSubChange)
if (this._onVipChange) app.off('vipChange', this._onVipChange)
},
/**
* 加载频道详情
* hasSubscribed / expiredAt 都从这个接口返回
*/
_loadChannelDetail() {
const self = this
api.getChannelDetail(this._domainId).then(function (res) {
if (res.code === 200 && res.data) {
const ch = res.data
const isFree = ch.isFree === 1
var expiredAt = ''
var isExpired = false
var isSubscribed = false
if (!isFree) {
if (ch.expiredAt) {
expiredAt = ch.expiredAt.substring(0, 10).replace(/-/g, '.')
isExpired = new Date(ch.expiredAt) < new Date()
}
isSubscribed = ch.hasSubscribed === 1 && !isExpired
}
// 可播放:VIP 或免费频道或已订阅
const canPlay = app.globalData.isVip || isFree || isSubscribed
self.setData({
domain: ch,
isSubscribed,
isExpired,
expiredAt,
isFree,
isVipOnly: ch.isVipOnly === 1,
isVip: app.globalData.isVip,
canPlay
})
// 详情加载后刷新节目列表(更新 _isLocked 状态)
self._loadPrograms()
}
}).catch(function (err) {
console.error('[ChannelDetail] 加载频道详情失败:', err)
})
},
/**
* 加载节目列表(静默刷新,不重复请求订阅状态)
*/
_loadPrograms() {
const self = this
api.getProgramList({ channelId: self._domainId, current: 1, pageSize: 50 })
.then(function (progRes) {
var contents = []
if (progRes.code === 200 && progRes.data) {
contents = progRes.data.list || progRes.data || []
}
var gd = app.globalData
var canPlay = self.data.canPlay
var total = contents.length
contents = contents.map(function (item, idx) {
return Object.assign({}, item, {
_displayIndex: String(total - idx).padStart(2, '0'),
_dateDot: item.createdAt ? item.createdAt.substring(0, 10).replace(/-/g, '.') : '',
durationText: item.duration > 0 ? util.formatTime(item.duration) : '',
_isThisPlaying: gd.activeContent && gd.activeContent.id === item.id,
_isLocked: !canPlay // 所有集全部锁定,没有试听
})
})
self.setData({
domainContents: contents,
isPlaying: gd.isPlaying,
loading: false
})
})
.catch(function (err) {
console.error('[ChannelDetail] 加载节目失败:', err)
self.setData({ loading: false })
})
},
/**
* 仅更新播放状态(不重新请求)
*/
_updatePlayState() {
var gd = app.globalData
var contents = this.data.domainContents.map(function (item) {
return Object.assign({}, item, {
_isThisPlaying: gd.activeContent && gd.activeContent.id === item.id
})
})
this.setData({ domainContents: contents, isPlaying: gd.isPlaying })
},
onPlayItem(e) {
const id = e.currentTarget.dataset.id
const gd = app.globalData
// 核心权限判断:VIP || 免费频道 || 已订阅
if (!this.data.canPlay) {
// 引导到支付页
this.onSubscribe()
return
}
var content = null
for (var i = 0; i < this.data.domainContents.length; i++) {
if (this.data.domainContents[i].id === id) {
content = this.data.domainContents[i]
break
}
}
if (!content) return
if (gd.activeContent && gd.activeContent.id === id) {
app.togglePlay()
} else {
app.playContent(content)
}
},
onSubscribe() {
const id = this._domainId
const domain = this.data.domain
// 已可播放(VIP / 免费 / 已订阅)——正常情况下不会触发此方法
if (this.data.canPlay) {
wx.showToast({ title: '您已可收听该频道', icon: 'none' })
return
}
// VIP专享频道:不支持单独订阅,必须开通 VIP
if (domain.isVipOnly === 1) {
wx.navigateTo({ url: '/pages/vip/index' })
return
}
// 免费频道(理论上不会到这里,安全先)
if (domain.isFree === 1) {
wx.showToast({ title: '免费频道,直接收听!', icon: 'none' })
return
}
// 付费频道(未订阅 / 已过期)——跳转订阅/支付页
var params = 'channelId=' + id
+ '&channelName=' + encodeURIComponent(domain.name || '')
+ '&monthlyPrice=' + (domain.monthlyPrice || 0)
+ '&quarterlyPrice=' + (domain.quarterlyPrice || 0)
+ '&annualPrice=' + (domain.annualPrice || 0)
wx.navigateTo({ url: '/pages/vip/index?' + params })
},
goFirstProgram() {
// 权限保护:不可播放时引导到订阅/VIP
if (!this.data.canPlay) {
this.onSubscribe()
return
}
var list = this.data.domainContents
if (list && list.length > 0) {
var first = list[0]
if (app.globalData.activeContent && app.globalData.activeContent.id === first.id) {
app.togglePlay()
} else {
app.playContent(first)
}
} else {
wx.showToast({ title: '暂无节目', icon: 'none' })
}
},
/** 续订:直接跳支付页,不走 canPlay 检查 */
onRenew() {
const id = this._domainId
const domain = this.data.domain
var params = 'channelId=' + id
+ '&channelName=' + encodeURIComponent(domain.name || '')
+ '&monthlyPrice=' + (domain.monthlyPrice || 0)
+ '&quarterlyPrice=' + (domain.quarterlyPrice || 0)
+ '&annualPrice=' + (domain.annualPrice || 0)
wx.navigateTo({ url: '/pages/vip/index?' + params })
},
goBack() {
wx.navigateBack()
},
// ===================== 分享钩子 =====================
onShareAppMessage() {
const domain = this.data.domain || {}
return {
title: domain.name ? '听全声汇频道:' + domain.name : '全声汇 - 精选频道',
path: '/pages/channel-detail/index?id=' + this._domainId,
imageUrl: ''
}
},
onShareTimeline() {
const domain = this.data.domain || {}
return {
title: domain.name ? '听全声汇频道:' + domain.name : '全声汇 - 精选频道',
query: 'id=' + this._domainId,
imageUrl: ''
}
}
})