web-retail-h5/pages/mine/marketDynamic/box-list.vue

305 lines
8.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- <view class="search-bar">
<u-search
placeholder="请输入会员编号或姓名查询"
v-model="keyword"
@custom="search"
@search="search"
></u-search>
</view> -->
<!-- 特殊会员信息 -->
<view class="top-member-card" v-if="topMember">
<view class="member-info-header">
<text>会员信息:</text>
<text class="member-info-text">{{ formatMemberInfo(topMember) }}</text>
</view>
<view class="stats-grid">
<view class="stat-item">
<text class="stat-value">{{ toInt(topMember.todayBox) }}</text>
<text class="stat-label">今日盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.yesterdayBox }}</text>
<text class="stat-label">昨日盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.monthBox }}</text>
<text class="stat-label">本月盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.lastMonthBox }}</text>
<text class="stat-label">上月盒数</text>
</view>
</view>
</view>
<!-- 列表 -->
<view class="member-list">
<view class="member-item" v-for="item in memberList" :key="item.memberId">
<view class="member-info-header list-header">
<text>会员信息:</text>
<text>{{ formatMemberInfo(item) }}</text>
</view>
<view class="stats-grid list-grid">
<view class="stat-item">
<text class="stat-value">{{ toInt(item.todayBox) }}</text>
<text class="stat-label">今日盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.yesterdayBox }}</text>
<text class="stat-label">昨日盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.monthBox }}</text>
<text class="stat-label">本月盒数</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.lastMonthBox }}</text>
<text class="stat-label">上月盒数</text>
</view>
</view>
</view>
</view>
<u-loadmore :status="loadStatus" />
</view>
</template>
<script>
// 假设的API方法您需要替换为真实实现
// import { getMarketBoxTop, getMarketBoxList } from '@/config/mine.js';
export default {
data() {
return {
keyword: '',
topMember: null, // 置顶的特殊会员
memberList: [], // 成员列表
page: 1,
pageSize: 10,
loadStatus: 'loadmore', // loadmore, loading, nomore
}
},
onLoad() {
this.fetchTopMember()
this.fetchMemberList(true)
},
onReachBottom() {
if (this.loadStatus === 'nomore' || this.loadStatus === 'loading') {
return
}
this.page++
this.fetchMemberList()
},
methods: {
toInt(value) {
const intValue = parseInt(value, 10)
return isNaN(intValue) ? value : intValue
},
formatMemberInfo(member) {
if (!member) return ''
const { memberCode, nickName, grade, award } = member
return `${memberCode}/${nickName || '未知'}/${grade}/${award}`
},
search() {
this.memberList = []
this.page = 1
this.fetchTopMember()
this.fetchMemberList(true)
},
// 获取置顶会员数据
async fetchTopMember() {
// --- MOCK DATA from screenshot ---
this.topMember = {
memberId: 'HZS55197913',
memberCode: 'HZS55197913',
nickName: '未知', // Screenshot has no name, API might
grade: 'V5',
award: 'S2',
todayBox: 3361.0,
yesterdayBox: 114,
monthBox: 3475,
lastMonthBox: 3206,
}
// --- REAL API CALL ---
// try {
// const res = await getMarketBoxTop({ keyword: this.keyword });
// if (res.code === 200) {
// // Real data mapping from fields like realizedBox, upMonthBox
// this.topMember = { ...res.data, todayBox: res.data.realizedBox, lastMonthBox: res.data.upMonthBox };
// }
// } catch (e) {
// console.error(e);
// }
},
// 获取会员列表数据
async fetchMemberList(isRefresh = false) {
if (isRefresh) {
this.page = 1
this.memberList = []
}
this.loadStatus = 'loading'
// --- MOCK DATA from screenshot ---
const mockData = [
{
memberId: 'HZS931295626',
memberCode: 'HZS931295626',
nickName: '未知',
grade: 'V5',
award: 'S1',
todayBox: 38.0,
yesterdayBox: 0,
monthBox: 38,
lastMonthBox: 503,
},
{
memberId: 'HZS938173516',
memberCode: 'HZS938173516',
nickName: '未知',
grade: 'V3',
award: 'S0',
todayBox: 25.0,
yesterdayBox: 0,
monthBox: 25,
lastMonthBox: 0,
},
{
memberId: 'HZS61632161',
memberCode: 'HZS61632161',
nickName: '未知',
grade: 'V3',
award: 'S0',
todayBox: 16.0,
yesterdayBox: 0,
monthBox: 16,
lastMonthBox: 0,
},
{
memberId: 'HZS978982363',
memberCode: 'HZS978982363',
nickName: '未知',
grade: 'V3',
award: 'S0',
todayBox: 15.0,
yesterdayBox: 0,
monthBox: 15,
lastMonthBox: 0,
},
]
// Simulate network delay and pagination
setTimeout(() => {
// Mock: stop after 2 pages
if (this.page > 2) {
this.loadStatus = 'nomore'
return
}
const moreData = mockData.map(item => ({
...item,
memberId: item.memberId + this.page, // unique key for v-for
}))
this.memberList = [...this.memberList, ...moreData]
// After adding data, check if we should be able to load more
this.loadStatus = this.page >= 2 ? 'nomore' : 'loadmore'
}, 500)
// --- REAL API CALL ---
// try {
// const res = await getMarketBoxList({ page: this.page, size: this.pageSize, keyword: this.keyword });
// if (res.code === 200) {
// const newList = res.data.records.map(item => ({ ...item, todayBox: item.realizedBox, lastMonthBox: item.upMonthBox }));
// this.memberList = [...this.memberList, ...newList];
// if (res.data.records.length < this.pageSize) {
// this.loadStatus = 'nomore';
// } else {
// this.loadStatus = 'loadmore';
// }
// }
// } catch(e) {
// this.loadStatus = 'loadmore';
// console.error(e);
// }
},
},
}
</script>
<style lang="scss" scoped>
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.search-bar {
margin-bottom: 20rpx;
}
.top-member-card {
background: linear-gradient(135deg, #005bac, #007bff);
border-radius: 16rpx;
padding: 20rpx;
color: #ffffff;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 91, 172, 0.3);
}
.member-info-header {
font-size: 28rpx;
margin-bottom: 20rpx;
.member-info-text {
font-weight: bold;
}
}
.stats-grid {
display: flex;
justify-content: space-around;
text-align: center;
}
.stat-item {
display: flex;
flex-direction: column;
gap: 10rpx;
}
.stat-value {
font-size: 32rpx;
font-weight: bold;
}
.stat-label {
font-size: 24rpx;
opacity: 0.9;
}
.member-list {
.member-item {
background: #ffffff;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
.list-header {
color: #333;
font-size: 26rpx;
}
.list-grid {
.stat-value {
color: #333;
}
.stat-label {
color: #666;
}
}
}
}
</style>