update chart style

This commit is contained in:
2023-12-11 13:19:22 +08:00
parent 9f4319bd13
commit e42c90dfc1

View File

@@ -6,12 +6,12 @@ import { NAlert, NCard, NSpace, NSpin, useMessage } from 'naive-ui'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { use } from 'echarts/core' import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers' import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts' import { BarChart, LineChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent } from 'echarts/components' import { TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent, ToolboxComponent } from 'echarts/components'
import VChart from 'vue-echarts' import VChart from 'vue-echarts'
import { format } from 'date-fns' import { addHours, format, getUnixTime, isSameDay, isSameHour, startOfHour } from 'date-fns'
use([CanvasRenderer, LineChart, TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent, LineChart]) use([CanvasRenderer, LineChart, TitleComponent, TooltipComponent, LegendComponent, GridComponent, DataZoomComponent, LineChart, ToolboxComponent, BarChart])
const accountInfo = useAccount() const accountInfo = useAccount()
const message = useMessage() const message = useMessage()
@@ -86,33 +86,65 @@ async function getUpstatHistory() {
message.error('加载失败') message.error('加载失败')
}) })
} }
function isSameDay(time1: number, time2: number) { function isSameDaySimple(time1: number, time2: number) {
const time1Date = new Date(time1) const time1Date = new Date(time1)
const time2Date = new Date(time2) const time2Date = new Date(time2)
return time1Date.getFullYear() === time2Date.getFullYear() && time1Date.getMonth() === time2Date.getMonth() && time1Date.getDate() === time2Date.getDate() return time1Date.getFullYear() === time2Date.getFullYear() && time1Date.getMonth() === time2Date.getMonth() && time1Date.getDate() === time2Date.getDate()
} }
function getOptions() { function getOptions() {
let fansIncreacement = [] as { time: number; count: number; timeString: string }[] let fansIncreacement = [] as { time: Date; count: number; timeString: string }[]
let completeTimeSeries: {
time: Date
count: number
}[] = []
let guards = [] as { time: number; count: number; timeString: string }[] let guards = [] as { time: number; count: number; timeString: string }[]
let fansIncreacementLastHour = 0 if (fansHistory.value) {
let lastHourFans = 0 const startTime = new Date(fansHistory.value[0].time)
fansHistory.value?.forEach((f) => { const endTime = new Date(fansHistory.value[fansHistory.value.length - 1].time)
if (!isSameDay(f.time, fansIncreacementLastHour)) {
fansIncreacement.push({ let currentTime = startTime
time: fansIncreacementLastHour, // 生成完整的小时序列
count: fansIncreacementLastHour == 0 ? 0 : f.count - lastHourFans, while (currentTime <= endTime) {
//将timeString转换为yyyy-MM-dd HH let found = fansHistory.value.find((f) => isSameHour(currentTime, f.time))
timeString: format(f.time, 'yyyy-MM-dd'), let count = found ? found.count : completeTimeSeries[completeTimeSeries.length - 1]?.count || 0
completeTimeSeries.push({
time: currentTime,
count: count,
}) })
fansIncreacementLastHour = f.time
lastHourFans = f.count currentTime = addHours(currentTime, 1)
} }
}) // 计算日增量数据
let previousDayCount = completeTimeSeries[0].count
completeTimeSeries.forEach((entry, index, array) => {
if (index === 0 || !isSameDay(entry.time, array[index - 1].time)) {
if (index > 0) {
let dailyIncrement = entry.count - previousDayCount
fansIncreacement.push({
time: startOfHour(array[index - 1].time),
count: dailyIncrement,
timeString: format(array[index - 1].time, 'yyyy-MM-dd'),
})
}
previousDayCount = entry.count
} else if (index === array.length - 1) {
let dailyIncrement = entry.count - previousDayCount
fansIncreacement.push({
time: startOfHour(entry.time),
count: dailyIncrement,
timeString: format(array[index - 1].time, 'yyyy-MM-dd'),
})
}
})
}
let lastDayGuards = 0 let lastDayGuards = 0
let lastDay = 0 let lastDay = 0
guardHistory.value?.forEach((g) => { guardHistory.value?.forEach((g) => {
if (!isSameDay(g.time, lastDayGuards)) { if (!isSameDaySimple(g.time, lastDayGuards)) {
guards.push({ guards.push({
time: lastDayGuards, time: lastDayGuards,
count: lastDay == 0 ? 0 : g.count - lastDayGuards, count: lastDay == 0 ? 0 : g.count - lastDayGuards,
@@ -142,7 +174,16 @@ function getOptions() {
lastUpstatLike = u.stats.likes lastUpstatLike = u.stats.likes
}) })
} }
const chartData = {
xAxisData: completeTimeSeries.map((entry) => format(entry.time, 'yyyy-MM-dd HH:mm')),
hourlyCounts: completeTimeSeries.map((entry) => entry.count),
dailyIncrements: fansIncreacement.map((entry) => {
return {
date: format(entry.time, 'yyyy-MM-dd'),
count: entry.count,
}
}),
}
fansOption.value = { fansOption.value = {
title: { title: {
text: '粉丝数', text: '粉丝数',
@@ -150,31 +191,33 @@ function getOptions() {
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
toolbox: {
feature: {
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ['line', 'bar'] },
restore: { show: true },
saveAsImage: { show: true },
},
}, },
legend: {}, legend: {},
yAxis: [ yAxis: [
{ {
type: 'value', type: 'value',
name: '每小时粉丝数',
}, },
{ {
type: 'value', type: 'value',
name: '每日增量',
}, },
], ],
xAxis: [ xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
axisLine: {
onZero: false,
lineStyle: {
color: '#EE6666',
},
},
// prettier-ignore
data: fansIncreacement.map((f) => f.timeString),
},
{ {
type: 'category', type: 'category',
axisTick: { axisTick: {
@@ -187,7 +230,23 @@ function getOptions() {
}, },
}, },
// prettier-ignore // prettier-ignore
data: fansHistory.value?.map(f => format(f.time, 'yyyy-MM-dd HH:mm')), data: chartData.xAxisData,
},
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
boundaryGap: false, // 设置为false使得柱状图紧贴左右两侧
axisLine: {
onZero: false,
lineStyle: {
color: '#EE6666',
},
},
// prettier-ignore
data: fansIncreacement.map((f) => f.timeString),
}, },
], ],
series: [ series: [
@@ -197,18 +256,17 @@ function getOptions() {
emphasis: { emphasis: {
focus: 'series', focus: 'series',
}, },
data: fansHistory.value?.map((f) => f.count), data: chartData.hourlyCounts,
}, },
{ {
name: '增量 /日', name: '增量 /日',
type: 'line', type: 'bar',
yAxisIndex: 1, yAxisIndex: 1,
smooth: true, xAxisIndex: 1,
showSymbol: false,
emphasis: { emphasis: {
focus: 'series', focus: 'series',
}, },
data: fansIncreacement.map((f) => f.count), data: chartData.dailyIncrements.map((f) => f.count),
}, },
], ],
dataZoom: [ dataZoom: [
@@ -316,8 +374,7 @@ function getOptions() {
}, },
{ {
name: '日增', name: '日增',
type: 'line', type: 'bar',
step: 'middle',
yAxisIndex: 1, yAxisIndex: 1,
emphasis: { emphasis: {
focus: 'series', focus: 'series',
@@ -379,10 +436,8 @@ function getOptions() {
}, },
{ {
name: '日增', name: '日增',
type: 'line', type: 'bar',
yAxisIndex: 1, yAxisIndex: 1,
step: 'middle',
emphasis: { emphasis: {
focus: 'series', focus: 'series',
}, },
@@ -414,7 +469,7 @@ onMounted(async () => {
<template> <template>
<NAlert v-if="accountInfo?.isBiliVerified != true" type="info"> 尚未进行Bilibili认证 </NAlert> <NAlert v-if="accountInfo?.isBiliVerified != true" type="info"> 尚未进行Bilibili认证 </NAlert>
<NSpin v-else-if="isLoading" show/> <NSpin v-else-if="isLoading" show />
<NCard v-else size="small"> <NCard v-else size="small">
<NSpace vertical> <NSpace vertical>
<VChart :option="fansOption" style="height: 200px" /> <VChart :option="fansOption" style="height: 200px" />