bindbox-mini/components/activity/RewardsPreview.vue

237 lines
5.1 KiB
Vue

<template>
<view>
<view class="section-header">
<text class="section-title">{{ title }}</text>
<text class="section-more" @tap="$emit('view-all')">查看全部</text>
</view>
<!-- 分组展示 -->
<view v-if="grouped && rewardGroups.length > 0">
<view class="prize-level-row" v-for="group in rewardGroups" :key="group.level">
<view class="level-header-row">
<view class="level-badge" :class="{ 'badge-boss': group.level === 'BOSS' }">{{ group.level }}赏</view>
<text class="level-prob">总概率 {{ group.totalPercent }}%</text>
</view>
<scroll-view class="preview-scroll" scroll-x>
<view class="preview-item" v-for="(item, idx) in group.rewards" :key="item.id || idx">
<view class="prize-tag" :class="{ 'tag-boss': item.boss }">{{ item.boss ? 'BOSS' : group.level }}</view>
<image class="preview-img" :src="item.image" mode="aspectFill" />
<view class="preview-name">{{ item.title }}</view>
</view>
</scroll-view>
</view>
</view>
<!-- 简单列表展示 -->
<view v-else-if="rewards.length > 0">
<scroll-view class="preview-scroll" scroll-x>
<view class="preview-item" v-for="(item, idx) in rewards" :key="idx">
<view class="prize-tag" :class="{ 'tag-boss': item.boss }">{{ item.boss ? 'BOSS' : (item.level || '赏') }}</view>
<image class="preview-img" :src="item.image" mode="aspectFill" />
<view class="preview-name">{{ item.title }}</view>
</view>
</scroll-view>
</view>
<!-- 空状态 -->
<view v-else class="empty-state">
<text class="empty-icon">📭</text>
<text class="empty-text">{{ emptyText }}</text>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
import { groupRewardsByLevel } from '@/utils/activity'
const props = defineProps({
title: {
type: String,
default: '奖池配置'
},
rewards: {
type: Array,
default: () => []
},
grouped: {
type: Boolean,
default: false
},
emptyText: {
type: String,
default: '暂无奖品配置'
}
})
defineEmits(['view-all'])
const rewardGroups = computed(() => {
if (!props.grouped) return []
return groupRewardsByLevel(props.rewards)
})
</script>
<style lang="scss" scoped>
/* ============================================
奖池预览 - 与原始设计完全一致
============================================ */
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $spacing-md;
}
.section-title {
font-size: $font-md;
font-weight: 700;
color: $text-main;
}
.section-more {
font-size: $font-sm;
color: $text-tertiary;
display: flex;
align-items: center;
&::after {
content: '>';
font-family: monospace;
margin-left: 6rpx;
font-weight: 700;
}
}
/* 等级分组 */
.prize-level-row {
margin-bottom: $spacing-lg;
background: rgba(0,0,0,0.02);
padding: $spacing-md;
border-radius: $radius-lg;
&:last-child {
margin-bottom: 0;
}
}
.level-header-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: $spacing-md;
}
.level-badge {
display: inline-block;
font-size: $font-xs;
font-weight: 900;
color: $text-main;
background: #F0F0F0;
padding: 4rpx 16rpx;
border-radius: 8rpx;
font-style: italic;
border: 1rpx solid rgba(0,0,0,0.05);
box-shadow: $shadow-xs;
&.badge-boss {
background: $gradient-gold;
color: #78350F;
border-color: rgba(217, 119, 6, 0.3);
}
}
.level-prob {
font-size: 22rpx;
color: $brand-primary;
font-weight: 800;
opacity: 0.9;
}
/* 预览滚动区域 */
.preview-scroll {
white-space: nowrap;
width: 100%;
}
.preview-item {
display: inline-block;
width: 180rpx;
margin-right: $spacing-md;
vertical-align: top;
position: relative;
transition: transform 0.2s;
&:active {
transform: scale(0.96);
}
&:last-child {
margin-right: 0;
}
}
.preview-img {
width: 180rpx;
height: 180rpx;
border-radius: $radius-lg;
background: $bg-secondary;
margin-bottom: $spacing-sm;
box-shadow: $shadow-sm;
border: 1rpx solid rgba(0,0,0,0.03);
}
.preview-name {
font-size: $font-xs;
color: $text-secondary;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
font-weight: 500;
}
/* 奖品标签 */
.prize-tag {
position: absolute;
top: 10rpx;
left: 10rpx;
background: rgba(0,0,0,0.6);
color: #fff;
font-size: $font-xs;
padding: 4rpx $spacing-sm;
border-radius: $radius-sm;
z-index: 10;
font-weight: 700;
backdrop-filter: blur(4rpx);
transform: scale(0.9);
transform-origin: top left;
&.tag-boss {
background: $gradient-brand;
box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.4);
}
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: $spacing-xl;
color: $text-sub;
}
.empty-icon {
font-size: 64rpx;
margin-bottom: $spacing-sm;
}
.empty-text {
font-size: $font-sm;
}
</style>