| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- <template>
- <el-main class="min-w-[700px]" ref="mainRef">
- <el-row :gutter="20">
- <el-col :span="8">
- <el-card shadow="hover">
- <div class="flex justify-between items-center">
- <el-icon size="60" color="#405CFF">
- <CalendarClock16Filled />
- </el-icon>
- <div class="flex flex-col items-end">
- <span class="text-[#999] text-base">使用时长</span>
- <span class="text-2xl font-bold mt-2">{{ time }} (天)</span>
- </div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="8">
- <el-card shadow="hover">
- <div class="flex justify-between items-center">
- <el-icon size="60" color="#15A8AA">
- <PersonAdd20Filled />
- </el-icon>
- <div class="flex flex-col items-end">
- <span class="text-[#999] text-base">今日新增</span>
- <span class="text-2xl font-bold mt-2">{{ userDatas.today }} (人)</span>
- </div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="8">
- <el-card shadow="hover">
- <div class="flex justify-between items-center">
- <el-icon size="60" color="#928EFB">
- <Chat24Filled />
- </el-icon>
- <div class="flex flex-col items-end">
- <span class="text-[#999] text-base">今日互动</span>
- <span class="text-2xl font-bold mt-2">{{ chatDatas.today }} (次)</span>
- </div>
- </div>
- </el-card>
- </el-col>
- </el-row>
- <el-card shadow="hover" class="mt-5">
- <div class="flex">
- <el-tabs class="demo-tabs" v-model="activeName" tab-position="left">
- <el-tab-pane name="user">
- <template #label>
- <div class="flex items-center py-4">
- <el-icon size="24"><DataArea20Filled /></el-icon>
- <span class="ml-1"> 人数统计 </span>
- </div>
- </template>
- </el-tab-pane>
- <el-tab-pane name="chat">
- <template #label>
- <div class="flex items-center py-4">
- <el-icon size="24"><DataTreemap20Filled /></el-icon>
- <span class="ml-1">互动统计</span>
- </div>
- </template></el-tab-pane
- >
- </el-tabs>
- <div id="chart" class="h-[500px] flex-1"></div>
- </div>
- </el-card>
- </el-main>
- </template>
- <script setup>
- import {
- CalendarClock16Filled,
- PersonAdd20Filled,
- Chat24Filled,
- DataArea20Filled,
- DataTreemap20Filled
- } from '@vicons/fluent'
- import { useUserStore } from '@/stores/user'
- import { differenceInCalendarDays } from 'date-fns'
- import { onMounted, watch, ref, nextTick } from 'vue'
- import { useDark, useToggle, useResizeObserver } from '@vueuse/core'
- import { http } from '@/plugins/http'
- const isDark = useDark({
- storageKey: 'dark-mode-admin'
- })
- import * as echarts from 'echarts'
- const { user } = useUserStore()
- const time = differenceInCalendarDays(new Date(), new Date(user.createdAt))
- watch(isDark, () => {
- initChart()
- })
- const myChart = ref(null)
- const mainRef = ref(null)
- useResizeObserver(mainRef, () => {
- nextTick(() => {
- initChart()
- })
- })
- const activeName = ref('user')
- watch(activeName, () => {
- initChart()
- })
- async function initChart() {
- if (activeName.value === 'user') {
- await http
- .get('/admin/users/getDatas', {
- apiUserId: user.apiUserId
- })
- .then((res) => {
- userDatas.value = res
- })
- } else {
- await http
- .get('/chat/getDatas', {
- apiUserId: user.apiUserId
- })
- .then((res) => {
- chatDatas.value = res
- })
- }
- if (myChart.value) {
- myChart.value.dispose()
- myChart.value = null
- }
- var chartDom = document.getElementById('chart')
- myChart.value = echarts.init(chartDom, isDark.value ? 'dark' : 'light')
- var option
- option = {
- backgroundColor: isDark.value ? 'rgb(29, 30, 31)' : '#fff',
- title: [
- {
- // text: '标题',
- left: '2%'
- },
- {
- text: activeName.value === 'user' ? '全部用户' : '互动次数',
- // subtext: userDatas.value.api + userDatas.value.user + '人',
- subtext:
- activeName.value === 'user'
- ? userDatas.value.api + userDatas.value.user + '人'
- : chatDatas.value.api + chatDatas.value.user + '次',
- textStyle: {
- fontSize: 14,
- color: isDark.value ? '#fff' : '#000',
- fontWeight: 'normal'
- },
- subtextStyle: {
- fontSize: 28,
- color: isDark.value ? '#fff' : '#000',
- fontWeight: 'bold'
- },
- textAlign: 'center',
- x: '50%',
- y: '20%'
- }
- ],
- grid: [
- {
- top: '50%',
- width: '100%',
- left: 10,
- containLabel: true
- }
- ],
- xAxis: { type: 'category', data: Object.keys(userDatas.value.week) },
- yAxis: { gridIndex: 0 },
- tooltip: [
- {
- trigger: 'item',
- formatter: function (params) {
- if (params.seriesType === 'pie') {
- return `${params.seriesName} <br/>${params.name} : ${params.value}${
- activeName.value === 'user' ? '人' : '次'
- } (${params.percent}%)`
- } else {
- return `${params.seriesName} <br/>${params.name} : ${params.value}${
- activeName.value === 'user' ? '人' : '次'
- } `
- }
- }
- }
- ],
- legend: {
- left: 'center',
- top: 'bottom',
- data: ['注册用户', '内部用户']
- },
- toolbox: {
- show: true,
- feature: {
- mark: { show: true },
- dataView: { show: true, readOnly: false },
- restore: { show: true },
- saveAsImage: { show: true }
- }
- },
- series: [
- {
- name: '注册用户',
- type: 'bar',
- stack: 'one',
- // data: activeName.value === 'user' ? [5, 3, 2, 1, 6, 7, 4] : [30, 20, 13, 50, 21, 12, 30]
- data:
- activeName.value === 'user'
- ? Object.keys(userDatas.value.week).map((key) => {
- return userDatas.value.week[key].user
- })
- : Object.keys(chatDatas.value.week).map((key) => {
- return chatDatas.value.week[key].user
- })
- },
- {
- name: '内部用户',
- type: 'bar',
- stack: 'one',
- // data: activeName.value === 'user' ? [3, 4, 2, 4, 5, 6, 2] : [20, 12, 15, 16, 29, 39, 10]
- data:
- activeName.value === 'user'
- ? Object.keys(userDatas.value.week).map((key) => {
- return userDatas.value.week[key].api
- })
- : Object.keys(chatDatas.value.week).map((key) => {
- return chatDatas.value.week[key].api
- })
- },
- {
- id: 'pie',
- name: activeName.value === 'user' ? '用户人数' : '互动次数',
- type: 'pie',
- radius: ['20%', '40%'],
- avoidLabelOverlap: false,
- center: ['50%', '25%'],
- itemStyle: {
- borderRadius: 5
- },
- data: [
- {
- value: activeName.value === 'user' ? userDatas.value.user : chatDatas.value.user,
- name: '注册用户'
- },
- { value: activeName.value === 'user' ? userDatas.value.api : chatDatas.value.api, name: '内部用户' }
- ]
- }
- ]
- }
- option && myChart.value.setOption(option)
- }
- const userDatas = ref({
- today: 0
- })
- const chatDatas = ref({
- today: 0
- })
- const role = ref('admin')
- onMounted(() => {
- http.get(`/auth/admin/getRole`).then((res) => {
- if (res === 'api') {
- role.value = 'api'
- }
- initChart()
- })
- })
- </script>
- <style lang="less" scoped>
- .el-tabs {
- --el-tabs-header-height: 60px;
- }
- </style>
|