feat(dashboard): add daily and monthly recharge rankings
This commit is contained in:
parent
8e2e3feaca
commit
62632adc7e
@ -80,6 +80,15 @@ export function listDailyUserRechargeTop(dateNumber) {
|
||||
})
|
||||
}
|
||||
|
||||
// 用户日/月充值排行榜(服务端分页)
|
||||
export function pageUserRechargeRank(params) {
|
||||
return request({
|
||||
url: '/count/currency/user-recharge-rank/page',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 最新平台内购情况
|
||||
export function latestPurchaseAmountPlatform(areaCode) {
|
||||
return request({
|
||||
|
||||
@ -4199,7 +4199,7 @@ export default {
|
||||
dailyGoldAnalysis: 'Daily Gold Analysis',
|
||||
dailyGoldSourceTop: 'Daily Gold Source Top',
|
||||
userGoldTop: 'User Gold Top 50',
|
||||
dailyRechargeTop: 'Daily Recharge Top 50'
|
||||
dailyRechargeTop: 'Recharge Ranking'
|
||||
},
|
||||
account: {
|
||||
accountLabel: 'Account'
|
||||
@ -4332,8 +4332,14 @@ export default {
|
||||
},
|
||||
rechargeTop: {
|
||||
datePlaceholder: 'Select date',
|
||||
title: 'Recharge Top 50 ({sysOriginName})',
|
||||
description: 'Same-day total recharge amount, including refunds',
|
||||
monthPlaceholder: 'Select month',
|
||||
platformPlaceholder: 'Select platform',
|
||||
title: 'Recharge Ranking ({sysOriginName})',
|
||||
descriptionDaily: 'Recharge total from 08:00 on the selected day to 08:00 the next day, including refunds',
|
||||
descriptionMonthly: 'Net recharge total for the selected month, with refunds deducted',
|
||||
daily: 'Daily',
|
||||
monthly: 'Monthly',
|
||||
rank: 'Rank',
|
||||
user: 'User',
|
||||
amount: 'Amount'
|
||||
},
|
||||
|
||||
@ -4196,7 +4196,7 @@ export default {
|
||||
dailyGoldAnalysis: '每日金币(分析)',
|
||||
dailyGoldSourceTop: '每日金币(来源榜)',
|
||||
userGoldTop: '用户金币(Top50)',
|
||||
dailyRechargeTop: '每日充值(Top50)'
|
||||
dailyRechargeTop: '充值排行榜'
|
||||
},
|
||||
account: {
|
||||
accountLabel: '账号'
|
||||
@ -4329,8 +4329,14 @@ export default {
|
||||
},
|
||||
rechargeTop: {
|
||||
datePlaceholder: '选择日期',
|
||||
title: '充值Top50({sysOriginName})',
|
||||
description: '当日充值总额,包含退款',
|
||||
monthPlaceholder: '选择月份',
|
||||
platformPlaceholder: '选择平台',
|
||||
title: '充值排行榜({sysOriginName})',
|
||||
descriptionDaily: '所选统计日08:00至次日08:00的充值总额,包含退款',
|
||||
descriptionMonthly: '所选月份的净充值总额,退款金额会扣除',
|
||||
daily: '日榜',
|
||||
monthly: '月榜',
|
||||
rank: '排名',
|
||||
user: '用户',
|
||||
amount: '金额'
|
||||
},
|
||||
|
||||
@ -1,134 +1,196 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="dily-register-user" :data-language="language">
|
||||
<el-date-picker
|
||||
v-model="dateNumber"
|
||||
style="margin-bottom: 10px;"
|
||||
type="date"
|
||||
:placeholder="$t('pages.dashboard.rechargeTop.datePlaceholder')"
|
||||
value-format="yyyyMMdd"
|
||||
size="mini"
|
||||
:picker-options="pickerOptions"
|
||||
:clearable="false"
|
||||
@change="changeDateNumber"
|
||||
/>
|
||||
<div v-for="(item, index) in list" :key="index">
|
||||
<el-card v-if="sysOriginPlatforms.includes(item.sysOrigin)" class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>{{ $t('pages.dashboard.rechargeTop.title', { sysOriginName: item.sysOriginName }) }}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div style="font-size: 12px;color: #666;margin-bottom: 10px;">{{ $t('pages.dashboard.rechargeTop.description') }}</div>
|
||||
<el-table
|
||||
:data="item.items"
|
||||
element-loading-text="Loading"
|
||||
fit
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column label="No" width="50" align="center">
|
||||
<template slot-scope="scope">{{ scope.$index + 1 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('pages.dashboard.rechargeTop.user')" prop="roomProfile.roomName" align="center" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
<user-table-exhibit :user-profile="scope.row.userProfile" :query-details="true" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('pages.dashboard.rechargeTop.amount')" min-width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.quantity || 0 }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<div v-loading="loading" class="user-recharge-rank" :data-language="language">
|
||||
<div class="query-bar">
|
||||
<el-radio-group v-model="listQuery.periodType" size="mini" @change="changePeriodType">
|
||||
<el-radio-button label="DAILY">{{ $t('pages.dashboard.rechargeTop.daily') }}</el-radio-button>
|
||||
<el-radio-button label="MONTHLY">{{ $t('pages.dashboard.rechargeTop.monthly') }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
<el-select
|
||||
v-model="listQuery.sysOrigin"
|
||||
size="mini"
|
||||
:placeholder="$t('pages.dashboard.rechargeTop.platformPlaceholder')"
|
||||
@change="handleSearch"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in permissionsSysOriginPlatformAlls"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-date-picker
|
||||
v-if="listQuery.periodType === 'DAILY'"
|
||||
v-model="listQuery.periodNumber"
|
||||
type="date"
|
||||
value-format="yyyyMMdd"
|
||||
size="mini"
|
||||
:clearable="false"
|
||||
:picker-options="dailyPickerOptions"
|
||||
:placeholder="$t('pages.dashboard.rechargeTop.datePlaceholder')"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-else
|
||||
v-model="listQuery.periodNumber"
|
||||
type="month"
|
||||
value-format="yyyyMM"
|
||||
size="mini"
|
||||
:clearable="false"
|
||||
:picker-options="monthlyPickerOptions"
|
||||
:placeholder="$t('pages.dashboard.rechargeTop.monthPlaceholder')"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>{{ $t('pages.dashboard.rechargeTop.title', { sysOriginName: selectedOriginName }) }}</span>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ listQuery.periodType === 'DAILY'
|
||||
? $t('pages.dashboard.rechargeTop.descriptionDaily')
|
||||
: $t('pages.dashboard.rechargeTop.descriptionMonthly') }}
|
||||
</div>
|
||||
<el-table :data="list" element-loading-text="Loading" fit highlight-current-row>
|
||||
<el-table-column :label="$t('pages.dashboard.rechargeTop.rank')" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ (listQuery.cursor - 1) * listQuery.limit + scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('pages.dashboard.rechargeTop.user')" align="center" min-width="220">
|
||||
<template slot-scope="scope">
|
||||
<user-table-exhibit
|
||||
v-if="scope.row.userProfile"
|
||||
:user-profile="scope.row.userProfile"
|
||||
:query-details="true"
|
||||
/>
|
||||
<span v-else>{{ scope.row.userId }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('pages.dashboard.rechargeTop.amount')" min-width="120" align="center">
|
||||
<template slot-scope="scope">{{ scope.row.quantity || 0 }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="listQuery.cursor"
|
||||
:limit.sync="listQuery.limit"
|
||||
@pagination="loadRank"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listDailyUserRechargeTop } from '@/api/statistics'
|
||||
import { currencyOrigins } from '@/constant/type'
|
||||
import { pageUserRechargeRank } from '@/api/statistics'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { formatDate, beforeDateObject } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'DilyRegisterUser',
|
||||
name: 'UserRechargeRank',
|
||||
components: { Pagination },
|
||||
data() {
|
||||
return {
|
||||
pickerOptions: {
|
||||
loading: false,
|
||||
list: [],
|
||||
total: 0,
|
||||
dailyPeriodNumber: formatDate(beforeDateObject(1), 'yyyyMMdd'),
|
||||
monthlyPeriodNumber: formatDate(new Date(), 'yyyyMM'),
|
||||
dailyPickerOptions: {
|
||||
disabledDate(date) {
|
||||
return date.getTime() > beforeDateObject(1).getTime()
|
||||
}
|
||||
},
|
||||
dateNumber: formatDate(beforeDateObject(new Date().getHours() >= 8 ? 1 : 2), 'yyyyMMdd'),
|
||||
loading: false,
|
||||
list: [],
|
||||
queryDetailsRow: {},
|
||||
selectOrigin: currencyOrigins[0].value,
|
||||
selectOriginName: currencyOrigins[0].name
|
||||
monthlyPickerOptions: {
|
||||
disabledDate(date) {
|
||||
const now = new Date()
|
||||
return date.getFullYear() > now.getFullYear() ||
|
||||
(date.getFullYear() === now.getFullYear() && date.getMonth() > now.getMonth())
|
||||
}
|
||||
},
|
||||
listQuery: {
|
||||
cursor: 1,
|
||||
limit: 20,
|
||||
sysOrigin: '',
|
||||
periodType: 'DAILY',
|
||||
periodNumber: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permissionsSysOriginPlatformAlls', 'language']),
|
||||
sysOriginPlatforms() {
|
||||
if (!this.permissionsSysOriginPlatformAlls || this.permissionsSysOriginPlatformAlls.length <= 0) {
|
||||
return []
|
||||
}
|
||||
return this.permissionsSysOriginPlatformAlls.map(item => item.value)
|
||||
selectedOriginName() {
|
||||
const selected = (this.permissionsSysOriginPlatformAlls || [])
|
||||
.find(item => item.value === this.listQuery.sysOrigin)
|
||||
return selected ? selected.name : this.listQuery.sysOrigin
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadOrigin()
|
||||
const firstOrigin = (this.permissionsSysOriginPlatformAlls || [])[0]
|
||||
if (!firstOrigin) {
|
||||
return
|
||||
}
|
||||
this.listQuery.sysOrigin = firstOrigin.value
|
||||
this.listQuery.periodNumber = this.dailyPeriodNumber
|
||||
this.loadRank()
|
||||
},
|
||||
methods: {
|
||||
loadOrigin() {
|
||||
changePeriodType(periodType) {
|
||||
// 分别保留日榜和月榜的选择值,切换周期时不会把 yyyyMMdd 错当成 yyyyMM 提交。
|
||||
this.listQuery.periodNumber = periodType === 'DAILY'
|
||||
? this.dailyPeriodNumber
|
||||
: this.monthlyPeriodNumber
|
||||
this.handleSearch()
|
||||
},
|
||||
handleSearch() {
|
||||
if (this.listQuery.periodType === 'DAILY') {
|
||||
this.dailyPeriodNumber = this.listQuery.periodNumber
|
||||
} else {
|
||||
this.monthlyPeriodNumber = this.listQuery.periodNumber
|
||||
}
|
||||
this.listQuery.cursor = 1
|
||||
this.loadRank()
|
||||
},
|
||||
loadRank() {
|
||||
if (!this.listQuery.sysOrigin || !this.listQuery.periodNumber) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
listDailyUserRechargeTop(this.dateNumber).then(res => {
|
||||
pageUserRechargeRank(this.listQuery).then(res => {
|
||||
const body = res.body || {}
|
||||
this.list = body.records || []
|
||||
this.total = Number(body.total || 0)
|
||||
this.loading = false
|
||||
const { body } = res
|
||||
const list = body || []
|
||||
this.list = list.filter(item => !item.sysOrigin || this.permissionsSysOriginPlatformAlls.some(sys => sys.value === item.sysOrigin))
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
querySearch(queryString, cb) {
|
||||
const restaurants = currencyOrigins
|
||||
const results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
|
||||
cb(results)
|
||||
},
|
||||
createFilter(queryString) {
|
||||
return restaurant => {
|
||||
return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) >= 0 ||
|
||||
restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) >= 0
|
||||
}
|
||||
},
|
||||
handleSelect(item) {
|
||||
const selectedItem = item || currencyOrigins[0]
|
||||
this.selectOrigin = selectedItem.value
|
||||
this.selectOriginName = selectedItem.name
|
||||
this.loadOrigin()
|
||||
},
|
||||
changeDateNumber() {
|
||||
this.loadOrigin()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.box-card {
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
|
||||
.card-col {
|
||||
.user-recharge-rank {
|
||||
.query-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.register-logout-count {
|
||||
.date {
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
.box-card {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-bottom: 10px;
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user