diff options
| author | Gregory <[email protected]> | 2024-04-26 17:38:47 +0800 |
|---|---|---|
| committer | Gregory <[email protected]> | 2024-04-26 17:38:47 +0800 |
| commit | ac8bc7f895baa346cdb498e1b8be41ce66130afd (patch) | |
| tree | 4d4e400af55c1938a20a72f93811e04cb13325d6 | |
| parent | ea9a916fa60a3ea2df7916fe5e1a9795f7a64ee7 (diff) | |
27 files changed, 6485 insertions, 0 deletions
diff --git a/src/img/logyy.jpg b/src/img/logyy.jpg Binary files differnew file mode 100644 index 0000000..4c721ab --- /dev/null +++ b/src/img/logyy.jpg diff --git a/src/img/logyy_美图抠图20240424.png b/src/img/logyy_美图抠图20240424.png Binary files differnew file mode 100644 index 0000000..6b7cdc0 --- /dev/null +++ b/src/img/logyy_美图抠图20240424.png diff --git a/src/views/home/echarts/zhuzhuangtu3.vue b/src/views/home/echarts/zhuzhuangtu3.vue new file mode 100644 index 0000000..e39d7e7 --- /dev/null +++ b/src/views/home/echarts/zhuzhuangtu3.vue @@ -0,0 +1,418 @@ +<template> + <div style="width: 100%;height: 100%;"> + <div style="width: 100%;height: 10%"><span style="margin-top: 1%;font-size: 20px;margin-left: 2%;float: left">探测的目标趋势</span></div> + <div ref="bingbox" style="width: 100%;height: 90%"></div> + </div> +</template> + +<script> + import * as echarts from 'echarts'; + var myChart1=null + export default { + props:{ + bing:{ + type:Object, + default: function() { + return { + datas:[], + signdata: [], + title:"", + bingtype:'', + AreaName:[], + } + } + }, + active:{ + type:Number, + default: function() { + return { + active:"" + } + } + } + }, + watch: { + bing: { + deep: true, + handler(val) { + console.log(val) + this.bingfn(val) + } + }, + }, + data(){ + return { + + } + }, + methods:{ + bingfn(data){ + console.log(data) + let that = this + //当前视口宽度 + let nowClientWidth = document.documentElement.clientWidth; + // 换算方法 + let nowSize = function (val, initWidth = 1920) { + return val * (nowClientWidth / initWidth); + }; + if (myChart1 != null) { + myChart1.clear()//销毁 + } + myChart1= echarts.init(this.$refs.bingbox) + myChart1.clear() + myChart1.off('mouseover') + + var option = { + animation:false, //动态展示 + grid: { + left: '5%', + right: '5%', + bottom: '5%', + containLabel: true + }, + // title: { + // text:"898989" + // }, + + xAxis: { + type: 'category', + data: data.xdata, + // data: ["2024-1-1","2024-1-2","2024-1-3","2024-1-4","2024-1-5","2024-1-6","2024-1-7"], + axisLine:{ + lineStyle:{ + color:'#f6fbfd' + } + }, + axisLabel:{ + interval:0, + show: true + } + + }, + // tooltip: { + // trigger: 'axis', + // // 添加样式 + // textStyle: { + // textAlign: 'left' // 内容左对齐 + // } + // }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + }, + // 使用 formatter 函数设置内容和样式 + formatter: function(params) { + var result = '<div style="text-align:left;">'; // 左对齐样式 + result += params[0].name + '<br>'; // 添加横坐标名称 + + params.forEach(function(item) { + result += item.marker + ' ' + item.seriesName + ': ' + item.value + '<br>'; // 添加数据项 + }); + + result += '</div>'; + return result; + } + }, + yAxis: [ + { + type: 'value', + name: '分类统计(个)', // 水量单位 + position: 'left', // 显示在左侧 + splitLine: { + show: false, + lineStyle: { + color: "rgb(255,16,18)", + } + }, + axisLine: { + lineStyle: { + color: '#f4f2fd' + } + } + }, + { + type: 'value', + name: '总量统计(个)', // 数量单位 + position: 'right', // 显示在右侧 + splitLine: { + show: false, + lineStyle: { + color: "rgb(255,16,18)", + } + }, + axisLine: { + lineStyle: { + color: '#f4be6a' + } + } + } + ], + // yAxis: { + // type: 'value', + // splitLine: {//分割线配置 + // show:false, + // lineStyle: { + // color: "rgb(255,16,18)", + // } + // }, + // axisLine:{ + // lineStyle:{ + // color:'#fdc909' + // } + // } + // }, + // yAxis:[ + // { + // type:'value', + // name:'分类数量', + // interval: 5, + // axisLabel: { + // formatter:'{value}个' + // } + // }, + // { + // type:'value', + // name:'总量', + // interval: 5, + // axisLabel: { + // formatter:'{value}个' + // } + // }, + // + // ], + series: [ + { + name:'IPv6', + barWidth: 20, //柱子宽度 + data:data.ydata1, + // data:[45,89,56,58,66,12,96], + color:["#2386bf"], //自定义颜色 + type: 'bar', + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + }, + { + name:'DNS', + barWidth: 20, //柱子宽度 + data:data.ydata2, + // data:[450,890,560,580,660,155,85], + color:["#434ff4"], //自定义颜色 + type: 'bar', + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + }, + { + name:'DoT', + barWidth: 20, //柱子宽度 + data:data.ydata3, + // data:[150,290,560,380,660,105,815], + color:["rgba(58,76,222,0.89)"], //自定义颜色 + type: 'bar', + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + }, + { + name:'DoH', + barWidth: 20, //柱子宽度 + data:data.ydata4, + // data:[650,790,560,180,660,15,85], + color:["#117cf4"], //自定义颜色 + type: 'bar', + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + } + , + { + name:'总量', + barWidth: 20, //柱子宽度 + data:data.ydata5, + // data:[1120,7090,5660,1800,6060,105,805], + color:["#f4be6a"], //自定义颜色 + type: 'line', + yAxisIndex: 1, + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + } + ], + graphic: [ + { + type:'group', + left:'center', + top:25, + children:[ + { + type: 'rect', + shape: { + width: 20, + height: 20 + }, + style: { + fill: '#2386bf' // 设置第一个色块的颜色 + }, + z: 100 + }, + { + type: 'text', + left: 25, + style: { + text: 'IPv6', // 设置第一个色块的含义 + fill: '#2386bf', + fontSize: 12 + }, + z: 100 + }, + //////////////// + { + type: 'rect', + left: 75, + shape: { + width: 20, + height: 20 + }, + style: { + fill: '#434ff4' // 设置第二个色块的颜色 + }, + z: 100 + }, + { + type: 'text', + left: 100, + style: { + text: 'DNS', // 设置第二个色块的含义 + fill: '#434ff4', + fontSize: 12 + }, + z: 100 + }, + /////////////// + { + type: 'rect', + left:150 , + shape: { + width: 20, + height: 20 + }, + style: { + fill: 'rgba(58,76,222,0.89)' // 设置第二个色块的颜色 + }, + z: 100 + }, + { + type: 'text', + left: 175, + style: { + text: 'DoT', // 设置第二个色块的含义 + fill: 'rgba(58,76,222,0.89)', + fontSize: 12 + }, + z: 100 + }, + ///////////////////////////////// + { + type: 'rect', + left: 225, + shape: { + width: 20, + height: 20 + }, + style: { + fill: '#117cf4' // 设置第二个色块的颜色 + }, + z: 100 + }, + { + type: 'text', + left: 250, + style: { + text: 'DoH', // 设置第二个色块的含义 + fill: '#117cf4', + fontSize: 12 + }, + z: 100 + }, + // ////////////////////////////// + // { + // type: 'rect', + // left: 300, + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#f4be6a' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 325, + // style: { + // text: '五线', // 设置第二个色块的含义 + // fill: '#f4be6a', + // fontSize: 12 + // }, + // z: 100 + // } + ] + } + + ] + }; + + + + + + + + myChart1.setOption(option,true) + window.addEventListener("resize", () => { + myChart1.resize(); + }); + } + }, + beforeDestroy() { + myChart1.clear() + }, + destroyed() { + myChart1.clear() + }, + mounted(){ + // this.bingfn(this.bing) + }, + } +</script> + +<style scoped="scoped"> +</style> diff --git a/src/views/menuMBGZ/index.vue b/src/views/menuMBGZ/index.vue new file mode 100644 index 0000000..b77e861 --- /dev/null +++ b/src/views/menuMBGZ/index.vue @@ -0,0 +1,1102 @@ +<template> + <div class="range-manage" ref="appRef"> + <div class="show"> + <Header + ></Header> + <div class="project" @keyup.enter="getImages"> + <el-input v-model="ipQuery" placeholder="IP地址搜索" suffix icon=""> + <template v-slot:suffix> + <div class="icon-group"> + <img src="../../img/inputl.png" alt="**"> + <img src="../../img/inputIcon.png" alt="*" @click="getImages"> + </div> + </template> + </el-input> + </div> + <div class="project"> +<!-- <el-select v-model="protocolValue" placeholder="协议筛选" clearable @change="query">--> +<!-- <el-select v-model="protocolValue" placeholder="协议筛选" multiple collapse-tags filterable clearable @change="query">--> + <el-select v-model="protocolValue" placeholder="协议筛选" filterable clearable @change="getImages"> + <el-option + v-for="(item,i) in proto" + :key="i" + :label="item" + :value="item"> + </el-option> + </el-select> + </div> + <div class="project"> + <el-select v-model="countryValue" placeholder="国家筛选" filterable clearable @change="getImages"> + <el-option + v-for="(item,i) in cou" + :key="i" + :label="item" + :value="item"> + </el-option> + </el-select> + </div> + <div class="project"> + <el-select v-model="operatorValue" placeholder="运营商筛选" filterable clearable @change="getImages"> + <el-option + v-for="(item,i) in isp" + :key="i" + :label="item" + :value="item"> + </el-option> + </el-select> + </div> + <div class="list" > + <el-table class="custom-table" + ref="multipleTable" + :data="tableData" + height="100%" + style="width: 100%;" + tooltip-effect="dark" + highlight-current-row + @selection-change="handleSelectionChange" + > + <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" label="IP地址" min-width="200"> + <template slot-scope="scope"> + <!-- 在这个插槽中自定义单元格的渲染方式 --> + <div style="white-space: pre-line;"> + <!-- 使用 v-for 循环遍历每个 IP 地址,并使用换行符分隔 --> + <span v-for="ip in toOne(scope.row.ipv4,scope.row.ipv6)"> + {{ ip }} + <br> <!-- 在每个 IP 地址后面添加换行符 --> + </span> + </div> + </template> + </el-table-column> + <el-table-column align="center" label="支持协议" min-width="250"> + <template slot-scope="scope"> + <el-tag v-for="i in scope.row.protocol" style="margin-left: 2px;background-color: rgba(235,235,241,1);color: black">{{i}}</el-tag> + </template> + </el-table-column> + <el-table-column align="center" label="防护措施" min-width="250"> + <template slot-scope="scope"> + <el-tag v-for="i in scope.row.protect" style="margin-left: 2px;background-color: rgba(235,235,241,1);color: black">{{i}}</el-tag> + </template> + </el-table-column> + <el-table-column align="center" + label="所在国家" + min-width="70"> + <template slot-scope="scope"> + {{countryCode[scope.row.cou]}} + </template> + </el-table-column> + <el-table-column align="center" + prop="isp" + label="运营商" + min-width="150"> + </el-table-column> + <el-table-column align="center" + prop="time" + label="发现时间" + min-width="100"> + </el-table-column> + <el-table-column align="center" + label="操作" + min-width="50"> + <template slot-scope="scope"> + <el-button type="text" size="medium" style="{'color': '#409eff'}" + @click="getInfo(scope.row)">详情</el-button> + </template> + </el-table-column> + </el-table> + </div> + <el-pagination + background + :current-page="page" + :page-sizes="[10, 20, 30, 40]" + :page-size="20" + :total="total" + layout="total, sizes, prev, pager, next, jumper" + @size-change="handleSizeChange" + @current-change="handleCurrentChange"> + </el-pagination> + <Earth :ip="ipQuery" :isp="operatorValue" :cou="countryValue" :protocol="protocolValue"></Earth> + <div class="mask"></div> + </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: 5%">代理{{info.id}}详情</span> + <div class="jbpz"> + <template> + <div> + <el-table + :show-header="false" + :data="infoTable" + border + style="margin: 20px;width:381px " + > + <el-table-column width="180" prop="title"></el-table-column> + <el-table-column width="200" prop="value"></el-table-column> + </el-table> + </div> + </template> + <footer class="anDiv"> + <el-button class="glBut" type="primary" @click="close">取消</el-button> + <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点', true)">确定</el-button> + </footer> + </div> + + </div> + </div> +</template> + +<script> + + import { PrismEditor } from 'vue-prism-editor'; + import 'vue-prism-editor/dist/prismeditor.min.css'; + import { highlight, languages } from 'prismjs/components/prism-core'; + import 'prismjs/components/prism-clike'; + import 'prismjs/components/prism-javascript'; + import 'prismjs/themes/prism.css'; // 如果想代码换个样式风格,把这个注释了,上面的三个放开一个 + import Header from './module/Header.vue' + import Earth from './module/indexDQ2' + + export default { + name: "imageMange", + components: { PrismEditor ,Header,Earth}, + data(){ + return{ + countryCode:[], + cou:[], + isp:[], + proto:[], + infoTable: [ + { + id: 1, + title: "用户ID", + value: 1, + }, + { + id: 2, + title: "微信昵称", + value:2, + }, + { + id: 3, + title: "会员名称", + value:3, + } + ], + info:[], + protocolValue:null, + countryValue:'', + ipQuery:null, + operatorValue:'', + file:'', + image_id:0, + addImage:{ + direct:false, + attribute:"private", + image_name:"", + image_version:"", + version_operate:"add", + image_description:"", + establish_mode:"gitOrCode", + git_address:"", + git_branch:"", + git_account:"", + git_password:"", + run_command:"", + run_args:"" + }, + barkImageParmer:{ + direct:false, + attribute:"private", + image_name:"", + image_version:"", + version_operate:"add", + image_description:"", + establish_mode:"gitOrCode", + git_address:"", + git_branch:"", + git_account:"", + git_password:"", + run_command:"", + run_args:"" + }, + queryByImageName:"", + selectImageStateValue: '', + page:1, + size:20, + 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:"基本配置", + tableData:[], + total:0, + multipleSelection: [], + fileList: [ + // { + // name: '', + // url: '' + // } + ], + + newlyPztj:false, + newlyPztjNext:false, + trackCountriesJson:["0","0","0","0","0","0","0","0","0","0","0","0"], + input:"", + bcmc:"", + bcms:"", + dockerOrTar:"dockerfile", + radioRatio: '1', + radioOwnership2: '1', + radioUpdateImage: '2', + radioHowToCreate: '1', + delTimer: null, + counter: 0 + + }; + }, + mounted() { + }, + watch: { + }, + created() { + var json = require('/src/api/world.json'); + this.countryCode= json.countryEtoC; + this.getImages() + this.targetFilter() + window.addEventListener('beforeunload', this.handleBeforeUnload) + }, + destroyed() { + // if (this.pendingTimer) { + // clearInterval(this.pendingTimer) + // this.pendingTimer = null + // } + if(this.delTimer) { + clearInterval(this.delTimer) + this.delTimer = null + } + this.counter = 0 + }, + beforeDestroy() { + window.removeEventListener('beforeunload', this.handleBeforeUnload) + }, + methods:{ + handleBeforeUnload() { + // if ((performance.getEntriesByType('navigation').length || []).length > 0) { + this.$router.push('/range/home') + // } + }, + toOne(val1,val2){ + let list=[]; + if(val1!=null && val1!=""){ + list.push(val1) + } + if(val2!=null && val2!=""){ + list.push(val2) + } + return list; + }, + targetFilter(){ + let data={ + } + this.$axios.get(this.$http.api.targetFilter,data).then(res=>{ + console.log('getImages======',res) + if(res.code===200){ + this.cou=res.cou; + this.isp=res.isp; + this.proto=res.proto; + } + }).catch(err=>{ + console.log(err) + }) + }, + formatIPs(row, column, cellValue) { + // let formattedIPs = cellValue.join(',\n'); + // return formattedIPs; + // 使用 map 方法处理每个 IP 地址,然后连接成带有换行符的字符串 + let formattedIPs = cellValue.map(ip => ip).join(',\n'); + + return formattedIPs; + + }, + onFileChange(event) { + this.file = event.target.files[0]; + }, + oneByThere(){ + if(this.dockerOrTar==='tar'){ + this.addImage.establish_mode="tar"; + }else { + if(this.radioOwnership2==='1'){ + this.addImage.establish_mode="code"; + }else { + this.addImage.establish_mode="git" + } + } + + }, + thereToOne(val){ + if(val==='tar'){ + this.dockerOrTar='tar' + }else { + if(val==='git'){ + this.dockerOrTar='dockerfile' + this.radioOwnership2='2' + }else { + this.dockerOrTar='dockerfile' + this.radioOwnership2='1' + } + } + }, + closeInfo(){ + this.infoType=''; + document.querySelector('.mask').style.display = 'none' + this.addImage=this.barkImageParmer + }, + CustomizationImageFales(){ + this.newlyPztj=false; + document.querySelector('.mask').style.display = 'none' + 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() + + this.getImages() + this.image_id=0 + + this.$notify({ + title: res.message, + type: 'success', + duration: 2500 + }) + if (this.delTimer) { + clearInterval(this.delTimer) + this.delTimer = null + this.counter = 0 + } + this.delTimer = setInterval(() => { + this.getTask(res?.result?.task_id || '') + }, 10 * 1000) + } + }).catch(err=>{ + console.log(err) + }) + }, + infoImage(val){ + let data={ + "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; + this.addImage.git_address=res.result.pipeline.git_address; + this.addImage.git_account=res.result.pipeline.git_account; + this.addImage.git_branch=res.result.pipeline.git_branch; + this.addImage.run_command=res.result.pipeline.run_command; + this.addImage.run_args=res.result.pipeline.run_args; + this.addImage.version_operate=res.result.pipeline.version_operate; + } + }).catch(err=>{ + console.log(err) + }) + }, + delImage(val){ + let data={ + "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() + } + }).catch(err=>{ + console.log(err) + }) + }, + updateImageToBark(){ + this.oneByThere(); + let formData = new FormData(); + formData.append('image_name', this.addImage.image_name); + formData.append('image_version', this.addImage.image_version); + formData.append('version_operate', this.addImage.version_operate); + formData.append('image_description', this.addImage.image_description); + formData.append('establish_mode', this.addImage.establish_mode); + formData.append('git_address', this.addImage.git_address); + formData.append('git_branch', this.addImage.git_branch); + formData.append('git_account', this.addImage.git_account); + formData.append('git_password', this.addImage.git_password); + formData.append('run_command', this.addImage.run_command); + formData.append('run_args', this.addImage.run_args); + const config = { + direct:this.addImage.direct, + attribute:this.addImage.attribute, + image_id:this.image_id + // headers: { + // 'Content-Type': 'multipart/form-data', + // } + }; + this.$axios.put(this.$http.api.asyncUpdateImage, formData ,config).then(res=>{ + if(res.code===200){ + this.CustomizationImageFales() + + this.page=1; + this.getImages() + this.image_id=0 + + this.$notify({ + title: res.message, + type: 'success', + duration: 2500 + }) + if (this.delTimer) { + clearInterval(this.delTimer) + this.delTimer = null + this.counter = 0 + } + this.delTimer = setInterval(() => { + this.getTask(res?.result?.task_id || '') + }, 10 * 1000) + } + }).catch(err=>{ + console.log(err) + }) + + }, + addImageToBark(){ + this.oneByThere(); + let formData = new FormData(); + formData.append('image_name', this.addImage.image_name); + formData.append('image_version', this.addImage.image_version); + formData.append('version_operate', this.addImage.version_operate); + formData.append('image_description', this.addImage.image_description); + formData.append('establish_mode', this.addImage.establish_mode); + formData.append('git_address', this.addImage.git_address); + formData.append('git_branch', this.addImage.git_branch); + formData.append('git_account', this.addImage.git_account); + formData.append('git_password', this.addImage.git_password); + formData.append('run_command', this.addImage.run_command); + formData.append('run_args', this.addImage.run_args); + formData.append('code_file', this.file); + + const config = { + direct:this.addImage.direct, + attribute:this.addImage.attribute, + // headers: { + // 'Content-Type': 'multipart/form-data', + // } + }; + this.$axios.post(this.$http.api.asyncAddImage, formData ,config).then(res=>{ + console.log('getImages======',res) + if(res.code===200){ + this.CustomizationImageFales() + + this.page=1; + this.getImages() + + this.$notify({ + title: res.message, + type: 'success', + duration: 2500 + }) + if (this.delTimer) { + clearInterval(this.delTimer) + this.delTimer = null + this.counter = 0 + } + this.delTimer = setInterval(() => { + this.getTask(res?.result?.task_id || '') + }, 10 * 1000) + } + }).catch(err=>{ + console.log(err) + }) + + }, + handleSizeChange(val) { + console.log(`每页 ${val} 条`); + this.size=val + this.getImages() + }, + handleCurrentChange(val) { + console.log(`当前页: ${val}`); + this.page=val + this.getImages() + }, + getImages(){ + let data={ + "ip":this.ipQuery, + "page":this.page, + "per_page":this.size, + "isp":this.operatorValue, + "cou":this.countryValue, + "protocol":this.protocolValue + } + const filteredData = {}; + for (const [key, value] of Object.entries(data)) { + if (value !== "") { + filteredData[key] = value; + } + } + this.$axios.get(this.$http.api.targetQueryList,filteredData).then(res=>{ + console.log('getImages======',res) + if(res.code===200){ + this.tableData=res.data + this.total=res.total + } + }).catch(err=>{ + console.log(err) + }) + }, + highlighter(code) { + return highlight(code, languages.js) + }, + getInfo(val){ + // 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' + // } + // this.info=val + // this.newlyPztj=true + this.$message.success('预留功能,待开发!') + + + }, + updateTag(val){ + this.tag=val + }, + handleSelectionChange(val) { + this.multipleSelection = val; + }, + handleRemove(file, fileList) { + console.log(file, fileList); + }, + handlePreview(file) { + console.log(file); + }, + handleExceed(files, fileList) { + this.$notify.warning(`当前限制选择 1个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`); + }, + beforeRemove(file, fileList) { + return this.$confirm(`确定移除 ${ file.name }?`); + }, + // 获取任务进度 + getTask(task_id) { + const url = this.$http.api.task + '/' + task_id + this.$axios.get(url, {}).then(res => { + if(res.task_status !== 'PENDING' && res.task_status !== 'STARTED') { + if (res?.task_result?.code === 500 || res?.task_result?.message === 'false') { + this.$notify({ + title: res?.task_result?.result || `${res.task_id}任务执行失败`, + type: 'success', + duration: 2500 + }) + } else { + this.$notify({ + title: res?.task_result?.result || `${res.task_id}任务执行完毕`, + type: 'success', + duration: 2500 + }) + } + clearInterval(this.delTimer) + this.delTimer = null + this.counter = 0 + this.getImages() + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.counter++ + if (this.counter >= 60) { + clearInterval(this.delTimer) + this.delTimer = null + this.counter = 0 + this.getImages() + } + }) + } + + } + } + +</script> + +<style lang='less' scoped="scoped"> + .page{ + width: 800%; + height: 5%; + margin-left: 2%; + background-color: #ec171d; + padding-left: 35%; + padding-top: 20%; + /*.el-pagination {*/ + /* transform: scale(0.2) !important;*/ + /*}*/ + .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;*/ + /*}*/ + + + } + .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: transparent; + /*color: #000;*/ + color: #fafafa; + + font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace; + font-size: 16px; + line-height: 1.5; + padding: 5px; + font-weight: 500; + } + + .my-editor ::v-deep .prism-editor__textarea::selection{ + background-color: #322dff !important; + color: #ed1210 !important; + user-select:none; + } + + .my-editor ::v-deep .prism-editor__textarea:focus { + border: 0px solid #007bff; + outline: none; + } + + .my-editor ::v-deep .prism-editor__line-numbers{ + padding-right: 10px; + } + .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; + .input{ + display: inline-block; + height: 60%; + width: 10%; + margin-left: 0.5%; + /*background-color: rgba(223, 230, 236, 0.1); !* 使用 rgba 函数设置颜色和透明度 *!*/ + /*background-image:url('../../img/bcglinput.png');*/ + /*background-repeat: no-repeat; !* 可选,防止图像重复 *!*/ + /*background-size: cover; !* 图像将被调整以完全填充,同时保持比例不变 *!*/ + .el-input::placeholder { + width: auto; + } + .icon-group { + display: flex; /* 设置容器为 Flexbox 容器 */ + align-items: center; /* 垂直居中图片 */ + gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ + + } + + .icon-group img { + /*margin-right: 10px; !* 图片之间留出一些距离 *!*/ + /*width: 1px; !* 指定图片的宽度 *!*/ + /*height: 10px; !* 指定图片的高度 *!*/ + transform: scale(1); + margin-right: 15px; + margin-top: 6px; + } + + } + .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; + } + + } + } + } + .range-manage{ + width: 100%; + height: 100%; + float: right; + position: relative; /* 确保相对定位生效 */ + .infoTar{ + z-index: 997; + width: 40%; + height: 50%; + position: absolute; /* 绝对定位 */ + /*position: relative;*/ + top: 50%; /* 向下偏移50% */ + left: 50%; /* 向右偏移50% */ + transform: translate(-50%, -50%); /* 回移50% */ + background-image:url('../../img/torInfo.svg'); + background-repeat: no-repeat; /* 可选,防止图像重复 */ + background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ + .infoTypography{ + display: flex; + justify-content: center; + width: 100%; + height: 70%; + margin-top: 5%; + .container{ + + width: 85%; + .row { + width: 100%; + .cell { + float: left; + display: inline-block; + width: 50%; + padding: 10px; + border: none; + text-align: left; + font-size: 18px; + color: #8c8faf; + } + .cellA { + float: left; + display: inline-block; + width: 51%; + padding: 10px; + border: none; + text-align: left; + font-size: 18px; + color: #8c8faf; + } + } + } + } + } + .infoDocker{ + z-index: 997; + width: 60%; + height: 70%; + position: absolute; /* 绝对定位 */ + /*position: relative;*/ + top: 50%; /* 向下偏移50% */ + left: 50%; /* 向右偏移50% */ + transform: translate(-50%, -50%); /* 回移50% */ + background-image:url('../../img/infoDocker.svg'); + background-repeat: no-repeat; /* 可选,防止图像重复 */ + background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ + .infoCode{ + width: 62%; + height: 92%; + margin-left: 4%; + margin-top: 2%; + display: inline-block; + float: left; + /*background-color: #0b6f08;*/ + } + .infoInfo{ + float: right; + margin-right: 3%; + margin-top: 2%; + width: 27%; + height: 70%; + /*background-color: #ed1210;*/ + .infoText{ + width: 100%; + margin-top: 2%; + color: #8c8faf; + font-size: 20px; + text-align: left; + padding-left: 2%; + overflow: wrap; + word-wrap: break-word; + } + } + } + .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%,高度自适应保持宽高比 */ + width: 95%; + /*height: auto; !*自适应高度*!*/ + height: 95%; + /*max-height: 95%; !*最大高度为父级高度的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%,高度自适应保持宽高比 */ + overflow-y: auto; + .head{ + width: 95%; + height: 7%; + margin-top: 1%; + margin-left: 2.5%; + text-align: right; + + /*background-color: #5daf34;*/ + .block{ + display: inline-block; + margin-left: 2%; + + } + .input{ + display: inline-block; + height: 60%; + width: 10%; + margin-left: 0.5%; + /*background-color: rgba(223, 230, 236, 0.1); !* 使用 rgba 函数设置颜色和透明度 *!*/ + /*background-image:url('../../img/bcglinput.png');*/ + /*background-repeat: no-repeat; !* 可选,防止图像重复 *!*/ + /*background-size: cover; !* 图像将被调整以完全填充,同时保持比例不变 *!*/ + .el-input::placeholder { + width: auto; + } + .icon-group { + display: flex; /* 设置容器为 Flexbox 容器 */ + align-items: center; /* 垂直居中图片 */ + gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ + + } + + .icon-group img { + /*margin-right: 10px; !* 图片之间留出一些距离 *!*/ + /*width: 1px; !* 指定图片的宽度 *!*/ + /*height: 10px; !* 指定图片的高度 *!*/ + transform: scale(1); + margin-right: 15px; + margin-top: 6px; + } + + } + .project{ + display: inline-block; + height: 60%; + width: 10%; + margin-top: 0.5%; + margin-left: 0.5%; + margin-right: 1%; + /*background-color: rgba(223, 230, 236, 0.1); !* 使用 rgba 函数设置颜色和透明度 *!*/ + /*background-image:url('../../img/bcglinput.png');*/ + /*background-repeat: no-repeat; !* 可选,防止图像重复 *!*/ + /*background-size: cover; !* 图像将被调整以完全填充,同时保持比例不变 *!*/ + .el-input::placeholder { + width: auto; + } + .icon-group { + display: flex; /* 设置容器为 Flexbox 容器 */ + align-items: center; /* 垂直居中图片 */ + gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ + + } + + .icon-group img { + /*margin-right: 10px; !* 图片之间留出一些距离 *!*/ + /*width: 1px; !* 指定图片的宽度 *!*/ + /*height: 10px; !* 指定图片的高度 *!*/ + transform: scale(1); + margin-right: 15px; + margin-top: 6px; + } + + } + .state{ + font-size: 10px; + float: left; + margin-top: 0.5%; + display: inline-block; + height: 60%; + width: 7%; + margin-left: 0.5%; + .custom-popper .el-select-dropdown { + max-height: 3px; + } + ::v-deep .el-input__inner{ + color: #000 !important; + } + + } + } + .list{ + width: 95%; + height: 76%; + margin-left: 2.5%; + margin-top: 1%; + 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>
\ No newline at end of file diff --git a/src/views/menuMBGZ/module/Header.vue b/src/views/menuMBGZ/module/Header.vue new file mode 100644 index 0000000..1c33305 --- /dev/null +++ b/src/views/menuMBGZ/module/Header.vue @@ -0,0 +1,89 @@ +<template> +<div class="head"> + <div class="target-select"> + <span style="font-size: 30px;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: 100%; + 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>
\ No newline at end of file diff --git a/src/views/menuMBGZ/module/indexDQ2.vue b/src/views/menuMBGZ/module/indexDQ2.vue new file mode 100644 index 0000000..103054d --- /dev/null +++ b/src/views/menuMBGZ/module/indexDQ2.vue @@ -0,0 +1,624 @@ +<template> + <div class='wrapper'> + <div class='chart' id='chart' > + </div> + </div> +</template> + +<script> + import axios from 'axios' + export default { + props:['ip','isp','cou','protocol'], + watch:{ + ip(newValue,oldValue){ + console.log("TTTTTTTTTTTTTTTTTT1") + console.log("新:"+newValue +"旧:"+oldValue) + console.log("TTTTTTTTTTTTTTTTTT1") + this.ip=newValue; + this.handleChange(); + }, + isp(newValue,oldValue){ + console.log("TTTTTTTTTTTTTTTTTT2") + console.log("新:"+newValue +"旧:"+oldValue) + console.log("TTTTTTTTTTTTTTTTTT2") + this.isp=newValue; + this.handleChange(); + }, + protocol(newValue,oldValue){ + console.log("TTTTTTTTTTTTTTTTTT3") + console.log("新:"+newValue +"旧:"+oldValue) + console.log("TTTTTTTTTTTTTTTTTT3") + this.protocol=newValue; + this.handleChange(); + }, + cou(newValue,oldValue){ + console.log("TTTTTTTTTTTTTTTTTT4") + console.log("新:"+newValue +"旧:"+oldValue) + console.log("TTTTTTTTTTTTTTTTTT4") + this.cou=newValue; + this.handleChange(); + } + + }, + name: "indexDQ2", + data () { + return { + // ip:"", + // isp:"", + // cou:"", + // protocol:null, + switchLanguage:"",//用于页面中英文切换 + // countryEnJson:"",//用于储存国家英文字典 + maxValue:0, + newestInfo:"", + ws: null, + // listAdd:[], + chart:undefined, + // res :[], + ddaattaa:"" + } + }, + created() { + this.handleChange0(); + }, + mounted () { + this.handleChange() + // this.getWorld() + // 模拟初始数据获取 + // 模拟数据更新 + // setInterval(() => { + // this.getData(); + // }, 3000); + }, + methods: { + handleChange0(){ + /****************************************************************************/ + let data = { + } + this.$axios.get(this.$http.api.targetMap,data).then(res=> { + console.log("地图访问成功") + if(res.code=='200'){ + console.log("地图访问成功OK") + this.ddaattaa=res.dataObject.earthAddTitle; + this.getWorld() + } + }) + /*********************************************************************************/ + // this.ddaattaa="{\"dataObject\":{\"newestCountry\":\"墨西哥\",\"maxValue\":8593,\"newestInfo\":\"墨西哥484\",\"earthAddTitle\":[{\"name\":\"美国\"" + + // ",\"title\":\"RECRUITMENTOFPERSONNELINMEXICOANDLATINAMERICA\",\"value\":893},{\"name\":\"印度\",\"title\":\"印度ixigo数据1700万\"," + + // "\"value\":1982},{\"name\":\"法国\",\"title\":\"France124K | NICEQUALITY\",\"value\":1645},{\"name\":\"英国\",\"title\":" + + // "\"100XAccountsHotmailUnitedKingdomFresh & FullAccess ⚡️Capture ⚡️PrivateAccs\",\"value\":1576},{\"name\":\"俄罗斯\"," + + // "\"title\":\"LeadershipoftheAirborneTroopsandothersofRussia\",\"value\":1279},{\"name\":\"德国\",\"title\":" + + // "\"1MGermanyUHQcombolist\",\"value\":1231},{\"name\":\"中国\",\"title\":\"900 - 山东 - 务工人员信息明细统计表\",\"value\":4275}," + + // "{\"name\":\"墨西哥\",\"title\":\"墨西哥务工人员信息明细统计表\",\"value\":8593}]}," + + // "\"code\":\"earth\"}" + // this.getWorld() + + }, + handleChange(){ + /****************************************************************************/ + let data = { + "ip":this.ip, + "isp":this.isp, + "cou":this.cou, + } + let data2 = { + "ip":this.ip, + "isp":this.isp, + "cou":this.cou, + "protocol":this.protocol, + } + this.$axios.get(this.$http.api.targetMap,this.protocol===null?data:data2).then(res=> { + console.log("地图访问成功") + if(res.code=='200'){ + console.log("地图访问成功OK") + this.ddaattaa=res.dataObject.earthAddTitle; + this.getWorld() + } + }) + /*********************************************************************************/ + // this.ddaattaa="{\"dataObject\":{\"newestCountry\":\"墨西哥\",\"maxValue\":8593,\"newestInfo\":\"墨西哥484\",\"earthAddTitle\":[{\"name\":\"美国\"" + + // ",\"title\":\"RECRUITMENTOFPERSONNELINMEXICOANDLATINAMERICA\",\"value\":893},{\"name\":\"印度\",\"title\":\"印度ixigo数据1700万\"," + + // "\"value\":1982},{\"name\":\"法国\",\"title\":\"France124K | NICEQUALITY\",\"value\":1645},{\"name\":\"英国\",\"title\":" + + // "\"100XAccountsHotmailUnitedKingdomFresh & FullAccess ⚡️Capture ⚡️PrivateAccs\",\"value\":1576},{\"name\":\"俄罗斯\"," + + // "\"title\":\"LeadershipoftheAirborneTroopsandothersofRussia\",\"value\":1279},{\"name\":\"德国\",\"title\":" + + // "\"1MGermanyUHQcombolist\",\"value\":1231},{\"name\":\"中国\",\"title\":\"900 - 山东 - 务工人员信息明细统计表\",\"value\":4275}," + + // "{\"name\":\"墨西哥\",\"title\":\"墨西哥务工人员信息明细统计表\",\"value\":8593}]}," + + // "\"code\":\"earth\"}" + // this.getWorld() + + }, + showTitleView(newestInfo,newestCountry){ + // console.log(newestInfo) + // let new_cname = dataArr[0]['name']+dataArr[0]['value'] + let new_cname = newestInfo //中国44 + // console.log("判断最后一条数据是否有变化") + // console.log("this.Cname:"+this.newestInfo) + // console.log("new_cname:"+new_cname) + if (this.newestInfo != new_cname){ + console.log("RRRRRRRRRRRRR进来了啊") + this.newestInfo = new_cname; + // this.showTooltip(-1); + this.showTooltip(newestCountry); + // this.showWireframe(-1) + this.showWireframe(newestCountry) + setTimeout(this.hideTooltip,10000); + } + + + }, + showWireframe(newestCountry) { + // // 取消高亮指定的数据图形 + // this.chart.dispatchAction({ + // type: 'downplay', + // seriesIndex: 0, + // dataIndex: index + // }) + // 高亮指定的数据图形 + this.chart.dispatchAction({ + type: 'highlight', + seriesIndex: 0, + name: newestCountry + // dataIndex: index + 1 + }) + }, + hideTooltip(){ + this.chart.dispatchAction({ + type: 'hideTip', + seriesIndex: 0, + dataIndex: -1 + }) + }, + // showTooltip(index) { + showTooltip(newestCountry) { + // // 隐藏提示框 + // this.chart.dispatchAction({ + // type: 'hideTip', + // seriesIndex: 0, + // dataIndex: index + // }) + // 显示提示框 + this.chart.dispatchAction({ + type: 'showTip', + seriesIndex: 0, + name:newestCountry + // dataIndex: index + 1 + }) + }, + getWorld () { //ddaattaa + /****************************************************************************/ + var json = require('/src/api/world.json'); + let namemap = json.namemap; + let dataArr=[]; + // this.maxValue=JSON.parse(this.ddaattaa).dataObject.maxValue + this.maxValue=20000 + // dataArr = JSON.parse(this.ddaattaa).dataObject.earthAddTitle + dataArr = this.ddaattaa + this.drawChart(namemap, dataArr); + // this.showTitleView( + // JSON.parse(this.ddaattaa).dataObject.newestInfo, + // JSON.parse(this.ddaattaa).dataObject.newestCountry + // ); + + + }, + drawChart (namemap, dataArr) { + let maxValue=this.maxValue + // 基于准备好的dom,初始化echarts实例 + let chart = this.$echarts.init(document.getElementById('chart')) + // 监听屏幕变化自动缩放图表 + window.addEventListener('resize', function () { + chart.resize() + }) + + /////////////////////////// + //用于存储地图数据 + var json = require('/src/api/world.json'); + var pointMap =json.trapeze; + var geoCoordMap = pointMap; + var countryEnJson=json.country_en; + var zh_en=this.switchLanguage; + + var max = 480, + min = 9; // todo + var maxSize4Pin = 50, + minSize4Pin = 20; + + var convertData = function (dataD) { + var res = []; + if(dataD){ + for (var i = 0; i < dataD.length; i++) { + var geoCoord = geoCoordMap[dataD[i].name]; + if (geoCoord) { + res.push({ + name: dataD[i].name, + name_en: countryEnJson[dataD[i].name], + zh_en:zh_en, + value: geoCoord.concat(dataD[i].value), + // value: geoCoord, + // size:dataD[i].value, + title: dataD[i].title, + }); + } + } + } + return res; + }; + // var convertDataA = function (dataD) { + // var res = []; + // if(dataD){ + // for (var i = 0; i < dataD.length; i++) { + // var geoCoord = geoCoordMap[dataD[i].name]; + // if (geoCoord) { + // res.push({ + // name: dataD[i].name, + // value: geoCoord.concat(dataD[i].value), + // // value: geoCoord, + // title: dataD[i].title, + // num:dataD[i].value, + // }); + // } + // } + // } + // return res; + // }; + // 绘制图表 + chart.setOption({ + + // 图表主标题 + // title: { + // // text: '数据泄露分布地图', // 主标题文本,支持使用 \n 换行 + // top: 20, // 定位 值: 'top', 'middle', 'bottom' 也可以是具体的值或者百分比 + // left: 'center', // 值: 'left', 'center', 'right' 同上 + // textStyle: { // 文本样式 + // fontSize: 24, + // fontWeight: 600, + // color: '#fff' + // } + // }, + // 提示框组件 + tooltip: { + trigger: 'item', // 触发类型, 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用 + // 提示框浮层内容格式器,支持字符串模板和回调函数两种形式 + // 使用函数模板 传入的数据值 -> value: number | Array + formatter: function (val) { + var text = ''; + text += '<div style="display:flex;flex-direction:row;">'+ + '<div style="background-color:#03D16D;height:auto;width:10px;margin-right:5px;"></div>'+ + '<div style="display:flex;flex-direction:column;">'+ + '<span>'+ val.data.name+'</span>'+ + '<span >'+'分类信息:'+'</span>'+ + '<span display:width="60px">'+ val.data.title+'</span>'+ + '</div>'+ + '</div>' + return text; + } + }, + // visualMap: { + // type: 'continuous', + // min: 0, + // max: 100, + // range: [1, 10], + // center: [104.114129, 37.550339], + // }, + // visualMap: { + // show: false, + // min: 0, + // max: 600, + // left: 'left', + // top: 'bottom', + // text: ['高', '低'], // 文本,默认为数值文本 + // calculable: true, + // seriesIndex: [1], + // //控制地图颜色的显示区间 + // inRange: { + // // color: ['#3B5077', '#031525'] // 蓝黑 + // // color: ['#ffc0cb', '#800080'] // 红紫 + // // color: ['#3C3B3F', '#605C3C'] // 黑绿 + // // color: ['#0f0c29', '#302b63', '#24243e'] // 黑紫黑 + // // color: ['#23074d', '#cc5333'] // 紫红 + // // color: ['#00467F', '#A5CC82'] // 蓝绿 + // // color: ['#1488CC', '#2B32B2'] // 浅蓝 + // // color: ['#00467F', '#A5CC82', '#ffc0cb'] // 蓝绿红 + // // color: ['#00467F', '#A5CC82'] // 蓝绿 + // // color: ['#00467F', '#A5CC82'] // 蓝绿 + // // color: ['#00467F', '#A5CC82'] // 蓝绿 + // color: ['#22e5e8', '#0035f9', '#22e5e8'] // 蓝绿 + // + // } + // }, + geo: { + //地图的初始配置 + // show: true, + map: 'world', + projection:'geoMercator', //使用墨卡托投影 + // mapProjection: { + // // 使用等经纬度投影 + // type: 'equidistantly' + // }, + // zoom:1, + // label: { + // normal: { + // show: false + // }, + // emphasis: { + // show: false + // } + // }, + roam:false, + // center:undefined, +///////////////////////////////////////////////////////1/2 + // 图形上的文本标签 + label: { + show: false// 是否显示对应地名 + }, + // 地图区域的多边形 图形样式 + itemStyle: { + // areaColor: '#3ca3e6', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + areaColor: '#0d1b4a', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + borderWidth: 0.5, // 描边线宽 为 0 时无描边 + borderColor: '#00F1FF', // 图形的描边颜色 支持的颜色格式同 color,不支持回调函数 + borderType: 'solid' // 描边类型,默认为实线,支持 'solid', 'dashed', 'dotted' + }, + // 高亮状态下的多边形和标签样式 + emphasis: { + label: { + show: false, // 是否显示标签 + color: '#fff' // 文字的颜色 如果设置为 'auto',则为视觉映射得到的颜色,如系列色 + }, + itemStyle: { + areaColor: '#3742ff' // 地图区域的颜色 + } + }, + ////////////////////////////////////////////////1/2 + // 自定义地区的名称映射 + nameMap: namemap, + + + + }, + series: [ + { + // type: 'map', // 类型 + type: 'scatter', // 使用墨卡托投影 + coordinateSystem:'geo', //使用地理坐标系 + // 系列名称,用于tooltip的显示,legend 的图例筛选 在 setOption 更新数据和配置项时用于指定对应的系列 + name: '数据泄露分布地图', + // mapType: 'world', // 地图类型 + // // 是否开启鼠标缩放和平移漫游 默认不开启 如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move' 设置成 true 为都开启 + // roam: false, + + ///////////////////////////////////////////////////////1/2 + // 图形上的文本标签 + // label: { + // show: false// 是否显示对应地名 + // }, + // // 地图区域的多边形 图形样式 + // itemStyle: { + // // areaColor: '#3ca3e6', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + // areaColor: '#0d1b4a', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + // borderWidth: 0.5, // 描边线宽 为 0 时无描边 + // borderColor: '#00F1FF', // 图形的描边颜色 支持的颜色格式同 color,不支持回调函数 + // borderType: 'solid' // 描边类型,默认为实线,支持 'solid', 'dashed', 'dotted' + // }, + // // 高亮状态下的多边形和标签样式 + // emphasis: { + // label: { + // show: false, // 是否显示标签 + // color: '#fff' // 文字的颜色 如果设置为 'auto',则为视觉映射得到的颜色,如系列色 + // }, + // itemStyle: { + // areaColor: '#3742ff' // 地图区域的颜色 + // } + // }, + ////////////////////////////////////////////////1/2 + geoIndex:0, + // // 自定义地区的名称映射 + // nameMap: namemap, + // 地图系列中的数据内容数组 数组项可以为单个数值 + // data: dataArr, + data: convertData(dataArr), + }, + // { + // type: 'map', + // map: 'world', + // geoIndex: 0, + // aspectScale: 0.75, //长宽比 + // showLegendSymbol: false, // 存在legend时显示 + // label: { + // show: false, + // // normal: { + // // show: true + // // }, + // // emphasis: { + // // show: false, + // // textStyle: { + // // color: '#fff' + // // } + // // } + // }, + // // roam: true, + // // itemStyle: { + // // normal: { + // // areaColor: '#031525', + // // borderColor: '#3B5077', + // // }, + // // emphasis: { + // // areaColor: '#2B91B7' + // // } + // // }, + // // 地图区域的多边形 图形样式 + // itemStyle: { + // // areaColor: '#3ca3e6', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + // areaColor: '#0d1b4a', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用 + // borderWidth: 0.5, // 描边线宽 为 0 时无描边 + // borderColor: '#00F1FF', // 图形的描边颜色 支持的颜色格式同 color,不支持回调函数 + // borderType: 'solid' // 描边类型,默认为实线,支持 'solid', 'dashed', 'dotted' + // }, + // // animation: true, + // namemap:namemap, + // data: dataArr + // // data: convertData(data) + // }, + { + name: '点', + type: 'scatter', + coordinateSystem: 'geo', + symbol: 'pin', //气泡 + symbolSize: function (size,val) { + var a = (maxSize4Pin - minSize4Pin) / (max - min); + var b = minSize4Pin - a * min; + // b = maxSize4Pin - a * max; + return a * val[2]*100 + b; + }, + label: { + normal: { + show: false, + formatter: function (params) { + return params.value[2] + }, + textStyle: { + color: '#fff', + fontSize: 9, + } + } + }, + itemStyle: { + normal: { + color: 'rgba(255,255,0,0)', //标志颜色 + } + }, + zlevel: 1, + data: convertData(dataArr), + }, + { + name: 'Top 500',//用于显示最高的前五个数据 + type: 'effectScatter', + coordinateSystem: 'geo', + // data: convertData(data.sort(function (a, b) { + // return a.value - b.value; + // }).slice(0, 500)), namemap, dataArr + symbolSize: function (val) { + // return val[2] / 2.3; + return val[2] / (maxValue*0.03); + }, + showEffectOn: 'render', + rippleEffect: { + brushType: 'stroke' + }, + hoverAnimation: true, + label: { + normal: { + formatter: '{b}', + position: 'right', + show: false + } + }, + itemStyle: { + normal: { + color: 'rgba(255,9,14,0.8)', + shadowBlur: 10, + shadowColor: '#05C3F9' + } + }, + zlevel: 1, + data: convertData(dataArr), + }, + + + ] + }) + // 定时显示提示框和高亮效果 + this.chart = chart; + // let index = -1 + // let indexK = -1 + // setInterval(function () { + // // 隐藏提示框 + // chart.dispatchAction({ + // type: 'hideTip', + // seriesIndex: 0, + // dataIndex: indexK + // }) + // // 显示提示框 + // chart.dispatchAction({ + // type: 'showTip', + // seriesIndex: 0, + // dataIndex: indexK + 1 + // }) + // index=index+10000 + // // if (index > data.length - 1) { + // // index = -1 + // // } + // },3000) + // setInterval(function () { + // // 隐藏提示框 + // chart.dispatchAction({ + // type: 'hideTip', + // seriesIndex: 0, + // dataIndex: index + // }) + // // 显示提示框 + // chart.dispatchAction({ + // type: 'showTip', + // seriesIndex: 0, + // dataIndex: index + 1 + // }) + // // 取消高亮指定的数据图形 + // chart.dispatchAction({ + // type: 'downplay', + // seriesIndex: 0, + // dataIndex: index + // }) + // // 高亮指定的数据图形 + // chart.dispatchAction({ + // type: 'highlight', + // seriesIndex: 0, + // dataIndex: index + 1 + // }) + // // index++ + // // if (index > data.length - 1) { + // // index = -1 + // // } + // }, 1000) + } + } + } +</script> + +<style scoped> + .wrapper { + /*margin-top: -80px;*/ + /*width: 100%;*/ + /*margin-left: -120px;*/ + /*margin-top: -10%;*/ + /*width: 100%;*/ + /*height: 100%;*/ + /*width: calc(100vw);*/ + /*height: calc(100vh);*/ + width: calc(100%); + height: calc(100%); + margin-left: -12%; + } + .wrapper .chart { + /*width: 120%;*/ + /*height: 780px;*/ + /*margin: 1px 2px 0;*/ + /*!*border: 1px solid #0d1b4d;*!*/ + /*!*background: url(../../../public/bg.jpg) no-repeat; #0d1b4d *!*/ + /*background-size: 100% 100%;*/ + + width: 100%; + height: 100%; + /*margin: 0.2% 0.2% 0;*/ + margin-top: 2%; + margin-left: 10%; + /*border: 1px solid #0d1b4d;*/ + /*background: url(../../../public/bg.jpg) no-repeat; #0d1b4d */ + background-size: 100% 100%; + z-index: 9; + /*position: absolute;*/ + position: relative; + } +</style> + + diff --git a/src/views/menuMBZTGZ/echarts/zhuzhuangtu3.vue b/src/views/menuMBZTGZ/echarts/zhuzhuangtu3.vue new file mode 100644 index 0000000..70862ed --- /dev/null +++ b/src/views/menuMBZTGZ/echarts/zhuzhuangtu3.vue @@ -0,0 +1,296 @@ +<template> + <div style="width: 100%;height: 100%;"> + <div style="width: 100%;height: 10%"><span style="margin-top: 1%;font-size: 20px;margin-left: 2%;float: left">节点时延统计</span></div> + <div ref="bingbox" style="width: 100%;height: 90%"></div> + </div> +</template> + +<script> + import * as echarts from 'echarts'; + var myChart1=null + export default { + props:{ + bing:{ + type:Object, + default: function() { + return { + datas:[], + signdata: [], + title:"", + bingtype:'', + AreaName:[], + } + } + }, + active:{ + type:Number, + default: function() { + return { + active:"" + } + } + } + }, + watch: { + bing: { + deep: true, + handler(val) { + console.log(val) + this.bingfn(val) + } + }, + }, + data(){ + return { + + } + }, + methods:{ + bingfn(data){ + console.log(data) + let that = this + //当前视口宽度 + let nowClientWidth = document.documentElement.clientWidth; + // 换算方法 + let nowSize = function (val, initWidth = 1920) { + return val * (nowClientWidth / initWidth); + }; + if (myChart1 != null) { + myChart1.clear()//销毁 + } + myChart1= echarts.init(this.$refs.bingbox) + myChart1.clear() + myChart1.off('mouseover') + + var option = { + animation:false, //动态展示 + grid: { + left: '5%', + right: '5%', + bottom: '5%', + containLabel: true + }, + // title: { + // text:"898989" + // }, + + xAxis: { + type: 'category', + data: data.xdata, + // data: ["2024-1-1","2024-1-2","2024-1-3","2024-1-4","2024-1-5","2024-1-6","2024-1-7"], + axisLine:{ + lineStyle:{ + color:'#f6fbfd' + } + }, + axisLabel:{ + interval:0, + show: true + } + + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + }, + // 使用 formatter 函数设置内容和样式 + formatter: function(params) { + var result = '<div style="text-align:left;">'; // 左对齐样式 + result += params[0].name + '<br>'; // 添加横坐标名称 + + params.forEach(function(item) { + result += item.marker + ' ' + item.seriesName + ': ' + item.value + '<br>'; // 添加数据项 + }); + + result += '</div>'; + return result; + } + }, + yAxis: [ + { + type: 'value', + name: '时延(ms)', + position: 'left', // 显示在左侧 + splitLine: { + show: false, + lineStyle: { + color: "rgb(255,16,18)", + } + }, + axisLine: { + lineStyle: { + color: '#f4f2fd' + } + } + }, + ], + series: [ + { + name:'时延', + barWidth: 20, //柱子宽度 + data:data.ydata1, + // data:[45,89,56,58,66,12,96], + color:["#2386bf"], //自定义颜色 + type: 'bar', + label:{ + show:true, + position:'top', + formatter:function (params) { + return params.value; + } + } + + }, + ], + // graphic: [ + // { + // type:'group', + // left:'center', + // top:25, + // children:[ + // { + // type: 'rect', + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#2386bf' // 设置第一个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 25, + // style: { + // text: 'IPv6', // 设置第一个色块的含义 + // fill: '#2386bf', + // fontSize: 12 + // }, + // z: 100 + // }, + // //////////////// + // { + // type: 'rect', + // left: 75, + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#434ff4' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 100, + // style: { + // text: 'DNS', // 设置第二个色块的含义 + // fill: '#434ff4', + // fontSize: 12 + // }, + // z: 100 + // }, + // /////////////// + // { + // type: 'rect', + // left:150 , + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: 'rgba(58,76,222,0.89)' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 175, + // style: { + // text: 'DoT', // 设置第二个色块的含义 + // fill: 'rgba(58,76,222,0.89)', + // fontSize: 12 + // }, + // z: 100 + // }, + // ///////////////////////////////// + // { + // type: 'rect', + // left: 225, + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#117cf4' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 250, + // style: { + // text: 'DoH', // 设置第二个色块的含义 + // fill: '#117cf4', + // fontSize: 12 + // }, + // z: 100 + // }, + // // ////////////////////////////// + // // { + // // type: 'rect', + // // left: 300, + // // shape: { + // // width: 20, + // // height: 20 + // // }, + // // style: { + // // fill: '#f4be6a' // 设置第二个色块的颜色 + // // }, + // // z: 100 + // // }, + // // { + // // type: 'text', + // // left: 325, + // // style: { + // // text: '五线', // 设置第二个色块的含义 + // // fill: '#f4be6a', + // // fontSize: 12 + // // }, + // // z: 100 + // // } + // ] + // } + // + // ] + }; + + + + + + + + myChart1.setOption(option,true) + window.addEventListener("resize", () => { + myChart1.resize(); + }); + } + }, + beforeDestroy() { + myChart1.clear() + }, + destroyed() { + myChart1.clear() + }, + mounted(){ + // this.bingfn(this.bing) + }, + } +</script> + +<style scoped="scoped"> +</style> diff --git a/src/views/menuMBZTGZ/echarts/zhuzhuangtu_jbs.vue b/src/views/menuMBZTGZ/echarts/zhuzhuangtu_jbs.vue new file mode 100644 index 0000000..5d1667f --- /dev/null +++ b/src/views/menuMBZTGZ/echarts/zhuzhuangtu_jbs.vue @@ -0,0 +1,419 @@ +<template> + <div style="width: 100%;height: 100%;"> + <div style="width: 100%;height: 10%"><span style="margin-top: 1%;font-size: 20px;margin-left: 2%;float: left">时延报警</span></div> + <div ref="bingbox" style="width: 100%;height: 90%"></div> + </div> +</template> + +<script> + import * as echarts from 'echarts'; + var myChart1=null + export default { + props:{ + bing:{ + type:Object, + default: function() { + return { + data:[], + // signdata: [], + // title:"", + // bingtype:'', + // AreaName:[], + } + } + }, + active:{ + type:Number, + default: function() { + return { + active:"" + } + } + } + }, + watch: { + bing: { + deep: true, + handler(val) { + console.log(val) + this.bingfn(val) + } + }, + }, + data(){ + return { + + } + }, + methods:{ + bingfn(data){ + console.log(data) + let that = this + //当前视口宽度 + let nowClientWidth = document.documentElement.clientWidth; + // 换算方法 + let nowSize = function (val, initWidth = 1920) { + return val * (nowClientWidth / initWidth); + }; + if (myChart1 != null) { + myChart1.clear()//销毁 + } + myChart1= echarts.init(this.$refs.bingbox) + myChart1.clear() + myChart1.off('mouseover') + + // var option = { + // animation:false, //动态展示 + // grid: { + // left: '5%', + // right: '5%', + // bottom: '5%', + // containLabel: true + // }, + // xAxis: { + // type: 'category', + // data: data.xdata, + // // data: ["2024-1-1","2024-1-2","2024-1-3","2024-1-4","2024-1-5","2024-1-6","2024-1-7"], + // axisLine:{ + // lineStyle:{ + // color:'#f6fbfd' + // } + // }, + // axisLabel:{ + // interval:0, + // show: true + // } + // + // }, + // tooltip: { + // trigger: 'axis', + // axisPointer: { + // type: 'shadow' + // }, + // // 使用 formatter 函数设置内容和样式 + // formatter: function(params) { + // var result = '<div style="text-align:left;">'; // 左对齐样式 + // result += params[0].name + '<br>'; // 添加横坐标名称 + // + // params.forEach(function(item) { + // result += item.marker + ' ' + item.seriesName + ': ' + item.value + '<br>'; // 添加数据项 + // }); + // + // result += '</div>'; + // return result; + // } + // }, + // yAxis: [ + // { + // type: 'value', + // name: '分类统计(个)', // 水量单位 + // position: 'left', // 显示在左侧 + // splitLine: { + // show: false, + // lineStyle: { + // color: "rgb(255,16,18)", + // } + // }, + // axisLine: { + // lineStyle: { + // color: '#f4f2fd' + // } + // } + // }, + // { + // type: 'value', + // name: '总量统计(个)', // 数量单位 + // position: 'right', // 显示在右侧 + // splitLine: { + // show: false, + // lineStyle: { + // color: "rgb(255,16,18)", + // } + // }, + // axisLine: { + // lineStyle: { + // color: '#f4be6a' + // } + // } + // } + // ], + // series: [ + // { + // name:'IPv6', + // barWidth: 20, //柱子宽度 + // data:data.ydata1, + // // data:[45,89,56,58,66,12,96], + // color:["#2386bf"], //自定义颜色 + // type: 'bar', + // label:{ + // show:true, + // position:'top', + // formatter:function (params) { + // return params.value; + // } + // } + // + // }, + // { + // name:'DNS', + // barWidth: 20, //柱子宽度 + // data:data.ydata2, + // // data:[450,890,560,580,660,155,85], + // color:["#434ff4"], //自定义颜色 + // type: 'bar', + // label:{ + // show:true, + // position:'top', + // formatter:function (params) { + // return params.value; + // } + // } + // + // }, + // { + // name:'DoT', + // barWidth: 20, //柱子宽度 + // data:data.ydata3, + // // data:[150,290,560,380,660,105,815], + // color:["rgba(58,76,222,0.89)"], //自定义颜色 + // type: 'bar', + // label:{ + // show:true, + // position:'top', + // formatter:function (params) { + // return params.value; + // } + // } + // + // }, + // { + // name:'DoH', + // barWidth: 20, //柱子宽度 + // data:data.ydata4, + // // data:[650,790,560,180,660,15,85], + // color:["#117cf4"], //自定义颜色 + // type: 'bar', + // label:{ + // show:true, + // position:'top', + // formatter:function (params) { + // return params.value; + // } + // } + // + // } + // , + // { + // name:'总量', + // barWidth: 20, //柱子宽度 + // data:data.ydata5, + // // data:[1120,7090,5660,1800,6060,105,805], + // color:["#f4be6a"], //自定义颜色 + // type: 'line', + // yAxisIndex: 1, + // label:{ + // show:true, + // position:'top', + // formatter:function (params) { + // return params.value; + // } + // } + // + // } + // ], + // graphic: [ + // { + // type:'group', + // left:'center', + // top:25, + // children:[ + // { + // type: 'rect', + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#2386bf' // 设置第一个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 25, + // style: { + // text: 'IPv6', // 设置第一个色块的含义 + // fill: '#2386bf', + // fontSize: 12 + // }, + // z: 100 + // }, + // //////////////// + // { + // type: 'rect', + // left: 75, + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#434ff4' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 100, + // style: { + // text: 'DNS', // 设置第二个色块的含义 + // fill: '#434ff4', + // fontSize: 12 + // }, + // z: 100 + // }, + // /////////////// + // { + // type: 'rect', + // left:150 , + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: 'rgba(58,76,222,0.89)' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 175, + // style: { + // text: 'DoT', // 设置第二个色块的含义 + // fill: 'rgba(58,76,222,0.89)', + // fontSize: 12 + // }, + // z: 100 + // }, + // ///////////////////////////////// + // { + // type: 'rect', + // left: 225, + // shape: { + // width: 20, + // height: 20 + // }, + // style: { + // fill: '#117cf4' // 设置第二个色块的颜色 + // }, + // z: 100 + // }, + // { + // type: 'text', + // left: 250, + // style: { + // text: 'DoH', // 设置第二个色块的含义 + // fill: '#117cf4', + // fontSize: 12 + // }, + // z: 100 + // }, + // // ////////////////////////////// + // // { + // // type: 'rect', + // // left: 300, + // // shape: { + // // width: 20, + // // height: 20 + // // }, + // // style: { + // // fill: '#f4be6a' // 设置第二个色块的颜色 + // // }, + // // z: 100 + // // }, + // // { + // // type: 'text', + // // left: 325, + // // style: { + // // text: '五线', // 设置第二个色块的含义 + // // fill: '#f4be6a', + // // fontSize: 12 + // // }, + // // z: 100 + // // } + // ] + // } + // + // ] + // }; + + var option = { + dataset: { + source:data.data + // source: [ + // ['延时', '节点'], + // [89.3, 'Matcha Latte'], + // [57.1, 'Milk Tea'], + // [74.4, 'Cheese Cocoa'], + // [50.1, 'Cheese Brownie'], + // [89.7, 'Matcha Cocoa'], + // [68.1, 'Tea'], + // [19.6, 'Orange Juice'], + // [10.6, 'Lemon Juice'], + // [32.7, 'Walnut Brownie'] + // ] + }, + grid: {containLabel: true}, + xAxis: {name: 'amount'}, + yAxis: {type: 'category'}, + visualMap: { + orient: 'horizontal', + left: 'center', + min: 0, + max: 50, + text: ['High Score', 'Low Score'], + // Map the score column to color + dimension: 0, + inRange: { + color: ['#11da11', '#E15457'] + } + }, + series: [ + { + type: 'bar', + encode: { + // Map the "amount" column to X axis. + x: 'score', + // Map the "product" column to Y axis + y: 'product' + } + } + ] + }; + + + + + + + + + myChart1.setOption(option,true) + window.addEventListener("resize", () => { + myChart1.resize(); + }); + } + }, + beforeDestroy() { + myChart1.clear() + }, + destroyed() { + myChart1.clear() + }, + mounted(){ + // this.bingfn(this.bing) + }, + } +</script> + +<style scoped="scoped"> +</style> diff --git a/src/views/menuMBZTGZ/index.vue b/src/views/menuMBZTGZ/index.vue new file mode 100644 index 0000000..fed0fda --- /dev/null +++ b/src/views/menuMBZTGZ/index.vue @@ -0,0 +1,225 @@ +<template> + <div class="home" ref="appRef"> + <div class="show"> + <div><span style="float: left;font-size: 20px;margin-left: 2%;color: #00C0FF;margin-top: 1%">{{"目标IP:"+parentLevelRow.target}}</span></div> + <div class="tag"> + <el-tag class="tags" :style="{'color': (tag==='目标时延') ? '#f8fdff': '#565e6e'}" @click="updateTag('目标时延')">目标时延:</el-tag> + <el-tag class="tags1" :style="{'color': (tag1==='ICMP/v6延时') ? '#f8fdff': '#565e6e'}" @click="updateTag1('ICMP/v6延时')">ICMP/v6延时</el-tag> + <el-tag class="tags1" :style="{'color': (tag1==='DNS查询时延') ? '#f8fdff': '#565e6e'}" @click="updateTag1('DNS查询时延')">DNS查询时延</el-tag> + <el-tag class="tags1" :style="{'color': (tag1==='TCP连接时延') ? '#f8fdff': '#565e6e'}" @click="updateTag1('TCP连接时延')">TCP连接时延</el-tag> + <el-tag class="tags" :style="{'color': (tag==='应答内容') ? '#f8fdff': '#565e6e'}" @click="updateTag('应答内容')">应答内容</el-tag> + </div> + <div v-if="tag==='应答内容'" class="answer"> + <div style="display: flex;margin-right: 5px;"> + <span style="margin-right: 2%;font-size: 25px;width: 15%">目标域名:</span> + <el-input v-model="input" placeholder="请输入目标IP"></el-input> + </div> + <el-button type="primary" style="margin-top: 2%;margin-bottom: 10%">查询</el-button> + + </div> + <div class="top" v-if="tag==='目标时延'"> + <div class="top-left"> + <SourceView class="top-left-target" :left1data="left1data"/> + </div> + <TargetView class="top-right" :left1data="left1data"/> + </div> + <div class="top" v-if="tag==='应答内容'"> + <div class="top-left"> + <div class="top-left-target" > + <div style="display: flex"> + <span style="font-size: 20px;margin-top: 1%;margin-left: 2%;margin-right: 2%;margin-top: 2%">应答结果参考来源</span> + <div class="project" style="margin-top: 2%"> + <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> + <div style="width: 90%;height: 75%;background-color: #324c98;margin-top: 1.5%;margin-left: auto; margin-right: auto;"></div> + + </div> + <!-- <SourceView class="top-left-target"/>--> + </div> + <div class="top-right" > + <div style="display: flex"> + <span style="font-size: 20px;margin-top: 1%;margin-left: 2%;margin-right: 2%;margin-top: 2%">目标解析器响应结果</span> + </div> + <div style="width: 90%;height: 75%;background-color: #324c98;margin-top: 3%;margin-left: auto; margin-right: auto;"></div> + </div> +<!-- <TargetView class="top-right"/>--> + </div> + <NodeView class="bottom" v-if="tag==='目标时延'"></NodeView> + </div> + </div> +</template> + +<script> +import TargetView from './module/target.vue' +import ImageView from './module/image.vue' +import SourceView from './module/source.vue' +import NodeView from './module/node.vue' +export default { + name: 'home', + components: { TargetView, ImageView, SourceView, NodeView }, + created() { + this.parentLevelRow = this.$route.query.row; + this.input=this.parentLevelRow.target_domain; + + + }, + // mounted() { + // this.$router.push('/range/home') + // }, + methods:{ + + + updateTag(val){ + if(val==='目标时延'){ + this.tag=val + this.tag1="ICMP/v6延时" + }else { + this.tag=val + this.tag1="" + } + + }, + updateTag1(val){ + this.tag1=val; + this.tag='目标时延'; + this.left1data.type=this.changePeram(val); + this.left1data.target=this.parentLevelRow.target; + + }, + changePeram(val){ + switch (val) { + case 'ICMP/v6延时': + return 'icmp'; + break; + case 'DNS查询时延': + return 'dns'; + break; + case 'TCP连接时延': + return 'tcp'; + break; + default: + console.log('No option selected'); + break; + } + } + }, + data() { + return { + left1data:{ + target:'1.1.1.1', + type:'icmp', + }, + leftYdata:[], + parentLevelRow:{}, + tag:'目标时延', + tag1:"ICMP/v6延时", + input:"", + powerFilter:[ + { + value:'8.8.8.8', + label:'谷歌(8.8.8.8)' + }, + { + value:'0.0.0.0', + label:'**(0.0.0.0)' + }, + { + value:'1.1.1.1', + label:'**(1.1.1.1)' + }, + ], + } + }, + +} +</script> +<style lang="less" scoped> + .answer { + width: 50%; /* 设置宽度为 50% */ + margin: 0 auto; /* 水平居中 */ + text-align: center; /* 内容居中 */ + margin-top: 5%; + } + .tag{ + margin-left: 9%; + .tags{ + margin-right: 1%; + margin-left: 5%; + font-size: 23px; + border: none; + background-color: transparent !important; + color: #565e6e; + } + .tags1{ + margin-right: 2%; + margin-top: 2%; + font-size: 18px; + border: none; + background-color: transparent !important; + color: #565e6e; + } + } +.home { + width: 100%; + height: 100%; + position: relative; /* 确保相对定位生效 */ +} +.show { + height: 95%; + width: 95%; + position: absolute; /* 绝对定位 */ + top: 50%; /* 向下偏移50% */ + left: 50%; /* 向右偏移50% */ + transform: translate(-50%, -50%); /* 回移50% */ + /*display: flex;*/ + /*flex-direction: column;*/ + /*justify-content: space-between;*/ + /*overflow-y: auto;*/ + +} +.top { + height: 49%; + display: flex; + flex-direction: row; + justify-content: space-between; + .top-left { + width: 49.5%; + display: flex; + flex-direction: column; + justify-content: space-between; + .top-left-target { + height: 90%; + background-image:url('../../img/background/homeTargetBg.svg'); + background-repeat: no-repeat; + background-size: cover; + } + /*.top-left-iamge {*/ + /* height: 48%;*/ + /* background-image:url('../../img/background/homeTargetBg.svg');*/ + /* background-repeat: no-repeat;*/ + /* background-size: cover;*/ + /*}*/ + } + .top-right { + width: 49.5%; + height: 90%; + background-image:url('../../img/background/homeSourceBg.svg'); + background-repeat: no-repeat; + background-size: cover; + } +} +.bottom { + height: 44%; + background-image:url('../../img/background/homeNodeBg.svg'); + background-repeat: no-repeat; + background-size: cover; +} +</style> diff --git a/src/views/menuMBZTGZ/mock.js b/src/views/menuMBZTGZ/mock.js new file mode 100644 index 0000000..667bb35 --- /dev/null +++ b/src/views/menuMBZTGZ/mock.js @@ -0,0 +1,135 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "items": [ + { + "role_name": "admin", + "id": 1, + "create_time": "2024-01-31T10:22:45", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "developer", + "id": 2, + "create_time": "2024-01-31T11:29:17", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "experimenter", + "id": 3, + "create_time": "2024-01-31T11:33:05", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + } + ] + } + ], + "total": 3, + "page": 1, + "size": 10, + "pages": 1 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/image.vue b/src/views/menuMBZTGZ/module/image.vue new file mode 100644 index 0000000..c5d2b04 --- /dev/null +++ b/src/views/menuMBZTGZ/module/image.vue @@ -0,0 +1,126 @@ +<template> + <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 class="card"> + <div class="title">DNSSEC</div> + <div> + <span class="info-span">{{ target.dnssec }}</span> + <span class="unit-span">个</span> + </div> + </div> + <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> + + +</template> + +<script> +import { Loading } from 'element-ui' +import { getTargetsResponse } from './imageMock.js' +export default { + name: 'imageView', + data() { + return { + loading: false, + imageData: {}, + target:{ + dnssec:0, + doh:0, + dot:0, + v6dns:0 + } + } + }, + created() { + this.init() + }, + mounted() { + // this.init() + }, + methods: { + init () { + // this.imageData = getTargetsResponse?.result + this.loading = true + 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) + }).finally(() => { + this.loading = false + }) + } + } +} +</script> + +<style lang="less" scoped> +.box { + width: 100%; + height: 80%; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + .card { + flex: 1; + .title { + color: #FFF; + font-family: PingFang HK; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; + margin-bottom: 10px; + } + .info-span { + color: #03F4FA; + font-family: PingFang HK; + font-size: 32px; + font-style: normal; + font-weight: 500; + line-height: normal; + padding: 5px; + } + .unit-span { + color: #FFF; + opacity: 0.7; + font-family: PingFang HK; + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: normal; + } + } +} +.box .card:not(:last-child) { + border-right: 1px solid rgba(216, 216, 216, 0.2); +} +</style>
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/imageMock.js b/src/views/menuMBZTGZ/module/imageMock.js new file mode 100644 index 0000000..ff5c210 --- /dev/null +++ b/src/views/menuMBZTGZ/module/imageMock.js @@ -0,0 +1,12 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "total_image_count": 45, + "system_image_count": 10, + "buildin_image_count": 34, + "define_image_count": 1 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/node.vue b/src/views/menuMBZTGZ/module/node.vue new file mode 100644 index 0000000..c887413 --- /dev/null +++ b/src/views/menuMBZTGZ/module/node.vue @@ -0,0 +1,436 @@ +<template> + <div class="node-card"> + <span style="font-size: 20px;float: left;margin-top: 0.5%;margin-left: 2%;margin-bottom: 0.5%">节点信息</span> + <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 { + 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() + }, + methods: { + handleSizeChange(val) { + console.log(`每页 ${val} 条`); + this.size=val + this.query() + }, + 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, + } + // 使用 Object.entries() 来遍历对象的键值对,并过滤掉值为空的属性 + const filteredData = {}; + for (const [key, value] of Object.entries(data)) { + if (value !== "") { + filteredData[key] = value; + } + } + 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) + }) + + }, + // 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: 85%; + 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%; + height: 100%; + .node-chart { + width: 100%; + height: 100%; + } + .range-select { + position: absolute; + top: 12px; + right: 260px; + ::v-deep .el-input { + width: 50%; + .el-input__inner { + background-color: transparent !important; + border-color: transparent; + border-radius: 0; + color: #FFFFFF; + } + /* select去除竖线 */ + .el-input__suffix::before { + content: ""; + width: 0; + height: 0; + margin: 0; + position: absolute; + } + /*select的上下箭头图标样式*/ + .el-select__caret { + color: #FFFFFF; + } + } + } + .tabs-container { + position: absolute; + top: 10px; + right: 36px; + ::v-deep .el-tabs__nav-wrap::after { + background-color: transparent; + } + ::v-deep .el-tabs__active-bar { + background-color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item { + color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item.is-active { + color: #FFFFFF; + } + } +} +</style>
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/nodeMock.js b/src/views/menuMBZTGZ/module/nodeMock.js new file mode 100644 index 0000000..e4c5983 --- /dev/null +++ b/src/views/menuMBZTGZ/module/nodeMock.js @@ -0,0 +1,15 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "total_count": 7, + "da_count": 1, + "relay_count": 4, + "exit_count": 2, + "onion_count": 0, + "client_count": 0, + "other_count": 0 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/source.vue b/src/views/menuMBZTGZ/module/source.vue new file mode 100644 index 0000000..1ce7437 --- /dev/null +++ b/src/views/menuMBZTGZ/module/source.vue @@ -0,0 +1,309 @@ +<template> + <div class="source-card"> +<!-- <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 { + props: { + left1data: { + type: Object, + // required: true, + default: function() { + return { + target:'', + type: '', + } + } + } + }, + watch: { + left1data: { + handler(newVal, oldVal) { + console.log('left1data changed:', newVal); + this.querydelay() + }, + deep: true + } + }, + name: 'SourceView', + components: { + ZhuZhuangTu3, + }, + data() { + return { + loading: false, + sourceData: {}, + sourceDataX: [], + sourceDataY: [], + cpuList: [], + memoryList: [], + activeName: 'CPU', + sourceChart: null, + rangeDict: [], + zhudouble:{ + xdata:[], + ydata1:[], //ipv6 + }, + } + }, + created() { + }, + mounted(){ + // this.init() + this.querydelay() + // this.getRangeDict() + }, + methods: { + querydelay(){ + const reqParams = { + "target": this.left1data.target, + "type": this.left1data.type, + } + this.loading = true + this.$axios.get(this.$http.api.targetDelay, reqParams).then(res => { + if (res.code == 200) { + for (let i = 0; i <res.delay_data.length>10?10:res.delay_data.length ; i++) { + this.zhudouble.xdata.push(res.delay_data[i].Id); + this.zhudouble.ydata1.push(res.delay_data[i].CurrDelay); + } + } + this.$refs.zhudouble.bingfn(this.zhudouble) + + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + + }, + // init() { + // + // this.loading = true + // 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) + // }).finally(() => { + // this.loading = false + // // this.initEcharts() + // }) + // }, + initEcharts() { + let that = this + var chartDom = document.getElementById('resource'); + this.sourceChart = echarts.init(chartDom); + var option; + + option = { + title: { + text: '靶场资源使用排序', + left: '10', + 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.sourceDataX, + axisTick: { + // alignWithLabel: true + show: false + }, + axisLabel: { + fontSize: '14', + color: 'rgba(255, 255, 255, 0.7)' + } + } + ], + yAxis: [ + { + type: 'value', + axisLabel: { + fontSize: '12', + color: 'rgba(255, 255, 255, 0.7)', + formatter: function(value) { + return value + ' (mcore)' + } + }, + splitLine: { + show: true, + lineStyle: { + color: ['rgba(199, 199, 200, 0.1)'], + width: 1, + type: 'dashed' + }, + } + } + ], + series: [ + { + // name: 'Direct', + type: 'bar', + barWidth: '20%', + data: this.sourceDataY, + 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: '#01FFFF' }, + { offset: 1, color: '#2160B8' } + ]) + } + } + } + ] + }; + option && this.sourceChart.setOption(option); + //点击事件 + this.sourceChart.on('click', function(params) { + const target_name = params.name + const target_id = that.rangeDict.find(item => item.label === target_name)?.value + that.$store.commit('globalAttrs/setCheckMenu', 'rangeConfigManage') + that.$store.commit('range/setTargetId', target_id) + }); + }, + // 刷新图标数据 + refreshData(data, tabName){ + if(!this.sourceChart){ + return + } + //更新数据 + var option = this.sourceChart.getOption() + option.series[0].data = data + option.yAxis[0].axisLabel.formatter = function(value) { + if (tabName === 'MEMEORY') { + return value + ' (Mi)' + } else { + return value + ' (mcore)' + } + } + this.sourceChart.setOption(option) + }, + tabClick(tab, event) { + switch (tab.name) { + case 'CPU': + this.refreshData(this.cpuList, 'CPU') + break; + case 'MEMEORY': + this.refreshData(this.memoryList, 'MEMEORY') + break; + default: + this.refreshData(this.cpuList, 'CPU') + 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) + // }) + // } + } +} +</script> + +<style lang="less" scoped> +.source-card { + position: relative; + width: 100%; + height: 100%; + .source-chart { + width: 100%; + height: 100%; + } + .tabs-container { + position: absolute; + top: 10px; + right: 36px; + ::v-deep .el-tabs__nav-wrap::after { + background-color: transparent; + } + ::v-deep .el-tabs__active-bar { + background-color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item { + color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item.is-active { + color: #FFFFFF; + } + } +} +</style>
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/sourceMock.js b/src/views/menuMBZTGZ/module/sourceMock.js new file mode 100644 index 0000000..c8397ac --- /dev/null +++ b/src/views/menuMBZTGZ/module/sourceMock.js @@ -0,0 +1,28 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "quick01": { + "total_memory": 3773.94921875, + "total_cpu": 24.433999999999997 + }, + "quick02": { + "total_memory": 1546.80078125, + "total_cpu": 76.94800000000001 + }, + "quick03": { + "total_memory": 1556.7578125, + "total_cpu": 79.413 + }, + "custom01": { + "total_memory": 0, + "total_cpu": 0 + }, + "custom02": { + "total_memory": 0, + "total_cpu": 0 + } + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/target.vue b/src/views/menuMBZTGZ/module/target.vue new file mode 100644 index 0000000..f304fdc --- /dev/null +++ b/src/views/menuMBZTGZ/module/target.vue @@ -0,0 +1,263 @@ +<template> + <div class="source-card"> + <!-- <div class="source-chart" id="resource" v-loading="loading"></div>--> + <ZhuZhuangTu_jbs :active="0" ref="zhudouble" :bing="zhudouble"></ZhuZhuangTu_jbs> + <!-- <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 ZhuZhuangTu_jbs from '../echarts/zhuzhuangtu_jbs' + + import { getTargetsResponse } from './sourceMock.js' + export default { + props: { + left1data: { + type: Object, + // required: true, + default: function() { + return { + target:'', + type: '', + } + } + } + }, + watch: { + left1data: { + handler(newVal, oldVal) { + console.log('left1data changed:', newVal); + this.querydelay() + }, + deep: true + } + }, + name: 'SourceView', + components: { + ZhuZhuangTu_jbs, + }, + data() { + return { + loading: false, + sourceData: {}, + sourceDataX: [], + sourceDataY: [], + cpuList: [], + memoryList: [], + activeName: 'CPU', + sourceChart: null, + rangeDict: [], + zhudouble:{ + data:[ + ['延时', '节点'], + ], + }, + } + }, + created() { + }, + mounted(){ + this.init() + // this.getRangeDict() + }, + methods: { + init() { + const reqParams = { + "target": this.left1data.target, + "type": this.left1data.type, + } + console.log("GGGGGGGGGGGGGGGGGGGG") + console.log(reqParams) + console.log("GGGGGGGGGGGGGGGGGGGG") + this.loading = true + this.$axios.get(this.$http.api.targetDelay,reqParams).then(res => { + if (res.code == 200) { + for (let i = 0; i <res.delay_data.length>10?10:res.delay_data.length ; i++) { + let A=[]; + A.push(res.delay_data[i].CurrDelay); + A.push(res.delay_data[i].Id); + this.zhudouble.data.push(A); + } + this.$refs.zhudouble.bingfn(this.zhudouble) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + this.initEcharts() + }) + }, + initEcharts() { + let that = this + var chartDom = document.getElementById('resource'); + this.sourceChart = echarts.init(chartDom); + var option; + + option = { + title: { + text: '靶场资源使用排序', + left: '10', + 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.sourceDataX, + axisTick: { + // alignWithLabel: true + show: false + }, + axisLabel: { + fontSize: '14', + color: 'rgba(255, 255, 255, 0.7)' + } + } + ], + yAxis: [ + { + type: 'value', + axisLabel: { + fontSize: '12', + color: 'rgba(255, 255, 255, 0.7)', + formatter: function(value) { + return value + ' (mcore)' + } + }, + splitLine: { + show: true, + lineStyle: { + color: ['rgba(199, 199, 200, 0.1)'], + width: 1, + type: 'dashed' + }, + } + } + ], + series: [ + { + // name: 'Direct', + type: 'bar', + barWidth: '20%', + data: this.sourceDataY, + 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: '#01FFFF' }, + { offset: 1, color: '#2160B8' } + ]) + } + } + } + ] + }; + option && this.sourceChart.setOption(option); + //点击事件 + this.sourceChart.on('click', function(params) { + const target_name = params.name + const target_id = that.rangeDict.find(item => item.label === target_name)?.value + that.$store.commit('globalAttrs/setCheckMenu', 'rangeConfigManage') + that.$store.commit('range/setTargetId', target_id) + }); + }, + // 刷新图标数据 + refreshData(data, tabName){ + if(!this.sourceChart){ + return + } + //更新数据 + var option = this.sourceChart.getOption() + option.series[0].data = data + option.yAxis[0].axisLabel.formatter = function(value) { + if (tabName === 'MEMEORY') { + return value + ' (Mi)' + } else { + return value + ' (mcore)' + } + } + this.sourceChart.setOption(option) + }, + tabClick(tab, event) { + switch (tab.name) { + case 'CPU': + this.refreshData(this.cpuList, 'CPU') + break; + case 'MEMEORY': + this.refreshData(this.memoryList, 'MEMEORY') + break; + default: + this.refreshData(this.cpuList, 'CPU') + break; + } + }, + } + } +</script> + +<style lang="less" scoped> + .source-card { + position: relative; + width: 100%; + height: 100%; + .source-chart { + width: 100%; + height: 100%; + } + .tabs-container { + position: absolute; + top: 10px; + right: 36px; + ::v-deep .el-tabs__nav-wrap::after { + background-color: transparent; + } + ::v-deep .el-tabs__active-bar { + background-color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item { + color: rgba(255, 255, 255,0.5); + } + ::v-deep .el-tabs__item.is-active { + color: #FFFFFF; + } + } + } +</style>
\ No newline at end of file diff --git a/src/views/menuMBZTGZ/module/targetMock.js b/src/views/menuMBZTGZ/module/targetMock.js new file mode 100644 index 0000000..2ca003e --- /dev/null +++ b/src/views/menuMBZTGZ/module/targetMock.js @@ -0,0 +1,12 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "total_target_count": 5, + "deploy_success_count": 0, + "deploy_fail_count": 0, + "no_deploy_count": 2 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuSurrogateInformation/module/Header.vue b/src/views/menuSurrogateInformation/module/Header.vue new file mode 100644 index 0000000..54ff3e7 --- /dev/null +++ b/src/views/menuSurrogateInformation/module/Header.vue @@ -0,0 +1,89 @@ +<template> +<div class="head"> + <div class="target-select"> + <span style="font-size: 30px;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>
\ No newline at end of file diff --git a/src/views/menuSysManagement/index.vue b/src/views/menuSysManagement/index.vue new file mode 100644 index 0000000..a729ad8 --- /dev/null +++ b/src/views/menuSysManagement/index.vue @@ -0,0 +1,414 @@ +<template> + <div class="range-config-manage" ref="appRef"> + <div class="show"> + <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" + 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="account" + label="账号" + width="280"/> + <el-table-column + align="center" + prop="username" + label="姓名" + width="250"/> + <el-table-column + align="center" + prop="time" + label="创建时间" + width="280"/> + <el-table-column + align="center" + prop="created_by" + label="创建人" + width="280"/> + <el-table-column + align="center" + prop="group" + label="权限组" + width="280"/> + <el-table-column + align="center" + label="操作" + width="250" + > + <template slot-scope="scope"> + <el-button type="text" size="small" :loading="scope.row.delLoading" @click="del(scope.row)">删除</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" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + > + </el-pagination> + <div class="mask"></div> + <UserForm + ref="userForm" + :is-add="isAdd" + :permission-dict="permissionDict" + @refresh="init"> + </UserForm> + </div> + </div> +</template> +<script> +import Header from './module/Header.vue' +import UserForm from './module/UserForm.vue' +import { getTargetsResponse } from './mock.js' +export default { + name: "RangeConfigManage", + components:{ Header, UserForm }, + data(){ + return{ + page: 1, + size: 10, + total: 0, + isAdd: false, + loading: false, + target_id: '', + tableData: [], + permissionDict: [] + } + }, + mounted() { + + }, + watch: {}, + created() { + this.init() + }, + methods:{ + init(params={}) { + // TODO: 暂时注释接口 + const reqParams = { + "page": this.page, + "per_page": this.size, + } + this.loading = true + this.$axios.get(this.$http.api.user, reqParams).then(res => { + if (res.code == 200) { + this.total = res?.total + this.tableData = res?.data + this.tableData.map(item => { + item.permissions.map(permi => { + this.$set(permi, 'delLoading', false) + return permi + }) + return item + }) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + query(params) { + this.init(params) + }, + // 打开添加角色dialog + addRole() { + this.isAdd = true + // this.$refs.userForm.title = '新增角色' + document.querySelector('.mask').style.display = 'block' + this.$refs.userForm.visible = true + }, + // 删除权限 + delPermission(permission, role_id) { + const url = this.$http.api.delPermission + '/' + role_id + permission.delLoading = true + this.$axios.put(url, {}, {permission_id: permission.id}).then(res => { + if (res.code == 200 || res.code == "OK") { + this.$notify({ + title: '删除权限成功', + type: 'success', + duration: 2500 + }) + this.init() + } + }).catch(err => { + console.log(err) + }).finally(() => { + permission.delLoading = false + }) + }, + // 删除 + del(row) { + this.$confirm('此操作将永久删除该任务, 是否继续?', '确认删除', { + confirmButtonText: '确认删除', + cancelButtonText: '取消', + type: 'info' + }).then(() => { + this.delUser(row) + }).catch(() => { + this.$notify({ + type: 'info', + message: '已取消删除' + }) + }) + }, + delUser(row) { + const url = this.$http.api.delRole + '/' + row.id + row.delLoading = true + this.$axios.delete(url, {}).then(res => { + if (res.code == 200 || res.code == "OK") { + this.$notify({ + title: '删除成功', + type: 'success', + duration: 2500 + }) + this.init() + } + }).catch(err => { + console.log(err) + }).finally(() => { + row.delLoading = false + }) + }, + // 详情 + taskInfo(val) { + this.$router.push({ path: 'menuTaskInfo', query: { row: val } }); + }, + // 获取权限字典 + getPermissionDict() { + const params = { + page: 1, + size: 99 + } + this.$axios.get(this.$http.api.getPermissionList, params).then(res => { + if (res.code == 200 || res.code == "OK") { + this.permissionDict = res?.result?.items.map(item => { + return { + label: item.permission_name, + value: item.id + } + }) + } + }).catch(err => { + console.log(err) + }) + }, + // 修改每页数据条数 + handleSizeChange(val) { + console.log(`每页 ${val} 条`) + this.page=1 + this.size=val + this.query() + }, + // 修改页数 + handleCurrentChange(val) { + console.log(`当前页: ${val}`) + this.page=val + this.query() + } + } +} + +</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%; + .permission-btn { + display: inline-block; + margin: 6px; + padding: 5px 8px; + border-radius: 3px; + color:rgba(0, 0, 0, 0.90); + background: #02DDEA; + } +} +.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%,高度自适应保持宽高比 */ + /*background-size: cover; !* 宽度为100%,高度自适应保持宽高比 *!*/ + + /*display: flex; !* 将容器设置为 Flex 容器 *!*/ + /*justify-content: center; !* 水平居中子元素 *!*/ + /*align-items: center; !* 垂直居中子元素 *!*/ + + .list{ + width: 95%; + height: 77%; + 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> diff --git a/src/views/menuSysManagement/mock.js b/src/views/menuSysManagement/mock.js new file mode 100644 index 0000000..667bb35 --- /dev/null +++ b/src/views/menuSysManagement/mock.js @@ -0,0 +1,135 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "items": [ + { + "role_name": "admin", + "id": 1, + "create_time": "2024-01-31T10:22:45", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "developer", + "id": 2, + "create_time": "2024-01-31T11:29:17", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "experimenter", + "id": 3, + "create_time": "2024-01-31T11:33:05", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + } + ] + } + ], + "total": 3, + "page": 1, + "size": 10, + "pages": 1 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuSysManagement/module/Header.vue b/src/views/menuSysManagement/module/Header.vue new file mode 100644 index 0000000..186eabf --- /dev/null +++ b/src/views/menuSysManagement/module/Header.vue @@ -0,0 +1,54 @@ +<template> +<div class="head"> + <div class="target-select"> + <span style="font-size: 30px;float: left;padding-top: 1%">用户列表</span> + </div> +<!-- <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> + +<script> +export default { + name: 'Header', + props: [], + data() { + return { + role_name: '' + } + }, + watch: {}, + methods: { + // 新增 + addRole() { + this.$emit('addRole') + } + } +} +</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%; + color: #ffffff; + } +} +</style>
\ No newline at end of file diff --git a/src/views/menuSysManagement/module/UserForm.vue b/src/views/menuSysManagement/module/UserForm.vue new file mode 100644 index 0000000..7628749 --- /dev/null +++ b/src/views/menuSysManagement/module/UserForm.vue @@ -0,0 +1,245 @@ +<template> + <div + class="user-dialog" + v-if="visible" + > +<!-- <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 + ref="userForm" + :model="form" + :rules="rules" + label-width="180px" + class="user-form" + > + <el-row style="margin-left: 5%;margin-top: 8%"> + <el-col :span="19"> + <el-form-item label="姓名" prop="username"> + <el-input v-model="form.username" placeholder="请输入姓名"></el-input> + </el-form-item> + <el-form-item label="账号" prop="domain"> + <el-input v-model="form.account" placeholder="请输入账号"></el-input> + </el-form-item> + <el-form-item label="密码" prop="inject"> + <el-input v-model="form.pwd" placeholder="请输入密码"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="submit-footer" style="margin-top: 10%"> + <div> + <el-button class="glBut" type="primary" @click="close">取消</el-button> + <el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">确认创建</el-button> + </div> + </div> + </div> +</template> + +<script> +export default { + name: 'UserForm', + // props: ['isAdd', 'permissionDict'], + data() { + return { + agencyLabel:false, + visible: false, + loading: false, + title: '任务创建', + form: { + account:"", //代理名称 + cur_user:"", //任务目标 + pwd:"", //执行代理 + username:"", //目标域名 + }, + role_id: '', + rules: { + account: [ + // { required: true, message: '请输入任务名称', trigger: 'blur' }, + { message: '请输入任务名称', trigger: 'blur' }, + { max: 50, message: '任务名称长度不能超过50个字符', trigger: 'blur' } + ], + pwd: [ + // { required: true, message: '请输入任务名称', trigger: 'blur' }, + { message: '请输入任务名称', trigger: 'blur' }, + { max: 50, message: '任务名称长度不能超过50个字符', trigger: 'blur' } + ], + username: [ + // { 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() { + let data={ + "account":this.form.account, + "cur_user":"获取当前用户", + "pwd":this.form.pwd, + "username":this.form.username, + } + this.$axios.post(this.$http.api.user,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 + const url = this.$http.api.addRole + this.$axios.post(url, this.form).then(res => { + if (res.code == 200 || res.code == "OK") { + this.resetForm() + this.close() + this.$emit('refresh') + this.$notify({ + title: '创建角色成功', + type: 'success', + duration: 2500 + }) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + edit() { + this.loading = true + const url = this.$http.api.editRole + `/${this.role_id}` + this.$axios.put(url, this.form.permissions).then(res => { + if (res.code == 200 || res.code == "OK") { + this.resetForm() + this.close() + this.$emit('refresh') + this.$notify({ + title: '编辑角色成功', + type: 'success', + duration: 2500 + }) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + resetForm() { + this.agencyLabel=false, + this.roleDict=[], + this.form = { + name:"", //代理名称 + ip:"", //任务目标 + agencyChange:"", //执行代理 + domain:"", //目标域名 + inject:"", //期望注入记录 + strategy:"",//策略 + stateAwareMode:"",//状态感知方式 + switchoverTime:"", //策略切换时限 + executeTime:"", //任务执行时限 + operationalConfiguration:"",//运行配置 + } + } + } +} +</script> + +<style lang="less" scoped> + .user-dialog{ + width: 563px; + height: 463px; + 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/tjpz.svg'); + background-repeat: no-repeat; /* 可选,防止图像重复 */ + background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ + .dialog-title { + font-size: 20px; + float: left; + margin: 11px 0 11px 35px; + } + .user-form { + margin-top: 70px; + text-align: left; + ::v-deep .el-form-item__content { + line-height: 15px; + } + } + .submit-footer{ + width: 100%; + float: left; + margin-top: 50px; + text-align: center; + .glBut{ + width: 90px; + height: 30px; + display: inline-flex; + align-items: center; + justify-content: center; + margin-left: 2%; + background-color: rgba(24, 133, 234, 0.2); + color: #1b7cc4; + } + .but-color { + background-color: #02DDEA; + } + } + } +</style>
\ No newline at end of file diff --git a/src/views/menuTaskInfo/index.vue b/src/views/menuTaskInfo/index.vue new file mode 100644 index 0000000..2b3581e --- /dev/null +++ b/src/views/menuTaskInfo/index.vue @@ -0,0 +1,676 @@ +<template> + <div class="range-config-manage" ref="appRef"> + <div class="show"> + <Header + @addRole="addRole" + ></Header> + <div class="header2"> + <div style="width: 45%; display: inline-block;"> + <el-descriptions class="custom-descriptions" > + <el-descriptions-item label="任务名称" >{{parentLevelRow.name}}</el-descriptions-item> + <el-descriptions-item label="代理编号">{{parentLevelRow.id}}</el-descriptions-item> + <el-descriptions-item label="执行状态"> + <el-tag type="info" v-if="parentLevelRow.status==='stop'">暂停</el-tag> + <el-tag type="warning" v-if="parentLevelRow.status==='working'">执行中</el-tag> + <el-tag type="danger" v-if="parentLevelRow.status==='finish'">已完成</el-tag> + </el-descriptions-item> + <el-descriptions-item label="任务目标"> + {{parentLevelRow.target}} + <span style="color: #00C0FF;margin-left: 5%" @click="getInfoByIp(parentLevelRow)">查看实时状态</span> + </el-descriptions-item> + </el-descriptions> + </div> + <div style="width: 45%; display: inline-block;"> + <el-row style="display: flex; flex-direction: row;"> + <el-col> + <div style="display: flex; flex-direction: column; align-items: center;"> + <el-button type="danger" class="enlarged-button" icon="el-icon-full-screen" circle @click="taskOps(parentLevelRow.id,'stop')"></el-button> + <span style="margin-top: 7%">停止</span> + </div> + </el-col> + <el-col> + <div style="display: flex; flex-direction: column; align-items: center;"> + <el-button type="info" class="enlarged-button" icon="el-icon-video-pause" circle @click="taskOps(parentLevelRow.id,'suspend')"></el-button> + <span style="margin-top: 7%">暂停</span> + </div> + </el-col> + <el-col> + <div style="display: flex; flex-direction: column; align-items: center;"> + <el-button type="success" class="enlarged-button" icon="el-icon-video-play" circle @click="taskOps(parentLevelRow.id,'start')"></el-button> + <span style="margin-top: 7%">开始</span> + </div> + </el-col> + </el-row> + </div> + </div> + <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="start_time" + label="开始执行时间" + width="280"/> + <el-table-column + align="center" + prop="status" + label="当前状态" + min-width="150" + style="width: 50%; height: 10%;" + > + <template slot-scope="scope"> + <el-result icon="success" style="transform: scale(0.8)" v-if="scope.row.policy_id === index0tableDataId"> + <template #title style="color: white;">执行中</template> + </el-result> + <el-result icon="warning" style="transform: scale(0.8)" v-if="scope.row.policy_id != index0tableDataId"> + <template #title style="color: white;">无效</template> + </el-result> + + </template> + </el-table-column> + <el-table-column + align="center" + prop="policy_name" + label="当前策略名称" + width="280"/> + <el-table-column + align="center" + prop="policy_param" + label="策略载荷生成参数" + width="280"> + </el-table-column> + <el-table-column + align="center" + label="执行输出" + min-width="150"> + <template slot-scope="scope"> + <el-button type="primary" @click="newlyPztj=!newlyPztj,getLog(scope.row.policy_id)">查看</el-button> + </template> + </el-table-column> + <el-table-column + align="center" + prop="policy_status" + label="效果评估" + width="280"> + </el-table-column> + + </el-table> + </div> + <div class="mask"></div> + <UserForm + ref="userForm" + :is-add="isAdd" + :permission-dict="permissionDict" + @refresh="init"> + </UserForm> + <div class="popup" v-if="newlyPztj"> + <span style="font-size: 30px;margin-left: 2%;margin-top: 20%">执行日志 <i class="el-icon-close" style="font-size:15px;float: right; padding-right: 7%;padding-top: 2.8%" @click="CustomizationImageFales()"></i></span> + <!-- 在此处指定弹窗的样式和内容 --> +<!-- <i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 2.8%" @click="CustomizationImageFales()"></i>--> + <div class="list" style="width: 90%;margin-left: 5%;margin-top: 5%"> + <el-table + class="custom-table" + ref="multipleTable" + v-loading="loading" + element-loading-text="加载中..." + height="100%" + style="width: 100%;" + :data="tableDataLog" + tooltip-effect="dark" + highlight-current-row + > + <el-table-column + align="center" + type="index" + label="序号" + width="50"/> + <el-table-column + align="center" + prop="time" + label="时间" + width="160"/> + <el-table-column + align="center" + prop="ip" + label="IP" + width="130"> + </el-table-column> + <el-table-column + align="center" + prop="targetip" + label="目标IP" + width="200"/> + <el-table-column + align="center" + prop="level" + label="日志级别" + width="100"> + </el-table-column> + <el-table-column + align="center" + prop="info" + label="日志内容" + width="200"> + </el-table-column> + + </el-table> + </div> + <el-pagination + class="custom-paginationLog" + background + :current-page="page" + :page-sizes="[10, 20, 30, 40]" + :page-size="10" + :total="total" + layout="total, sizes, prev, pager, next, jumper" + @size-change="handleSizeChangeLog" + @current-change="handleCurrentChangeLog" + > + </el-pagination> + + + <footer style="margin-top: 10%"> + <el-button class="glBut" type="primary" @click="CustomizationImageFales()">取消</el-button> + </footer> + + + + + + </div> + </div> + </div> +</template> +<script> +import Header from './module/Header.vue' +import UserForm from './module/UserForm.vue' +import { getTargetsResponse } from './mock.js' +export default { + name: "RangeConfigManage", + components:{ Header, UserForm }, + data(){ + return{ + logId:0, + parentLevelRow:{}, + id_log:'', + page_log:1, + per_page_log:10, + newlyPztj:false, + page: 1, + size: 10, + total: 0, + isAdd: false, + loading: false, + target_id: '', + tableData: [], + tableDataLog: [], + index0tableDataId:0, + permissionDict: [], + } + }, + mounted() { + + }, + watch: {}, + created() { + this.parentLevelRow = this.$route.query.row; + this.init() + }, + methods:{ + getInfoByIp(val){ + this.$router.push({ path: 'menuMBZTGZ', query: { row: val } }); + }, + CustomizationImageFales(){ + this.newlyPztj=false; + document.querySelector('.mask').style.display = 'none' + }, + init(params={}) { + // TODO: 暂时注释接口 + const reqParams = { + "taskid": (this.parentLevelRow.id)?(this.parentLevelRow.id):0, + ...params + } + this.loading = true + this.$axios.get(this.$http.api.taskInfo, reqParams).then(res => { + // if (res.code == 200 || res.code == "OK") { + // this.total = res?.data?.total + // this.total = 100 + this.tableData = res?.data + this.index0tableDataId=res?.data[0].policy_id + this.tableData.map(item => { + item.permissions.map(permi => { + this.$set(permi, 'delLoading', false) + return permi + }) + return item + }) + // } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + taskOps(id,type){ + const reqParams = { + "taskid":id, + "ops": type, + } + this.loading = true + this.$axios.get(this.$http.api.taskOps, reqParams).then(res => { + if (res.code == 200) { + this.$message.success(type+'成功!') + + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + getLog(val) { + // TODO: 暂时注释接口 + document.querySelector('.mask').style.display = 'block', + this.logId=val + + const reqParams = { + "id":this.logId, + "page": this.page_log, + "per_page": this.per_page_log, + } + this.loading = true + this.$axios.get(this.$http.api.taskInfoLog, reqParams).then(res => { + // if (res.code == 200 || res.code == "OK") { + // this.total = res?.data?.total + this.total = 100 + this.tableDataLog = res?.data + this.tableData.map(item => { + item.permissions.map(permi => { + this.$set(permi, 'delLoading', false) + return permi + }) + return item + }) + // } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + getLogPage() { + // TODO: 暂时注释接口 + document.querySelector('.mask').style.display = 'block' + const reqParams = { + "id":this.logId, + "page": this.page_log, + "per_page": this.per_page_log, + } + this.loading = true + this.$axios.get(this.$http.api.taskInfoLog, reqParams).then(res => { + // if (res.code == 200 || res.code == "OK") { + // this.total = res?.data?.total + this.total = 100 + this.tableDataLog = res?.data + this.tableData.map(item => { + item.permissions.map(permi => { + this.$set(permi, 'delLoading', false) + return permi + }) + return item + }) + // } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + query(params) { + this.init(params) + }, + // 打开添加角色dialog + addRole() { + this.isAdd = true + this.$refs.userForm.title = '新增角色' + document.querySelector('.mask').style.display = 'block' + this.$refs.userForm.visible = true + }, + // 删除权限 + delPermission(permission, role_id) { + const url = this.$http.api.delPermission + '/' + role_id + permission.delLoading = true + this.$axios.put(url, {}, {permission_id: permission.id}).then(res => { + if (res.code == 200 || res.code == "OK") { + this.$notify({ + title: '删除权限成功', + type: 'success', + duration: 2500 + }) + this.init() + } + }).catch(err => { + console.log(err) + }).finally(() => { + permission.delLoading = false + }) + }, + // 删除 + del(row) { + this.$confirm('此操作将永久删除该角色, 是否继续?', '确认删除', { + confirmButtonText: '确认删除', + cancelButtonText: '取消', + type: 'info' + }).then(() => { + this.delUser(row) + }).catch(() => { + this.$notify({ + type: 'info', + message: '已取消删除' + }) + }) + }, + delUser(row) { + const url = this.$http.api.delRole + '/' + row.id + row.delLoading = true + this.$axios.delete(url, {}).then(res => { + if (res.code == 200 || res.code == "OK") { + this.$notify({ + title: '删除成功', + type: 'success', + duration: 2500 + }) + this.init() + } + }).catch(err => { + console.log(err) + }).finally(() => { + 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 + }, + // 获取权限字典 + getPermissionDict() { + const params = { + page: 1, + size: 99 + } + this.$axios.get(this.$http.api.getPermissionList, params).then(res => { + if (res.code == 200 || res.code == "OK") { + this.permissionDict = res?.result?.items.map(item => { + return { + label: item.permission_name, + value: item.id + } + }) + } + }).catch(err => { + console.log(err) + }) + }, + // 修改每页数据条数 + handleSizeChange(val) { + console.log(`每页 ${val} 条`) + this.page=1 + this.size=val + this.query() + }, + // 修改页数 + handleCurrentChange(val) { + console.log(`当前页: ${val}`) + this.page=val + this.query() + }, + handleSizeChangeLog(val) { + console.log(`每页 ${val} 条`) + this.page=1 + this.size=val + this.getLogPage() + }, + // 修改页数 + handleCurrentChangeLog(val) { + console.log(`当前页: ${val}`) + this.page=val + this.getLogPage() + }, + } +} + +</script> + +<style lang='less' scoped="scoped"> + .custom-paginationLog{ + /*float: right;*/ + /*margin-left: 20%;*/ + transform: scale(0.8); + /*display: flex;*/ + /*justify-content: flex-end; !* 使用 Flexbox 将内容靠右 *!*/ + /*/deep/ .el-pagination{*/ + /* float: right;*/ + /*}*/ + } + /*.custom-paginationLog /deep/ .el-pagination /deep/ .is-background {*/ + /* float: right;*/ + /*}*/ + .popup{ + z-index: 997; + width: 50%; + height: 90%; + 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; + } + + } + } + } + .header2{ + white-space: nowrap; + width: 100%; + height: auto; + margin-bottom: 1%; + margin-left: 2.5%; + .enlarged-button { + transform: scale(1.5); /* 将按钮和图标整体放大 1.5 倍 */ + margin-left: 3%; + margin-right: 3%; + } + .custom-descriptions{ + background-color: rgba(0,0,0,0); + /deep/ .el-descriptions-item{ + background-color: rgba(19, 34, 99, 1); + } + + + } + /*.custom-descriptions /deep/ .el-descriptions{*/ + /* background-color: #f04247; !* 设置背景颜色为灰色 *!*/ + /*}*/ + } +.custom-table { + width: 100%; + height: 100%; + .permission-btn { + display: inline-block; + margin: 6px; + padding: 5px 8px; + border-radius: 3px; + color:rgba(0, 0, 0, 0.90); + background: #02DDEA; + } +} +.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%,高度自适应保持宽高比 */ + /*background-size: cover; !* 宽度为100%,高度自适应保持宽高比 *!*/ + + /*display: flex; !* 将容器设置为 Flex 容器 *!*/ + /*justify-content: center; !* 水平居中子元素 *!*/ + /*align-items: center; !* 垂直居中子元素 *!*/ + + .list{ + width: 95%; + height: 70%; + 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> diff --git a/src/views/menuTaskInfo/mock.js b/src/views/menuTaskInfo/mock.js new file mode 100644 index 0000000..667bb35 --- /dev/null +++ b/src/views/menuTaskInfo/mock.js @@ -0,0 +1,135 @@ +const getTargetsResponse = { + "code": 200, + "message": "success", + "result": { + "items": [ + { + "role_name": "admin", + "id": 1, + "create_time": "2024-01-31T10:22:45", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "developer", + "id": 2, + "create_time": "2024-01-31T11:29:17", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "国家网络管理", + "id": 4, + "create_time": "2024-01-30T10:04:50" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + }, + { + "permission_name": "用户管理", + "id": 6, + "create_time": "2024-01-30T10:05:30" + }, + { + "permission_name": "角色管理", + "id": 7, + "create_time": "2024-01-30T10:06:22" + }, + { + "permission_name": "首页", + "id": 8, + "create_time": "2024-01-30T10:07:01" + } + ] + }, + { + "role_name": "experimenter", + "id": 3, + "create_time": "2024-01-31T11:33:05", + "permissions": [ + { + "permission_name": "靶场配置管理", + "id": 1, + "create_time": "2024-01-30T10:03:03" + }, + { + "permission_name": "靶场节点管理", + "id": 2, + "create_time": "2024-01-30T10:03:48" + }, + { + "permission_name": "个人管理", + "id": 3, + "create_time": "2024-01-30T10:04:18" + }, + { + "permission_name": "镜像管理", + "id": 5, + "create_time": "2024-01-30T10:05:07" + } + ] + } + ], + "total": 3, + "page": 1, + "size": 10, + "pages": 1 + } +} + +export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/menuTaskInfo/module/Header.vue b/src/views/menuTaskInfo/module/Header.vue new file mode 100644 index 0000000..0f6381b --- /dev/null +++ b/src/views/menuTaskInfo/module/Header.vue @@ -0,0 +1,50 @@ +<template> +<div class="head"> + <div class="target-select"> + <span style="font-size: 30px;float: left;padding-top: 1%">任务详情</span> + </div> +</div> +</template> + +<script> +export default { + name: 'Header', + props: [], + data() { + return { + role_name: '' + } + }, + watch: {}, + methods: { + // 新增 + addRole() { + this.$emit('addRole') + } + } +} +</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%; + color: #ffffff; + } +} +</style>
\ No newline at end of file diff --git a/src/views/menuTaskInfo/module/UserForm.vue b/src/views/menuTaskInfo/module/UserForm.vue new file mode 100644 index 0000000..a99c9d5 --- /dev/null +++ b/src/views/menuTaskInfo/module/UserForm.vue @@ -0,0 +1,178 @@ +<template> + <div + class="user-dialog" + v-if="visible" + > + <span class="dialog-title">{{ title }}</span> + <!-- 在此处指定弹窗的样式和内容 --> + <i class="el-icon-close" style="float: right; padding-right: 8%;padding-top: 3%" @click="close"></i> + <el-form + ref="userForm" + :model="form" + :rules="rules" + 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-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> + </el-col> + </el-row> + </el-form> + <div class="submit-footer"> + <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> + </div> + </div> + </div> +</template> + +<script> +export default { + name: 'UserForm', + props: ['isAdd', 'permissionDict'], + data() { + return { + visible: false, + loading: false, + title: '新增角色', + form: { + role_name: '', // 角色名称 + permissions: [] // 选中权限 + }, + role_id: '', + rules: { + role_name: [ + { required: true, message: '请输入角色名称', trigger: 'blur' } + ], + permissions: [ + { required: true, message: '请选择权限', trigger: 'change' } + ] + } + } + }, + methods: { + 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() + } + } + }) + }, + add () { + this.loading = true + const url = this.$http.api.addRole + this.$axios.post(url, this.form).then(res => { + if (res.code == 200 || res.code == "OK") { + this.resetForm() + this.close() + this.$emit('refresh') + this.$notify({ + title: '创建角色成功', + type: 'success', + duration: 2500 + }) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + edit() { + this.loading = true + const url = this.$http.api.editRole + `/${this.role_id}` + this.$axios.put(url, this.form.permissions).then(res => { + if (res.code == 200 || res.code == "OK") { + this.resetForm() + this.close() + this.$emit('refresh') + this.$notify({ + title: '编辑角色成功', + type: 'success', + duration: 2500 + }) + } + }).catch(err => { + console.log(err) + }).finally(() => { + this.loading = false + }) + }, + resetForm() { + this.form = { + role_name: '', // 角色名称 + permissions: [] // 选中权限 + } + } + } +} +</script> + +<style lang="less" scoped> + .user-dialog{ + width: 520px; + height: 363px; + position: absolute; /* 绝对定位 */ + top: 50%; /* 向下偏移50% */ + left: 50%; /* 向右偏移50% */ + transform: translate(-50%, -50%); /* 回移50% */ + background-image:url('../../../img/background/dialog520-363.svg'); + background-repeat: no-repeat; /* 可选,防止图像重复 */ + background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ + .dialog-title { + font-size: 20px; + float: left; + margin: 11px 0 11px 20px; + } + .user-form { + margin-top: 70px; + text-align: left; + ::v-deep .el-form-item__content { + line-height: 15px; + } + } + .submit-footer{ + width: 100%; + float: left; + margin-top: 50px; + text-align: center; + .glBut{ + width: 90px; + height: 30px; + display: inline-flex; + align-items: center; + justify-content: center; + margin-left: 2%; + background-color: rgba(24, 133, 234, 0.2); + color: #1b7cc4; + } + .but-color { + background-color: #02DDEA; + } + } + } +</style>
\ No newline at end of file |
