feat(): 资源使用中的实时数据以及历史数据开发
parent
35c7b46409
commit
715f86d3a8
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -15,16 +15,23 @@ const guishiPro = '/shzh/ptjstest'
|
|||
const shengUrl2Pro = ''
|
||||
|
||||
const nmjPro = '/shzh/jcsj'
|
||||
|
||||
|
||||
|
||||
const jsapi = {
|
||||
|
||||
ptjs: {
|
||||
czrz: shengUrlPro + '/prod-api/baseplat-system/operlog/hb/list',
|
||||
czdbl: guishiPro + '/monitor/summary',
|
||||
export:guishiPro + '/monitor/export/',
|
||||
resource:guishiPro + '/resource/page',
|
||||
treeList:shengUrlPro + "/prod-api/baseplat-basic/hb/village/getChild/"
|
||||
treeList: shengUrlPro + "/prod-api/baseplat-basic/hb/village/getChild/",
|
||||
cpuPage: guishiPro + '/cpu/page',
|
||||
cpuQuery: guishiPro + '/cpu/list/query',
|
||||
memoryQuery: guishiPro + '/memory/list/query',
|
||||
diskQuery: guishiPro + '/disk/list/query',
|
||||
memoryPage: guishiPro + '/memory/page',
|
||||
diskPage: guishiPro + '/disk/page',
|
||||
diskList: guishiPro + '/disk/list',
|
||||
realCpu: guishiPro + '/cpu/latest',
|
||||
realMemory: guishiPro + '/memory/latest',
|
||||
realDisk: guishiPro + '/disk/latest',
|
||||
},
|
||||
|
||||
service: {
|
||||
|
|
|
|||
|
|
@ -274,7 +274,14 @@ const session = {
|
|||
id:121, redirect: "/ptjs/czrz", parent_id: -1, name: "平台监视", type: 1, order: 1, children: [
|
||||
{ id: 402, path: "/ptjs/czrz", parent_id: 500, name: "操作日志", type: 0, order: 1},
|
||||
{ id: 403, path: "/ptjs/czdbl", parent_id: 500, name: "测站到报率", type: 0, order: 1},
|
||||
{ id: 404, path: "/ptjs/zysy", parent_id: 500, name: "资源使用", type: 0, order: 1},
|
||||
{
|
||||
id: 404, path: "/ptjs/zysy", parent_id: 500, name: "资源使用", type: 0, order: 1,
|
||||
children: [
|
||||
// { id: 407, path: "/ptjs/zysy/ls", parent_id: 500, name: "历史", type: 0, order: 1 },
|
||||
{ id: 405, path: "/ptjs/zysy/sssj", parent_id: 500, name: "实时数据", type: 0, order: 1 },
|
||||
{ id: 406, path: "/ptjs/zysy/lssj", parent_id: 500, name: "历史数据", type: 0, order: 1 },
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,13 @@ const routes = [
|
|||
// 测站到报率
|
||||
{ path: '/ptjs/czdbl', exact: true, component: lazy(() => import('./views/Ptjs/Czdbl')) },
|
||||
|
||||
// 资源使用-实时数据
|
||||
{ path: '/ptjs/zysy/sssj', exact: true, component: lazy(() => import('./views/Ptjs/Sssj')) },
|
||||
// 资源使用-历史数据
|
||||
{ path: '/ptjs/zysy/lssj', exact: true, component: lazy(() => import('./views/Ptjs/Lssj')) },
|
||||
|
||||
// 资源使用
|
||||
{ path: '/ptjs/zysy', exact: true, component: lazy(() => import('./views/Ptjs/Zysy')) },
|
||||
{ path: '/ptjs/zysy/ls', exact: true, component: lazy(() => import('./views/Ptjs/Zysy')) },
|
||||
//监测站点
|
||||
{ path: '/jczd/zdbg', exact: true, component: lazy(() => import('./views/Jczd/Bg')) },
|
||||
{ path: '/jczd/zdsp', exact: true, component: lazy(() => import('./views/Jczd/Sp')) },
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ export default function dblOption(sellist,selday) {
|
|||
},
|
||||
saveAsImage: {
|
||||
show: true,
|
||||
title: '保存为图片'
|
||||
name:'日到报率详情',
|
||||
title: '保存为图片'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Card, message, Table, Space, Button, Spin, Tree } from 'antd';
|
|||
import ToolBar from './toolbar.js';
|
||||
import ToolBottom from './toolBottom.js';
|
||||
import apiurl from '../../../models/apiurl'
|
||||
import { xyt_httpget2, httpPostFile } from "../../../utils/request";
|
||||
import { xyt_httpget2, httpPostFile,httpGetFile } from "../../../utils/request";
|
||||
import { exportFile } from '../../../utils/tools'
|
||||
import { resJson } from './res.js';
|
||||
import ReactEcharts from 'echarts-for-react';
|
||||
|
|
@ -410,6 +410,20 @@ export default function Czrz() {
|
|||
return node;
|
||||
})
|
||||
}
|
||||
|
||||
// 山洪数据映射
|
||||
const dataUpdate = (data) => {
|
||||
return data.map(item => {
|
||||
if (item.adcd == '420391000000000') {
|
||||
item.adcd = '420381450000000';
|
||||
item.adnm = '武当山';
|
||||
}
|
||||
if (item.adcd == '421303000000000') {
|
||||
item.adcd = '421302000000000';
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
const onLoadData = async ({ key, children }) => {
|
||||
if (key.substr(4) != '00000000000') {
|
||||
return
|
||||
|
|
@ -417,8 +431,10 @@ export default function Czrz() {
|
|||
try {
|
||||
const res = await xyt_httpget2(apiurl.ptjs.treeList + key)
|
||||
if (res.code == 200) {
|
||||
const filterData =res.data.filter(item => item.adcd != '420891000000000')
|
||||
const results = dataUpdate(filterData)
|
||||
setTreeList(origin =>
|
||||
updateTreeData(origin, key, res.data.map(item => ({ ...item, isLeaf: true })))
|
||||
updateTreeData(origin, key, results.map(item => ({ ...item, isLeaf: true })))
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -472,11 +488,11 @@ export default function Czrz() {
|
|||
}
|
||||
// 下载测站离线表
|
||||
const download = () => {
|
||||
// httpPostFile(apiurl.service.yjgx.downLoad, params).then((res) => {
|
||||
// if (res) {
|
||||
// exportFile('测站离线表.xlsx', res.data)
|
||||
// }
|
||||
// })
|
||||
httpGetFile(apiurl.ptjs.export + '?' + `tm=${SearchBottom.operTime}`).then((res) => {
|
||||
if (res) {
|
||||
exportFile('测站离线表.xlsx', res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
if (searchVal) {
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ export default function qsOption(timeList, listObj, hbobj, list) {
|
|||
chartTimeList[idx] = str.substring(5, 10);
|
||||
});
|
||||
|
||||
console.log("miny",minY);
|
||||
console.log("chartTimeList", chartTimeList);
|
||||
console.log("addSerise",addSerise.data);
|
||||
|
||||
|
||||
|
||||
return {
|
||||
|
|
@ -150,6 +152,7 @@ console.log("miny",minY);
|
|||
},
|
||||
saveAsImage: {
|
||||
show: true,
|
||||
name:'到报率变化趋势',
|
||||
title: '保存为图片'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
import React, { useState, useMemo } from 'react'
|
||||
import { Card, Tabs,Table } from "antd";
|
||||
import ReactEcharts from 'echarts-for-react';
|
||||
import ToolBar from './toolbar';
|
||||
import zyOptions from './qsOption'
|
||||
import moment from 'moment';
|
||||
import NormalSelect from '../../../components/Form/NormalSelect';
|
||||
import usePageTable from '../../../components/Crud/usePageTable.js'
|
||||
import { findPage2 } from '../../../components/Crud/_.js'
|
||||
import apiurl from '../../../models/apiurl'
|
||||
import { httppost,httpget } from '../../../utils/request.js';
|
||||
import { useEffect } from 'react';
|
||||
export default function Lssj() {
|
||||
const [searchVal, setSearchVal] = useState(false)
|
||||
const [cbOptions, setCbOptions] = useState([])
|
||||
const [cbValue, setCbValue] = useState("/")
|
||||
const [optionsData, setOptionsData] = useState([])
|
||||
const cpuColumn = [
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'tm',
|
||||
key: 'tm',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '用户态CPU时间(s)',
|
||||
dataIndex: 'userTime',
|
||||
key: 'userTime',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '系统态CPU时间(s)',
|
||||
dataIndex: 'system',
|
||||
key: 'system',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '空闲态CPU时间(s)',
|
||||
dataIndex: 'idle',
|
||||
key: 'idle',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},{
|
||||
title: 'I/O等待时间(s)',
|
||||
dataIndex: 'iowait',
|
||||
key: 'iowait',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: 'CPU使用率(%)',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
]
|
||||
const ncColumn = [
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'tm',
|
||||
key: 'tm',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '总内存(MB)',
|
||||
dataIndex: 'totalSpace',
|
||||
key: 'totalSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '已用内存(MB)',
|
||||
dataIndex: 'usedSpace',
|
||||
key: 'usedSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '可用内存(MB)',
|
||||
dataIndex: 'freeSpace',
|
||||
key: 'freeSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '内存使用率(%)',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
]
|
||||
const ccColumn = [
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'tm',
|
||||
key: 'tm',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '挂载点',
|
||||
dataIndex: 'mount',
|
||||
key: 'mount',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '磁盘名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '总磁盘量(GB)',
|
||||
dataIndex: 'totalSpace',
|
||||
key: 'totalSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '已用磁盘量(GB)',
|
||||
dataIndex: 'usedSpace',
|
||||
key: 'usedSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '可用磁盘量(GB)',
|
||||
dataIndex: 'freeSpace',
|
||||
key: 'freeSpace',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title: '磁盘使用率(%)',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
width: 120,
|
||||
align: "center",
|
||||
},
|
||||
]
|
||||
|
||||
const url = useMemo(() => {
|
||||
if (searchVal) {
|
||||
switch (searchVal.type) {
|
||||
case 0:
|
||||
return apiurl.ptjs.cpuPage
|
||||
case 1:
|
||||
return apiurl.ptjs.memoryPage
|
||||
case 2:
|
||||
return apiurl.ptjs.diskPage
|
||||
}
|
||||
} else {
|
||||
return apiurl.ptjs.cpuPage
|
||||
}
|
||||
},[searchVal])
|
||||
const { tableProps, search, refresh } = usePageTable((params) => findPage2(url, params))
|
||||
|
||||
const options = useMemo(() => {
|
||||
if (searchVal && optionsData.length >0) {
|
||||
return zyOptions(optionsData || [],searchVal.type)
|
||||
} else {
|
||||
return zyOptions()
|
||||
}
|
||||
}, [searchVal,optionsData])
|
||||
|
||||
const newColumns = useMemo(() => {
|
||||
if (searchVal) {
|
||||
switch (searchVal.type) {
|
||||
case 0:
|
||||
return cpuColumn
|
||||
case 1:
|
||||
return ncColumn
|
||||
case 2:
|
||||
return ccColumn
|
||||
}
|
||||
|
||||
} else {
|
||||
return cpuColumn
|
||||
}
|
||||
}, [searchVal])
|
||||
|
||||
|
||||
const getDiskList = async () => {
|
||||
try {
|
||||
const res = await httpget(apiurl.ptjs.diskList)
|
||||
if (res.code == 200) {
|
||||
setCbOptions(res.data.map(item => ({ label: item.mount, value: item.mount })))
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取cpu整个时间范围内数据
|
||||
const getTotalList = async (params,url) => {
|
||||
try {
|
||||
const res = await httppost(url,params)
|
||||
if (res.code == 200) {
|
||||
const result = res.data.map(item => ({...item,tm:moment(item.tm).format('HH:mm:ss')}))
|
||||
setOptionsData(result)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
if (searchVal) {
|
||||
const params = {
|
||||
...searchVal,
|
||||
mount: searchVal?.type == 2 ? cbValue :undefined
|
||||
};
|
||||
search(params)
|
||||
const url = searchVal.type == 0 ? apiurl.ptjs.cpuQuery :
|
||||
searchVal.type == 1 ? apiurl.ptjs.memoryQuery :
|
||||
searchVal.type == 2 ? apiurl.ptjs.diskQuery :
|
||||
apiurl.ptjs.cpuQuery
|
||||
getTotalList({...params,type:undefined},url)
|
||||
}
|
||||
}, [searchVal,cbValue])
|
||||
useEffect(() => {
|
||||
getDiskList();
|
||||
}, [])
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className='page'>
|
||||
<Card style={{ display: 'flex', flexDirection: 'column', width: '100%', marginRight: 10 }}>
|
||||
<div className='flex' style={{ alignItems: 'center', marginRight: 10, marginBottom: 20 }}>
|
||||
<img src={require('../../../assets/images/panelTitle.png')} style={{ marginRight: 5 }}></img>
|
||||
<span style={{ fontSize: 16, fontWeight: 'bold' }}>资源使用</span>
|
||||
</div>
|
||||
<ToolBar
|
||||
setToolVal={setSearchVal}
|
||||
/>
|
||||
{optionsData.length > 0 && tableProps.dataSource.length > 0 ?
|
||||
<>
|
||||
<div style={{ width: '100%', height: 440, border: '1px solid #dfdfdf', marginTop: 15,position:'relative' }}>
|
||||
<ReactEcharts option={options} style={{ width: "100%", height: '100%' }} notMerge={true} />
|
||||
{searchVal.type == 2 && <div style={{ position: 'absolute', top: 10, right: 10 }}>
|
||||
<NormalSelect
|
||||
options={cbOptions}
|
||||
onChange={(value) => {
|
||||
setCbValue(value)
|
||||
}}
|
||||
value={cbValue}
|
||||
style={{ width: '230px' }} /></div>}
|
||||
</div>
|
||||
<Table
|
||||
columns={newColumns}
|
||||
{...tableProps}
|
||||
scroll={{ x: 1000, y: "calc( 100vh - 500px )" }}
|
||||
rowKey="inx"
|
||||
/>
|
||||
</> :
|
||||
<img
|
||||
src={`${process.env.PUBLIC_URL}/assets/noData.png`}
|
||||
alt=''
|
||||
style={{marginLeft: '36%',marginTop:"10%"}}
|
||||
/>
|
||||
}
|
||||
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
import { color } from "echarts";
|
||||
import moment from "moment"
|
||||
export default function qsOption(data=[],type=0) {
|
||||
const minY = Math.ceil(Math.min(...data?.map(item => item.rate)));
|
||||
const maxY = Math.floor(Math.max(...data?.map(item => item.rate)));
|
||||
const name = type == 0 ? 'CPU使用率' :
|
||||
type == 1 ? '内存使用率' :
|
||||
type == 2 ? '存储使用率' : 'CPU使用率'
|
||||
const chartType = type != 0 ? 'bar' : 'line';
|
||||
return {
|
||||
legend: {
|
||||
show: true,
|
||||
top:10
|
||||
},
|
||||
grid: {
|
||||
left: '4%',
|
||||
right: '4%',
|
||||
bottom: '8%',
|
||||
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function (params) {
|
||||
if (params.length > 0) {
|
||||
var result = params[0].name + "<br>";
|
||||
params.forEach(function (item) {
|
||||
if (item.value) {
|
||||
result +=
|
||||
item.marker +
|
||||
" " +
|
||||
item.seriesName +
|
||||
" : " +
|
||||
item.value +
|
||||
"%</br>";
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: data.map(item => item.tm),
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
name: name,
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}%'
|
||||
},
|
||||
min: minY,
|
||||
max: maxY,
|
||||
axisLine: {
|
||||
show: true,
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name:name,
|
||||
type: chartType,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color:'#02a7f0',
|
||||
label: {
|
||||
show: false,
|
||||
formatter: '{c}%'
|
||||
},
|
||||
labelLine: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
},
|
||||
data: data.map(item => item.rate)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Form, Input, Button, DatePicker } from 'antd';
|
||||
import NormalSelect from '../../../components/Form/NormalSelect';
|
||||
import dayjs from 'dayjs';
|
||||
import { FileTextOutlined } from '@ant-design/icons';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const ToolBar = ({ setToolVal }) => {
|
||||
const [showIcon, setShowIcon] = useState(false)
|
||||
const selectList=[
|
||||
{key:'最近1小时',value:1},
|
||||
{key:'最近1天',value:2},
|
||||
{key:'最近7天',value:3},
|
||||
{key:'最近1个月',value:4},
|
||||
]
|
||||
const Stypes = [
|
||||
{ label: 'CPU', value: 0 },
|
||||
{ label: '内存', value: 1 },
|
||||
{ label: '存储', value: 2 },
|
||||
];
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const onFinish = (values) => {
|
||||
if (values.tm) {
|
||||
values.stm = values.tm[0] ? dayjs(values.tm[0]).format('YYYY-MM-DD HH:mm:ss') : "";
|
||||
values.etm = values.tm[1] ? dayjs(values.tm[1]).format('YYYY-MM-DD HH:mm:ss') : "";
|
||||
delete values.tm
|
||||
}
|
||||
setToolVal(values);
|
||||
}
|
||||
|
||||
const selectTime = (params)=>{
|
||||
let tmValue=[]
|
||||
if(params === 1){
|
||||
tmValue=[dayjs().subtract(1, 'hours'),
|
||||
dayjs()
|
||||
]
|
||||
}else if(params ===2){
|
||||
tmValue=[dayjs().subtract(1, 'days'),
|
||||
dayjs()
|
||||
]
|
||||
}else if(params ===3){
|
||||
tmValue=[dayjs().subtract(7, 'days'),
|
||||
dayjs()
|
||||
]
|
||||
}else if(params ===4){
|
||||
tmValue=[dayjs().subtract(1, 'months'),
|
||||
dayjs()
|
||||
]
|
||||
}
|
||||
form.setFieldsValue({...params,tm:tmValue})
|
||||
}
|
||||
|
||||
const onValuesChange = (values, allValues) => {
|
||||
if (allValues.tm) {
|
||||
allValues.stm = allValues.tm[0] ? dayjs(allValues.tm[0]).format('YYYY-MM-DD HH:mm:ss') : "";
|
||||
allValues.etm = allValues.tm[1] ? dayjs(allValues.tm[1]).format('YYYY-MM-DD HH:mm:ss') : "";
|
||||
delete allValues.operTime
|
||||
}
|
||||
console.log(values,allValues);
|
||||
setToolVal(allValues)
|
||||
}
|
||||
useEffect(() => {
|
||||
const tm = [dayjs().subtract(1, 'hours'), dayjs()];
|
||||
form.setFieldsValue({ tm, type: 0 })
|
||||
const stm = tm[0].format('YYYY-MM-DD HH:mm:ss');
|
||||
const etm = tm[1].format('YYYY-MM-DD HH:mm:ss');
|
||||
setToolVal({type:0,stm,etm})
|
||||
}, [])
|
||||
return (
|
||||
<div className='pageToolBar' style={{position:'relative'}}>
|
||||
<Form form={form} onFinish={onFinish} size='Default' layout="inline" style={{columnGap:25}} onValuesChange={onValuesChange}>
|
||||
<Form.Item label="监测时间" name="tm">
|
||||
<RangePicker
|
||||
placeholder={['开始日期', '结束日期']}
|
||||
format='YYYY-MM-DD HH:mm:ss'
|
||||
style={{ width: 350 }}
|
||||
showTime
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="监测指标" name="type" wrapperCol={{span:1}}>
|
||||
<NormalSelect options={Stypes} style={{ width: '120px' }} />
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{offset:8}}>
|
||||
<Button type="primary" htmlType="submit" size='Default'>查询</Button>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button size='Default' onClick={() => form.resetFields()}>重置</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div style={{display:'flex',justifyContent:'end',position:'absolute',left:"25.5%",
|
||||
top:"7%"}}
|
||||
onClick={()=>{
|
||||
setShowIcon(!showIcon)
|
||||
}}
|
||||
>
|
||||
<FileTextOutlined style={{fontSize:24,color:'skyblue'}}/>
|
||||
{showIcon &&<div className='selecItem' style={{position:'absolute',zIndex:2,width:200,top:"100%",left:"7.5%",backgroundColor:'#fff',border:'1px solid #f0f0f0',padding:'5px 10px'}}>
|
||||
{selectList.map((item)=>{
|
||||
return <div style={{cursor:'pointer'}} onClick={()=>selectTime(item.value)}>{item.key}</div>
|
||||
})}
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ToolBar;
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
import React from 'react'
|
||||
import { Descriptions } from 'antd'
|
||||
import './index.less'
|
||||
export default function Cpu({data}) {
|
||||
return (
|
||||
<div>
|
||||
<Descriptions title='CPU信息' layout='horizontal' bordered column={2}>
|
||||
<Descriptions.Item label="处理器的名称" span={1}>
|
||||
{data?.cpuVendor}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理器的制造" span={1}>
|
||||
{data?.cpuName}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理器的系列" span={1}>
|
||||
{data?.cpuFamily}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理器的型号" span={1}>
|
||||
{data?.cpuModel}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理器的步进版本" span={1}>
|
||||
{data?.cpuStepping}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="处理器的唯一标识符" span={1}>
|
||||
{data?.processorId}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU是否支持64位架构" span={1}>
|
||||
{data?.cpu64bit ? '是':'否'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU的标称频率" span={1}>
|
||||
{data?.cpuVendorFreq}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="逻辑处理器(线程)的数量" span={1}>
|
||||
{data?.logicalProcessorCount}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="物理处理器的数量" span={1}>
|
||||
{data?.physicalProcessorCount}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU使用率(%)" span={1}>
|
||||
{data?.systemCpuLoad}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU的最大频率" span={1}>
|
||||
{data?.maxFreq}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="CPU缓存的总大小" span={1}>
|
||||
{data?.cacheSize}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
{/* <div className='resourceTitle'>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>CPU</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 'bold' }}>AMD</div>
|
||||
</div>
|
||||
<div className='echarts-resource-box'></div>
|
||||
<div className='cpu-list'>
|
||||
<div className='left'>
|
||||
<div className='first-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>利用率</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>速度</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>3.15GHZ</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>进程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>线程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div><div>
|
||||
<div>句柄</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>正常运行时间</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='right'>
|
||||
<div className='first' style={{display:'flex',columnGap:0,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>基准速度:</div>
|
||||
<div style={{width:100,fontSize:16}}>2.00GHZ</div>
|
||||
</div>
|
||||
<div className='second' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>插槽:</div>
|
||||
<div style={{width:100,fontSize:16}}>1</div>
|
||||
</div>
|
||||
<div className='second1' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>内核:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second2' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>逻辑处理器:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second4' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>虚拟化:</div>
|
||||
<div style={{width:100,fontSize:16}}>已启用</div>
|
||||
</div>
|
||||
<div className='second3' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L1缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second5' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L2缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second6' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L3缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
import React from 'react'
|
||||
import { Table } from 'antd'
|
||||
import './index.less'
|
||||
import { render } from '@testing-library/react';
|
||||
export default function Disk({ data }) {
|
||||
|
||||
// 工具函数:格式化字节大小
|
||||
const formatBytes = (bytes, decimals = 2) => {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024; // 1 KB = 1024 Bytes
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k)); // 计算单位索引
|
||||
|
||||
// 格式化数值并保留指定小数位数
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(decimals))} ${sizes[i]}`;
|
||||
};
|
||||
const newColumns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 60,
|
||||
render: (_, record, index) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '文件存储名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 120,
|
||||
|
||||
},
|
||||
{
|
||||
title: '挂载点路径',
|
||||
dataIndex: 'mount',
|
||||
key: 'mount',
|
||||
width: 120,
|
||||
}, {
|
||||
title: '文件系统类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
width: 120,
|
||||
}, {
|
||||
title: '总空间大小',
|
||||
dataIndex: 'totalSpace',
|
||||
key: 'totalSpace',
|
||||
width: 120,
|
||||
render: (v) => <span>{formatBytes(v)}</span>
|
||||
}, {
|
||||
title: '可用空间大小',
|
||||
dataIndex: 'totalSpace',
|
||||
key: 'totalSpace',
|
||||
width: 120,
|
||||
render: (v) => <span>{formatBytes(v)}</span>
|
||||
|
||||
},
|
||||
{
|
||||
title: '空闲空间大小',
|
||||
dataIndex: 'freeSpace',
|
||||
key: 'freeSpace',
|
||||
width: 120,
|
||||
render: (v) => <span>{formatBytes(v)}</span>
|
||||
|
||||
},
|
||||
]
|
||||
return (
|
||||
<div>
|
||||
<div style={{fontSize:16,fontWeight:600}}>存储信息</div>
|
||||
<Table
|
||||
columns={newColumns}
|
||||
dataSource={data?.fileStores || []}
|
||||
pagination={false}
|
||||
scroll={{ x: 1000, }}
|
||||
rowKey="inx"
|
||||
/>
|
||||
{/* <div className='resourceTitle'>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>CPU</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 'bold' }}>AMD</div>
|
||||
</div>
|
||||
<div className='echarts-resource-box'></div>
|
||||
<div className='cpu-list'>
|
||||
<div className='left'>
|
||||
<div className='first-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>利用率</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>速度</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>3.15GHZ</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>进程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>线程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div><div>
|
||||
<div>句柄</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>正常运行时间</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='right'>
|
||||
<div className='first' style={{display:'flex',columnGap:0,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>基准速度:</div>
|
||||
<div style={{width:100,fontSize:16}}>2.00GHZ</div>
|
||||
</div>
|
||||
<div className='second' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>插槽:</div>
|
||||
<div style={{width:100,fontSize:16}}>1</div>
|
||||
</div>
|
||||
<div className='second1' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>内核:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second2' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>逻辑处理器:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second4' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>虚拟化:</div>
|
||||
<div style={{width:100,fontSize:16}}>已启用</div>
|
||||
</div>
|
||||
<div className='second3' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L1缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second5' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L2缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second6' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L3缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
import React from 'react'
|
||||
import { Descriptions } from 'antd'
|
||||
import './index.less'
|
||||
export default function Memory({ data }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Descriptions title='内存信息' layout='horizontal' bordered column={2}>
|
||||
<Descriptions.Item label="总交换空间大小(byte)" span={1}>
|
||||
{data?.virtualMemory?.swapTotal}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="已使用的交换空间大小(byte)" span={1}>
|
||||
{data?.virtualMemory?.swapUsed}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="从交换空间换入的页数" span={1}>
|
||||
{data?.virtualMemory?.swapPagesIn}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="换出到交换空间的页数" span={1}>
|
||||
{data?.virtualMemory?.swapPagesOut}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="虚拟内存的最大容量(byte)" span={1}>
|
||||
{data?.virtualMemory?.virtualMax}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="当前使用的虚拟内存大小(byte)" span={1}>
|
||||
{data?.virtualMemory?.virtualInUse}
|
||||
</Descriptions.Item>
|
||||
|
||||
</Descriptions>
|
||||
{/* <div className='resourceTitle'>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>CPU</div>
|
||||
<div style={{ fontSize: 18, fontWeight: 'bold' }}>AMD</div>
|
||||
</div>
|
||||
<div className='echarts-resource-box'></div>
|
||||
<div className='cpu-list'>
|
||||
<div className='left'>
|
||||
<div className='first-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>利用率</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>速度</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>3.15GHZ</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>进程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>线程</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div><div>
|
||||
<div>句柄</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='second-row' style={{ display: 'flex', columnGap: 10 }}>
|
||||
<div>
|
||||
<div>正常运行时间</div>
|
||||
<div style={{ fontSize: 24, fontWeight: 'bold' }}>20%</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className='right'>
|
||||
<div className='first' style={{display:'flex',columnGap:0,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>基准速度:</div>
|
||||
<div style={{width:100,fontSize:16}}>2.00GHZ</div>
|
||||
</div>
|
||||
<div className='second' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>插槽:</div>
|
||||
<div style={{width:100,fontSize:16}}>1</div>
|
||||
</div>
|
||||
<div className='second1' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>内核:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second2' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>逻辑处理器:</div>
|
||||
<div style={{width:100,fontSize:16}}>8</div>
|
||||
</div>
|
||||
<div className='second4' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>虚拟化:</div>
|
||||
<div style={{width:100,fontSize:16}}>已启用</div>
|
||||
</div>
|
||||
<div className='second3' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L1缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second5' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L2缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
<div className='second6' style={{display:'flex',columnGap:10,alignItems:'center'}}>
|
||||
<div style={{ width: 100,fontSize:16 }}>L3缓存:</div>
|
||||
<div style={{width:100,fontSize:16}}>512</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import React,{useState,useEffect} from 'react'
|
||||
import { Card, Tabs } from "antd"
|
||||
import Cpu from './Cpu';
|
||||
import Memory from './Memory.js';
|
||||
import Disk from './Disk.js';
|
||||
import apiurl from '../../../models/apiurl'
|
||||
import { httppost,httpget } from '../../../utils/request.js';
|
||||
export default function Sssj() {
|
||||
const items = [
|
||||
{
|
||||
key: '1',
|
||||
label: 'CPU',
|
||||
children: '',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: '内存',
|
||||
children: '',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: '存储',
|
||||
children: '',
|
||||
},
|
||||
];
|
||||
const [objData, setObjData] = useState({})
|
||||
const [tabs, setTabs] = useState('1');
|
||||
const getCpuReal = async (tabs) => {
|
||||
const url = tabs == '1' ? apiurl.ptjs.realCpu :
|
||||
tabs == '2' ? apiurl.ptjs.realMemory :
|
||||
tabs == '3' ? apiurl.ptjs.realDisk :
|
||||
apiurl.ptjs.realCpu;
|
||||
try {
|
||||
const res = await httpget(url)
|
||||
if (res.code == 200) {
|
||||
setObjData(res.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
getCpuReal(tabs)
|
||||
}, [tabs])
|
||||
|
||||
return (
|
||||
<div className='page'>
|
||||
<Card style={{ display: 'flex', flexDirection: 'column',width:'100%',marginRight:10 }}>
|
||||
<div className='flex' style={{ alignItems: 'center', marginRight: 10, marginBottom: 20 }}>
|
||||
<img src={require('../../../assets/images/panelTitle.png')} style={{ marginRight: 5 }}></img>
|
||||
<span style={{ fontSize: 16, fontWeight: 'bold' }}>资源使用</span>
|
||||
</div>
|
||||
<Tabs defaultActiveKey="1" items={items} onChange={(e) => setTabs(e)}/>
|
||||
{tabs === '1' && <Cpu data={objData} />}
|
||||
{tabs === '2' && <Memory data={objData} />}
|
||||
{tabs === '3' && <Disk data={objData} />}
|
||||
</Card>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
.resourceTitle{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.echarts-resource-box{
|
||||
width: 100%;
|
||||
height: 440px;
|
||||
}
|
||||
.cpu-list{
|
||||
display: flex;
|
||||
column-gap: 10px;
|
||||
.left{
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue