Add online info to statistics management page
This commit is contained in:
@@ -74,6 +74,11 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.big-chart {
|
||||||
|
width: 0;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/assets/svg/online.svg
Normal file
1
src/assets/svg/online.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M739.584 575.561143A365.824 365.824 0 0 0 513.828571 950.857143H73.142857c0-242.358857 196.498286-438.857143 438.857143-438.857143 83.346286 0 161.243429 23.222857 227.584 63.561143zM512 512a219.428571 219.428571 0 1 1 0-438.857143 219.428571 219.428571 0 0 1 0 438.857143z m182.857143 146.285714h256v73.142857h-256v-73.142857z m-73.142857 109.714286h329.142857v73.142857h-329.142857v-73.142857z m-36.571429 109.714286h365.714286v73.142857H585.142857v-73.142857z" /></svg>
|
||||||
|
After Width: | Height: | Size: 545 B |
@@ -16,6 +16,7 @@ export const URL_SYS_STATISTIC_SOFTWARE = `${URL_SYS_STATISTIC}/software`
|
|||||||
export const URL_SYS_STATISTIC_HARDWARE = `${URL_SYS_STATISTIC}/hardware`
|
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_CPU = `${URL_SYS_STATISTIC}/cpu`
|
||||||
export const URL_SYS_STATISTIC_STORAGE = `${URL_SYS_STATISTIC}/storage`
|
export const URL_SYS_STATISTIC_STORAGE = `${URL_SYS_STATISTIC}/storage`
|
||||||
|
export const URL_SYS_STATISTIC_ONLINE = `${URL_SYS_STATISTIC}/online`
|
||||||
|
|
||||||
export const URL_API_V1 = '/api/v1'
|
export const URL_API_V1 = '/api/v1'
|
||||||
export const URL_API_V1_AVATAR_RANDOM_BASE64 = `${URL_API_V1}/avatar/base64`
|
export const URL_API_V1_AVATAR_RANDOM_BASE64 = `${URL_API_V1}/avatar/base64`
|
||||||
|
|||||||
12
src/global.d.ts
vendored
12
src/global.d.ts
vendored
@@ -294,10 +294,6 @@ interface AvatarBase64Vo {
|
|||||||
base64: string
|
base64: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SystemSettingsVo {
|
|
||||||
mail: MailSettingsVo
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MailSettingsVo {
|
interface MailSettingsVo {
|
||||||
host?: string
|
host?: string
|
||||||
port?: number
|
port?: number
|
||||||
@@ -381,3 +377,11 @@ interface FileStoreInfoVo {
|
|||||||
total: number
|
total: number
|
||||||
free: number
|
free: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OnlineInfoVo {
|
||||||
|
current: number
|
||||||
|
history: {
|
||||||
|
time: string
|
||||||
|
record: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,9 +5,14 @@ import {
|
|||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
TooltipComponentOption,
|
TooltipComponentOption,
|
||||||
GridComponent,
|
GridComponent,
|
||||||
GridComponentOption
|
GridComponentOption,
|
||||||
|
ToolboxComponentOption,
|
||||||
|
DataZoomComponentOption,
|
||||||
|
ToolboxComponent,
|
||||||
|
DataZoomComponent
|
||||||
} from 'echarts/components'
|
} from 'echarts/components'
|
||||||
import { BarChart, BarSeriesOption } from 'echarts/charts'
|
import { BarChart, BarSeriesOption, LineChart, LineSeriesOption } from 'echarts/charts'
|
||||||
|
import { UniversalTransition } from 'echarts/features'
|
||||||
import { SVGRenderer } from 'echarts/renderers'
|
import { SVGRenderer } from 'echarts/renderers'
|
||||||
import '@/assets/css/pages/system/index.scss'
|
import '@/assets/css/pages/system/index.scss'
|
||||||
import { useUpdatedEffect } from '@/util/hooks'
|
import { useUpdatedEffect } from '@/util/hooks'
|
||||||
@@ -16,6 +21,7 @@ import { utcToLocalTime } from '@/util/datetime'
|
|||||||
import {
|
import {
|
||||||
r_sys_statistic_cpu,
|
r_sys_statistic_cpu,
|
||||||
r_sys_statistic_hardware,
|
r_sys_statistic_hardware,
|
||||||
|
r_sys_statistic_online,
|
||||||
r_sys_statistic_software,
|
r_sys_statistic_software,
|
||||||
r_sys_statistic_storage
|
r_sys_statistic_storage
|
||||||
} from '@/services/system'
|
} from '@/services/system'
|
||||||
@@ -25,9 +31,23 @@ import FitFullScreen from '@/components/common/FitFullScreen'
|
|||||||
import HideScrollbar from '@/components/common/HideScrollbar'
|
import HideScrollbar from '@/components/common/HideScrollbar'
|
||||||
import LoadingMask from '@/components/common/LoadingMask'
|
import LoadingMask from '@/components/common/LoadingMask'
|
||||||
|
|
||||||
echarts.use([TooltipComponent, GridComponent, BarChart, SVGRenderer])
|
echarts.use([
|
||||||
|
TooltipComponent,
|
||||||
|
ToolboxComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
BarChart,
|
||||||
|
LineChart,
|
||||||
|
SVGRenderer,
|
||||||
|
UniversalTransition
|
||||||
|
])
|
||||||
type EChartsOption = echarts.ComposeOption<
|
type EChartsOption = echarts.ComposeOption<
|
||||||
TooltipComponentOption | GridComponentOption | BarSeriesOption
|
| TooltipComponentOption
|
||||||
|
| ToolboxComponentOption
|
||||||
|
| GridComponentOption
|
||||||
|
| BarSeriesOption
|
||||||
|
| DataZoomComponentOption
|
||||||
|
| LineSeriesOption
|
||||||
>
|
>
|
||||||
|
|
||||||
const barDefaultSeriesOption: BarSeriesOption = {
|
const barDefaultSeriesOption: BarSeriesOption = {
|
||||||
@@ -46,7 +66,7 @@ const barDefaultSeriesOption: BarSeriesOption = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const eChartsBaseOption: EChartsOption = {
|
const barEChartsBaseOption: EChartsOption = {
|
||||||
tooltip: {},
|
tooltip: {},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
show: false
|
show: false
|
||||||
@@ -70,9 +90,43 @@ const eChartsBaseOption: EChartsOption = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lineEChartsBaseOption: EChartsOption = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
dataZoom: {
|
||||||
|
yAxisIndex: 'none'
|
||||||
|
},
|
||||||
|
restore: {},
|
||||||
|
saveAsImage: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'time'
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
interval: 1
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
type: 'inside',
|
||||||
|
start: 0,
|
||||||
|
end: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: 0,
|
||||||
|
end: 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [{}]
|
||||||
|
}
|
||||||
|
|
||||||
interface CommonCardProps extends React.PropsWithChildren {
|
interface CommonCardProps extends React.PropsWithChildren {
|
||||||
icon: IconComponent
|
icon: IconComponent
|
||||||
title: string
|
title: React.ReactNode
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
expand?: React.ReactNode
|
expand?: React.ReactNode
|
||||||
}
|
}
|
||||||
@@ -97,6 +151,97 @@ const CommonCard: React.FC<CommonCardProps> = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OnlineInfo: React.FC = () => {
|
||||||
|
const onlineInfoDivRef = useRef<HTMLDivElement>(null)
|
||||||
|
const onlineInfoEChartsRef = useRef<echarts.EChartsType | null>(null)
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [currentOnlineCount, setCurrentOnlineCount] = useState(-1)
|
||||||
|
|
||||||
|
useUpdatedEffect(() => {
|
||||||
|
const chartResizeObserver = new ResizeObserver(() => {
|
||||||
|
onlineInfoEChartsRef.current?.resize()
|
||||||
|
})
|
||||||
|
|
||||||
|
onlineInfoDivRef.current && chartResizeObserver.observe(onlineInfoDivRef.current)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
onlineInfoDivRef.current && chartResizeObserver.unobserve(onlineInfoDivRef.current)
|
||||||
|
}
|
||||||
|
}, [isLoading])
|
||||||
|
|
||||||
|
useUpdatedEffect(() => {
|
||||||
|
getOnlineInfo()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const getOnlineInfo = () => {
|
||||||
|
if (isLoading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(true)
|
||||||
|
|
||||||
|
void r_sys_statistic_online().then((res) => {
|
||||||
|
const response = res.data
|
||||||
|
if (response.success) {
|
||||||
|
const data = response.data
|
||||||
|
if (data) {
|
||||||
|
setIsLoading(false)
|
||||||
|
|
||||||
|
setCurrentOnlineCount(data.current)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const dataList = data.history.map((value) => [value.time, value.record])
|
||||||
|
|
||||||
|
onlineInfoEChartsRef.current = echarts.init(
|
||||||
|
onlineInfoDivRef.current,
|
||||||
|
null,
|
||||||
|
{ renderer: 'svg' }
|
||||||
|
)
|
||||||
|
|
||||||
|
onlineInfoEChartsRef.current?.setOption({
|
||||||
|
...lineEChartsBaseOption,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '在线人数',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'none',
|
||||||
|
areaStyle: {},
|
||||||
|
data: dataList
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CommonCard
|
||||||
|
icon={IconFatwebOnline}
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<FlexBox gap={10} direction={'horizontal'}>
|
||||||
|
<span style={{ whiteSpace: 'nowrap' }}>在线用户</span>
|
||||||
|
<AntdTag>当前 {currentOnlineCount}</AntdTag>
|
||||||
|
</FlexBox>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
loading={isLoading}
|
||||||
|
expand={
|
||||||
|
<AntdButton title={'刷新'} onClick={() => getOnlineInfo()}>
|
||||||
|
<Icon component={IconFatwebRefresh} />
|
||||||
|
</AntdButton>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FlexBox className={'card-content'} direction={'horizontal'}>
|
||||||
|
<div className={'big-chart'} ref={onlineInfoDivRef} />
|
||||||
|
</FlexBox>
|
||||||
|
</CommonCard>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const SoftwareInfo: React.FC = () => {
|
const SoftwareInfo: React.FC = () => {
|
||||||
const [softwareInfoData, setSoftwareInfoData] = useState<SoftwareInfoVo>()
|
const [softwareInfoData, setSoftwareInfoData] = useState<SoftwareInfoVo>()
|
||||||
|
|
||||||
@@ -271,9 +416,9 @@ const CPUInfo: React.FC = () => {
|
|||||||
|
|
||||||
setCpuInfoEChartsOption(
|
setCpuInfoEChartsOption(
|
||||||
dataList.map((value, index) => ({
|
dataList.map((value, index) => ({
|
||||||
...eChartsBaseOption,
|
...barEChartsBaseOption,
|
||||||
yAxis: {
|
yAxis: {
|
||||||
...eChartsBaseOption.yAxis,
|
...barEChartsBaseOption.yAxis,
|
||||||
data: [index === 0 ? '总占用' : `CPU ${index - 1}`]
|
data: [index === 0 ? '总占用' : `CPU ${index - 1}`]
|
||||||
},
|
},
|
||||||
series: value
|
series: value
|
||||||
@@ -501,13 +646,13 @@ const StorageInfo: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const storageInfoVoToStorageEChartsOption = (label: string, used: number, free: number) => ({
|
const storageInfoVoToStorageEChartsOption = (label: string, used: number, free: number) => ({
|
||||||
...eChartsBaseOption,
|
...barEChartsBaseOption,
|
||||||
xAxis: {
|
xAxis: {
|
||||||
...eChartsBaseOption.xAxis,
|
...barEChartsBaseOption.xAxis,
|
||||||
max: used + free
|
max: used + free
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
...eChartsBaseOption.yAxis,
|
...barEChartsBaseOption.yAxis,
|
||||||
data: [label]
|
data: [label]
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
@@ -577,6 +722,7 @@ const System: React.FC = () => {
|
|||||||
<FitFullScreen>
|
<FitFullScreen>
|
||||||
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
|
<HideScrollbar isShowVerticalScrollbar autoHideWaitingTime={500}>
|
||||||
<FlexBox direction={'horizontal'} className={'root-content'}>
|
<FlexBox direction={'horizontal'} className={'root-content'}>
|
||||||
|
<OnlineInfo />
|
||||||
<SoftwareInfo />
|
<SoftwareInfo />
|
||||||
<HardwareInfo />
|
<HardwareInfo />
|
||||||
<CPUInfo />
|
<CPUInfo />
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
URL_SYS_STATISTIC_SOFTWARE,
|
URL_SYS_STATISTIC_SOFTWARE,
|
||||||
URL_SYS_STATISTIC_HARDWARE,
|
URL_SYS_STATISTIC_HARDWARE,
|
||||||
URL_SYS_STATISTIC_CPU,
|
URL_SYS_STATISTIC_CPU,
|
||||||
URL_SYS_STATISTIC_STORAGE
|
URL_SYS_STATISTIC_STORAGE,
|
||||||
|
URL_SYS_STATISTIC_ONLINE
|
||||||
} from '@/constants/urls.constants'
|
} from '@/constants/urls.constants'
|
||||||
import request from '@/services/index'
|
import request from '@/services/index'
|
||||||
|
|
||||||
@@ -86,3 +87,5 @@ export const r_sys_statistic_hardware = () =>
|
|||||||
export const r_sys_statistic_cpu = () => request.get<CpuInfoVo>(URL_SYS_STATISTIC_CPU)
|
export const r_sys_statistic_cpu = () => request.get<CpuInfoVo>(URL_SYS_STATISTIC_CPU)
|
||||||
|
|
||||||
export const r_sys_statistic_storage = () => request.get<StorageInfoVo>(URL_SYS_STATISTIC_STORAGE)
|
export const r_sys_statistic_storage = () => request.get<StorageInfoVo>(URL_SYS_STATISTIC_STORAGE)
|
||||||
|
|
||||||
|
export const r_sys_statistic_online = () => request.get<OnlineInfoVo>(URL_SYS_STATISTIC_ONLINE)
|
||||||
|
|||||||
Reference in New Issue
Block a user