feat(bonus): 奖金页面调整
This commit is contained in:
parent
f5cae88636
commit
d98b9bd93c
|
@ -79,7 +79,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
async open() {
|
async open() {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
if (this.areaTree.length === 0) {
|
if (this.areaTree?.length === 0) {
|
||||||
await this.loadAreaTree()
|
await this.loadAreaTree()
|
||||||
}
|
}
|
||||||
this.popupVisible = true
|
this.popupVisible = true
|
||||||
|
|
|
@ -20,3 +20,7 @@ export const nextRound = params =>
|
||||||
|
|
||||||
export const realTimeBonus = () =>
|
export const realTimeBonus = () =>
|
||||||
http.post('/bonus/api/bonus/query-current-bonus')
|
http.post('/bonus/api/bonus/query-current-bonus')
|
||||||
|
|
||||||
|
//奖金明细列表
|
||||||
|
export const queryBonusList = params =>
|
||||||
|
http.post('/bonus/api/bonus/query-bonus-first/', { params })
|
||||||
|
|
|
@ -53,10 +53,6 @@ export const updateData = data =>
|
||||||
export const queryBonusDetail = (data, data1) =>
|
export const queryBonusDetail = (data, data1) =>
|
||||||
http.post('/bonus/api/bonus/query-bonus-detail/' + data1, data)
|
http.post('/bonus/api/bonus/query-bonus-detail/' + data1, data)
|
||||||
|
|
||||||
//首购收益
|
|
||||||
export const queryBonusFirst = (data, data1) =>
|
|
||||||
http.post('/bonus/api/bonus/query-bonus-first/' + data1, data)
|
|
||||||
|
|
||||||
//复购收益
|
//复购收益
|
||||||
export const queryBonusRepurchase = (data, data1) =>
|
export const queryBonusRepurchase = (data, data1) =>
|
||||||
http.post('/bonus/api/bonus/query-bonus-repurchase/' + data1, data)
|
http.post('/bonus/api/bonus/query-bonus-repurchase/' + data1, data)
|
||||||
|
|
14
pages.json
14
pages.json
|
@ -302,6 +302,20 @@
|
||||||
"navigationBarBackgroundColor": "#fff"
|
"navigationBarBackgroundColor": "#fff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/mine/marketDynamic/achievement-list",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "市场动态",
|
||||||
|
"navigationBarBackgroundColor": "#fff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/mine/marketDynamic/box-list",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "市场盒数",
|
||||||
|
"navigationBarBackgroundColor": "#fff"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/shareRegist/success",
|
"path": "pages/shareRegist/success",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
<view class="summary-bar">
|
<view class="summary-bar">
|
||||||
<text class="summary-text"
|
<text class="summary-text"
|
||||||
>今日实发合计:
|
>今日实发合计:
|
||||||
<text class="summary-amount">{{
|
<text class="summary-amount">{{ todayTotal }}</text></text
|
||||||
formatAmount(todayTotal)
|
|
||||||
}}</text></text
|
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
@ -58,16 +56,12 @@
|
||||||
class="bonus-item"
|
class="bonus-item"
|
||||||
>
|
>
|
||||||
<text class="item-label">{{ fieldName }}(¥)</text>
|
<text class="item-label">{{ fieldName }}(¥)</text>
|
||||||
<text class="item-value">{{
|
<text class="item-value">{{ dailyBonus[fieldKey] }}</text>
|
||||||
formatAmount(dailyBonus[fieldKey])
|
|
||||||
}}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-footer">
|
<view class="card-footer">
|
||||||
<text class="subtotal-label">小计(¥)</text>
|
<text class="subtotal-label">小计(¥)</text>
|
||||||
<text class="subtotal-value">{{
|
<text class="subtotal-value">{{ dailyBonus.subtotal }}</text>
|
||||||
formatAmount(dailyBonus.subtotal)
|
|
||||||
}}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
@ -100,7 +94,7 @@
|
||||||
// 注意: 后端API需要支持按日期范围查询奖金明细
|
// 注意: 后端API需要支持按日期范围查询奖金明细
|
||||||
// import { getBonusDetailsByDate, getTodayBonusTotal } from '@/config/bonus.js';
|
// import { getBonusDetailsByDate, getTodayBonusTotal } from '@/config/bonus.js';
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import { queryBonusTotal, queryBonusList } from '@/config/bonus'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -119,26 +113,21 @@ export default {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
},
|
},
|
||||||
BONUS_FIELD_MAP: {
|
BONUS_FIELD_MAP: {
|
||||||
levelGapIncome: '直推收益',
|
retailRangeIncome: '直推收益',
|
||||||
peerIncome: '平级收益',
|
retailSameLevelIncome: '平级收益',
|
||||||
regionalIncome: '区域收益',
|
retailAreaIncome: '区域收益',
|
||||||
welfareLevelGapIncome: '福利级差收益',
|
// welfareLevelGapIncome: '福利级差收益',
|
||||||
welfareDividendIncome: '福利分红收益',
|
// welfareDividendIncome: '福利分红收益',
|
||||||
repeatConsumptionIncome: '重消收益',
|
backPoints: '重消收益',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.setDefaultDateRange()
|
this.setDefaultDateRange()
|
||||||
this.handleSearch()
|
this.handleSearch()
|
||||||
|
this.getBonusTotal()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatAmount(amount) {
|
|
||||||
if (typeof amount !== 'number') {
|
|
||||||
return '0.00'
|
|
||||||
}
|
|
||||||
return amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
||||||
},
|
|
||||||
setDefaultDateRange() {
|
setDefaultDateRange() {
|
||||||
const end = new Date()
|
const end = new Date()
|
||||||
const start = new Date()
|
const start = new Date()
|
||||||
|
@ -189,80 +178,34 @@ export default {
|
||||||
this.page.pageNum++
|
this.page.pageNum++
|
||||||
this.fetchBonusData()
|
this.fetchBonusData()
|
||||||
},
|
},
|
||||||
// 模拟数据获取
|
getBonusTotal() {
|
||||||
|
queryBonusTotal().then(res => {
|
||||||
|
this.todayTotal = res.data.todayTotal
|
||||||
|
})
|
||||||
|
},
|
||||||
async fetchBonusData() {
|
async fetchBonusData() {
|
||||||
if (this.loading) return
|
if (this.loading) return
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
// 模拟API调用延时
|
try {
|
||||||
await new Promise(resolve => setTimeout(resolve, 800))
|
const params = {
|
||||||
|
startDate: this.startDate,
|
||||||
// TODO: 当后端API就绪时,替换下面的模拟数据逻辑
|
endDate: this.endDate,
|
||||||
// 实际调用:
|
pageNum: this.page.pageNum,
|
||||||
// try {
|
pageSize: this.page.pageSize,
|
||||||
// const params = { startDate: this.startDate, endDate: this.endDate, pageNum: this.page.pageNum, pageSize: this.page.pageSize };
|
|
||||||
// const res = await getBonusDetailsByDate(params);
|
|
||||||
// if (res.data.list.length < this.page.pageSize) {
|
|
||||||
// this.hasMore = false;
|
|
||||||
// }
|
|
||||||
// this.bonusList = [...this.bonusList, ...res.data.list];
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Failed to fetch bonus data:", error);
|
|
||||||
// uni.showToast({ title: '数据加载失败', icon: 'none' });
|
|
||||||
// } finally {
|
|
||||||
// this.loading = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// --- 模拟数据生成 ---
|
|
||||||
this.todayTotal = Math.random() * 1000
|
|
||||||
const mockData = []
|
|
||||||
// 模拟 "没有更多数据"
|
|
||||||
if (this.page.pageNum > 3) {
|
|
||||||
this.hasMore = false
|
|
||||||
this.loading = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.startDate && this.endDate) {
|
|
||||||
// 在模拟中,我们基于页码创建伪随机数据,而不是日期
|
|
||||||
for (let i = 0; i < this.page.pageSize; i++) {
|
|
||||||
const dayOffset = (this.page.pageNum - 1) * this.page.pageSize + i
|
|
||||||
const date = dayjs(this.endDate).subtract(dayOffset, 'day')
|
|
||||||
if (date.isBefore(dayjs(this.startDate))) {
|
|
||||||
this.hasMore = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
const bonusDetails = {
|
|
||||||
levelGapIncome: Math.random() * 100,
|
|
||||||
peerIncome: Math.random() * 200,
|
|
||||||
regionalIncome: 0,
|
|
||||||
welfareLevelGapIncome: 0,
|
|
||||||
welfareDividendIncome: 0,
|
|
||||||
repeatConsumptionIncome: Math.random() * 50,
|
|
||||||
}
|
|
||||||
|
|
||||||
const subtotal = Object.values(bonusDetails).reduce(
|
|
||||||
(sum, value) => sum + value,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
mockData.push({
|
|
||||||
date: date.format('YYYY-MM-DD'),
|
|
||||||
...bonusDetails,
|
|
||||||
subtotal: subtotal,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
const res = await queryBonusList(params)
|
||||||
|
console.log(res)
|
||||||
|
if (res.rows.length < this.page.pageSize) {
|
||||||
|
this.hasMore = false
|
||||||
|
}
|
||||||
|
this.bonusList = [...this.bonusList, ...res.rows]
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch bonus data:', error)
|
||||||
|
uni.showToast({ title: '数据加载失败', icon: 'none' })
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mockData.length < this.page.pageSize) {
|
|
||||||
this.hasMore = false
|
|
||||||
}
|
|
||||||
|
|
||||||
this.bonusList = [...this.bonusList, ...mockData]
|
|
||||||
// --- 模拟数据结束 ---
|
|
||||||
|
|
||||||
this.loading = false
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@
|
||||||
<view class="market-stats-container">
|
<view class="market-stats-container">
|
||||||
<view
|
<view
|
||||||
class="stat-block primary"
|
class="stat-block primary"
|
||||||
@click="goTo('/pages/performanceEchart/index')"
|
@click="goTo('/pages/mine/marketDynamic/achievement-list')"
|
||||||
>
|
>
|
||||||
<view class="stat-content">
|
<view class="stat-content">
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
|
@ -302,7 +302,7 @@
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="stat-block secondary"
|
class="stat-block secondary"
|
||||||
@click="goTo('/pages/mine/order/index')"
|
@click="goTo('/pages/mine/marketDynamic/box-list')"
|
||||||
>
|
>
|
||||||
<view class="stat-content">
|
<view class="stat-content">
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
|
@ -746,7 +746,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getMarketDynamicBoxCount() {
|
getMarketDynamicBoxCount() {
|
||||||
console.log('🌈ad', this.userInfo)
|
|
||||||
getMarketDynamicBoxCount({
|
getMarketDynamicBoxCount({
|
||||||
pkBigMember: this.userInfo.memberCode,
|
pkBigMember: this.userInfo.memberCode,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
|
|
@ -0,0 +1,301 @@
|
||||||
|
<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>
|
||||||
|
// 假设的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.fetchTopMember()
|
||||||
|
this.fetchMemberList(true)
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.loadStatus === 'nomore' || this.loadStatus === 'loading') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.page++
|
||||||
|
this.fetchMemberList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
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 ---
|
||||||
|
this.topMember = {
|
||||||
|
memberId: 'HZS32223336', // Using memberId as key
|
||||||
|
memberCode: 'HZS32223336',
|
||||||
|
nickName: '小新哥',
|
||||||
|
grade: 'V5',
|
||||||
|
award: 'W1',
|
||||||
|
todayAchievement: 0.0,
|
||||||
|
yesterdayAchievement: 1.0978,
|
||||||
|
monthAchievement: 2.3395,
|
||||||
|
lastMonthAchievement: 10.7727,
|
||||||
|
}
|
||||||
|
// --- REAL API CALL ---
|
||||||
|
// try {
|
||||||
|
// const res = await getMarketAchievementTop({ keyword: this.keyword });
|
||||||
|
// if (res.code === 200) {
|
||||||
|
// this.topMember = res.data;
|
||||||
|
// }
|
||||||
|
// } catch (e) {
|
||||||
|
// console.error(e);
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
// 获取会员列表数据
|
||||||
|
async fetchMemberList(isRefresh = false) {
|
||||||
|
if (isRefresh) {
|
||||||
|
this.page = 1
|
||||||
|
this.memberList = []
|
||||||
|
}
|
||||||
|
this.loadStatus = 'loading'
|
||||||
|
|
||||||
|
// --- MOCK DATA ---
|
||||||
|
const mockData = [
|
||||||
|
{
|
||||||
|
memberId: 'HZS81617255',
|
||||||
|
memberCode: 'HZS81617255',
|
||||||
|
nickName: '小星哥',
|
||||||
|
grade: 'V5',
|
||||||
|
award: 'W1',
|
||||||
|
todayAchievement: 0.0,
|
||||||
|
yesterdayAchievement: 0.0499,
|
||||||
|
monthAchievement: 1.2881,
|
||||||
|
lastMonthAchievement: 26.3515,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 'HZS93817578',
|
||||||
|
memberCode: 'HZS93817578',
|
||||||
|
nickName: '婉琳',
|
||||||
|
grade: 'V5',
|
||||||
|
award: 'W1',
|
||||||
|
todayAchievement: 0.0,
|
||||||
|
yesterdayAchievement: 0.0,
|
||||||
|
monthAchievement: 0.508,
|
||||||
|
lastMonthAchievement: 2.422,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 'HZS55865236',
|
||||||
|
memberCode: 'HZS55865236',
|
||||||
|
nickName: '谭谭',
|
||||||
|
grade: 'V5',
|
||||||
|
award: 'W1',
|
||||||
|
todayAchievement: 0.0,
|
||||||
|
yesterdayAchievement: 0.0,
|
||||||
|
monthAchievement: 0.4261,
|
||||||
|
lastMonthAchievement: 8.5454,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 'HZS67896897',
|
||||||
|
memberCode: 'HZS67896897',
|
||||||
|
nickName: '楠杉',
|
||||||
|
grade: 'V5',
|
||||||
|
award: 'W1',
|
||||||
|
todayAchievement: 0.0,
|
||||||
|
yesterdayAchievement: 0.0,
|
||||||
|
monthAchievement: 0.0,
|
||||||
|
lastMonthAchievement: 0.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 getMarketAchievementList({ page: this.page, size: this.pageSize, keyword: this.keyword });
|
||||||
|
// if (res.code === 200) {
|
||||||
|
// this.memberList = [...this.memberList, ...res.data.records];
|
||||||
|
// 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>
|
|
@ -0,0 +1,304 @@
|
||||||
|
<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>
|
Loading…
Reference in New Issue