/** * 收听历史 — 历史 / 收藏 两 Tab */ const app = getApp() const api = require('../../utils/api') const util = require('../../utils/util') Page({ data: { tab: 'history', historyList: [], isPlaying: false, loading: true, channelFilters: [], selectedChannel: '全部' }, _allHistoryList: [], onShow() { const self = this const gd = app.globalData // 未登录则先登录 if (!gd.isLoggedIn || !gd.token) { app.login().then(function () { self._refresh() }).catch(function () { self.setData({ loading: false }) wx.showToast({ title: '请先登录', icon: 'none' }) }) } else { this._refresh() } this._onPlayerChange = () => this._updatePlayState() app.on('playerStateChange', this._onPlayerChange) }, onHide() { if (this._onPlayerChange) app.off('playerStateChange', this._onPlayerChange) }, setTab(e) { const tab = e.currentTarget.dataset.val if (tab === this.data.tab) return this.setData({ tab, historyList: [], loading: true, channelFilters: [], selectedChannel: '全部' }) this._allHistoryList = [] this._refresh() }, _refresh() { if (this.data.tab === 'history') { this._loadHistory() } else if (this.data.tab === 'favorite') { this._loadFavorites() } else { this._loadLikes() } }, _loadHistory() { const self = this const gd = app.globalData api.getHistoryList({ current: 1, pageSize: 30 }).then(function (res) { if (res.code === 200 && res.data) { var list = (res.data.list || []).map(function (item) { var program = item.program || {} var channel = program.channel || null // 历史用 item.duration(记录收听时长),优先级高于 program.duration var dur = item.duration || program.duration || 0 var bgColors = ['#FFE8CC', '#FFF0E0', '#FFE4D6', '#FFF3DC', '#FFE9F0'] var cid = program.channelId || '' var colorIdx = cid ? (cid.charCodeAt(cid.length - 1) % bgColors.length) : 0 return { id: program.id, title: program.title || '未知节目', channelId: program.channelId || '', content: program.content || '', audioId: program.audioId || '', duration: dur, _domainName: channel ? (channel.name || '') : '', _icon: program.cover || (channel && channel.cover) || '📻', _bgColor: bgColors[colorIdx], _friendlyDate: util.getFriendlyDate(item.createdAtStr ? item.createdAtStr.substring(0, 10) : ''), durationText: dur > 0 ? util.formatTime(dur) : '', _progress: item.progress || 0, _isThisPlaying: gd.activeContent && gd.activeContent.id === program.id } }) self.setData({ historyList: list, isPlaying: gd.isPlaying, loading: false }) self._allHistoryList = list self._extractChannelFilters(list) } else { self.setData({ historyList: [], loading: false }) } }).catch(function (err) { console.error('[History] 加载历史失败:', err) self.setData({ loading: false }) }) }, _loadFavorites() { const self = this const gd = app.globalData api.getFavoriteList({ current: 1, pageSize: 30 }).then(function (res) { if (res.code === 200 && res.data) { var list = (res.data.list || []).map(function (item) { // program 嵌套在 item.program 下,channel 可能为 null var program = item.program || {} var channel = program.channel || null var dur = program.duration || 0 // 根据 channelId 末位生成固定暖色,增加视觉区分 var bgColors = ['#FFE8CC', '#FFF0E0', '#FFE4D6', '#FFF3DC', '#FFE9F0'] var cid = program.channelId || '' var colorIdx = cid ? (cid.charCodeAt(cid.length - 1) % bgColors.length) : 0 return { id: program.id, title: program.title || '未知节目', channelId: program.channelId || '', content: program.content || '', audioId: program.audioId || '', duration: dur, // channel 为 null 时不显示频道名 _domainName: channel ? (channel.name || '') : '', _icon: program.cover || (channel && channel.cover) || '📻', _bgColor: bgColors[colorIdx], // 收藏时间用 item.createdAtStr _friendlyDate: util.getFriendlyDate(item.createdAtStr ? item.createdAtStr.substring(0, 10) : ''), // duration 为 0 则不显示时长 durationText: dur > 0 ? util.formatTime(dur) : '', _isThisPlaying: gd.activeContent && gd.activeContent.id === program.id } }) self.setData({ historyList: list, isPlaying: gd.isPlaying, loading: false }) self._allHistoryList = list self._extractChannelFilters(list) } else { self.setData({ historyList: [], loading: false }) } }).catch(function (err) { console.error('[History] 加载收藏失败:', err) self.setData({ loading: false }) }) }, _loadLikes() { const self = this const gd = app.globalData api.getLikeList({ current: 1, pageSize: 30 }).then(function (res) { if (res.code === 200 && res.data) { var list = (res.data.list || []).map(function (item) { // RadioLike → program → channel (可能为 null) var program = item.program || {} var channel = program.channel || null // duration 为 0 时不显示时长 var dur = program.duration || 0 // 从 channelId 生成一个固定暖色背景,增加视觉区分 var bgColors = ['#FFE8CC', '#FFF0E0', '#FFE4D6', '#FFF3DC', '#FFE9F0'] var cid = program.channelId || '' var colorIdx = cid ? (cid.charCodeAt(cid.length - 1) % bgColors.length) : 0 return { id: program.id, title: program.title || '未知节目', channelId: program.channelId || '', content: program.content || '', audioId: program.audioId || '', duration: dur, // channel 为 null 时频道名不显示 _domainName: channel ? (channel.name || '') : '', _icon: program.cover || (channel && channel.cover) || '📻', _bgColor: bgColors[colorIdx], // 显示"点赞时间",用 item.createdAtStr(点赞时间) _friendlyDate: util.getFriendlyDate(item.createdAtStr ? item.createdAtStr.substring(0, 10) : ''), // duration 为 0 则不显示时长,避免展示 "00:00" durationText: dur > 0 ? util.formatTime(dur) : '', _isLiked: true, _isThisPlaying: gd.activeContent && gd.activeContent.id === program.id } }) self.setData({ historyList: list, isPlaying: gd.isPlaying, loading: false }) self._allHistoryList = list self._extractChannelFilters(list) } else { self.setData({ historyList: [], loading: false }) } }).catch(function (err) { console.error('[History] 加载点赞失败:', err) self.setData({ loading: false }) }) }, _updatePlayState() { var gd = app.globalData var list = this.data.historyList.map(function (item) { return Object.assign({}, item, { _isThisPlaying: gd.activeContent && gd.activeContent.id === item.id }) }) this.setData({ historyList: list, isPlaying: gd.isPlaying }) }, _extractChannelFilters(list) { var names = {} list.forEach(function (item) { if (item._domainName) names[item._domainName] = true }) var filters = ['全部'].concat(Object.keys(names).sort()) this.setData({ channelFilters: filters }) }, onChannelFilter(e) { var name = e.currentTarget.dataset.name this.setData({ selectedChannel: name }) this._applyChannelFilter(name) }, _applyChannelFilter(name) { if (name === '全部') { this.setData({ historyList: this._allHistoryList }) } else { var filtered = this._allHistoryList.filter(function (item) { return item._domainName === name }) this.setData({ historyList: filtered }) } }, onPlay(e) { const id = e.currentTarget.dataset.id const gd = app.globalData if (gd.activeContent && gd.activeContent.id === id) { app.togglePlay() return } // 从列表中找到基础信息 var base = null for (var i = 0; i < this.data.historyList.length; i++) { if (this.data.historyList[i].id === id) { base = this.data.historyList[i] break } } if (!base) return // 拉取完整节目详情(含 audio.url)再播放 wx.showLoading({ title: '加载中' }) api.getProgramDetail(id).then(function (res) { wx.hideLoading() if (res.code === 200 && res.data) { app.playContent(Object.assign({}, base, res.data)) } else { wx.showToast({ title: '加载失败', icon: 'none' }) } }).catch(function () { wx.hideLoading() wx.showToast({ title: '网络异常', icon: 'none' }) }) }, onDeleteItem(e) { const id = e.currentTarget.dataset.id const tab = this.data.tab const self = this // 赞过 tab 点击爱心可取消点赞 if (tab === 'like') { wx.showModal({ title: '取消点赞', content: '确定取消对这个节目的点赞吗?', success(res) { if (!res.confirm) return api.toggleLike(id).then(function (r) { if (r.code === 200) { var list = self.data.historyList.filter(function (item) { return item.id !== id }) self.setData({ historyList: list }) } else { wx.showToast({ title: r.msg || '操作失败', icon: 'none' }) } }).catch(function () { wx.showToast({ title: '网络异常', icon: 'none' }) }) } }) return } const label = tab === 'history' ? '历史' : '收藏' wx.showModal({ title: '删除' + label, content: '确定删除这条' + label + '吗?', success(res) { if (!res.confirm) return const fn = tab === 'history' ? api.deleteHistory(id) : api.removeFavorite(id) fn.then(function (r) { if (r.code === 200) { var list = self.data.historyList.filter(function (item) { return item.id !== id }) self.setData({ historyList: list }) } else { wx.showToast({ title: r.msg || '删除失败', icon: 'none' }) } }).catch(function () { wx.showToast({ title: '网络异常', icon: 'none' }) }) } }) }, onClear() { const self = this const tab = this.data.tab var label = '' var fn = null if (tab === 'history') { label = '收听历史' fn = api.deleteAllHistory() } else if (tab === 'favorite') { label = '全部收藏' fn = api.removeAllFavorites() } else if (tab === 'like') { label = '全部点赞' fn = api.removeAllLikes() } if (!fn) return wx.showModal({ title: '清空' + label, content: '确定要清空所有' + label + '吗?', success(res) { if (!res.confirm) return fn.then(function (r) { if (r.code === 200) { self.setData({ historyList: [] }) } else { wx.showToast({ title: r.msg || '操作失败', icon: 'none' }) } }).catch(function () { wx.showToast({ title: '网络异常', icon: 'none' }) }) } }) }, goDiscover() { wx.switchTab({ url: '/pages/discover/index' }) }, goHome() { wx.switchTab({ url: '/pages/index/index' }) }, goVip() { wx.navigateTo({ url: '/pages/vip/index' }) } })