Browse Source

style: 优化按钮

add:对接底部柱状图完成
zhangyong/milestone-20250913-现金管理
lihui 2 months ago
parent
commit
2864fde2d2
  1. 4
      src/assets/css/btn.css
  2. 325
      src/components/workspace/GoldGraphMarkets.vue
  3. 30
      src/views/workspace/index.vue

4
src/assets/css/btn.css

@ -20,8 +20,8 @@ v-if="hasRecharge"
color: #666; /* 未激活文字色 */ color: #666; /* 未激活文字色 */
/* 确保激活状态下 hover 也不变化 */ /* 确保激活状态下 hover 也不变化 */
&:hover { &:hover {
background-color: #E5EBFE !important; /* 保持默认背景色 */
color: #666 !important; /* 保持默认文字色 */
background-color: #668BFF !important; /* 保持默认背景色 */
color: #fff !important; /* 保持默认文字色 */
border-color: transparent; /* 若有边框,保持默认 */ border-color: transparent; /* 若有边框,保持默认 */
} }
} }

325
src/components/workspace/GoldGraphMarkets.vue

@ -16,7 +16,7 @@
免费金币: {{ activeTab === 'recharge' ? sumRechargeFree / 100 : sumConsumeFree / 100 }}   免费金币: {{ activeTab === 'recharge' ? sumRechargeFree / 100 : sumConsumeFree / 100 }}  
任务金币: {{ activeTab === 'recharge' ? sumRechargeTask / 100 : sumConsumeTask / 100 }}   任务金币: {{ activeTab === 'recharge' ? sumRechargeTask / 100 : sumConsumeTask / 100 }}  
</div> </div>
<div>
<div style="display: flex;">
<el-button @click="getYes()" size="small" :type="activeTimeRange === 'yes' ? 'primary' : ''">昨天 <el-button @click="getYes()" size="small" :type="activeTimeRange === 'yes' ? 'primary' : ''">昨天
</el-button> </el-button>
<el-button @click="getToday()" size="small" :type="activeTimeRange === 'today' ? 'primary' : ''">今天 <el-button @click="getToday()" size="small" :type="activeTimeRange === 'today' ? 'primary' : ''">今天
@ -28,42 +28,42 @@
<el-button @click="getYear()" size="small" :type="activeTimeRange === 'year' ? 'primary' : ''">本年 <el-button @click="getYear()" size="small" :type="activeTimeRange === 'year' ? 'primary' : ''">本年
</el-button> </el-button>
</div> </div>
<div>
<div style="display: flex;">
<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" style="width:20vw;margin-left:0.5vw;" value-format="YYYY-MM-DD HH:mm:ss"
:default-time="defaultTime" :default-time="defaultTime"
:disabled-date="disabledDate" @change="handleDatePickerChange"/> :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>
<el-popover
placement="top-start"
title="数据说明"
:width="240"
trigger="hover"
content="若统计周期跨越 40 天以上,将展示月份维度的数据。"
>
<template #reference>
<el-icon
class="service-icon"
style="
margin-left: 5px;
cursor: pointer;
font-size: 22px;
transition: all 0.3s ease;
"
>
<Service />
</el-icon>
</template>
</el-popover>
</div> </div>
<div class="graph-content"> <div class="graph-content">
<div ref="chartRef" class="left"></div>
<div class="right">
<el-card class="graph-card-list">
<div class="card-large">金币{{ activeTab === 'recharge' ? '充值' : '消费' }}排名</div>
<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="permanent"></el-option>
<el-option label="免费金币" value="free"></el-option>
<el-option label="任务金币" value="task"></el-option>
</el-select>
<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="market" label="地区" align="center">
<template #default="scope">
<span>{{ marketMapping[scope.row.market] || scope.row.market }}</span>
</template>
</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>
</div>
<div ref="chartRef" style="width:100%;height:500px;"></div>
</div> </div>
</el-card> </el-card>
</div> </div>
@ -77,6 +77,7 @@ import {ElMessage} from 'element-plus'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import utc from 'dayjs-plugin-utc' import utc from 'dayjs-plugin-utc'
import {marketMapping} from "@/utils/marketMap.js"; import {marketMapping} from "@/utils/marketMap.js";
import {Service} from "@element-plus/icons-vue";
dayjs.extend(utc) dayjs.extend(utc)
@ -329,180 +330,95 @@ const disabledDate = (time) => {
return time.getTime() < limitDate.getTime(); return time.getTime() < limitDate.getTime();
} }
// x
const dates = ref()
// //
const getMarkets = async () => {
console.log("adminData", adminData.value.account)
try {
const response = await API({
url: '/general/adminMarkets',
data: {
account: adminData.value.account
}
})
if (Array.isArray(response.data)) {
// markets.value = response.data.filter(data => data !== "1")
markets.value = response.data
console.log('市场列表获取成功:', markets.value)
} else {
console.error('获取市场列表失败', response)
ElMessage.error('获取市场列表失败')
}
} catch (error) {
console.error('获取市场列表失败:', error)
ElMessage.error('获取市场列表失败')
}
}
// //
const getChartData = async () => { const getChartData = async () => {
try {
//
if (!markets.value || markets.value.length === 0) {
await getMarkets()
}
//
if (!dateRange.value || dateRange.value.length === 0) {
getYear()
}
const params = {
markets: markets.value,
startDate: dateRange.value[0],
endDate: dateRange.value[1]
};
const params = {
startDate: dateRange.value[0],
endDate: dateRange.value[1],
}
try {
const response = await API({ const response = await API({
url: '/workbench/getGraph',
url: '/workbench/getSingleGraph',
data: params data: params
}) })
console.log('看看params', params)
if (Array.isArray(response.marketGraphs)) {
// const filteredGraphs = response.marketGraphs.filter(data => data.market !== "1");
//
processChartData(response.marketGraphs)
//
processRankingData(response.marketGraphs)
} else {
console.error('获取图表数据失败:', response)
if (!response.marketGraphs || !Array.isArray(response.marketGraphs)) {
ElMessage.error('获取图表数据失败') ElMessage.error('获取图表数据失败')
return
}
//
const marketGraphs = response.marketGraphs
console.log('图表数据:', marketGraphs)
//
marketGraphs.sort((a, b) => new Date(a.currentDate) - new Date(b.currentDate));
// X
const validDates = marketGraphs.map(item => item.currentDate).filter(date => date != null);
if (validDates.length === 0) {
console.log('没有日数据,使用月数据');
dates.value = marketGraphs.map(item => item.currentMonth);
} else {
dates.value = validDates;
} }
//
const rechargePermanent = marketGraphs.map(item => item.sumRechargePermanent || 0).map(item => item / 100);
const rechargeFree = marketGraphs.map(item => item.sumRechargeFree || 0).map(item => item / 100);
const rechargeTask = marketGraphs.map(item => item.sumRechargeTask || 0).map(item => item / 100);
//
const consumePermanent = marketGraphs.map(item => item.sumConsumePermanent || 0).map(item => item / 100);
const consumeFree = marketGraphs.map(item => item.sumConsumeFree || 0).map(item => item / 100);
const consumeTask = marketGraphs.map(item => item.sumConsumeTask || 0).map(item => item / 100);
// /100
sumRechargePermanent.value = rechargePermanent.reduce((a, b) => a + b, 0)
sumRechargeFree.value = rechargeFree.reduce((a, b) => a + b, 0)
sumRechargeTask.value = rechargeTask.reduce((a, b) => a + b, 0)
sumConsumePermanent.value = consumePermanent.reduce((a, b) => a + b, 0)
sumConsumeFree.value = consumeFree.reduce((a, b) => a + b, 0)
sumConsumeTask.value = consumeTask.reduce((a, b) => a + b, 0)
sumConsume.value =
sumConsumePermanent.value + sumConsumeFree.value + sumConsumeTask.value
//
updateChart({
dates,
rechargePermanent,
rechargeFree,
rechargeTask,
consumePermanent,
consumeFree,
consumeTask
})
} catch (error) { } catch (error) {
console.error('获取图表数据失败:', error) console.error('获取图表数据失败:', error)
ElMessage.error('获取图表数据失败') ElMessage.error('获取图表数据失败')
} }
} }
//
const processChartData = (marketCards) => {
const chartData = {
rechargePermanent: [],
rechargeFree: [],
rechargeTask: [],
consumePermanent: [],
consumeFree: [],
consumeTask: [],
sumConsume: []
}
//
const sumRechargePermanent1 = ref(0)
const sumRechargeFree1 = ref(0)
const sumRechargeTask1 = ref(0)
const sumConsumePermanent1 = ref(0)
const sumConsumeFree1 = ref(0)
const sumConsumeTask1 = ref(0)
const sumConsume1 = ref(0)
marketCards.forEach(market => {
chartData.rechargePermanent.push(market.sumRechargePermanent / 100 || 0)
chartData.rechargeFree.push(market.sumRechargeFree / 100 || 0)
chartData.rechargeTask.push(market.sumRechargeTask / 100 || 0)
chartData.consumePermanent.push(market.sumConsumePermanent / 100 || 0)
chartData.consumeFree.push(market.sumConsumeFree / 100 || 0)
chartData.consumeTask.push(market.sumConsumeTask / 100 || 0)
chartData.sumConsume.push(market.sumConsume / 100 || 0)
//
sumRechargePermanent1.value += (market.sumRechargePermanent || 0)
sumRechargeFree1.value += (market.sumRechargeFree || 0)
//sumRechargeTask1.value += (market.sumRechargeTask || 0)
sumConsumePermanent1.value += (market.sumConsumePermanent || 0)
sumConsumeFree1.value += (market.sumConsumeFree || 0)
sumConsumeTask1.value += (market.sumConsumeTask || 0)
sumConsume1.value += (market.sumConsume || 0)
})
sumRechargePermanent.value = sumRechargePermanent1.value
sumRechargeFree.value = sumRechargeFree1.value
sumRechargeTask.value = 0
sumConsumePermanent.value = sumConsumePermanent1.value
sumConsumeFree.value = sumConsumeFree1.value
sumConsumeTask.value = sumConsumeTask1.value
sumConsume.value = sumConsume1.value
updateChart(chartData)
}
const processRankingData = (marketCards) => {
//
const rankingData = marketCards.map(market => {
let coinAmount = 0;
if (activeTab.value === 'recharge') {
//
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,
coinAmount: coinAmount
};
});
//
rankingData.sort((a, b) => b.coinAmount - a.coinAmount);
//
tableData.value = rankingData.map((item, index) => ({
rank: index + 1,
...item
}));
}
watch(selectedType, () => { watch(selectedType, () => {
getChartData(); getChartData();
}); });
// //
const updateChart = (chartData) => { const updateChart = (chartData) => {
if (!chartInstance) {
initChart()
}
if (!chartInstance) initChart()
chartLoading.value = true chartLoading.value = true
try { try {
let series = [] let series = []
let legend = [] let legend = []
@ -514,24 +430,18 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargePermanent, data: chartData.rechargePermanent,
itemStyle: {color: '#5470c6'},
barWidth: 30
}, },
{ {
name: '免费金币', name: '免费金币',
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargeFree, data: chartData.rechargeFree,
itemStyle: {color: '#91cc75'},
barWidth: 30
}, },
{ {
name: '任务金币', name: '任务金币',
type: 'bar', type: 'bar',
stack: 'recharge', stack: 'recharge',
data: chartData.rechargeTask, data: chartData.rechargeTask,
itemStyle: {color: '#fac858'},
barWidth: 30
} }
] ]
legend = ['永久金币', '免费金币', '任务金币'] legend = ['永久金币', '免费金币', '任务金币']
@ -542,24 +452,18 @@ const updateChart = (chartData) => {
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumePermanent, data: chartData.consumePermanent,
itemStyle: {color: '#5470c6'},
barWidth: 30
}, },
{ {
name: '免费金币', name: '免费金币',
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumeFree, data: chartData.consumeFree,
itemStyle: {color: '#91cc75'},
barWidth: 30
}, },
{ {
name: '任务金币', name: '任务金币',
type: 'bar', type: 'bar',
stack: 'consume', stack: 'consume',
data: chartData.consumeTask, data: chartData.consumeTask,
itemStyle: {color: '#fac858'},
barWidth: 30
} }
] ]
legend = ['永久金币', '免费金币', '任务金币'] legend = ['永久金币', '免费金币', '任务金币']
@ -568,19 +472,7 @@ const updateChart = (chartData) => {
const option = { const option = {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
let result = params[0].name + '<br/>'
let total = 0;
params.forEach(param => {
result += `${param.seriesName}: ${param.value.toLocaleString()}<br/>`;
total += param.value;
})
result += `${activeTab.value === 'recharge' ? '充值' : '消费'}: ${total.toLocaleString()}`;
return result
}
axisPointer: {type: 'shadow'},
}, },
legend: { legend: {
data: legend, data: legend,
@ -594,30 +486,24 @@ const updateChart = (chartData) => {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
//
data: markets.value,
data: chartData.dates.value,
axisLabel: { axisLabel: {
interval: 0,
rotate: 0
rotate: 45
} }
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
axisLabel: {
formatter: (v) => v.toLocaleString()
},
splitLine: { splitLine: {
lineStyle: { lineStyle: {
type: 'dashed', type: 'dashed',
width: 1,
color: '#000000'
width: 1
} }
},
axisLabel: {
formatter: function (value) {
return value.toLocaleString()
}
},
}
}, },
series: series,
series,
// dataZoom: [ // dataZoom: [
// { // {
// type: 'slider', // type: 'slider',
@ -637,9 +523,7 @@ const updateChart = (chartData) => {
console.error('图表更新失败:', error) console.error('图表更新失败:', error)
ElMessage.error('图表渲染失败') ElMessage.error('图表渲染失败')
} finally { } finally {
setTimeout(() => {
chartLoading.value = false
}, 300)
setTimeout(() => (chartLoading.value = false), 300)
} }
} }
@ -668,7 +552,6 @@ const handleDatePickerChange = () => {
onMounted(async () => { onMounted(async () => {
await getAdminData() await getAdminData()
await getMarkets()
getYear() getYear()
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
chartInstance.resize() chartInstance.resize()

30
src/views/workspace/index.vue

@ -15,21 +15,41 @@
</el-row> </el-row>
<el-row class="graphs"> <el-row class="graphs">
<el-col :span="24"> <el-col :span="24">
<GoldGraph/>
<div v-if="loading">加载中...</div>
<GoldGraphMarkets v-else-if="GraphFlag" />
<GoldGraph v-else />
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</template> </template>
<script setup> <script setup>
import {ref, onMounted} from 'vue'
import API from '@/util/http'
import GoldManagement from "@/components/workspace/GoldManagement.vue" import GoldManagement from "@/components/workspace/GoldManagement.vue"
import CashManagement from "@/components/workspace/CashManagement.vue" import CashManagement from "@/components/workspace/CashManagement.vue"
import GoldGraph from "@/components/workspace/GoldGraph.vue"
import GoldGraphMarkets from "@/components/workspace/GoldGraphMarkets.vue";
import API from "@/util/http.js";
import {onMounted, ref} from "vue";
import GoldGraph from "@/components/workspace/GoldGraph.vue";
const GraphFlag = ref();
const loading = ref(true); //
const getAdminData = async function () {
try {
loading.value = true; //
const result = await API({url: '/admin/userinfo', data: {}});
GraphFlag.value = result.markets !== '总部' && result.markets !== '研发部';
console.log("GraphFlag",GraphFlag.value);
} catch (error) {
console.log('请求失败', error);
} finally {
loading.value = false; //
}
};
onMounted(async () => {
await getAdminData()
})
</script> </script>
<style scoped> <style scoped>

Loading…
Cancel
Save