summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/img/logyy.jpgbin0 -> 18730 bytes
-rw-r--r--src/img/logyy_美图抠图20240424.pngbin0 -> 119599 bytes
-rw-r--r--src/views/home/echarts/zhuzhuangtu3.vue418
-rw-r--r--src/views/menuMBGZ/index.vue1102
-rw-r--r--src/views/menuMBGZ/module/Header.vue89
-rw-r--r--src/views/menuMBGZ/module/indexDQ2.vue624
-rw-r--r--src/views/menuMBZTGZ/echarts/zhuzhuangtu3.vue296
-rw-r--r--src/views/menuMBZTGZ/echarts/zhuzhuangtu_jbs.vue419
-rw-r--r--src/views/menuMBZTGZ/index.vue225
-rw-r--r--src/views/menuMBZTGZ/mock.js135
-rw-r--r--src/views/menuMBZTGZ/module/image.vue126
-rw-r--r--src/views/menuMBZTGZ/module/imageMock.js12
-rw-r--r--src/views/menuMBZTGZ/module/node.vue436
-rw-r--r--src/views/menuMBZTGZ/module/nodeMock.js15
-rw-r--r--src/views/menuMBZTGZ/module/source.vue309
-rw-r--r--src/views/menuMBZTGZ/module/sourceMock.js28
-rw-r--r--src/views/menuMBZTGZ/module/target.vue263
-rw-r--r--src/views/menuMBZTGZ/module/targetMock.js12
-rw-r--r--src/views/menuSurrogateInformation/module/Header.vue89
-rw-r--r--src/views/menuSysManagement/index.vue414
-rw-r--r--src/views/menuSysManagement/mock.js135
-rw-r--r--src/views/menuSysManagement/module/Header.vue54
-rw-r--r--src/views/menuSysManagement/module/UserForm.vue245
-rw-r--r--src/views/menuTaskInfo/index.vue676
-rw-r--r--src/views/menuTaskInfo/mock.js135
-rw-r--r--src/views/menuTaskInfo/module/Header.vue50
-rw-r--r--src/views/menuTaskInfo/module/UserForm.vue178
27 files changed, 6485 insertions, 0 deletions
diff --git a/src/img/logyy.jpg b/src/img/logyy.jpg
new file mode 100644
index 0000000..4c721ab
--- /dev/null
+++ b/src/img/logyy.jpg
Binary files differ
diff --git a/src/img/logyy_美图抠图20240424.png b/src/img/logyy_美图抠图20240424.png
new file mode 100644
index 0000000..6b7cdc0
--- /dev/null
+++ b/src/img/logyy_美图抠图20240424.png
Binary files differ
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