448 lines
14 KiB
Vue
448 lines
14 KiB
Vue
<template>
|
|
<view class="member-mall">
|
|
<view class="section-header">
|
|
<text class="section-title">会员商城</text>
|
|
</view>
|
|
<!-- 会员总数 -->
|
|
<view class="member-sum-box">
|
|
<view class="member-sum-box-left">会员总数</view>
|
|
<view class="member-sum-total">{{ memberData.totalMembers ? memberData.totalMembers.toLocaleString() : 0 }}
|
|
</view>
|
|
<view class="member-sum-box-right">本月新增 {{ memberData.monthNewMembers ?
|
|
memberData.monthNewMembers.toLocaleString() : 0 }} 个</view>
|
|
</view>
|
|
|
|
<!-- 近30天数据 -->
|
|
<view class="section-header">
|
|
<text class="section-title">近30天数据</text>
|
|
</view>
|
|
|
|
<view class="recent-data">
|
|
<view class="recent-data-top">
|
|
<view class="recent-data-top-item" style="left: 0;top: 0;">
|
|
<view class="recent-data-top-value">{{ memberData.newMembersCount ?
|
|
memberData.newMembersCount.toLocaleString() : 0
|
|
}}
|
|
</view>
|
|
<view class="recent-data-top-label">新增会员数</view>
|
|
</view>
|
|
|
|
<view class="recent-data-top-item" style="left: 30%;top: 0;">
|
|
<view class="recent-data-top-value">{{ memberData.openCount ? memberData.openCount.toLocaleString()
|
|
: 0 }}</view>
|
|
<view class="recent-data-top-label">打开次数</view>
|
|
</view>
|
|
|
|
<view class="recent-data-top-item" style="right: 30%;top: 0;">
|
|
<view class="recent-data-top-value">{{ memberData.newPeopleCount ?
|
|
memberData.newPeopleCount.toLocaleString() : 0 }}
|
|
</view>
|
|
<view class="recent-data-top-label">新增人数</view>
|
|
</view>
|
|
|
|
<view class="recent-data-top-item" style="right: 0;top: 0;">
|
|
<view class="recent-data-top-value">{{ memberData.visitCount ?
|
|
memberData.visitCount.toLocaleString() : 0 }}</view>
|
|
<view class="recent-data-top-label">访问人数</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 会员消费情况 -->
|
|
<view class="section-header">
|
|
<text class="section-title">会员消费情况</text>
|
|
</view>
|
|
|
|
<view class="member-consumption">
|
|
<view class="member-consumption-item">
|
|
<view class="member-consumption-label">会员消费笔数/笔</view>
|
|
<view class="member-consumption-progress"></view>
|
|
<view class="member-consumption-value">{{ memberData.consumptionCount ? memberData.consumptionCount : 0
|
|
}}</view>
|
|
</view>
|
|
|
|
<view class="member-consumption-item">
|
|
<view class="member-consumption-label">会员总销售额/元</view>
|
|
<view class="member-consumption-progress2"></view>
|
|
<view class="member-consumption-value">{{ memberData.totalSalesAmount }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="member-content-box">
|
|
<view class="member-content-box-item">
|
|
<view class="member-content-box-item-box">
|
|
<view class="member-content-box-item-label">工会会员</view>
|
|
<view class="member-content-box-item-value">{{ memberData.unionMembers || 0 }}</view>
|
|
</view>
|
|
<view class="member-content-box-item-box" style="margin-top: 18px;">
|
|
<view class="member-content-box-item-label">会员占比</view>
|
|
<view class="member-content-box-item-value">{{ (memberData.memberRatio || 0) + '%' }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="member-content-box-item">
|
|
<view class="member-content-box-item-box">
|
|
<view class="member-content-box-item-label">会员转化率</view>
|
|
<view class="member-content-box-item-value">{{ (memberData.conversionRate || 0) + '%' }}</view>
|
|
</view>
|
|
<view class="member-content-box-item-box" style="margin-top: 18px;">
|
|
<view class="member-content-box-item-label">会员增长率</view>
|
|
<view class="member-content-box-item-value">{{ (memberData.growthRate || 0) + '%' }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 会员消费数据概览 -->
|
|
<view class="section-header">
|
|
<text class="section-title">会员消费数据概览</text>
|
|
</view>
|
|
|
|
<view class="member-overview">
|
|
<view class="member-overview-item">
|
|
<view class="member-overview-item-top">{{ memberData.buyPeopleCount || 0 }}</view>
|
|
<view class="member-overview-item-bottom">购买人数</view>
|
|
</view>
|
|
|
|
<view class="member-overview-item">
|
|
<view class="member-overview-item-top">{{ memberData.avgAmount || 0 }}</view>
|
|
<view class="member-overview-item-bottom">人均消费</view>
|
|
</view>
|
|
|
|
<view class="member-overview-item">
|
|
<view class="member-overview-item-top">{{ (memberData.repurchaseRate || 0) }}</view>
|
|
<view class="member-overview-item-bottom">客单价</view>
|
|
</view>
|
|
|
|
<view class="member-overview-item">
|
|
<view class="member-overview-item-top">{{ (memberData.totalAmount || 0) + '%' }}</view>
|
|
<view class="member-overview-item-bottom">会员复购率</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import request from "@/util/index.js";
|
|
import moment from 'moment'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
memberData: {
|
|
totalMembers: 0,
|
|
monthNewMembers: 0,
|
|
newMembersCount: 0,
|
|
openCount: 0,
|
|
newPeopleCount: 0,
|
|
visitCount: 0,
|
|
consumptionCount: 0,
|
|
totalSalesAmount: 0,
|
|
unionMembers: 0,
|
|
memberRatio: 0,
|
|
conversionRate: 0,
|
|
growthRate: 0,
|
|
buyPeopleCount: 0,
|
|
avgAmount: 0,
|
|
repurchaseRate: 0,
|
|
totalAmount: 0
|
|
}
|
|
}
|
|
},
|
|
props: {
|
|
selectTime: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
},
|
|
watch: {
|
|
selectTime: {
|
|
handler(newVal, oldVal) {
|
|
if (newVal !== oldVal) {
|
|
this.handleGetMemberMallData()
|
|
}
|
|
},
|
|
immediate: false
|
|
}
|
|
},
|
|
onReady() {
|
|
this.handleGetMemberMallData()
|
|
},
|
|
|
|
methods: {
|
|
// 获取会员商城数据
|
|
async handleGetMemberMallData() {
|
|
const req = {
|
|
ProvinceCode: '530000',
|
|
StatisticsDate: this.selectTime ? moment(this.selectTime).subtract(1, 'd').format('YYYY-MM-DD') : moment().subtract(1, 'd').format('YYYY-MM-DD')
|
|
}
|
|
|
|
const data = await this.getMemberMallData(req);
|
|
|
|
// 处理数据
|
|
this.processChartData(data)
|
|
},
|
|
|
|
// 发起API请求获取会员商城数据
|
|
async getMemberMallData(params) {
|
|
// 写死数据返回
|
|
const mockData = {
|
|
totalMembers: 15071,
|
|
monthNewMembers: 146,
|
|
newMembersCount: 270,
|
|
openCount: 3203,
|
|
newPeopleCount: 757,
|
|
visitCount: 1914,
|
|
consumptionCount: 104,
|
|
totalSalesAmount: '47, 550.60',
|
|
unionMembers: 1782,
|
|
memberRatio: 11.82,
|
|
conversionRate: 32.17,
|
|
growthRate: 0.97,
|
|
buyPeopleCount: 99,
|
|
avgAmount: 480.31,
|
|
repurchaseRate: 461.66,
|
|
totalAmount: 2.02
|
|
}
|
|
|
|
return mockData || {}
|
|
},
|
|
|
|
// 处理图表数据
|
|
processChartData(data) {
|
|
// 更新数据
|
|
this.memberData = {
|
|
totalMembers: data.totalMembers || 0,
|
|
monthNewMembers: data.monthNewMembers || 0,
|
|
newMembersCount: data.newMembersCount || 0,
|
|
openCount: data.openCount || 0,
|
|
newPeopleCount: data.newPeopleCount || 0,
|
|
visitCount: data.visitCount || 0,
|
|
consumptionCount: data.consumptionCount || 0,
|
|
totalSalesAmount: data.totalSalesAmount || 0,
|
|
unionMembers: data.unionMembers || 0,
|
|
memberRatio: data.memberRatio || 0,
|
|
conversionRate: data.conversionRate || 0,
|
|
growthRate: data.growthRate || 0,
|
|
buyPeopleCount: data.buyPeopleCount || 0,
|
|
avgAmount: data.avgAmount || 0,
|
|
repurchaseRate: data.repurchaseRate || 0,
|
|
totalAmount: data.totalAmount || 0
|
|
}
|
|
|
|
},
|
|
|
|
// 格式化金额
|
|
formatMoney(amount) {
|
|
if (!amount || amount === 0) return '0.00'
|
|
return Number(amount).toLocaleString('zh-CN', {
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
@text-primary: #333;
|
|
@text-secondary: #666;
|
|
@bg-white: #ffffff;
|
|
|
|
.member-mall {
|
|
width: 100%;
|
|
|
|
.member-sum-box {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 18rpx 24rpx;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
margin-bottom: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
|
|
.member-sum-box-left {
|
|
font-size: 24rpx;
|
|
font-weight: 600;
|
|
color: @text-primary;
|
|
}
|
|
|
|
.member-sum-total {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #1890FF;
|
|
}
|
|
|
|
.member-sum-box-right {
|
|
font-size: 24rpx;
|
|
font-weight: 400;
|
|
color: @text-secondary;
|
|
text-align: right;
|
|
}
|
|
}
|
|
|
|
.section-header {
|
|
margin-bottom: 12rpx;
|
|
|
|
.section-title {
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: @text-primary;
|
|
}
|
|
}
|
|
|
|
.recent-data {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
margin-bottom: 24rpx;
|
|
height: 136rpx;
|
|
|
|
.recent-data-top {
|
|
width: 100%;
|
|
height: 136rpx;
|
|
position: relative;
|
|
|
|
.recent-data-top-item {
|
|
position: absolute;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
.recent-data-top-value {
|
|
width: 88rpx;
|
|
height: 88rpx;
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
line-height: 88rpx;
|
|
text-align: center;
|
|
background: linear-gradient(135deg, #1890ff 0%, #46B8F3 100%);
|
|
border-radius: 50%;
|
|
box-shadow: 0 4rpx 12rpx rgba(24, 144, 255, 0.3);
|
|
}
|
|
|
|
.recent-data-top-label {
|
|
font-size: 24rpx;
|
|
color: @text-secondary;
|
|
line-height: 36rpx;
|
|
text-align: center;
|
|
margin-top: 10rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.member-content-box {
|
|
display: flex;
|
|
gap: 24rpx;
|
|
margin-bottom: 32rpx;
|
|
|
|
.member-content-box-item {
|
|
flex: 1;
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
text-align: center;
|
|
|
|
.member-content-box-item-box {
|
|
margin-bottom: 18rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.member-content-box-item-label {
|
|
font-size: 24rpx;
|
|
color: @text-primary;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.member-content-box-item-value {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #1890FF;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.member-consumption {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 24rpx;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
margin-bottom: 24rpx;
|
|
|
|
.member-consumption-item {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 18rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.member-consumption-label {
|
|
font-size: 24rpx;
|
|
color: @text-primary;
|
|
width: 190rpx;
|
|
}
|
|
|
|
.member-consumption-progress {
|
|
flex: 1;
|
|
height: 24rpx;
|
|
background: linear-gradient(90deg, #1890ff 0%, #46B8F3 100%);
|
|
border-radius: 22rpx;
|
|
margin: 0 24rpx;
|
|
}
|
|
|
|
.member-consumption-progress2 {
|
|
flex: 1;
|
|
height: 24rpx;
|
|
background: linear-gradient(90deg, #52C41A 0%, #3CD495 100%);
|
|
border-radius: 22rpx;
|
|
margin: 0 24rpx;
|
|
}
|
|
|
|
.member-consumption-value {
|
|
font-size: 24rpx;
|
|
font-weight: 600;
|
|
color: @text-primary;
|
|
width: 190rpx;
|
|
text-align: right;
|
|
}
|
|
}
|
|
}
|
|
|
|
.member-overview {
|
|
display: flex;
|
|
width: 100%;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.member-overview-item {
|
|
width: calc(25% - 18rpx);
|
|
box-sizing: border-box;
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 12rpx;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
text-align: center;
|
|
|
|
.member-overview-item-top {
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
color: #1890FF;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.member-overview-item-bottom {
|
|
font-size: 24rpx;
|
|
color: @text-primary;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |