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

253 lines
6.8 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">{{ topMember.todayAchievement }}</text>
<text class="stat-label">今日业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.yesterdayAchievement }}</text>
<text class="stat-label">昨日业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.monthAchievement }}</text>
<text class="stat-label">本月业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ topMember.lastMonthAchievement }}</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">{{ item.todayAchievement }}</text>
<text class="stat-label">今日业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.yesterdayAchievement }}</text>
<text class="stat-label">昨日业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.monthAchievement }}</text>
<text class="stat-label">本月业绩</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ item.lastMonthAchievement }}</text>
<text class="stat-label">上月业绩</text>
</view>
</view>
</view>
</view>
<u-loadmore :status="loadStatus" />
</view>
</template>
<script>
import { marketDynamicsList } from '@/config/market'
// 假设的API方法您需要替换为真实实现
// import { getMarketAchievementTop, getMarketAchievementList } from '@/config/mine.js';
export default {
data() {
return {
keyword: '',
topMember: null, // 置顶的特殊会员
memberList: [], // 成员列表
page: 1,
pageSize: 10,
loadStatus: 'loadmore', // loadmore, loading, nomore
}
},
onLoad() {
uni.setNavigationBarTitle({
title: '市场动态-业绩',
})
this.fetchData(true)
},
onReachBottom() {
if (this.loadStatus === 'nomore' || this.loadStatus === 'loading') {
return
}
this.page++
this.fetchData()
},
methods: {
formatMemberInfo(member) {
if (!member) return ''
// 使用 award 字段来表示会员的奖励或头衔
const { memberCode, nickName, grade, award } = member
let info = `${memberCode}/${nickName}/${grade}`
// 当 award 存在且不为 "无" 时,才将其拼接到会员信息中
if (award && award !== '无') {
info += `/${award}`
}
return info
},
search() {
this.fetchData(true)
},
// 映射API数据到组件内使用的数据结构
mapApiDataToMember(apiData) {
if (!apiData) return null
return {
memberId: apiData.pkId || apiData.memberCode, // 使用 pkId 作为唯一标识
memberCode: apiData.memberCode,
nickName: apiData.memberName,
grade: apiData.gradeName,
award: apiData.awardsName,
todayAchievement: parseFloat(apiData.todayPv || 0).toFixed(2),
yesterdayAchievement: parseFloat(apiData.yesterdayPv || 0).toFixed(2),
monthAchievement: parseFloat(apiData.currentMonthPv || 0).toFixed(2),
lastMonthAchievement: parseFloat(apiData.lastMonthPv || 0).toFixed(2),
}
},
// 获取会员列表数据
async fetchData(isRefresh = false) {
if (isRefresh) {
this.page = 1
this.memberList = []
this.topMember = null
}
this.loadStatus = 'loading'
try {
const res = await marketDynamicsList({
pageNum: this.page,
pageSize: this.pageSize,
keyWords: this.keyword,
queryType: 2,
})
if (res.code === 200 && res.data) {
// 在刷新时,更新顶部特殊会员信息
if (this.page === 1 && res.data.bigRange) {
this.topMember = this.mapApiDataToMember(res.data.bigRange)
}
const newMembers = res.data.rows.map(item =>
this.mapApiDataToMember(item)
)
this.memberList = [...this.memberList, ...newMembers]
// 根据返回的数据量判断是否还有更多数据
if (
newMembers.length < this.pageSize ||
this.memberList.length >= res.data.total
) {
this.loadStatus = 'nomore'
} else {
this.loadStatus = 'loadmore'
}
} else {
// 接口异常或无数据时,标记为没有更多数据
this.loadStatus = 'nomore'
}
} 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>