/** * 频道详情 — 从后端获取频道信息 + 节目列表 * * 性能优化: * - 使用 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, // 快捷字段,避免模板 domain.isFree isVipOnly: 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._loadPrograms() app.on('playerStateChange', this._onPlayerChange) app.on('subscriptionChange', this._onSubChange) }, onHide() { if (this._onPlayerChange) app.off('playerStateChange', this._onPlayerChange) if (this._onSubChange) app.off('subscriptionChange', this._onSubChange) }, /** * 加载频道详情 * 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 } self.setData({ domain: ch, isSubscribed, isExpired, expiredAt, isFree, isVipOnly: ch.isVipOnly === 1 }) } }).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 isSubscribed = self.data.isSubscribed var isFree = self.data.domain.isFree === 1 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: util.formatTime(item.duration || 0), _isThisPlaying: gd.activeContent && gd.activeContent.id === item.id, _isLocked: !isSubscribed && !isFree && idx > 0 }) }) 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 idx = parseInt(e.currentTarget.dataset.idx) const gd = app.globalData if (!this.data.isSubscribed && !(this.data.domain.isFree === 1) && idx > 0) { wx.showToast({ title: '请先订阅该频道以解锁往期内容', icon: 'none' }) 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 // 已订阅 → 已在订阅中,无需操作 if (this.data.isSubscribed) { wx.showToast({ title: '您已订阅该频道', icon: 'none' }) return } // 免费频道 → 直接收听 if (domain.isFree === 1) { wx.showToast({ title: '免费频道,直接收听!', icon: 'none' }) return } // VIP专享且未开通 → VIP页 if (domain.isVipOnly === 1 && !app.globalData.isVip) { wx.navigateTo({ url: '/pages/vip/index' }) 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 }) }, goBack() { wx.navigateBack() } })