You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
424 lines
12 KiB
424 lines
12 KiB
<template>
|
|
<el-col :span="4">
|
|
<el-card class="center-card margin-bottom">数据总览</el-card>
|
|
</el-col>
|
|
<el-row :span="24">
|
|
<!-- 第一个卡片 -->
|
|
<el-card class="card-item">
|
|
<template #header>
|
|
<div class="card-header">
|
|
<div class="card-title">当前金币余量</div>
|
|
<div>100 较前一日 -100</div>
|
|
</div>
|
|
</template>
|
|
<div>
|
|
<div class="margin-bottom">永久金币:100</div>
|
|
<div class="margin-bottom">免费金币:100</div>
|
|
<div class="margin-bottom">[六月到期|100] [12月到期|100]</div>
|
|
<div>任务金币:100</div>
|
|
</div>
|
|
</el-card>
|
|
<!-- 第二个卡片 -->
|
|
<el-card class="card-item">
|
|
<div class="card-title">全年累计充值金币数</div>
|
|
<div class="card-title">100</div>
|
|
<div> </div>
|
|
<div class="center-card">折合新币累计金额:100</div>
|
|
<template #footer >
|
|
<el-col class="margin-bottom center-card">昨日新增:100</el-col>
|
|
<el-col class="margin-bottom center-card">其中充值:100</el-col>
|
|
</template>
|
|
</el-card>
|
|
<!-- 第三个卡片 -->
|
|
<el-card class="card-item">
|
|
<div class="card-title">全年累计消耗金币数</div>
|
|
<div class="card-title">100</div>
|
|
<div class="center-card">消费:100</div>
|
|
<div class="center-card">退款:100</div>
|
|
<template #footer>
|
|
<div></div>
|
|
<div class="margin-bottom center-card">昨日新增消耗:100</div>
|
|
<div class="margin-bottom center-card">昨日新增消费:100</div>
|
|
<div class="margin-bottom center-card">昨日新增退款:100</div>
|
|
</template>
|
|
</el-card>
|
|
<!-- 第四个卡片 -->
|
|
<el-card class="card-item">
|
|
<el-col class="card-title">全年累计充值人头数</el-col>
|
|
<el-col class="card-title">100</el-col>
|
|
<el-col class="center-card">周同比:???</el-col>
|
|
<el-col class="center-card">日环比</el-col>
|
|
<template #footer>
|
|
<el-col class="margin-bottom center-card">昨日充值人数:100</el-col>
|
|
<el-col class="margin-bottom center-card">其中首充:100</el-col>
|
|
</template>
|
|
</el-card>
|
|
</el-row>
|
|
|
|
|
|
<el-row :gutter="10" style="margin-top: 20px">
|
|
<el-col :span="24">
|
|
<el-card style="width: 100%">
|
|
<el-row>
|
|
<el-col :span="15">
|
|
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
|
<el-tab-pane label="金币充值" name="recharge"></el-tab-pane>
|
|
<el-tab-pane label="金币消费" name="consume"></el-tab-pane>
|
|
</el-tabs>
|
|
</el-col>
|
|
<el-col :span="9" style="text-align: right">
|
|
<el-radio-group v-model="timeRange" @change="handleTimeRangeChange" style="margin-right: 5px; margin-top:5px">
|
|
<el-radio-button label="day" style="border-color: white">今日</el-radio-button>
|
|
<el-radio-button label="week" style="border-color: white">本周</el-radio-button>
|
|
<el-radio-button label="month" style="border-color: white">本月</el-radio-button>
|
|
<el-radio-button label="year" style="border-color: white">本年</el-radio-button>
|
|
</el-radio-group>
|
|
<el-date-picker
|
|
v-model="dateRange"
|
|
type="daterange"
|
|
range-separator="→"
|
|
start-placeholder="开始时间"
|
|
end-placeholder="结束时间"
|
|
style="width: 200px"
|
|
@change="handleDateRangeChange"
|
|
/>
|
|
<el-button style="margin-left: 5px" @click="loadChart">查询</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<el-row :gutter="20" style="margin-top: 20px">
|
|
<el-col :span="18">
|
|
<div class="bar">
|
|
<div v-show="activeTab === 'recharge'" id="recharge" style="width: 100%; height: 400px"></div>
|
|
<div v-show="activeTab === 'consume'" id="consume" style="width: 100%; height: 400px"></div>
|
|
</div>
|
|
</el-col>
|
|
<el-col :span="6">
|
|
<el-card class="rank-card" style="width: 100%; height: 100%">
|
|
<div class="card-large margin-bottom">金币{{ activeTab === 'recharge' ? '充值' : '消费' }}排名</div>
|
|
<el-select v-model="selectedType" style="width: 100%; margin-bottom: 15px">
|
|
<el-option label="全部类型" value="all"></el-option>
|
|
<el-option label="永久金币" value="permanent"></el-option>
|
|
<el-option label="免费金币" value="free"></el-option>
|
|
<el-option label="任务金币" value="task"></el-option>
|
|
</el-select>
|
|
<el-table :data="tableData" height="320px">
|
|
<el-table-column prop="rank" label="排名" width="60" align="center"></el-table-column>
|
|
<el-table-column prop="region" label="地区" align="center"></el-table-column>
|
|
<el-table-column prop="coinAmount" label="金币数量" align="center">
|
|
<template #default="{ row }">
|
|
{{ row.coinAmount.toLocaleString() }}
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
</template>
|
|
|
|
<script setup>
|
|
import * as echarts from 'echarts'
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
import API from '@/util/http'
|
|
|
|
const histogramData = ref([])
|
|
const middleCategory = ref([])
|
|
const middleRecharge = ref([])
|
|
const middleFree = ref([])
|
|
const middleTask = ref([])
|
|
const tableData = ref([])
|
|
const area = ref([])
|
|
|
|
// 变量
|
|
const activeTab = ref('consume')
|
|
const updateType = ref(1)
|
|
const timeRange = ref('day')
|
|
const dateRange = ref([])
|
|
const selectedType = ref('all')
|
|
|
|
// ECharts实例
|
|
let rechargeBar = null
|
|
let consumeBar = null
|
|
|
|
const formatDate = (date) => {
|
|
const year = date.getFullYear()
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
// 本周一
|
|
const getWeekStart = (date) => {
|
|
const day = date.getDay()
|
|
const diff = date.getDate() - day + (day === 0 ? -6 : 1) // 如果周日,则返回上周一
|
|
return new Date(date.setDate(diff))
|
|
}
|
|
|
|
// 本周日
|
|
const getWeekEnd = (date) => {
|
|
const start = getWeekStart(new Date(date))
|
|
const end = new Date(start)
|
|
end.setDate(start.getDate() + 6)
|
|
return end
|
|
}
|
|
|
|
// 月份第一天
|
|
const getMonthStart = (date) => {
|
|
return new Date(date.getFullYear(), date.getMonth(), 1)
|
|
}
|
|
|
|
// 月份最后一天
|
|
const getMonthEnd = (date) => {
|
|
return new Date(date.getFullYear(), date.getMonth() + 1, 0)
|
|
}
|
|
|
|
// 年份第一天
|
|
const getYearStart = (date) => {
|
|
return new Date(date.getFullYear(), 0, 1)
|
|
}
|
|
|
|
// 年份最后一天
|
|
const getYearEnd = (date) => {
|
|
return new Date(date.getFullYear(), 11, 31)
|
|
}
|
|
|
|
const handleTimeRangeChange = (value) => {
|
|
const now = new Date()
|
|
let start, end
|
|
|
|
switch (value) {
|
|
case 'day': // 今日
|
|
start = new Date(now)
|
|
end = new Date(now)
|
|
break
|
|
case 'week': // 本周
|
|
start = getWeekStart(new Date(now))
|
|
end = getWeekEnd(new Date(now))
|
|
break
|
|
case 'month': // 本月
|
|
start = getMonthStart(now)
|
|
end = getMonthEnd(now)
|
|
break
|
|
case 'year': // 本年
|
|
start = getYearStart(now)
|
|
end = getYearEnd(now)
|
|
break
|
|
default:
|
|
start = new Date()
|
|
end = new Date()
|
|
}
|
|
|
|
dateRange.value = [start, end]
|
|
loadChart()
|
|
}
|
|
|
|
const handleDateRangeChange = () => {
|
|
timeRange.value = ''
|
|
}
|
|
|
|
// 获取地区数据
|
|
const getAreas = async () => {
|
|
try {
|
|
const result = await API({
|
|
url: 'http://18.143.76.3:10704/general/market',
|
|
data: {}
|
|
})
|
|
middleCategory.value = result.data.map(item => item.name)
|
|
|
|
// 生成表格数据(模拟)
|
|
tableData.value = result.data.slice(0, 11).map((item, index) => ({
|
|
rank: index + 1,
|
|
region: item.name,
|
|
coinAmount: Math.floor(Math.random() * 1000000) + 500000
|
|
}))// D老师加的这一段(????????????????)
|
|
} catch (error) {
|
|
console.error('获取地区数据失败:', error)
|
|
}
|
|
}
|
|
|
|
const getChartData = async () => {
|
|
try {
|
|
const params = {
|
|
updateType: updateType.value
|
|
}
|
|
|
|
if (dateRange.value && dateRange.value.length === 2) {
|
|
params.searchStartTime = formatDate(dateRange.value[0])
|
|
params.searchEndTime = formatDate(dateRange.value[1])
|
|
}
|
|
|
|
const result = await API({
|
|
url: '/statistics/getCoinTime',
|
|
data: params
|
|
})
|
|
|
|
histogramData.value = result.data || []
|
|
|
|
middleRecharge.value = histogramData.value.map(item =>
|
|
Math.abs(item.rechargeSumCoin || 0)
|
|
)
|
|
middleFree.value = histogramData.value.map(item =>
|
|
Math.abs(item.freeSumCoin || 0)
|
|
)
|
|
middleTask.value = histogramData.value.map(item =>
|
|
Math.abs(item.taskSumCoin || 0)
|
|
)
|
|
|
|
updateChart()
|
|
} catch (error) {
|
|
console.error('请求图表数据失败:', error)
|
|
}
|
|
}
|
|
|
|
const updateChart = () => {
|
|
const option = {
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
axisPointer: { type: 'shadow' },
|
|
formatter: function (params) {
|
|
let total = 0
|
|
let content = `${params[0].name}<br/>`
|
|
params.forEach((param) => {
|
|
content += `${param.seriesName}: ${param.value.toLocaleString()}<br/>`
|
|
total += param.value
|
|
})
|
|
content += `总和: ${total.toLocaleString()}`
|
|
return content
|
|
}
|
|
},
|
|
legend: {
|
|
right: '2%',
|
|
orient: 'vertical',
|
|
itemGap: 10
|
|
},
|
|
grid: {
|
|
left: '3%',
|
|
right: '10%',
|
|
bottom: '3%',
|
|
containLabel: true
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
data: middleCategory.value,
|
|
axisLabel: {
|
|
interval: 0,
|
|
rotate: 30
|
|
}
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
axisLabel: {
|
|
formatter: (value) => value.toLocaleString()
|
|
}
|
|
},
|
|
series: [
|
|
{
|
|
name: '永久金币',
|
|
color: '#35e383',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
data: middleRecharge.value
|
|
},
|
|
{
|
|
name: '免费金币',
|
|
color: '#5f8ff5',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
data: middleFree.value
|
|
},
|
|
{
|
|
name: '任务金币',
|
|
color: '#ffe733',
|
|
type: 'bar',
|
|
stack: 'total',
|
|
data: middleTask.value
|
|
}
|
|
]
|
|
}
|
|
|
|
if (activeTab.value === 'recharge' && rechargeBar) {
|
|
rechargeBar.setOption(option)
|
|
rechargeBar.resize()
|
|
} else if (consumeBar) {
|
|
consumeBar.setOption(option)
|
|
consumeBar.resize()
|
|
}
|
|
}
|
|
|
|
const initCharts = () => {
|
|
const rechargeDom = document.getElementById('recharge')
|
|
const consumeDom = document.getElementById('consume')
|
|
|
|
if (rechargeDom) {
|
|
rechargeBar = echarts.init(rechargeDom)
|
|
}
|
|
|
|
if (consumeDom) {
|
|
consumeBar = echarts.init(consumeDom)
|
|
}
|
|
}
|
|
|
|
const loadChart = async () => {
|
|
await getAreas()
|
|
await getChartData()
|
|
}
|
|
|
|
// 页面切换
|
|
const handleTabChange = (tab) => {
|
|
updateType.value = tab === 'recharge' ? 0 : 1
|
|
loadChart()
|
|
}
|
|
|
|
const handleResize = () => {
|
|
if (rechargeBar) rechargeBar.resize()
|
|
if (consumeBar) consumeBar.resize()
|
|
}
|
|
|
|
onMounted(() => {
|
|
initCharts()
|
|
loadChart()
|
|
window.addEventListener('resize', handleResize)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
if (rechargeBar) rechargeBar.dispose()
|
|
if (consumeBar) consumeBar.dispose()
|
|
window.removeEventListener('resize', handleResize)
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.center-card {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.margin-bottom {
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.card-item {
|
|
width: 24%;
|
|
height: 260px;
|
|
margin-right: 10px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
.card-title {
|
|
font-weight: bold;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.margin-top{
|
|
margin-top: 5px;
|
|
}
|
|
</style>
|