任务大厅,限量显示
This commit is contained in:
parent
b97cd0f267
commit
4fe3ecb571
@ -11,17 +11,13 @@
|
||||
<!-- Tab栏 - 毛玻璃风格 -->
|
||||
<view class="tab-bar glass-card">
|
||||
<view class="tab-item" :class="{ active: currentTab === 1 }" @click="switchTab(1)">
|
||||
<text class="tab-text">未使用</text>
|
||||
<text class="tab-text">有效</text>
|
||||
<view class="tab-indicator" v-if="currentTab === 1"></view>
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: currentTab === 2 }" @click="switchTab(2)">
|
||||
<text class="tab-text">已使用</text>
|
||||
<text class="tab-text">已失效</text>
|
||||
<view class="tab-indicator" v-if="currentTab === 2"></view>
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: currentTab === 3 }" @click="switchTab(3)">
|
||||
<text class="tab-text">已过期</text>
|
||||
<view class="tab-indicator" v-if="currentTab === 3"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区 -->
|
||||
@ -51,7 +47,7 @@
|
||||
v-for="(item, index) in list"
|
||||
:key="item.id || index"
|
||||
class="coupon-ticket"
|
||||
:class="getCouponClass()"
|
||||
:class="getCouponClass(item)"
|
||||
:style="{ animationDelay: `${index * 0.05}s` }"
|
||||
>
|
||||
<!-- 左侧金额区域 -->
|
||||
@ -60,7 +56,7 @@
|
||||
<text class="coupon-symbol">¥</text>
|
||||
<text class="coupon-amount">{{ formatValue(item.remaining ?? item.amount ?? 0) }}</text>
|
||||
</view>
|
||||
<text class="coupon-label">{{ currentTab === 1 ? '可用' : (currentTab === 2 ? '已用' : '过期') }}</text>
|
||||
<text class="coupon-label" :class="getLabelClass(item)">{{ item.status_desc || '可用' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 中间分割线 -->
|
||||
@ -105,7 +101,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-status" v-else>
|
||||
<text class="status-tag" :class="currentTab === 2 ? 'used' : 'expired'">{{ currentTab === 2 ? '已使用' : '已过期' }}</text>
|
||||
<text class="status-tag" :class="getStatusTagClass(item)">{{ item.status_desc || '已失效' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -224,17 +220,32 @@ function getUsedPercent(item) {
|
||||
// 获取空状态文本
|
||||
function getEmptyText() {
|
||||
if (currentTab.value === 1) return '暂无可用优惠券'
|
||||
if (currentTab.value === 2) return '暂无使用记录'
|
||||
return '暂无过期优惠券'
|
||||
return '暂无失效优惠券'
|
||||
}
|
||||
|
||||
// 获取优惠券样式类
|
||||
function getCouponClass() {
|
||||
if (currentTab.value === 2) return 'coupon-used'
|
||||
if (currentTab.value === 3) return 'coupon-expired'
|
||||
function getCouponClass(item) {
|
||||
const sub = item?.sub_status || ''
|
||||
if (currentTab.value === 2) return 'coupon-invalid'
|
||||
if (sub === 'in_use') return 'coupon-in-use'
|
||||
return ''
|
||||
}
|
||||
|
||||
// 获取卡片标签样式
|
||||
function getLabelClass(item) {
|
||||
const sub = item?.sub_status || ''
|
||||
if (sub === 'in_use') return 'label-in-use'
|
||||
if (sub === 'unused') return 'label-unused'
|
||||
return 'label-invalid'
|
||||
}
|
||||
|
||||
// 获取失效 Tab 中的状态标签样式
|
||||
function getStatusTagClass(item) {
|
||||
const sub = item?.sub_status || ''
|
||||
if (sub === 'expired') return 'expired'
|
||||
return 'used'
|
||||
}
|
||||
|
||||
// 切换Tab
|
||||
function switchTab(tab) {
|
||||
if (currentTab.value === tab) return
|
||||
@ -270,8 +281,8 @@ async function fetchData(append = false) {
|
||||
try {
|
||||
const userId = getUserId()
|
||||
// status: 0=unused, 1=used, 2=expired
|
||||
const statusMap = { 1: 0, 2: 1, 3: 2 }
|
||||
const res = await getUserCoupons(userId, statusMap[currentTab.value], page.value, pageSize)
|
||||
// status: 1=有效, 2=已失效
|
||||
const res = await getUserCoupons(userId, currentTab.value, page.value, pageSize)
|
||||
const items = res.list || res.data || []
|
||||
|
||||
if (append) {
|
||||
@ -555,13 +566,26 @@ onLoad(() => {
|
||||
|
||||
.coupon-label {
|
||||
font-size: 20rpx;
|
||||
color: $brand-primary;
|
||||
margin-top: 8rpx;
|
||||
border: 1px solid $brand-primary;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.label-unused {
|
||||
color: $brand-primary;
|
||||
border: 1px solid $brand-primary;
|
||||
}
|
||||
|
||||
.label-in-use {
|
||||
color: #FF8D3F;
|
||||
border: 1px solid #FF8D3F;
|
||||
}
|
||||
|
||||
.label-invalid {
|
||||
color: $text-tertiary;
|
||||
border: 1px solid $text-tertiary;
|
||||
}
|
||||
|
||||
/* 分割线 */
|
||||
.coupon-divider {
|
||||
width: 30rpx;
|
||||
@ -763,25 +787,25 @@ onLoad(() => {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 过期/已使用状态 */
|
||||
.coupon-used .coupon-left,
|
||||
.coupon-expired .coupon-left {
|
||||
/* 已失效/使用中状态 */
|
||||
.coupon-invalid .coupon-left {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.coupon-used .coupon-value,
|
||||
.coupon-expired .coupon-value,
|
||||
.coupon-used .coupon-label,
|
||||
.coupon-expired .coupon-label {
|
||||
.coupon-invalid .coupon-value,
|
||||
.coupon-invalid .coupon-label {
|
||||
color: $text-tertiary;
|
||||
border-color: $text-tertiary;
|
||||
}
|
||||
|
||||
.coupon-used .coupon-name,
|
||||
.coupon-expired .coupon-name {
|
||||
.coupon-invalid .coupon-name {
|
||||
color: $text-sub;
|
||||
}
|
||||
|
||||
.coupon-in-use .coupon-left {
|
||||
background: linear-gradient(135deg, #FFF3E0, #fff);
|
||||
}
|
||||
|
||||
/* 加载更多 */
|
||||
.loading-more {
|
||||
display: flex;
|
||||
|
||||
@ -87,6 +87,12 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="task-status-wrap">
|
||||
<view v-if="task.quota > 0 && task.quota <= task.claimed_count" class="task-quota-tag exhausted">
|
||||
已领完
|
||||
</view>
|
||||
<view v-else-if="task.quota > 0" class="task-quota-tag">
|
||||
剩余 {{ task.quota - task.claimed_count }} 份
|
||||
</view>
|
||||
<view class="task-status" :class="getTaskStatusClass(task)">
|
||||
{{ getTaskStatusText(task) }}
|
||||
</view>
|
||||
@ -117,7 +123,11 @@
|
||||
<view v-if="isTierClaimed(task.id, tier.id)" class="tier-btn claimed">
|
||||
<text>已领取</text>
|
||||
</view>
|
||||
<!-- 已领完 (限量逻辑) -->
|
||||
<!-- 已领完 (任务级限量逻辑) -->
|
||||
<view v-else-if="task.quota > 0 && task.quota <= task.claimed_count" class="tier-btn disabled">
|
||||
<text>已领完</text>
|
||||
</view>
|
||||
<!-- 已领完 (档位级限量逻辑) -->
|
||||
<view v-else-if="tier.quota > 0 && tier.remaining === 0" class="tier-btn disabled">
|
||||
<text>已领完</text>
|
||||
</view>
|
||||
@ -215,6 +225,9 @@ function getTaskStatusClass(task) {
|
||||
const allClaimed = allTiers.every(t => progress.includes(t.id))
|
||||
if (allClaimed) return 'status-done'
|
||||
|
||||
// 任务级已领完
|
||||
if (task.quota > 0 && task.quota <= task.claimed_count) return 'status-done'
|
||||
|
||||
// 检查是否有可领取的
|
||||
if (allTiers.some(t => isTierClaimable(task, t) && !progress.includes(t.id))) {
|
||||
return 'status-claimable'
|
||||
@ -232,6 +245,9 @@ function getTaskStatusText(task) {
|
||||
const allClaimed = allTiers.every(t => progress.includes(t.id))
|
||||
if (allClaimed) return '已完成'
|
||||
|
||||
// 任务级已领完
|
||||
if (task.quota > 0 && task.quota <= task.claimed_count) return '已领完'
|
||||
|
||||
if (allTiers.some(t => isTierClaimable(task, t) && !progress.includes(t.id))) {
|
||||
return '可领取'
|
||||
}
|
||||
@ -811,6 +827,22 @@ function getSubProgressWidth(sub, task) {
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-left: 16rpx;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.task-quota-tag {
|
||||
font-size: 20rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 100rpx;
|
||||
background: rgba(#ff9500, 0.1);
|
||||
color: #ff9500;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
|
||||
&.exhausted {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
color: $text-tertiary;
|
||||
}
|
||||
}
|
||||
|
||||
.task-status {
|
||||
|
||||
@ -253,10 +253,9 @@
|
||||
<text class="close-btn" @tap="closeCouponsPopup">×</text>
|
||||
</view>
|
||||
|
||||
<view class="popup-tabs coupon-tabs-3">
|
||||
<view class="popup-tab" :class="{ active: couponsTab === 1 }" @tap="switchCouponsTab(1)">未使用</view>
|
||||
<view class="popup-tab" :class="{ active: couponsTab === 2 }" @tap="switchCouponsTab(2)">已使用</view>
|
||||
<view class="popup-tab" :class="{ active: couponsTab === 3 }" @tap="switchCouponsTab(3)">已过期</view>
|
||||
<view class="popup-tabs coupon-tabs-2">
|
||||
<view class="popup-tab" :class="{ active: couponsTab === 1 }" @tap="switchCouponsTab(1)">有效</view>
|
||||
<view class="popup-tab" :class="{ active: couponsTab === 2 }" @tap="switchCouponsTab(2)">已失效</view>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y class="coupon-scroll" @scrolltolower="loadMoreCoupons">
|
||||
@ -273,7 +272,7 @@
|
||||
<text class="coupon-symbol">¥</text>
|
||||
<text class="coupon-amount-num">{{ formatCouponValue(item.remaining ?? item.amount ?? 0) }}</text>
|
||||
</view>
|
||||
<text class="coupon-label">{{ couponsTab === 1 ? '可用' : (couponsTab === 2 ? '已用' : '过期') }}</text>
|
||||
<text class="coupon-label" :class="getCouponLabelClass(item)">{{ item.status_desc || '可用' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 中间分割线 -->
|
||||
@ -313,7 +312,7 @@
|
||||
<view class="use-btn-v2">去使用</view>
|
||||
</view>
|
||||
<view class="coupon-status-v2" v-else>
|
||||
<text class="status-tag" :class="couponsTab === 2 ? 'used' : 'expired'">{{ couponsTab === 2 ? '已使用' : '已过期' }}</text>
|
||||
<text class="status-tag" :class="getCouponStatusTagClass(item)">{{ item.status_desc || '已失效' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -1181,8 +1180,8 @@ export default {
|
||||
this.couponsLoading = true
|
||||
try {
|
||||
// status: 0=unused, 1=used, 2=expired
|
||||
const statusMap = { 1: 0, 2: 1, 3: 2 }
|
||||
const res = await getUserCoupons(this.userId, statusMap[this.couponsTab], this.couponsPage)
|
||||
// status: 1=有效, 2=已失效
|
||||
const res = await getUserCoupons(this.userId, this.couponsTab, this.couponsPage)
|
||||
const list = res.list || res.data || []
|
||||
if (list.length < 10) this.couponsHasMore = false
|
||||
this.couponsList = [...this.couponsList, ...list]
|
||||
@ -1195,14 +1194,25 @@ export default {
|
||||
},
|
||||
getCouponEmptyText() {
|
||||
if (this.couponsTab === 1) return '暂无可用优惠券'
|
||||
if (this.couponsTab === 2) return '暂无使用记录'
|
||||
return '暂无过期优惠券'
|
||||
return '暂无失效优惠券'
|
||||
},
|
||||
getCouponCardClass(item) {
|
||||
if (this.couponsTab === 2) return 'coupon-used'
|
||||
if (this.couponsTab === 3) return 'coupon-expired'
|
||||
if (this.couponsTab === 2) return 'coupon-invalid'
|
||||
const sub = item?.sub_status || ''
|
||||
if (sub === 'in_use') return 'coupon-in-use'
|
||||
return ''
|
||||
},
|
||||
getCouponLabelClass(item) {
|
||||
const sub = item?.sub_status || ''
|
||||
if (sub === 'in_use') return 'label-in-use'
|
||||
if (sub === 'unused') return 'label-unused'
|
||||
return 'label-invalid'
|
||||
},
|
||||
getCouponStatusTagClass(item) {
|
||||
const sub = item?.sub_status || ''
|
||||
if (sub === 'expired') return 'expired'
|
||||
return 'used'
|
||||
},
|
||||
formatCouponValue(val) {
|
||||
return (Number(val) / 100).toFixed(0)
|
||||
},
|
||||
@ -2046,18 +2056,24 @@ export default {
|
||||
.status-tag { font-size: 22rpx; color: $text-tertiary; background: #F5F5F5; padding: 4rpx 12rpx; border-radius: 6rpx; }
|
||||
.coupon-used-time { font-size: 18rpx; color: $text-tertiary; margin-top: 4rpx; text-align: left; }
|
||||
|
||||
/* 过期/已使用状态 */
|
||||
.coupon-used .coupon-left-v2, .coupon-expired .coupon-left-v2 {
|
||||
/* 失效/使用中状态 */
|
||||
.coupon-invalid .coupon-left-v2 {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
.coupon-used .coupon-remaining, .coupon-expired .coupon-remaining,
|
||||
.coupon-used .coupon-label, .coupon-expired .coupon-label {
|
||||
.coupon-invalid .coupon-remaining,
|
||||
.coupon-invalid .coupon-label {
|
||||
color: $text-tertiary;
|
||||
border-color: $text-tertiary;
|
||||
}
|
||||
.coupon-used .coupon-name-v2, .coupon-expired .coupon-name-v2 {
|
||||
.coupon-invalid .coupon-name-v2 {
|
||||
color: $text-sub;
|
||||
}
|
||||
.coupon-in-use .coupon-left-v2 {
|
||||
background: linear-gradient(135deg, #FFF3E0, #fff);
|
||||
}
|
||||
.label-unused { color: $brand-primary; border: 1px solid $brand-primary; }
|
||||
.label-in-use { color: #FF8D3F; border: 1px solid #FF8D3F; }
|
||||
.label-invalid { color: $text-tertiary; border: 1px solid $text-tertiary; }
|
||||
|
||||
/* 道具卡 */
|
||||
.item-cards-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20rpx; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user