846 行
21 KiB
Vue
846 行
21 KiB
Vue
<template>
|
||
<view class="coupon-page fc-page">
|
||
<!-- 自定义导航栏:深绿渐变沉浸式 -->
|
||
<fc-navbar title="优惠券中心" theme="gradient" :show-back="true" />
|
||
|
||
<!-- 顶部深绿沉浸底座 -->
|
||
<view class="coupon-page__backdrop">
|
||
<view class="coupon-page__backdrop-ambient"></view>
|
||
</view>
|
||
|
||
<!-- 顶部主标签页(我的卡券 vs 领券中心) -->
|
||
<view class="coupon-page__tabs-wrap">
|
||
<view class="coupon-page__tabs">
|
||
<view
|
||
class="coupon-page__tab-item"
|
||
:class="{ 'coupon-page__tab-item--active': mainTab === 'mine' }"
|
||
@click="switchMainTab('mine')"
|
||
>
|
||
<text class="coupon-page__tab-text">我的卡券</text>
|
||
<text v-if="myCouponCount > 0" class="coupon-page__tab-badge">{{ myCouponCount }}</text>
|
||
<view v-if="mainTab === 'mine'" class="coupon-page__tab-line"></view>
|
||
</view>
|
||
<view
|
||
class="coupon-page__tab-item"
|
||
:class="{ 'coupon-page__tab-item--active': mainTab === 'market' }"
|
||
@click="switchMainTab('market')"
|
||
>
|
||
<text class="coupon-page__tab-text">领券中心</text>
|
||
<view v-if="marketAvailableCount > 0" class="coupon-page__tab-dot"></view>
|
||
<view v-if="mainTab === 'market'" class="coupon-page__tab-line"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 二级筛选栏(仅在「我的卡券」显示:全部 / 未使用 / 已使用 / 已过期) -->
|
||
<view v-if="mainTab === 'mine'" class="coupon-page__sub-filter">
|
||
<view
|
||
v-for="f in subFilters"
|
||
:key="f.key"
|
||
class="coupon-page__filter-chip"
|
||
:class="{ 'coupon-page__filter-chip--active': subStatus === f.key }"
|
||
@click="switchSubStatus(f.key)"
|
||
>
|
||
<text class="coupon-page__filter-chip-text">{{ f.label }}</text>
|
||
<text v-if="f.count > 0" class="coupon-page__filter-chip-num">({{ f.count }})</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 卡券列表主体容器 -->
|
||
<view class="coupon-page__body">
|
||
<!-- 骨架/加载占位 -->
|
||
<view v-if="loading" class="coupon-page__loading">
|
||
<text class="coupon-page__loading-text">正在加载优惠券...</text>
|
||
</view>
|
||
|
||
<!-- 1. 我的卡券列表 -->
|
||
<view v-else-if="mainTab === 'mine'">
|
||
<view v-if="filteredMyCoupons.length > 0" class="coupon-list">
|
||
<view
|
||
v-for="item in filteredMyCoupons"
|
||
:key="item.id"
|
||
class="coupon-card"
|
||
:class="[`coupon-card--${item.status}`]"
|
||
>
|
||
<!-- 卡片左侧:金额与门槛 -->
|
||
<view class="coupon-card__left">
|
||
<view class="coupon-card__amount-row">
|
||
<text class="coupon-card__currency">¥</text>
|
||
<text class="coupon-card__amount">{{ formatAmount(item.amount) }}</text>
|
||
</view>
|
||
<text class="coupon-card__condition">
|
||
{{ item.minAmount > 0 ? `满${item.minAmount}元可用` : '无门槛' }}
|
||
</text>
|
||
</view>
|
||
|
||
<!-- 中间齿孔分隔 -->
|
||
<view class="coupon-card__divider">
|
||
<view class="coupon-card__hole coupon-card__hole--top"></view>
|
||
<view class="coupon-card__dash"></view>
|
||
<view class="coupon-card__hole coupon-card__hole--bottom"></view>
|
||
</view>
|
||
|
||
<!-- 卡片右侧:信息与操作 -->
|
||
<view class="coupon-card__right">
|
||
<view class="coupon-card__info">
|
||
<view class="coupon-card__title-row">
|
||
<text class="coupon-card__tag">{{ getCouponTypeLabel(item.type) }}</text>
|
||
<text class="coupon-card__title fc-ellipsis">{{ item.name || '通用优惠券' }}</text>
|
||
</view>
|
||
<text class="coupon-card__date">
|
||
{{ item.expireAt ? `有效期至 ${formatDate(item.expireAt)}` : '永久有效' }}
|
||
</text>
|
||
</view>
|
||
|
||
<!-- 右侧操作/状态印章 -->
|
||
<view class="coupon-card__action">
|
||
<!-- 未使用态:去使用按钮(春绿底墨绿字) -->
|
||
<view
|
||
v-if="item.status === 'unused'"
|
||
class="coupon-card__btn coupon-card__btn--use"
|
||
@click="goUseCoupon(item)"
|
||
>
|
||
<text class="coupon-card__btn-text">去使用</text>
|
||
</view>
|
||
<!-- 已使用印章 -->
|
||
<view v-else-if="item.status === 'used'" class="coupon-card__stamp coupon-card__stamp--used">
|
||
<text class="coupon-card__stamp-text">已使用</text>
|
||
</view>
|
||
<!-- 已过期印章 -->
|
||
<view v-else class="coupon-card__stamp coupon-card__stamp--expired">
|
||
<text class="coupon-card__stamp-text">已过期</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 我的卡券空状态 -->
|
||
<fc-empty
|
||
v-else
|
||
icon="inbox"
|
||
:text="emptyTextMine"
|
||
btn-text="去领券中心"
|
||
@action="switchMainTab('market')"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 2. 领券中心列表 -->
|
||
<view v-else-if="mainTab === 'market'">
|
||
<view v-if="marketCoupons.length > 0" class="coupon-list">
|
||
<view
|
||
v-for="c in marketCoupons"
|
||
:key="c.id"
|
||
class="coupon-card"
|
||
:class="{ 'coupon-card--received': c.received || c.left === 0 }"
|
||
>
|
||
<!-- 卡片左侧:面额与门槛 -->
|
||
<view class="coupon-card__left">
|
||
<view class="coupon-card__amount-row">
|
||
<text class="coupon-card__currency">¥</text>
|
||
<text class="coupon-card__amount">{{ formatAmount(c.amount) }}</text>
|
||
</view>
|
||
<text class="coupon-card__condition">
|
||
{{ c.minAmount > 0 ? `满${c.minAmount}元可用` : '无门槛' }}
|
||
</text>
|
||
</view>
|
||
|
||
<!-- 中间齿孔分隔 -->
|
||
<view class="coupon-card__divider">
|
||
<view class="coupon-card__hole coupon-card__hole--top"></view>
|
||
<view class="coupon-card__dash"></view>
|
||
<view class="coupon-card__hole coupon-card__hole--bottom"></view>
|
||
</view>
|
||
|
||
<!-- 卡片右侧:券信息与领取按钮 -->
|
||
<view class="coupon-card__right">
|
||
<view class="coupon-card__info">
|
||
<view class="coupon-card__title-row">
|
||
<text class="coupon-card__tag">{{ getCouponTypeLabel(c.type) }}</text>
|
||
<text class="coupon-card__title fc-ellipsis">{{ c.name || '通用优惠券' }}</text>
|
||
</view>
|
||
<view class="coupon-card__meta-row">
|
||
<text class="coupon-card__date">
|
||
{{ c.days > 0 ? `领取后 ${c.days} 天内有效` : '永久有效' }}
|
||
</text>
|
||
<text v-if="c.left > 0" class="coupon-card__stock">仅剩{{ c.left }}张</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="coupon-card__action">
|
||
<!-- 已领取 -->
|
||
<view v-if="c.received" class="coupon-card__btn coupon-card__btn--disabled">
|
||
<text class="coupon-card__btn-text--disabled">已领取</text>
|
||
</view>
|
||
<!-- 已抢光 -->
|
||
<view v-else-if="c.left === 0" class="coupon-card__btn coupon-card__btn--disabled">
|
||
<text class="coupon-card__btn-text--disabled">已抢光</text>
|
||
</view>
|
||
<!-- 立即领取按钮(亮绿底墨绿字) -->
|
||
<view
|
||
v-else
|
||
class="coupon-card__btn coupon-card__btn--receive"
|
||
:class="{ 'coupon-card__btn--loading': receivingId === c.id }"
|
||
@click="handleReceive(c)"
|
||
>
|
||
<text class="coupon-card__btn-text">
|
||
{{ receivingId === c.id ? '领取中' : '立即领取' }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 领券中心空状态 -->
|
||
<fc-empty
|
||
v-else
|
||
icon="inbox"
|
||
text="暂无可领取的优惠券,稍后再来瞧瞧吧"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import FcNavbar from '@/components/fc-navbar/fc-navbar.vue'
|
||
import FcEmpty from '@/components/fc-empty/fc-empty.vue'
|
||
import couponApi from '@/common/api/coupon.js'
|
||
import memberApi from '@/common/api/member.js'
|
||
import { useUserStore } from '@/common/store/index.js'
|
||
|
||
export default {
|
||
name: 'CouponsPage',
|
||
components: {
|
||
FcNavbar,
|
||
FcEmpty,
|
||
},
|
||
data() {
|
||
return {
|
||
/** 当前主 Tab:mine(我的卡券) | market(领券中心) */
|
||
mainTab: 'mine',
|
||
/** 我的卡券二级筛选状态:all(全部) | unused(未使用) | used(已使用) | expired(已过期) */
|
||
subStatus: 'unused',
|
||
/** 数据加载状态 */
|
||
loading: false,
|
||
/** 正在领取的券ID */
|
||
receivingId: null,
|
||
/** 用户拥有的卡券列表 */
|
||
myCoupons: [],
|
||
/** 领券中心的券模板列表 */
|
||
marketCoupons: [],
|
||
}
|
||
},
|
||
computed: {
|
||
/**
|
||
* 检查当前是否登录
|
||
* @returns {boolean}
|
||
*/
|
||
isLogin() {
|
||
try {
|
||
return useUserStore().isLogin.value
|
||
} catch (e) {
|
||
return false
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 我的可用卡券总数
|
||
* @returns {number}
|
||
*/
|
||
myCouponCount() {
|
||
return this.myCoupons.filter((c) => c.status === 'unused').length
|
||
},
|
||
|
||
/**
|
||
* 领券中心剩余可领取数量标记
|
||
* @returns {number}
|
||
*/
|
||
marketAvailableCount() {
|
||
return this.marketCoupons.filter((c) => !c.received && (c.left === -1 || c.left > 0)).length
|
||
},
|
||
|
||
/**
|
||
* 我的卡券二级分类配置及各状态计数
|
||
* @returns {Array<{key: string, label: string, count: number}>}
|
||
*/
|
||
subFilters() {
|
||
const unusedCount = this.myCoupons.filter((c) => c.status === 'unused').length
|
||
const usedCount = this.myCoupons.filter((c) => c.status === 'used').length
|
||
const expiredCount = this.myCoupons.filter((c) => c.status === 'expired').length
|
||
return [
|
||
{ key: 'unused', label: '未使用', count: unusedCount },
|
||
{ key: 'all', label: '全部', count: this.myCoupons.length },
|
||
{ key: 'used', label: '已使用', count: usedCount },
|
||
{ key: 'expired', label: '已过期', count: expiredCount },
|
||
]
|
||
},
|
||
|
||
/**
|
||
* 经过二级分类筛选后的卡券列表
|
||
* @returns {Array}
|
||
*/
|
||
filteredMyCoupons() {
|
||
if (this.subStatus === 'all') {
|
||
return this.myCoupons
|
||
}
|
||
return this.myCoupons.filter((c) => c.status === this.subStatus)
|
||
},
|
||
|
||
/**
|
||
* 我的卡券空状态提示语
|
||
* @returns {string}
|
||
*/
|
||
emptyTextMine() {
|
||
if (this.subStatus === 'unused') return '暂无未使用的优惠券'
|
||
if (this.subStatus === 'used') return '暂无已使用的优惠券记录'
|
||
if (this.subStatus === 'expired') return '暂无过期的优惠券'
|
||
return '您还没有优惠券,快去领取专属福利吧'
|
||
},
|
||
},
|
||
|
||
/**
|
||
* 页面加载生命周期
|
||
* @param {Object} options 页面传参,可指定 tab=mine|market
|
||
*/
|
||
onLoad(options) {
|
||
if (options && options.tab === 'market') {
|
||
this.mainTab = 'market'
|
||
}
|
||
this.initData()
|
||
},
|
||
|
||
/**
|
||
* 下拉刷新生命周期
|
||
*/
|
||
async onPullDownRefresh() {
|
||
await this.initData()
|
||
uni.stopPullDownRefresh()
|
||
},
|
||
|
||
methods: {
|
||
/**
|
||
* 初始化加载所有卡券数据
|
||
*/
|
||
async initData() {
|
||
this.loading = true
|
||
try {
|
||
await Promise.all([this.loadMyCoupons(), this.loadMarketCoupons()])
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载我的卡券资产
|
||
*/
|
||
async loadMyCoupons() {
|
||
if (!this.isLogin) {
|
||
this.myCoupons = []
|
||
return
|
||
}
|
||
try {
|
||
const res = await memberApi.assets()
|
||
this.myCoupons = (res && Array.isArray(res.coupons)) ? res.coupons : []
|
||
} catch (err) {
|
||
this.myCoupons = []
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 加载领券中心公开列表
|
||
*/
|
||
async loadMarketCoupons() {
|
||
try {
|
||
const res = await couponApi.list({ page: 1, size: 50 })
|
||
this.marketCoupons = (res && Array.isArray(res.list)) ? res.list : []
|
||
} catch (err) {
|
||
this.marketCoupons = []
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 切换一级主 Tab
|
||
* @param {'mine'|'market'} tab
|
||
*/
|
||
switchMainTab(tab) {
|
||
this.mainTab = tab
|
||
},
|
||
|
||
/**
|
||
* 切换二级状态筛选
|
||
* @param {'all'|'unused'|'used'|'expired'} key
|
||
*/
|
||
switchSubStatus(key) {
|
||
this.subStatus = key
|
||
},
|
||
|
||
/**
|
||
* 点击去使用优惠券
|
||
* @param {Object} item 优惠券对象
|
||
*/
|
||
goUseCoupon(item) {
|
||
uni.showActionSheet({
|
||
itemList: ['发布同城信息(可用券抵扣)', '浏览最新同城信息'],
|
||
success: (res) => {
|
||
if (res.tapIndex === 0) {
|
||
uni.navigateTo({ url: '/pages/post/create' })
|
||
} else {
|
||
uni.switchTab({ url: '/pages/index/index' })
|
||
}
|
||
},
|
||
})
|
||
},
|
||
|
||
/**
|
||
* 领取优惠券操作
|
||
* @param {Object} c 券对象
|
||
*/
|
||
async handleReceive(c) {
|
||
if (!this.isLogin) {
|
||
uni.showToast({ title: '请先登录后再领券', icon: 'none' })
|
||
setTimeout(() => {
|
||
uni.navigateTo({ url: '/pages/auth/login' })
|
||
}, 600)
|
||
return
|
||
}
|
||
if (this.receivingId) return
|
||
this.receivingId = c.id
|
||
|
||
try {
|
||
await couponApi.receive(c.id)
|
||
uni.showToast({ title: '领取成功!', icon: 'success' })
|
||
// 标记已领取
|
||
c.received = true
|
||
if (c.left > 0) c.left -= 1
|
||
// 重新静默拉取我的资产
|
||
this.loadMyCoupons()
|
||
} catch (e) {
|
||
// 提示已由 request 拦截层处理或直接提示
|
||
uni.showToast({ title: (e && e.message) || '领取失败,请重试', icon: 'none' })
|
||
} finally {
|
||
this.receivingId = null
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 格式化金额数值
|
||
* @param {number|string} val
|
||
* @returns {string}
|
||
*/
|
||
formatAmount(val) {
|
||
const n = Number(val)
|
||
if (isNaN(n)) return '0'
|
||
return Number.isInteger(n) ? String(n) : n.toFixed(1)
|
||
},
|
||
|
||
/**
|
||
* 格式化时间字符串至年月日
|
||
* @param {string} dateStr
|
||
* @returns {string}
|
||
*/
|
||
formatDate(dateStr) {
|
||
if (!dateStr) return ''
|
||
return String(dateStr).slice(0, 10)
|
||
},
|
||
|
||
/**
|
||
* 解析优惠券类型文案
|
||
* @param {string} type
|
||
* @returns {string}
|
||
*/
|
||
getCouponTypeLabel(type) {
|
||
if (type === 'discount') return '折扣券'
|
||
if (type === 'cash') return '现金抵扣'
|
||
return '满减券'
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* 页面根容器 */
|
||
.coupon-page {
|
||
min-height: 100vh;
|
||
background-color: $fc-bg;
|
||
position: relative;
|
||
padding-bottom: 60rpx;
|
||
}
|
||
|
||
/* 顶部沉浸底座 */
|
||
.coupon-page__backdrop {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 380rpx;
|
||
background: $fc-gradient-hero;
|
||
overflow: hidden;
|
||
z-index: 0;
|
||
pointer-events: none;
|
||
}
|
||
.coupon-page__backdrop-ambient {
|
||
position: absolute;
|
||
top: -60rpx;
|
||
right: -60rpx;
|
||
width: 320rpx;
|
||
height: 320rpx;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle, rgba(0, 224, 112, 0.28) 0%, rgba(0, 224, 112, 0) 70%);
|
||
filter: blur(20px);
|
||
}
|
||
|
||
/* 主标签页切换条 */
|
||
.coupon-page__tabs-wrap {
|
||
position: relative;
|
||
z-index: 2;
|
||
padding: 16rpx 32rpx 0;
|
||
}
|
||
.coupon-page__tabs {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-around;
|
||
height: 88rpx;
|
||
}
|
||
.coupon-page__tab-item {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 12rpx 24rpx;
|
||
}
|
||
.coupon-page__tab-text {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: $fc-text-secondary;
|
||
transition: all 0.2s ease;
|
||
}
|
||
.coupon-page__tab-item--active .coupon-page__tab-text {
|
||
font-size: 34rpx;
|
||
font-weight: 700;
|
||
color: $fc-primary-text;
|
||
}
|
||
.coupon-page__tab-badge {
|
||
margin-left: 8rpx;
|
||
padding: 2rpx 12rpx;
|
||
border-radius: 20rpx;
|
||
background-color: $fc-accent;
|
||
color: #ffffff;
|
||
font-size: 20rpx;
|
||
font-weight: 700;
|
||
line-height: 28rpx;
|
||
}
|
||
.coupon-page__tab-dot {
|
||
width: 12rpx;
|
||
height: 12rpx;
|
||
border-radius: 50%;
|
||
background-color: $fc-primary;
|
||
margin-left: 8rpx;
|
||
}
|
||
.coupon-page__tab-line {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 48rpx;
|
||
height: 6rpx;
|
||
border-radius: 4rpx;
|
||
background-color: $fc-primary;
|
||
}
|
||
|
||
/* 二级筛选栏(胶囊筛选) */
|
||
.coupon-page__sub-filter {
|
||
position: relative;
|
||
z-index: 2;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx 32rpx 10rpx;
|
||
gap: 16rpx;
|
||
overflow-x: auto;
|
||
}
|
||
.coupon-page__filter-chip {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10rpx 24rpx;
|
||
border-radius: 32rpx;
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
backdrop-filter: blur(8px);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.25);
|
||
transition: all 0.2s ease;
|
||
}
|
||
.coupon-page__filter-chip--active {
|
||
background-color: #ffffff;
|
||
border-color: #ffffff;
|
||
box-shadow: 0 4rpx 12rpx rgba(4, 48, 30, 0.1);
|
||
}
|
||
.coupon-page__filter-chip-text {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 0.9);
|
||
font-weight: 500;
|
||
}
|
||
.coupon-page__filter-chip--active .coupon-page__filter-chip-text {
|
||
color: $fc-primary-text;
|
||
font-weight: 600;
|
||
}
|
||
.coupon-page__filter-chip-num {
|
||
font-size: 22rpx;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
margin-left: 6rpx;
|
||
}
|
||
.coupon-page__filter-chip--active .coupon-page__filter-chip-num {
|
||
color: $fc-primary-text;
|
||
}
|
||
|
||
/* 内容主体 */
|
||
.coupon-page__body {
|
||
position: relative;
|
||
z-index: 2;
|
||
padding: 20rpx 28rpx;
|
||
}
|
||
|
||
/* 加载中状态 */
|
||
.coupon-page__loading {
|
||
padding: 100rpx 0;
|
||
text-align: center;
|
||
}
|
||
.coupon-page__loading-text {
|
||
font-size: 26rpx;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
/* 卡券列表 */
|
||
.coupon-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
/* 经典打孔卡券卡片 */
|
||
.coupon-card {
|
||
display: flex;
|
||
height: 196rpx;
|
||
background-color: #ffffff;
|
||
border-radius: 20rpx;
|
||
box-shadow: 0 6rpx 20rpx rgba(4, 48, 30, 0.05);
|
||
overflow: hidden;
|
||
position: relative;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
/* 卡片左侧:阳光金价值面额 */
|
||
.coupon-card__left {
|
||
width: 200rpx;
|
||
background: linear-gradient(135deg, #fffcf5 0%, #fff7e6 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 16rpx 12rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
.coupon-card__amount-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
color: $fc-accent;
|
||
}
|
||
.coupon-card__currency {
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
margin-right: 2rpx;
|
||
}
|
||
.coupon-card__amount {
|
||
font-size: 54rpx;
|
||
font-weight: 800;
|
||
line-height: 1;
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
}
|
||
.coupon-card__condition {
|
||
margin-top: 10rpx;
|
||
font-size: 20rpx;
|
||
color: $fc-accent-dark;
|
||
background-color: rgba(245, 166, 35, 0.12);
|
||
padding: 2rpx 12rpx;
|
||
border-radius: 12rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 中间打孔虚线 */
|
||
.coupon-card__divider {
|
||
width: 24rpx;
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #ffffff;
|
||
flex-shrink: 0;
|
||
}
|
||
.coupon-card__hole {
|
||
position: absolute;
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
border-radius: 50%;
|
||
background-color: $fc-bg;
|
||
left: 0;
|
||
z-index: 2;
|
||
}
|
||
.coupon-card__hole--top {
|
||
top: -12rpx;
|
||
}
|
||
.coupon-card__hole--bottom {
|
||
bottom: -12rpx;
|
||
}
|
||
.coupon-card__dash {
|
||
height: 120rpx;
|
||
border-left: 2rpx dashed #e2e8e4;
|
||
}
|
||
|
||
/* 卡片右侧:详情与操作 */
|
||
.coupon-card__right {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20rpx 24rpx 20rpx 16rpx;
|
||
min-width: 0;
|
||
}
|
||
.coupon-card__info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
padding-right: 16rpx;
|
||
}
|
||
.coupon-card__title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
.coupon-card__tag {
|
||
font-size: 20rpx;
|
||
color: $fc-primary-ink;
|
||
background: $fc-primary;
|
||
padding: 2rpx 10rpx;
|
||
border-radius: 6rpx;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
.coupon-card__title {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
}
|
||
.coupon-card__date {
|
||
font-size: 22rpx;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
.coupon-card__meta-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
.coupon-card__stock {
|
||
font-size: 20rpx;
|
||
color: $fc-accent;
|
||
background: $fc-accent-lighter;
|
||
padding: 2rpx 8rpx;
|
||
border-radius: 6rpx;
|
||
}
|
||
|
||
/* 操作区域 */
|
||
.coupon-card__action {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* 按钮通用 */
|
||
.coupon-card__btn {
|
||
padding: 14rpx 30rpx;
|
||
border-radius: 32rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 140rpx;
|
||
box-shadow: 0 4rpx 12rpx rgba(0, 224, 112, 0.2);
|
||
transition: all 0.2s ease;
|
||
}
|
||
.coupon-card__btn:active {
|
||
transform: scale(0.96);
|
||
}
|
||
|
||
/* 亮绿主按钮:规范严格执行亮绿底用深墨绿字 */
|
||
.coupon-card__btn--use,
|
||
.coupon-card__btn--receive {
|
||
background: $fc-gradient-primary;
|
||
}
|
||
.coupon-card__btn-text {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: $fc-primary-ink; /* 亮绿底配深墨绿字,符合高对比度规范 */
|
||
}
|
||
|
||
/* 禁用态按钮 */
|
||
.coupon-card__btn--disabled {
|
||
background: #f0f3f1;
|
||
box-shadow: none;
|
||
pointer-events: none;
|
||
}
|
||
.coupon-card__btn-text--disabled {
|
||
font-size: 24rpx;
|
||
color: #9eb1a7;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 状态印章(微倾斜盖章质感) */
|
||
.coupon-card__stamp {
|
||
width: 110rpx;
|
||
height: 110rpx;
|
||
border-radius: 50%;
|
||
border: 3rpx dashed #b8c7bf;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transform: rotate(-15deg);
|
||
opacity: 0.6;
|
||
}
|
||
.coupon-card__stamp-text {
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
color: #7b9286;
|
||
}
|
||
.coupon-card__stamp--used {
|
||
border-color: #8fa398;
|
||
}
|
||
.coupon-card__stamp--expired {
|
||
border-color: #d1b8b8;
|
||
}
|
||
.coupon-card__stamp--expired .coupon-card__stamp-text {
|
||
color: #a88d8d;
|
||
}
|
||
|
||
/* 针对已失效或已领取的弱化卡面 */
|
||
.coupon-card--used,
|
||
.coupon-card--expired {
|
||
opacity: 0.72;
|
||
}
|
||
.coupon-card--used .coupon-card__left,
|
||
.coupon-card--expired .coupon-card__left {
|
||
background: #f7f9f8;
|
||
}
|
||
.coupon-card--used .coupon-card__amount-row,
|
||
.coupon-card--expired .coupon-card__amount-row {
|
||
color: #8c9e95;
|
||
}
|
||
.coupon-card--used .coupon-card__condition,
|
||
.coupon-card--expired .coupon-card__condition {
|
||
color: #8c9e95;
|
||
background-color: #ecefe5;
|
||
}
|
||
.coupon-card--used .coupon-card__tag,
|
||
.coupon-card--expired .coupon-card__tag {
|
||
background: #e2e8e4;
|
||
color: #63776d;
|
||
}
|
||
</style>
|