346 lines
6.4 KiB
Vue
346 lines
6.4 KiB
Vue
<template>
|
|
<view class="points-log-page">
|
|
<!-- 积分流水列表 -->
|
|
<scroll-view
|
|
scroll-y
|
|
class="log-scroll"
|
|
@scrolltolower="loadMore"
|
|
:refresher-enabled="true"
|
|
:refresher-triggered="refreshing"
|
|
@refresherrefresh="refresh"
|
|
>
|
|
<view class="log-list">
|
|
<view
|
|
class="log-item"
|
|
v-for="log in logList"
|
|
:key="log.id"
|
|
>
|
|
<view class="log-left">
|
|
<view class="log-icon" :class="getSourceTypeClass(log.source_type)">
|
|
{{ getSourceTypeIcon(log.source_type) }}
|
|
</view>
|
|
<view class="log-info">
|
|
<text class="log-type">{{ getSourceTypeText(log.source_type) }}</text>
|
|
<text class="log-time">{{ formatDate(log.created_at) }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="log-right">
|
|
<text class="log-points" :class="getPointsClass(log.points)">
|
|
{{ formatPoints(log.points) }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 空状态 -->
|
|
<view v-if="!loading && logList.length === 0" class="empty-state">
|
|
<text class="empty-icon">📋</text>
|
|
<text class="empty-text">暂无积分流水记录</text>
|
|
</view>
|
|
|
|
<!-- 加载更多 -->
|
|
<view v-if="loading && logList.length > 0" class="loading-more">
|
|
<text class="loading-text">加载中...</text>
|
|
</view>
|
|
|
|
<!-- 没有更多 -->
|
|
<view v-if="!hasMore && logList.length > 0" class="no-more">
|
|
<text class="no-more-text">没有更多记录了</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import request from '@/api/request.js';
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
logList: [],
|
|
loading: false,
|
|
refreshing: false,
|
|
page: 1,
|
|
pageSize: 10,
|
|
hasMore: true
|
|
};
|
|
},
|
|
onLoad() {
|
|
this.loadLogList();
|
|
},
|
|
methods: {
|
|
// 格式化日期时间
|
|
formatDate(dateStr) {
|
|
if (!dateStr) return '';
|
|
const date = new Date(dateStr);
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const hour = String(date.getHours()).padStart(2, '0');
|
|
const minute = String(date.getMinutes()).padStart(2, '0');
|
|
return `${year}-${month}-${day} ${hour}:${minute}`;
|
|
},
|
|
|
|
// 格式化积分显示
|
|
formatPoints(points) {
|
|
if (!points && points !== 0) return '0';
|
|
const num = parseFloat(points);
|
|
if (num > 0) {
|
|
return `+${num}`;
|
|
}
|
|
return String(num);
|
|
},
|
|
|
|
// 获取积分样式类(正数绿色,负数红色)
|
|
getPointsClass(points) {
|
|
const num = parseFloat(points);
|
|
return num > 0 ? 'positive' : 'negative';
|
|
},
|
|
|
|
// 获取积分来源类型文本
|
|
getSourceTypeText(sourceType) {
|
|
const typeMap = {
|
|
1: '签到',
|
|
2: '邀请',
|
|
3: '消费',
|
|
4: '兑换扣除',
|
|
5: '系统发放',
|
|
6: '消费',
|
|
7: '回退'
|
|
};
|
|
return typeMap[sourceType] || '未知';
|
|
},
|
|
|
|
// 获取积分来源类型图标
|
|
getSourceTypeIcon(sourceType) {
|
|
const iconMap = {
|
|
1: '📅',
|
|
2: '👥',
|
|
3: '🛍️',
|
|
4: '💸',
|
|
5: '🎁',
|
|
6: '🛒',
|
|
7: '↩️'
|
|
};
|
|
return iconMap[sourceType] || '📝';
|
|
},
|
|
|
|
// 获取积分来源类型样式类
|
|
getSourceTypeClass(sourceType) {
|
|
const classMap = {
|
|
1: 'type-sign',
|
|
2: 'type-invite',
|
|
3: 'type-consume',
|
|
4: 'type-exchange',
|
|
5: 'type-system',
|
|
6: 'type-consume',
|
|
7: 'type-refund'
|
|
};
|
|
return classMap[sourceType] || '';
|
|
},
|
|
|
|
// 加载积分流水列表
|
|
async loadLogList() {
|
|
if (this.loading || !this.hasMore) return;
|
|
|
|
this.loading = true;
|
|
try {
|
|
const params = {
|
|
page: this.page,
|
|
page_size: this.pageSize
|
|
};
|
|
|
|
const response = await request('xcx/user_points_logs', 'GET', params);
|
|
|
|
// 处理返回数据
|
|
let logs = [];
|
|
if (Array.isArray(response)) {
|
|
logs = response;
|
|
} else if (response.list && Array.isArray(response.list)) {
|
|
logs = response.list;
|
|
} else if (response.data && Array.isArray(response.data)) {
|
|
logs = response.data;
|
|
}
|
|
|
|
if (logs.length < this.pageSize) {
|
|
this.hasMore = false;
|
|
}
|
|
|
|
if (this.page === 1) {
|
|
this.logList = logs;
|
|
} else {
|
|
this.logList = [...this.logList, ...logs];
|
|
}
|
|
|
|
this.page++;
|
|
} catch (error) {
|
|
console.error('加载积分流水失败:', error);
|
|
// 如果是第一页且没有数据,显示空状态
|
|
if (this.page === 1) {
|
|
this.logList = [];
|
|
}
|
|
} finally {
|
|
this.loading = false;
|
|
this.refreshing = false;
|
|
}
|
|
},
|
|
|
|
// 刷新列表
|
|
refresh() {
|
|
this.refreshing = true;
|
|
this.page = 1;
|
|
this.hasMore = true;
|
|
this.logList = [];
|
|
this.loadLogList();
|
|
},
|
|
|
|
// 加载更多
|
|
loadMore() {
|
|
if (!this.loading && this.hasMore) {
|
|
this.loadLogList();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.points-log-page {
|
|
min-height: 100vh;
|
|
background-color: #f5f5f5;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.log-scroll {
|
|
flex: 1;
|
|
height: calc(100vh);
|
|
}
|
|
|
|
.log-list {
|
|
padding: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16rpx;
|
|
}
|
|
|
|
.log-item {
|
|
background-color: #fff;
|
|
border-radius: 24rpx;
|
|
padding: 32rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.log-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 24rpx;
|
|
flex: 1;
|
|
}
|
|
|
|
.log-icon {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 40rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.log-icon.type-sign {
|
|
background-color: #fff3e0;
|
|
}
|
|
|
|
.log-icon.type-invite {
|
|
background-color: #e3f2fd;
|
|
}
|
|
|
|
.log-icon.type-consume {
|
|
background-color: #fce4ec;
|
|
}
|
|
|
|
.log-icon.type-exchange {
|
|
background-color: #ffebee;
|
|
}
|
|
|
|
.log-icon.type-system {
|
|
background-color: #e8f5e9;
|
|
}
|
|
|
|
.log-icon.type-refund {
|
|
background-color: #f3e5f5;
|
|
}
|
|
|
|
.log-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8rpx;
|
|
flex: 1;
|
|
}
|
|
|
|
.log-type {
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.log-time {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.log-right {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.log-points {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.log-points.positive {
|
|
color: #26b95a;
|
|
}
|
|
|
|
.log-points.negative {
|
|
color: #e7000b;
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 120rpx 0;
|
|
}
|
|
|
|
.empty-icon {
|
|
font-size: 120rpx;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.loading-more,
|
|
.no-more {
|
|
text-align: center;
|
|
padding: 40rpx 0;
|
|
}
|
|
|
|
.loading-text,
|
|
.no-more-text {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
</style>
|
|
|