first commit
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 频道详情 — 从后端获取频道信息 + 节目列表
|
||||
*
|
||||
* 性能优化:
|
||||
* - 使用 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()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"global-player": "/components/global-player/index",
|
||||
"t-message": "tdesign-miniprogram/message/message"
|
||||
},
|
||||
"navigationBarTitleText": "频道详情"
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
<!-- 频道详情 —— 频道信息头部 + 往期内容列表 -->
|
||||
<view class="detail-page">
|
||||
|
||||
<!-- 频道信息头部 -->
|
||||
<view class="hero" style="background: linear-gradient(135deg, {{domain.bgColor || '#FF9D42'}}, {{domain.bgColorEnd || '#FFB366'}});">
|
||||
<!-- 频道信息 -->
|
||||
<view class="hero-content">
|
||||
<text class="hero-icon">{{domain.cover || domain.icon || '📻'}}</text>
|
||||
<text class="hero-name">{{domain.name}}</text>
|
||||
<text class="hero-tag">{{domain.tag || domain.description || ''}}</text>
|
||||
|
||||
<!-- ═══ 按钮区:根据频道类型和订阅状态分情况 ═══ -->
|
||||
|
||||
<!-- 1. 免费频道 -->
|
||||
<block wx:if="{{isFree}}">
|
||||
<view class="hero-badge free-badge">🎁 永久免费</view>
|
||||
<button class="hero-sub-btn free-btn" bindtap="onSubscribe">
|
||||
<text>▶ 开始收听</text>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!-- 2. VIP专享 -->
|
||||
<block wx:elif="{{isVipOnly}}">
|
||||
<view class="hero-badge vip-badge">👑 VIP专享</view>
|
||||
<button class="hero-sub-btn vip-btn" bindtap="onSubscribe">
|
||||
<text>开通 VIP 解锁</text>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!-- 3. 已订阅且有效 -->
|
||||
<block wx:elif="{{isSubscribed}}">
|
||||
<button class="hero-sub-btn subscribed" bindtap="onSubscribe">
|
||||
<text>✓ 已订阅</text>
|
||||
</button>
|
||||
<text wx:if="{{expiredAt}}" class="hero-expired">有效至 {{expiredAt}}</text>
|
||||
</block>
|
||||
|
||||
<!-- 4. 订阅已过期(重新订阅) -->
|
||||
<block wx:elif="{{isExpired}}">
|
||||
<view class="hero-badge expired-badge">⏰ 订阅已到期</view>
|
||||
<button class="hero-sub-btn renew-btn" bindtap="onSubscribe">
|
||||
<text>续费订阅</text>
|
||||
</button>
|
||||
<text wx:if="{{expiredAt}}" class="hero-expired">已于 {{expiredAt}} 到期</text>
|
||||
</block>
|
||||
|
||||
<!-- 5. 未订阅付费频道 -->
|
||||
<block wx:else>
|
||||
<button class="hero-sub-btn" bindtap="onSubscribe">
|
||||
<text>订阅频道</text>
|
||||
</button>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- 底部波浪装饰 -->
|
||||
<view class="hero-wave"></view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<view class="content-area">
|
||||
|
||||
<!-- 提示条:根据状态动态切换 -->
|
||||
<!-- VIP专享未开通 -->
|
||||
<view wx:if="{{isVipOnly && !isSubscribed}}" class="trial-notice vip-notice" bindtap="onSubscribe">
|
||||
<text class="notice-icon">👑</text>
|
||||
<view class="notice-info">
|
||||
<text class="notice-title">VIP专属频道</text>
|
||||
<text class="notice-desc">开通全频道会员,畅享本频道全部内容及免广告特权</text>
|
||||
</view>
|
||||
<text class="notice-action">去开通 ›</text>
|
||||
</view>
|
||||
|
||||
<!-- 订阅已过期(非免费频道) -->
|
||||
<view wx:elif="{{isExpired && !isFree}}" class="trial-notice expired-notice" bindtap="onSubscribe">
|
||||
<text class="notice-icon">⏰</text>
|
||||
<view class="notice-info">
|
||||
<text class="notice-title">订阅已到期</text>
|
||||
<text class="notice-desc">您的订阅已于 {{expiredAt}} 到期,续费后可继续收听全部内容</text>
|
||||
</view>
|
||||
<text class="notice-action">续费 ›</text>
|
||||
</view>
|
||||
|
||||
<!-- 付费频道未订阅(试听) -->
|
||||
<view wx:elif="{{!isSubscribed && !isFree}}" class="trial-notice" bindtap="onSubscribe">
|
||||
<text class="notice-icon">🔒</text>
|
||||
<view class="notice-info">
|
||||
<text class="notice-title">试听模式</text>
|
||||
<text class="notice-desc">可试听最新一期,订阅后解锁全部历史内容</text>
|
||||
</view>
|
||||
<text class="notice-action">订阅 ›</text>
|
||||
</view>
|
||||
|
||||
<!-- 内容列表标题 -->
|
||||
<view class="list-header">
|
||||
<text class="list-title">内容列表</text>
|
||||
<view class="list-count">{{domainContents.length}} 期</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容列表 -->
|
||||
<view class="list">
|
||||
<view
|
||||
wx:for="{{domainContents}}"
|
||||
wx:key="id"
|
||||
class="list-item {{item._isThisPlaying ? 'playing' : ''}} {{item._isLocked ? 'locked' : ''}}"
|
||||
bindtap="onPlayItem"
|
||||
data-id="{{item.id}}"
|
||||
data-idx="{{index}}"
|
||||
>
|
||||
<!-- 序号 -->
|
||||
<text class="item-index">{{item._displayIndex}}</text>
|
||||
|
||||
<!-- 信息 -->
|
||||
<view class="item-info">
|
||||
<text class="item-title {{item._isThisPlaying ? 'text-primary' : ''}}">{{item.title}}</text>
|
||||
<view class="item-meta">
|
||||
<text>{{item._dateDot}}</text>
|
||||
<text class="meta-dot">·</text>
|
||||
<text>{{item.durationText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 播放按钮 -->
|
||||
<view wx:if="{{!item._isLocked}}" class="item-play-btn {{item._isThisPlaying ? 'active' : ''}}">
|
||||
<image
|
||||
wx:if="{{item._isThisPlaying && isPlaying}}"
|
||||
src="/assets/icons/pause.svg"
|
||||
class="item-play-icon"
|
||||
/>
|
||||
<image
|
||||
wx:else
|
||||
src="/assets/icons/play.svg"
|
||||
class="item-play-icon"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view style="height: 200rpx;"></view>
|
||||
<global-player />
|
||||
<t-message id="t-message" />
|
||||
</view>
|
||||
@@ -0,0 +1,295 @@
|
||||
/* 频道详情页样式 */
|
||||
|
||||
.detail-page {
|
||||
min-height: 100vh;
|
||||
background: #FCFCFC;
|
||||
}
|
||||
|
||||
/* 沉浸式头部 */
|
||||
.hero {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.back-btn {
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
.back-arrow {
|
||||
font-size: 48rpx;
|
||||
color: #FFF;
|
||||
font-weight: 300;
|
||||
margin-top: -4rpx;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 100rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.hero-icon {
|
||||
font-size: 120rpx;
|
||||
margin-bottom: 24rpx;
|
||||
text-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.hero-name {
|
||||
font-size: 52rpx;
|
||||
font-weight: 800;
|
||||
color: #FFF;
|
||||
letter-spacing: -2rpx;
|
||||
margin-bottom: 12rpx;
|
||||
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.hero-tag {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.hero-sub-btn {
|
||||
padding: 16rpx 56rpx;
|
||||
border-radius: 999rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 700;
|
||||
background: #FFF;
|
||||
color: #333;
|
||||
border: none;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
z-index: 10;
|
||||
}
|
||||
.hero-sub-btn::after { border: none; }
|
||||
.hero-sub-btn:active { transform: scale(0.97); }
|
||||
.hero-sub-btn.subscribed {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
color: #FFF;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.3);
|
||||
box-shadow: none;
|
||||
}
|
||||
.hero-expired {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 20rpx;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
|
||||
/* 徽标(免费 / VIP / 到期)*/
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 999rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.free-badge { background: rgba(46, 204, 113, 0.25); color: #FFF; border: 1rpx solid rgba(255,255,255,0.3); }
|
||||
.vip-badge { background: rgba(251, 191, 36, 0.3); color: #FFC; border: 1rpx solid rgba(255,255,255,0.3); }
|
||||
.expired-badge { background: rgba(239, 68, 68, 0.3); color: #FFF; border: 1rpx solid rgba(255,255,255,0.3); }
|
||||
|
||||
/* 按钮变体 */
|
||||
.hero-sub-btn.free-btn { background: #2ECC71; color: #FFF; box-shadow: 0 8rpx 24rpx rgba(46,204,113,0.3); }
|
||||
.hero-sub-btn.vip-btn { background: linear-gradient(135deg, #FBBF24, #D97706); color: #1F2937; box-shadow: 0 8rpx 24rpx rgba(251,191,36,0.35); }
|
||||
.hero-sub-btn.renew-btn { background: linear-gradient(135deg, #FF9D42, #FF7832); color: #FFF; box-shadow: 0 8rpx 24rpx rgba(255,120,50,0.35); }
|
||||
|
||||
/* 波浪 */
|
||||
.hero-wave {
|
||||
position: absolute;
|
||||
bottom: -4rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 64rpx;
|
||||
background: #FCFCFC;
|
||||
border-radius: 100% 100% 0 0;
|
||||
}
|
||||
|
||||
/* 内容区 */
|
||||
.content-area {
|
||||
padding: 0 32rpx;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 试听提示 */
|
||||
.trial-notice {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
background: var(--color-primary-light);
|
||||
border: 1rpx solid rgba(255, 157, 66, 0.2);
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
/* VIP提示(金色) */
|
||||
.vip-notice {
|
||||
background: rgba(251, 191, 36, 0.08);
|
||||
border-color: rgba(251, 191, 36, 0.3);
|
||||
}
|
||||
/* 到期提示(红色) */
|
||||
.expired-notice {
|
||||
background: rgba(239, 68, 68, 0.06);
|
||||
border-color: rgba(239, 68, 68, 0.2);
|
||||
}
|
||||
.notice-action {
|
||||
flex-shrink: 0;
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
margin-left: 8rpx;
|
||||
align-self: center;
|
||||
}
|
||||
.notice-icon {
|
||||
font-size: 32rpx;
|
||||
margin-right: 16rpx;
|
||||
flex-shrink: 0;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
.notice-info {
|
||||
flex: 1;
|
||||
}
|
||||
.notice-title {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
.notice-desc {
|
||||
display: block;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
margin-top: 6rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 列表头 */
|
||||
.list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16rpx 0 24rpx;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
background: rgba(252, 252, 252, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.04);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.list-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
.list-count {
|
||||
margin-left: 12rpx;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
background: #F5F5F5;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 999rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 列表项 */
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-radius: 32rpx;
|
||||
border: 1rpx solid #F5F5F5;
|
||||
background: #FFF;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.02);
|
||||
margin-bottom: 16rpx;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.list-item:active {
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.list-item.playing {
|
||||
background: rgba(255, 157, 66, 0.06);
|
||||
border-color: rgba(255, 157, 66, 0.15);
|
||||
}
|
||||
.list-item.locked {
|
||||
opacity: 0.45;
|
||||
filter: grayscale(0.3);
|
||||
}
|
||||
|
||||
.item-index {
|
||||
width: 72rpx;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
color: #DDD;
|
||||
font-style: italic;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
flex: 1;
|
||||
padding-right: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.item-title {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.item-title.text-primary {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
.item-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8rpx;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
font-weight: 500;
|
||||
}
|
||||
.meta-dot {
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
|
||||
.item-play-btn {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
background: #F5F5F5;
|
||||
border: 1rpx solid #EEE;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.item-play-btn.active {
|
||||
background: var(--color-primary);
|
||||
border-color: transparent;
|
||||
box-shadow: 0 4rpx 16rpx rgba(255, 157, 66, 0.3);
|
||||
}
|
||||
.item-play-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
.item-play-btn.active .item-play-icon {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
Reference in New Issue
Block a user