diff --git a/web/public/js/components/maps/traffic-map-box.js b/web/public/js/components/maps/traffic-map-box.js
new file mode 100644
index 00000000..296b2806
--- /dev/null
+++ b/web/public/js/components/maps/traffic-map-box.js
@@ -0,0 +1,183 @@
+Vue.component("traffic-map-box", {
+ props: ["v-stats", "v-is-attack"],
+ mounted: function () {
+ this.render()
+ },
+ data: function () {
+ let maxPercent = 0
+ this.vStats.forEach(function (v) {
+ let percent = parseFloat(v.percent)
+ if (percent > maxPercent) {
+ maxPercent = percent
+ }
+ })
+
+ if (maxPercent < 100) {
+ maxPercent *= 1.2 // 不要让某一项100%
+ }
+
+ return {
+ stats: this.vStats,
+ chart: null,
+ minOpacity: 0.2,
+ maxPercent: maxPercent
+ }
+ },
+ methods: {
+ render: function () {
+ this.chart = teaweb.initChart(document.getElementById("traffic-map-box"));
+ let that = this
+ this.chart.setOption({
+ backgroundColor: "white",
+ grid: {top: 0, bottom: 0, left: 0, right: 0},
+ roam: true,
+ tooltip: {
+ trigger: "item"
+ },
+ series: [{
+ type: "map",
+ map: "world",
+ zoom: 1.2,
+ selectedMode: false,
+ itemStyle: {
+ areaColor: "#E9F0F9",
+ borderColor: "#999"
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: "#8B9BD3",
+ opacity: 1.0
+ }
+ },
+ //select: {itemStyle:{ areaColor: "#8B9BD3", opacity: 0.8 }},
+ label: {
+ show: true,
+ formatter: function (args) {
+ return ""
+ }
+ },
+ tooltip: {
+ formatter: function (args) {
+ let name = args.name
+ let stat = null
+ that.stats.forEach(function (v) {
+ if (v.name == name) {
+ stat = v
+ }
+ })
+
+ if (stat != null) {
+ return name + "
流量:" + stat.formattedBytes + "
请求数:" + teaweb.formatNumber(stat.countRequests) + "
流量占比:" + stat.percent + "%"
+ }
+ return name
+ }
+ },
+ data: this.stats.map(function (v) {
+ let opacity = parseFloat(v.percent) / that.maxPercent
+ if (opacity < that.minOpacity) {
+ opacity = that.minOpacity
+ }
+ let fullOpacity = opacity * 3
+ if (fullOpacity > 1) {
+ fullOpacity = 1
+ }
+ let isAttack = this.vIsAttack
+ let bgColor = "#276AC6"
+ if (isAttack) {
+ bgColor = "#B03A5B"
+ }
+ return {
+ name: v.name,
+ value: v.bytes,
+ percent: parseFloat(v.percent),
+ itemStyle: {
+ areaColor: bgColor,
+ opacity: opacity
+ },
+ emphasis: {
+ itemStyle: {
+ areaColor: bgColor,
+ opacity: fullOpacity
+ }
+ }
+ }
+ }),
+ nameMap: window.WorldCountriesMap
+ }]
+ })
+ this.chart.resize()
+ },
+ select: function (countryName) {
+ if (this.chart == null) {
+ return
+ }
+ let option = this.chart.getOption()
+ let that = this
+ option.series[0].data.forEach(function (v) {
+ let opacity = v.percent / that.maxPercent
+ if (opacity < that.minOpacity) {
+ opacity = that.minOpacity
+ }
+
+ if (v.name == countryName) {
+ if (v.isSelected) {
+ v.itemStyle.opacity = opacity
+ v.isSelected = false
+ return
+ }
+ v.isSelected = true
+ opacity *= 3
+ if (opacity > 1) {
+ opacity = 1
+ }
+
+ // 至少是0.5,让用户能够看清
+ if (opacity < 0.5) {
+ opacity = 0.5
+ }
+ v.itemStyle.opacity = opacity
+ } else {
+ v.itemStyle.opacity = opacity
+ v.isSelected = false
+ }
+ })
+ this.chart.setOption(option)
+ }
+ },
+ template: `
+
+
+ |
+
+ |
+
+
+
+
+
+ | 国家/地区排行 |
+
+
+
+
+ | 暂无数据 |
+
+
+
+
+ |
+
+ {{stat.name}}
+ {{stat.percent}}% ({{stat.formattedBytes}})
+ |
+
+
+
+
+ |
+
+
+
`
+})
\ No newline at end of file
diff --git a/web/public/js/components/server/metric-charts.js b/web/public/js/components/server/metric-charts.js
index 6e7354c2..62826bbd 100644
--- a/web/public/js/components/server/metric-charts.js
+++ b/web/public/js/components/server/metric-charts.js
@@ -411,7 +411,7 @@ Vue.component("metric-chart", {
template: `
{{chart.name}} ({{valueTypeName}})
-
+
`
})
diff --git a/web/public/js/world-countries-map.js b/web/public/js/world-countries-map.js
new file mode 100644
index 00000000..ad44582f
--- /dev/null
+++ b/web/public/js/world-countries-map.js
@@ -0,0 +1,191 @@
+window.WorldCountriesMap = {
+ "Afghanistan": "阿富汗",
+ "Albania": "阿尔巴尼亚",
+ "Algeria": "阿尔及利亚",
+ "Angola": "安哥拉",
+ "Argentina": "阿根廷",
+ "Armenia": "亚美尼亚",
+ "Australia": "澳大利亚",
+ "Austria": "奥地利",
+ "Azerbaijan": "阿塞拜疆",
+ "Bahamas": "巴哈马",
+ "Bahrain": "巴林",
+ "Bangladesh": "孟加拉国",
+ "Belarus": "白俄罗斯",
+ "Belgium": "比利时",
+ "Belize": "伯利兹",
+ "Benin": "贝宁",
+ "Bhutan": "不丹",
+ "Bolivia": "玻利维亚",
+ "Bosnia and Herz.": "波斯尼亚和墨塞哥维那",
+ "Botswana": "博茨瓦纳",
+ "Brazil": "巴西",
+ "British Virgin Islands": "英属维尔京群岛",
+ "Brunei": "文莱",
+ "Bulgaria": "保加利亚",
+ "Burkina Faso": "布基纳法索",
+ "Burundi": "布隆迪",
+ "Cambodia": "柬埔寨",
+ "Cameroon": "喀麦隆",
+ "Canada": "加拿大",
+ "Cape Verde": "佛得角",
+ "Cayman Islands": "开曼群岛",
+ "Central African Rep.": "中非共和国",
+ "Chad": "乍得",
+ "Chile": "智利",
+ "China": "中国",
+ "Colombia": "哥伦比亚",
+ "Comoros": "科摩罗",
+ "Congo": "刚果共和国",
+ "Costa Rica": "哥斯达黎加",
+ "Croatia": "克罗地亚",
+ "Cuba": "古巴",
+ "Cyprus": "塞浦路斯",
+ "Czech Rep.": "捷克",
+ "Côte d'Ivoire": "科特迪瓦",
+ "Dem. Rep. Congo": "刚果民主共和国",
+ "Dem. Rep. Korea": "朝鲜",
+ "Denmark": "丹麦",
+ "Djibouti": "吉布提",
+ "Dominican Rep.": "多米尼加共和国",
+ "Ecuador": "厄瓜多尔",
+ "Egypt": "埃及",
+ "El Salvador": "萨尔瓦多",
+ "Equatorial Guinea": "赤道几内亚",
+ "Eritrea": "厄立特里亚",
+ "Estonia": "爱沙尼亚",
+ "Ethiopia": "埃塞俄比亚",
+ "Falkland Is.": "福克兰群岛",
+ "Fiji": "斐济",
+ "Finland": "芬兰",
+ "Fr. S. Antarctic Lands": "所罗门群岛",
+ "France": "法国",
+ "Gabon": "加蓬",
+ "Gambia": "冈比亚",
+ "Georgia": "格鲁吉亚",
+ "Germany": "德国",
+ "Ghana": "加纳",
+ "Greece": "希腊",
+ "Greenland": "格陵兰",
+ "Guatemala": "危地马拉",
+ "Guinea": "几内亚",
+ "Guinea-Bissau": "几内亚比绍",
+ "Guyana": "圭亚那",
+ "Haiti": "海地",
+ "Honduras": "洪都拉斯",
+ "Hungary": "匈牙利",
+ "Iceland": "冰岛",
+ "India": "印度",
+ "Indonesia": "印度尼西亚",
+ "Iran": "伊朗",
+ "Iraq": "伊拉克",
+ "Ireland": "爱尔兰",
+ "Isle of Man": "英属马恩岛",
+ "Israel": "以色列",
+ "Italy": "意大利",
+ "Jamaica": "牙买加",
+ "Japan": "日本",
+ "Jordan": "约旦",
+ "Kazakhstan": "哈萨克斯坦",
+ "Kenya": "肯尼亚",
+ "Korea": "韩国",
+ "Kuwait": "科威特",
+ "Kyrgyzstan": "吉尔吉斯斯坦",
+ "Lao PDR": "老挝",
+ "Latvia": "拉脱维亚",
+ "Lebanon": "黎巴嫩",
+ "Lesotho": "莱索托",
+ "Liberia": "利比里亚",
+ "Libya": "利比亚",
+ "Lithuania": "立陶宛",
+ "Luxembourg": "卢森堡",
+ "Macedonia": "马其顿",
+ "Madagascar": "马达加斯加",
+ "Malawi": "马拉维",
+ "Malaysia": "马来西亚",
+ "Maldives": "马尔代夫",
+ "Mali": "马里",
+ "Malta": "马耳他",
+ "Mauritania": "毛里塔尼亚",
+ "Mauritius": "毛里求斯",
+ "Mexico": "墨西哥",
+ "Moldova": "摩尔多瓦",
+ "Monaco": "摩纳哥",
+ "Mongolia": "蒙古",
+ "Montenegro": "黑山共和国",
+ "Morocco": "摩洛哥",
+ "Mozambique": "莫桑比克",
+ "Myanmar": "缅甸",
+ "Namibia": "纳米比亚",
+ "Nepal": "尼泊尔",
+ "Netherlands": "荷兰",
+ "New Caledonia": "新喀里多尼亚",
+ "New Zealand": "新西兰",
+ "Nicaragua": "尼加拉瓜",
+ "Niger": "尼日尔",
+ "Nigeria": "尼日利亚",
+ "Norway": "挪威",
+ "Oman": "阿曼",
+ "Pakistan": "巴基斯坦",
+ "Panama": "巴拿马",
+ "Papua New Guinea": "巴布亚新几内亚",
+ "Paraguay": "巴拉圭",
+ "Peru": "秘鲁",
+ "Philippines": "菲律宾",
+ "Poland": "波兰",
+ "Portugal": "葡萄牙",
+ "Puerto Rico": "波多黎各",
+ "Qatar": "卡塔尔",
+ "Reunion": "留尼旺",
+ "Romania": "罗马尼亚",
+ "Russia": "俄罗斯",
+ "Rwanda": "卢旺达",
+ "S. Geo. and S. Sandw. Is.": "南乔治亚岛和南桑威奇群岛",
+ "S. Sudan": "南苏丹",
+ "San Marino": "圣马力诺",
+ "Saudi Arabia": "沙特阿拉伯",
+ "Senegal": "塞内加尔",
+ "Serbia": "塞尔维亚",
+ "Sierra Leone": "塞拉利昂",
+ "Singapore": "新加坡",
+ "Slovakia": "斯洛伐克",
+ "Slovenia": "斯洛文尼亚",
+ "Solomon Is.": "所罗门群岛",
+ "Somalia": "索马里",
+ "South Africa": "南非",
+ "Spain": "西班牙",
+ "Sri Lanka": "斯里兰卡",
+ "Sudan": "苏丹",
+ "Suriname": "苏里南",
+ "Swaziland": "斯威士兰",
+ "Sweden": "瑞典",
+ "Switzerland": "瑞士",
+ "Syria": "叙利亚",
+ "Tajikistan": "塔吉克斯坦",
+ "Tanzania": "坦桑尼亚",
+ "Thailand": "泰国",
+ "Togo": "多哥",
+ "Tonga": "汤加",
+ "Trinidad and Tobago": "特立尼达和多巴哥",
+ "Tunisia": "突尼斯",
+ "Turkey": "土耳其",
+ "Turkmenistan": "土库曼斯坦",
+ "U.S. Virgin Islands": "美属维尔京群岛",
+ "Uganda": "乌干达",
+ "Ukraine": "乌克兰",
+ "United Arab Emirates": "阿拉伯联合酋长国",
+ "United Kingdom": "英国",
+ "United States": "美国",
+ "Uruguay": "乌拉圭",
+ "Uzbekistan": "乌兹别克斯坦",
+ "Vanuatu": "瓦努阿图共和国",
+ "Vatican City": "梵蒂冈",
+ "Venezuela": "委内瑞拉",
+ "Vietnam": "越南",
+ "W. Sahara": "西撒哈拉",
+ "Yemen": "也门",
+ "Yugoslavia": "南斯拉夫",
+ "Zaire": "扎伊尔",
+ "Zambia": "赞比亚",
+ "Zimbabwe": "津巴布韦"
+}
\ No newline at end of file
diff --git a/web/views/@default/clusters/cluster/boards/index.css b/web/views/@default/clusters/cluster/boards/index.css
index 32455584..1d37831e 100644
--- a/web/views/@default/clusters/cluster/boards/index.css
+++ b/web/views/@default/clusters/cluster/boards/index.css
@@ -26,7 +26,7 @@
display: inline;
}
.chart-box {
- height: 20em;
+ height: 14em;
}
h4 span {
font-size: 0.8em;
diff --git a/web/views/@default/clusters/cluster/boards/index.less b/web/views/@default/clusters/cluster/boards/index.less
index 8c27d9ce..0e788f91 100644
--- a/web/views/@default/clusters/cluster/boards/index.less
+++ b/web/views/@default/clusters/cluster/boards/index.less
@@ -38,7 +38,7 @@
}
.chart-box {
- height: 20em;
+ height: 14em;
}
h4 {
diff --git a/web/views/@default/clusters/cluster/node/boards/index.css b/web/views/@default/clusters/cluster/node/boards/index.css
index 32455584..1d37831e 100644
--- a/web/views/@default/clusters/cluster/node/boards/index.css
+++ b/web/views/@default/clusters/cluster/node/boards/index.css
@@ -26,7 +26,7 @@
display: inline;
}
.chart-box {
- height: 20em;
+ height: 14em;
}
h4 span {
font-size: 0.8em;
diff --git a/web/views/@default/clusters/cluster/node/boards/index.less b/web/views/@default/clusters/cluster/node/boards/index.less
index 8c27d9ce..0e788f91 100644
--- a/web/views/@default/clusters/cluster/node/boards/index.less
+++ b/web/views/@default/clusters/cluster/node/boards/index.less
@@ -38,7 +38,7 @@
}
.chart-box {
- height: 20em;
+ height: 14em;
}
h4 {
diff --git a/web/views/@default/dashboard/boards/dns.css b/web/views/@default/dashboard/boards/dns.css
index 27ad787d..99af3c69 100644
--- a/web/views/@default/dashboard/boards/dns.css
+++ b/web/views/@default/dashboard/boards/dns.css
@@ -28,6 +28,6 @@
display: inline;
}
.chart-box {
- height: 20em;
+ height: 14em;
}
/*# sourceMappingURL=dns.css.map */
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/dns.less b/web/views/@default/dashboard/boards/dns.less
index fcb67336..0e503413 100644
--- a/web/views/@default/dashboard/boards/dns.less
+++ b/web/views/@default/dashboard/boards/dns.less
@@ -42,5 +42,5 @@
}
.chart-box {
- height: 20em;
+ height: 14em;
}
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/index.css b/web/views/@default/dashboard/boards/index.css
index 5b8adc8c..76a0d662 100644
--- a/web/views/@default/dashboard/boards/index.css
+++ b/web/views/@default/dashboard/boards/index.css
@@ -28,7 +28,13 @@
display: inline;
}
.chart-box {
- height: 20em;
+ height: 14em;
+}
+.traffic-map-box {
+ height: 16em;
+}
+.traffic-map-box div::-webkit-scrollbar {
+ width: 4px;
}
h4 span {
font-size: 0.8em;
diff --git a/web/views/@default/dashboard/boards/index.css.map b/web/views/@default/dashboard/boards/index.css.map
index 7d33dd48..ce6de77e 100644
--- a/web/views/@default/dashboard/boards/index.css.map
+++ b/web/views/@default/dashboard/boards/index.css.map
@@ -1 +1 @@
-{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,GAAG,QACF,EACC,MAAK;EACJ,kBAAA;EACA,UAAA;EACA,QAAA;;AAKH;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;EACC,gBAAA;EACA,WAAA","file":"index.css"}
\ No newline at end of file
+{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA,GAAG,QACF,EACC,MAAK;EACJ,kBAAA;EACA,UAAA;EACA,QAAA;;AAKH;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;EACC,gBAAA;EACA,WAAA","file":"index.css"}
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/index.html b/web/views/@default/dashboard/boards/index.html
index cff3f284..99866c2c 100644
--- a/web/views/@default/dashboard/boards/index.html
+++ b/web/views/@default/dashboard/boards/index.html
@@ -1,5 +1,11 @@
{$layout}
-{$template "/echarts"}
+
+{$var "header"}
+
+
+
+
+{$end}
{$template "menu"}
@@ -111,6 +117,12 @@
+
+
+
+
+
+