209 lines
9.0 KiB
Vue
209 lines
9.0 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<!-- 搜索栏 -->
|
||
<el-row :gutter="10" style="margin-bottom:16px">
|
||
<el-input v-model="queryParams.userId" placeholder="用户ID" clearable @clear="handleSearch" @keyup.enter.native="handleSearch" style="width:130px" />
|
||
<el-input v-model="queryParams.nickName" placeholder="昵称" clearable @clear="handleSearch" @keyup.enter.native="handleSearch" style="width:130px" />
|
||
<el-input v-model="queryParams.phone" placeholder="手机号" clearable @clear="handleSearch" @keyup.enter.native="handleSearch" style="width:150px" />
|
||
<el-date-picker
|
||
v-model="dateRange"
|
||
type="datetimerange"
|
||
range-separator="至"
|
||
start-placeholder="开始时间"
|
||
end-placeholder="结束时间"
|
||
value-format="yyyy-MM-dd HH:mm:ss"
|
||
:default-time="['00:00:00', '23:59:59']"
|
||
:picker-options="pickerOptions"
|
||
style="width:380px"
|
||
/>
|
||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||
</el-row>
|
||
|
||
<!-- 排序提示 -->
|
||
<el-alert :closable="false" style="margin-bottom:12px" type="info">
|
||
当前排序:
|
||
<b>{{ sortLabels[queryParams.sortField] || '总流水' }}</b>
|
||
<span style="margin-left:4px">{{ queryParams.sortOrder === 'asc' ? '↑ 升序' : '↓ 降序' }}</span>
|
||
<span style="margin-left:12px;color:#7a664e">点击表头可切换排序字段和方向</span>
|
||
</el-alert>
|
||
|
||
<!-- 数据表格 -->
|
||
<div style="overflow-x:auto">
|
||
<el-table v-loading="loading" :data="tableData" border @sort-change="handleSortChange" style="width:100%">
|
||
<el-table-column prop="userId" label="用户ID" width="90" align="center" fixed sortable="custom" />
|
||
<el-table-column prop="nickName" label="昵称" width="120" show-overflow-tooltip fixed />
|
||
<el-table-column prop="phone" label="手机号" min-width="120" align="center" />
|
||
<el-table-column label="用户类型" min-width="80" align="center">
|
||
<template slot-scope="scope">
|
||
<el-tag size="mini" :type="userTypeTag(scope.row.userType)">{{ userTypeLabel(scope.row.userType) }}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<!-- 充值 -->
|
||
<el-table-column prop="totalRecharge" label="总充值" min-width="110" align="right" sortable="custom">
|
||
<template slot-scope="scope"><span style="color:#457450">{{ formatMoney(scope.row.totalRecharge) }}</span></template>
|
||
</el-table-column>
|
||
|
||
<!-- 消费流水 -->
|
||
<el-table-column prop="totalTurnover" label="总流水" min-width="110" align="right" sortable="custom">
|
||
<template slot-scope="scope"><span style="color:#a4485a">{{ formatMoney(scope.row.totalTurnover) }}</span></template>
|
||
</el-table-column>
|
||
|
||
<!-- 游戏分类消费 -->
|
||
<el-table-column label="游戏分类消费" align="center">
|
||
<el-table-column prop="classicBox" label="经典开箱" min-width="100" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.classicBox) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="fightGame" label="对战" min-width="80" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.fightGame) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="luckyUpgrade" label="幸运升级" min-width="100" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.luckyUpgrade) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="wheelGame" label="疯狂转盘" min-width="100" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.wheelGame) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="olympusGame" label="玫瑰女郎" min-width="100" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.olympusGame) }}</template>
|
||
</el-table-column>
|
||
<el-table-column prop="rollRoom" label="roll房" min-width="90" align="right" sortable="custom">
|
||
<template slot-scope="scope">{{ formatMoney(scope.row.rollRoom) }}</template>
|
||
</el-table-column>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
<el-pagination
|
||
style="margin-top:16px;text-align:right"
|
||
background
|
||
layout="total, prev, pager, next, sizes"
|
||
:total="total"
|
||
:page-size.sync="queryParams.pageSize"
|
||
:current-page.sync="queryParams.pageNum"
|
||
:page-sizes="[5,10,20,50]"
|
||
@size-change="loadData"
|
||
@current-change="loadData"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { getUserTurnover } from '@/api/skins/userTurnover'
|
||
|
||
const sortLabels = {
|
||
totalRecharge: '充值', totalTurnover: '总流水',
|
||
classicBox: '经典开箱', fightGame: '对战', luckyUpgrade: '幸运升级',
|
||
wheelGame: '疯狂转盘', olympusGame: '玫瑰女郎', rollRoom: 'roll房',
|
||
userId: '用户ID'
|
||
}
|
||
|
||
/** 格式化日期为 yyyy-MM-dd HH:mm:ss */
|
||
function fmtDate(d) {
|
||
const y = d.getFullYear()
|
||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||
const day = String(d.getDate()).padStart(2, '0')
|
||
const h = String(d.getHours()).padStart(2, '0')
|
||
const min = String(d.getMinutes()).padStart(2, '0')
|
||
const s = String(d.getSeconds()).padStart(2, '0')
|
||
return `${y}-${m}-${day} ${h}:${min}:${s}`
|
||
}
|
||
|
||
/** 获取默认日期范围:昨天00:00:00 至 今天当前时间 */
|
||
function getDefaultDateRange() {
|
||
const now = new Date()
|
||
const yesterday = new Date(now)
|
||
yesterday.setDate(yesterday.getDate() - 1)
|
||
yesterday.setHours(0, 0, 0, 0)
|
||
return [fmtDate(yesterday), fmtDate(now)]
|
||
}
|
||
|
||
export default {
|
||
name: 'UserTurnover',
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
tableData: [],
|
||
total: 0,
|
||
sortLabels,
|
||
// 日期范围,默认昨天00:00:00 至 今天当前时间
|
||
dateRange: getDefaultDateRange(),
|
||
pickerOptions: {
|
||
shortcuts: [
|
||
{ text: '今日', onClick(picker) {
|
||
const now = new Date(); const start = new Date(now); start.setHours(0, 0, 0, 0)
|
||
picker.$emit('pick', [start, now])
|
||
}},
|
||
{ text: '昨日', onClick(picker) {
|
||
const yd = new Date(); yd.setDate(yd.getDate() - 1); yd.setHours(0, 0, 0, 0)
|
||
const ydEnd = new Date(yd); ydEnd.setHours(23, 59, 59, 999)
|
||
picker.$emit('pick', [yd, ydEnd])
|
||
}},
|
||
{ text: '本周', onClick(picker) {
|
||
const now = new Date(); const day = now.getDay(); const diff = day === 0 ? 6 : day - 1
|
||
const monday = new Date(now); monday.setDate(monday.getDate() - diff); monday.setHours(0, 0, 0, 0)
|
||
picker.$emit('pick', [monday, now])
|
||
}},
|
||
{ text: '上周', onClick(picker) {
|
||
const now = new Date(); const day = now.getDay(); const diff = day === 0 ? 6 : day - 1
|
||
const lastMonday = new Date(now); lastMonday.setDate(lastMonday.getDate() - diff - 7); lastMonday.setHours(0, 0, 0, 0)
|
||
const lastSunday = new Date(lastMonday); lastSunday.setDate(lastSunday.getDate() + 6); lastSunday.setHours(23, 59, 59, 999)
|
||
picker.$emit('pick', [lastMonday, lastSunday])
|
||
}}
|
||
]
|
||
},
|
||
queryParams: {
|
||
userId: null,
|
||
nickName: null,
|
||
phone: null,
|
||
sortField: 'totalTurnover',
|
||
sortOrder: 'desc',
|
||
pageNum: 1,
|
||
pageSize: 10
|
||
}
|
||
}
|
||
},
|
||
created() { this.loadData() },
|
||
methods: {
|
||
loadData() {
|
||
this.loading = true
|
||
const params = { ...this.queryParams }
|
||
if (params.userId) params.userId = Number(params.userId)
|
||
// 日期范围(已是完整的 yyyy-MM-dd HH:mm:ss 格式)
|
||
if (this.dateRange && this.dateRange.length === 2) {
|
||
params.startTime = this.dateRange[0]
|
||
params.endTime = this.dateRange[1]
|
||
}
|
||
getUserTurnover(params).then(res => {
|
||
this.tableData = res.data.rows || []
|
||
this.total = res.data.total || 0
|
||
}).finally(() => { this.loading = false })
|
||
},
|
||
handleSearch() { this.queryParams.pageNum = 1; this.loadData() },
|
||
handleReset() {
|
||
this.dateRange = getDefaultDateRange()
|
||
this.queryParams = { userId: null, nickName: null, phone: null, sortField: 'totalTurnover', sortOrder: 'desc', pageNum: 1, pageSize: 10 }
|
||
this.loadData()
|
||
},
|
||
handleSortChange({ prop, order }) {
|
||
this.queryParams.sortField = prop || 'totalTurnover'
|
||
this.queryParams.sortOrder = order === 'ascending' ? 'asc' : 'desc'
|
||
this.loadData()
|
||
},
|
||
formatMoney(v) {
|
||
if (v == null) return '0.00'
|
||
return Number(v).toFixed(2)
|
||
},
|
||
userTypeLabel(type) {
|
||
const map = { '01': '主播', '02': '普通用户', '03': '机器人', '04': '招商', '05': '卡商', '99': '超级管理员' }
|
||
return map[type] || type || '-'
|
||
},
|
||
userTypeTag(type) {
|
||
const map = { '01': 'success', '02': '', '03': 'info', '04': 'warning', '05': 'danger', '99': 'danger' }
|
||
return map[type] || ''
|
||
}
|
||
}
|
||
}
|
||
</script>
|