V2 完成
This commit is contained in:
@@ -4,11 +4,11 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>靶场管理</title>
|
||||
<title>DNS</title>
|
||||
<script type="text/javascript">
|
||||
window.g = {
|
||||
// baseURL:'172.16.0.120:31540', //开发环境
|
||||
baseURL: document.location.host, //正式环境
|
||||
baseURL: '124.221.228.62:2525', //正式环境
|
||||
// queryTags:[],
|
||||
// switchLanguage:"en",
|
||||
switchLanguage:"zh"
|
||||
|
||||
@@ -16,6 +16,7 @@ if (process.env.NODE_ENV == 'development') {
|
||||
// 请求超时时间
|
||||
axios.defaults.timeout = 60000;
|
||||
axios.defaults.headers['Content-Type'] = 'application/json';
|
||||
// axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
// post请求头
|
||||
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
|
||||
// axios.defaults.headers['Access-Control-Allow-Header']='Access-Control-Allow-Origin'
|
||||
@@ -26,11 +27,13 @@ axios.defaults.headers['Content-Type'] = 'application/json';
|
||||
|
||||
|
||||
// // 请求拦截器
|
||||
axios.interceptors.request.use(
|
||||
axios.interceptors.request.use(
|
||||
|
||||
config => {
|
||||
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
|
||||
// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
|
||||
const token = localStorage.getItem('token');
|
||||
// const token = localStorage.getItem('token');
|
||||
const token = "localStorage.getItem('token')";
|
||||
if(token!=''){
|
||||
config.headers['Authorization'] = 'Bearer ' + token
|
||||
}
|
||||
@@ -42,10 +45,10 @@ axios.interceptors.request.use(
|
||||
// if(userId!=''){
|
||||
// config.headers.userId = userId;
|
||||
// }
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
return Promise.error(error);
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
return Promise.error(error);
|
||||
})
|
||||
|
||||
// 响应拦截器
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
export default {
|
||||
api: {
|
||||
//任务管理
|
||||
taskList:'/task/',
|
||||
//任务详情
|
||||
taskInfo:'/task/detail',
|
||||
//任务详情日志
|
||||
taskInfoLog:'/task/tp',
|
||||
//代理信息
|
||||
agentQueryList:'/agent/',
|
||||
//代理删除
|
||||
agentDel:'/agent/del',
|
||||
//目标信息获取
|
||||
targetQueryList:'/target/',
|
||||
targetMap:'target/map',
|
||||
//目标信息筛选基础数据
|
||||
targetFilter:'/target/filter',
|
||||
//目标信息时延
|
||||
targetDelay:'/target/delay',
|
||||
taskOps:'/task/ops',
|
||||
//任务创建
|
||||
taskCreate:'/task/create',
|
||||
taskDel:'/task/del',
|
||||
//仪表盘——num
|
||||
sysNum:'/sys/num',
|
||||
//仪表盘-柱状图数据接口
|
||||
sysNumDate:'/sys/num/date',
|
||||
//仪表盘—系统操作日志
|
||||
sysLog:'sys/log',
|
||||
//系统管理——用户列表 **创建用户也是该接口区别为 获取是get 创建是post**
|
||||
user:'/user/',
|
||||
|
||||
// 登录
|
||||
login: '/token', // 登录
|
||||
getMenus: '/api/user/menu', // 获取菜单
|
||||
@@ -114,5 +144,11 @@ export default {
|
||||
asyncAddImage: '/api/async/image', // 异步新增镜像
|
||||
asyncBuildImage: '/api/async/image/build', // 异步构建镜像
|
||||
|
||||
|
||||
|
||||
//系统管理
|
||||
|
||||
//系统介绍
|
||||
|
||||
},
|
||||
}
|
||||
@@ -1058,5 +1058,191 @@
|
||||
"赞比亚": "ZM",
|
||||
"扎伊尔": "ZR",
|
||||
"津巴布韦": "ZW"
|
||||
}
|
||||
},
|
||||
"countryEtoC":{
|
||||
"AD": "安道尔共和国",
|
||||
"AE" : "阿拉伯联合酋长国",
|
||||
"AF": "阿富汗",
|
||||
"AG": "安提瓜和巴布达",
|
||||
"AI": "安圭拉岛",
|
||||
"AL" : "阿尔巴尼亚",
|
||||
"AM" : "阿美尼亚",
|
||||
"" : "阿森松",
|
||||
"AO" : "安哥拉",
|
||||
"AR": "阿根廷",
|
||||
"AT" : "奥地利",
|
||||
"AU" : "澳大利亚",
|
||||
"AZ" : "阿塞拜疆",
|
||||
"BB" : "巴巴多斯",
|
||||
"BD" : "孟加拉国",
|
||||
"BE" : "比利时",
|
||||
"BF" : "布基纳法索",
|
||||
"BG" : "保加利亚",
|
||||
"BH" : "巴林",
|
||||
"BI" : "布隆迪",
|
||||
"BJ" : "贝宁",
|
||||
"BL" : "巴勒斯坦",
|
||||
"BM" : "百慕大群岛",
|
||||
"BN" : "文莱",
|
||||
"BO" : "玻利维亚",
|
||||
"BR" : "巴西",
|
||||
"BS" : "巴哈马",
|
||||
"BW" : "博茨瓦纳",
|
||||
"BY" : "白俄罗斯",
|
||||
"BZ" : "伯利兹",
|
||||
"CA" : "加拿大",
|
||||
"CF" : "中非共和国",
|
||||
"CG" : "刚果",
|
||||
"CH" : "瑞士",
|
||||
"CK" : "库克群岛",
|
||||
"CL" : "智利",
|
||||
"CM" : "喀麦隆",
|
||||
"CN" : "中国",
|
||||
"CO" : "哥伦比亚",
|
||||
"CR" : "哥斯达黎加",
|
||||
"CZ" : "捷克",
|
||||
"CU" : "古巴",
|
||||
"CY" : "塞浦路斯",
|
||||
"DE" : "德国",
|
||||
"DJ" : "吉布提",
|
||||
"DK" : "丹麦",
|
||||
"DO" : "多米尼加共和国",
|
||||
"DZ" : "阿尔及利亚",
|
||||
"EC" : "厄瓜多尔",
|
||||
"EE" : "爱沙尼亚",
|
||||
"EG" : "埃及",
|
||||
"ES" : "西班牙",
|
||||
"ET" : "埃塞俄比亚",
|
||||
"FI" : "芬兰",
|
||||
"FJ" : "斐济",
|
||||
"FR" : "法国",
|
||||
"GA" : "加蓬",
|
||||
"GB" : "英国",
|
||||
"GD" : "格林纳达",
|
||||
"GE" : "格鲁吉亚",
|
||||
"GF" : "法属圭亚那",
|
||||
"GH" : "加纳",
|
||||
"GI" : "直布罗陀",
|
||||
"GM" : "冈比亚",
|
||||
"GN" : "几内亚",
|
||||
"GR" : "希腊",
|
||||
"GT" : "危地马拉",
|
||||
"GU" : "关岛",
|
||||
"GY" : "圭亚那",
|
||||
"HK" : "中国香港",
|
||||
"HN" : "洪都拉斯",
|
||||
"HT" : "海地",
|
||||
"HU" : "匈牙利",
|
||||
"ID" : "印度尼西亚",
|
||||
"IE" : "爱尔兰",
|
||||
"IL" : "以色列",
|
||||
"IN" : "印度",
|
||||
"IQ" : "伊拉克",
|
||||
"IR" : "伊朗",
|
||||
"IS" : "冰岛",
|
||||
"IT" : "意大利",
|
||||
"JM" : "牙买加",
|
||||
"JO" : "约旦",
|
||||
"JP" : "日本",
|
||||
"KE" : "肯尼亚",
|
||||
"KG" : "吉尔吉斯坦",
|
||||
"KH" : "柬埔寨",
|
||||
"KP" : "朝鲜",
|
||||
"KR" : "韩国",
|
||||
"KT" : "科特迪瓦共和国",
|
||||
"KW" : "科威特",
|
||||
"KZ": "哈萨克斯坦",
|
||||
"LA": "老挝",
|
||||
"LB": "黎巴嫩",
|
||||
"LC": "圣卢西亚",
|
||||
"LI": "列支敦士登",
|
||||
"LK": "斯里兰卡",
|
||||
"LR": "利比里亚",
|
||||
"LS": "莱索托",
|
||||
"LT": "立陶宛",
|
||||
"LU": "卢森堡",
|
||||
"LV": "拉脱维亚",
|
||||
"LY": "利比亚",
|
||||
"MA": "摩洛哥",
|
||||
"MC": "摩纳哥",
|
||||
"MD": "摩尔多瓦",
|
||||
"MG": "马达加斯加",
|
||||
"ML": "马里",
|
||||
"MM": "缅甸",
|
||||
"MN": "蒙古",
|
||||
"MO": "中国澳门",
|
||||
"MS": "蒙特塞拉特岛",
|
||||
"MT": "马耳他",
|
||||
"MU": "毛里求斯",
|
||||
"MV": "马尔代夫",
|
||||
"MW": "马拉维",
|
||||
"MX": "墨西哥",
|
||||
"MY": "马来西亚",
|
||||
"MZ": "莫桑比克",
|
||||
"NA": "纳米比亚",
|
||||
"NE": "尼日尔",
|
||||
"NG": "尼日利亚",
|
||||
"NI": "尼加拉瓜",
|
||||
"NL": "荷兰",
|
||||
"NO": "挪威",
|
||||
"NP": "尼泊尔",
|
||||
"NR": "瑙鲁",
|
||||
"NZ": "新西兰",
|
||||
"OM": "阿曼",
|
||||
"PA": "巴拿马",
|
||||
"PE": "秘鲁",
|
||||
"PF": "法属玻利尼西亚",
|
||||
"PG": "巴布亚新几内亚",
|
||||
"PH": "菲律宾",
|
||||
"PK": "巴基斯坦",
|
||||
"PL": "波兰",
|
||||
"PR": "波多黎各",
|
||||
"PT": "葡萄牙",
|
||||
"PY": "巴拉圭",
|
||||
"QA": "卡塔尔",
|
||||
"RO": "罗马尼亚",
|
||||
"RU": "俄罗斯",
|
||||
"SA": "沙特阿拉伯",
|
||||
"SB": "所罗门群岛",
|
||||
"SC": "塞舌尔",
|
||||
"SD": "苏丹",
|
||||
"SE": "瑞典",
|
||||
"SG": "新加坡",
|
||||
"SI": "斯洛文尼亚",
|
||||
"SK": "斯洛伐克",
|
||||
"SL": "塞拉利昂",
|
||||
"SM": "圣马力诺",
|
||||
"SN": "塞内加尔",
|
||||
"SO": "索马里",
|
||||
"SR": "苏里南",
|
||||
"ST": "圣多美和普林西比",
|
||||
"SV": "萨尔瓦多",
|
||||
"SY": "叙利亚",
|
||||
"SZ": "斯威士兰",
|
||||
"TD": "乍得",
|
||||
"TG": "多哥",
|
||||
"TH": "泰国",
|
||||
"TJ": "塔吉克斯坦",
|
||||
"TM": "土库曼斯坦",
|
||||
"TN": "突尼斯",
|
||||
"TO": "汤加",
|
||||
"TR": "土耳其",
|
||||
"TT": "特立尼达和多巴哥",
|
||||
"TW": "中国台湾",
|
||||
"TZ": "坦桑尼亚",
|
||||
"UA": "乌克兰",
|
||||
"UG": "乌干达",
|
||||
"US": "美国",
|
||||
"UY": "乌拉圭",
|
||||
"UZ": "乌兹别克斯坦",
|
||||
"VC": "圣文森特岛",
|
||||
"VE": "委内瑞拉",
|
||||
"VN": "越南",
|
||||
"YE": "也门",
|
||||
"YU": "南斯拉夫",
|
||||
"ZA": "南非",
|
||||
"ZM": "赞比亚",
|
||||
"ZR": "扎伊尔",
|
||||
"ZW" : "津巴布韦"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
<div class="headNew" >
|
||||
<div class="headNewLeft" >
|
||||
<div class="headNewLeftText">
|
||||
<span>YYDNS</span>
|
||||
<!-- <span>YYDNS</span>-->
|
||||
<!-- <img src="../img/logyy.jpg">-->
|
||||
<img src="../img/logyy_美图抠图20240424.png" style="width: 180px">
|
||||
</div>
|
||||
</div>
|
||||
<div class="headNewCenter" >
|
||||
@@ -315,7 +317,7 @@
|
||||
.headNew{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:url('../img/header.svg');
|
||||
/*background-image:url('../img/header.svg');*/
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
.headNewLeft{
|
||||
@@ -326,14 +328,17 @@
|
||||
width: 22%;
|
||||
height: 5%;
|
||||
float: left;
|
||||
background-image: url('../img/headerLeft.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
/*background-image: url('../img/headerLeft.svg');*/
|
||||
/*background-image: url('../img/logyy_美图抠图20240424.png');*/
|
||||
/*background-repeat: no-repeat;*/
|
||||
/*background-size: 100% auto;*/
|
||||
.headNewLeftText{
|
||||
color: #ece9f8;
|
||||
font-size: 20px;
|
||||
margin-top: 3.1%;
|
||||
margin-left: 35%;
|
||||
/*margin-top: 3.1%;*/
|
||||
margin-top: -8%;
|
||||
/*margin-left: 35%;*/
|
||||
margin-left: 10%;
|
||||
}
|
||||
}
|
||||
.headNewCenter{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<div :class="hit==='menuMBGZ'? 'NotesHit':'Notes'" v-on:click="updataHit('menuMBGZ')">
|
||||
<div class="nameIframe">
|
||||
<img src="../img/6.png">
|
||||
<span>MBGZ</span>
|
||||
<span>目标感知</span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="hit==='menuTaskManagement'? 'NotesHit':'Notes'" @click="updataHit('menuTaskManagement')">
|
||||
|
||||
@@ -10,6 +10,7 @@ Router.prototype.push = function push(location) {
|
||||
return originalPush.call(this, location).catch(err => err)
|
||||
}
|
||||
|
||||
|
||||
export default new Router({
|
||||
// mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
@@ -67,8 +68,23 @@ export default new Router({
|
||||
title: '系统介绍',
|
||||
component: () => import('@/views/menuSysIntroduce/index'),
|
||||
meta: { requiresAuth: true } // 需要登录才能访问
|
||||
},
|
||||
{
|
||||
path: 'menuTaskInfo',
|
||||
name: 'menuTaskInfo',
|
||||
title: '任务详情',
|
||||
component: () => import('@/views/menuTaskInfo/index'),
|
||||
meta: { requiresAuth: true } // 需要登录才能访问
|
||||
},
|
||||
{
|
||||
path: 'menuMBZTGZ',
|
||||
name: 'menuMBZTGZ',
|
||||
title: '目标状态详情',
|
||||
component: () => import('@/views/menuMBZTGZ/index'),
|
||||
meta: { requiresAuth: true } // 需要登录才能访问
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,34 +1,39 @@
|
||||
<template>
|
||||
<div class="box" id="show-loading" v-loading="loading">
|
||||
<div class="card">
|
||||
<div class="title">镜像总数</div>
|
||||
<div>
|
||||
<span class="info-span">{{ imageData.total_image_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<div>
|
||||
<span style="color: #dfe6ec;font-size: 20px;float: left;margin-left: 3%;margin-top: 2%">已探测目标</span>
|
||||
<div class="box" id="show-loading" v-loading="loading">
|
||||
<div class="card">
|
||||
<div class="title">IPv6</div>
|
||||
<div>
|
||||
<span class="info-span">{{ target.v6dns }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">基础镜像</div>
|
||||
<div>
|
||||
<span class="info-span">{{ imageData.system_image_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<div class="card">
|
||||
<div class="title">DNSSEC</div>
|
||||
<div>
|
||||
<span class="info-span">{{ target.dnssec }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">内置镜像</div>
|
||||
<div>
|
||||
<span class="info-span">{{ imageData.buildin_image_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<div class="card">
|
||||
<div class="title">DoT</div>
|
||||
<div>
|
||||
<span class="info-span">{{ target.dot }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">DoH</div>
|
||||
<div>
|
||||
<span class="info-span">{{ target.doh }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">自定义镜像</div>
|
||||
<div>
|
||||
<span class="info-span">{{ imageData.define_image_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -39,22 +44,32 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
imageData: {}
|
||||
imageData: {},
|
||||
target:{
|
||||
dnssec:0,
|
||||
doh:0,
|
||||
dot:0,
|
||||
v6dns:0
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.init()
|
||||
this.init()
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
// this.init()
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
// this.imageData = getTargetsResponse?.result
|
||||
this.loading = true
|
||||
this.$axios.get(this.$http.api.getimageStatistics).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.imageData = res?.result
|
||||
this.$axios.get(this.$http.api.sysNum).then(res => {
|
||||
if (res.code == 200) {
|
||||
this.target.dnssec=res?.target?.dnssec
|
||||
this.target.doh=res?.target?.doh
|
||||
this.target.dot=res?.target?.dot
|
||||
this.target.v6dns=res?.target?.v6dns
|
||||
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
@@ -69,7 +84,7 @@ export default {
|
||||
<style lang="less" scoped>
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: 80%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
@@ -79,7 +94,7 @@ export default {
|
||||
.title {
|
||||
color: #FFF;
|
||||
font-family: PingFang HK;
|
||||
font-size: 12px;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
|
||||
@@ -1,240 +1,430 @@
|
||||
<template>
|
||||
<div class="node-card">
|
||||
<div class="node-chart" id="node" v-loading="loading"></div>
|
||||
<el-select class="range-select" v-model="target_id" placeholder="全部靶场" @change="changeRange">
|
||||
<el-option
|
||||
v-for="item in rangeDict"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<div class="tabs-container">
|
||||
<el-tabs v-model="activeName" @tab-click="tabClick">
|
||||
<el-tab-pane label="总量" name="total"></el-tab-pane>
|
||||
<el-tab-pane label="已完成" name="complete"></el-tab-pane>
|
||||
<el-tab-pane label="创建中" name="pending"></el-tab-pane>
|
||||
<el-tab-pane label="创建失败" name="false"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<span style="font-size: 20px;float: left;margin-top: 1%;margin-left: 2%">系统运行日志</span>
|
||||
<div class="project">
|
||||
<div class="block">
|
||||
<el-date-picker
|
||||
v-model="time1"
|
||||
type="datetime"
|
||||
placeholder="选择开始时间"
|
||||
align="right"
|
||||
:picker-options="pickerOptions"
|
||||
@change="query">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project">
|
||||
<div class="block">
|
||||
<el-date-picker
|
||||
v-model="time2"
|
||||
type="datetime"
|
||||
placeholder="选择结束时间"
|
||||
align="right"
|
||||
:picker-options="pickerOptions"
|
||||
@change="query">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project">
|
||||
<el-select v-model="log_level" placeholder="日志等级筛选" clearable @change="query">
|
||||
<el-option
|
||||
v-for="item in log_levels"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="project" @keyup.enter="query">
|
||||
<el-input v-model="userAccount" placeholder="用户账号筛选" suffix icon="">
|
||||
<template v-slot:suffix>
|
||||
<div class="icon-group">
|
||||
<img src="../../../img/inputl.png" alt="**">
|
||||
<img src="../../../img/inputIcon.png" alt="*" @click="query">
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="list" >
|
||||
<el-table class="custom-table"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
height="100%"
|
||||
style="width: 100%;"
|
||||
tooltip-effect="dark"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column type="index" align="center" min-width="100">
|
||||
<template slot="header" slot-scope="scope">
|
||||
<span>序号</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="time"
|
||||
label="时间"
|
||||
min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="level"
|
||||
label="日志级别"
|
||||
min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="日志信息" min-width="300">
|
||||
<template slot-scope="scope" >{{ scope.row.info.substr(0, 80)}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="user"
|
||||
label="用户账号"
|
||||
min-width="100">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center"
|
||||
prop="ip"
|
||||
label="用户IP"
|
||||
min-width="100">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="10"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
import { Loading } from 'element-ui'
|
||||
import { getTargetsResponse } from './nodeMock.js'
|
||||
export default {
|
||||
name: 'NodeView',
|
||||
data() {
|
||||
return {
|
||||
target_id: '',
|
||||
target_name: '',
|
||||
loading: false,
|
||||
nodeData: {},
|
||||
nodeDataX: [],
|
||||
nodeDataY: [],
|
||||
rangeDict: [],
|
||||
nodeChart: null,
|
||||
activeName: 'total'
|
||||
tableData:[],
|
||||
total:0,
|
||||
page:1,
|
||||
size:10,
|
||||
time1:'',
|
||||
time2:'',
|
||||
log_level:"",
|
||||
userAccount:"",
|
||||
pickerOptions: {
|
||||
shortcuts: [{
|
||||
text: '今天',
|
||||
onClick(picker) {
|
||||
picker.$emit('pick', new Date());
|
||||
}
|
||||
}, {
|
||||
text: '昨天',
|
||||
onClick(picker) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() - 3600 * 1000 * 24);
|
||||
picker.$emit('pick', date);
|
||||
}
|
||||
}, {
|
||||
text: '一周前',
|
||||
onClick(picker) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
|
||||
picker.$emit('pick', date);
|
||||
}
|
||||
}]
|
||||
},
|
||||
|
||||
log_levels:[
|
||||
{
|
||||
value:'ERROR',
|
||||
label:'ERROR'
|
||||
},
|
||||
{
|
||||
value:'INFO',
|
||||
label:'INFO'
|
||||
},
|
||||
{
|
||||
value:'WARNING',
|
||||
label:'WARNING'
|
||||
},
|
||||
],
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.query()
|
||||
},
|
||||
mounted(){
|
||||
this.init()
|
||||
// this.init()
|
||||
},
|
||||
methods: {
|
||||
async init() {
|
||||
await this.getRangeDict()
|
||||
await this.initData()
|
||||
this.initEcharts()
|
||||
handleSizeChange(val) {
|
||||
console.log(`每页 ${val} 条`);
|
||||
this.size=val
|
||||
this.query()
|
||||
},
|
||||
initData() {
|
||||
// this.nodeData = getTargetsResponse?.result
|
||||
// for (const key in this.nodeData) {
|
||||
// this.nodeDataX.push(key)
|
||||
// this.nodeDataY.push(this.nodeData[key])
|
||||
// }
|
||||
|
||||
const reqParams = {}
|
||||
if (this.target_id) {
|
||||
reqParams.target_id = this.target_id
|
||||
handleCurrentChange(val) {
|
||||
console.log(`当前页: ${val}`);
|
||||
this.page=val
|
||||
this.query()
|
||||
},
|
||||
query(){
|
||||
let data={
|
||||
"per_page":this.size,
|
||||
"page":this.page,
|
||||
"begin":this.time1.toString(),
|
||||
"end":this.time2.toString(),
|
||||
"level":this.log_level,
|
||||
"user":this.userAccount,
|
||||
}
|
||||
if (this.activeName !== 'total') {
|
||||
reqParams.status = this.activeName
|
||||
}
|
||||
this.loading = true
|
||||
return this.$axios.get(this.$http.api.getNodeStatistics, reqParams).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.nodeDataX = []
|
||||
this.nodeDataY = []
|
||||
this.nodeData = res?.result || {}
|
||||
for (const key in this.nodeData) {
|
||||
this.nodeDataX.push(key)
|
||||
this.nodeDataY.push(this.nodeData[key])
|
||||
}
|
||||
// 使用 Object.entries() 来遍历对象的键值对,并过滤掉值为空的属性
|
||||
const filteredData = {};
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
if (value !== "") {
|
||||
filteredData[key] = value;
|
||||
}
|
||||
}).catch(err => {
|
||||
}
|
||||
this.$axios.get(this.$http.api.sysLog,filteredData).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.tableData=res?.log_data
|
||||
// this.total=res?.total
|
||||
this.total=100
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 获取靶场列表字典
|
||||
getRangeDict() {
|
||||
const reqParams = {
|
||||
page: 1,
|
||||
size: 99,
|
||||
}
|
||||
return this.$axios.get(this.$http.api.getTargets, reqParams).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.rangeDict = res?.result?.items.map(item => {
|
||||
return {
|
||||
label: item.target_name,
|
||||
value: item.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
}).finally(() => {
|
||||
this.rangeDict.unshift({label: '全部靶场', value: ''})
|
||||
this.target_id = this.rangeDict[0].value
|
||||
this.target_name = this.rangeDict[0].label
|
||||
})
|
||||
},
|
||||
// 改变靶场
|
||||
async changeRange(val) {
|
||||
this.target_name = this.rangeDict.find(item => item.value === val)?.label
|
||||
await this.initData()
|
||||
this.refreshData()
|
||||
},
|
||||
// 改变靶场状态
|
||||
async changeRangeStatus() {
|
||||
await this.initData()
|
||||
this.refreshData()
|
||||
},
|
||||
// 刷新图标数据
|
||||
refreshData(){
|
||||
if(!this.nodeChart){
|
||||
return
|
||||
}
|
||||
//更新数据
|
||||
var option = this.nodeChart.getOption()
|
||||
option.title[0].text = `${this.target_name}节点统计`,
|
||||
option.xAxis[0].data = this.nodeDataX
|
||||
option.series[0].data = this.nodeDataY
|
||||
this.nodeChart.setOption(option)
|
||||
},
|
||||
// 切换靶场状态
|
||||
tabClick(tab, event) {
|
||||
this.changeRangeStatus()
|
||||
},
|
||||
//初始化节点柱状图
|
||||
initEcharts() {
|
||||
var chartDom = document.getElementById('node');
|
||||
this.nodeChart = echarts.init(chartDom);
|
||||
var option;
|
||||
|
||||
option = {
|
||||
title: {
|
||||
text: `${this.target_name}节点统计`,
|
||||
left: 'center',
|
||||
top: '15',
|
||||
textStyle: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: 16,
|
||||
fontWeight: 500
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
// trigger: 'axis',
|
||||
axisPointer: {
|
||||
// type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: '25%',
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '8%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: this.nodeDataX,
|
||||
axisTick: {
|
||||
// alignWithLabel: true
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
fontSize: '14',
|
||||
color: 'rgba(255, 255, 255, 0.7)'
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '靶场中各类节点数量',
|
||||
nameTextStyle: {
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
padding: [0, 0, 0, 70]
|
||||
},
|
||||
axisLabel: {
|
||||
fontSize: '12',
|
||||
color: 'rgba(255, 255, 255, 0.7)'
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: ['rgba(199, 199, 200, 0.1)'],
|
||||
width: 1,
|
||||
type: 'dashed'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
// name: 'Direct',
|
||||
type: 'bar',
|
||||
barWidth: '20%',
|
||||
data: this.nodeDataY,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, // 是否显示
|
||||
position: 'top', // 显示位置
|
||||
color: '#FFFFFF',
|
||||
formatter: function (params) {
|
||||
// 核心部分 formatter 可以为字符串也可以是回调
|
||||
if (parseInt(params.value) === 0) {
|
||||
return '';
|
||||
} else {
|
||||
return params.data.label;
|
||||
}
|
||||
}
|
||||
},
|
||||
// 每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#3280D7' },
|
||||
{ offset: 1, color: '#4122E2' }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
option && this.nodeChart.setOption(option);
|
||||
}
|
||||
},
|
||||
// async init() {
|
||||
// await this.getRangeDict()
|
||||
// await this.initData()
|
||||
// this.initEcharts()
|
||||
// },
|
||||
// initData() {
|
||||
// // this.nodeData = getTargetsResponse?.result
|
||||
// // for (const key in this.nodeData) {
|
||||
// // this.nodeDataX.push(key)
|
||||
// // this.nodeDataY.push(this.nodeData[key])
|
||||
// // }
|
||||
//
|
||||
// const reqParams = {}
|
||||
// if (this.target_id) {
|
||||
// reqParams.target_id = this.target_id
|
||||
// }
|
||||
// if (this.activeName !== 'total') {
|
||||
// reqParams.status = this.activeName
|
||||
// }
|
||||
// this.loading = true
|
||||
// return this.$axios.get(this.$http.api.getNodeStatistics, reqParams).then(res => {
|
||||
// if (res.code == 200 || res.code == "OK") {
|
||||
// this.nodeDataX = []
|
||||
// this.nodeDataY = []
|
||||
// this.nodeData = res?.result || {}
|
||||
// for (const key in this.nodeData) {
|
||||
// this.nodeDataX.push(key)
|
||||
// this.nodeDataY.push(this.nodeData[key])
|
||||
// }
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// console.log(err)
|
||||
// }).finally(() => {
|
||||
// this.loading = false
|
||||
// })
|
||||
// },
|
||||
// 获取靶场列表字典
|
||||
// getRangeDict() {
|
||||
// const reqParams = {
|
||||
// page: 1,
|
||||
// size: 99,
|
||||
// }
|
||||
// return this.$axios.get(this.$http.api.getTargets, reqParams).then(res => {
|
||||
// if (res.code == 200 || res.code == "OK") {
|
||||
// this.rangeDict = res?.result?.items.map(item => {
|
||||
// return {
|
||||
// label: item.target_name,
|
||||
// value: item.id
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// console.log(err)
|
||||
// }).finally(() => {
|
||||
// this.rangeDict.unshift({label: '全部靶场', value: ''})
|
||||
// this.target_id = this.rangeDict[0].value
|
||||
// this.target_name = this.rangeDict[0].label
|
||||
// })
|
||||
// },
|
||||
// 改变靶场
|
||||
// async changeRange(val) {
|
||||
// this.target_name = this.rangeDict.find(item => item.value === val)?.label
|
||||
// await this.initData()
|
||||
// this.refreshData()
|
||||
// },
|
||||
// 改变靶场状态
|
||||
// async changeRangeStatus() {
|
||||
// await this.initData()
|
||||
// this.refreshData()
|
||||
// },
|
||||
// 刷新图标数据
|
||||
// refreshData(){
|
||||
// if(!this.nodeChart){
|
||||
// return
|
||||
// }
|
||||
// //更新数据
|
||||
// var option = this.nodeChart.getOption()
|
||||
// option.title[0].text = `${this.target_name}节点统计`,
|
||||
// option.xAxis[0].data = this.nodeDataX
|
||||
// option.series[0].data = this.nodeDataY
|
||||
// this.nodeChart.setOption(option)
|
||||
// },
|
||||
// 切换靶场状态
|
||||
// tabClick(tab, event) {
|
||||
// this.changeRangeStatus()
|
||||
// },
|
||||
//初始化节点柱状图
|
||||
// initEcharts() {
|
||||
// var chartDom = document.getElementById('node');
|
||||
// this.nodeChart = echarts.init(chartDom);
|
||||
// var option;
|
||||
//
|
||||
// option = {
|
||||
// title: {
|
||||
// text: `${this.target_name}节点统计`,
|
||||
// left: 'center',
|
||||
// top: '15',
|
||||
// textStyle: {
|
||||
// color: '#FFFFFF',
|
||||
// fontSize: 16,
|
||||
// fontWeight: 500
|
||||
// }
|
||||
// },
|
||||
// tooltip: {
|
||||
// // trigger: 'axis',
|
||||
// axisPointer: {
|
||||
// // type: 'shadow'
|
||||
// }
|
||||
// },
|
||||
// grid: {
|
||||
// top: '25%',
|
||||
// left: '3%',
|
||||
// right: '4%',
|
||||
// bottom: '8%',
|
||||
// containLabel: true
|
||||
// },
|
||||
// xAxis: [
|
||||
// {
|
||||
// type: 'category',
|
||||
// data: this.nodeDataX,
|
||||
// axisTick: {
|
||||
// // alignWithLabel: true
|
||||
// show: false
|
||||
// },
|
||||
// axisLabel: {
|
||||
// fontSize: '14',
|
||||
// color: 'rgba(255, 255, 255, 0.7)'
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// yAxis: [
|
||||
// {
|
||||
// type: 'value',
|
||||
// name: '靶场中各类节点数量',
|
||||
// nameTextStyle: {
|
||||
// color: 'rgba(255, 255, 255, 0.7)',
|
||||
// padding: [0, 0, 0, 70]
|
||||
// },
|
||||
// axisLabel: {
|
||||
// fontSize: '12',
|
||||
// color: 'rgba(255, 255, 255, 0.7)'
|
||||
// },
|
||||
// splitLine: {
|
||||
// show: true,
|
||||
// lineStyle: {
|
||||
// color: ['rgba(199, 199, 200, 0.1)'],
|
||||
// width: 1,
|
||||
// type: 'dashed'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// series: [
|
||||
// {
|
||||
// // name: 'Direct',
|
||||
// type: 'bar',
|
||||
// barWidth: '20%',
|
||||
// data: this.nodeDataY,
|
||||
// itemStyle: {
|
||||
// normal: {
|
||||
// label: {
|
||||
// show: true, // 是否显示
|
||||
// position: 'top', // 显示位置
|
||||
// color: '#FFFFFF',
|
||||
// formatter: function (params) {
|
||||
// // 核心部分 formatter 可以为字符串也可以是回调
|
||||
// if (parseInt(params.value) === 0) {
|
||||
// return '';
|
||||
// } else {
|
||||
// return params.data.label;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// // 每个柱子的颜色即为colorList数组里的每一项,如果柱子数目多于colorList的长度,则柱子颜色循环使用该数组
|
||||
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
// { offset: 0, color: '#3280D7' },
|
||||
// { offset: 1, color: '#4122E2' }
|
||||
// ])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
// option && this.nodeChart.setOption(option);
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.list{
|
||||
width: 95%;
|
||||
height: 69%;
|
||||
margin-left: 2.5%;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
border: none;
|
||||
}
|
||||
.project{
|
||||
display: inline-block;
|
||||
height: auto;
|
||||
width: 10%;
|
||||
margin-left: 0.5%;
|
||||
margin-right: 3%;
|
||||
margin-top: 1%;
|
||||
margin-bottom: 1%;
|
||||
.el-input::placeholder {
|
||||
width: auto;
|
||||
}
|
||||
.icon-group {
|
||||
display: flex; /* 设置容器为 Flexbox 容器 */
|
||||
align-items: center; /* 垂直居中图片 */
|
||||
gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */
|
||||
|
||||
}
|
||||
.icon-group img {
|
||||
transform: scale(1);
|
||||
margin-right: 15px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
}
|
||||
.node-card {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
<template>
|
||||
<div class="source-card">
|
||||
<div class="source-chart" id="resource" v-loading="loading"></div>
|
||||
<div class="tabs-container">
|
||||
<el-tabs v-model="activeName" @tab-click="tabClick">
|
||||
<el-tab-pane label="CPU" name="CPU"></el-tab-pane>
|
||||
<el-tab-pane label="MEMEORY" name="MEMEORY"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<!-- <div class="source-chart" id="resource" v-loading="loading"></div>-->
|
||||
<ZhuZhuangTu3 :active="0" ref="zhudouble" :bing="zhudouble"></ZhuZhuangTu3>
|
||||
<!-- <div class="tabs-container">-->
|
||||
<!-- <el-tabs v-model="activeName" @tab-click="tabClick">-->
|
||||
<!-- <el-tab-pane label="CPU" name="CPU"></el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="MEMEORY" name="MEMEORY"></el-tab-pane>-->
|
||||
<!-- </el-tabs>-->
|
||||
|
||||
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts';
|
||||
import ZhuZhuangTu3 from '../echarts/zhuzhuangtu3'
|
||||
|
||||
import { getTargetsResponse } from './sourceMock.js'
|
||||
export default {
|
||||
name: 'SourceView',
|
||||
components: {
|
||||
ZhuZhuangTu3,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -25,14 +33,22 @@ export default {
|
||||
memoryList: [],
|
||||
activeName: 'CPU',
|
||||
sourceChart: null,
|
||||
rangeDict: []
|
||||
rangeDict: [],
|
||||
zhudouble:{
|
||||
xdata:[],
|
||||
ydata1:[], //ipv6
|
||||
ydata2:[], //dnsses
|
||||
ydata3:[], //dot
|
||||
ydata4:[], //doh
|
||||
ydata5:[], //总计
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted(){
|
||||
this.init()
|
||||
this.getRangeDict()
|
||||
// this.getRangeDict()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
@@ -45,15 +61,26 @@ export default {
|
||||
// }
|
||||
// this.initEcharts()
|
||||
this.loading = true
|
||||
this.$axios.get(this.$http.api.getSourceStatistics).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.sourceData = res?.result || {}
|
||||
for (const key in this.sourceData) {
|
||||
this.sourceDataX.push(key)
|
||||
this.sourceDataY.push(this.sourceData[key]['total_cpu'])
|
||||
this.cpuList.push(this.sourceData[key]['total_cpu'])
|
||||
this.memoryList.push(this.sourceData[key]['total_memory'])
|
||||
}
|
||||
this.$axios.get(this.$http.api.sysNumDate).then(res => {
|
||||
if (res.code == 200) {
|
||||
this.zhudouble.ydata1=[];
|
||||
this.zhudouble.ydata2=[];
|
||||
this.zhudouble.ydata3=[];
|
||||
this.zhudouble.ydata4=[];
|
||||
this.zhudouble.ydata5=[];
|
||||
this.zhudouble.xdata=[];
|
||||
|
||||
|
||||
Object.keys(res.date_data).forEach(date => {
|
||||
console.log(`Date: ${date}, dot value: ${res.date_data[date].dot}`);
|
||||
this.zhudouble.xdata.push(date)
|
||||
this.zhudouble.ydata1.push(res.date_data[date].v6dns)
|
||||
this.zhudouble.ydata2.push(res.date_data[date].dnssec)
|
||||
this.zhudouble.ydata3.push(res.date_data[date].dot)
|
||||
this.zhudouble.ydata4.push(res.date_data[date].doh)
|
||||
this.zhudouble.ydata5.push(res.date_data[date].v6dns+res.date_data[date].dnssec+res.date_data[date].dot+res.date_data[date].doh)
|
||||
});
|
||||
this.$refs.zhudouble.bingfn(this.zhudouble)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
@@ -196,25 +223,25 @@ export default {
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 获取靶场列表字典
|
||||
getRangeDict() {
|
||||
const reqParams = {
|
||||
page: 1,
|
||||
size: 99,
|
||||
}
|
||||
return this.$axios.get(this.$http.api.getTargets, reqParams).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.rangeDict = res?.result?.items.map(item => {
|
||||
return {
|
||||
label: item.target_name,
|
||||
value: item.id
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
// // 获取靶场列表字典
|
||||
// getRangeDict() {
|
||||
// const reqParams = {
|
||||
// page: 1,
|
||||
// size: 99,
|
||||
// }
|
||||
// return this.$axios.get(this.$http.api.getTargets, reqParams).then(res => {
|
||||
// if (res.code == 200 || res.code == "OK") {
|
||||
// this.rangeDict = res?.result?.items.map(item => {
|
||||
// return {
|
||||
// label: item.target_name,
|
||||
// value: item.id
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// console.log(err)
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<template>
|
||||
<div class="box" v-loading="loading">
|
||||
<div class="card">
|
||||
<div class="title">靶场数量</div>
|
||||
<div class="title">已部署代理</div>
|
||||
<div>
|
||||
<span class="info-span">{{ targetData.total_target_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<span class="info-span">{{ agent_num }}</span>
|
||||
<span class="unit-span">台</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">部署成功</div>
|
||||
<div class="title">已执行任务</div>
|
||||
<div>
|
||||
<span class="info-span">{{ targetData.deploy_success_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<span class="info-span">{{ task_num }}</span>
|
||||
<span class="unit-span">次</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">部署失败</div>
|
||||
<div class="title">已运行时间</div>
|
||||
<div>
|
||||
<span class="info-span">{{ targetData.deploy_fail_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
<span class="info-span">{{ workday }}</span>
|
||||
<span class="unit-span">天</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="title">未部署</div>
|
||||
<div>
|
||||
<span class="info-span">{{ targetData.no_deploy_count }}</span>
|
||||
<span class="unit-span">个</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="card">-->
|
||||
<!-- <div class="title">未部署</div>-->
|
||||
<!-- <div>-->
|
||||
<!-- <span class="info-span">{{ targetData.no_deploy_count }}</span>-->
|
||||
<!-- <span class="unit-span">个</span>-->
|
||||
<!-- </div> -->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,23 +39,29 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
targetData: {}
|
||||
targetData: {},
|
||||
//num
|
||||
agent_num:0,
|
||||
task_num:0,
|
||||
workday:0,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.init()
|
||||
this.init()
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
// this.init()
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
// this.targetData = getTargetsResponse?.result
|
||||
|
||||
this.loading = true
|
||||
this.$axios.get(this.$http.api.getTargetStatistics).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.targetData = res?.result
|
||||
this.$axios.get(this.$http.api.sysNum).then(res => {
|
||||
if (res.code == 200) {
|
||||
this.agent_num=res?.agent_num
|
||||
this.task_num=res?.task_num
|
||||
this.workday=res?.workday
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
@@ -80,7 +86,7 @@ export default {
|
||||
.title {
|
||||
color: #FFF;
|
||||
font-family: PingFang HK;
|
||||
font-size: 12px;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
<template>
|
||||
<div class="account-manage" ref="appRef">
|
||||
<div class="show">
|
||||
<div class="title">修改密码</div>
|
||||
<div class="form-box">
|
||||
<el-form
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
ref="accountForm"
|
||||
label-position="right"
|
||||
label-width="100px"
|
||||
class="form-content"
|
||||
>
|
||||
<el-form-item label="原始密码" prop="old_password">
|
||||
<el-input v-model="form.old_password" placeholder="请输入原始密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="new_password">
|
||||
<el-input v-model="form.new_password" placeholder="请输入新密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码" prop="new_password_again">
|
||||
<el-input v-model="form.new_password_again" placeholder="请输入新密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="small">取消</el-button>
|
||||
<el-button :loading="loading" size="small" type="primary" @click="onSubmit">确认</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data(){
|
||||
return{
|
||||
loading: false,
|
||||
form: {
|
||||
old_password: '',
|
||||
new_password: '',
|
||||
new_password_again: ''
|
||||
},
|
||||
rules: {
|
||||
old_password: [
|
||||
{ required: true, message: '请输入原始密码', trigger: 'change' },
|
||||
{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'change' }
|
||||
],
|
||||
new_password: [
|
||||
{ required: true, message: '请输入新密码', trigger: 'change' },
|
||||
{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'change' }
|
||||
],
|
||||
new_password_again: [
|
||||
{ required: true, message: '请输入新密码', trigger: 'change' },
|
||||
{ min: 1, max: 20, message: '长度在 1 到 20 个字符', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
watch: {},
|
||||
created() {},
|
||||
methods:{
|
||||
// 创建新密码
|
||||
onSubmit() {
|
||||
this.$refs.accountForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.editPwd()
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
editPwd() {
|
||||
this.loading = true
|
||||
const url = this.$http.api.updatePwd
|
||||
this.$axios.put(url, {}, this.form).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.resetForm()
|
||||
this.$notify({
|
||||
title: '修改密码成功',
|
||||
type: 'success',
|
||||
duration: 2500
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
resetForm() {
|
||||
this.form = {
|
||||
old_password: '',
|
||||
new_password: '',
|
||||
new_password_again: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped="scoped">
|
||||
.account-manage{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
position: relative; /* 确保相对定位生效 */
|
||||
.show{
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
position: absolute; /* 绝对定位 */
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
background-image:url('../../img/backgroundFourCorner.png');
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
.title {
|
||||
font-family: PingFang HK;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
padding: 30px 0 0 30px;
|
||||
}
|
||||
.form-box {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.form-content {
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,32 +1,40 @@
|
||||
<template>
|
||||
<div class="range-manage" ref="appRef">
|
||||
<div class="show">
|
||||
<div class="head">
|
||||
<span style="font-size: 16px;float: left;padding-top: 1%">镜像列表</span>
|
||||
<!-- <img src="../../img/customImages.png" style="height: 70% ;width: 10%;margin-right: 2%;color: #ffffff" @click="newlyPztj=true">-->
|
||||
<img src="../../img/customImages.png" style="height: 70% ;width: 10%;margin-right: 2%;color: #ffffff" @click="customizationImage(null)">
|
||||
<div class="input" @keyup.enter="updateAndQuery">
|
||||
<el-input v-model="queryByImageName" placeholder="名称查询输入" suffix icon="">
|
||||
<template v-slot:suffix>
|
||||
<div class="icon-group">
|
||||
<img src="../../img/inputl.png" alt="**">
|
||||
<img src="../../img/inputIcon.png" alt="*" @click="updateAndQuery">
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="project">
|
||||
<el-select v-model="selectImageStateValue" placeholder="全部镜像" @change="selectImageState()">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
|
||||
<Header
|
||||
></Header>
|
||||
<div>
|
||||
<span style="font-size: 20px;margin-bottom: 1%;margin-top: 0.5%;float: left;margin-left: 3%;color: #00C0FF">至少需要一个代理才能创建任务,每个代理同时只执行一项任务</span>
|
||||
</div>
|
||||
<div class="project">
|
||||
<el-select v-model="powerValue" placeholder="能力筛选" clearable @change="query">
|
||||
<el-option
|
||||
v-for="item in powerFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="project">
|
||||
<el-select v-model="stateValue" placeholder="状态筛选" clearable @change="query">
|
||||
<el-option
|
||||
v-for="item in stateFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="project">
|
||||
<el-select v-model="freeValue" placeholder="空闲筛选" clearable @change="query">
|
||||
<el-option
|
||||
v-for="item in freeFilter"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="list" >
|
||||
<el-table class="custom-table"
|
||||
@@ -44,70 +52,41 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="image_name"
|
||||
label="镜像名称"
|
||||
prop="id"
|
||||
label="编号"
|
||||
min-width="200">
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="image_version"
|
||||
label="镜像版本"
|
||||
min-width="100">
|
||||
<el-table-column align="center" label="IP地址" min-width="300">
|
||||
<template slot-scope="scope">
|
||||
<!-- 在这个插槽中自定义单元格的渲染方式 -->
|
||||
<div style="white-space: pre-line;">
|
||||
<!-- 使用 v-for 循环遍历每个 IP 地址,并使用换行符分隔 -->
|
||||
<span v-for="(ip, index) in scope.row.ipaddr" :key="index">
|
||||
{{ ip }}
|
||||
<br> <!-- 在每个 IP 地址后面添加换行符 -->
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="image_type"
|
||||
label="镜像类别"
|
||||
min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="publish_time"
|
||||
label="推送时间"
|
||||
min-width="200">
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
prop="image_size"
|
||||
label="镜像大小"
|
||||
prop="atype"
|
||||
label="能力类型"
|
||||
min-width="150">
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
label="构建方式"
|
||||
min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.define_image.length===0">
|
||||
导入
|
||||
</span>
|
||||
<span v-if="scope.row.define_image.length>0">
|
||||
{{scope.row.define_image[0].establish_mode}}
|
||||
</span>
|
||||
</template>
|
||||
<el-table-column align="center" label="当前状态" min-width="100">
|
||||
<template slot-scope="scope">{{ scope.row.status?"在线":"离线" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center"
|
||||
label="镜像状态"
|
||||
min-width="130">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.define_image.length===0">
|
||||
已构建
|
||||
</span>
|
||||
<span v-if="scope.row.define_image.length>0">
|
||||
{{scope.row.define_image[0].has_build==='True'?scope.row.define_image[0].build_status==='True'?'已构建':'构建失败':'未构建'}}
|
||||
</span>
|
||||
</template>
|
||||
<el-table-column align="center" label="是否空闲" min-width="100">
|
||||
<template slot-scope="scope">{{ scope.row.idle?"空闲":"执行中" }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center"
|
||||
label="操作"
|
||||
min-width="380">
|
||||
min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<!-- <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>-->
|
||||
<el-button type="text" size="medium" :style="{'color': (scope.row.define_image.length===0) ? '#565e6e': '#409eff'}"
|
||||
@click="scope.row.define_image.length===0?'':getInfo(scope.row)">查看详情</el-button>
|
||||
<el-button type="text" size="medium" :style="{'color': (scope.row.image_type==='system' || scope.row.image_type==='buildin') ? '#565e6e': '#409eff'}"
|
||||
@click="(scope.row.image_type==='system' || scope.row.image_type==='buildin') ? '' : customizationImage(scope.row)">修改配置</el-button>
|
||||
<el-button type="text" size="medium" :style="{'color': (scope.row.define_image.length===0
|
||||
||(scope.row.define_image[0].has_build==='True'&&scope.row.define_image[0].build_status==='True')) ? '#565e6e': '#409eff'}"
|
||||
@click="(scope.row.define_image.length===0
|
||||
||((scope.row.define_image[0].has_build==='True'&&scope.row.define_image[0].build_status==='True')))?NobuildingImage():buildImage(scope.row.id)">
|
||||
{{scope.row.define_image.length===0?'构建镜像':(scope.row.define_image[0].has_build==='True'&&scope.row.define_image[0].build_status==='False')?"重新构建":"构建镜像"}}
|
||||
</el-button>
|
||||
<el-button type="text" size="medium" @click="delImage(scope.row.id)">删除镜像</el-button>
|
||||
<el-button type="text" size="medium" style="{'color': '#409eff'}"
|
||||
@click="getInfo(scope.row)">详情</el-button>
|
||||
<el-button type="text" size="medium" @click="agentdel(scope.row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -124,246 +103,68 @@
|
||||
>
|
||||
</el-pagination>
|
||||
<div class="mask"></div>
|
||||
</div>
|
||||
<div class="infoTar" v-if="infoType==='tar'">
|
||||
<i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 6%" @click="infoType=''"></i>
|
||||
<div class="infoTypography">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="cell">Tar包名称:{{infoType}}</div>
|
||||
<div class="cell">上传时间:{{infoType}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cell">Tar包大小:{{infoType}}</div>
|
||||
<div class="cell">状态:{{infoType}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cellA">上传者:{{infoType}}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cellA">描述:{{infoType}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="anType">
|
||||
<div>
|
||||
<el-button class="glBut" type="primary" @click="closeInfo()">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="infoDocker" v-if="infoType==='docker'">
|
||||
<i class="el-icon-close" style="float: right; padding-right: 5%;padding-top: 2%" @click="closeInfo()"></i>
|
||||
<div class="infoCode">
|
||||
<Card>
|
||||
<prism-editor class="my-editor" v-model="code" :highlight="highlighter" readonly :line-numbers="true"></prism-editor>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="infoInfo">
|
||||
<div>
|
||||
<div class="infoText">
|
||||
<!-- 状态:{{infoType}}-->
|
||||
状态:
|
||||
<template>
|
||||
<span v-if="addImage.define_image.length===0">
|
||||
已构建
|
||||
</span>
|
||||
<span v-if="addImage.define_image.length>0">
|
||||
{{addImage.define_image[0].has_build==='True'?addImage.define_image[0].build_status==='True'?'已构建':'构建失败':'未构建'}}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="infoText">
|
||||
上传者99:{{addImage.user_id}}
|
||||
</div>
|
||||
<div class="infoText">
|
||||
上传时间:{{addImage.publish_time}}
|
||||
</div>
|
||||
<div class="infoText">
|
||||
描述:{{addImage.image_description}}
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 135%">
|
||||
<div>
|
||||
<el-button type="primary" @click="closeInfo()">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="popup" v-if="newlyPztj">
|
||||
<!-- 在此处指定弹窗的样式和内容 -->
|
||||
<!-- <i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 2.8%" @click="newlyPztj=false"></i>-->
|
||||
<i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 2.8%" @click="CustomizationImageFales()"></i>
|
||||
<div class="tag">
|
||||
<el-tag class="tags" :style="{'color': (tag==='基本配置') ? '#f8fdff': '#565e6e'}" @click="updateTag('基本配置'),tagStep=1">基本配置</el-tag>
|
||||
<el-tag class="tags" :style="{'color': (tag==='镜像配置') ? '#f8fdff': '#565e6e'}" @click="updateTag('镜像配置'),tagStep=2">镜像配置</el-tag>
|
||||
<el-tag class="tags" :style="{'color': (tag==='构建') ? '#f8fdff': '#565e6e'}" @click="updateTag('构建'),tagStep=3">构建</el-tag>
|
||||
</div>
|
||||
<div class="jbpz" v-if="tagStep===1">
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">镜像名称</span>
|
||||
<el-input class="srk" v-model="addImage.image_name" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">镜像版本</span>
|
||||
<el-input class="srk" v-model="addImage.image_version" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">镜像描述</span>
|
||||
<el-input class="srk" v-model="addImage.image_description" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="radioType">
|
||||
<div style="margin-right: 25%">
|
||||
<span style="margin-right: 6%">拥有权</span>
|
||||
<el-radio v-model="addImage.attribute" label="private">私有</el-radio>
|
||||
<el-radio v-model="addImage.attribute" label="public">公有</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="anType">
|
||||
<div>
|
||||
<el-button class="glBut" type="primary" @click="CustomizationImageFales()">取消</el-button>
|
||||
<el-button class="glBut" type="primary" @click="tagStep+=1 , tag='镜像配置'">下一步</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jbpz" v-if="tagStep===2" >
|
||||
<!-- <div class="srkType">-->
|
||||
<!-- <span style="margin-right: 3%">镜像名称</span>-->
|
||||
<!-- <el-input class="srk" v-model="addImage.image_name" placeholder="请输入内容"></el-input>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="radioType">-->
|
||||
<!-- <div style="margin-right: 15%">-->
|
||||
<!-- <span style="margin-right: 5%">镜像构建方式</span>-->
|
||||
<!-- <el-radio v-model="dockerOrTar" label="dockerfile">Dockerfile</el-radio>-->
|
||||
<!-- <el-radio v-model="dockerOrTar" label="tar">Tar包导入</el-radio>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="tar" v-if="dockerOrTar==='tar'">
|
||||
<span style="margin-right: 5%;margin-top: 4%">上传Tar包</span>
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-remove="beforeRemove"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:file-list="fileList">
|
||||
<div class="uploadBgImg">
|
||||
<!-- 只能上传jpg/png文件,且不超过500kb-->
|
||||
</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div class="radioType" v-if="dockerOrTar==='dockerfile'">
|
||||
<div style="margin-right: 15%;margin-top: 5%">
|
||||
<!-- <span style="margin-right: 5%">代码形式</span>-->
|
||||
<span style="margin-right: 5%">镜像构建方式</span>
|
||||
<el-radio v-model="radioOwnership2" label="1">直接上传</el-radio>
|
||||
<el-radio v-model="radioOwnership2" label="2">git拉取</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tar" v-if="dockerOrTar==='dockerfile'&&radioOwnership2==='1'" style="margin-left: 36%">
|
||||
<!-- <div class="uploadBgImg">-->
|
||||
<input class="uploadBgImg" type="file" @change="onFileChange">
|
||||
<!-- 只能上传jpg/png文件,且不超过500kb-->
|
||||
<!-- </div>-->
|
||||
<!-- <el-upload-->
|
||||
<!-- class="upload-demo"-->
|
||||
<!-- :on-preview="handlePreview"-->
|
||||
<!-- :on-remove="handleRemove"-->
|
||||
<!-- :before-remove="beforeRemove"-->
|
||||
<!-- multiple-->
|
||||
<!-- :limit="1"-->
|
||||
<!-- :on-exceed="handleExceed"-->
|
||||
<!-- :file-list="fileList">-->
|
||||
<!-- <div class="uploadBgImg">-->
|
||||
<!-- <!– 只能上传jpg/png文件,且不超过500kb–>-->
|
||||
<span style="color: #f5f7f0;font-size: 20px;float: left;margin-left: 6%;margin-top: 1%">代理{{info.id}}详情</span>
|
||||
<div class="jbpz">
|
||||
<template>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col :span="20">当前状态</el-col>
|
||||
<el-col :span="20">{{info.status?'在线':'离线'}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>编号</el-col>
|
||||
<el-col>{{info.id}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>通信端口</el-col>
|
||||
<el-col>{{info.port}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>运行平台</el-col>
|
||||
<el-col>{{info.sys}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>IP地址</el-col>
|
||||
<el-col>
|
||||
<span v-for="i in info.ipaddr">
|
||||
{{i}}
|
||||
<br>
|
||||
</span>
|
||||
<!-- {{info.ipaddr}}-->
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>CPU核心数</el-col>
|
||||
<el-col>{{info.cpu_num}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
<!-- </div>-->
|
||||
<!-- </el-upload>-->
|
||||
</div>
|
||||
<div class="tar" v-if="dockerOrTar==='dockerfile'&&radioOwnership2==='1'" style="margin-left: 36%">
|
||||
<span style="color: #00C0FF">仅支持zip tar.gz,且文件名不可包含特殊字符 '!@#)(' </span>
|
||||
</div>
|
||||
<div v-if="radioOwnership2==='2'&&dockerOrTar==='dockerfile'">
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">git地址</span>
|
||||
<el-input class="srk" v-model="addImage.git_address" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">分支名</span>
|
||||
<el-input class="srk" v-model="addImage.git_branch" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">git账号</span>
|
||||
<el-input class="srk" v-model="addImage.git_account" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">git密码</span>
|
||||
<el-input class="srk" v-model="addImage.git_password" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">启动命令</span>
|
||||
<el-input class="srk" v-model="addImage.run_command" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="srkType">
|
||||
<span style="margin-right: 3%">启动参数</span>
|
||||
<el-input class="srk" v-model="addImage.run_args" placeholder="请输入内容"></el-input>
|
||||
</div>
|
||||
<div class="radioType" v-if="addImage.establish_mode==='git'">
|
||||
<div style="margin-left: 1%">
|
||||
<span style="margin-right: 5%">递增镜像版本号</span>
|
||||
<el-radio v-model="addImage.version_operate" label="add">是</el-radio>
|
||||
<el-radio v-model="addImage.version_operate">其他</el-radio>
|
||||
<el-input style="width: 20%;margin-left: 2%;background-color: #0c295b;display: inline-block;border: none;"
|
||||
v-model="addImage.image_version" placeholder="必须含有数字" v-if="addImage.version_operate!='add'"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dockerFile" v-if="radioOwnership2==='2'">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-remove="beforeRemove"
|
||||
multiple
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:file-list="fileList">
|
||||
<div class="uploadBgImg">
|
||||
<!-- 只能上传jpg/png文件,且不超过500kb-->
|
||||
</div>
|
||||
</el-upload>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>系统内存</el-col>
|
||||
<el-col>{{info.mem}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
</div>
|
||||
<div class="anType">
|
||||
<div>
|
||||
<el-button class="glBut" type="primary" @click="CustomizationImageFales()">取消</el-button>
|
||||
<el-button class="glBut" type="primary" @click="tagStep-=1 , tag='基本配置'">上一步</el-button>
|
||||
<el-button class="glBut" type="primary" @click="tagStep+=1 , tag='构建'">下一步</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jbpz" v-if="tagStep===3">
|
||||
<div style="width: 50%;float: left;margin-left: 10%">
|
||||
<div style="margin-right: 10%">
|
||||
<div><el-radio v-model="addImage.direct" :label="getLabel(true)" style="margin-top: 15%">直接构建</el-radio></div>
|
||||
<div><el-radio v-model="addImage.direct" :label="getLabel(false)" style="margin-top: 15%">仅添加配置</el-radio></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="anType">
|
||||
<div>
|
||||
<el-button class="glBut" type="primary" @click="CustomizationImageFales()">取消</el-button>
|
||||
<el-button class="glBut" type="primary" @click="tagStep-=1 , tag='镜像配置'">上一步</el-button>
|
||||
<el-button class="glBut" type="primary" @click="image_id===0?addImageToBark():updateImageToBark()">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>运行时间</el-col>
|
||||
<el-col>{{info.start_time}}</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
</template>
|
||||
<footer class="anDiv">
|
||||
<el-button class="glBut" type="primary" @click="CustomizationImageFales">关闭</el-button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -375,19 +176,85 @@
|
||||
import { highlight, languages } from 'prismjs/components/prism-core';
|
||||
import 'prismjs/components/prism-clike';
|
||||
import 'prismjs/components/prism-javascript';
|
||||
// import 'prismjs/themes/prism-solarizedlight.css'; // 代码的其他样式风格
|
||||
// import 'prismjs/themes/prism-coy.css';
|
||||
// import 'prismjs/themes/prism-tomorrow.css';
|
||||
import 'prismjs/themes/prism.css'; // 如果想代码换个样式风格,把这个注释了,上面的三个放开一个
|
||||
import Header from './module/Header.vue'
|
||||
|
||||
export default {
|
||||
name: "imageMange",
|
||||
// props:['fTag','fInput','fFrom','FIsConfigQuery'],
|
||||
// components:{
|
||||
// router
|
||||
// },
|
||||
components: { PrismEditor },
|
||||
components: { PrismEditor ,Header},
|
||||
data(){
|
||||
return{
|
||||
infoTable: [
|
||||
{
|
||||
id: 1,
|
||||
title: "用户ID",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "微信昵称",
|
||||
value:2,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "会员名称",
|
||||
value:3,
|
||||
}
|
||||
],
|
||||
info:[],
|
||||
powerValue:'',
|
||||
stateValue:'',
|
||||
freeValue:'',
|
||||
powerFilter:[
|
||||
{
|
||||
value:'全部',
|
||||
label:'全部'
|
||||
},
|
||||
{
|
||||
value:'渗透',
|
||||
label:'渗透'
|
||||
},
|
||||
{
|
||||
value:'状态感知',
|
||||
label:'状态感知'
|
||||
},
|
||||
{
|
||||
value:'参数感知',
|
||||
label:'参数感知'
|
||||
},
|
||||
],
|
||||
stateFilter:[
|
||||
{
|
||||
value:'全部',
|
||||
label:'全部'
|
||||
},
|
||||
{
|
||||
value:'在线',
|
||||
label:'在线'
|
||||
},
|
||||
{
|
||||
value:'离线',
|
||||
label:'离线'
|
||||
},
|
||||
],
|
||||
freeFilter:[
|
||||
{
|
||||
value:'全部',
|
||||
label:'全部'
|
||||
},
|
||||
{
|
||||
value:'空闲',
|
||||
label:'空闲'
|
||||
},
|
||||
{
|
||||
value:'执行中',
|
||||
label:'执行中'
|
||||
},
|
||||
],
|
||||
file:'',
|
||||
image_id:0,
|
||||
addImage:{
|
||||
@@ -427,7 +294,6 @@
|
||||
code: '/**\n* JS判断两个数组是否相等\n* @param {Array} arr1\n* @param {Array} arr2\n* @returns {boolean} 返回true 或 false\n*/\nfunction arrayEqual(arr1, arr2) {\n if (arr1 === arr2) return true;\n if (arr1.length != arr2.length) return false;\n for (var i = 0; i < arr1.length; ++i) {\n if (arr1[i] !== arr2[i]) return false;\n }\n return true;\n}',
|
||||
infoType:"",
|
||||
tag:"基本配置",
|
||||
tagStep:1,
|
||||
tableData:[],
|
||||
total:0,
|
||||
multipleSelection: [],
|
||||
@@ -449,19 +315,6 @@
|
||||
radioOwnership2: '1',
|
||||
radioUpdateImage: '2',
|
||||
radioHowToCreate: '1',
|
||||
options: [{
|
||||
value: '',
|
||||
label: '全部镜像'
|
||||
}, {
|
||||
value: 'system',
|
||||
label: '系统'
|
||||
}, {
|
||||
value: 'buildin',
|
||||
label: '内置'
|
||||
}, {
|
||||
value: 'define',
|
||||
label: '自定义'
|
||||
}],
|
||||
delTimer: null,
|
||||
counter: 0
|
||||
|
||||
@@ -472,7 +325,8 @@
|
||||
watch: {
|
||||
},
|
||||
created() {
|
||||
this.getImages()
|
||||
// this.getImages()
|
||||
this.query();
|
||||
},
|
||||
destroyed() {
|
||||
// if (this.pendingTimer) {
|
||||
@@ -486,6 +340,50 @@
|
||||
this.counter = 0
|
||||
},
|
||||
methods:{
|
||||
formatIPs(row, column, cellValue) {
|
||||
// let formattedIPs = cellValue.join(',\n');
|
||||
// return formattedIPs;
|
||||
// 使用 map 方法处理每个 IP 地址,然后连接成带有换行符的字符串
|
||||
let formattedIPs = cellValue.map(ip => ip).join(',\n');
|
||||
|
||||
return formattedIPs;
|
||||
|
||||
},
|
||||
query(){
|
||||
let data={
|
||||
"page":this.page,
|
||||
"per_page":this.size,
|
||||
"atype":this.powerValue==='参数感知'?'csgz':(this.powerValue==='状态感知'?'ztgz':(this.powerValue==='渗透'?'gjst':'all')),
|
||||
"status":this.stateValue==='在线'?1:(this.stateValue==='离线'?0:2),
|
||||
"idle":this.freeValue==='空闲'?1:(this.stateValue==='执行中'?0:2)
|
||||
}
|
||||
this.$axios.get(this.$http.api.agentQueryList,data).then(res=>{
|
||||
if(res.code===200){
|
||||
this.tableData=res.agent_data
|
||||
this.total=res.total
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
agentdel(val){
|
||||
let data={
|
||||
"id":val.toString(),
|
||||
}
|
||||
this.$axios.post(this.$http.api.agentDel,data).then(res=>{
|
||||
if(res.code===200){
|
||||
this.$message.success(res.msg)
|
||||
}else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
onFileChange(event) {
|
||||
this.file = event.target.files[0];
|
||||
},
|
||||
@@ -502,9 +400,6 @@
|
||||
|
||||
},
|
||||
thereToOne(val){
|
||||
console.log("RRRRRRRRRRRRRRRRRRRRRRRRR")
|
||||
console.log(val)
|
||||
console.log("RRRRRRRRRRRRRRRRRRRRRRRRR")
|
||||
if(val==='tar'){
|
||||
this.dockerOrTar='tar'
|
||||
}else {
|
||||
@@ -525,30 +420,14 @@
|
||||
CustomizationImageFales(){
|
||||
this.newlyPztj=false;
|
||||
document.querySelector('.mask').style.display = 'none'
|
||||
this.image_id=0
|
||||
this.addImage=this.barkImageParmer
|
||||
},
|
||||
customizationImage(val){
|
||||
this.tagStep=1;
|
||||
this.tag="基本配置"
|
||||
if(val!=null){
|
||||
this.image_id=val.id
|
||||
this.addImage=val
|
||||
this.infoImage(this.image_id);
|
||||
this.thereToOne(val.define_image[0].establish_mode)
|
||||
}
|
||||
this.newlyPztj=true;
|
||||
document.querySelector('.mask').style.display = 'block'
|
||||
},
|
||||
getLabel(boolValue) {
|
||||
return boolValue ? true: false;
|
||||
// this.image_id=0
|
||||
// this.addImage=this.barkImageParmer
|
||||
},
|
||||
buildImage(val){
|
||||
let data={
|
||||
"image_id":val,
|
||||
}
|
||||
this.$axios.get(this.$http.api.asyncBuildImage,data).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.CustomizationImageFales()
|
||||
|
||||
@@ -578,7 +457,6 @@
|
||||
"image_id":val,
|
||||
}
|
||||
this.$axios.get(this.$http.api.infoImage,data).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.addImage.git_account=res.result.pipeline.git_account;
|
||||
this.addImage.git_password=res.result.pipeline.git_password;
|
||||
@@ -598,7 +476,6 @@
|
||||
"image_id":val,
|
||||
}
|
||||
this.$axios.delete(this.$http.api.delImage,data).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.image_id=0
|
||||
this.getImages()
|
||||
@@ -630,7 +507,6 @@
|
||||
// }
|
||||
};
|
||||
this.$axios.put(this.$http.api.asyncUpdateImage, formData ,config).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.CustomizationImageFales()
|
||||
|
||||
@@ -707,59 +583,37 @@
|
||||
})
|
||||
|
||||
},
|
||||
updateAndQuery(){
|
||||
this.page=1;
|
||||
this.getImages()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
console.log(`每页 ${val} 条`);
|
||||
this.size=val
|
||||
this.getImages()
|
||||
this.query()
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
console.log(`当前页: ${val}`);
|
||||
this.page=val
|
||||
this.getImages()
|
||||
this.query()
|
||||
},
|
||||
getImages(){
|
||||
let data={
|
||||
// "image_name":"da",
|
||||
"image_type":this.selectImageStateValue,
|
||||
"image_name":this.queryByImageName,
|
||||
"image_state":this.selectImageStateValue,
|
||||
"page":this.page,
|
||||
"size":this.size
|
||||
|
||||
}
|
||||
this.$axios.get(this.$http.api.getImages,data).then(res=>{
|
||||
this.$axios.get(this.$http.api.agentQueryList,data).then(res=>{
|
||||
console.log('getImages======',res)
|
||||
if(res.code===200){
|
||||
this.tableData=res.result.items
|
||||
this.total=res.result.total
|
||||
}
|
||||
// if(res.code===200){
|
||||
this.tableData=res.agent_data
|
||||
this.total=100
|
||||
// }
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
selectImageState(){
|
||||
this.page=1
|
||||
console.log(this.selectImageStateValue)
|
||||
this.getImages()
|
||||
},
|
||||
NobuildingImage(){
|
||||
console.log("无需重新构建")
|
||||
},
|
||||
highlighter(code) {
|
||||
return highlight(code, languages.js)
|
||||
},
|
||||
getInfo(info){
|
||||
getInfo(val){
|
||||
this.info=val
|
||||
this.newlyPztj=true
|
||||
document.querySelector('.mask').style.display = 'block'
|
||||
this.addImage=info;
|
||||
if(info.define_image[0].establish_mode==='tar'){
|
||||
this.infoType='tar'
|
||||
}else if(info.define_image[0].establish_mode==='git'
|
||||
|| info.define_image[0].establish_mode==='code'){
|
||||
this.infoType='docker'
|
||||
}
|
||||
},
|
||||
updateTag(val){
|
||||
this.tag=val
|
||||
@@ -768,19 +622,15 @@
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
handleRemove(file, fileList) {
|
||||
console.log("111111111")
|
||||
console.log(file, fileList);
|
||||
},
|
||||
handlePreview(file) {
|
||||
console.log("2222222222222")
|
||||
console.log(file);
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
console.log("3333333333333")
|
||||
this.$notify.warning(`当前限制选择 1个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
|
||||
},
|
||||
beforeRemove(file, fileList) {
|
||||
console.log("444444444444")
|
||||
return this.$confirm(`确定移除 ${ file.name }?`);
|
||||
},
|
||||
// 获取任务进度
|
||||
@@ -825,12 +675,42 @@
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped="scoped">
|
||||
.state{
|
||||
display: inline-block;
|
||||
height: auto;
|
||||
width: 10%;
|
||||
margin-left: 0.5%;
|
||||
.custom-popper .el-select-dropdown {
|
||||
max-height: 3px;
|
||||
}
|
||||
}
|
||||
.project{
|
||||
display: inline-block;
|
||||
height: auto;
|
||||
width: 10%;
|
||||
margin-left: 0.5%;
|
||||
margin-right: 3%;
|
||||
.el-input::placeholder {
|
||||
width: auto;
|
||||
}
|
||||
.icon-group {
|
||||
display: flex; /* 设置容器为 Flexbox 容器 */
|
||||
align-items: center; /* 垂直居中图片 */
|
||||
gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */
|
||||
|
||||
}
|
||||
.icon-group img {
|
||||
transform: scale(1);
|
||||
margin-right: 15px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
}
|
||||
.custom-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.my-editor {
|
||||
/*background: #fa3919;*/
|
||||
background: transparent;
|
||||
/*color: #000;*/
|
||||
color: #fafafa;
|
||||
@@ -843,9 +723,7 @@
|
||||
}
|
||||
|
||||
.my-editor ::v-deep .prism-editor__textarea::selection{
|
||||
/*background-color: #cce2ff !important;*/
|
||||
background-color: #322dff !important;
|
||||
/*color: #000 !important;*/
|
||||
color: #ed1210 !important;
|
||||
user-select:none;
|
||||
}
|
||||
@@ -860,10 +738,9 @@
|
||||
}
|
||||
.popup{
|
||||
z-index: 997;
|
||||
width: 40%;
|
||||
height: 70%;
|
||||
width: 43%;
|
||||
height: 75%;
|
||||
position: absolute; /* 绝对定位 */
|
||||
/*position: relative;*/
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
@@ -882,12 +759,15 @@
|
||||
}
|
||||
}
|
||||
.jbpz{
|
||||
margin-top: 10%;
|
||||
margin-left: 15%;
|
||||
height: 100%;
|
||||
width: 70%;
|
||||
text-align: center;
|
||||
position:relative;
|
||||
.project{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
/*float: left;*/
|
||||
margin-top: 3%;
|
||||
text-align: center;
|
||||
padding-right: 10%;
|
||||
@@ -949,16 +829,12 @@
|
||||
bottom:4%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
/*margin-bottom: 2%;*/
|
||||
/*width: 100%;*/
|
||||
/*text-align: center;*/
|
||||
.glBut{
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/*margin-left: 10%;*/
|
||||
background-color: rgba(24, 133, 234, 0.2);
|
||||
color: #1b7cc4;
|
||||
}
|
||||
@@ -969,8 +845,6 @@
|
||||
.range-manage{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/*background-color: #010f4e;*/
|
||||
/*background-color: rgba(255, 25, 49, 0.4);*/
|
||||
float: right;
|
||||
position: relative; /* 确保相对定位生效 */
|
||||
.infoTar{
|
||||
@@ -994,16 +868,13 @@
|
||||
.container{
|
||||
|
||||
width: 85%;
|
||||
/*background-color: #af321e;*/
|
||||
.row {
|
||||
width: 100%;
|
||||
.cell {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
/*background-color: #2daf23;*/
|
||||
padding: 10px;
|
||||
/*border: 1px solid #ccc;*/
|
||||
border: none;
|
||||
text-align: left;
|
||||
font-size: 18px;
|
||||
@@ -1013,9 +884,7 @@
|
||||
float: left;
|
||||
display: inline-block;
|
||||
width: 51%;
|
||||
/*background-color: #2daf23;*/
|
||||
padding: 10px;
|
||||
/*border: 1px solid #ccc;*/
|
||||
border: none;
|
||||
text-align: left;
|
||||
font-size: 18px;
|
||||
@@ -1174,8 +1043,7 @@
|
||||
}
|
||||
.list{
|
||||
width: 95%;
|
||||
height: 84%;
|
||||
/*max-height: 84%;*/
|
||||
height: 76%;
|
||||
margin-left: 2.5%;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
@@ -1194,30 +1062,30 @@
|
||||
// scrollbar-width: none;
|
||||
// }
|
||||
// }
|
||||
.page{
|
||||
width: 95%;
|
||||
height: 5%;
|
||||
margin-left: 2%;
|
||||
/*background-color: #ec171d;*/
|
||||
padding-left: 35%;
|
||||
padding-top: 0.9%;
|
||||
.el-pagination {
|
||||
transform: scale(1.5);
|
||||
}
|
||||
.el-pagination .btn-next, .el-pagination .btn-prev {
|
||||
background: #0b6f08 !important;
|
||||
color: #00F1FF !important;
|
||||
}
|
||||
/*.el-pagination .number:not(.active) {*/
|
||||
/* background-color: red !important;*/
|
||||
/* color: white;*/
|
||||
/*}*/
|
||||
/*.el-pagination button:disabled{*/
|
||||
/* background-color: #a10e0e;*/
|
||||
/*}*/
|
||||
/*.page{*/
|
||||
/* width: 95%;*/
|
||||
/* height: 5%;*/
|
||||
/* margin-left: 2%;*/
|
||||
/* !*background-color: #ec171d;*!*/
|
||||
/* padding-left: 35%;*/
|
||||
/* padding-top: 0.9%;*/
|
||||
/* .el-pagination {*/
|
||||
/* transform: scale(1.5);*/
|
||||
/* }*/
|
||||
/* .el-pagination .btn-next, .el-pagination .btn-prev {*/
|
||||
/* background: #0b6f08 !important;*/
|
||||
/* color: #00F1FF !important;*/
|
||||
/* }*/
|
||||
/* !*.el-pagination .number:not(.active) {*!*/
|
||||
/* !* background-color: red !important;*!*/
|
||||
/* !* color: white;*!*/
|
||||
/* !*}*!*/
|
||||
/* !*.el-pagination button:disabled{*!*/
|
||||
/* !* background-color: #a10e0e;*!*/
|
||||
/* !*}*!*/
|
||||
|
||||
|
||||
}
|
||||
/*}*/
|
||||
// 遮罩层
|
||||
.mask{
|
||||
position: fixed; /*将元素设置为固定定位*/
|
||||
|
||||
@@ -1,75 +1,90 @@
|
||||
<template>
|
||||
<div class="range-config-manage" ref="appRef">
|
||||
<div class="show">
|
||||
<Header
|
||||
></Header>
|
||||
<div class="list" >
|
||||
<el-table
|
||||
class="custom-table"
|
||||
ref="multipleTable"
|
||||
v-loading="loading"
|
||||
element-loading-text="加载中..."
|
||||
height="100%"
|
||||
style="width: 100%;"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
align="center"
|
||||
type="index"
|
||||
label="序号"
|
||||
width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="country_name"
|
||||
label="介绍名称"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="network_count"
|
||||
label="网段数"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="used_ip_count"
|
||||
label="已用ip数"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="unused_ip_count"
|
||||
label="未用ip数"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="create_time"
|
||||
label="创建时间"
|
||||
min-width="150">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.create_time | formatTime }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
min-width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="medium" :loading="scope.row.delLoading" >详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <Header-->
|
||||
<!-- ></Header>-->
|
||||
<div>
|
||||
<span style="font-size: 20px;margin-bottom: 1%;margin-top: 2%;float: left;margin-left: 3%;color: #00C0FF">能力指代不同渗透策略,代理将根据策略逻辑以及主控端下发的生成参数生成对应的载荷</span>
|
||||
</div>
|
||||
<div class="list" id="show-loading">
|
||||
<div class="single" v-for="rangeItem in rangeList" :key="rangeItem.target_name">
|
||||
<div class="title">
|
||||
<el-tag type="success" style="margin-right: 2%">标签二</el-tag>
|
||||
<el-tag>标签一</el-tag>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row" >
|
||||
<span style="float: left;margin-left: 2%;font-size: 20px;color: #efefef"> IPV6 DDOS</span>
|
||||
<div style="margin-left: auto;">
|
||||
<el-button size="mini" type="primary" @click="getInfo(rangeItem)">详情</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<span style="word-wrap: break-word;">
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkklllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="10"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
>
|
||||
</el-pagination>
|
||||
<div class="mask"></div>
|
||||
<div class="popup" v-if="newlyPztj">
|
||||
<!-- 在此处指定弹窗的样式和内容 -->
|
||||
<i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 2.8%" @click="CustomizationImageFales()"></i>
|
||||
<span style="color: #f5f7f0;font-size: 20px;float: left;margin-left: 6%;margin-top: 1%">详情999</span>
|
||||
<div class="jbpz">
|
||||
<template>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col :span="20">当前状态</el-col>
|
||||
<el-col :span="20">离线</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>编号</el-col>
|
||||
<el-col>999</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>通信端口</el-col>
|
||||
<el-col>3706</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>运行平台</el-col>
|
||||
<el-col>linux</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>IP地址</el-col>
|
||||
<el-col>1.1.1.1</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>CPU核心数</el-col>
|
||||
<el-col>9</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>系统内存</el-col>
|
||||
<el-col>85G</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
<el-row style="display: flex; flex-direction: row;">
|
||||
<el-col>运行时间</el-col>
|
||||
<el-col>55天</el-col>
|
||||
</el-row>
|
||||
<el-divider content-position="center"></el-divider>
|
||||
|
||||
</template>
|
||||
<footer class="anDiv">
|
||||
<el-button class="glBut" type="primary" @click="CustomizationImageFales">关闭</el-button>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-drawer
|
||||
title=""
|
||||
:visible.sync="drawer"
|
||||
@@ -85,13 +100,41 @@ export default {
|
||||
components:{ Header},
|
||||
data(){
|
||||
return{
|
||||
newlyPztj:false,
|
||||
info:{},
|
||||
drawer: false,
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
isAdd: false,
|
||||
loading: false,
|
||||
tableData: []
|
||||
tableData: [],
|
||||
|
||||
rangeList:[
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
@@ -99,12 +142,128 @@ export default {
|
||||
created() {
|
||||
},
|
||||
methods:{
|
||||
getInfo(val){
|
||||
this.info=val
|
||||
this.newlyPztj=true
|
||||
document.querySelector('.mask').style.display = 'block'
|
||||
},
|
||||
CustomizationImageFales(){
|
||||
this.newlyPztj=false;
|
||||
document.querySelector('.mask').style.display = 'none'
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped="scoped">
|
||||
.popup{
|
||||
z-index: 997;
|
||||
width: 43%;
|
||||
height: 75%;
|
||||
position: absolute; /* 绝对定位 */
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
background-image:url('../../img/tjpz.svg');
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
.tag{
|
||||
margin-left: 9%;
|
||||
.tags{
|
||||
margin-right: 5%;
|
||||
margin-top: 2%;
|
||||
font-size: 23px;
|
||||
border: none;
|
||||
background-color: transparent !important;
|
||||
color: #565e6e;
|
||||
}
|
||||
}
|
||||
.jbpz{
|
||||
margin-top: 10%;
|
||||
margin-left: 15%;
|
||||
height: 100%;
|
||||
width: 70%;
|
||||
text-align: center;
|
||||
position:relative;
|
||||
.project{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-top: 3%;
|
||||
text-align: center;
|
||||
padding-right: 10%;
|
||||
|
||||
}
|
||||
.tar{
|
||||
display: flex;
|
||||
margin-left: 23%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
::v-deep .el-upload-list {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
width: 300px !important;
|
||||
padding-left: 20%;
|
||||
}
|
||||
.uploadBgImg{
|
||||
margin-top: 5%;
|
||||
width: 300px;
|
||||
height: 40px;
|
||||
background-image: url("../../img/shangchuan.png");
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% auto; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
text-align: right;
|
||||
padding-right: 10%;
|
||||
padding-top: 2%;
|
||||
font-size:0;
|
||||
color: rgba(81, 84, 102, 0.84);
|
||||
}
|
||||
.uploadBgImg::file-selector-button{
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
.srkType{
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin-top: 2%;
|
||||
text-align: center;
|
||||
.srk{
|
||||
width: 40%;
|
||||
margin-left: 2%;
|
||||
background-color: #0c295b;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.radioType{
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin-top: 2%;
|
||||
text-align: center;
|
||||
}
|
||||
.anType{
|
||||
height: 10%;
|
||||
position:absolute;
|
||||
bottom:4%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.glBut{
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(24, 133, 234, 0.2);
|
||||
color: #1b7cc4;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -134,20 +293,92 @@ export default {
|
||||
/*justify-content: center; !* 水平居中子元素 *!*/
|
||||
/*align-items: center; !* 垂直居中子元素 *!*/
|
||||
|
||||
/*.list{*/
|
||||
/* width: 95%;*/
|
||||
/* height: 84%;*/
|
||||
/* margin-left: 2.5%;*/
|
||||
/* overflow-y: auto;*/
|
||||
/* overflow-y: scroll;*/
|
||||
/* overflow-x: hidden;*/
|
||||
/* border: none;*/
|
||||
/*}*/
|
||||
/*.list::-webkit-scrollbar {*/
|
||||
/* width: 0px; !* 隐藏滚动条 *!*/
|
||||
/* height: 0px;*/
|
||||
/* background-color: transparent; !* 让背景透明 *!*/
|
||||
|
||||
/*}*/
|
||||
.list{
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
width: 95%;
|
||||
height: 84%;
|
||||
margin-left: 2.5%;
|
||||
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
border: none;
|
||||
}
|
||||
.list::-webkit-scrollbar {
|
||||
width: 0px; /* 隐藏滚动条 */
|
||||
height: 0px;
|
||||
background-color: transparent; /* 让背景透明 */
|
||||
|
||||
.single:hover{
|
||||
border: 1px solid #159dd3;
|
||||
}
|
||||
.single{
|
||||
width: 32%;
|
||||
height: 25.5%;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(186, 208, 241, 0.10);
|
||||
background: rgba(25, 33, 61, 0.40);
|
||||
margin-left: 1.2%;
|
||||
margin-bottom: 0.9%;
|
||||
padding: 20px;
|
||||
display: inline-block;
|
||||
.title{
|
||||
text-align: left;
|
||||
}
|
||||
.container{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 10px 0 10px 0;
|
||||
.row {
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.cell {
|
||||
flex-grow: 1;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border: none;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cell.small {
|
||||
flex-basis: 33.5%;
|
||||
}
|
||||
|
||||
.cell.large {
|
||||
flex-basis: 66.5%;
|
||||
}
|
||||
}
|
||||
.buttons{
|
||||
text-align: left;
|
||||
|
||||
.glBut{
|
||||
width: 80px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// margin-left: 2%;
|
||||
background-color: rgba(14, 61, 138, 0.50);
|
||||
color: #02DDEA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 隐藏火狐浏览器滚动条 */
|
||||
@-moz-document url-prefix() {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="head">
|
||||
<div class="target-select">
|
||||
<span style="font-size: 14px;float: left;padding-top: 1%">系统介绍页面</span>
|
||||
</div>
|
||||
<div class="input">
|
||||
<el-input v-model="country_name" placeholder="查询" suffix icon="">
|
||||
<template v-slot:suffix>
|
||||
<div class="icon-group">
|
||||
<img src="../../../img/inputl.png" alt="**">
|
||||
<img src="../../../img/inputIcon.png" alt="*" @click="query">
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
<span style="font-size: 24px;float: left;padding-top: 1%">能力指代不同渗透策略,代理将根据策略逻辑以及主控端下发的生成参数生成对应的载荷</span>
|
||||
</div>
|
||||
<!-- <div class="input">-->
|
||||
<!-- <el-input v-model="country_name" placeholder="查询" suffix icon="">-->
|
||||
<!-- <template v-slot:suffix>-->
|
||||
<!-- <div class="icon-group">-->
|
||||
<!-- <img src="../../../img/inputl.png" alt="**">-->
|
||||
<!-- <img src="../../../img/inputIcon.png" alt="*" @click="query">-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
<template>
|
||||
<div class="range-config-manage" ref="appRef">
|
||||
<div class="show">
|
||||
<Header
|
||||
></Header>
|
||||
<div class="list" >
|
||||
<el-table
|
||||
class="custom-table"
|
||||
ref="multipleTable"
|
||||
v-loading="loading"
|
||||
element-loading-text="加载中..."
|
||||
height="100%"
|
||||
style="width: 100%;"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column
|
||||
align="center"
|
||||
type="index"
|
||||
label="序号"
|
||||
width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="username"
|
||||
label="名称"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="role_name"
|
||||
label="角色"
|
||||
min-width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
min-width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" :loading="scope.row.delLoading" >详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="10"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
>
|
||||
</el-pagination>
|
||||
<div class="mask"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Header from './module/Header.vue'
|
||||
export default {
|
||||
name: "RangeConfigManage",
|
||||
components:{ Header },
|
||||
data(){
|
||||
return{
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
watch: {},
|
||||
created() {
|
||||
},
|
||||
methods:{
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped="scoped">
|
||||
.custom-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.range-config-manage{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/*background-color: #010f4e;*/
|
||||
// background-color: rgba(255, 25, 49, 0.4);
|
||||
float: right;
|
||||
position: relative; /* 确保相对定位生效 */
|
||||
|
||||
.show{
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
/*background-color: #67c23a;*/
|
||||
position: absolute; /* 绝对定位 */
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
background-image:url('../../img/backgroundFourCorner.png');
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
|
||||
.list{
|
||||
width: 95%;
|
||||
height: 84%;
|
||||
margin-left: 2.5%;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
border: none;
|
||||
}
|
||||
.list::-webkit-scrollbar {
|
||||
width: 0px; /* 隐藏滚动条 */
|
||||
height: 0px;
|
||||
background-color: transparent; /* 让背景透明 */
|
||||
|
||||
}
|
||||
/* 隐藏火狐浏览器滚动条 */
|
||||
@-moz-document url-prefix() {
|
||||
.trackSource {
|
||||
scrollbar-width: none;
|
||||
}
|
||||
}
|
||||
// 遮罩层
|
||||
.mask{
|
||||
position: fixed; /*将元素设置为固定定位*/
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0,0,0,0.5); /*通过rgba函数来控制遮罩层的透明度*/
|
||||
display: none; /*将元素隐藏*/
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<div class="head">
|
||||
<div class="target-select">
|
||||
<span style="font-size: 14px;float: left;padding-top: 1%">系统管理页面</span>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<el-input v-model="username" placeholder="名称查询输入" suffix icon="" >
|
||||
<template v-slot:suffix>
|
||||
<div class="icon-group">
|
||||
<img src="../../../img/inputl.png" alt="**">
|
||||
<img src="../../../img/inputIcon.png" alt="*" @click="query">
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Header',
|
||||
props: [],
|
||||
data() {
|
||||
return {
|
||||
username: ''
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
// 新增
|
||||
addUser() {
|
||||
this.$emit('addUser')
|
||||
},
|
||||
// 查询
|
||||
query() {
|
||||
let params = {}
|
||||
if (this.username !== '') {
|
||||
params.username = this.username
|
||||
}
|
||||
this.$emit('query', params)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.head{
|
||||
width: 95%;
|
||||
height: 7%;
|
||||
margin-top: 1%;
|
||||
margin-left: 2.5%;
|
||||
text-align: right;
|
||||
.target-select{
|
||||
font-size: 10px;
|
||||
float: left;
|
||||
margin-top: 0.5%;
|
||||
display: inline-block;
|
||||
height: 60%;
|
||||
width: 10%;
|
||||
margin-left: 0.5%;
|
||||
}
|
||||
.add-btn {
|
||||
height: 70%;
|
||||
width: 10%;
|
||||
margin-right: 2%;
|
||||
color: #ffffff;
|
||||
}
|
||||
.input{
|
||||
display: inline-block;
|
||||
height: 60%;
|
||||
width: 10%;
|
||||
margin-left: 0.5%;
|
||||
.el-input::placeholder {
|
||||
width: auto;
|
||||
}
|
||||
.icon-group {
|
||||
display: flex; /* 设置容器为 Flexbox 容器 */
|
||||
align-items: center; /* 垂直居中图片 */
|
||||
gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */
|
||||
}
|
||||
.icon-group img {
|
||||
transform: scale(1);
|
||||
margin-right: 15px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,6 +4,9 @@
|
||||
<Header
|
||||
@addRole="addRole"
|
||||
></Header>
|
||||
<div>
|
||||
<span style="font-size: 20px;margin-bottom: 1%;margin-top: 0.5%;float: left;margin-left: 3%;color: #00C0FF">至少需要一个代理才能创建任务,每个代理同时只执行一项任务</span>
|
||||
</div>
|
||||
<div class="list" >
|
||||
<el-table
|
||||
class="custom-table"
|
||||
@@ -23,31 +26,38 @@
|
||||
width="150"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="role_name"
|
||||
label="角色"
|
||||
width="200"/>
|
||||
prop="id"
|
||||
label="任务编号"
|
||||
width="280"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="agent"
|
||||
label="执行代理编号"
|
||||
width="280"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="permissions"
|
||||
label="权限"
|
||||
prop="status"
|
||||
label="当前状态"
|
||||
min-width="150">
|
||||
<template slot-scope="scope">
|
||||
<div class="permission-btn" v-for="permission in scope.row.permissions" :key="scope.row.id + '' + permission.id">
|
||||
<span v-loading="permission.delLoading">
|
||||
{{ permission.permission_name }}
|
||||
</span>
|
||||
<svg-icon icon-class="closeBtn" @click="delPermission(permission, scope.row.id)"></svg-icon>
|
||||
</div>
|
||||
<el-tag type="info" v-if="scope.row.status==='stop'">暂停</el-tag>
|
||||
<el-tag type="warning" v-if="scope.row.status==='working'">执行中</el-tag>
|
||||
<el-tag type="danger" v-if="scope.row.status==='finish'">已完成</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="create_time"
|
||||
label="创建时间"
|
||||
width="280"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="操作"
|
||||
width="200"
|
||||
width="250"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="medium" @click="edit(scope.row)">修改权限</el-button>
|
||||
<el-button type="text" size="small" :loading="scope.row.delLoading" @click="del(scope.row)">删除</el-button>
|
||||
<el-button type="text" size="medium" @click="taskInfo(scope.row)">详情</el-button>
|
||||
<el-button type="text" size="small" @click="del(scope.row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -56,7 +66,7 @@
|
||||
background
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 30, 40]"
|
||||
:page-size="10"
|
||||
:page-size="20"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="handleSizeChange"
|
||||
@@ -83,7 +93,7 @@ export default {
|
||||
data(){
|
||||
return{
|
||||
page: 1,
|
||||
size: 10,
|
||||
size: 20,
|
||||
total: 0,
|
||||
isAdd: false,
|
||||
loading: false,
|
||||
@@ -97,25 +107,22 @@ export default {
|
||||
},
|
||||
watch: {},
|
||||
created() {
|
||||
this.getPermissionDict()
|
||||
this.init()
|
||||
},
|
||||
methods:{
|
||||
init(params={}) {
|
||||
// this.tableData = getTargetsResponse?.result?.items
|
||||
// this.total = getTargetsResponse?.result?.total
|
||||
|
||||
// TODO: 暂时注释接口
|
||||
const reqParams = {
|
||||
page: this.page,
|
||||
size: this.size,
|
||||
"page": this.page,
|
||||
"per_page": this.size,
|
||||
...params
|
||||
}
|
||||
this.loading = true
|
||||
this.$axios.get(this.$http.api.getRoleList, reqParams).then(res => {
|
||||
if (res.code == 200 || res.code == "OK") {
|
||||
this.total = res?.result?.total
|
||||
this.tableData = res?.result?.items
|
||||
this.$axios.get(this.$http.api.taskList, reqParams).then(res => {
|
||||
// if (res.code == 200 || res.code == "OK") {
|
||||
// this.total = res?.data?.total
|
||||
this.total = 100
|
||||
this.tableData = res?.data
|
||||
this.tableData.map(item => {
|
||||
item.permissions.map(permi => {
|
||||
this.$set(permi, 'delLoading', false)
|
||||
@@ -123,7 +130,7 @@ export default {
|
||||
})
|
||||
return item
|
||||
})
|
||||
}
|
||||
// }
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
}).finally(() => {
|
||||
@@ -136,7 +143,7 @@ export default {
|
||||
// 打开添加角色dialog
|
||||
addRole() {
|
||||
this.isAdd = true
|
||||
this.$refs.userForm.title = '新增角色'
|
||||
// this.$refs.userForm.title = '新增角色'
|
||||
document.querySelector('.mask').style.display = 'block'
|
||||
this.$refs.userForm.visible = true
|
||||
},
|
||||
@@ -160,18 +167,18 @@ export default {
|
||||
})
|
||||
},
|
||||
// 删除
|
||||
del(row) {
|
||||
this.$confirm('此操作将永久删除该角色, 是否继续?', '确认删除', {
|
||||
confirmButtonText: '确认删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'info'
|
||||
}).then(() => {
|
||||
this.delUser(row)
|
||||
}).catch(() => {
|
||||
this.$notify({
|
||||
type: 'info',
|
||||
message: '已取消删除'
|
||||
})
|
||||
del(id) {
|
||||
let data={
|
||||
"id":id,
|
||||
}
|
||||
this.$axios.post(this.$http.api.taskDel,data).then(res=>{
|
||||
if(res.code===200){
|
||||
this.$message.success(res.msg)
|
||||
}else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
},
|
||||
delUser(row) {
|
||||
@@ -192,16 +199,9 @@ export default {
|
||||
row.delLoading = false
|
||||
})
|
||||
},
|
||||
// 修改
|
||||
edit(row) {
|
||||
this.isAdd = false
|
||||
this.$refs.userForm.title = '修改权限'
|
||||
this.$refs.userForm.role_id = row.id
|
||||
this.$refs.userForm.form.role_name = row.role_name
|
||||
this.$refs.userForm.form.permissions = row.permissions.map(permission => permission.id)
|
||||
this.getPermissionDict()
|
||||
document.querySelector('.mask').style.display = 'block'
|
||||
this.$refs.userForm.visible = true
|
||||
// 详情
|
||||
taskInfo(val) {
|
||||
this.$router.push({ path: 'menuTaskInfo', query: { row: val } });
|
||||
},
|
||||
// 获取权限字典
|
||||
getPermissionDict() {
|
||||
@@ -241,6 +241,110 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped="scoped">
|
||||
.popup{
|
||||
z-index: 997;
|
||||
width: 40%;
|
||||
height: 70%;
|
||||
position: absolute; /* 绝对定位 */
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
background-image:url('../../img/tjpz.svg');
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
.tag{
|
||||
margin-left: 9%;
|
||||
.tags{
|
||||
margin-right: 5%;
|
||||
margin-top: 2%;
|
||||
font-size: 23px;
|
||||
border: none;
|
||||
background-color: transparent !important;
|
||||
color: #565e6e;
|
||||
}
|
||||
}
|
||||
.jbpz{
|
||||
margin-top: 10%;
|
||||
margin-left: 23%;
|
||||
height: 100%;
|
||||
position:relative;
|
||||
.project{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin-top: 3%;
|
||||
text-align: center;
|
||||
padding-right: 10%;
|
||||
|
||||
}
|
||||
.tar{
|
||||
display: flex;
|
||||
margin-left: 23%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
::v-deep .el-upload-list {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
width: 300px !important;
|
||||
padding-left: 20%;
|
||||
}
|
||||
.uploadBgImg{
|
||||
margin-top: 5%;
|
||||
width: 300px;
|
||||
height: 40px;
|
||||
background-image: url("../../img/shangchuan.png");
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% auto; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
text-align: right;
|
||||
padding-right: 10%;
|
||||
padding-top: 2%;
|
||||
font-size:0;
|
||||
color: rgba(81, 84, 102, 0.84);
|
||||
}
|
||||
.uploadBgImg::file-selector-button{
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
.srkType{
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin-top: 2%;
|
||||
text-align: center;
|
||||
.srk{
|
||||
width: 40%;
|
||||
margin-left: 2%;
|
||||
background-color: #0c295b;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.radioType{
|
||||
width: 100%;
|
||||
float: left;
|
||||
margin-top: 2%;
|
||||
text-align: center;
|
||||
}
|
||||
.anType{
|
||||
height: 10%;
|
||||
position:absolute;
|
||||
bottom:4%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
.glBut{
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgba(24, 133, 234, 0.2);
|
||||
color: #1b7cc4;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.custom-table {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -280,7 +384,7 @@ export default {
|
||||
|
||||
.list{
|
||||
width: 95%;
|
||||
height: 84%;
|
||||
height: 77%;
|
||||
margin-left: 2.5%;
|
||||
overflow-y: auto;
|
||||
overflow-y: scroll;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<template>
|
||||
<div class="head">
|
||||
<div class="target-select">
|
||||
<span style="font-size: 14px;float: left;padding-top: 1%">角色列表</span>
|
||||
<span style="font-size: 30px;float: left;padding-top: 1%">任务列表</span>
|
||||
</div>
|
||||
<img class="add-btn" src="../../../img/btn/addRoleBtn.svg" @click="addRole">
|
||||
<!-- <img class="add-btn" src="../../../img/btn/addRoleBtn.svg" @click="addRole">-->
|
||||
<el-row>
|
||||
<el-button type="primary" plain @click="addRole">新增任务</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
class="user-dialog"
|
||||
v-if="visible"
|
||||
>
|
||||
<span class="dialog-title">{{ title }}</span>
|
||||
<!-- <span class="dialog-title">{{ title }}</span>-->
|
||||
<span class="dialog-title">任务创建</span>
|
||||
<!-- 在此处指定弹窗的样式和内容 -->
|
||||
<i class="el-icon-close" style="float: right; padding-right: 8%;padding-top: 3%" @click="close"></i>
|
||||
<el-form
|
||||
@@ -13,29 +14,81 @@
|
||||
label-width="150px"
|
||||
class="user-form"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="角色名称" prop="role_name">
|
||||
<el-input v-model="form.role_name" :disabled="!isAdd" placeholder="请输入名称"></el-input>
|
||||
<el-row style="margin-left: 25%;margin-top: 8%">
|
||||
<el-col :span="15">
|
||||
<el-form-item label="任务名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-form-item label="权限" prop="permissions">
|
||||
<el-checkbox-group v-model="form.permissions" style="display: inline-block;">
|
||||
<el-checkbox v-for="permission in permissionDict" :label="permission.value" :key="permission.value">
|
||||
{{ permission.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-form-item label="任务目标" prop="ip">
|
||||
<div style="display: flex;margin-right: 5px;">
|
||||
<el-input v-model="form.ip" placeholder="请输入目标IP"></el-input>
|
||||
<el-button type="primary" style="margin-left: 1%" @click="getTagsByIP(form.ip),agencyLabel=true">确认</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标信息" prop="role_id" v-if="agencyLabel && roleDict.length>0">
|
||||
<el-tag class="el-tag_en" v-for="i in this.roleDict" style="margin-right: 1%">{{i}}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="执行代理" prop="agencyChange">
|
||||
<el-select v-model="form.agencyChange" placeholder="代理选择">
|
||||
<el-option
|
||||
v-for="item in agencyChange"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标域名" prop="domain">
|
||||
<el-input v-model="form.domain" placeholder="www.google.com"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="期望注入记录" prop="inject">
|
||||
<el-input v-model="form.inject" placeholder="域名记录类型+域名记录"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="期望策略" prop="strategy">
|
||||
<el-select v-model="form.strategy" placeholder="自动选择">
|
||||
<el-option
|
||||
v-for="item in strategy"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-divider content-position="center">附加选项</el-divider>
|
||||
<el-form-item label="状态感知方式" prop="stateAwareMode">
|
||||
<el-select v-model="form.stateAwareMode" placeholder="自动选择">
|
||||
<el-option
|
||||
v-for="item in stateAwareMode"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="策略切换时间" prop="switchoverTime">
|
||||
<el-input v-model="form.switchoverTime" placeholder="单位:分钟"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="任务执行时限" prop="executeTime">
|
||||
<el-input v-model="form.executeTime" placeholder="单位:分钟"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="运行配置" prop="operationalConfiguration">
|
||||
<el-select v-model="form.operationalConfiguration" placeholder="运行配置选择">
|
||||
<el-option
|
||||
v-for="item in operationalConfiguration"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="submit-footer">
|
||||
<div class="submit-footer" style="margin-top: 1%">
|
||||
<div>
|
||||
<el-button class="glBut" type="primary" @click="resetForm">重置</el-button>
|
||||
<el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">{{isAdd ? '提交' : '确定'}}</el-button>
|
||||
<el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">确认创建</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,43 +97,108 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'UserForm',
|
||||
props: ['isAdd', 'permissionDict'],
|
||||
// props: ['isAdd', 'permissionDict'],
|
||||
data() {
|
||||
return {
|
||||
agencyLabel:false,
|
||||
visible: false,
|
||||
loading: false,
|
||||
title: '新增角色',
|
||||
title: '任务创建',
|
||||
form: {
|
||||
role_name: '', // 角色名称
|
||||
permissions: [] // 选中权限
|
||||
name:"", //代理名称
|
||||
ip:"", //任务目标
|
||||
agencyChange:"", //执行代理
|
||||
domain:"", //目标域名
|
||||
inject:"", //期望注入记录
|
||||
strategy:"",//策略
|
||||
stateAwareMode:"",//状态感知方式
|
||||
switchoverTime:"", //策略切换时限
|
||||
executeTime:"", //任务执行时限
|
||||
operationalConfiguration:"",//运行配置
|
||||
},
|
||||
role_id: '',
|
||||
rules: {
|
||||
role_name: [
|
||||
{ required: true, message: '请输入角色名称', trigger: 'blur' }
|
||||
name: [
|
||||
// { required: true, message: '请输入任务名称', trigger: 'blur' },
|
||||
{ message: '请输入任务名称', trigger: 'blur' },
|
||||
{ max: 50, message: '任务名称长度不能超过50个字符', trigger: 'blur' }
|
||||
],
|
||||
permissions: [
|
||||
{ required: true, message: '请选择权限', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
},
|
||||
roleDict:[],
|
||||
strategy:[
|
||||
{ value: 'auto', label: '自动选择', type: 'success' },
|
||||
{ value: 'ddos', label: '拒绝服务', type: 'warning' },
|
||||
{ value: 'sjqp', label: '数据欺骗', type: 'warning' },
|
||||
],
|
||||
agencyChange:[
|
||||
{ value: '中国北京', label: '中国北京', type: 'success' },
|
||||
{ value: '美国纽约', label: '美国纽约', type: 'warning' },
|
||||
],
|
||||
stateAwareMode:[
|
||||
{ value: 'auto', label: '自动选择', type: 'success' },
|
||||
{ value: 'tcp', label: 'TCP时延', type: 'warning' },
|
||||
{ value: 'icmp', label: 'ICMP/v6', type: 'danger' },
|
||||
{ value: 'dns', label: 'DNS解析时延', type: 'danger' },
|
||||
{ value: 'record', label: '记录正确性验证', type: 'danger' },
|
||||
],
|
||||
operationalConfiguration:[
|
||||
{ value: 'now', label: '立刻执行', type: 'success' },
|
||||
{ value: 'man', label: '手动执行', type: 'warning' },
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTagsByIP(val){
|
||||
let data={
|
||||
"ip":val?val:'1.1.1.1'
|
||||
}
|
||||
this.$axios.get(this.$http.api.targetQueryList,data).then(res=>{
|
||||
if(res.code===200){
|
||||
this.roleDict=res?.data[0]?.protect
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
close() {
|
||||
this.resetForm()
|
||||
document.querySelector('.mask').style.display = 'none'
|
||||
this.visible = false
|
||||
},
|
||||
submit() {
|
||||
this.$refs.userForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.isAdd) {
|
||||
this.add()
|
||||
} else {
|
||||
this.edit()
|
||||
}
|
||||
let data={
|
||||
"target":this.form.domain,
|
||||
"agent":this.form.agencyChange,
|
||||
"name":this.form.name,
|
||||
"target_domain":"",
|
||||
"target_rr":this.form.inject,
|
||||
"policy_time":this.form.switchoverTime,
|
||||
"run_time":this.form.executeTime,
|
||||
"run_flag":this.form.operationalConfiguration,
|
||||
"policy":this.form.strategy,
|
||||
"scan":this.form.stateAwareMode,
|
||||
}
|
||||
console.log("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
|
||||
console.log(data)
|
||||
console.log("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
|
||||
this.$axios.post(this.$http.api.taskCreate,data).then(res=>{
|
||||
if(res.code===200){
|
||||
this.$message.success('任务创建成功!')
|
||||
}else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
},
|
||||
add () {
|
||||
this.loading = true
|
||||
@@ -123,9 +241,19 @@ export default {
|
||||
})
|
||||
},
|
||||
resetForm() {
|
||||
this.agencyLabel=false,
|
||||
this.roleDict=[],
|
||||
this.form = {
|
||||
role_name: '', // 角色名称
|
||||
permissions: [] // 选中权限
|
||||
name:"", //代理名称
|
||||
ip:"", //任务目标
|
||||
agencyChange:"", //执行代理
|
||||
domain:"", //目标域名
|
||||
inject:"", //期望注入记录
|
||||
strategy:"",//策略
|
||||
stateAwareMode:"",//状态感知方式
|
||||
switchoverTime:"", //策略切换时限
|
||||
executeTime:"", //任务执行时限
|
||||
operationalConfiguration:"",//运行配置
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,19 +262,20 @@ export default {
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user-dialog{
|
||||
width: 520px;
|
||||
height: 363px;
|
||||
width: 963px;
|
||||
height: 863px;
|
||||
position: absolute; /* 绝对定位 */
|
||||
top: 50%; /* 向下偏移50% */
|
||||
left: 50%; /* 向右偏移50% */
|
||||
transform: translate(-50%, -50%); /* 回移50% */
|
||||
background-image:url('../../../img/background/dialog520-363.svg');
|
||||
/*background-image:url('../../../img/background/dialog520-363.svg');*/
|
||||
background-image:url('../../../img/tjpz.svg');
|
||||
background-repeat: no-repeat; /* 可选,防止图像重复 */
|
||||
background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */
|
||||
.dialog-title {
|
||||
font-size: 20px;
|
||||
float: left;
|
||||
margin: 11px 0 11px 20px;
|
||||
margin: 11px 0 11px 35px;
|
||||
}
|
||||
.user-form {
|
||||
margin-top: 70px;
|
||||
|
||||
Reference in New Issue
Block a user