A 监控中心 增加分组

pull/289/head
zyupo 2020-12-02 18:59:35 +08:00
parent 8bf264bcd2
commit d11ee1258d
8 changed files with 80 additions and 31 deletions

View File

@ -21,6 +21,7 @@ class Detection(models.Model, ModelMixin):
) )
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
type = models.CharField(max_length=2, choices=TYPES) type = models.CharField(max_length=2, choices=TYPES)
group = models.CharField(max_length=255, null=True)
addr = models.CharField(max_length=255) addr = models.CharField(max_length=255)
extra = models.TextField(null=True) extra = models.TextField(null=True)
desc = models.CharField(max_length=255, null=True) desc = models.CharField(max_length=255, null=True)

View File

@ -13,12 +13,14 @@ import json
class DetectionView(View): class DetectionView(View):
def get(self, request): def get(self, request):
detections = Detection.objects.all() detections = Detection.objects.all()
return json_response(detections) groups = [x['group'] for x in detections.order_by('group').values('group').distinct()]
return json_response({'groups': groups, 'detections': [x.to_dict() for x in detections]})
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(
Argument('id', type=int, required=False), Argument('id', type=int, required=False),
Argument('name', help='请输入任务名称'), Argument('name', help='请输入任务名称'),
Argument('group', help='请选择任务分组'),
Argument('addr', help='请输入监控地址'), Argument('addr', help='请输入监控地址'),
Argument('type', filter=lambda x: x in dict(Detection.TYPES), help='请选择监控类型'), Argument('type', filter=lambda x: x in dict(Detection.TYPES), help='请选择监控类型'),
Argument('extra', required=False), Argument('extra', required=False),

1
spug_web/.gitignore vendored
View File

@ -4,6 +4,7 @@
/node_modules /node_modules
/.pnp /.pnp
.pnp.js .pnp.js
/.idea/
# testing # testing
/coverage /coverage

View File

@ -5,6 +5,7 @@
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { Modal, Form, Input, Select, Button } from 'antd'; import { Modal, Form, Input, Select, Button } from 'antd';
import TemplateSelector from '../exec/task/TemplateSelector'; import TemplateSelector from '../exec/task/TemplateSelector';
import { LinkButton, ACEditor } from 'components'; import { LinkButton, ACEditor } from 'components';
@ -48,6 +49,26 @@ export default observer(function () {
store.record.type = v; store.record.type = v;
store.record.addr = undefined; store.record.addr = undefined;
store.record.extra = undefined; store.record.extra = undefined;
};
function handleAddGroup() {
Modal.confirm({
icon: <ExclamationCircleOutlined />,
title: '添加监控分组',
content: (
<Form layout="vertical" style={{ marginTop: 24 }}>
<Form.Item required label="监控分组">
<Input onChange={e => store.record.group = e.target.value} />
</Form.Item>
</Form>
),
onOk: () => {
if (store.record.group) {
store.groups.push(store.record.group);
}
},
})
} }
const SiteBefore = ( const SiteBefore = (
@ -58,13 +79,13 @@ export default observer(function () {
) )
function canNext() { function canNext() {
const {type, addr, extra, domain} = store.record; const { type, addr, extra, domain, group } = store.record;
if (type === '1') { if (type === '1') {
return name && domain return name && domain && group
} else if (type === '5') { } else if (type === '5') {
return name && addr return name && addr && group
} else { } else {
return name && addr && extra return name && addr && extra && group
} }
} }
@ -78,7 +99,7 @@ export default observer(function () {
return t.includes(store.record.type) ? { display: 'flex' } : { display: 'none' } return t.includes(store.record.type) ? { display: 'flex' } : { display: 'none' }
} }
const {name, desc, type, addr, extra, domain} = store.record; const { name, desc, type, addr, extra, domain, group } = store.record;
return ( return (
<Form labelCol={{ span: 6 }} wrapperCol={{ span: 14 }}> <Form labelCol={{ span: 6 }} wrapperCol={{ span: 14 }}>
<Form.Item label="监控类型" help={helpMap[type]}> <Form.Item label="监控类型" help={helpMap[type]}>
@ -90,8 +111,20 @@ export default observer(function () {
<Select.Option value="4">自定义脚本</Select.Option> <Select.Option value="4">自定义脚本</Select.Option>
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item required label="任务名称"> <Form.Item required label="监控分组" style={{ marginBottom: 0 }}>
<Input value={name} onChange={e => store.record.name = e.target.value} placeholder="请输入任务名称"/> <Form.Item style={{ display: 'inline-block', width: 'calc(75%)', marginRight: 8 }}>
<Select value={group} placeholder="请选择监控分组" onChange={v => store.record.group = v}>
{store.groups.map(item => (
<Select.Option value={item} key={item}>{item}</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item style={{ display: 'inline-block', width: 'calc(25%-8px)' }}>
<Button type="link" onClick={handleAddGroup}>添加分组</Button>
</Form.Item>
</Form.Item>
<Form.Item required label="监控名称">
<Input value={name} onChange={e => store.record.name = e.target.value} placeholder="请输入监控名称" />
</Form.Item> </Form.Item>
<Form.Item required label="监控地址" style={getStyle(['1'])}> <Form.Item required label="监控地址" style={getStyle(['1'])}>
<Input <Input

View File

@ -34,7 +34,7 @@ export default observer(function () {
function handleSubmit() { function handleSubmit() {
setLoading(true) setLoading(true)
const formData = form.getFieldsValue(); const formData = form.getFieldsValue();
Object.assign(formData, lds.pick(store.record, ['id', 'name', 'desc', 'addr', 'extra', 'type'])) Object.assign(formData, lds.pick(store.record, ['id', 'name', 'desc', 'addr', 'extra', 'type', 'group']))
formData['id'] = store.record.id; formData['id'] = store.record.id;
http.post('/api/monitor/', formData) http.post('/api/monitor/', formData)
.then(() => { .then(() => {

View File

@ -96,7 +96,8 @@ class ComTable extends React.Component {
showTotal: total => `${total}`, showTotal: total => `${total}`,
pageSizeOptions: ['10', '20', '50', '100'] pageSizeOptions: ['10', '20', '50', '100']
}}> }}>
<Table.Column title="任务名称" dataIndex="name"/> <Table.Column title="监控分组" dataIndex="group" />
<Table.Column title="监控名称" dataIndex="name"/>
<Table.Column title="类型" dataIndex="type_alias"/> <Table.Column title="类型" dataIndex="type_alias"/>
<Table.Column ellipsis title="地址" render={info => { <Table.Column ellipsis title="地址" render={info => {
if ('34'.includes(info.type)) { if ('34'.includes(info.type)) {

View File

@ -19,7 +19,14 @@ export default observer(function () {
<Breadcrumb.Item>监控中心</Breadcrumb.Item> <Breadcrumb.Item>监控中心</Breadcrumb.Item>
</Breadcrumb> </Breadcrumb>
<SearchForm> <SearchForm>
<SearchForm.Item span={7} title="任务名称"> <SearchForm.Item span={7} title="监控分组">
<Select allowClear value={store.f_group} onChange={v => store.f_group = v} placeholder="请选择">
{store.groups.map(item => (
<Select.Option value={item} key={item}>{item}</Select.Option>
))}
</Select>
</SearchForm.Item>
<SearchForm.Item span={7} title="监控名称">
<Input allowClear value={store.f_name} onChange={e => store.f_name = e.target.value} placeholder="请输入"/> <Input allowClear value={store.f_name} onChange={e => store.f_name = e.target.value} placeholder="请输入"/>
</SearchForm.Item> </SearchForm.Item>
<SearchForm.Item span={7} title="检测类型"> <SearchForm.Item span={7} title="检测类型">

View File

@ -12,6 +12,7 @@ class Store {
@observable records = []; @observable records = [];
@observable record = {}; @observable record = {};
@observable types = []; @observable types = [];
@observable groups = [];
@observable page = 0; @observable page = 0;
@observable isFetching = false; @observable isFetching = false;
@observable formVisible = false; @observable formVisible = false;
@ -20,12 +21,14 @@ class Store {
@observable f_type; @observable f_type;
@observable f_status; @observable f_status;
@observable f_active = ''; @observable f_active = '';
@observable f_group;
@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 => x.name.toLowerCase().includes(this.f_name.toLowerCase()));
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_status !== undefined) { if (this.f_status !== undefined) {
if (this.f_status === -1) { if (this.f_status === -1) {
records = records.filter(x => x.is_active && !x.latest_status_alias); records = records.filter(x => x.is_active && !x.latest_status_alias);
@ -39,16 +42,17 @@ class Store {
fetchRecords = () => { fetchRecords = () => {
this.isFetching = true; this.isFetching = true;
http.get('/api/monitor/') http.get('/api/monitor/')
.then(res => { .then(({groups, detections}) => {
const tmp = new Set(); const tmp = new Set();
res.map(item => { detections.map(item => {
tmp.add(item['type_alias']); tmp.add(item['type_alias']);
const value = item['latest_run_time']; const value = item['latest_run_time'];
item['latest_run_time_alias'] = value ? moment(value).fromNow() : null; item['latest_run_time_alias'] = value ? moment(value).fromNow() : null;
return null return null
}); });
this.types = Array.from(tmp); this.types = Array.from(tmp);
this.records = res this.records = detections;
this.groups = groups;
}) })
.finally(() => this.isFetching = false) .finally(() => this.isFetching = false)
}; };