mirror of https://github.com/openspug/spug
U 优化监控中心总览
parent
8ebedda67f
commit
f421729752
|
@ -8,7 +8,6 @@ import { observer } from 'mobx-react';
|
||||||
import { Card, Input, Select, Space, Tooltip, Spin, message } from 'antd';
|
import { Card, Input, Select, Space, Tooltip, Spin, message } from 'antd';
|
||||||
import { FrownOutlined, RedoOutlined, SyncOutlined } from '@ant-design/icons';
|
import { FrownOutlined, RedoOutlined, SyncOutlined } from '@ant-design/icons';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
import { http, includes } from 'libs';
|
|
||||||
import store from './store';
|
import store from './store';
|
||||||
|
|
||||||
const StyleMap = {
|
const StyleMap = {
|
||||||
|
@ -16,7 +15,7 @@ const StyleMap = {
|
||||||
'1': {background: '#16a98733', border: '2px solid #16a987', color: '#16a987'},
|
'1': {background: '#16a98733', border: '2px solid #16a987', color: '#16a987'},
|
||||||
'2': {background: '#ffba0033', border: '2px solid #ffba00', color: '#ffba00'},
|
'2': {background: '#ffba0033', border: '2px solid #ffba00', color: '#ffba00'},
|
||||||
'3': {background: '#f2655d33', border: '2px solid #f2655d', color: '#f2655d'},
|
'3': {background: '#f2655d33', border: '2px solid #f2655d', color: '#f2655d'},
|
||||||
'10': {background: '#99999919', border: '2px dashed #999999'}
|
'10': {background: '#99999919', border: '2px dashed #999999', color: '#999999'}
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatusMap = {
|
const StatusMap = {
|
||||||
|
@ -27,18 +26,16 @@ const StatusMap = {
|
||||||
'10': '待调度'
|
'10': '待调度'
|
||||||
}
|
}
|
||||||
|
|
||||||
let AutoReload = null
|
|
||||||
|
|
||||||
function CardItem(props) {
|
function CardItem(props) {
|
||||||
const {status, type, desc, name, target, latest_run_time} = props.data
|
const {status, type, desc, name, target, latest_run_time} = props.data
|
||||||
const title = (
|
const title = (
|
||||||
<div>
|
<div>
|
||||||
<div>类型: {type}</div>
|
<div>类型: {type}</div>
|
||||||
<div>名称: {name}</div>
|
<div>名称: {name}</div>
|
||||||
<div>描述: {desc}</div>
|
|
||||||
<div>目标: {target}</div>
|
<div>目标: {target}</div>
|
||||||
<div>状态: {StatusMap[status]}</div>
|
<div>状态: {StatusMap[status]}</div>
|
||||||
<div>更新: {latest_run_time || '---'}</div>
|
<div>更新: {latest_run_time || '---'}</div>
|
||||||
|
<div>描述: {desc}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
|
@ -49,48 +46,24 @@ function CardItem(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function MonitorCard() {
|
function MonitorCard() {
|
||||||
const [fetching, setFetching] = useState(true);
|
|
||||||
const [autoReload, setAutoReload] = useState(false);
|
const [autoReload, setAutoReload] = useState(false);
|
||||||
const [status, setStatus] = useState();
|
const [status, setStatus] = useState();
|
||||||
const [records, setRecords] = useState([]);
|
|
||||||
const [dataSource, setDataSource] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchRecords()
|
store.fetchOverviews()
|
||||||
|
|
||||||
return () => AutoReload = null
|
return () => store.autoReload = null
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
function fetchRecords() {
|
|
||||||
if (AutoReload === false) return
|
|
||||||
setFetching(true);
|
|
||||||
return http.get('/api/monitor/overview/')
|
|
||||||
.then(res => setRecords(res))
|
|
||||||
.finally(() => {
|
|
||||||
setFetching(false)
|
|
||||||
if (AutoReload) setTimeout(fetchRecords, 5000)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const data = records.filter(x =>
|
|
||||||
(!store.f_type || x.type === store.f_type) &&
|
|
||||||
(!store.f_group || x.group === store.f_group) &&
|
|
||||||
(!store.f_name || includes(x.name, store.f_name))
|
|
||||||
)
|
|
||||||
setDataSource(data)
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [records, store.f_type, store.f_group, store.f_name])
|
|
||||||
|
|
||||||
function handleAutoReload() {
|
function handleAutoReload() {
|
||||||
AutoReload = !autoReload
|
store.autoReload = !autoReload
|
||||||
message.info(autoReload ? '关闭自动刷新' : '开启自动刷新')
|
message.info(autoReload ? '关闭自动刷新' : '开启自动刷新')
|
||||||
if (!autoReload) fetchRecords()
|
if (!autoReload) store.fetchOverviews()
|
||||||
setAutoReload(!autoReload)
|
setAutoReload(!autoReload)
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredRecords = dataSource.filter(x => !status || x.status === status)
|
const filteredRecords = store.ovDataSource.filter(x => !status || x.status === status)
|
||||||
return (
|
return (
|
||||||
<Card title="总览" style={{marginBottom: 24}} extra={(
|
<Card title="总览" style={{marginBottom: 24}} extra={(
|
||||||
<Space size="middle">
|
<Space size="middle">
|
||||||
|
@ -116,18 +89,17 @@ function MonitorCard() {
|
||||||
</Space>
|
</Space>
|
||||||
</Space>
|
</Space>
|
||||||
)}>
|
)}>
|
||||||
<Spin spinning={fetching}>
|
<Spin spinning={store.ovFetching}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
{Object.entries(StyleMap).map(([s, style]) => {
|
{Object.entries(StyleMap).map(([s, style]) => {
|
||||||
if (s === '10') return null
|
const count = store.ovDataSource.filter(x => x.status === s).length;
|
||||||
const count = dataSource.filter(x => x.status === s).length;
|
|
||||||
return count ? (
|
return count ? (
|
||||||
<div
|
<div
|
||||||
key={s}
|
key={s}
|
||||||
className={styles.item}
|
className={styles.item}
|
||||||
style={s === status ? style : {...style, background: '#fff'}}
|
style={s === status ? style : {...style, background: '#fff'}}
|
||||||
onClick={() => setStatus(s === status ? '' : s)}>
|
onClick={() => setStatus(s === status ? '' : s)}>
|
||||||
{dataSource.filter(x => x.status === s).length}
|
{store.ovDataSource.filter(x => x.status === s).length}
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -42,7 +42,8 @@ export default observer(function () {
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
store.record = {};
|
store.record = {};
|
||||||
store.formVisible = false;
|
store.formVisible = false;
|
||||||
store.fetchRecords()
|
store.fetchRecords();
|
||||||
|
store.fetchOverviews()
|
||||||
}, () => setLoading(false))
|
}, () => setLoading(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,21 @@
|
||||||
* Released under the AGPL-3.0 License.
|
* Released under the AGPL-3.0 License.
|
||||||
*/
|
*/
|
||||||
import { observable, computed } from 'mobx';
|
import { observable, computed } from 'mobx';
|
||||||
import http from 'libs/http';
|
import { http, includes } from 'libs';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import lds from 'lodash';
|
import lds from 'lodash';
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
|
autoReload = null;
|
||||||
@observable records = [];
|
@observable records = [];
|
||||||
@observable record = {};
|
@observable record = {};
|
||||||
@observable types = [];
|
@observable types = [];
|
||||||
@observable groups = [];
|
@observable groups = [];
|
||||||
|
@observable overviews = [];
|
||||||
@observable page = 0;
|
@observable page = 0;
|
||||||
@observable isFetching = false;
|
@observable isFetching = false;
|
||||||
@observable formVisible = false;
|
@observable formVisible = false;
|
||||||
|
@observable ovFetching = false;
|
||||||
|
|
||||||
@observable f_name;
|
@observable f_name;
|
||||||
@observable f_type;
|
@observable f_type;
|
||||||
|
@ -25,12 +28,20 @@ class Store {
|
||||||
@computed get dataSource() {
|
@computed get dataSource() {
|
||||||
let records = this.records;
|
let records = this.records;
|
||||||
if (this.f_active) records = records.filter(x => x.is_active === (this.f_active === '1'));
|
if (this.f_active) records = records.filter(x => x.is_active === (this.f_active === '1'));
|
||||||
if (this.f_name) records = records.filter(x => x.name.toLowerCase().includes(this.f_name.toLowerCase()));
|
if (this.f_name) records = records.filter(x => includes(x.name, this.f_name));
|
||||||
if (this.f_type) records = records.filter(x => x.type_alias === this.f_type);
|
if (this.f_type) records = records.filter(x => x.type_alias === this.f_type);
|
||||||
if (this.f_group) records = records.filter(x => x.group === this.f_group);
|
if (this.f_group) records = records.filter(x => x.group === this.f_group);
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@computed get ovDataSource() {
|
||||||
|
let records = this.overviews;
|
||||||
|
if (this.f_type) records = records.filter(x => x.type === this.f_type);
|
||||||
|
if (this.f_group) records = records.filter(x => x.group === this.f_group);
|
||||||
|
if (this.f_name) records = records.filter(x => includes(x.name, this.f_name));
|
||||||
|
return records
|
||||||
|
}
|
||||||
|
|
||||||
fetchRecords = () => {
|
fetchRecords = () => {
|
||||||
this.isFetching = true;
|
this.isFetching = true;
|
||||||
http.get('/api/monitor/')
|
http.get('/api/monitor/')
|
||||||
|
@ -49,6 +60,17 @@ class Store {
|
||||||
.finally(() => this.isFetching = false)
|
.finally(() => this.isFetching = false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fetchOverviews = () => {
|
||||||
|
if (this.autoReload === false) return
|
||||||
|
this.ovFetching = true;
|
||||||
|
return http.get('/api/monitor/overview/')
|
||||||
|
.then(res => this.overviews = res)
|
||||||
|
.finally(() => {
|
||||||
|
this.ovFetching = false;
|
||||||
|
if (this.autoReload) setTimeout(this.fetchOverviews, 5000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
showForm = (info) => {
|
showForm = (info) => {
|
||||||
if (info) {
|
if (info) {
|
||||||
this.record = lds.cloneDeep(info)
|
this.record = lds.cloneDeep(info)
|
||||||
|
|
Loading…
Reference in New Issue