保持无logo

This commit is contained in:
吴亚丹 2022-04-11 13:48:57 +08:00
commit 50748d1972
19 changed files with 545 additions and 450 deletions

View File

@ -7,7 +7,7 @@ import subprocess
from apps.host.models import HostModel
from lib.ssh import SSH
from apps.task.models import JobModel
from sysom import settings
from django.conf import settings
class SshJob:

View File

@ -19,7 +19,11 @@ from lib.ssh import SSH
logger = logging.getLogger(__name__)
job_defaults = {'max_instances': 10}
job_defaults = {
'max_instances': 10,
'misfire_grace_time': None,
'coalesce': True,
}
scheduler = BackgroundScheduler(job_defaults=job_defaults)
scheduler.start()

View File

@ -5,7 +5,7 @@ const Settings = {
contentWidth: 'Fluid',
fixedHeader: true,
fixSiderbar: true,
title: '统信有幄UMOP',
logo: '/logo.png',
title: '系统运维平台',
logo: null,
};
export default Settings;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@ -25,24 +25,6 @@ body,
margin: 0;
}
.ant-pro-top-nav-header-logo h1{
color: rgba(255, 255, 255, 0.65);
line-height: 48px;
font-size: 15px;
font-weight: bold;
}
.ant-pro-top-nav-header-logo img{
padding-right:20px;
height:15px;
vertical-align: text-top;
border-right: 1px solid rgba(255, 255, 255, 0.65);
}
.ant-pro-top-nav-header-menu{
margin-left: 50px;
}
canvas {
display: block;
}

View File

@ -2,4 +2,14 @@ export default {
'component.tagSelect.expand': '展开',
'component.tagSelect.collapse': '收起',
'component.tagSelect.all': '全部',
'component.ListCard.needed_to_repair': '需要修复的漏洞(CVE)',
'component.ListCard.high_needed_to_repair': '需要修复的高危漏洞(CVE)',
'component.ListCard.hosts_with_vul': '存在漏洞的主机',
'component.ListCard.today_repaired': '今日已修复漏洞',
'component.ListCard.cumulate_repaired': '累计已修复漏洞',
'component.ListCard.latest_scan_time': '最新扫描时间',
'component.ListCard.scan': '一键扫描',
'component.ListCard.scanning': '扫描中',
'component.ListCard.success': '扫描成功',
'component.ListCard.failed': '扫描失败'
};

View File

@ -66,6 +66,35 @@ export default {
'pages.journal.audit.login': '登录行为',
'pages.journal.audit.action': '操作行为',
'pages.journal.audit.response_status': '返回状态',
'pages.journal.task.task_id': '任务ID',
'pages.journal.task.status': '状态',
'pages.journal.task.params': '参数列表',
'pages.journal.task.success': '成功',
'pages.journal.task.fail': '失败',
'pages.security.list.index':'序号',
'pages.security.list.cve_id':'编号',
'pages.security.list.pub_time':'发布时间',
'pages.security.list.vul_level':'漏洞等级',
'pages.security.list.hosts':'涉及主机',
'pages.security.list.operation':'操作',
'pages.security.list.high':'高危',
'pages.security.list.medium':'中危',
'pages.security.list.critical':'严重',
'pages.security.list.low':'低危',
'pages.security.list.repair':'修复',
'pages.security.list.confirm':'确认修复吗',
'pages.security.list.re':'正在修复中...',
'pages.security.list.error':'修复出错了,',
'pages.security.list.details':'查看详情,',
'pages.security.Homelist.name':'软件名称',
'pages.security.Homelist.vul_level':'严重程度',
'pages.security.Homelist.fixed_version':'修复版本',
'pages.security.Homelist.hostname':'主机名称',
'pages.security.Homelist.ip':'IP地址',
'pages.security.Homelist.created_by':'用户',
'pages.security.Homelist.created_at':'创建时间',
'pages.security.Homelist.status':'主机状态',
'pages.security.Homelist.re':'修复中',
'pages.security.Historical.title': '历史修复漏洞信息',
'pages.security.Historical.id': '序号',
'pages.security.Historical.cve_id': 'cve编号',
@ -84,11 +113,5 @@ export default {
'pages.security.Historical.fail': '失败',
'pages.security.Historical.fix_details': 'CVE修复详情',
'pages.security.Historical.fix_success': 'CVE修复成功',
'pages.security.Historical.fix_fail': 'CVE修复失败失败原因',
'pages.journal.task.task_id': '任务ID',
'pages.journal.task.status': '状态',
'pages.journal.task.params': '参数列表',
'pages.journal.task.success': '成功',
'pages.journal.task.fail': '失败',
};
'pages.security.Historical.fix_fail': 'CVE修复失败失败原因'
};

View File

@ -0,0 +1,177 @@
import { useRef ,useState} from 'react';
import { useIntl, FormattedMessage ,history} from 'umi';
import { Button,Modal,Progress,Card,Row,Col} from 'antd';
import ProCard from '@ant-design/pro-card';
import ProTable from '@ant-design/pro-table';
import "./homelist.less";
import {getOneById,manyApi} from '../service'
const Cvetable=(params)=> {
const request=async()=>{
const msg=await getOneById(params.id);
msg.data = [...msg.setlovodata]
return msg
}
const [succesvisible, setsuccesvisible] = useState(false);
const [errvisible, seterrvisible] = useState(false);
const [vlue,setCount]=useState(0)
const [selectedRowKeys, setselectedRowKeys] = useState(0);
const [selectedRows,setselectedRows]=useState(0)
const rowSelection = {
onChange: (selectedRowKeys,selectedRows) => {
setselectedRowKeys(selectedRowKeys)
setselectedRows(selectedRows)
},
};
const columns=[
{
title: <FormattedMessage id="pages.security.list.index" defaultMessage="index" />,
dataIndex: 'index',
align: "center",
hideInSearch: true,
render: (txt, record, index) => index + 1,
},
{
title:<FormattedMessage id="pages.security.Homelist.hostname" defaultMessage="hostname" />,
dataIndex:'hostname',
},
{
title:<FormattedMessage id="pages.security.Homelist.ip" defaultMessage="ip" />,
dataIndex:"ip",
},
{
title:<FormattedMessage id="pages.security.Homelist.created_by" defaultMessage="created_by" />,
dataIndex:"created_by",
},
{
title:<FormattedMessage id="pages.security.Homelist.created_at" defaultMessage="created_at" />,
dataIndex:"created_at",
},
{
title:<FormattedMessage id="pages.security.Homelist.status" defaultMessage="status" />,
dataIndex:"status",
align: "center",
render: (txt, record) => {
if (record.status === "running") {
return <div className="numbersuccess">
<FormattedMessage id="pages.hostTable.status.running" defaultMessage="Running" />
</div>
} else if(record.status === "offline"){
return <div className="numbererr">
<FormattedMessage id="pages.hostTable.status.offline" defaultMessage="Offline" />
</div>
}else{
return <div className="numbererr">
<FormattedMessage id="pages.hostTable.status.abnormal" defaultMessage="Offline" />
</div>
}
}
},
{
title: <FormattedMessage id="pages.security.list.operation" defaultMessage="operation" />,
dataIndex: "option",
align: "center",
valueType: "option",
render: (_, record) => [
<a key="showDetail" onClick={async()=>{
setsuccesvisible(true)
seterrvisible(false)
const time =setInterval(()=>{
setCount(vlue=>vlue+1);
},2500)
const arry=[];
const id=params.id
arry.push({"cve_id":id, "hostname":[record.hostname ]})
const msg=await manyApi({cve_id_list:arry});
if(msg){
setsuccesvisible(true)
setCount(99);
clearInterval(time)
if(msg.message=="fix cve failed"){
seterrvisible(true)
setsuccesvisible(false);
setCount(0);
}else{
setTimeout(() => {
history.push("/security/list")
}, 1000);
}
}
}}>
{<FormattedMessage id="pages.security.list.repair" defaultMessage="repair" />}
</a>,
],
},
]
const repair=async()=>{
const arry=[];
const leght =selectedRows.length;
if(leght>0){
setsuccesvisible(true)
seterrvisible(false)
const time =setInterval(()=>{
setCount(vlue=>vlue+1);
},2500)
const id=params.id
for(let i = 0; i < leght; i++){
arry.push({"cve_id":id, "hostname":[selectedRows[i].hostname ]})
}
const msg=await manyApi({cve_id_list:arry});
if(msg){
setsuccesvisible(true)
setCount(99);
clearInterval(time)
if(msg.message=="fix cve failed"){
seterrvisible(true)
setsuccesvisible(false);
setCount(0);
}else{
setTimeout(() => {
history.push("/security/list")
}, 1000);
}
}
}
}
const [flags,setflags]=useState(false)
const cancel=()=>{
if(succesvisible==true){
setflags(true)
}else{
history.push("/security/list")
}
}
return (
<>
<ProTable
rowKey="hostname"
columns={columns}
search={false}
request={request}
rowSelection={rowSelection}
/>
<ProCard>
<Row>
<Col span={13}>
{succesvisible?( <p>修复中< Progress width={40} percent={vlue} size="small" /></p>):null}
{errvisible?(<p>修复出错了<Button type="link" size="small" href={"/security/historical" }>查看详情</Button></p>):null}
</Col>
<Col span={11}>
<Row className="allbtn">
<Col><Button type="primary" onClick={repair}>一键修复</Button></Col>
<Col style={{'line-height':'58px'}}><Button disabled={flags} onClick={cancel} style={{'margin-right':'10px'}}>返回</Button></Col>
</Row>
</Col>
</Row>
</ProCard>
</>
);
}
export default Cvetable;

View File

@ -0,0 +1,51 @@
import { useRef, useState } from "react";
import { useIntl, FormattedMessage } from "umi";
import ProTable from "@ant-design/pro-table";
import {getOneById} from '../service'
import "./homelist.less";
const Toptable = (params) => {
console.log(params.id)
const request=async()=>{
const msg=await getOneById(params.id);
msg.data = [...msg.setdata]
return msg
}
const columns=[
{
title:<FormattedMessage id="pages.security.Homelist.name" defaultMessage="name" />,
dataIndex:'name',
align: "center",
},
{
title:<FormattedMessage id="pages.security.Homelist.vul_level" defaultMessage="vul_level" />,
dataIndex:"vul_level",
key:"vul_level",
},
{
title:<FormattedMessage id="pages.security.Homelist.fixed_version" defaultMessage="fixed_version" />,
dataIndex:"fixed_version",
key:"fixed_version",
}
]
return (
<div>
<ProTable
columns={columns}
search={false}
scroll={{ y: 200 }}
rowKey="fixed_version"
request={request}
headerTitle={params.id}
pagination={false}
/>
</div>
);
};
export default Toptable;

View File

@ -3,15 +3,18 @@
margin-bottom: 20px;
}
.numbersuccess{
color: palegreen;
}
.numbererr{
color: red
}
.ant-card-body{
padding-bottom: 0px;
}
.allbtn{
display:flex;
flex-direction:row-reverse;
align-items: center;
}
// .numbersuccess{
// color: palegreen;
// }
// .numbererr{
// color: red
// }
}

View File

@ -1,207 +1,22 @@
import React ,{useState,useEffect}from 'react';
import { Card, Table, Button,Progress,Row, Col} from "antd";
import './homelist.less'
import { useRef ,useState} from 'react';
import { useIntl, FormattedMessage } from 'umi';
import ProCard from '@ant-design/pro-card';
import { PageContainer } from '@ant-design/pro-layout';
import Toptable from './Toptable'
import Cvetable from './Cvetable'
import './homelist.less'
import {getOneById,manyApi} from '../service'
import Headcard from "../components/Headcard";
function index(props) {
const [data,setdata]=useState([])
const [lovodata,setlovodata]=useState([])
const [total,setTotal]=useState(0)
const [selectedRowKeys, setselectedRowKeys] = useState([]);
const [selectedRows, setselectedRows] = useState([]);
const [title,settitle]=useState("")
const [vlue,setCount]=useState(0)
useEffect(async()=>{
const msg=await getOneById(props.match.params.id);
setlovodata(msg.setlovodata)
setdata(msg.setdata)
settitle(msg.title)
},[])
const[succesvisible,setsuccesvisible]=useState(false);
const [errvisible,seterrvisible]=useState(false)
const fn = () => {
props.history.push("/security/historical");
};
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys, selectedRows) => {
setselectedRowKeys(selectedRowKeys);
setselectedRows(selectedRows);
},
};
const columns=[
{
title:"软件名称",
dataIndex:'name',
key:'name'
},
{
title:"严重程度",
dataIndex:"vul_level",
key:"vul_level",
},
{
title:"修复版本",
dataIndex:"fixed_version",
key:"fixed_version",
}
]
const lnvohost=[
{
title: "序号",
key: "id",
width: 80,
align: "center",
render: (txt, record, index) => index + 1,
},
{
title:"主机名称",
dataIndex:'hostname',
key:'hostname'
},
{
title:"IP地址",
dataIndex:"ip",
key:"ip",
},
{
title:"用户",
dataIndex:"created_by",
key:"created_by",
},
{
title:"创建时间",
dataIndex:"created_at",
key:"created_at",
},
{
title:"主机状态",
dataIndex:"status",
key:"status",
render:(txt,record)=>{
if(record.status==="running"){
return <div className="numbersuccess">运行中</div>
}else{
return <div className="numbererr">离线</div>
}
}
},{
title:"操作",
render:(txt,record,index)=>{
return (
<div>
<Button type="link" onClick={async()=>{
setsuccesvisible(true)
seterrvisible(false)
const time =setInterval(()=>{
setCount(vlue=>vlue+1);
},2500)
const arry=[];
const id=props.match.params.id
arry.push({"cve_id":id, "hostname":[record.hostname ]})
const msg=await manyApi({cve_id_list:arry});
if(msg){
setsuccesvisible(true)
setCount(99);
clearInterval(time)
if(msg.message=="fix cve failed"){
seterrvisible(true)
setsuccesvisible(false);
setCount(0);
}else{
setTimeout(() => {
props.history.push("/security/list")
}, 1000);
}
}
}}>修复</Button>
</div>
)
}
}
]
const repair=async()=>{
const arry=[];
const leght =selectedRows.length;
if(leght>0){
setsuccesvisible(true)
seterrvisible(false)
const time =setInterval(()=>{
setCount(vlue=>vlue+1);
},2500)
const id=props.match.params.id
for(let i = 0; i < leght; i++){
arry.push({"cve_id":id, "hostname":[selectedRows[i].hostname ]})
}
const msg=await manyApi({cve_id_list:arry});
if(msg){
setsuccesvisible(true)
setCount(99);
clearInterval(time)
if(msg.message=="fix cve failed"){
seterrvisible(true)
setsuccesvisible(false);
setCount(0);
}else{
setTimeout(() => {
props.history.push("/security/list")
}, 1000);
}
}
}
}
const paginationProps = {
showSizeChanger: true,
showQuickJumper: true,
total: total, //
pageSizeOptions: [10,20,50,100] ,
defaultPageSize:20,
// current: pageNum, //
showTotal: ((total,ranage) => `${total}`),
position:["bottomRight"],
// size:"small"
};
return (
<div>
<PageContainer>
<Headcard paren={fn} isShow={true} upData={false}/>
<Card className="list-table" title={title}>
<Table size="small" pagination={false} scroll={{ y: 100 }} rowKey="fixed_version" columns={columns} dataSource={data} />
</Card>
<Card title="涉及主机" className="lnvohost">
<Table rowKey="hostname" size="small" rowSelection={rowSelection} pagination={ paginationProps} columns={lnvohost} dataSource={lovodata}> </Table>
<Row>
<Col span={13}>
{succesvisible?( <p>修复中< Progress width={40} percent={vlue} size="small" /></p>):null}
{errvisible?(<p>恢复出错了<Button type="link" size="small" onClick={()=>props.history.push('/security/historical')}>查看详情</Button></p>):null}
</Col>
<Col span={11}>
<Row className="allbtn">
<Col><Button type="primary" onClick={repair}>一键修复</Button></Col>
<Col style={{'line-height':'58px'}}><Button onClick={()=>{ props.history.push("/security/list") }} style={{'margin-right':'10px'}}>取消</Button></Col>
</Row>
</Col>
</Row>
</Card>
</PageContainer>
</div>
const { Divider } = ProCard;
const Homelist=(props)=> {
const id=props.match.params.id
return (
<PageContainer>
<Divider/>
<Toptable id={id}/>
<Divider/>
<Cvetable id={id}/>
</PageContainer>
);
}
export default index;
export default Homelist;

View File

@ -1,39 +1,46 @@
import React, { useState, useEffect, useRef } from "react";
import { Card, Table, Button, Progress, Modal, Tooltip, message, } from "antd";
import { useRef ,useState} from 'react';
import { useIntl, FormattedMessage } from 'umi';
import ProCard from '@ant-design/pro-card';
import { PageContainer } from '@ant-design/pro-layout';
import { Button,Modal,Progress} from 'antd';
import ProTable from '@ant-design/pro-table';
import Restoration from "../components/restoration"
import ListCard from '../components/ListCard'
import "./list.less";
import { listApi, manyApi, updataApi } from "../service";
import { PageContainer } from "@ant-design/pro-layout";
import Headcard from "../components/Headcard";
import { listApi, manyApi } from "../service";
function List(props) {
// console.log(props)
const [data, setdata] = useState([]);
useEffect(async () => {
const msg = await listApi();
setdata(msg.data);
}, []);
const { Divider } = ProCard;
const List=(props)=> {
const actionRef = useRef();
const intl = useIntl();
const fn = () => {
props.history.push("/security/historical");
};
const [selectedRowKeys, setselectedRowKeys] = useState(0);
const [selectedRows,setselectedRows]=useState(0)
const rowSelection = {
onChange: (selectedRowKeys,selectedRows) => {
setselectedRowKeys(selectedRowKeys)
setselectedRows(selectedRows)
},
};
const [isModalVisible, setIsModalVisible] = useState(false);
const [succesvisible, setsuccesvisible] = useState(false);
const [errvisible, seterrvisible] = useState(false);
const [vlue, setCount] = useState(0);
const [huan,sethuan]=useState(false)
const showModal = () => {
const leght = selectedRows.length;
if (leght > 0) {
const leght = selectedRows.length;
if (leght > 0) {
setIsModalVisible(true);
}
};
const handleOk = async () => {
const time = setInterval(() => {
setCount((vlue) => vlue + 1);
}, 2500);
}, 4500);
setIsModalVisible(false);
setsuccesvisible(true);
const arry = [];
@ -44,7 +51,7 @@ function List(props) {
hostname: selectedRows[i].hosts,
});
}
const msg = await manyApi({ cve_id_list: arry });
const msg = await manyApi({ cve_id_list: arry });
if (msg) {
setIsModalVisible(false);
setsuccesvisible(true);
@ -63,73 +70,67 @@ function List(props) {
const handleCancel = () => {
setIsModalVisible(false);
};
const geng=async()=>{
sethuan(true)
const msg = await updataApi();
console.log(msg)
if(msg.message=="success"){
sethuan(false)
props.history.push("/security");
}else if(msg.message=="forbidden"){
sethuan(false)
message.warning('操作频率过快,请稍后再试!');
}
}
const columns = [
{
title: "序号",
key: "index",
width: 80,
title: <FormattedMessage id="pages.security.list.index" defaultMessage="index" />,
dataIndex: 'index',
align: "center",
hideInSearch: true,
render: (txt, record, index) => index + 1,
},
{
title: "编号",
dataIndex: "cve_id",
key: "cve_id",
title: <FormattedMessage id="pages.security.list.cve_id" defaultMessage="cve_id" />,
dataIndex: 'cve_id',
align: "center",
hideInSearch: true
},
{
title: "发布时间",
dataIndex: "pub_time",
key: "pub_time",
title: <FormattedMessage id="pages.security.list.pub_time" defaultMessage="pub_time" />,
dataIndex: 'pub_time',
valueType: 'dateTime',
align: "center",
sorter: (a, b) => a.pub_time.length - b.pub_time.length,
hideInSearch: true,
sorter: (a, b) => a.pub_time - b.pub_time,
},
{
title: "漏洞等级",
dataIndex: "vul_level",
key: "vul_level",
title: <FormattedMessage id="pages.security.list.vul_level" defaultMessage="vul_level" />,
dataIndex: 'vul_level',
align: "center",
render: (txt, record) => {
if (record.vul_level == "high") {
return <div>高危</div>;
} else if (record.vul_level == "medium") {
return <div>中危</div>;
} else if (record.vul_level == "critical") {
return <div>严重</div>;
} else if (record.vul_level == "low") {
return <div>低危</div>;
} else if (record.vul_level == "") {
return <div></div>;
}
filters: true,
onFilter: true,
hideInSearch: true,
valueEnum: {
high: {
text: (
<FormattedMessage id="pages.security.list.high" defaultMessage="high" />
),
},
medium: {
text: (
<FormattedMessage id="pages.security.list.medium" defaultMessage="medium" />
),
},
critical: {
text: (
<FormattedMessage id="pages.security.list.critical" defaultMessage="critical" />
),
},
low: {
text: (
<FormattedMessage id="pages.security.list.low" defaultMessage="low" />
),
},
},
filters: [
{ text: "严重", value: "critical" },
{ text: "高危", value: "high" },
{ text: "中危", value: "medium" },
{ text: "低危", value: "low" },
],
onFilter: (value, record) => record.vul_level.includes(value),
},
{
title: <FormattedMessage id="pages.security.list.hosts" defaultMessage="hosts" />,
dataIndex: 'hosts',
width: "20%",
title: "涉及主机",
align: "center",
dataIndex: "hosts",
key: "hosts",
valueType: 'select',
hideInSearch: true,
onCell: () => {
return {
style: {
@ -141,105 +142,62 @@ function List(props) {
},
};
},
render: (text) => (
<span placement="topLeft" title={text}>
{text.toString()}
render: (_,record,text) => (
<span placement="topLeft" title={record.hosts.toString()} >
{record.hosts.toString()}
</span>
),
},
{
title: "操作",
title: <FormattedMessage id="pages.security.list.operation" defaultMessage="operation" />,
dataIndex: "option",
align: "center",
render: (txt, record, index) => {
return (
<div>
<Button
type="link"
onClick={() =>
props.history.push(`/security/homelist/${record.cve_id}`)
}
>
{" "}
修复{" "}
</Button>
</div>
);
},
valueType: "option",
render: (_, record) => [
<a key="showDetail" href={"/security/homelist/" + record.cve_id}>
{<FormattedMessage id="pages.security.list.repair" defaultMessage="repair" />}
</a>,
],
},
];
const [selectedRowKeys, setselectedRowKeys] = useState(0);
const [selectedRows, setselectedRows] = useState(0);
const [total, setTotal] = useState(0);
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys, selectedRows) => {
setselectedRowKeys(selectedRowKeys);
setselectedRows(selectedRows);
},
};
const paginationProps = {
showSizeChanger: true,
showQuickJumper: true,
total: total, //
pageSizeOptions: [10, 20, 50, 100],
defaultPageSize: 20,
// current: pageNum, //
showTotal: (total, ranage) => `${total}`,
position: ["bottomRight"],
// size:"small"
};
return (
<div>
<PageContainer>
<Headcard paren={fn} isShow={true} geng={geng} quan={huan} upData={true}/>
<Card
className="list-table"
extra={
<Button type="primary" size="small" onClick={showModal}>
修复
</Button>
}
>
<Table
rowSelection={rowSelection}
rowKey="cve_id"
columns={columns}
dataSource={data}
size="small"
pagination={paginationProps}
/>
<Modal
width={320}
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
centered={true}
>
<p className="stop">确定修复吗</p>
<div>
<PageContainer>
<ListCard refreshTable={listApi} />
<Divider />
<ProTable rowKey="cve_id" columns={columns} search={false} request={listApi}
toolBarRender={() => [
<Restoration paren={fn}/>,
<Button type="primary" key="primary" onClick={showModal}>
{<FormattedMessage id="pages.security.list.repair" defaultMessage="repair" />}
</Button>
]}
rowSelection={rowSelection}
/>
<Modal width={320} visible={isModalVisible} onOk={handleOk} onCancel={handleCancel} centered={true}>
<p className="stop">
{<FormattedMessage id="pages.security.list.confirm" defaultMessage="confirm" />}
</p>
</Modal>
<Modal
width={320}
visible={succesvisible}
footer={null}
centered={true}
<Modal width={320} visible={succesvisible} footer={null} centered={true}
>
<p> 正在修复中...</p>
<p> {<FormattedMessage id="pages.security.list.re" defaultMessage="re" />}</p>
<Progress percent={vlue} size="small" />
</Modal>
<Modal width={320} visible={errvisible} footer={null} centered={true}>
<p>
恢复出错了
<Button
type="link"
size="small"
<p> {<FormattedMessage id="pages.security.list.error" defaultMessage="error" />}
<Button type="link" size="small"
onClick={() => props.history.push("/security/historical")}
>
查看详情
{<FormattedMessage id="pages.security.list.details" defaultMessage="details" />}
</Button>
</p>
</Modal>
</Card>
</PageContainer>
</PageContainer>
</div>
);
}

View File

@ -4,6 +4,7 @@
.blue{
width: 20px;
height: 20px;
background: blue;
}
.tan{
position: relative;
@ -11,6 +12,13 @@ height: 20px;
width: 200px;
}
// .waring{
// width: 25px;
// height: 25px;
// background-image: url(../../../../public/icons/waring.png);
// background-repeat:no-repeat;
// }
.ant-modal-body{
p{
@ -21,9 +29,4 @@ height: 20px;
}
}
.Ooylined{
float:right;
}

View File

@ -4,7 +4,6 @@ import { Button, Row, Col } from "antd";
import "./Viewdetails.less";
import { viewApi, summaryApi } from "../service";
import { PageContainer } from "@ant-design/pro-layout";
import Headcard from "../components/Headcard";
import ProCard from "@ant-design/pro-card";
function index(props) {
@ -30,7 +29,6 @@ function index(props) {
return (
<div>
<PageContainer>
{/* <Headcard paren={fn} isShow={false} upData={false} /> */}
<ProCard className="card_result">
<h3> <span>
<FormattedMessage id="pages.hostTable.hostname" defaultMessage="Hostname" />
@ -56,4 +54,4 @@ function index(props) {
);
}
export default index;
export default index;

View File

@ -1,41 +0,0 @@
import React,{useState,useEffect} from 'react';
import { Card, Button,Row,Col} from "antd";
import {summaryApi} from '../service'
import {SyncOutlined} from '@ant-design/icons';
import '../List/list.less'
function Headcard(param) {
console.log(param)
const [affectcount,setaffectcount]=useState(0);
const [cvecount,setcvecount]=useState(0);
const [higtcount,sethigtcount]=useState(0)
useEffect(async() => {
const msg=await summaryApi();
setaffectcount(msg.affect)
setcvecount(msg.cvecount)
sethigtcount(msg.highcount)
}, []);
return (
<div>
<Card>
<Row>
<Col span={20}>
<span>{affectcount}台主机存在被攻击风险涉及CVE漏洞{cvecount}其中高危漏洞{higtcount}请尽快修复</span>
{param.isShow?(<Button type="link" onClick={param.paren}>历史修复</Button>):""}
{param.upData?(<Button type="link" onClick={param.geng}>更新</Button>):""}
</Col>
<Col span={4}>
{param.quan?( < SyncOutlined className="Ooylined" style={{fontSize:'22px',}} spin />):""}
</Col>
</Row>
</Card>
</div>
);
}
export default Headcard;

View File

@ -0,0 +1,99 @@
import { Statistic ,Button, message} from 'antd';
import { useState, useEffect } from 'react';
import { useIntl, FormattedMessage } from 'umi';
import ProCard from '@ant-design/pro-card';
import RcResizeObserver from 'rc-resize-observer';
import {summaryApi,updataApi} from '../service'
const { Divider } = ProCard;
import '../List/list.less'
import { size } from 'lodash-es';
const ListCard=(props)=> {
const intl = useIntl();
const [responsive, setResponsive] = useState(false);
const [complete, setComplete] = useState(false);
const [StatisticList, setStatisticList] = useState()
const getSummary = async() => {
setComplete(true);
let msg=await summaryApi();
if(msg){
setComplete(false);
if(msg.success){
message.success(intl.formatMessage({id:'component.ListCard.success',defaultMessage:'Scan success'}));
setStatisticList(msg.data.fixed_cve)
props.refreshTable();
}else{
message.error(intl.formatMessage({id:'component.ListCard.failed',defaultMessage:'Scan failed'}));
}
}
}
useEffect(async() => {
let msg=await summaryApi();
if(msg.success)
setStatisticList(msg.data.fixed_cve)
}, []);
return (
<RcResizeObserver
key="resize-observer"
onResize={(offset) => {
setResponsive(offset.width < 596);
}}>
<ProCard.Group direction={responsive ? 'column' : 'row'}>
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.needed_to_repair',
defaultMessage: 'Need to repair',
})}
value={StatisticList?.cve_count} valueStyle={{ color: "red", textAlign:'center' }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.high_needed_to_repair',
defaultMessage: 'High-risk need to Repair',
})}
value={StatisticList?.high_cve_count} valueStyle={{ color: "red", textAlign:'center' }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.hosts_with_vul',
defaultMessage: 'Hosts with vulnerabilities',
})}
value={StatisticList?.affect_host_count} valueStyle={{ color: "red", textAlign:'center' }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.today_repaired',
defaultMessage: 'Today has been repaired',
})}
value={StatisticList?.cvefix_today_count} valueStyle={{ color: "red", textAlign:'center' }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.cumulate_repaired',
defaultMessage: 'Cumulative revision',
})}
value={StatisticList?.cvefix_all_count} valueStyle={{ color: "red",textAlign:'center' }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title={intl.formatMessage({
id: 'component.ListCard.latest_scan_time',
defaultMessage: 'Latest scan time',
})}
value={StatisticList?.latest_scan_time} valueStyle={{ color: "white",fontSize:13,whiteSpace:'nowrap',textAlign:'center' }} />
</ProCard>
<ProCard>
<Button onClick={getSummary} type="primary" loading={complete}>{complete ? <FormattedMessage id="component.ListCard.scanning" defaultMessage="Scanning" /> : <FormattedMessage id="component.ListCard.scan" defaultMessage="Scan" />}</Button>
</ProCard>
</ProCard.Group>
</RcResizeObserver>
);
}
export default ListCard;

View File

@ -0,0 +1,12 @@
import { Button, message } from "antd";
const restoration=(param)=> {
// console.log(param)
return (
<div>
<Button type="primary" key="primary" onClick={param.paren}>历史修复</Button>
</div>
);
}
export default restoration;

View File

@ -18,7 +18,7 @@ const token = localStorage.getItem('token');
}
export async function summaryApi(options) {
const msg= await request('/api/v1/vul/summary', {
const msg= await request('/api/v1/vul/summary/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@ -27,12 +27,13 @@ const token = localStorage.getItem('token');
...(options || {}),
});
return {
affect:msg.data.fixed_cve.affect_host_count,
cvecount:msg.data.fixed_cve.cve_count,
highcount:msg.data.fixed_cve.high_cve_count
}
return msg;
}
// {
// affect:msg.data.fixed_cve.affect_host_count,
// cvecount:msg.data.fixed_cve.cve_count,
// highcount:msg.data.fixed_cve.high_cve_count
// }
@ -58,9 +59,9 @@ const token = localStorage.getItem('token');
},
...(options || {}),
});
msg.data.data = [...msg.data.hosts_datail];
msg.data.data = [...msg.data.hosts_datail];
return msg.data;
};
}
export async function getOneById(id,options) {
@ -79,7 +80,7 @@ const token = localStorage.getItem('token');
setdata:msg.data.software,
};
};
}
@ -94,7 +95,7 @@ const token = localStorage.getItem('token');
});
return msg;
};
}
export async function manyApi(body, options) {
@ -121,7 +122,7 @@ const token = localStorage.getItem('token');
...(options || {}),
});
return msg
return msg;
}

View File

@ -32,7 +32,7 @@ const VmcoreCard = () => {
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>
<Statistic title="月宕机率" value={StatisticList?.rate_30days} suffix="%" valueStyle={{ color: "red" }} />
<Statistic title="月宕机率" value={StatisticList?.rate_30days} precision={2} suffix="%" valueStyle={{ color: "red" }} />
</ProCard>
<Divider type={responsive ? 'horizontal' : 'vertical'} />
<ProCard>