|
|
<template> <div class="gold-management"> <div class="gold-title"> <div class="text1"> 金币管理 <span class="text1-update-time">最后更新时间:{{ workDataUpdateTime && workDataUpdateTime !== '1970-01-01 08:00:00' ? workDataUpdateTime : '该地区暂无数据' }} </span> </div> </div> <!-- 第一行:包含两个横向格子 --> <el-row> <el-col :span="12"> <!-- 第一个卡片 --> <div class="card-item-row1"> <div class="card-title">当前金币余量 <span style="font-weight: bold">{{ currentGold / 100 }}</span> 较前一日 {{ dailyChange / 100 }} <template v-if="dailyChange > 0"> <el-image :src="upArrow" style="width: 14px;"/> </template> <template v-else-if="dailyChange < 0"> <el-image :src="downArrow" style="width: 14px;"/> </template> <template v-else> <el-image :src="pingArrow" style="width: 14px; padding-top: 12px"/> </template> </div> <div> <el-row> <!-- 左边文本信息 --> <el-col :span="12"> <div class="margin-bottom" style="white-space: nowrap;"> 永久金币:<b>{{ currentPermanent / 100 }}</b> </div> <div class="margin-bottom"> </div>
<div class="margin-bottom">免费金币:{{ currentFree / 100 }}</div> <!-- <div class="margin-bottom"> </div>--> <!-- <div class="margin-bottom"> </div>--> <div class="margin-bottom"> [6月到期:{{ currentFreeJune / 100 }}] </div> <div class="margin-bottom"> </div>
<div class="margin-bottom">任务金币:{{ currentTask / 100 }}</div> </el-col> <!-- 右边图表 --> <el-col :span="12"> <!-- <div ref="goldTypeChart" style="width: 100%; height: 100px;"></div>--> <div style="width: 100%; height: 60px;"> </div> <div class="margin-bottom"> [12月到期:{{ currentFreeDecember / 100 }}] </div> </el-col> </el-row> </div>
</div> </el-col> <el-col :span="12"> <!-- 第二个卡片 --> <div class="card-item-row1"> <div class="card-title">全年累计充值金币数{{ yearlyRecharge / 100 }}</div> <el-row> <el-col :span="12"> <div class="center-card">折合新币累计金额</div> <el-image :src="svg1" style="width: 68px; display: block;margin: 0 auto;"/> <div class="center-card">{{ yearlyMoney / 100 }}新币</div> </el-col> <el-col :span="12" style="border-left: 2px solid #CFE6FE; height: 120px"> <div class="center-card" style="white-space: nowrap;">昨日新增金币:{{ recharge / 100 }}</div> <div ref="rechargeGoldChart" style="width: 68px; height: 68px; display: block;margin: 0 auto;"></div> <div class="center-card" style="white-space: nowrap;">其中永久金币:{{ money / 100 }}</div> </el-col> </el-row> </div> </el-col> </el-row>
<!-- 第二行:包含两个横向格子 --> <el-row> <el-col :span="12"> <!-- 第三个卡片 --> <div class="card-item"> <div class="card-title">全年累计消费金币数{{ yearlyReduce / 100 }}</div> <el-row style="height: 200px;"> <el-col :span="12"> <div ref="consumeChart" style="width:100%; height: 68%;"></div> </el-col> <el-col :span="12"> <div ref="consumeDetailChart" style="width: 100%; height: 88%;"></div> </el-col> </el-row> </div> </el-col> <el-col :span="12"> <!-- 第四个卡片 --> <div class="card-item"> <div class="card-title">全年累计充值人头数{{ yearlyRechargeNum }}</div> <el-row style="height: 200px;"> <el-col :span="12" style="border-right: 2px solid #CFE6FE; height: 150px"> <div class="chart5"> <el-image :src="svg2" style="width: 68px; display: block;margin: 0 auto;"/> <div class="margin-bottom"> <div style="display: flex; gap: 10px; font-size: 14px;">周同比:{{ sumWow }}% <el-image v-if="sumWow > 0" :src="upArrow" style="width: 10px;"/> <el-image v-else-if="sumWow < 0" :src="downArrow" style="width: 10px;"/> <el-image v-else :src="pingArrow" style="width: 10px;"/> </div> <div style="display: flex; gap: 10px; font-size: 14px;"> 日环比:{{ sumDaily }}% <el-image v-if="sumDaily > 0" :src="upArrow" style="width: 10px;"/> <el-image v-else-if="sumDaily < 0" :src="downArrow" style="width: 10px;"/> <el-image v-else :src="pingArrow" style="width: 10px; "/> </div> </div>
</div>
</el-col> <!-- 新增的环形图容器 --> <el-col :span="12"> <div ref="rechargePeopleChart" style="width:100%; height: 68%;"></div> </el-col> </el-row> </div> </el-col> </el-row> </div> </template>
<script setup> import {onMounted, ref, nextTick} from 'vue' import * as echarts from 'echarts' import API from '@/util/http' import dayjs from 'dayjs'; import utc from 'dayjs-plugin-utc' import {ArrowDownBold, ArrowUpBold, SemiSelect} from '@element-plus/icons-vue' import svg1 from '@/assets/SvgIcons/折合新币累计金额.svg' import svg2 from '@/assets/SvgIcons/周同比.svg' import upArrow from '@/assets/SvgIcons/上升箭头.svg' import downArrow from '@/assets/SvgIcons/下降箭头.svg' import pingArrow from '@/assets/SvgIcons/持平.svg'
dayjs.extend(utc)
// 用户信息
const adminData = ref({}) // 卡片数据相关
const currentGold = ref(0) const dailyChange = ref(0) const currentPermanent = ref(0) const currentFree = ref(0) const currentFreeJune = ref(0) const currentFreeDecember = ref(0) const currentTask = ref(0) const yearlyRecharge = ref(0) const yearlyMoney = ref(0) const recharge = ref(0) const money = ref(0) const yearlyReduce = ref(0) const yearlyConsume = ref(0) const yearlyRefund = ref(0) const dailyReduce = ref(0) const dailyConsume = ref(0) const dailyRefund = ref(0) const yearlyRechargeNum = ref(0) const sumWow = ref(0) const sumDaily = ref(0) const rechargeNum = ref(0) const ydayRechargeNum = ref(0) const firstRecharge = ref(0) const length = ref(0)
// ECharts 实例引用
const goldTypeChart = ref(null) const rechargeGoldChart = ref(null) const consumeChart = ref(null) const consumeDetailChart = ref(null) const rechargePeopleChart = ref(null)
// 要加上所有市场的,还有额外计算的(总数 = 永久 + 6月 + 12月 + 免费 + 任务)
const processData = (data) => { const summary = { currentGold: 0, dailyChange: 0, currentPermanent: 0, currentFreeJune: 0, currentFreeDecember: 0, currentTask: 0, currentFree: 0, recharge: 0, money: 0, yearlyRecharge: 0, yearlyMoney: 0, consumePermanent: 0, consumeFreeJune: 0, consumeFreeDecember: 0, consumeTask: 0, refundPermanent: 0, refundFreeJune: 0, refundFreeDecember: 0, refundTask: 0, dailyReduce: 0, yearlyConsume: 0, yearlyRefund: 0, yearlyReduce: 0, rechargeNum: 0, ydayRechargeNum: 0, firstRecharge: 0, sumWow: 0, sumDaily: 0, yearlyRechargeNum: 0 }
// 遍历市场
data.marketCards.forEach(market => { for (const i in summary) { if (market[i] !== undefined && market[i] !== null) { summary[i] += market[i] } } })
// wow和daily除一下
length.value = data.markets.length console.log(length.value)
// 计算昨日新增消费和退款
const yesterdayConsume = summary.consumePermanent + summary.consumeFreeJune + summary.consumeFreeDecember + summary.consumeTask const yesterdayRefund = summary.refundPermanent + summary.refundFreeJune + summary.refundFreeDecember + summary.refundTask
// 更新卡片数据
currentGold.value = summary.currentGold.toFixed(2) dailyChange.value = summary.dailyChange.toFixed(2) currentPermanent.value = summary.currentPermanent.toFixed(2) currentFree.value = summary.currentFree.toFixed(2) currentFreeJune.value = summary.currentFreeJune.toFixed(2) currentFreeDecember.value = summary.currentFreeDecember.toFixed(2) currentTask.value = summary.currentTask.toFixed(2)
yearlyRecharge.value = summary.yearlyRecharge.toFixed(2) yearlyMoney.value = summary.yearlyMoney.toFixed(2) recharge.value = summary.recharge.toFixed(2) money.value = summary.money.toFixed(2)
yearlyReduce.value = summary.yearlyReduce.toFixed(2) yearlyConsume.value = summary.yearlyConsume.toFixed(2) yearlyRefund.value = summary.yearlyRefund.toFixed(2) dailyReduce.value = summary.dailyReduce.toFixed(2) dailyConsume.value = yesterdayConsume.toFixed(2) dailyRefund.value = yesterdayRefund.toFixed(2)
yearlyRechargeNum.value = summary.yearlyRechargeNum
ydayRechargeNum.value = summary.ydayRechargeNum firstRecharge.value = summary.firstRecharge
// 初始化图表
nextTick(() => { // initGoldTypeChart();
initRechargeGoldChart(); initConsumeChart(); initConsumeDetailChart(); initRechargePeopleChart(); }); }
// 初始化金币类型南丁格尔图
const initGoldTypeChart = () => { const myChart = echarts.init(goldTypeChart.value); const option = { tooltip: { trigger: 'item', formatter: function (params) { let realValue = 0 if (params.name === '永久金币') realValue = currentPermanent.value / 100 else if (params.name === '免费金币') realValue = (currentFreeJune.value / 100 + currentFreeDecember.value / 100) else realValue = currentTask.value / 100 return `${params.name}: ${realValue}` } }, toolbox: { show: true, feature: {} }, series: [ { name: 'Nightingale Chart', type: 'pie', radius: ['0%', '100%'], center: ['50%', '50%'], roseType: 'area', itemStyle: { borderRadius: 5 }, data: [ {value: Math.log(currentPermanent.value / 100 + 1), name: '永久金币'}, {value: Math.log((currentFreeJune.value / 100 + currentFreeDecember.value / 100) + 1), name: '免费金币'}, {value: Math.log(currentTask.value / 100 + 1), name: '任务金币'} ], labelLine: {show: false}, label: {show: false} } ] }; myChart.setOption(option); }
// 初始化充值金币环形图
const initRechargeGoldChart = () => { const myChart = echarts.init(rechargeGoldChart.value); const option = { series: [ { type: 'pie', radius: ['60%', '85%'], silent: true, clockwise: true, label: {show: false}, data: [ { value: recharge.value / 100, itemStyle: {color: '#80aaff'}
} ] }, { type: 'pie', radius: ['60%', '75%'], startAngle: 180, silent: true, clockwise: true, label: {show: false}, data: [ { value: money.value / 100, itemStyle: {color: '#f2c97d'}
}, { value: (recharge.value / 100 - money.value / 100), itemStyle: {color: 'transparent'} } ] } ] };
myChart.setOption(option); }
// 初始化消费退款环形图
const initConsumeChart = () => { const myChart = echarts.init(consumeChart.value); const option = { legend: { orient: 'vertical', left: '10%', top: '85', icon: 'circle', iconSize: 5, textSize: 12, itemWidth: 7, itemHeight: 7, },
series: [ { type: 'pie', radius: ['30%', '45%'], center: ['50%', '35%'], silent: true, clockwise: true, label: {show: false}, data: [ { value: yearlyConsume.value / 100, name: '消耗:' + yearlyConsume.value / 100, // name: '消耗:' + 1234567890,
itemStyle: {color: '#7DB7FA'}
}, { value: yearlyRefund.value / 100, name: '退款:' + yearlyRefund.value / 100, itemStyle: {color: '#F7D47C'}
} ], } ] }; myChart.setOption(option); }; // 初始化消费明细环形图
const initConsumeDetailChart = () => { const myChart = echarts.init(consumeDetailChart.value); const option = { // 增加图表内边距,避免内容溢出
legend: { orient: 'vertical', left: '20%', top: '85', icon: 'circle', iconSize: 5, itemWidth: 7, itemHeight: 7,
}, series: [ { type: 'pie', radius: ['25%', '40%'], center: ['50%', '25%'], silent: true, clockwise: true, label: {show: false}, data: [ { value: dailyConsume.value / 100, name: '昨日新增消费:' + dailyConsume.value / 100, itemStyle: {color: '#65C9C9'} } ] }, { type: 'pie', radius: ['25%', '35%'], center: ['50%', '25%'],
startAngle: 180, silent: true, clockwise: true, label: {show: false}, data: [ { value: dailyReduce.value / 100, name: '昨日新增消耗:' + dailyReduce.value / 100, // name: '昨日新增消耗:' + 1234567890,
itemStyle: {color: '#9469D1'} }, { value: dailyRefund.value / 100, name: '昨日新增退款:' + dailyRefund.value / 100, itemStyle: {color: '#B8DB6E'} } ] } ] };
myChart.setOption(option); }; // 初始化充值人头环形图
const initRechargePeopleChart = () => { const myChart = echarts.init(rechargePeopleChart.value); const option = { legend: { orient: 'vertical', left: '20%', top: '85', icon: 'circle', iconSize: 5, textSize: 18, itemWidth: 7, itemHeight: 7, }, series: [ { type: 'pie', radius: ['30%', '50%'], center: ['50%', '35%'], silent: true, clockwise: true, label: {show: false}, data: [ { value: ydayRechargeNum.value, name: '昨日充值人数:' + ydayRechargeNum.value, itemStyle: {color: '#65C9C9'} }, ], }, { type: 'pie', radius: ['30%', '45%'], center: ['50%', '35%'], silent: true, clockwise: true, label: {show: false}, data: [ { value: firstRecharge.value, name: '其中首充:' + firstRecharge.value, itemStyle: {color: '#9469D1'} }, { value: ydayRechargeNum.value - firstRecharge.value, itemStyle: {color: 'transparent'} } ], } ] }; myChart.setOption(option); } // 获取卡片数据
const getCardData = async () => { try { const response = await API({url: '/workbench/getCard', data: {}}) workDataUpdateTime.value = response.updateTime // 周同比
sumWow.value = response.sumWow.toFixed(2) // 日环比
sumDaily.value = response.sumDaily.toFixed(2)
if (response && response.data) { processData(response.data) } else if (Array.isArray(response?.marketCards)) { processData(response) } else { console.error('无效的API响应结构:', response) } } catch (error) { console.error('获取卡片数据失败:', error) } }
const workDataUpdateTime = ref(null)
onMounted(async () => { await getCardData() }) </script>
<style scoped lang="scss">
.center-card { display: flex; justify-content: center; align-items: center; }
.card-item-row1 { height: 160px; width: auto; background: #E4F0FC; box-shadow: 0 0 4px 0 #00000040; border-radius: 10px; margin-top: 20px; margin-left: 5px; margin-right: 5px; margin-bottom: -5px; padding-bottom: 10px; }
.card-item { height: 200px; width: auto; background: #E4F0FC; box-shadow: 0 0 4px 0 #00000040; border-radius: 10px; margin-top: 20px; margin-left: 5px; margin-right: 5px; margin-bottom: -5px; padding-bottom: 10px; }
.card-title { font-weight: bold; height: 36px; width: 100%; flex-shrink: 0; border-radius: 8px; background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%); box-shadow: 0 0 2px 0 #00152940; display: flex; align-items: center; justify-content: center; margin-top: -5px; margin-bottom: 10px; }
.card-item .el-col { overflow: visible; }
@keyframes spin { 0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); } }
.gold-title { width: 100%; height: 5vh; flex-shrink: 0; border-radius: 8px; background: linear-gradient(90deg, #E4F0FC 0%, #FFF178 50%, #E4F0FC 100%); box-shadow: 0 2px 2px 0 #00152940; display: flex; align-items: center; justify-content: center; }
.text1 { color: #040a2d; font-family: " PingFang SC "; font-size: 28px; font-style: normal; font-weight: 900; line-height: 31.79px; }
.text1-update-time { width: 100%; height: 26px; flex-shrink: 0; color: #040a2d; font-family: "PingFang SC"; font-size: 20px; font-style: normal; font-weight: 700; line-height: 31.79px; }
/* 背景卡片大小 */ .gold-management { margin: 10px 5px; width: 100%; height: 50vh; flex-shrink: 0; border-radius: 8px; background: #E7F4FD; box-shadow: 0 2px 2px 0 #00000040; flex-direction: column; align-items: center; }
.margin-bottom { padding-left: 20px; }
.chart5 { margin-top: 15px;
.margin-bottom { margin-top: 10px; padding-left: 20px; } } </style>
|