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

<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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;较前一日 -100</div>
</div>
</template>
<div>
<div class="margin-bottom">永久金币100</div>
<div class="margin-bottom">免费金币100</div>
<div class="margin-bottom">[六月到期|100]&nbsp;&nbsp;&nbsp;&nbsp;[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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>