|
|
@ -9,15 +9,22 @@ |
|
|
|
<template #header> |
|
|
|
<div class="card-header"> |
|
|
|
<div class="card-title">当前金币余量</div> |
|
|
|
<div>{{ currentGold / 100 }} 较前一日 {{ dailyChange / 100 }} |
|
|
|
<div>{{ currentGold / 100 }} 较前一日 {{ |
|
|
|
dailyChange / 100 }} |
|
|
|
<template v-if="dailyChange > 0"> |
|
|
|
<el-icon style="color:red"><ArrowUpBold /></el-icon> |
|
|
|
<el-icon style="color:red"> |
|
|
|
<ArrowUpBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else-if="dailyChange < 0"> |
|
|
|
<el-icon style="color:forestgreen"><ArrowDownBold /></el-icon> |
|
|
|
<el-icon style="color:forestgreen"> |
|
|
|
<ArrowDownBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<el-icon style="color:grey"><SemiSelect /></el-icon> |
|
|
|
<el-icon style="color:grey"> |
|
|
|
<SemiSelect /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
</div> |
|
|
|
</div> |
|
|
@ -25,7 +32,9 @@ |
|
|
|
<div> |
|
|
|
<div class="margin-bottom">永久金币:{{ currentPermanent / 100 }}</div> |
|
|
|
<div class="margin-bottom">免费金币:{{ currentFree / 100 }}</div> |
|
|
|
<div class="margin-bottom">[六月到期|{{ currentFreeJune / 100 }}] [12月到期|{{ currentFreeDecember / 100 }}]</div> |
|
|
|
<div class="margin-bottom">[六月到期|{{ currentFreeJune / 100 }}] [12月到期|{{ |
|
|
|
currentFreeDecember / |
|
|
|
100 }}]</div> |
|
|
|
<div>任务金币:{{ currentTask / 100 }}</div> |
|
|
|
</div> |
|
|
|
</el-card> |
|
|
@ -68,24 +77,36 @@ |
|
|
|
<el-col class="card-title">{{ yearlyRechargeNum }}</el-col> |
|
|
|
<el-col class="center-card">周同比:{{ sumWow }}% |
|
|
|
<template v-if="sumWow > 0"> |
|
|
|
<el-icon style="color:red"><ArrowUpBold /></el-icon> |
|
|
|
<el-icon style="color:red"> |
|
|
|
<ArrowUpBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else-if="sumWow < 0"> |
|
|
|
<el-icon style="color:forestgreen"><ArrowDownBold /></el-icon> |
|
|
|
<el-icon style="color:forestgreen"> |
|
|
|
<ArrowDownBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<el-icon style="color:grey"><SemiSelect /></el-icon> |
|
|
|
<el-icon style="color:grey"> |
|
|
|
<SemiSelect /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
</el-col> |
|
|
|
<el-col class="center-card">日环比:{{ sumDaily }}% |
|
|
|
<template v-if="sumDaily > 0"> |
|
|
|
<el-icon style="color:red"><ArrowUpBold /></el-icon> |
|
|
|
<el-icon style="color:red"> |
|
|
|
<ArrowUpBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else-if="sumDaily < 0"> |
|
|
|
<el-icon style="color:forestgreen"><ArrowDownBold /></el-icon> |
|
|
|
<el-icon style="color:forestgreen"> |
|
|
|
<ArrowDownBold /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<el-icon style="color:grey"><SemiSelect /></el-icon> |
|
|
|
<el-icon style="color:grey"> |
|
|
|
<SemiSelect /> |
|
|
|
</el-icon> |
|
|
|
</template> |
|
|
|
</el-col> |
|
|
|
<template #footer> |
|
|
@ -106,21 +127,24 @@ |
|
|
|
<el-tab-pane label="金币消费" name="consume"></el-tab-pane> |
|
|
|
</el-tabs> |
|
|
|
</el-col> |
|
|
|
<el-col :span="21"> |
|
|
|
<el-col :span="24"> |
|
|
|
<el-row> |
|
|
|
<div style="margin-top:5px">合计 |
|
|
|
永久金币 {{ activeTab === 'recharge' ? sumRechargePermanent / 100 : sumConsumePermanent / 100 }} |
|
|
|
免费金币 {{ activeTab === 'recharge' ? sumRechargeFree / 100 : sumConsumeFree / 100 }} |
|
|
|
任务金币 {{ activeTab === 'recharge' ? sumRechargeTask / 100 : sumConsumeTask / 100 }} |
|
|
|
永久金币 {{ activeTab === 'recharge' ? sumRechargePermanent / 100 : sumConsumePermanent / 100 |
|
|
|
}} |
|
|
|
免费金币 {{ activeTab === 'recharge' ? sumRechargeFree / 100 : sumConsumeFree / 100 |
|
|
|
}} |
|
|
|
任务金币 {{ activeTab === 'recharge' ? sumRechargeTask / 100 : sumConsumeTask / 100 |
|
|
|
}} |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<el-button @click="getToday()" label="day" style="margin-left:250px">今日</el-button> |
|
|
|
<el-button @click="getWeek()" label="week">本周</el-button> |
|
|
|
<el-button @click="getMonth()" label="month">本月</el-button> |
|
|
|
<el-button @click="getYear()" label="year">本年</el-button> |
|
|
|
</div> |
|
|
|
<el-radio-group v-model="timeRange" @change="handleTimeRangeChange" style="margin-right: 5px; margin-left:100px"> |
|
|
|
<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: 100px" @change="handleDateRangeChange" value-format="YYYY-MM-DD HH:mm:ss" /> |
|
|
|
<el-date-picker v-model="dateRange" type="datetimerange" range-separator="→" start-placeholder="开始时间" |
|
|
|
end-placeholder="结束时间" style="margin-left:10px" /> |
|
|
|
<el-button type="primary" style="margin-left: 5px" @click="getChartData">查询</el-button> |
|
|
|
</el-row> |
|
|
|
</el-col> |
|
|
@ -163,13 +187,15 @@ import * as echarts from 'echarts' |
|
|
|
import { ref, onMounted, nextTick, watch } from 'vue' |
|
|
|
import API from '@/util/http' |
|
|
|
import { ElMessage } from 'element-plus' |
|
|
|
import dayjs from 'dayjs'; |
|
|
|
import utc from 'dayjs-plugin-utc' |
|
|
|
dayjs.extend(utc) |
|
|
|
import { ArrowUpBold, ArrowDownBold, SemiSelect } from '@element-plus/icons-vue' |
|
|
|
// 地区数据 |
|
|
|
const markets = ref([]) |
|
|
|
// 图表相关 |
|
|
|
const activeTab = ref('recharge') |
|
|
|
const timeRange = ref('') |
|
|
|
const dateRange = ref([]) |
|
|
|
const activeTab = ref('recharge') |
|
|
|
const selectedType = ref('all') |
|
|
|
const tableData = ref([]) |
|
|
|
const chartRef = ref(null) |
|
|
@ -207,6 +233,47 @@ const sumDaily = ref(0) |
|
|
|
const rechargeNum = ref(0) |
|
|
|
const firstRecharge = ref(0) |
|
|
|
const length = ref(0) |
|
|
|
const formatDate = function(date) { |
|
|
|
const year = date.getFullYear(); |
|
|
|
const month = String(date.getMonth() + 1).padStart(2, '0'); |
|
|
|
const day = String(date.getDate()).padStart(2, '0'); |
|
|
|
const hours = String(date.getHours()).padStart(2, '0'); |
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0'); |
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0'); |
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
|
|
|
} |
|
|
|
// 今天 |
|
|
|
const getToday = function () { |
|
|
|
const today = new Date() |
|
|
|
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate()) |
|
|
|
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1) |
|
|
|
dateRange.value = [formatDate(startTime), formatDate(endTime)] |
|
|
|
console.log('看看dateRange', dateRange.value) |
|
|
|
} |
|
|
|
// 本周 |
|
|
|
const getWeek = function () { |
|
|
|
const today = new Date() |
|
|
|
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 6) |
|
|
|
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1) |
|
|
|
dateRange.value = [formatDate(startTime), formatDate(endTime)] |
|
|
|
console.log('看看dateRange', dateRange.value) |
|
|
|
} |
|
|
|
// 本月 |
|
|
|
const getMonth = function () { |
|
|
|
const today = new Date() |
|
|
|
const startTime = new Date(today.getFullYear(), today.getMonth(), 1) |
|
|
|
const endTime = new Date(today.getFullYear(), today.getMonth() + 1, 1) |
|
|
|
dateRange.value = [formatDate(startTime), formatDate(endTime)] |
|
|
|
console.log('看看dateRange', dateRange.value) |
|
|
|
} |
|
|
|
// 本年 |
|
|
|
const getYear = function () { |
|
|
|
const today = new Date() |
|
|
|
const startTime = new Date(today.getFullYear(), 0, 1) |
|
|
|
const endTime = new Date(today.getFullYear() + 1, 0, 1) |
|
|
|
dateRange.value = [formatDate(startTime), formatDate(endTime)] |
|
|
|
console.log('看看dateRange', dateRange.value) |
|
|
|
} |
|
|
|
|
|
|
|
// 要加上所有市场的,还有额外计算的(总数 = 永久 + 6月 + 12月 + 免费 + 任务) |
|
|
|
const processData = (data) => { |
|
|
@ -311,12 +378,13 @@ const getChartData = async () => { |
|
|
|
await getMarkets() |
|
|
|
} |
|
|
|
|
|
|
|
// 构建请求参数 |
|
|
|
|
|
|
|
const params = { |
|
|
|
markets: markets.value, |
|
|
|
startDate: dateRange.value[0] || formatDate(new Date(0)), |
|
|
|
endDate: dateRange.value[1] || formatDate(new Date()) |
|
|
|
} |
|
|
|
startDate: dateRange.value[0], |
|
|
|
endDate: dateRange.value[1] |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const response = await API({ |
|
|
|
url: '/workbench/getGraph', |
|
|
@ -384,17 +452,42 @@ const processChartData = (marketCards) => { |
|
|
|
updateChart(chartData) |
|
|
|
} |
|
|
|
|
|
|
|
// 处理排名数据 - 修改点:根据接口字段计算金币数量 |
|
|
|
const processRankingData = (marketCards) => { |
|
|
|
// 根据当前选中的标签计算每个市场的总金币数量 |
|
|
|
// 根据当前选中的标签和类型计算每个市场的总金币数量 |
|
|
|
const rankingData = marketCards.map(market => { |
|
|
|
let coinAmount = 0; |
|
|
|
if (activeTab.value === 'recharge') { |
|
|
|
// 充值排名:永久金币 + 免费金币 |
|
|
|
coinAmount = (market.sumRechargePermanent / 100 || 0) + (market.sumRechargeFree / 100 || 0); |
|
|
|
// 充值排名 |
|
|
|
switch (selectedType.value) { |
|
|
|
case 'all': |
|
|
|
coinAmount = (market.sumRechargePermanent / 100 || 0) + (market.sumRechargeFree / 100 || 0) + (market.sumRechargeTask / 100 || 0); |
|
|
|
break; |
|
|
|
case 'permanent': |
|
|
|
coinAmount = market.sumRechargePermanent / 100 || 0; |
|
|
|
break; |
|
|
|
case 'free': |
|
|
|
coinAmount = market.sumRechargeFree / 100 || 0; |
|
|
|
break; |
|
|
|
case 'task': |
|
|
|
coinAmount = market.sumRechargeTask / 100 || 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 消费排名:永久金币 + 免费金币 + 任务金币 |
|
|
|
// 消费排名 |
|
|
|
switch (selectedType.value) { |
|
|
|
case 'all': |
|
|
|
coinAmount = (market.sumConsumePermanent / 100 || 0) + (market.sumConsumeFree / 100 || 0) + (market.sumConsumeTask / 100 || 0); |
|
|
|
break; |
|
|
|
case 'permanent': |
|
|
|
coinAmount = market.sumConsumePermanent / 100 || 0; |
|
|
|
break; |
|
|
|
case 'free': |
|
|
|
coinAmount = market.sumConsumeFree / 100 || 0; |
|
|
|
break; |
|
|
|
case 'task': |
|
|
|
coinAmount = market.sumConsumeTask / 100 || 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return { |
|
|
|
market: market.market, // 使用 market 字段作为地区名称 |
|
|
@ -412,6 +505,10 @@ const processRankingData = (marketCards) => { |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
// 监听 selectedType 的变化,重新处理排名数据 |
|
|
|
watch(selectedType, () => { |
|
|
|
getChartData(); |
|
|
|
}); |
|
|
|
// 更新图表 |
|
|
|
const updateChart = (chartData) => { |
|
|
|
if (!chartInstance) { |
|
|
@ -532,65 +629,6 @@ const handleTabChange = () => { |
|
|
|
console.log('标签切换调用图表') |
|
|
|
} |
|
|
|
|
|
|
|
// 格式化日期为字符串 |
|
|
|
const formatDate = (date) => { |
|
|
|
const year = date.getFullYear() |
|
|
|
const month = String(date.getMonth() + 1).padStart(2, '0') |
|
|
|
const day = String(date.getDate()).padStart(2, '0') |
|
|
|
const hours = String(date.getHours()).padStart(2, '0') |
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0') |
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0') |
|
|
|
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
|
|
|
} |
|
|
|
// 处理时间范围变化 |
|
|
|
const handleTimeRangeChange = () => { |
|
|
|
const now = new Date() |
|
|
|
let startDate, endDate |
|
|
|
|
|
|
|
if (timeRange.value === 'day') { |
|
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0) |
|
|
|
endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59) |
|
|
|
} else if (timeRange.value === 'week') { |
|
|
|
const day = now.getDay() |
|
|
|
const diff = now.getDate() - day + (day === 0 ? -6 : 1) |
|
|
|
startDate = new Date(now.setDate(diff)) |
|
|
|
startDate.setHours(0, 0, 0, 0) |
|
|
|
endDate = new Date(now) |
|
|
|
endDate.setDate(now.getDate() + 6) |
|
|
|
endDate.setHours(23, 59, 59, 0) |
|
|
|
} else if (timeRange.value === 'month') { |
|
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0) |
|
|
|
endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59) |
|
|
|
} else { |
|
|
|
startDate = new Date(now.getFullYear(), 0, 1, 0, 0, 0) |
|
|
|
endDate = new Date(now.getFullYear(), 11, 31, 23, 59, 59) |
|
|
|
} |
|
|
|
|
|
|
|
dateRange.value = [ |
|
|
|
formatDate(startDate), |
|
|
|
formatDate(endDate) |
|
|
|
] |
|
|
|
|
|
|
|
getChartData() |
|
|
|
console.log('时间切换调用') |
|
|
|
} |
|
|
|
|
|
|
|
// 处理日期范围变化 |
|
|
|
const handleDateRangeChange = () => { |
|
|
|
timeRange.value = 'custom' |
|
|
|
// 确保日期范围数组中的值是正确格式 |
|
|
|
if (dateRange.value.length === 2) { |
|
|
|
dateRange.value = dateRange.value.map(date => { |
|
|
|
if (typeof date === 'string') { |
|
|
|
return new Date(date).toISOString().slice(0, 19).replace('T', ' ') |
|
|
|
} |
|
|
|
return formatDate(date) |
|
|
|
}) |
|
|
|
} |
|
|
|
getChartData() |
|
|
|
console.log('日期选择器的改变调用') |
|
|
|
} |
|
|
|
const getAdminData = async function () { |
|
|
|
try { |
|
|
|
const result = await API({ url: '/admin/userinfo', data: {} }) |
|
|
@ -616,10 +654,13 @@ const getCardData = async () => { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
|
|
|
|
await getAdminData() |
|
|
|
await getCardData() |
|
|
|
await getMarkets() |
|
|
|
getYear() |
|
|
|
await getChartData() |
|
|
|
console.log('挂载后调用') |
|
|
|
}) |
|
|
@ -693,7 +734,12 @@ onMounted(async () => { |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes spin { |
|
|
|
0% { transform: rotate(0deg); } |
|
|
|
100% { transform: rotate(360deg); } |
|
|
|
0% { |
|
|
|
transform: rotate(0deg); |
|
|
|
} |
|
|
|
|
|
|
|
100% { |
|
|
|
transform: rotate(360deg); |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |