商业版WAF看板增加地图

This commit is contained in:
GoEdgeLab
2021-12-05 19:38:14 +08:00
parent 90f48a1a3c
commit c3a9f15bc3
6 changed files with 68 additions and 16 deletions

View File

@@ -5,11 +5,15 @@ Vue.component("traffic-map-box", {
}, },
data: function () { data: function () {
let maxPercent = 0 let maxPercent = 0
let isAttack = this.vIsAttack
this.vStats.forEach(function (v) { this.vStats.forEach(function (v) {
let percent = parseFloat(v.percent) let percent = parseFloat(v.percent)
if (percent > maxPercent) { if (percent > maxPercent) {
maxPercent = percent maxPercent = percent
} }
v.formattedCountRequests = teaweb.formatCount(v.countRequests) + "次"
v.formattedCountAttackRequests = teaweb.formatCount(v.countAttackRequests) + "次"
}) })
if (maxPercent < 100) { if (maxPercent < 100) {
@@ -17,10 +21,12 @@ Vue.component("traffic-map-box", {
} }
return { return {
isAttack: isAttack,
stats: this.vStats, stats: this.vStats,
chart: null, chart: null,
minOpacity: 0.2, minOpacity: 0.2,
maxPercent: maxPercent maxPercent: maxPercent,
selectedCountryName: ""
} }
}, },
methods: { methods: {
@@ -29,7 +35,12 @@ Vue.component("traffic-map-box", {
let that = this let that = this
this.chart.setOption({ this.chart.setOption({
backgroundColor: "white", backgroundColor: "white",
grid: {top: 0, bottom: 0, left: 0, right: 0}, grid: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
roam: true, roam: true,
tooltip: { tooltip: {
trigger: "item" trigger: "item"
@@ -50,12 +61,6 @@ Vue.component("traffic-map-box", {
} }
}, },
//select: {itemStyle:{ areaColor: "#8B9BD3", opacity: 0.8 }}, //select: {itemStyle:{ areaColor: "#8B9BD3", opacity: 0.8 }},
label: {
show: true,
formatter: function (args) {
return ""
}
},
tooltip: { tooltip: {
formatter: function (args) { formatter: function (args) {
let name = args.name let name = args.name
@@ -67,7 +72,7 @@ Vue.component("traffic-map-box", {
}) })
if (stat != null) { if (stat != null) {
return name + "<br/>流量:" + stat.formattedBytes + "<br/>请求数" + teaweb.formatNumber(stat.countRequests) + "<br/>流量占比" + stat.percent + "%" return name + "<br/>流量:" + stat.formattedBytes + "<br/>流量占比" + stat.percent + "%<br/>请求数:" + stat.formattedCountRequests + "<br/>攻击数" + stat.formattedCountAttackRequests
} }
return name return name
} }
@@ -81,11 +86,12 @@ Vue.component("traffic-map-box", {
if (fullOpacity > 1) { if (fullOpacity > 1) {
fullOpacity = 1 fullOpacity = 1
} }
let isAttack = this.vIsAttack let isAttack = that.vIsAttack
let bgColor = "#276AC6" let bgColor = "#276AC6"
if (isAttack) { if (isAttack) {
bgColor = "#B03A5B" bgColor = "#B03A5B"
} }
return { return {
name: v.name, name: v.name,
value: v.bytes, value: v.bytes,
@@ -99,6 +105,19 @@ Vue.component("traffic-map-box", {
areaColor: bgColor, areaColor: bgColor,
opacity: fullOpacity opacity: fullOpacity
} }
},
label: {
show: false,
formatter: function (args) {
if (args.name == that.selectedCountryName) {
return args.name
}
return ""
},
fontSize: "10px",
color: "#fff",
backgroundColor: "#8B9BD3",
padding: [2, 2, 2, 2]
} }
} }
}), }),
@@ -123,9 +142,12 @@ Vue.component("traffic-map-box", {
if (v.isSelected) { if (v.isSelected) {
v.itemStyle.opacity = opacity v.itemStyle.opacity = opacity
v.isSelected = false v.isSelected = false
v.label.show = false
that.selectedCountryName = ""
return return
} }
v.isSelected = true v.isSelected = true
that.selectedCountryName = countryName
opacity *= 3 opacity *= 3
if (opacity > 1) { if (opacity > 1) {
opacity = 1 opacity = 1
@@ -136,9 +158,11 @@ Vue.component("traffic-map-box", {
opacity = 0.5 opacity = 0.5
} }
v.itemStyle.opacity = opacity v.itemStyle.opacity = opacity
v.label.show = true
} else { } else {
v.itemStyle.opacity = opacity v.itemStyle.opacity = opacity
v.isSelected = false v.isSelected = false
v.label.show = false
} }
}) })
this.chart.setOption(option) this.chart.setOption(option)
@@ -166,11 +190,13 @@ Vue.component("traffic-map-box", {
<tbody> <tbody>
<tr v-for="(stat, index) in stats.slice(0, 10)"> <tr v-for="(stat, index) in stats.slice(0, 10)">
<td @click.prevent="select(stat.name)" style="cursor: pointer" colspan="2"> <td @click.prevent="select(stat.name)" style="cursor: pointer" colspan="2">
<div class="ui progress bar blue" style="margin-bottom: 0.3em"> <div class="ui progress bar" :class="{red: vIsAttack, blue:!vIsAttack}" style="margin-bottom: 0.3em">
<div class="bar" style="min-width: 0; height: 4px;" :style="{width: stat.percent + '%'}"></div> <div class="bar" style="min-width: 0; height: 4px;" :style="{width: stat.percent + '%'}"></div>
</div> </div>
<div>{{stat.name}}</div> <div>{{stat.name}}</div>
<div><span class="grey">{{stat.percent}}% </span><span class="small grey">{{stat.formattedBytes}}</span></div> <div><span class="grey">{{stat.percent}}% </span>
<span class="small grey" v-if="isAttack">{{stat.formattedCountAttackRequests}}</span>
<span class="small grey" v-if="!isAttack">{{stat.formattedBytes}}</span></div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@@ -30,6 +30,12 @@
.chart-box { .chart-box {
height: 14em; height: 14em;
} }
.traffic-map-box {
height: 16em;
}
.traffic-map-box div::-webkit-scrollbar {
width: 4px;
}
.color-span { .color-span {
font-size: 0.8em; font-size: 0.8em;
padding: 4px; padding: 4px;

View File

@@ -1 +1 @@
{"version":3,"sources":["waf.less"],"names":[],"mappings":"AAAA,GAAG,QACF;EACC,kBAAA;EACA,UAAA;EACA,UAAA;;AAIF;EACC,0BAAA;EACA,2BAAA;;AAFD,KAIC;EACC,kBAAA;EACA,4BAAA;;AANF,KAIC,QAIC,IAAG;EACF,iBAAA;;AATH,KAIC,QAIC,IAAG,MAGF;EACC,cAAA;EACA,mBAAA;;AAbJ,KAkBC,QAAO;EACN,eAAA;;AAnBF,KAsBC,GACC;EACC,aAAA;;AAxBH,KA4BC,QAAO,MACN;EACC,eAAA;;AAKH;EACC,YAAA;;AAGD;EACC,gBAAA;EACA,YAAA;;AAGD,EAAE,OACD;EACC,iBAAA;EACA,YAAA","file":"waf.css"} {"version":3,"sources":["waf.less"],"names":[],"mappings":"AAAA,GAAG,QACF;EACC,kBAAA;EACA,UAAA;EACA,UAAA;;AAIF;EACC,0BAAA;EACA,2BAAA;;AAFD,KAIC;EACC,kBAAA;EACA,4BAAA;;AANF,KAIC,QAIC,IAAG;EACF,iBAAA;;AATH,KAIC,QAIC,IAAG,MAGF;EACC,cAAA;EACA,mBAAA;;AAbJ,KAkBC,QAAO;EACN,eAAA;;AAnBF,KAsBC,GACC;EACC,aAAA;;AAxBH,KA4BC,QAAO,MACN;EACC,eAAA;;AAKH;EACC,YAAA;;AAGD;EACC,YAAA;;AADD,gBAGC,IAAG;EACF,UAAA;;AAIF;EACC,gBAAA;EACA,YAAA;;AAGD,EAAE,OACD;EACC,iBAAA;EACA,YAAA","file":"waf.css"}

View File

@@ -1,6 +1,13 @@
{$layout} {$layout}
{$var "header"}
<!-- world map -->
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
<script type="text/javascript" src="/js/world.js"></script>
<script type="text/javascript" src="/js/world-countries-map.js"></script>
{$end}
{$template "menu"} {$template "menu"}
{$template "/echarts"}
<div class="ui four columns grid"> <div class="ui four columns grid">
<div class="ui column"> <div class="ui column">
@@ -24,6 +31,13 @@
</div> </div>
</div> </div>
<!-- 流量地图 -->
<div class="ui divider"></div>
<div class="traffic-map-box" v-if="!isLoading">
<traffic-map-box :v-stats="topCountryStats" :v-is-attack="true"></traffic-map-box>
</div>
<div class="ui divider"></div>
<!-- 最近日志 --> <!-- 最近日志 -->
<div v-if="accessLogs.length > 0"> <div v-if="accessLogs.length > 0">
<div class="ui divider"></div> <div class="ui divider"></div>

View File

@@ -2,8 +2,6 @@ Tea.context(function () {
this.isLoading = false this.isLoading = false
this.$delay(function () { this.$delay(function () {
let that = this
this.board.countDailyBlocks = teaweb.formatCount(this.board.countDailyBlocks) this.board.countDailyBlocks = teaweb.formatCount(this.board.countDailyBlocks)
this.board.countDailyCaptcha = teaweb.formatCount(this.board.countDailyCaptcha) this.board.countDailyCaptcha = teaweb.formatCount(this.board.countDailyCaptcha)
this.board.countDailyLogs = teaweb.formatCount(this.board.countDailyLogs) this.board.countDailyLogs = teaweb.formatCount(this.board.countDailyLogs)

View File

@@ -45,6 +45,14 @@
height: 14em; height: 14em;
} }
.traffic-map-box {
height: 16em;
div::-webkit-scrollbar {
width: 4px;
}
}
.color-span { .color-span {
font-size: 0.8em; font-size: 0.8em;
padding: 4px; padding: 4px;