Browse Source

add:工作台左侧卡片,右侧卡片,底部柱状图,柱状图需要优化排名部分 按钮部分

lihui/feature-20250915101448-现金管理
lihui 2 weeks ago
parent
commit
3acbf1c452
  1. 14
      src/assets/SvgIcons/上升箭头.svg
  2. 14
      src/assets/SvgIcons/下降箭头.svg
  3. 14
      src/assets/SvgIcons/持平.svg
  4. 64
      src/components/workspace/CashManagement.vue
  5. 100
      src/components/workspace/GoldGraph.vue
  6. 471
      src/components/workspace/GoldManagement.vue
  7. 8
      src/views/workspace/index.vue

14
src/assets/SvgIcons/上升箭头.svg

@ -0,0 +1,14 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 14" class="design-iconfont">
<path d="M3.33333 14H6.66667V7.875V5.25H10L5 0L0 5.25H3.33333V7.875V14Z" fill="url(#9ch16kl2f__paint0_linear_454_32894)"/>
<path d="M6.54883 13.8828V5.13281H9.72656L5 0.170898L0.273438 5.13281H3.45117V13.8828H6.54883Z" stroke="url(#9ch16kl2f__paint1_linear_454_32894)" stroke-opacity=".63" stroke-width=".235129" stroke-miterlimit="10"/>
<defs>
<linearGradient id="9ch16kl2f__paint0_linear_454_32894" x1=".938339" y1="14" x2="12.7734" y2="9.25209" gradientUnits="userSpaceOnUse">
<stop stop-color="#F46C6C"/>
<stop offset="1" stop-color="#FCC4C5"/>
</linearGradient>
<linearGradient id="9ch16kl2f__paint1_linear_454_32894" x1=".975668" y1="14" x2="12.7608" y2="9.22824" gradientUnits="userSpaceOnUse">
<stop stop-color="#FCC4C5"/>
<stop offset="1" stop-color="#fff"/>
</linearGradient>
</defs>
</svg>

14
src/assets/SvgIcons/下降箭头.svg

@ -0,0 +1,14 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 14" class="design-iconfont">
<path d="M3.33333 0H6.66667V6.125V8.75H10L5 14L0 8.75H3.33333V6.125V0Z" fill="url(#3jb4xovw8__paint0_linear_415_444599)"/>
<path d="M6.50977 0.157227V8.90723H9.63379L5 13.7725L0.366211 8.90723H3.49023V0.157227H6.50977Z" stroke="url(#3jb4xovw8__paint1_linear_415_444599)" stroke-opacity=".63" stroke-width=".313505" stroke-miterlimit="10"/>
<defs>
<linearGradient id="3jb4xovw8__paint0_linear_415_444599" x1=".938339" y1="-6.2e-7" x2="12.7734" y2="4.74791" gradientUnits="userSpaceOnUse">
<stop stop-color="#047CF5"/>
<stop offset="1" stop-color="#4CB9F9"/>
</linearGradient>
<linearGradient id="3jb4xovw8__paint1_linear_415_444599" x1=".975668" y1="4.4e-7" x2="12.7608" y2="4.77176" gradientUnits="userSpaceOnUse">
<stop stop-color="#4CB9F9"/>
<stop offset="1" stop-color="#fff"/>
</linearGradient>
</defs>
</svg>

14
src/assets/SvgIcons/持平.svg

@ -0,0 +1,14 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 5" class="design-iconfont">
<rect x="1" y="1" width="11" height="3" rx=".6875" fill="url(#12pnzcg9o__paint0_linear_443_32365)" fill-opacity=".7"/>
<rect x=".838349" y=".838349" width="11.3233" height="3.3233" rx=".849151" stroke="url(#12pnzcg9o__paint1_linear_443_32365)" stroke-opacity=".63" stroke-width=".323302" stroke-miterlimit="10"/>
<defs>
<linearGradient id="12pnzcg9o__paint0_linear_443_32365" x1="2.03217" y1="1" x2="4.91594" y2="6.93872" gradientUnits="userSpaceOnUse">
<stop/>
<stop offset="1" stop-color="#8A8A8A"/>
</linearGradient>
<linearGradient id="12pnzcg9o__paint1_linear_443_32365" x1="2.07323" y1="1" x2="4.90949" y2="6.89506" gradientUnits="userSpaceOnUse">
<stop stop-color="#8A8A8A"/>
<stop offset="1" stop-color="#fff"/>
</linearGradient>
</defs>
</svg>

64
src/components/workspace/CashManagement.vue

@ -4,7 +4,7 @@
<div class="cash-title"> <div class="cash-title">
<div class="text1"> 现金管理 <div class="text1"> 现金管理
<span class="text1-update-time">最后更新时间{{ <span class="text1-update-time">最后更新时间{{
workDataUpdateTime && workDataUpdateTime !== '1970-01-01 08:00:00' ? workDataUpdateTime : '该地区暂无数据'
workDataUpdateTime && workDataUpdateTime !== '1970-01-01 08:00:00' ? workDataUpdateTime : '该地区暂无数据'
}}</span> }}</span>
</div> </div>
</div> </div>
@ -30,18 +30,18 @@
<script setup> <script setup>
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { ref, onMounted } from 'vue'
import {ref, onMounted} from 'vue'
// //
const cashData = ref({ const cashData = ref({
updateTime: '2025-09-24 12:00:00', updateTime: '2025-09-24 12:00:00',
totalIncome: 1200000, totalIncome: 1200000,
markets: [ markets: [
{ name: '北京', value: 450000 },
{ name: '上海', value: 300000 },
{ name: '广州', value: 200000 },
{ name: '深圳', value: 150000 },
{ name: '其他', value: 100000 }
{name: '北京', value: 450000},
{name: '上海', value: 300000},
{name: '广州', value: 200000},
{name: '深圳', value: 150000},
{name: '其他', value: 100000}
] ]
}) })
@ -53,16 +53,17 @@ const renderChart = () => {
chartInstance = echarts.init(chartRef.value) chartInstance = echarts.init(chartRef.value)
} }
const option = { const option = {
tooltip: { trigger: 'item' },
tooltip: {trigger: 'item'},
legend: { legend: {
bottom: 5, // bottom: 5, //
left: 'center' },
left: 'center'
},
series: [ series: [
{ {
type: 'pie', type: 'pie',
radius: ['40%', '70%'], radius: ['40%', '70%'],
data: cashData.value.markets, data: cashData.value.markets,
center: [ '60%', '45%'] //
center: ['60%', '45%'] //
} }
] ]
} }
@ -79,7 +80,7 @@ onMounted(() => {
.cash-management { .cash-management {
margin: 10px 5px; margin: 10px 5px;
width: 100%; width: 100%;
height: 55vh;
height: 50vh;
flex-shrink: 0; flex-shrink: 0;
border-radius: 8px; border-radius: 8px;
background: #E7F4FD; background: #E7F4FD;
@ -88,6 +89,7 @@ onMounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
/* /*
.cash-card { .cash-card {
width: 100%; width: 100%;
@ -134,29 +136,29 @@ onMounted(() => {
/* 总收入的渐变框 */ /* 总收入的渐变框 */
.text2 { .text2 {
margin: 13px;
margin: 13px;
width: 95%; width: 95%;
height: 48px;
flex-shrink: 0;
border-radius: 8px;
background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
height: 48px;
flex-shrink: 0;
border-radius: 8px;
background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
} }
/* 总收入字体 */ /* 总收入字体 */
.text2-income { .text2-income {
width: 215px;
height: 26px;
flex-shrink: 0;
color: #040a2d;
font-family: "PingFang SC";
font-size: 20px;
font-style: normal;
font-weight: 900;
line-height: 31.79px;
width: 215px;
height: 26px;
flex-shrink: 0;
color: #040a2d;
font-family: "PingFang SC";
font-size: 20px;
font-style: normal;
font-weight: 900;
line-height: 31.79px;
} }
/* 图表容器 */ /* 图表容器 */
@ -197,9 +199,9 @@ justify-content: center;
} }
/* 图表样式 */ /* 图表样式 */
/* .chart {
.chart {
flex: 1; flex: 1;
height: 300px; height: 300px;
margin-top: 10px; margin-top: 10px;
} */
}
</style> </style>

100
src/components/workspace/GoldGraph.vue

@ -1,6 +1,6 @@
<template> <template>
<div class="graph"> <div class="graph">
<el-card style="width:84vw;">
<el-card style="width:100%;" class="graph-card">
<div> <div>
<el-tabs v-model="activeTab" @tab-change="handleTabChange"> <el-tabs v-model="activeTab" @tab-change="handleTabChange">
<el-tab-pane label="金币充值" name="recharge"></el-tab-pane> <el-tab-pane label="金币充值" name="recharge"></el-tab-pane>
@ -29,8 +29,9 @@
<div> <div>
<el-date-picker size="small" v-model="dateRange" type="datetimerange" range-separator="" <el-date-picker size="small" v-model="dateRange" type="datetimerange" range-separator=""
start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss" start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss"
style="width:20vw;margin-left:0.5vw;" value-format="YYYY-MM-DD HH:mm:ss" :default-time="defaultTime"
:disabled-date="disabledDate" @change="handleDatePickerChange" />
style="width:20vw;margin-left:0.5vw;" value-format="YYYY-MM-DD HH:mm:ss"
:default-time="defaultTime"
:disabled-date="disabledDate" @change="handleDatePickerChange"/>
<el-button type="primary" size="small" style="margin-left: 0.5vw" @click="getChartData">查询</el-button> <el-button type="primary" size="small" style="margin-left: 0.5vw" @click="getChartData">查询</el-button>
</div> </div>
</div> </div>
@ -38,15 +39,15 @@
<div class="graph-content"> <div class="graph-content">
<div ref="chartRef" class="left"></div> <div ref="chartRef" class="left"></div>
<div class="right"> <div class="right">
<el-card>
<el-card class="graph-card-list">
<div class="card-large">金币{{ activeTab === 'recharge' ? '充值' : '消费' }}排名</div> <div class="card-large">金币{{ activeTab === 'recharge' ? '充值' : '消费' }}排名</div>
<el-select v-model="selectedType" style="width: 100%; margin-bottom: 15px">
<el-select class="card-select" v-model="selectedType" style="width: 100%; margin-bottom: 15px">
<el-option label="全部类型" value="all"></el-option> <el-option label="全部类型" value="all"></el-option>
<el-option label="永久金币" value="permanent"></el-option> <el-option label="永久金币" value="permanent"></el-option>
<el-option label="免费金币" value="free"></el-option> <el-option label="免费金币" value="free"></el-option>
<el-option label="任务金币" value="task"></el-option> <el-option label="任务金币" value="task"></el-option>
</el-select> </el-select>
<el-table :data="tableData" height="320px">
<el-table class="card-table" :data="tableData" height="320px">
<el-table-column prop="rank" label="排名" width="60" align="center"></el-table-column> <el-table-column prop="rank" label="排名" width="60" align="center"></el-table-column>
<el-table-column prop="market" label="地区" align="center"> <el-table-column prop="market" label="地区" align="center">
<template #default="scope"> <template #default="scope">
@ -511,7 +512,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargePermanent, data: chartData.rechargePermanent,
itemStyle: { color: '#5470c6' },
itemStyle: {color: '#5470c6'},
barWidth: 30 barWidth: 30
}, },
{ {
@ -519,7 +520,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargeFree, data: chartData.rechargeFree,
itemStyle: { color: '#91cc75' },
itemStyle: {color: '#91cc75'},
barWidth: 30 barWidth: 30
}, },
{ {
@ -527,7 +528,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargeTask, data: chartData.rechargeTask,
itemStyle: { color: '#fac858' },
itemStyle: {color: '#fac858'},
barWidth: 30 barWidth: 30
} }
] ]
@ -539,7 +540,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumePermanent, data: chartData.consumePermanent,
itemStyle: { color: '#5470c6' },
itemStyle: {color: '#5470c6'},
barWidth: 30 barWidth: 30
}, },
{ {
@ -547,7 +548,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumeFree, data: chartData.consumeFree,
itemStyle: { color: '#91cc75' },
itemStyle: {color: '#91cc75'},
barWidth: 30 barWidth: 30
}, },
{ {
@ -555,7 +556,7 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumeTask, data: chartData.consumeTask,
itemStyle: { color: '#fac858' },
itemStyle: {color: '#fac858'},
barWidth: 30 barWidth: 30
} }
] ]
@ -594,16 +595,24 @@ const updateChart = (chartData) => {
data: markets.value, data: markets.value,
axisLabel: { axisLabel: {
interval: 0, interval: 0,
rotate: 30
rotate: 0
} }
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
splitLine: {
lineStyle: {
type: 'dashed',
width: 1,
color: '#000000'
}
},
axisLabel: { axisLabel: {
formatter: function (value) { formatter: function (value) {
return value.toLocaleString() return value.toLocaleString()
} }
}
},
}, },
series: series, series: series,
// dataZoom: [ // dataZoom: [
@ -639,7 +648,7 @@ const handleTabChange = () => {
const getAdminData = async function () { const getAdminData = async function () {
try { try {
const result = await API({ url: '/admin/userinfo', data: {} })
const result = await API({url: '/admin/userinfo', data: {}})
adminData.value = result adminData.value = result
console.log('用户信息', adminData.value) console.log('用户信息', adminData.value)
} catch (error) { } catch (error) {
@ -649,7 +658,7 @@ const getAdminData = async function () {
// //
const getCardData = async () => { const getCardData = async () => {
try { try {
const response = await API({ url: '/workbench/getCard', data: {} })
const response = await API({url: '/workbench/getCard', data: {}})
workDataUpdateTime.value = response.updateTime workDataUpdateTime.value = response.updateTime
// //
sumWow.value = response.sumWow.toFixed(2) sumWow.value = response.sumWow.toFixed(2)
@ -756,6 +765,7 @@ onUnmounted(() => {
font-size: 16px; font-size: 16px;
text-align: center; text-align: center;
margin-bottom: 15px; margin-bottom: 15px;
} }
@keyframes spin { @keyframes spin {
@ -767,4 +777,62 @@ onUnmounted(() => {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.graph-card {
background: #F3FAFF;
box-shadow: 0 0 8px 0 #00000040;
}
.graph-card-list {
background: #F3FAFF;
box-shadow: 0 0 8px 0 #00000040;
padding: 12px;
.card-select {
:deep(.el-input__wrapper) {
background-color: #E7F4FD !important;
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25) !important;
border: none !important;
}
:deep(.el-input__inner) {
background-color: transparent !important;
}
:deep(.el-input__suffix) {
background-color: transparent !important;
}
}
/* 表格整体背景:把表格容器设为卡片背景 */
:deep(.el-table) {
background-color: #F3FAFF !important;
box-shadow: none !important;
}
/* 表头/表体 wrapper 与 table body 单元格 */
:deep(.el-table__header-wrapper),
:deep(.el-table__body-wrapper),
:deep(.el-table__body),
:deep(.el-table__header),
:deep(.el-table__body tbody),
:deep(.el-table__body tr),
:deep(.el-table__row),
:deep(.el-table__cell),
:deep(.el-table__body td) {
background-color: transparent !important;
}
/* 表头 */
:deep(.el-table__header th) {
background-color: #F3FAFF !important;
}
/* 行之间的分隔线(更像卡片内表格) */
:deep(.el-table .el-table__row):not(:last-child) {
border-bottom: 1px solid rgba(0,0,0,0.06);
}
}
</style> </style>

471
src/components/workspace/GoldManagement.vue

@ -1,43 +1,40 @@
<template> <template>
<div>
金币管理 <span class="text">
最后更新时间{{
workDataUpdateTime && workDataUpdateTime !== '1970-01-01 08:00:00' ? workDataUpdateTime : '该地区暂无数据'
}}
</span>
<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-row>
<el-col :span="12"> <el-col :span="12">
<!-- 第一个卡片 --> <!-- 第一个卡片 -->
<el-card class="card-item">
<template #header>
<div class="card-title">当前金币余量
<span style="font-weight: bold">{{
currentGold / 100
}}</span>&nbsp;&nbsp;&nbsp;&nbsp;较前一日
{{ dailyChange / 100 }}
<template v-if="dailyChange > 0">
<el-icon style="color:red">
<ArrowUpBold/>
</el-icon>
</template>
<template v-else-if="dailyChange < 0">
<el-icon style="color:forestgreen">
<ArrowDownBold/>
</el-icon>
</template>
<template v-else>
<el-icon style="color:grey">
<SemiSelect/>
</el-icon>
</template>
</div>
</template>
<div class="card-item-row1">
<div class="card-title">当前金币余量
<span style="font-weight: bold">{{
currentGold / 100
}}</span>&nbsp;&nbsp;&nbsp;&nbsp;较前一日
{{ dailyChange / 100 }}&nbsp;
<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> <div>
<el-row> <el-row>
<!-- 左边文本信息 --> <!-- 左边文本信息 -->
<el-col :span="12"> <el-col :span="12">
<div class="margin-bottom">永久金币<b>{{ currentPermanent / 100 }}</b></div>
<div class="margin-bottom" style="white-space: nowrap;">
永久金币<b>{{ currentPermanent / 100 }}</b>
</div>
<div class="margin-bottom">&nbsp;</div> <div class="margin-bottom">&nbsp;</div>
<div class="margin-bottom">免费金币{{ currentFree / 100 }}</div> <div class="margin-bottom">免费金币{{ currentFree / 100 }}</div>
@ -48,7 +45,7 @@
</div> </div>
<div class="margin-bottom">&nbsp;</div> <div class="margin-bottom">&nbsp;</div>
<div>任务金币{{ currentTask / 100 }}</div>
<div class="margin-bottom">任务金币{{ currentTask / 100 }}</div>
</el-col> </el-col>
<!-- 右边图表 --> <!-- 右边图表 -->
<el-col :span="12"> <el-col :span="12">
@ -61,88 +58,76 @@
</el-row> </el-row>
</div> </div>
</el-card>
</div>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<!-- 第二个卡片 --> <!-- 第二个卡片 -->
<el-card class="card-item">
<div class="card-item-row1">
<div class="card-title">全年累计充值金币数{{ yearlyRecharge / 100 }}</div> <div class="card-title">全年累计充值金币数{{ yearlyRecharge / 100 }}</div>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<div class="center-card">折合新币累计金额:{{ yearlyMoney / 100 }}</div>
<div class="center-card">昨日新增金币{{ recharge / 100 }}</div>
<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>
<el-col :span="12">
<div class="center-card">其中永久金币{{ money / 100 }}</div>
<!-- 新增的环形图容器 -->
<div ref="rechargeGoldChart" style="width: 100%; height: 150px; margin-top: 10px;"></div>
<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-col>
</el-row> </el-row>
</el-card>
</div>
</el-col> </el-col>
</el-row> </el-row>
<!-- 第二行包含两个横向格子 --> <!-- 第二行包含两个横向格子 -->
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<!-- 第三个卡片 --> <!-- 第三个卡片 -->
<el-card class="card-item">
<div class="card-item">
<div class="card-title">全年累计消费金币数{{ yearlyReduce / 100 }}</div> <div class="card-title">全年累计消费金币数{{ yearlyReduce / 100 }}</div>
<div style="padding-left: 30%;">消耗{{ yearlyConsume / 100 }}</div>
<div style="padding-left: 30%;">退款{{ yearlyRefund / 100 }}</div>
<!-- 新增的两个环形图容器 -->
<div ref="consumeChart" style="width: 100%; height: 150px; margin-top: 10px;"></div>
<template #footer>
<div style="margin-bottom:0.5%;padding-left: 30%;">昨日新增消费{{ dailyConsume / 100 }}</div>
<div style="margin-bottom:0.5%;padding-left: 30%;">昨日新增消耗{{ dailyReduce / 100 }}</div>
<div style="margin-bottom:0.5%;padding-left: 30%;">昨日新增退款{{ dailyRefund / 100 }}</div>
</template>
</el-card>
<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>
<el-col :span="12"> <el-col :span="12">
<!-- 第四个卡片 --> <!-- 第四个卡片 -->
<el-card class="card-item">
<el-col class="card-title">全年累计充值人头数{{ yearlyRechargeNum }}</el-col>
<el-col style="padding-left: 35%;">周同比:{{ sumWow }}%&nbsp;&nbsp;&nbsp;&nbsp;
<template v-if="sumWow > 0">
<el-icon style="color:red">
<ArrowUpBold/>
</el-icon>
</template>
<template v-else-if="sumWow < 0">
<el-icon style="color:forestgreen">
<ArrowDownBold/>
</el-icon>
</template>
<template v-else>
<el-icon style="color:grey">
<SemiSelect/>
</el-icon>
</template>
</el-col>
<el-col style="padding-left: 35%;">日环比:{{ sumDaily }}%&nbsp;&nbsp;&nbsp;&nbsp;
<template v-if="sumDaily > 0">
<el-icon style="color:red">
<ArrowUpBold/>
</el-icon>
</template>
<template v-else-if="sumDaily < 0">
<el-icon style="color:forestgreen">
<ArrowDownBold/>
</el-icon>
</template>
<template v-else>
<el-icon style="color:grey">
<SemiSelect/>
</el-icon>
</template>
</el-col>
<!-- 新增的环形图容器 -->
<div ref="rechargePeopleChart" style="width: 100%; height: 150px; margin-top: 10px;"></div>
<template #footer>
<el-col style="padding-left: 35%;margin-bottom:0.5%">昨日充值人数{{ ydayRechargeNum }}</el-col>
<el-col style="padding-left: 35%;">其中首充{{ firstRecharge }}</el-col>
</template>
</el-card>
<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-col>
</el-row> </el-row>
</div> </div>
@ -155,6 +140,11 @@ import API from '@/util/http'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import utc from 'dayjs-plugin-utc' import utc from 'dayjs-plugin-utc'
import {ArrowDownBold, ArrowUpBold, SemiSelect} from '@element-plus/icons-vue' 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) dayjs.extend(utc)
@ -190,6 +180,7 @@ const length = ref(0)
const goldTypeChart = ref(null) const goldTypeChart = ref(null)
const rechargeGoldChart = ref(null) const rechargeGoldChart = ref(null)
const consumeChart = ref(null) const consumeChart = ref(null)
const consumeDetailChart = ref(null)
const rechargePeopleChart = ref(null) const rechargePeopleChart = ref(null)
// ( = + 6 + 12 + + ) // ( = + 6 + 12 + + )
@ -271,9 +262,10 @@ const processData = (data) => {
// //
nextTick(() => { nextTick(() => {
initGoldTypeChart();
// initGoldTypeChart();
initRechargeGoldChart(); initRechargeGoldChart();
initConsumeChart(); initConsumeChart();
initConsumeDetailChart();
initRechargePeopleChart(); initRechargePeopleChart();
}); });
} }
@ -326,18 +318,40 @@ const initRechargeGoldChart = () => {
series: [ series: [
{ {
type: 'pie', type: 'pie',
radius: ['50%', '70%'],
radius: ['60%', '85%'],
silent: true,
clockwise: true,
label: {show: false},
data: [ data: [
{value: money.value / 100, name: '永久金币'},
{value: (recharge.value - money.value) / 100, name: '其他金币'}
],
label: {
show: true,
formatter: '{b}: {c}'
}
{
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); myChart.setOption(option);
} }
@ -345,46 +359,157 @@ const initRechargeGoldChart = () => {
const initConsumeChart = () => { const initConsumeChart = () => {
const myChart = echarts.init(consumeChart.value); const myChart = echarts.init(consumeChart.value);
const option = { const option = {
legend: {
orient: 'vertical',
left: '10%',
top: '85',
icon: 'circle',
iconSize: 5,
textSize: 12,
itemWidth: 7,
itemHeight: 7,
},
series: [ series: [
{ {
type: 'pie', type: 'pie',
radius: ['40%', '70%'],
radius: ['30%', '45%'],
center: ['50%', '35%'],
silent: true,
clockwise: true,
label: {show: false},
data: [ data: [
{value: yearlyConsume.value / 100, name: '消耗'},
{value: yearlyRefund.value / 100, name: '退款'}
{
value: yearlyConsume.value / 100,
name: '消耗:' + yearlyConsume.value / 100,
// name: '' + 1234567890,
itemStyle: {color: '#7DB7FA'}
},
{
value: yearlyRefund.value / 100,
name: '退款:' + yearlyRefund.value / 100,
itemStyle: {color: '#F7D47C'}
}
], ],
label: {
show: true,
formatter: '{b}: {c}'
}
} }
] ]
}; };
myChart.setOption(option); myChart.setOption(option);
}
};
//
const initConsumeDetailChart = () => {
const myChart = echarts.init(consumeDetailChart.value);
const option = {
//
legend: {
orient: 'vertical',
left: 'left',
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 initRechargePeopleChart = () => {
const myChart = echarts.init(rechargePeopleChart.value); const myChart = echarts.init(rechargePeopleChart.value);
const option = { const option = {
legend: {
orient: 'vertical',
left: 'left',
top: '85',
icon: 'circle',
iconSize: 5,
textSize: 18,
itemWidth: 7,
itemHeight: 7,
},
series: [ series: [
{ {
type: 'pie', type: 'pie',
radius: ['40%', '70%'],
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: [ data: [
{value: firstRecharge.value, name: '首充'},
{value: (ydayRechargeNum.value - firstRecharge.value), name: '非首充'}
{
value: firstRecharge.value,
name: '其中首充:' + firstRecharge.value,
itemStyle: {color: '#9469D1'}
},
{
value: ydayRechargeNum.value - firstRecharge.value,
itemStyle: {color: 'transparent'}
}
], ],
label: {
show: true,
formatter: '{b}: {c}'
}
} }
] ]
}; };
myChart.setOption(option); myChart.setOption(option);
} }
// //
const getCardData = async () => { const getCardData = async () => {
try { try {
@ -406,6 +531,7 @@ const getCardData = async () => {
console.error('获取卡片数据失败:', error) console.error('获取卡片数据失败:', error)
} }
} }
const workDataUpdateTime = ref(null) const workDataUpdateTime = ref(null)
@ -415,12 +541,7 @@ onMounted(async () => {
</script> </script>
<style scoped> <style scoped>
.card {
height: 28vh;
margin-bottom: 0.5vh;
display: flex;
justify-content: center;
}
.center-card { .center-card {
display: flex; display: flex;
@ -428,18 +549,50 @@ onMounted(async () => {
align-items: 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 { .card-item {
height: 28vh;
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 { .card-title {
font-weight: bold; font-weight: bold;
margin-bottom: 1vh;
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; display: flex;
justify-content: center;
align-items: center; align-items: center;
justify-content: center;
margin-top: -5px;
margin-bottom: 10px;
}
.card-item .el-col {
overflow: visible;
} }
@keyframes spin { @keyframes spin {
@ -451,4 +604,64 @@ onMounted(async () => {
transform: rotate(360deg); 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> </style>

8
src/views/workspace/index.vue

@ -3,13 +3,13 @@
<el-header class="header"> <el-header class="header">
<div class="title">数据总览</div> <div class="title">数据总览</div>
</el-header> </el-header>
<div style="height: 100vh; overflow: auto;">
<div style="height: 100vh;">
<el-row class="cards" > <el-row class="cards" >
<el-col :span="12">
<el-col :span="14">
<GoldManagement :cardData="cardData" /> <GoldManagement :cardData="cardData" />
</el-col> </el-col>
<!-- 右上格子占12列 --> <!-- 右上格子占12列 -->
<el-col :span="12">
<el-col :span="10">
<CashManagement /> <CashManagement />
</el-col> </el-col>
</el-row> </el-row>
@ -35,7 +35,7 @@ const markets = ref([])
const account = ref('') const account = ref('')
const activeTab = ref('recharge') const activeTab = ref('recharge')
// 👉 tab
// tab
const handleTabChange = async (tab) => { const handleTabChange = async (tab) => {
activeTab.value = tab activeTab.value = tab
await getGraphData() await getGraphData()

Loading…
Cancel
Save