bindbox-mini/components/activity/RecordsList.vue

240 lines
5.2 KiB
Vue

<template>
<view class="records-wrapper">
<view class="records-list" v-if="records && records.length">
<view v-for="(item, idx) in records" :key="item.id ? `${item.id}_${idx}` : idx" class="record-item">
<!-- 用户信息 (左侧, 紧凑) -->
<view class="user-info-section">
<image class="user-avatar" :src="item.avatar || defaultAvatar" mode="aspectFill" />
<view class="user-detail">
<text class="user-name">{{ item.user_name }}</text>
<text class="record-time">{{ formatTime(item.created_at) }}</text>
</view>
</view>
<!-- 奖品信息 (右侧, 扩展) -->
<view class="prize-info-section">
<view class="prize-image-wrap">
<image class="record-img" :src="item.image" mode="aspectFill" />
<view class="level-badge" v-if="item.level_name">{{ item.level_name }}</view>
</view>
<view class="record-info">
<view class="record-title">{{ item.title }}</view>
<view class="record-meta">
<text class="record-count">x1</text>
</view>
</view>
</view>
</view>
</view>
<view class="empty-state-compact" v-else>
<view class="empty-icon-wrap">
<text class="empty-icon">🎁</text>
</view>
<text class="empty-title">{{ emptyText }}</text>
<text class="empty-hint">快来参与活动获得奖品吧</text>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue'
defineProps({
records: {
type: Array,
default: () => []
},
emptyText: {
type: String,
default: '暂无购买记录'
}
})
const defaultAvatar = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
function formatTime(t) {
if (!t) return ''
const d = new Date(t)
if (isNaN(d.getTime())) return t // 如果解析失败直接返回
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const hh = String(d.getHours()).padStart(2, '0')
const mm = String(d.getMinutes()).padStart(2, '0')
const ss = String(d.getSeconds()).padStart(2, '0')
return `${m}-${day} ${hh}:${mm}:${ss}`
}
</script>
<style lang="scss" scoped>
.records-list {
padding: $spacing-xs 0;
}
.record-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: $spacing-md $spacing-sm;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
&:last-child {
border-bottom: none;
}
}
.record-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: $spacing-md $spacing-sm;
border-bottom: 1rpx solid rgba(0, 0, 0, 0.03);
&:last-child {
border-bottom: none;
}
}
.user-info-section {
display: flex;
align-items: center;
gap: $spacing-xs;
flex: 0 0 35%; // 固定宽度给用户信息
min-width: 0;
}
.user-avatar {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
background: $bg-secondary;
border: 1px solid rgba(0,0,0,0.05);
flex-shrink: 0;
}
.user-detail {
display: flex;
flex-direction: column;
gap: 2rpx;
min-width: 0;
}
.user-name {
font-size: 24rpx;
color: $text-main;
font-weight: 500;
@include text-ellipsis(1);
}
.record-time {
font-size: 20rpx;
color: $text-sub;
@include text-ellipsis(1);
}
.prize-info-section {
display: flex;
align-items: center;
gap: $spacing-sm;
flex: 1;
min-width: 0;
justify-content: flex-end;
}
.prize-image-wrap {
position: relative;
width: 72rpx;
height: 72rpx;
flex-shrink: 0;
}
.record-img {
width: 100%;
height: 100%;
border-radius: $radius-md;
background: $bg-secondary;
border: 1px solid rgba(0,0,0,0.05);
}
.level-badge {
position: absolute;
top: -6rpx;
right: -6rpx;
background: $gradient-gold;
color: #fff;
font-size: 16rpx;
padding: 2rpx 6rpx;
border-radius: 4rpx;
font-weight: bold;
box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
}
.record-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
align-items: flex-start; // 左对齐
}
.record-title {
font-size: 24rpx;
font-weight: 500;
color: $text-main;
@include text-ellipsis(2); // 允许两行
line-height: 1.3;
margin-bottom: 4rpx;
width: 100%;
}
.record-meta {
display: flex;
align-items: center;
}
.record-count {
font-size: 20rpx;
color: $brand-primary;
background: rgba($brand-primary, 0.08);
padding: 2rpx 8rpx;
border-radius: 4rpx;
}
/* 紧凑优雅的空状态 */
.empty-state-compact {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: $spacing-lg $spacing-xl;
min-height: 200rpx;
}
.empty-icon-wrap {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, rgba($brand-primary, 0.1) 0%, rgba($accent-gold, 0.1) 100%);
border-radius: 50%;
margin-bottom: $spacing-md;
}
.empty-icon {
font-size: 40rpx;
}
.empty-title {
font-size: $font-md;
color: $text-sub;
font-weight: 600;
margin-bottom: 8rpx;
}
.empty-hint {
font-size: $font-xs;
color: $text-tertiary;
}
</style>