|
|
<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>
|