mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 22:57:15 +08:00 
			
		
		
		
	feat: 分析页增加数据总览和热门模块列表,调整分析页布局
This commit is contained in:
		| @@ -5,16 +5,26 @@ export type * from './type' | ||||
| 
 | ||||
| const BASE_URL = '/dashboard' | ||||
| 
 | ||||
| /** @desc 查询访问趋势 */ | ||||
| export function listDashboardAccessTrend(days: number) { | ||||
|   return http.get<T.DashboardAccessTrendResp[]>(`${BASE_URL}/access/trend/${days}`) | ||||
| } | ||||
| 
 | ||||
| /** @desc 查询公告列表 */ | ||||
| export function listDashboardNotice() { | ||||
|   return http.get<T.DashboardNoticeResp[]>(`${BASE_URL}/notice`) | ||||
| } | ||||
| 
 | ||||
| /** @desc 查询 PV 总览 */ | ||||
| export function getDashboardOverviewPv() { | ||||
|   return http.get<T.DashboardOverviewCommonResp>(`${BASE_URL}/analysis/overview/pv`) | ||||
| } | ||||
| 
 | ||||
| /** @desc 查询 IP 总览 */ | ||||
| export function getDashboardOverviewIp() { | ||||
|   return http.get<T.DashboardOverviewCommonResp>(`${BASE_URL}/analysis/overview/ip`) | ||||
| } | ||||
| 
 | ||||
| /** @desc 查询访问趋势 */ | ||||
| export function getDashboardAccessTrend(days: number) { | ||||
|   return http.get<T.DashboardAccessTrendResp[]>(`${BASE_URL}/access/trend/${days}`) | ||||
| } | ||||
| 
 | ||||
| /** @desc 查询访问时段分析 */ | ||||
| export function getAnalysisTimeslot() { | ||||
|   return http.get<T.DashboardChartCommonResp[]>(`${BASE_URL}/analysis/timeslot`) | ||||
| @@ -1,3 +1,3 @@ | ||||
| export * from './common' | ||||
| export * from './captcha' | ||||
| export * from './home' | ||||
| export * from './dashboard' | ||||
|   | ||||
| @@ -5,6 +5,13 @@ export interface ImageCaptchaResp { | ||||
|   expireTime: number | ||||
| } | ||||
|  | ||||
| /** 仪表盘公告类型 */ | ||||
| export interface DashboardNoticeResp { | ||||
|   id: number | ||||
|   title: string | ||||
|   type: number | ||||
| } | ||||
|  | ||||
| /** 仪表盘访问趋势类型 */ | ||||
| export interface DashboardAccessTrendResp { | ||||
|   date: string | ||||
| @@ -12,19 +19,20 @@ export interface DashboardAccessTrendResp { | ||||
|   ipCount: number | ||||
| } | ||||
|  | ||||
| /** 仪表盘图表类型 */ | ||||
| /** 仪表盘通用总览类型 */ | ||||
| export interface DashboardOverviewCommonResp { | ||||
|   total: number | ||||
|   today: number | ||||
|   growth: number | ||||
|   dataList: DashboardChartCommonResp[] | ||||
| } | ||||
|  | ||||
| /** 仪表盘通用图表类型 */ | ||||
| export interface DashboardChartCommonResp { | ||||
|   name: string | ||||
|   value: number | ||||
| } | ||||
|  | ||||
| /** 仪表盘公告类型 */ | ||||
| export interface DashboardNoticeResp { | ||||
|   id: number | ||||
|   title: string | ||||
|   type: number | ||||
| } | ||||
|  | ||||
| /* 行为验证码类型 */ | ||||
| export interface BehaviorCaptchaResp { | ||||
|   originalImageBase64: string | ||||
|   | ||||
| @@ -18,9 +18,9 @@ export function useChart(sourceOption: optionsFn) { | ||||
|   // echarts support https://echarts.apache.org/zh/theme-builder.html | ||||
|   // 这里不使用 | ||||
|   // TODO 图表主题 | ||||
|   const option = computed<EChartsOption>(() => { | ||||
|   const chartOption = computed<EChartsOption>(() => { | ||||
|     return sourceOption(isDark.value) | ||||
|   }) | ||||
|  | ||||
|   return { option } | ||||
|   return { chartOption } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card title="访问时段分析" class="general-card" :header-style="{ paddingBottom: '16px' }"> | ||||
|       <Chart style="width: 100%; height: 370px" :option="option" /> | ||||
|     <a-card class="general-card" title="访问时段分析"> | ||||
|       <Chart :option="chartOption" style="width: 100%; height: 370px" /> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { graphic } from 'echarts' | ||||
| import { type EChartsOption, graphic } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { type DashboardChartCommonResp, getAnalysisTimeslot as getData } from '@/apis/common' | ||||
|  | ||||
| @@ -29,8 +29,8 @@ const tooltipItemsHtmlString = (items) => { | ||||
| } | ||||
|  | ||||
| const xAxis = ref<string[]>([]) | ||||
| const dataList = ref<number[]>([]) | ||||
| const { option } = useChart((isDark) => { | ||||
| const chartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: '40', | ||||
| @@ -121,12 +121,14 @@ const { option } = useChart((isDark) => { | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '浏览量(PV)', | ||||
|         data: dataList.value, | ||||
|         name: '访问次数', | ||||
|         data: chartData.value, | ||||
|         type: 'line', | ||||
|         smooth: true, | ||||
|         showSymbol: false, | ||||
|         color: '#246EFF', | ||||
|         color: isDark ? '#3D72F6' : '#246EFF', | ||||
|         symbol: 'circle', | ||||
|         symbolSize: 10, | ||||
|         emphasis: { | ||||
|           focus: 'series', | ||||
|           itemStyle: { | ||||
| @@ -185,7 +187,7 @@ const getChartData = async () => { | ||||
|     const { data } = await getData() | ||||
|     data.forEach((item: DashboardChartCommonResp) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       dataList.value.push(item.value) | ||||
|       chartData.value.push(item.value) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card title="访问趋势" class="general-card"> | ||||
|     <a-card class="general-card" title="访问趋势"> | ||||
|       <template #extra> | ||||
|         <a-radio-group v-model:model-value="dateRange" type="button" size="small" @change="onChange as any"> | ||||
|           <a-radio :value="7">近7天</a-radio> | ||||
|           <a-radio :value="30">近30天</a-radio> | ||||
|         </a-radio-group> | ||||
|       </template> | ||||
|       <Chart :option="option" :style="{ height: '326px' }" /> | ||||
|       <Chart :option="chartOption" style="height: 460px" /> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { graphic } from 'echarts' | ||||
| import { type DashboardAccessTrendResp, listDashboardAccessTrend } from '@/apis' | ||||
| import { type EChartsOption, graphic } from 'echarts' | ||||
| import { type DashboardAccessTrendResp, getDashboardAccessTrend as getData } from '@/apis' | ||||
| import { useChart } from '@/hooks' | ||||
|  | ||||
| // 提示框 | ||||
| @@ -34,14 +34,14 @@ const tooltipItemsHtmlString = (items) => { | ||||
|     .join('') | ||||
| } | ||||
|  | ||||
| const xData = ref<string[]>([]) | ||||
| const pvStatisticsData = ref<number[]>([]) | ||||
| const ipStatisticsData = ref<number[]>([]) | ||||
| const { option } = useChart((isDark) => { | ||||
| const xAxis = ref<string[]>([]) | ||||
| const pvChartData = ref<number[]>([]) | ||||
| const ipChartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: '38', | ||||
|       right: '0', | ||||
|       right: '5', | ||||
|       top: '10', | ||||
|       bottom: '50' | ||||
|     }, | ||||
| @@ -55,13 +55,13 @@ const { option } = useChart((isDark) => { | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       offset: 2, | ||||
|       data: xData.value, | ||||
|       data: xAxis.value, | ||||
|       boundaryGap: false, | ||||
|       axisLabel: { | ||||
|         color: '#4E5969', | ||||
|         formatter(value: number, idx: number) { | ||||
|           if (idx === 0) return '' | ||||
|           if (idx === xData.value.length - 1) return '' | ||||
|           if (idx === xAxis.value.length - 1) return '' | ||||
|           return `${value}` | ||||
|         } | ||||
|       }, | ||||
| @@ -75,7 +75,7 @@ const { option } = useChart((isDark) => { | ||||
|         show: true, | ||||
|         interval: (idx: number) => { | ||||
|           if (idx === 0) return false | ||||
|           return idx !== xData.value.length - 1 | ||||
|           return idx !== xAxis.value.length - 1 | ||||
|         }, | ||||
|         lineStyle: { | ||||
|           color: isDark ? '#3F3F3F' : '#E5E8EF' | ||||
| @@ -124,8 +124,8 @@ const { option } = useChart((isDark) => { | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '浏览量(PV)', | ||||
|         data: pvStatisticsData.value, | ||||
|         name: '访问次数', | ||||
|         data: pvChartData.value, | ||||
|         type: 'line', | ||||
|         smooth: true, | ||||
|         showSymbol: false, | ||||
| @@ -154,8 +154,8 @@ const { option } = useChart((isDark) => { | ||||
|         } | ||||
|       }, | ||||
|       { | ||||
|         name: 'IP数', | ||||
|         data: ipStatisticsData.value, | ||||
|         name: '独立IP', | ||||
|         data: ipChartData.value, | ||||
|         type: 'line', | ||||
|         smooth: true, | ||||
|         showSymbol: false, | ||||
| @@ -193,14 +193,14 @@ const dateRange = ref(30) | ||||
| const getChartData = async (days: number) => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     xData.value = [] | ||||
|     pvStatisticsData.value = [] | ||||
|     ipStatisticsData.value = [] | ||||
|     const { data: chartData } = await listDashboardAccessTrend(days) | ||||
|     chartData.forEach((el: DashboardAccessTrendResp) => { | ||||
|       xData.value.unshift(el.date) | ||||
|       pvStatisticsData.value.unshift(el.pvCount) | ||||
|       ipStatisticsData.value.unshift(el.ipCount) | ||||
|     xAxis.value = [] | ||||
|     pvChartData.value = [] | ||||
|     ipChartData.value = [] | ||||
|     const { data: chartData } = await getData(days) | ||||
|     chartData.forEach((item: DashboardAccessTrendResp) => { | ||||
|       xAxis.value.push(item.date) | ||||
|       pvChartData.value.push(item.pvCount) | ||||
|       ipChartData.value.push(item.ipCount) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   | ||||
| @@ -1,23 +1,23 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card class="general-card" title="浏览器分析" :header-style="{ paddingBottom: '12px' }"> | ||||
|     <a-card class="general-card" title="浏览器"> | ||||
|       <div class="chart"> | ||||
|         <Chart v-if="!loading" style="height: 210px" :option="option" /> | ||||
|         <Chart v-if="!loading" :option="chartOption" style="height: 190px" /> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { type DashboardChartCommonResp, getAnalysisBrowser as getData } from '@/apis/common' | ||||
| 
 | ||||
| const xAxis = ref<string[]>([]) | ||||
| const dataList = ref([]) | ||||
| const { option } = useChart((isDark) => { | ||||
| const chartData = ref([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     legend: { | ||||
|       bottom: 'center', | ||||
|       data: xAxis.value, | ||||
|       bottom: 0, | ||||
|       icon: 'circle', | ||||
| @@ -36,8 +36,8 @@ const { option } = useChart((isDark) => { | ||||
|     series: [ | ||||
|       { | ||||
|         type: 'pie', | ||||
|         radius: ['50%', '70%'], | ||||
|         center: ['50%', '45%'], | ||||
|         radius: ['35%', '60%'], | ||||
|         center: ['50%', '42%'], | ||||
|         label: { | ||||
|           formatter: '{d}% ', | ||||
|           color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969' | ||||
| @@ -46,22 +46,22 @@ const { option } = useChart((isDark) => { | ||||
|           borderColor: isDark ? '#000' : '#fff', | ||||
|           borderWidth: 1 | ||||
|         }, | ||||
|         data: dataList.value | ||||
|         data: chartData.value | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| const loading = ref(false) | ||||
| const colors = ['#249EFF', '#846BCE', '#21CCFF', '#0E42D2', '#86DF6C'] | ||||
| const colors = ['#246EFF', '#00B2FF', '#81E2FF', '#846BCE', '#86DF6C'] | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     data.forEach((item: DashboardChartCommonResp, index) => { | ||||
|     data.forEach((item: DashboardChartCommonResp, index: number) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       dataList.value.push({ | ||||
|       chartData.value.push({ | ||||
|         ...item, | ||||
|         itemStyle: { | ||||
|           color: data.length > 1 && index === data.length - 1 ? colors[colors.length - 1] : colors[index] | ||||
							
								
								
									
										30
									
								
								src/views/dashboard/analysis/components/DataOverview.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/views/dashboard/analysis/components/DataOverview.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <template> | ||||
|   <a-card class="general-card" title="数据总览"> | ||||
|     <a-grid :cols="24" :col-gap="12" :row-gap="12"> | ||||
|       <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|         <Pv /> | ||||
|       </a-grid-item> | ||||
|       <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|         <Ip /> | ||||
|       </a-grid-item> | ||||
|       <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|         <Demo1 /> | ||||
|       </a-grid-item> | ||||
|       <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|         <Demo2 /> | ||||
|       </a-grid-item> | ||||
|     </a-grid> | ||||
|     <template #extra> | ||||
|       <slot name="extra"></slot> | ||||
|     </template> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import Pv from './flow/Pv.vue' | ||||
| import Ip from './flow/Ip.vue' | ||||
| import Demo1 from './flow/Demo1.vue' | ||||
| import Demo2 from './flow/Demo2.vue' | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"></style> | ||||
							
								
								
									
										101
									
								
								src/views/dashboard/analysis/components/Module.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/views/dashboard/analysis/components/Module.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card class="general-card" title="热门模块 (Top10)"> | ||||
|       <div class="chart"> | ||||
|         <Chart v-if="!loading" :option="chartOption" style="width: 100%; height: 355px" /> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { type DashboardChartCommonResp, getAnalysisModule as getData } from '@/apis/common' | ||||
|  | ||||
| const yAxis = ref<string[]>([]) | ||||
| const chartData = ref([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: 55, | ||||
|       right: 20, | ||||
|       top: 0, | ||||
|       bottom: 20 | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'value', | ||||
|       axisLabel: { | ||||
|         show: true, | ||||
|         formatter(value: number, idx: number) { | ||||
|           if (idx === 0) return String(value) | ||||
|           return `${Number(value) / 1000}k` | ||||
|         } | ||||
|       }, | ||||
|       splitLine: { | ||||
|         lineStyle: { | ||||
|           color: isDark ? '#484849' : '#E5E8EF' | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     yAxis: { | ||||
|       type: 'category', | ||||
|       data: yAxis.value, | ||||
|       axisLabel: { | ||||
|         show: true, | ||||
|         color: '#4E5969' | ||||
|       }, | ||||
|       axisTick: { | ||||
|         show: true, | ||||
|         length: 2, | ||||
|         lineStyle: { | ||||
|           color: '#A9AEB8' | ||||
|         }, | ||||
|         alignWithLabel: true | ||||
|       }, | ||||
|       axisLine: { | ||||
|         lineStyle: { | ||||
|           color: isDark ? '#484849' : '#A9AEB8' | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'axis' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         data: chartData.value, | ||||
|         type: 'bar', | ||||
|         barWidth: 7, | ||||
|         itemStyle: { | ||||
|           color: '#4086FF', | ||||
|           borderRadius: 4 | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     data.forEach((item: DashboardChartCommonResp) => { | ||||
|       yAxis.value.unshift(item.name) | ||||
|       chartData.value.unshift(item.value) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| </style> | ||||
| @@ -1,82 +0,0 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card class="general-card" title="模块分析" :header-style="{ paddingBottom: '12px' }"> | ||||
|       <div class="chart"> | ||||
|         <Chart v-if="!loading" style="height: 210px" :option="option" /> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { useChart } from '@/hooks' | ||||
| import { type DashboardChartCommonResp, getAnalysisModule as getData } from '@/apis/common' | ||||
|  | ||||
| const xAxis = ref<string[]>([]) | ||||
| const dataList = ref([]) | ||||
| const { option } = useChart((isDark) => { | ||||
|   return { | ||||
|     legend: { | ||||
|       bottom: 'center', | ||||
|       data: xAxis.value, | ||||
|       bottom: 0, | ||||
|       icon: 'circle', | ||||
|       itemWidth: 8, | ||||
|       textStyle: { | ||||
|         color: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969' | ||||
|       }, | ||||
|       itemStyle: { | ||||
|         borderWidth: 0 | ||||
|       } | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'item' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         type: 'pie', | ||||
|         radius: ['50%', '70%'], | ||||
|         center: ['50%', '45%'], | ||||
|         label: { | ||||
|           formatter: '{d}% ', | ||||
|           color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969' | ||||
|         }, | ||||
|         itemStyle: { | ||||
|           borderColor: isDark ? '#000' : '#fff', | ||||
|           borderWidth: 1 | ||||
|         }, | ||||
|         data: dataList.value | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| const colors = ['#249EFF', '#846BCE', '#21CCFF', '#0E42D2', '#86DF6C'] | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     data.forEach((item: DashboardChartCommonResp, index) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       dataList.value.push({ | ||||
|         ...item, | ||||
|         itemStyle: { | ||||
|           color: data.length > 1 && index === data.length - 1 ? colors[colors.length - 1] : colors[index] | ||||
|         } | ||||
|       }) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| </style> | ||||
| @@ -1,23 +1,23 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card class="general-card" title="终端分析" :header-style="{ paddingBottom: '12px' }"> | ||||
|     <a-card class="general-card" title="终端"> | ||||
|       <div class="chart"> | ||||
|         <Chart v-if="!loading" style="height: 210px" :option="option" /> | ||||
|         <Chart v-if="!loading" :option="chartOption" style="height: 190px" /> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { type DashboardChartCommonResp, getAnalysisOs as getData } from '@/apis/common' | ||||
| 
 | ||||
| const xAxis = ref<string[]>([]) | ||||
| const dataList = ref([]) | ||||
| const { option } = useChart((isDark) => { | ||||
| const chartData = ref([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     legend: { | ||||
|       bottom: 'center', | ||||
|       data: xAxis.value, | ||||
|       bottom: 0, | ||||
|       icon: 'circle', | ||||
| @@ -36,8 +36,8 @@ const { option } = useChart((isDark) => { | ||||
|     series: [ | ||||
|       { | ||||
|         type: 'pie', | ||||
|         radius: ['50%', '70%'], | ||||
|         center: ['50%', '45%'], | ||||
|         radius: ['35%', '60%'], | ||||
|         center: ['50%', '42%'], | ||||
|         label: { | ||||
|           formatter: '{d}% ', | ||||
|           color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969' | ||||
| @@ -46,22 +46,22 @@ const { option } = useChart((isDark) => { | ||||
|           borderColor: isDark ? '#000' : '#fff', | ||||
|           borderWidth: 1 | ||||
|         }, | ||||
|         data: dataList.value | ||||
|         data: chartData.value | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
| 
 | ||||
| const loading = ref(false) | ||||
| const colors = ['#249EFF', '#846BCE', '#21CCFF', '#0E42D2', '#86DF6C'] | ||||
| const colors = ['#246EFF', '#00B2FF', '#81E2FF', '#846BCE', '#86DF6C'] | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     data.forEach((item: DashboardChartCommonResp, index) => { | ||||
|     data.forEach((item: DashboardChartCommonResp, index: number) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       dataList.value.push({ | ||||
|       chartData.value.push({ | ||||
|         ...item, | ||||
|         itemStyle: { | ||||
|           color: data.length > 1 && index === data.length - 1 ? colors[colors.length - 1] : colors[index] | ||||
							
								
								
									
										148
									
								
								src/views/dashboard/analysis/components/flow/Demo1.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/views/dashboard/analysis/components/flow/Demo1.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :style="{ | ||||
|         background: isDark | ||||
|           ? 'linear-gradient(180deg, #284991 0%, #122B62 100%)' | ||||
|           : 'linear-gradient(180deg, #f2f9fe 0%, #e6f4fe 100%)', | ||||
|       }" | ||||
|     > | ||||
|       <div class="content-wrap"> | ||||
|         <div class="content"> | ||||
|           <a-statistic | ||||
|             title="统计示例" | ||||
|             :value="count" | ||||
|             :value-from="0" | ||||
|             animation | ||||
|             show-group-separator | ||||
|           /> | ||||
|           <div class="desc"> | ||||
|             <a-typography-text type="secondary" class="label">较昨日</a-typography-text> | ||||
|             <a-typography-text v-if="growth > 0" type="success" :title="`${growth}%`"> | ||||
|               {{ growth }} | ||||
|               <icon-arrow-rise /> | ||||
|             </a-typography-text> | ||||
|             <a-typography-text v-else type="danger" :title="`${growth}%`"> | ||||
|               {{ growth }} | ||||
|               <icon-arrow-fall /> | ||||
|             </a-typography-text> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="chart"> | ||||
|           <Chart v-if="!loading" :option="chartOption" /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { computed } from 'vue' | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { useAppStore } from '@/stores' | ||||
|  | ||||
| const appStore = useAppStore() | ||||
| const isDark = computed(() => appStore.theme === 'dark') | ||||
|  | ||||
| const count = ref(0) | ||||
| const growth = ref(0) | ||||
| const xAxis = ref<string[]>([]) | ||||
| const chartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: 0, | ||||
|       right: 30, | ||||
|       top: 10, | ||||
|       bottom: 0 | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       data: xAxis.value | ||||
|     }, | ||||
|     yAxis: { | ||||
|       show: false | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'axis' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '示例', | ||||
|         data: chartData.value, | ||||
|         type: 'line', | ||||
|         showSymbol: false, | ||||
|         lineStyle: { | ||||
|           color: '#246EFF', | ||||
|           width: 2, | ||||
|           type: 'dashed' | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     xAxis.value = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'] | ||||
|     count.value = 88888 | ||||
|     growth.value = 88.8 | ||||
|     chartData.value = [10, 2, 4, 30, 21, 6, 7, 8, 1, 2, 3, 10] | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| :deep(.arco-card) { | ||||
|   border-radius: 4px; | ||||
| } | ||||
| :deep(.arco-card-body) { | ||||
|   width: 100%; | ||||
|   height: 134px; | ||||
|   padding: 0; | ||||
| } | ||||
| .content-wrap { | ||||
|   width: 100%; | ||||
|   padding: 16px; | ||||
|   white-space: nowrap; | ||||
| } | ||||
| :deep(.content) { | ||||
|   float: left; | ||||
|   width: 108px; | ||||
|   height: 102px; | ||||
| } | ||||
| :deep(.arco-statistic) { | ||||
|   .arco-statistic-title { | ||||
|     font-size: 16px; | ||||
|     font-weight: bold; | ||||
|     white-space: nowrap; | ||||
|   } | ||||
|   .arco-statistic-content { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .chart { | ||||
|   float: right; | ||||
|   width: calc(100% - 108px); | ||||
|   height: 90px; | ||||
|   vertical-align: bottom; | ||||
| } | ||||
|  | ||||
| .label { | ||||
|   padding-right: 8px; | ||||
|   font-size: 12px; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										159
									
								
								src/views/dashboard/analysis/components/flow/Demo2.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/views/dashboard/analysis/components/flow/Demo2.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :style="{ | ||||
|         background: isDark | ||||
|           ? 'linear-gradient(180deg, #312565 0%, #201936 100%)' | ||||
|           : 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)', | ||||
|       }" | ||||
|     > | ||||
|       <div class="content-wrap"> | ||||
|         <div class="content"> | ||||
|           <a-statistic | ||||
|             title="统计示例" | ||||
|             :value="count" | ||||
|             :value-from="0" | ||||
|             animation | ||||
|             show-group-separator | ||||
|           /> | ||||
|           <div class="desc"> | ||||
|             <a-typography-text type="secondary" class="label">较昨日</a-typography-text> | ||||
|             <a-typography-text v-if="growth > 0" type="success" :title="`${growth}%`"> | ||||
|               {{ growth }} | ||||
|               <icon-arrow-rise /> | ||||
|             </a-typography-text> | ||||
|             <a-typography-text v-else type="danger" :title="`${growth}%`"> | ||||
|               {{ growth }} | ||||
|               <icon-arrow-fall /> | ||||
|             </a-typography-text> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="chart"> | ||||
|           <Chart v-if="!loading" :option="chartOption" /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { computed } from 'vue' | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { useAppStore } from '@/stores' | ||||
|  | ||||
| const appStore = useAppStore() | ||||
| const isDark = computed(() => appStore.theme === 'dark') | ||||
|  | ||||
| const count = ref(0) | ||||
| const growth = ref(0) | ||||
| const chartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: 0, | ||||
|       right: 0, | ||||
|       top: 0, | ||||
|       bottom: 0 | ||||
|     }, | ||||
|     legend: { | ||||
|       show: true, | ||||
|       top: 'center', | ||||
|       right: '20%', | ||||
|       orient: 'vertical', | ||||
|       icon: 'circle', | ||||
|       itemWidth: 6, | ||||
|       itemHeight: 6, | ||||
|       textStyle: { | ||||
|         color: '#4E5969' | ||||
|       } | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '总计', | ||||
|         type: 'pie', | ||||
|         radius: ['50%', '70%'], | ||||
|         center: ['30%', '50%'], | ||||
|         label: { | ||||
|           show: false | ||||
|         }, | ||||
|         data: chartData.value | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| const colors = ['#8D4EDA', '#00B2FF', '#86DF6C'] | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     count.value = 88888 | ||||
|     growth.value = 88.8 | ||||
|     const data = [30, 20, 10] | ||||
|     data.forEach((item, index) => { | ||||
|       chartData.value.push({ | ||||
|         name: `示例${index + 1}`, | ||||
|         value: item, | ||||
|         itemStyle: { | ||||
|           color: data.length > 1 && index === data.length - 1 ? colors[colors.length - 1] : colors[index] | ||||
|         } | ||||
|       }) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| :deep(.arco-card) { | ||||
|   border-radius: 4px; | ||||
| } | ||||
| :deep(.arco-card-body) { | ||||
|   width: 100%; | ||||
|   height: 134px; | ||||
|   padding: 0; | ||||
| } | ||||
| .content-wrap { | ||||
|   width: 100%; | ||||
|   padding: 16px; | ||||
|   white-space: nowrap; | ||||
| } | ||||
| :deep(.content) { | ||||
|   float: left; | ||||
|   width: 108px; | ||||
|   height: 102px; | ||||
| } | ||||
| :deep(.arco-statistic) { | ||||
|   .arco-statistic-title { | ||||
|     font-size: 16px; | ||||
|     font-weight: bold; | ||||
|     white-space: nowrap; | ||||
|   } | ||||
|   .arco-statistic-content { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .chart { | ||||
|   float: right; | ||||
|   width: calc(100% - 108px); | ||||
|   height: 90px; | ||||
|   vertical-align: bottom; | ||||
| } | ||||
|  | ||||
| .label { | ||||
|   padding-right: 8px; | ||||
|   font-size: 12px; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										153
									
								
								src/views/dashboard/analysis/components/flow/Ip.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/views/dashboard/analysis/components/flow/Ip.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :style="{ | ||||
|         background: isDark | ||||
|           ? ' linear-gradient(180deg, #3D492E 0%, #263827 100%)' | ||||
|           : 'linear-gradient(180deg, #F5FEF2 0%, #E6FEEE 100%)', | ||||
|       }" | ||||
|     > | ||||
|       <div class="content-wrap"> | ||||
|         <div class="content"> | ||||
|           <a-statistic | ||||
|             title="独立IP" | ||||
|             :value="count" | ||||
|             :value-from="0" | ||||
|             animation | ||||
|             show-group-separator | ||||
|           /> | ||||
|           <div class="desc"> | ||||
|             <a-typography-text type="secondary" class="label">今日</a-typography-text> | ||||
|             <a-typography-text v-if="growth > 0" type="success" :title="`${growth}%`"> | ||||
|               {{ today }} | ||||
|               <icon-arrow-rise /> | ||||
|             </a-typography-text> | ||||
|             <a-typography-text v-else type="danger" :title="`${growth}%`"> | ||||
|               {{ today }} | ||||
|               <icon-arrow-fall /> | ||||
|             </a-typography-text> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="chart"> | ||||
|           <Chart v-if="!loading" :option="chartOption" /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { computed } from 'vue' | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { useAppStore } from '@/stores' | ||||
| import { type DashboardChartCommonResp, getDashboardOverviewIp as getData } from '@/apis' | ||||
|  | ||||
| const appStore = useAppStore() | ||||
| const isDark = computed(() => appStore.theme === 'dark') | ||||
|  | ||||
| const count = ref(0) | ||||
| const today = ref(0) | ||||
| const growth = ref(0) | ||||
| const xAxis = ref<string[]>([]) | ||||
| const chartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: 0, | ||||
|       right: 30, | ||||
|       top: 10, | ||||
|       bottom: 0 | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       data: xAxis.value | ||||
|     }, | ||||
|     yAxis: { | ||||
|       show: false | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'axis' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '独立IP', | ||||
|         data: chartData.value, | ||||
|         type: 'line', | ||||
|         showSymbol: false, | ||||
|         lineStyle: { | ||||
|           color: '#2CAB40', | ||||
|           width: 2 | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     count.value = data.total | ||||
|     today.value = data.today | ||||
|     growth.value = data.growth | ||||
|     data.dataList.forEach((item: DashboardChartCommonResp) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       chartData.value.push(item.value) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| :deep(.arco-card) { | ||||
|   border-radius: 4px; | ||||
| } | ||||
| :deep(.arco-card-body) { | ||||
|   width: 100%; | ||||
|   height: 134px; | ||||
|   padding: 0; | ||||
| } | ||||
| .content-wrap { | ||||
|   width: 100%; | ||||
|   padding: 16px; | ||||
|   white-space: nowrap; | ||||
| } | ||||
| :deep(.content) { | ||||
|   float: left; | ||||
|   width: 108px; | ||||
|   height: 102px; | ||||
| } | ||||
| :deep(.arco-statistic) { | ||||
|   .arco-statistic-title { | ||||
|     font-size: 16px; | ||||
|     font-weight: bold; | ||||
|     white-space: nowrap; | ||||
|   } | ||||
|   .arco-statistic-content { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .chart { | ||||
|   float: right; | ||||
|   width: calc(100% - 108px); | ||||
|   height: 90px; | ||||
|   vertical-align: bottom; | ||||
| } | ||||
|  | ||||
| .label { | ||||
|   padding-right: 8px; | ||||
|   font-size: 12px; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										153
									
								
								src/views/dashboard/analysis/components/flow/Pv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/views/dashboard/analysis/components/flow/Pv.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card | ||||
|       class="general-card" | ||||
|       :style="{ | ||||
|         background: isDark | ||||
|           ? 'linear-gradient(180deg, #284991 0%, #122B62 100%)' | ||||
|           : 'linear-gradient(180deg, #f2f9fe 0%, #e6f4fe 100%)', | ||||
|       }" | ||||
|     > | ||||
|       <div class="content-wrap"> | ||||
|         <div class="content"> | ||||
|           <a-statistic | ||||
|             title="访问次数" | ||||
|             :value="count" | ||||
|             :value-from="0" | ||||
|             animation | ||||
|             show-group-separator | ||||
|           /> | ||||
|           <div class="desc"> | ||||
|             <a-typography-text type="secondary" class="label">今日</a-typography-text> | ||||
|             <a-typography-text v-if="growth > 0" type="success" :title="`${growth}%`"> | ||||
|               {{ today }} | ||||
|               <icon-arrow-rise /> | ||||
|             </a-typography-text> | ||||
|             <a-typography-text v-else type="danger" :title="`${growth}%`"> | ||||
|               {{ today }} | ||||
|               <icon-arrow-fall /> | ||||
|             </a-typography-text> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="chart"> | ||||
|           <Chart v-if="!loading" :option="chartOption" /> | ||||
|         </div> | ||||
|       </div> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { computed } from 'vue' | ||||
| import type { EChartsOption } from 'echarts' | ||||
| import { useChart } from '@/hooks' | ||||
| import { useAppStore } from '@/stores' | ||||
| import { type DashboardChartCommonResp, getDashboardOverviewPv as getData } from '@/apis' | ||||
|  | ||||
| const appStore = useAppStore() | ||||
| const isDark = computed(() => appStore.theme === 'dark') | ||||
|  | ||||
| const count = ref(0) | ||||
| const today = ref(0) | ||||
| const growth = ref(0) | ||||
| const xAxis = ref<string[]>([]) | ||||
| const chartData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark: EChartsOption) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: 0, | ||||
|       right: 30, | ||||
|       top: 10, | ||||
|       bottom: 0 | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       data: xAxis.value | ||||
|     }, | ||||
|     yAxis: { | ||||
|       show: false | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'axis' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '访问次数', | ||||
|         data: chartData.value, | ||||
|         type: 'line', | ||||
|         showSymbol: false, | ||||
|         lineStyle: { | ||||
|           color: '#246EFF', | ||||
|           width: 2 | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| // 查询图表数据 | ||||
| const getChartData = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const { data } = await getData() | ||||
|     count.value = data.total | ||||
|     today.value = data.today | ||||
|     growth.value = data.growth | ||||
|     data.dataList.forEach((item: DashboardChartCommonResp) => { | ||||
|       xAxis.value.push(item.name) | ||||
|       chartData.value.push(item.value) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| :deep(.arco-card) { | ||||
|   border-radius: 4px; | ||||
| } | ||||
| :deep(.arco-card-body) { | ||||
|   width: 100%; | ||||
|   height: 134px; | ||||
|   padding: 0; | ||||
| } | ||||
| .content-wrap { | ||||
|   width: 100%; | ||||
|   padding: 16px; | ||||
|   white-space: nowrap; | ||||
| } | ||||
| :deep(.content) { | ||||
|   float: left; | ||||
|   width: 108px; | ||||
|   height: 102px; | ||||
| } | ||||
| :deep(.arco-statistic) { | ||||
|   .arco-statistic-title { | ||||
|     font-size: 16px; | ||||
|     font-weight: bold; | ||||
|     white-space: nowrap; | ||||
|   } | ||||
|   .arco-statistic-content { | ||||
|     margin-top: 10px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .chart { | ||||
|   float: right; | ||||
|   width: calc(100% - 108px); | ||||
|   height: 90px; | ||||
|   vertical-align: bottom; | ||||
| } | ||||
|  | ||||
| .label { | ||||
|   padding-right: 8px; | ||||
|   font-size: 12px; | ||||
| } | ||||
| </style> | ||||
| @@ -1,34 +1,40 @@ | ||||
| <template> | ||||
|   <div class="gi_page container"> | ||||
|     <a-space direction="vertical" :size="16" fill> | ||||
|     <a-space direction="vertical" :size="14" fill> | ||||
|       <div> | ||||
|         <AccessTrend /> | ||||
|         <DataOverview /> | ||||
|       </div> | ||||
|       <div> | ||||
|         <a-grid :cols="24" :col-gap="16" :row-gap="16"> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 8, xxl: 8 }"> | ||||
|             <ModuleItem /> | ||||
|         <a-grid :cols="24" :col-gap="14" :row-gap="14"> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 18, xxl: 18 }"> | ||||
|             <AccessTrend /> | ||||
|           </a-grid-item> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 8, xxl: 8 }"> | ||||
|             <OsItem /> | ||||
|           </a-grid-item> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 8, xxl: 8 }"> | ||||
|             <BrowserItem /> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|             <Os style="margin-bottom: 16px" /> | ||||
|             <Browser /> | ||||
|           </a-grid-item> | ||||
|         </a-grid> | ||||
|       </div> | ||||
|       <div> | ||||
|         <a-grid :cols="24" :col-gap="16" :row-gap="16"> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 18, xxl: 18 }"> | ||||
|             <AccessTimeslot /> | ||||
|           </a-grid-item> | ||||
|           <a-grid-item :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 6, xxl: 6 }"> | ||||
|             <Module /> | ||||
|           </a-grid-item> | ||||
|         </a-grid> | ||||
|       </div> | ||||
|     </a-space> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import DataOverview from './components/DataOverview.vue' | ||||
| import AccessTrend from './components/AccessTrend.vue' | ||||
| import ModuleItem from './components/ModuleItem.vue' | ||||
| import OsItem from './components/OsItem.vue' | ||||
| import BrowserItem from './components/BrowserItem.vue' | ||||
| import Os from './components/Os.vue' | ||||
| import Browser from './components/Browser.vue' | ||||
| import Module from './components/Module.vue' | ||||
| import AccessTimeslot from './components/AccessTimeslot.vue' | ||||
|  | ||||
| defineOptions({ name: 'Analysis' }) | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|           <a-radio :value="30">近30天</a-radio> | ||||
|         </a-radio-group> | ||||
|       </template> | ||||
|       <VCharts :option="option" autoresize :style="{ height: '326px' }"></VCharts> | ||||
|       <VCharts :option="chartOption" autoresize :style="{ height: '326px' }"></VCharts> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
| @@ -15,7 +15,7 @@ | ||||
| <script lang="ts" setup> | ||||
| import VCharts from 'vue-echarts' | ||||
| import { graphic } from 'echarts' | ||||
| import { type DashboardAccessTrendResp, listDashboardAccessTrend } from '@/apis' | ||||
| import { type DashboardAccessTrendResp, getDashboardAccessTrend as getData } from '@/apis' | ||||
| import { useChart } from '@/hooks' | ||||
|  | ||||
| // 提示框 | ||||
| @@ -38,7 +38,7 @@ const tooltipItemsHtmlString = (items) => { | ||||
| const xData = ref<string[]>([]) | ||||
| const pvStatisticsData = ref<number[]>([]) | ||||
| const ipStatisticsData = ref<number[]>([]) | ||||
| const { option } = useChart((isDark) => { | ||||
| const { chartOption } = useChart((isDark) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: '38', | ||||
| @@ -197,11 +197,11 @@ const getChartData = async (days: number) => { | ||||
|     xData.value = [] | ||||
|     pvStatisticsData.value = [] | ||||
|     ipStatisticsData.value = [] | ||||
|     const { data: chartData } = await listDashboardAccessTrend(days) | ||||
|     chartData.forEach((el: DashboardAccessTrendResp) => { | ||||
|       xData.value.unshift(el.date) | ||||
|       pvStatisticsData.value.unshift(el.pvCount) | ||||
|       ipStatisticsData.value.unshift(el.ipCount) | ||||
|     const { data } = await getData(days) | ||||
|     data.forEach((el: DashboardAccessTrendResp) => { | ||||
|       xData.value.push(el.date) | ||||
|       pvStatisticsData.value.push(el.pvCount) | ||||
|       ipStatisticsData.value.push(el.ipCount) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   | ||||
		Reference in New Issue
	
	Block a user