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

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1080 1024"><path d="M265.216 920.348444a41.472 41.472 0 0 1-41.415111-42.211555v-215.608889a42.154667 42.154667 0 1 1 83.512889 0v215.608889a42.097778 42.097778 0 0 1-42.097778 42.211555z m207.701333 0a41.472 41.472 0 0 1-41.358222-42.211555V536.689778a42.097778 42.097778 0 0 1 83.512889 0v340.764444a42.097778 42.097778 0 0 1-42.097778 42.894222z m207.758223 0a41.472 41.472 0 0 1-41.358223-42.211555V728.177778a42.097778 42.097778 0 0 1 83.512889 0v149.959111a42.097778 42.097778 0 0 1-42.097778 42.211555z m207.758222 0a41.472 41.472 0 0 1-41.415111-42.211555v-276.48a42.154667 42.154667 0 1 1 83.569777 0v279.950222a42.097778 42.097778 0 0 1-42.097777 38.684445zM210.659556 502.101333a41.415111 41.415111 0 0 1-33.792-16.554666 42.211556 42.211556 0 0 1 10.353777-58.766223l300.202667-231.537777a42.723556 42.723556 0 0 1 51.768889 0l138.069333 112.64 222.947556-185.969778a41.756444 41.756444 0 0 1 53.816889 63.601778l-247.808 208.782222a41.358222 41.358222 0 0 1-53.134223 0L515.072 280.917333 238.933333 493.112889a42.723556 42.723556 0 0 1-28.273777 8.988444z" /><path d="M927.118222 336.896a42.097778 42.097778 0 0 1-42.097778-41.472V179.313778h-117.361777a42.154667 42.154667 0 0 1 0-83.626667h159.459555a42.097778 42.097778 0 0 1 42.097778 41.415111v158.321778a42.097778 42.097778 0 0 1-42.097778 41.528889z" /></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -17,6 +17,7 @@ export const URL_SYS_STATISTIC_HARDWARE = `${URL_SYS_STATISTIC}/hardware`
export const URL_SYS_STATISTIC_CPU = `${URL_SYS_STATISTIC}/cpu`
export const URL_SYS_STATISTIC_STORAGE = `${URL_SYS_STATISTIC}/storage`
export const URL_SYS_STATISTIC_ONLINE = `${URL_SYS_STATISTIC}/online`
export const URL_SYS_STATISTIC_ACTIVE = `${URL_SYS_STATISTIC}/active`
export const URL_API_V1 = '/api/v1'
export const URL_API_V1_AVATAR_RANDOM_BASE64 = `${URL_API_V1}/avatar/base64`

15
src/global.d.ts vendored
View File

@@ -389,3 +389,18 @@ interface OnlineInfoVo {
interface OnlineInfoGetParam {
scope: string
}
interface ActiveInfoVo {
registerHistory: {
time: string
count: number
}[]
loginHistory: {
time: string
count: number
}[]
}
interface ActiveInfoGetParam {
scope: string
}

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 />

View File

@@ -13,7 +13,8 @@ import {
URL_SYS_STATISTIC_HARDWARE,
URL_SYS_STATISTIC_CPU,
URL_SYS_STATISTIC_STORAGE,
URL_SYS_STATISTIC_ONLINE
URL_SYS_STATISTIC_ONLINE,
URL_SYS_STATISTIC_ACTIVE
} from '@/constants/urls.constants'
import request from '@/services/index'
@@ -90,3 +91,6 @@ export const r_sys_statistic_storage = () => request.get<StorageInfoVo>(URL_SYS_
export const r_sys_statistic_online = (param: OnlineInfoGetParam) =>
request.get<OnlineInfoVo>(URL_SYS_STATISTIC_ONLINE, param)
export const r_sys_statistic_active = (param: ActiveInfoGetParam) =>
request.get<ActiveInfoVo>(URL_SYS_STATISTIC_ACTIVE, param)

View File

@@ -28,3 +28,11 @@ export const localTimeToUtc = (localTime: string) => {
export const isPastTime = (utcTime: string) => {
return moment.utc(utcTime).isBefore(moment.now())
}
export const utcToMillisecond = (utcTime: string) => {
return moment.utc(utcTime).valueOf()
}
export const millisecondToUtc = (millisecond: number) => {
return moment(millisecond).toISOString()
}