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.

818 lines
23 KiB

  1. <!--各地区的金币充值和消费情况柱状图-->
  2. <template>
  3. <div class="graph">
  4. <el-card style="width:100%;" class="graph-card">
  5. <div>
  6. <el-tabs v-model="activeTab" @tab-change="handleTabChange">
  7. <el-tab-pane label="金币充值" name="recharge"></el-tab-pane>
  8. <el-tab-pane label="金币消费" name="consume"></el-tab-pane>
  9. </el-tabs>
  10. </div>
  11. <div class="condition">
  12. <div class="stats">
  13. <div v-if="activeTab === 'consume'">合计{{ sumConsume / 100 }}</div>&nbsp;&nbsp;
  14. 永久金币: {{ activeTab === 'recharge' ? sumRechargePermanent / 100 : sumConsumePermanent / 100 }}&nbsp;&nbsp;
  15. 免费金币: {{ activeTab === 'recharge' ? sumRechargeFree / 100 : sumConsumeFree / 100 }}&nbsp;&nbsp;
  16. 任务金币: {{ activeTab === 'recharge' ? sumRechargeTask / 100 : sumConsumeTask / 100 }}&nbsp;&nbsp;
  17. </div>
  18. <div>
  19. <el-button @click="getYes()" size="small" :type="activeTimeRange === 'yes' ? 'primary' : ''">昨天
  20. </el-button>
  21. <el-button @click="getToday()" size="small" :type="activeTimeRange === 'today' ? 'primary' : ''">今天
  22. </el-button>
  23. <el-button @click="getWeek()" size="small" :type="activeTimeRange === 'week' ? 'primary' : ''">本周
  24. </el-button>
  25. <el-button @click="getMonth()" size="small" :type="activeTimeRange === 'month' ? 'primary' : ''">本月
  26. </el-button>
  27. <el-button @click="getYear()" size="small" :type="activeTimeRange === 'year' ? 'primary' : ''">本年
  28. </el-button>
  29. </div>
  30. <div>
  31. <el-date-picker size="small" v-model="dateRange" type="datetimerange" range-separator=""
  32. start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss"
  33. style="width:20vw;margin-left:0.5vw;" value-format="YYYY-MM-DD HH:mm:ss"
  34. :default-time="defaultTime"
  35. :disabled-date="disabledDate" @change="handleDatePickerChange"/>
  36. <el-button type="primary" size="small" style="margin-left: 0.5vw" @click="getChartData">查询</el-button>
  37. </div>
  38. </div>
  39. <div class="graph-content">
  40. <div ref="chartRef" class="left"></div>
  41. <div class="right">
  42. <el-card class="graph-card-list">
  43. <div class="card-large">金币{{ activeTab === 'recharge' ? '充值' : '消费' }}排名</div>
  44. <el-select class="card-select" v-model="selectedType" style="width: 100%; margin-bottom: 15px">
  45. <el-option label="全部类型" value="all"></el-option>
  46. <el-option label="永久金币" value="permanent"></el-option>
  47. <el-option label="免费金币" value="free"></el-option>
  48. <el-option label="任务金币" value="task"></el-option>
  49. </el-select>
  50. <el-table class="card-table" :data="tableData" height="320px">
  51. <el-table-column prop="rank" label="排名" width="60" align="center"></el-table-column>
  52. <el-table-column prop="market" label="地区" align="center">
  53. <template #default="scope">
  54. <span>{{ marketMapping[scope.row.market] || scope.row.market }}</span>
  55. </template>
  56. </el-table-column>
  57. <el-table-column prop="coinAmount" label="金币数量" align="center">
  58. <template #default="{ row }">
  59. {{ row.coinAmount.toLocaleString() }}
  60. </template>
  61. </el-table-column>
  62. </el-table>
  63. </el-card>
  64. </div>
  65. </div>
  66. </el-card>
  67. </div>
  68. </template>
  69. <script setup>
  70. import * as echarts from 'echarts'
  71. import {onMounted, onUnmounted, ref, watch} from 'vue'
  72. import API from '@/util/http'
  73. import {ElMessage} from 'element-plus'
  74. import dayjs from 'dayjs';
  75. import utc from 'dayjs-plugin-utc'
  76. import {marketMapping} from "@/utils/marketMap.js";
  77. dayjs.extend(utc)
  78. const defaultTime = [
  79. new Date(2000, 1, 1, 0, 0, 0),
  80. new Date(2000, 2, 1, 23, 59, 59),
  81. ]
  82. // 地区数据
  83. const markets = ref([])
  84. // 图表相关
  85. const dateRange = ref([])
  86. const activeTab = ref('recharge')
  87. const selectedType = ref('all')
  88. const tableData = ref([])
  89. const chartRef = ref(null)
  90. let chartInstance = null
  91. // 图表合计数
  92. const sumRechargePermanent = ref(0)
  93. const sumRechargeFree = ref(0)
  94. const sumRechargeTask = ref(0)
  95. const sumConsumePermanent = ref(0)
  96. const sumConsumeFree = ref(0)
  97. const sumConsumeTask = ref(0)
  98. const sumConsume = ref(0)
  99. // 用户信息
  100. const adminData = ref({})
  101. // 卡片数据相关
  102. const currentGold = ref(0)
  103. const dailyChange = ref(0)
  104. const currentPermanent = ref(0)
  105. const currentFree = ref(0)
  106. const currentFreeJune = ref(0)
  107. const currentFreeDecember = ref(0)
  108. const currentTask = ref(0)
  109. const yearlyRecharge = ref(0)
  110. const yearlyMoney = ref(0)
  111. const recharge = ref(0)
  112. const money = ref(0)
  113. const yearlyReduce = ref(0)
  114. const yearlyConsume = ref(0)
  115. const yearlyRefund = ref(0)
  116. const dailyReduce = ref(0)
  117. const dailyConsume = ref(0)
  118. const dailyRefund = ref(0)
  119. const yearlyRechargeNum = ref(0)
  120. const sumWow = ref(0)
  121. const sumDaily = ref(0)
  122. const rechargeNum = ref(0)
  123. const ydayRechargeNum = ref(0)
  124. const firstRecharge = ref(0)
  125. const length = ref(0)
  126. // 加载状态
  127. const chartLoading = ref(true)
  128. const handleResize = () => {
  129. if (chartInstance.value) {
  130. try {
  131. chartInstance.value.resize()
  132. console.log('resize一下')
  133. } catch (error) {
  134. console.error('图表resize失败:', error)
  135. }
  136. }
  137. }
  138. // 初始化图表
  139. const initChart = () => {
  140. if (!chartInstance && chartRef.value) {
  141. chartInstance = echarts.init(chartRef.value)
  142. window.addEventListener('resize', handleResize)
  143. }
  144. }
  145. // 销毁图表
  146. const destroyChart = () => {
  147. if (chartInstance.value) {
  148. try {
  149. chartInstance.value.dispose()
  150. } catch (error) {
  151. console.error('图表销毁失败:', error)
  152. }
  153. chartInstance.value = null
  154. }
  155. window.removeEventListener('resize', handleResize)
  156. }
  157. const formatDate = function (date) {
  158. const year = date.getFullYear();
  159. const month = String(date.getMonth() + 1).padStart(2, '0');
  160. const day = String(date.getDate()).padStart(2, '0');
  161. const hours = String(date.getHours()).padStart(2, '0');
  162. const minutes = String(date.getMinutes()).padStart(2, '0');
  163. const seconds = String(date.getSeconds()).padStart(2, '0');
  164. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  165. }
  166. // 昨天
  167. const getYes = function () {
  168. const yesterday = dayjs().subtract(1, 'day')
  169. const startTime = yesterday.startOf('day').format('YYYY-MM-DD HH:mm:ss')
  170. const endTime = yesterday.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  171. dateRange.value = [startTime, endTime]
  172. console.log('看看dateRange', dateRange.value)
  173. activeTimeRange.value = 'yes' // 标记当前激活状态
  174. getChartData()
  175. }
  176. // 今天
  177. const getToday = function () {
  178. const today = dayjs()
  179. const startTime = today.startOf('day').format('YYYY-MM-DD HH:mm:ss')
  180. const endTime = today.endOf('day').format('YYYY-MM-DD HH:mm:ss')
  181. // const endTime = today.add(1, 'day').startOf('day').format('YYYY-MM-DD HH:mm:ss')
  182. dateRange.value = [startTime, endTime]
  183. console.log('看看dateRange', dateRange.value)
  184. activeTimeRange.value = 'today' // 标记当前激活状态
  185. getChartData()
  186. }
  187. // 本周
  188. const getWeek = function () {
  189. const today = dayjs();
  190. // 获取今天是星期几(0是周日,1是周一,...,6是周六)
  191. const day = today.day();
  192. // 计算本周一(如果今天是周一,就取今天;如果是周日,就减6天)
  193. let monday = today.subtract(day === 0 ? 6 : day - 1, 'day');
  194. // 计算本周日(如果今天是周日,就取今天;否则就加(7 - day)天)
  195. let sunday = today.add(day === 0 ? 0 : 7 - day, 'day');
  196. // 设置时间为起始和结束
  197. const startTime = monday.startOf('day').format('YYYY-MM-DD HH:mm:ss');
  198. const endTime = sunday.endOf('day').format('YYYY-MM-DD HH:mm:ss');
  199. dateRange.value = [startTime, endTime];
  200. console.log('本周时间范围(周一到周日):', dateRange.value);
  201. activeTimeRange.value = 'week';
  202. getChartData();
  203. };
  204. // 本月
  205. const getMonth = function () {
  206. const today = dayjs()
  207. const startTime = today.startOf('month').format('YYYY-MM-DD HH:mm:ss')
  208. // const endTime = today.add(1, 'month').startOf('month').format('YYYY-MM-DD HH:mm:ss')
  209. const endTime = today.endOf('month').format('YYYY-MM-DD HH:mm:ss')
  210. dateRange.value = [startTime, endTime]
  211. console.log('看看dateRange', dateRange.value)
  212. activeTimeRange.value = 'month' // 标记当前激活状态
  213. getChartData()
  214. }
  215. // 本年
  216. const getYear = function () {
  217. const today = dayjs()
  218. const startTime = today.startOf('year').format('YYYY-MM-DD HH:mm:ss')
  219. const endTime = today.endOf('year').format('YYYY-MM-DD HH:mm:ss')
  220. // const endTime = today.add(1, 'year').startOf('year').format('YYYY-MM-DD HH:mm:ss')
  221. dateRange.value = [startTime, endTime]
  222. console.log('看看dateRange', dateRange.value)
  223. activeTimeRange.value = 'year' // 标记当前激活状态
  224. getChartData()
  225. }
  226. // 要加上所有市场的,还有额外计算的(总数 = 永久 + 6月 + 12月 + 免费 + 任务)
  227. const processData = (data) => {
  228. const summary = {
  229. currentGold: 0,
  230. dailyChange: 0,
  231. currentPermanent: 0,
  232. currentFreeJune: 0,
  233. currentFreeDecember: 0,
  234. currentTask: 0,
  235. currentFree: 0,
  236. recharge: 0,
  237. money: 0,
  238. yearlyRecharge: 0,
  239. yearlyMoney: 0,
  240. consumePermanent: 0,
  241. consumeFreeJune: 0,
  242. consumeFreeDecember: 0,
  243. consumeTask: 0,
  244. refundPermanent: 0,
  245. refundFreeJune: 0,
  246. refundFreeDecember: 0,
  247. refundTask: 0,
  248. dailyReduce: 0,
  249. yearlyConsume: 0,
  250. yearlyRefund: 0,
  251. yearlyReduce: 0,
  252. rechargeNum: 0,
  253. ydayRechargeNum: 0,
  254. firstRecharge: 0,
  255. sumWow: 0,
  256. sumDaily: 0,
  257. yearlyRechargeNum: 0
  258. }
  259. // 遍历市场
  260. data.marketCards.forEach(market => {
  261. for (const i in summary) {
  262. if (market[i] !== undefined && market[i] !== null) { // 其实还应该卡一个number
  263. summary[i] += market[i]
  264. }
  265. }
  266. })
  267. // wow和daily除一下
  268. length.value = data.markets.length
  269. console.log(length.value)
  270. // 计算昨日新增消费和退款
  271. const yesterdayConsume = summary.consumePermanent + summary.consumeFreeJune + summary.consumeFreeDecember + summary.consumeTask
  272. const yesterdayRefund = summary.refundPermanent + summary.refundFreeJune + summary.refundFreeDecember + summary.refundTask
  273. // 更新卡片数据
  274. currentGold.value = summary.currentGold.toFixed(2)
  275. dailyChange.value = summary.dailyChange.toFixed(2)
  276. currentPermanent.value = summary.currentPermanent.toFixed(2)
  277. currentFree.value = summary.currentFree.toFixed(2)
  278. currentFreeJune.value = summary.currentFreeJune.toFixed(2)
  279. currentFreeDecember.value = summary.currentFreeDecember.toFixed(2)
  280. currentTask.value = summary.currentTask.toFixed(2)
  281. yearlyRecharge.value = summary.yearlyRecharge.toFixed(2)
  282. yearlyMoney.value = summary.yearlyMoney.toFixed(2)
  283. recharge.value = summary.recharge.toFixed(2)
  284. money.value = summary.money.toFixed(2)
  285. yearlyReduce.value = summary.yearlyReduce.toFixed(2)
  286. yearlyConsume.value = summary.yearlyConsume.toFixed(2)
  287. yearlyRefund.value = summary.yearlyRefund.toFixed(2)
  288. dailyReduce.value = summary.dailyReduce.toFixed(2)
  289. dailyConsume.value = yesterdayConsume.toFixed(2)
  290. dailyRefund.value = yesterdayRefund.toFixed(2)
  291. yearlyRechargeNum.value = summary.yearlyRechargeNum
  292. // // 周同比
  293. // sumWow.value = (marketCards.sumWow / length.value).toFixed(2)
  294. // // 日环比
  295. // sumDaily.value = (marketCards.sumDaily / length.value).toFixed(2)
  296. // rechargeNum.value = summary.rechargeNum
  297. ydayRechargeNum.value = summary.ydayRechargeNum
  298. firstRecharge.value = summary.firstRecharge
  299. }
  300. //无法选择的时间
  301. const disabledDate = (time) => {
  302. const limitDate = new Date(2025, 0, 1);
  303. return time.getTime() < limitDate.getTime();
  304. }
  305. // 获取市场列表
  306. const getMarkets = async () => {
  307. console.log("adminData", adminData.value.account)
  308. try {
  309. const response = await API({
  310. url: '/general/adminMarkets',
  311. data: {
  312. account: adminData.value.account
  313. }
  314. })
  315. if (Array.isArray(response.data)) {
  316. // markets.value = response.data.filter(data => data !== "1")
  317. markets.value = response.data
  318. console.log('市场列表获取成功:', markets.value)
  319. } else {
  320. console.error('获取市场列表失败', response)
  321. ElMessage.error('获取市场列表失败')
  322. }
  323. } catch (error) {
  324. console.error('获取市场列表失败:', error)
  325. ElMessage.error('获取市场列表失败')
  326. }
  327. }
  328. // 获取图表数据
  329. const getChartData = async () => {
  330. try {
  331. // 校验市场数据到底有没有
  332. if (!markets.value || markets.value.length === 0) {
  333. await getMarkets()
  334. }
  335. // 本年
  336. if (!dateRange.value || dateRange.value.length === 0) {
  337. getYear()
  338. }
  339. const params = {
  340. markets: markets.value,
  341. startDate: dateRange.value[0],
  342. endDate: dateRange.value[1]
  343. };
  344. const response = await API({
  345. url: '/workbench/getGraph',
  346. data: params
  347. })
  348. console.log('看看params', params)
  349. if (Array.isArray(response.marketGraphs)) {
  350. // const filteredGraphs = response.marketGraphs.filter(data => data.market !== "1");
  351. // 处理图表数据
  352. processChartData(response.marketGraphs)
  353. // 处理排名数据
  354. processRankingData(response.marketGraphs)
  355. } else {
  356. console.error('获取图表数据失败:', response)
  357. ElMessage.error('获取图表数据失败')
  358. }
  359. } catch (error) {
  360. console.error('获取图表数据失败:', error)
  361. ElMessage.error('获取图表数据失败')
  362. }
  363. }
  364. // 处理图表数据
  365. const processChartData = (marketCards) => {
  366. const chartData = {
  367. rechargePermanent: [],
  368. rechargeFree: [],
  369. rechargeTask: [],
  370. consumePermanent: [],
  371. consumeFree: [],
  372. consumeTask: [],
  373. sumConsume: []
  374. }
  375. // 这是图表的合计数,怎样遍历?????
  376. const sumRechargePermanent1 = ref(0)
  377. const sumRechargeFree1 = ref(0)
  378. const sumRechargeTask1 = ref(0)
  379. const sumConsumePermanent1 = ref(0)
  380. const sumConsumeFree1 = ref(0)
  381. const sumConsumeTask1 = ref(0)
  382. const sumConsume1 = ref(0)
  383. marketCards.forEach(market => {
  384. chartData.rechargePermanent.push(market.sumRechargePermanent / 100 || 0)
  385. chartData.rechargeFree.push(market.sumRechargeFree / 100 || 0)
  386. chartData.rechargeTask.push(market.sumRechargeTask / 100 || 0)
  387. chartData.consumePermanent.push(market.sumConsumePermanent / 100 || 0)
  388. chartData.consumeFree.push(market.sumConsumeFree / 100 || 0)
  389. chartData.consumeTask.push(market.sumConsumeTask / 100 || 0)
  390. chartData.sumConsume.push(market.sumConsume / 100 || 0)
  391. // 合计数合计数合计数咋算
  392. sumRechargePermanent1.value += (market.sumRechargePermanent || 0)
  393. sumRechargeFree1.value += (market.sumRechargeFree || 0)
  394. //sumRechargeTask1.value += (market.sumRechargeTask || 0)
  395. sumConsumePermanent1.value += (market.sumConsumePermanent || 0)
  396. sumConsumeFree1.value += (market.sumConsumeFree || 0)
  397. sumConsumeTask1.value += (market.sumConsumeTask || 0)
  398. sumConsume1.value += (market.sumConsume || 0)
  399. })
  400. sumRechargePermanent.value = sumRechargePermanent1.value
  401. sumRechargeFree.value = sumRechargeFree1.value
  402. sumRechargeTask.value = 0
  403. sumConsumePermanent.value = sumConsumePermanent1.value
  404. sumConsumeFree.value = sumConsumeFree1.value
  405. sumConsumeTask.value = sumConsumeTask1.value
  406. sumConsume.value = sumConsume1.value
  407. updateChart(chartData)
  408. }
  409. const processRankingData = (marketCards) => {
  410. // 每个市场的总金币数
  411. const rankingData = marketCards.map(market => {
  412. let coinAmount = 0;
  413. if (activeTab.value === 'recharge') {
  414. // 充值排名
  415. switch (selectedType.value) {
  416. case 'all':
  417. coinAmount = (market.sumRechargePermanent / 100 || 0) + (market.sumRechargeFree / 100 || 0) + (market.sumRechargeTask / 100 || 0);
  418. break;
  419. case 'permanent':
  420. coinAmount = market.sumRechargePermanent / 100 || 0;
  421. break;
  422. case 'free':
  423. coinAmount = market.sumRechargeFree / 100 || 0;
  424. break;
  425. case 'task':
  426. coinAmount = market.sumRechargeTask / 100 || 0;
  427. break;
  428. }
  429. } else {
  430. // 消费排名
  431. switch (selectedType.value) {
  432. case 'all':
  433. coinAmount = (market.sumConsumePermanent / 100 || 0) + (market.sumConsumeFree / 100 || 0) + (market.sumConsumeTask / 100 || 0);
  434. break;
  435. case 'permanent':
  436. coinAmount = market.sumConsumePermanent / 100 || 0;
  437. break;
  438. case 'free':
  439. coinAmount = market.sumConsumeFree / 100 || 0;
  440. break;
  441. case 'task':
  442. coinAmount = market.sumConsumeTask / 100 || 0;
  443. break;
  444. }
  445. }
  446. return {
  447. market: market.market,
  448. coinAmount: coinAmount
  449. };
  450. });
  451. // 按金币数量排序
  452. rankingData.sort((a, b) => b.coinAmount - a.coinAmount);
  453. // 排名序号
  454. tableData.value = rankingData.map((item, index) => ({
  455. rank: index + 1,
  456. ...item
  457. }));
  458. }
  459. watch(selectedType, () => {
  460. getChartData();
  461. });
  462. // 更新图表
  463. const updateChart = (chartData) => {
  464. if (!chartInstance) {
  465. initChart()
  466. }
  467. chartLoading.value = true
  468. try {
  469. let series = []
  470. let legend = []
  471. if (activeTab.value === 'recharge') {
  472. series = [
  473. {
  474. name: '永久金币',
  475. type: 'bar',
  476. stack: 'recharge',
  477. data: chartData.rechargePermanent,
  478. itemStyle: {color: '#5470c6'},
  479. barWidth: 30
  480. },
  481. {
  482. name: '免费金币',
  483. type: 'bar',
  484. stack: 'recharge',
  485. data: chartData.rechargeFree,
  486. itemStyle: {color: '#91cc75'},
  487. barWidth: 30
  488. },
  489. {
  490. name: '任务金币',
  491. type: 'bar',
  492. stack: 'recharge',
  493. data: chartData.rechargeTask,
  494. itemStyle: {color: '#fac858'},
  495. barWidth: 30
  496. }
  497. ]
  498. legend = ['永久金币', '免费金币', '任务金币']
  499. } else {
  500. series = [
  501. {
  502. name: '永久金币',
  503. type: 'bar',
  504. stack: 'consume',
  505. data: chartData.consumePermanent,
  506. itemStyle: {color: '#5470c6'},
  507. barWidth: 30
  508. },
  509. {
  510. name: '免费金币',
  511. type: 'bar',
  512. stack: 'consume',
  513. data: chartData.consumeFree,
  514. itemStyle: {color: '#91cc75'},
  515. barWidth: 30
  516. },
  517. {
  518. name: '任务金币',
  519. type: 'bar',
  520. stack: 'consume',
  521. data: chartData.consumeTask,
  522. itemStyle: {color: '#fac858'},
  523. barWidth: 30
  524. }
  525. ]
  526. legend = ['永久金币', '免费金币', '任务金币']
  527. }
  528. const option = {
  529. tooltip: {
  530. trigger: 'axis',
  531. axisPointer: {
  532. type: 'shadow'
  533. },
  534. formatter: function (params) {
  535. let result = params[0].name + '<br/>'
  536. let total = 0;
  537. params.forEach(param => {
  538. result += `${param.seriesName}: ${param.value.toLocaleString()}<br/>`;
  539. total += param.value;
  540. })
  541. result += `${activeTab.value === 'recharge' ? '充值' : '消费'}: ${total.toLocaleString()}`;
  542. return result
  543. }
  544. },
  545. legend: {
  546. data: legend,
  547. bottom: 10
  548. },
  549. grid: {
  550. left: '3%',
  551. right: '4%',
  552. bottom: '10%',
  553. containLabel: true
  554. },
  555. xAxis: {
  556. type: 'category',
  557. // 横坐标数据 之后要改成一个时间的
  558. data: markets.value,
  559. axisLabel: {
  560. interval: 0,
  561. rotate: 0
  562. }
  563. },
  564. yAxis: {
  565. type: 'value',
  566. splitLine: {
  567. lineStyle: {
  568. type: 'dashed',
  569. width: 1,
  570. color: '#000000'
  571. }
  572. },
  573. axisLabel: {
  574. formatter: function (value) {
  575. return value.toLocaleString()
  576. }
  577. },
  578. },
  579. series: series,
  580. // dataZoom: [
  581. // {
  582. // type: 'slider',
  583. // show: true,
  584. // start: 0,
  585. // end: 100,
  586. // maxSpan: 100,
  587. // minSpan: 100,
  588. //
  589. // height: 2,
  590. // },
  591. // ]
  592. }
  593. chartInstance.setOption(option)
  594. } catch (error) {
  595. console.error('图表更新失败:', error)
  596. ElMessage.error('图表渲染失败')
  597. } finally {
  598. setTimeout(() => {
  599. chartLoading.value = false
  600. }, 300)
  601. }
  602. }
  603. // 处理标签切换
  604. const handleTabChange = () => {
  605. getChartData()
  606. console.log('标签切换调用图表')
  607. }
  608. const getAdminData = async function () {
  609. try {
  610. const result = await API({url: '/admin/userinfo', data: {}})
  611. adminData.value = result
  612. console.log('用户信息', adminData.value)
  613. } catch (error) {
  614. console.log('请求失败', error)
  615. }
  616. }
  617. // 标记当前激活的时间范围按钮
  618. const activeTimeRange = ref('')
  619. // 日期选择器变化时清除按钮激活状态
  620. const handleDatePickerChange = () => {
  621. activeTimeRange.value = ''
  622. }
  623. onMounted(async () => {
  624. await getAdminData()
  625. await getMarkets()
  626. getYear()
  627. window.addEventListener('resize', () => {
  628. chartInstance.resize()
  629. })
  630. })
  631. onUnmounted(() => {
  632. destroyChart()
  633. })
  634. </script>
  635. <style scoped lang="scss">
  636. .graph {
  637. .condition {
  638. width: 100%;
  639. height: 1%;
  640. display: flex;
  641. align-items: center;
  642. .stats {
  643. display: flex;
  644. align-items: center;
  645. width: 35vw;
  646. font-size: 15px;
  647. }
  648. }
  649. .graph-content {
  650. flex: 1;
  651. height: auto;
  652. display: flex;
  653. .left {
  654. width: 70%;
  655. height: auto;
  656. }
  657. .right {
  658. flex: 1;
  659. padding: 0.5vw 2vh;
  660. }
  661. }
  662. }
  663. .center-card {
  664. display: flex;
  665. justify-content: center;
  666. align-items: center;
  667. }
  668. .margin-bottom {
  669. margin-bottom: 0.5vh;
  670. }
  671. .card-item {
  672. width: 25%;
  673. height: 28vh;
  674. display: flex;
  675. flex-direction: column;
  676. justify-content: center;
  677. margin-right: 0.25vw;
  678. }
  679. .card-title {
  680. font-weight: bold;
  681. margin-bottom: 1vh;
  682. display: flex;
  683. justify-content: center;
  684. align-items: center;
  685. }
  686. .card-large {
  687. font-weight: bold;
  688. font-size: 16px;
  689. text-align: center;
  690. margin-bottom: 15px;
  691. }
  692. @keyframes spin {
  693. 0% {
  694. transform: rotate(0deg);
  695. }
  696. 100% {
  697. transform: rotate(360deg);
  698. }
  699. }
  700. .graph-card {
  701. background: #F3FAFF;
  702. box-shadow: 0 0 8px 0 #00000040;
  703. }
  704. .graph-card-list {
  705. background: #F3FAFF;
  706. box-shadow: 0 0 8px 0 #00000040;
  707. padding: 12px;
  708. .card-select {
  709. :deep(.el-input__wrapper) {
  710. background-color: #E7F4FD !important;
  711. box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25) !important;
  712. border: none !important;
  713. }
  714. :deep(.el-input__inner) {
  715. background-color: transparent !important;
  716. }
  717. :deep(.el-input__suffix) {
  718. background-color: transparent !important;
  719. }
  720. }
  721. /* 表格整体背景:把表格容器设为卡片背景 */
  722. :deep(.el-table) {
  723. background-color: #F3FAFF !important;
  724. box-shadow: none !important;
  725. }
  726. /* 表头/表体 wrapper 与 table body 单元格 */
  727. :deep(.el-table__header-wrapper),
  728. :deep(.el-table__body-wrapper),
  729. :deep(.el-table__body),
  730. :deep(.el-table__header),
  731. :deep(.el-table__body tbody),
  732. :deep(.el-table__body tr),
  733. :deep(.el-table__row),
  734. :deep(.el-table__cell),
  735. :deep(.el-table__body td) {
  736. background-color: transparent !important;
  737. }
  738. /* 表头 */
  739. :deep(.el-table__header th) {
  740. background-color: #F3FAFF !important;
  741. }
  742. /* 行之间的分隔线(更像卡片内表格) */
  743. :deep(.el-table .el-table__row):not(:last-child) {
  744. border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  745. }
  746. }
  747. </style>