Add active information management to statistic

This commit is contained in:
2023-12-19 16:51:04 +08:00
parent 9b1beed8b5
commit 46ec332298
6 changed files with 202 additions and 7 deletions

View File

@@ -14,11 +14,13 @@ import {
import { BarChart, BarSeriesOption, LineChart, LineSeriesOption } from 'echarts/charts'
import { UniversalTransition } from 'echarts/features'
import { SVGRenderer } from 'echarts/renderers'
import { TopLevelFormatterParams } from 'echarts/types/dist/shared'
import '@/assets/css/pages/system/index.scss'
import { useUpdatedEffect } from '@/util/hooks'
import { formatByteSize } from '@/util/common'
import { utcToLocalTime } from '@/util/datetime'
import {
r_sys_statistic_active,
r_sys_statistic_cpu,
r_sys_statistic_hardware,
r_sys_statistic_online,
@@ -90,6 +92,30 @@ const barEChartsBaseOption: EChartsOption = {
}
}
const getTooltipTimeFormatter = (format: string = 'yyyy-MM-DD HH:mm:ss') => {
return (params: TopLevelFormatterParams) =>
`${utcToLocalTime(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access
params[0].data[0],
format
)}<br><span style="display: flex; justify-content: space-between"><span>${
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
params[0]['marker']
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
}${params[0]['seriesName']}</span><span style="font-weight: bold">${
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access
params[0].data[1]
}</span></span> `
}
const lineEChartsBaseOption: EChartsOption = {
tooltip: {
trigger: 'axis'
@@ -114,11 +140,8 @@ const lineEChartsBaseOption: EChartsOption = {
{
type: 'inside',
start: 0,
end: 100
},
{
start: 0,
end: 100
end: 100,
minValueSpan: 2 * 60 * 60 * 1000
}
],
series: [{}]
@@ -201,7 +224,6 @@ const OnlineInfo: React.FC = () => {
setTimeout(() => {
const dataList = data.history.map((value) => [value.time, value.record])
onlineInfoEChartsRef.current = echarts.init(
onlineInfoDivRef.current,
null,
@@ -210,6 +232,13 @@ const OnlineInfo: React.FC = () => {
onlineInfoEChartsRef.current?.setOption({
...lineEChartsBaseOption,
tooltip: {
...lineEChartsBaseOption.tooltip,
formatter: getTooltipTimeFormatter('yyyy-MM-DD HH:mm')
},
xAxis: {
...lineEChartsBaseOption.xAxis
},
series: [
{
name: '在线人数',
@@ -267,6 +296,142 @@ const OnlineInfo: React.FC = () => {
)
}
const ActiveInfo: React.FC = () => {
const activeInfoDivRef = useRef<HTMLDivElement>(null)
const activeInfoEChartsRef = useRef<echarts.EChartsType | null>(null)
const [isLoading, setIsLoading] = useState(false)
const [scope, setScope] = useState('WEAK')
useUpdatedEffect(() => {
const chartResizeObserver = new ResizeObserver(() => {
activeInfoEChartsRef.current?.resize()
})
activeInfoDivRef.current && chartResizeObserver.observe(activeInfoDivRef.current)
return () => {
activeInfoDivRef.current && chartResizeObserver.unobserve(activeInfoDivRef.current)
}
}, [isLoading])
useUpdatedEffect(() => {
getActiveInfo()
}, [])
const handleOnScopeChange = (value: string) => {
setScope(value)
getActiveInfo(value)
}
const handleOnRefresh = () => {
getActiveInfo()
}
const getActiveInfo = (_scope: string = scope) => {
if (isLoading) {
return
}
setIsLoading(true)
void r_sys_statistic_active({ scope: _scope }).then((res) => {
const response = res.data
if (response.success) {
const data = response.data
if (data) {
setIsLoading(false)
setTimeout(() => {
const registerList = data.registerHistory.map((value) => [
value.time,
value.count
])
const loginList = data.loginHistory.map((value) => [
value.time,
value.count
])
activeInfoEChartsRef.current = echarts.init(
activeInfoDivRef.current,
null,
{ renderer: 'svg' }
)
activeInfoEChartsRef.current?.setOption({
...lineEChartsBaseOption,
tooltip: {
...lineEChartsBaseOption.tooltip,
formatter: getTooltipTimeFormatter('yyyy-MM-DD')
},
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
minValueSpan: 2 * 24 * 60 * 60 * 1000
}
],
series: [
{
name: '注册人数',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {},
data: registerList
},
{
name: '登录人数',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {},
data: loginList
}
]
})
})
}
}
})
}
return (
<CommonCard
icon={IconFatwebAnalysis}
title={
<>
<FlexBox gap={10} direction={'horizontal'}>
<span style={{ whiteSpace: 'nowrap' }}></span>
</FlexBox>
</>
}
loading={isLoading}
expand={
<>
<AntdSelect value={scope} onChange={handleOnScopeChange} disabled={isLoading}>
<AntdSelect.Option key={'WEAK'}>7</AntdSelect.Option>
<AntdSelect.Option key={'MONTH'}>30</AntdSelect.Option>
<AntdSelect.Option key={'QUARTER'}>3</AntdSelect.Option>
<AntdSelect.Option key={'YEAR'}>12</AntdSelect.Option>
<AntdSelect.Option key={'TWO_YEARS'}>2</AntdSelect.Option>
<AntdSelect.Option key={'THREE_YEARS'}>3</AntdSelect.Option>
<AntdSelect.Option key={'FIVE_YEARS'}>5</AntdSelect.Option>
<AntdSelect.Option key={'ALL'}></AntdSelect.Option>
</AntdSelect>
<AntdButton title={'刷新'} onClick={handleOnRefresh} disabled={isLoading}>
<Icon component={IconFatwebRefresh} />
</AntdButton>
</>
}
>
<FlexBox className={'card-content'} direction={'horizontal'}>
<div className={'big-chart'} ref={activeInfoDivRef} />
</FlexBox>
</CommonCard>
)
}
const SoftwareInfo: React.FC = () => {
const [softwareInfoData, setSoftwareInfoData] = useState<SoftwareInfoVo>()
@@ -748,6 +913,7 @@ const System: React.FC = () => {
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
<FlexBox direction={'horizontal'} className={'root-content'}>
<OnlineInfo />
<ActiveInfo />
<SoftwareInfo />
<HardwareInfo />
<CPUInfo />