Skip to content

Commit

Permalink
feat: 新增分析页
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles7c committed Oct 17, 2024
1 parent ad31d9f commit 455f269
Show file tree
Hide file tree
Showing 11 changed files with 766 additions and 10 deletions.
20 changes: 20 additions & 0 deletions src/apis/common/home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,23 @@ export function listDashboardAccessTrend(days: number) {
export function listDashboardNotice() {
return http.get<T.DashboardNoticeResp[]>(`${BASE_URL}/notice`)
}

/** @desc 查询访问时段分析 */
export function getAnalysisTimeslot() {
return http.get<T.DashboardChartCommonResp[]>(`${BASE_URL}/analysis/timeslot`)
}

/** @desc 查询模块分析 */
export function getAnalysisModule() {
return http.get<T.DashboardChartCommonResp[]>(`${BASE_URL}/analysis/module`)
}

/** @desc 查询终端分析 */
export function getAnalysisOs() {
return http.get<T.DashboardChartCommonResp[]>(`${BASE_URL}/analysis/os`)
}

/** @desc 查询浏览器分析 */
export function getAnalysisBrowser() {
return http.get<T.DashboardChartCommonResp[]>(`${BASE_URL}/analysis/browser`)
}
6 changes: 6 additions & 0 deletions src/apis/common/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export interface DashboardAccessTrendResp {
ipCount: number
}

/** 仪表盘图表类型 */
export interface DashboardChartCommonResp {
name: string
value: number
}

/** 仪表盘公告类型 */
export interface DashboardNoticeResp {
id: number
Expand Down
41 changes: 41 additions & 0 deletions src/components/Chart/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<VCharts
v-if="renderChart"
:option="option"
:autoresize="autoResize"
:style="{ width, height }"
/>
</template>

<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import VCharts from 'vue-echarts'
defineProps({
option: {
type: Object,
default() {
return {}
}
},
autoResize: {
type: Boolean,
default: true
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
})
const renderChart = ref(false)
// wait container expand
nextTick(() => {
renderChart.value = true
})
</script>

<style scoped lang="less"></style>
10 changes: 2 additions & 8 deletions src/styles/global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
padding: $margin;
box-sizing: border-box;
overflow-y: auto;
overflow-x: hidden;
}

// 表格页面
Expand Down Expand Up @@ -311,18 +312,11 @@

// 通用卡片
.general-card {
height: 100%;
overflow-y: auto;
border: none;
& > .arco-card-header {
height: auto;
padding: $padding;
border: none;
.arco-card-header-title {
color: var(--color-text-1);
font-size: 18px;
font-weight: 500;
line-height: 1.5;
}
}
& > .arco-card-body {
padding: 0 $padding $padding $padding;
Expand Down
1 change: 1 addition & 0 deletions src/types/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
Chart: typeof import('./../components/Chart/index.vue')['default']
CronForm: typeof import('./../components/GenCron/CronForm/index.vue')['default']
CronModel: typeof import('./../components/GenCron/CronModel/index.vue')['default']
DateRangePicker: typeof import('./../components/DateRangePicker/index.vue')['default']
Expand Down
204 changes: 204 additions & 0 deletions src/views/dashboard/analysis/components/AccessTimeslot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
<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>
</a-spin>
</template>

<script lang="ts" setup>
import { graphic } from 'echarts'
import { useChart } from '@/hooks'
import { type DashboardChartCommonResp, getAnalysisTimeslot as getData } from '@/apis/common'
// 提示框
const tooltipItemsHtmlString = (items) => {
return items
.map(
(el) => `<div class="content-panel">
<p>
<span style="background-color: ${el.color}" class="tooltip-item-icon"></span>
<span>${el.seriesName}</span>
</p>
<span class="tooltip-value">
${el.value}
</span>
</div>`
)
.join('')
}
const xAxis = ref<string[]>([])
const dataList = ref<number[]>([])
const { option } = useChart((isDark) => {
return {
grid: {
left: '40',
right: 0,
top: '20',
bottom: '100'
},
xAxis: {
type: 'category',
offset: 2,
data: xAxis.value,
boundaryGap: false,
axisLabel: {
color: '#4E5969',
formatter(value: number, idx: number) {
if (idx === 0) return ''
if (idx === xAxis.value.length - 1) return ''
return `${value}`
}
},
axisLine: {
lineStyle: {
color: isDark ? '#3f3f3f' : '#A9AEB8'
}
},
axisTick: {
show: true,
alignWithLabel: true,
lineStyle: {
color: '#86909C'
},
interval(idx: number) {
if (idx === 0) return false
if (idx === xAxis.value.length - 1) return false
return true
}
},
splitLine: {
show: true,
interval: (idx: number) => {
if (idx === 0) return false
return idx !== xAxis.value.length - 1
},
lineStyle: {
color: isDark ? '#3F3F3F' : '#E5E8EF'
}
},
axisPointer: {
show: true,
lineStyle: {
color: '#23ADFF',
width: 2
}
}
},
yAxis: {
type: 'value',
axisLabel: {
formatter(value: any, idx: number) {
if (idx === 0) return value
if (value >= 1000) {
return `${value / 1000}k`
}
return `${value}`
}
},
axisLine: {
show: false
},
splitLine: {
lineStyle: {
type: 'dashed',
color: isDark ? '#3F3F3F' : '#E5E8EF'
}
}
},
tooltip: {
show: true,
trigger: 'axis',
formatter(params) {
const [firstElement] = params
return `<div>
<p class="tooltip-title">${firstElement.axisValueLabel}</p>
${tooltipItemsHtmlString(params)}
</div>`
},
className: 'echarts-tooltip-diy'
},
series: [
{
name: '浏览量(PV)',
data: dataList.value,
type: 'line',
smooth: true,
showSymbol: false,
color: '#246EFF',
emphasis: {
focus: 'series',
itemStyle: {
borderWidth: 2,
borderColor: '#E0E3FF'
}
},
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(17, 126, 255, 0.16)'
},
{
offset: 1,
color: 'rgba(17, 128, 255, 0)'
}
])
}
}
],
dataZoom: [
{
bottom: 40,
type: 'slider',
left: 40,
right: 14,
height: 14,
borderColor: 'transparent',
handleIcon:
'image://http://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/1ee5a8c6142b2bcf47d2a9f084096447.svg~tplv-49unhts6dw-image.image',
handleSize: '20',
handleStyle: {
shadowColor: 'rgba(0, 0, 0, 0.2)',
shadowBlur: 4
},
brushSelect: false,
backgroundColor: isDark ? '#313132' : '#F2F3F5'
},
{
type: 'inside',
start: 0,
end: 100,
zoomOnMouseWheel: false
}
]
}
})
const loading = ref(false)
// 查询图表数据
const getChartData = async () => {
try {
loading.value = true
const { data } = await getData()
data.forEach((item: DashboardChartCommonResp) => {
xAxis.value.push(item.name)
dataList.value.push(item.value)
})
} finally {
loading.value = false
}
}
onMounted(() => {
getChartData()
})
</script>

<style lang="scss" scoped>
:deep(.arco-card-body) {
padding-bottom: 0;
}
</style>
Loading

0 comments on commit 455f269

Please sign in to comment.