V2 完成

This commit is contained in:
Gregory
2024-04-26 17:37:16 +08:00
parent d1222bff52
commit ea9a916fa6
20 changed files with 1744 additions and 1288 deletions

View File

@@ -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"

View File

@@ -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);
})
// 响应拦截器

View File

@@ -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', // 异步构建镜像
//系统管理
//系统介绍
},
}

View File

@@ -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" : "津巴布韦"
}
}

View File

@@ -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{

View File

@@ -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')">

View File

@@ -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 } // 需要登录才能访问
}
]
}
]
})
})

View File

@@ -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;

View File

@@ -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%;

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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">-->
<!-- &lt;!&ndash; 只能上传jpg/png文件且不超过500kb&ndash;&gt;-->
<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; /*将元素设置为固定定位*/

View File

@@ -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() {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;