diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go
index 8a3bed0b..211d6531 100644
--- a/internal/rpc/rpc_client.go
+++ b/internal/rpc/rpc_client.go
@@ -207,6 +207,10 @@ func (this *RPCClient) HTTPFirewallRuleSetRPC() pb.HTTPFirewallRuleSetServiceCli
return pb.NewHTTPFirewallRuleSetServiceClient(this.pickConn())
}
+func (this *RPCClient) FirewallRPC() pb.FirewallServiceClient {
+ return pb.NewFirewallServiceClient(this.pickConn())
+}
+
func (this *RPCClient) HTTPLocationRPC() pb.HTTPLocationServiceClient {
return pb.NewHTTPLocationServiceClient(this.pickConn())
}
diff --git a/internal/web/actions/default/dashboard/boards/waf.go b/internal/web/actions/default/dashboard/boards/waf.go
index fcf111f9..9e00c9a5 100644
--- a/internal/web/actions/default/dashboard/boards/waf.go
+++ b/internal/web/actions/default/dashboard/boards/waf.go
@@ -5,6 +5,8 @@ package boards
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ "github.com/iwind/TeaGo/maps"
)
type WafAction struct {
@@ -21,5 +23,54 @@ func (this *WafAction) RunGet(params struct{}) {
return
}
+ resp, err := this.RPC().FirewallRPC().ComposeFirewallGlobalBoard(this.AdminContext(), &pb.ComposeFirewallGlobalBoardRequest{})
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Data["board"] = maps.Map{
+ "countDailyLogs": resp.CountDailyLogs,
+ "countDailyBlocks": resp.CountDailyBlocks,
+ "countDailyCaptcha": resp.CountDailyCaptcha,
+ "countWeeklyBlocks": resp.CountWeeklyBlocks,
+ }
+
+ {
+ var statMaps = []maps.Map{}
+ for _, stat := range resp.HourlyStats {
+ statMaps = append(statMaps, maps.Map{
+ "hour": stat.Hour,
+ "countLogs": stat.CountLogs,
+ "countCaptcha": stat.CountCaptcha,
+ "countBlocks": stat.CountBlocks,
+ })
+ }
+ this.Data["hourlyStats"] = statMaps
+ }
+
+ {
+ var statMaps = []maps.Map{}
+ for _, stat := range resp.DailyStats {
+ statMaps = append(statMaps, maps.Map{
+ "day": stat.Day,
+ "countLogs": stat.CountLogs,
+ "countCaptcha": stat.CountCaptcha,
+ "countBlocks": stat.CountBlocks,
+ })
+ }
+ this.Data["dailyStats"] = statMaps
+ }
+
+ {
+ var statMaps = []maps.Map{}
+ for _, stat := range resp.HttpFirewallRuleGroups {
+ statMaps = append(statMaps, maps.Map{
+ "name": stat.HttpFirewallRuleGroup.Name,
+ "count": stat.Count,
+ })
+ }
+ this.Data["groupStats"] = statMaps
+ }
+
this.Show()
}
diff --git a/internal/web/actions/default/dashboard/boards/wafLogs.go b/internal/web/actions/default/dashboard/boards/wafLogs.go
new file mode 100644
index 00000000..fec2cfec
--- /dev/null
+++ b/internal/web/actions/default/dashboard/boards/wafLogs.go
@@ -0,0 +1,28 @@
+// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
+
+package boards
+
+import (
+ "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
+ "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+ timeutil "github.com/iwind/TeaGo/utils/time"
+)
+
+type WafLogsAction struct {
+ actionutils.ParentAction
+}
+
+func (this *WafLogsAction) RunPost(params struct{}) {
+ resp, err := this.RPC().HTTPAccessLogRPC().ListHTTPAccessLogs(this.AdminContext(), &pb.ListHTTPAccessLogsRequest{
+ HasFirewallPolicy: true,
+ Reverse: false,
+ Day: timeutil.Format("Ymd"),
+ Size: 5,
+ })
+ if err != nil {
+ this.ErrorPage(err)
+ return
+ }
+ this.Data["accessLogs"] = resp.HttpAccessLogs
+ this.Success()
+}
diff --git a/internal/web/actions/default/dashboard/init.go b/internal/web/actions/default/dashboard/init.go
index 07ef2959..9321f294 100644
--- a/internal/web/actions/default/dashboard/init.go
+++ b/internal/web/actions/default/dashboard/init.go
@@ -18,6 +18,7 @@ func init() {
Prefix("/dashboard/boards").
Get("", new(boards.IndexAction)).
Get("/waf", new(boards.WafAction)).
+ Post("/wafLogs", new(boards.WafLogsAction)).
Get("/dns", new(boards.DnsAction)).
Get("/user", new(boards.UserAction)).
diff --git a/web/public/js/utils.js b/web/public/js/utils.js
index d73a1b10..1ea25164 100644
--- a/web/public/js/utils.js
+++ b/web/public/js/utils.js
@@ -134,6 +134,24 @@ window.teaweb = {
formatNumber: function (x) {
return x.toString().replace(/\B(?= 1000 * 1000 * 1000) {
+ unit = "B"
+ divider = 1000 * 1000 * 1000
+ } else if (x >= 1000 * 1000) {
+ unit = "M"
+ divider = 1000 * 1000
+ } else if (x >= 1000) {
+ unit = "K"
+ divider = 1000
+ }
+ if (unit.length == 0) {
+ return x.toString()
+ }
+ return (Math.round(x * 100 / divider) / 100) + unit
+ },
bytesAxis: function (stats, countFunc) {
let max = Math.max.apply(this, stats.map(countFunc))
let divider = 1
@@ -362,12 +380,34 @@ window.teaweb = {
},
renderBarChart: function (options) {
let chartId = options.id
+ if (chartId == null || chartId.length == 0) {
+ throw new Error("'options.id' should not be empty")
+ }
+
let name = options.name
let values = options.values
+ if (values == null || !(values instanceof Array)) {
+ throw new Error("'options.values' should be array")
+ }
+
let xFunc = options.x
+ if (typeof (xFunc) != "function") {
+ throw new Error("'options.x' should be a function")
+ }
+
let tooltipFunc = options.tooltip
+ if (typeof(tooltipFunc) != "function") {
+ throw new Error("'options.tooltip' should be a function")
+ }
+
let axis = options.axis
+ if (axis == null) {
+ axis = {unit: "", count: 1}
+ }
let valueFunc = options.value
+ if (typeof (valueFunc) != "function") {
+ throw new Error("'options.value' should be a function")
+ }
let click = options.click
let chartBox = document.getElementById(chartId)
diff --git a/web/views/@default/dashboard/boards/waf.css b/web/views/@default/dashboard/boards/waf.css
index 7a6beaea..896d8fc2 100644
--- a/web/views/@default/dashboard/boards/waf.css
+++ b/web/views/@default/dashboard/boards/waf.css
@@ -30,4 +30,8 @@
.chart-box {
height: 20em;
}
+.color-span {
+ font-size: 0.8em;
+ padding: 4px;
+}
/*# sourceMappingURL=waf.css.map */
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/waf.css.map b/web/views/@default/dashboard/boards/waf.css.map
index e252fba4..a341a494 100644
--- a/web/views/@default/dashboard/boards/waf.css.map
+++ b/web/views/@default/dashboard/boards/waf.css.map
@@ -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","file":"waf.css"}
\ No newline at end of file
+{"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","file":"waf.css"}
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/waf.html b/web/views/@default/dashboard/boards/waf.html
index 6ad5ba32..7ef0a3f1 100644
--- a/web/views/@default/dashboard/boards/waf.html
+++ b/web/views/@default/dashboard/boards/waf.html
@@ -1,3 +1,56 @@
{$layout}
{$template "menu"}
-{$template "/echarts"}
\ No newline at end of file
+{$template "/echarts"}
+
+
+
+
今日拦截
+
{{board.countDailyBlocks}}次
+
+
+
+
今日验证码验证
+
{{board.countDailyCaptcha}}次
+
+
+
+
今日记录
+
{{board.countDailyLogs}}次
+
+
+
+
本周拦截
+
{{board.countWeeklyBlocks}}次
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+拦截类型分布
+
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/waf.js b/web/views/@default/dashboard/boards/waf.js
new file mode 100644
index 00000000..65b81cef
--- /dev/null
+++ b/web/views/@default/dashboard/boards/waf.js
@@ -0,0 +1,166 @@
+Tea.context(function () {
+ this.$delay(function () {
+ let that = this
+
+ this.board.countDailyBlocks = teaweb.formatCount(this.board.countDailyBlocks)
+ this.board.countDailyCaptcha = teaweb.formatCount(this.board.countDailyCaptcha)
+ this.board.countDailyLogs = teaweb.formatCount(this.board.countDailyLogs)
+ this.board.countWeeklyBlocks = teaweb.formatCount(this.board.countWeeklyBlocks)
+
+ this.reloadHourlyChart()
+ this.reloadGroupChart()
+ this.reloadAccessLogs()
+ })
+
+ this.requestsTab = "hourly"
+
+ this.selectRequestsTab = function (tab) {
+ this.requestsTab = tab
+ this.$delay(function () {
+ switch (tab) {
+ case "hourly":
+ this.reloadHourlyChart()
+ break
+ case "daily":
+ this.reloadDailyChart()
+ break
+ }
+ })
+ }
+
+ this.reloadHourlyChart = function () {
+ let axis = teaweb.countAxis(this.hourlyStats, function (v) {
+ return [v.countLogs, v.countCaptcha, v.countBlocks].$max()
+ })
+ let that = this
+ this.reloadLineChart("hourly-chart", "按小时统计", this.hourlyStats, function (v) {
+ return v.hour.substring(8, 10)
+ }, function (args) {
+ let index = args.dataIndex
+ let hour = that.hourlyStats[index].hour.substring(0, 4) + "-" + that.hourlyStats[index].hour.substring(4, 6) + "-" + that.hourlyStats[index].hour.substring(6, 8) + " " + that.hourlyStats[index].hour.substring(8)
+ return hour + "时
拦截: "
+ + teaweb.formatNumber(that.hourlyStats[index].countBlocks) + "
验证码: " + teaweb.formatNumber(that.hourlyStats[index].countCaptcha) + "
记录: " + teaweb.formatNumber(that.hourlyStats[index].countLogs)
+ }, axis)
+ }
+
+ this.reloadDailyChart = function () {
+ let axis = teaweb.countAxis(this.dailyStats, function (v) {
+ return [v.countLogs, v.countCaptcha, v.countBlocks].$max()
+ })
+ let that = this
+ this.reloadLineChart("daily-chart", "按天统计", this.dailyStats, function (v) {
+ return v.day.substring(4, 6) + "月" + v.day.substring(6, 8) + "日"
+ }, function (args) {
+ let index = args.dataIndex
+ let day = that.dailyStats[index].day.substring(0, 4) + "-" + that.dailyStats[index].day.substring(4, 6) + "-" + that.dailyStats[index].day.substring(6, 8)
+ return day + "
拦截: "
+ + teaweb.formatNumber(that.dailyStats[index].countBlocks) + "
验证码: " + teaweb.formatNumber(that.dailyStats[index].countCaptcha) + "
记录: " + teaweb.formatNumber(that.dailyStats[index].countLogs)
+ }, axis)
+ }
+
+ this.reloadLineChart = function (chartId, name, stats, xFunc, tooltipFunc, axis) {
+ let chartBox = document.getElementById(chartId)
+ if (chartBox == null) {
+ return
+ }
+ let chart = echarts.init(chartBox)
+ let option = {
+ xAxis: {
+ data: stats.map(xFunc)
+ },
+ yAxis: {
+ axisLabel: {
+ formatter: function (value) {
+ return value + axis.unit
+ }
+ }
+ },
+ tooltip: {
+ show: true,
+ trigger: "item",
+ formatter: tooltipFunc
+ },
+ grid: {
+ left: 42,
+ top: 10,
+ right: 20,
+ bottom: 20
+ },
+ series: [
+ {
+ name: name,
+ type: "line",
+ data: stats.map(function (v) {
+ return v.countLogs / axis.divider;
+ }),
+ itemStyle: {
+ color: "#879BD7"
+ },
+ areaStyle: {},
+ stack: "总量"
+ },
+ {
+ name: name,
+ type: "line",
+ data: stats.map(function (v) {
+ return v.countCaptcha / axis.divider;
+ }),
+ itemStyle: {
+ color: "#FBD88A"
+ },
+ areaStyle: {},
+ stack: "总量"
+ },
+ {
+ name: name,
+ type: "line",
+ data: stats.map(function (v) {
+ return v.countBlocks / axis.divider;
+ }),
+ itemStyle: {
+ color: "#F39494"
+ },
+ areaStyle: {},
+ stack: "总量"
+ }
+ ],
+ animation: true
+ }
+ chart.setOption(option)
+ chart.resize()
+ }
+
+ this.reloadGroupChart = function () {
+ let axis = teaweb.countAxis(this.groupStats, function (v) {
+ return v.count
+ })
+ teaweb.renderBarChart({
+ id: "group-chart",
+ values: this.groupStats,
+ x: function (v) {
+ return v.name
+ },
+ value: function (v) {
+ return v.count / axis.divider
+ },
+ tooltip: function (args, stats) {
+ let index = args.dataIndex
+ return stats[index].name + ": " + stats[index].count
+ },
+ axis: axis
+ })
+ }
+
+ this.accessLogs = []
+ this.reloadAccessLogs = function () {
+ this.$post(".wafLogs")
+ .success(function (resp) {
+ if (resp.data.accessLogs != null) {
+ this.accessLogs = resp.data.accessLogs
+ }
+ })
+ .done(function () {
+ this.$delay(this.reloadAccessLogs, 10000)
+ })
+ }
+})
\ No newline at end of file
diff --git a/web/views/@default/dashboard/boards/waf.less b/web/views/@default/dashboard/boards/waf.less
index fcb67336..f5151713 100644
--- a/web/views/@default/dashboard/boards/waf.less
+++ b/web/views/@default/dashboard/boards/waf.less
@@ -43,4 +43,9 @@
.chart-box {
height: 20em;
+}
+
+.color-span {
+ font-size: 0.8em;
+ padding: 4px;
}
\ No newline at end of file
diff --git a/web/views/@default/servers/server/stat/waf.js b/web/views/@default/servers/server/stat/waf.js
index 63e374e1..0bcf3508 100644
--- a/web/views/@default/servers/server/stat/waf.js
+++ b/web/views/@default/servers/server/stat/waf.js
@@ -1,198 +1,182 @@
Tea.context(function () {
- this.$delay(function () {
- let that = this
+ this.$delay(function () {
+ let that = this
- this.totalDailyStats = this.logDailyStats.map(function (v, k) {
- return {
- day: v.day,
- count: that.logDailyStats[k].count + that.blockDailyStats[k].count + that.captchaDailyStats[k].count
- }
- })
- let dailyUnit = this.processMaxUnit(this.totalDailyStats)
- this.reloadLineChart("daily-chart", "规则分组", this.totalDailyStats, function (v) {
- return v.day.substring(4, 6) + "-" + v.day.substring(6)
- }, function (args) {
+ this.countDailyBlock = teaweb.formatCount(this.countDailyBlock)
+ this.countDailyCaptcha = teaweb.formatCount(this.countDailyCaptcha)
+ this.countDailyLog = teaweb.formatCount(this.countDailyLog)
+ this.countWeeklyBlock = teaweb.formatCount(this.countWeeklyBlock)
+ this.countMonthlyBlock = teaweb.formatCount(this.countMonthlyBlock)
- return that.logDailyStats[args.dataIndex].day.substring(4, 6) + "-" + that.logDailyStats[args.dataIndex].day.substring(6) + ": 拦截: "
- + teaweb.formatNumber(that.blockDailyStats[args.dataIndex].count) + ", 验证码: " + teaweb.formatNumber(that.captchaDailyStats[args.dataIndex].count) + ", 记录: " + teaweb.formatNumber(that.logDailyStats[args.dataIndex].count)
- }, dailyUnit)
+ this.totalDailyStats = this.logDailyStats.map(function (v, k) {
+ return {
+ day: v.day,
+ count: that.logDailyStats[k].count + that.blockDailyStats[k].count + that.captchaDailyStats[k].count
+ }
+ })
+ let dailyAxis = teaweb.countAxis(this.totalDailyStats, function (v) {
+ return v.count
+ })
+ this.reloadLineChart("daily-chart", "规则分组", this.totalDailyStats, function (v) {
+ return v.day.substring(4, 6) + "-" + v.day.substring(6)
+ }, function (args) {
+ return that.logDailyStats[args.dataIndex].day.substring(4, 6) + "-" + that.logDailyStats[args.dataIndex].day.substring(6) + ": 拦截: "
+ + teaweb.formatNumber(that.blockDailyStats[args.dataIndex].count) + ", 验证码: " + teaweb.formatNumber(that.captchaDailyStats[args.dataIndex].count) + ", 记录: " + teaweb.formatNumber(that.logDailyStats[args.dataIndex].count)
+ }, dailyAxis)
- let groupUnit = this.processMaxUnit(this.groupStats)
- let total = this.groupStats.$sum(function (k, v) {
- return v.rawCount
- })
- this.reloadBarChart("group-chart", "规则分组", this.groupStats, function (v) {
- return v.group.name
- }, function (args) {
- let percent = ""
- if (total > 0) {
- percent = ", 占比: " + (Math.round(that.groupStats[args.dataIndex].rawCount * 100 * 100 / total) / 100) + "%"
- }
- return that.groupStats[args.dataIndex].group.name + ": " + teaweb.formatNumber(that.groupStats[args.dataIndex].rawCount) + percent
- }, groupUnit)
+ let groupAxis = teaweb.countAxis(this.groupStats, function (v) {
+ return v.count
+ })
+ let total = this.groupStats.$sum(function (k, v) {
+ return v.count
+ })
+ this.reloadBarChart("group-chart", "规则分组", this.groupStats, function (v) {
+ return v.group.name
+ }, function (args) {
+ let percent = ""
+ if (total > 0) {
+ percent = ", 占比: " + (Math.round(that.groupStats[args.dataIndex].count * 100 * 100 / total) / 100) + "%"
+ }
+ return that.groupStats[args.dataIndex].group.name + ": " + teaweb.formatNumber(that.groupStats[args.dataIndex].count) + percent
+ }, groupAxis)
- window.addEventListener("resize", function () {
- that.resizeChart("daily-chart")
- that.resizeChart("group-chart")
- })
- })
+ window.addEventListener("resize", function () {
+ that.resizeChart("daily-chart")
+ that.resizeChart("group-chart")
+ })
+ })
- this.reloadLineChart = function (chartId, name, stats, xFunc, tooltipFunc, unit) {
- let chartBox = document.getElementById(chartId)
- if (chartBox == null) {
- return
- }
- let that = this
- let chart = echarts.init(chartBox)
- let option = {
- xAxis: {
- data: stats.map(xFunc)
- },
- yAxis: {
- axisLabel: {
- formatter: function (value) {
- return value + unit
- }
- }
- },
- tooltip: {
- show: true,
- trigger: "item",
- formatter: tooltipFunc
- },
- grid: {
- left: 40,
- top: 10,
- right: 20,
- bottom: 20
- },
- series: [
- {
- name: name,
- type: "line",
- data: this.totalDailyStats.map(function (v, index) {
- return that.totalDailyStats[index].count;
- }),
- areaStyle: {},
- itemStyle: {
- color: "#9DD3E8"
- }
- },
- {
- name: name,
- type: "line",
- data: this.logDailyStats.map(function (v) {
- return v.count;
- }),
- itemStyle: {
- color: "#879BD7"
- }
- },
- {
- name: name,
- type: "line",
- data: this.blockDailyStats.map(function (v) {
- return v.count;
- }),
- itemStyle: {
- color: "#F39494"
- }
- },
- {
- name: name,
- type: "line",
- data: this.captchaDailyStats.map(function (v) {
- return v.count;
- }),
- itemStyle: {
- color: "#FBD88A"
- }
- }
- ],
- animation: true
- }
- chart.setOption(option)
- chart.resize()
- }
+ this.reloadLineChart = function (chartId, name, stats, xFunc, tooltipFunc, axis) {
+ let chartBox = document.getElementById(chartId)
+ if (chartBox == null) {
+ return
+ }
+ let that = this
+ let chart = echarts.init(chartBox)
+ let option = {
+ xAxis: {
+ data: stats.map(xFunc)
+ },
+ yAxis: {
+ axisLabel: {
+ formatter: function (value) {
+ return value + axis.unit
+ }
+ }
+ },
+ tooltip: {
+ show: true,
+ trigger: "item",
+ formatter: tooltipFunc
+ },
+ grid: {
+ left: 40,
+ top: 10,
+ right: 20,
+ bottom: 20
+ },
+ series: [
+ {
+ name: name,
+ type: "line",
+ data: this.totalDailyStats.map(function (v, index) {
+ return that.totalDailyStats[index].count / axis.divider;
+ }),
+ areaStyle: {},
+ itemStyle: {
+ color: "#9DD3E8"
+ }
+ },
+ {
+ name: name,
+ type: "line",
+ data: this.logDailyStats.map(function (v) {
+ return v.count / axis.divider;
+ }),
+ itemStyle: {
+ color: "#879BD7"
+ }
+ },
+ {
+ name: name,
+ type: "line",
+ data: this.blockDailyStats.map(function (v) {
+ return v.count / axis.divider;
+ }),
+ itemStyle: {
+ color: "#F39494"
+ }
+ },
+ {
+ name: name,
+ type: "line",
+ data: this.captchaDailyStats.map(function (v) {
+ return v.count / axis.divider;
+ }),
+ itemStyle: {
+ color: "#FBD88A"
+ }
+ }
+ ],
+ animation: true
+ }
+ chart.setOption(option)
+ chart.resize()
+ }
- this.reloadBarChart = function (chartId, name, stats, xFunc, tooltipFunc, unit) {
- let chartBox = document.getElementById(chartId)
- if (chartBox == null) {
- return
- }
- let chart = echarts.init(chartBox)
- let option = {
- xAxis: {
- data: stats.map(xFunc)
- },
- yAxis: {
- axisLabel: {
- formatter: function (value) {
- return value + unit
- }
- }
- },
- tooltip: {
- show: true,
- trigger: "item",
- formatter: tooltipFunc
- },
- grid: {
- left: 40,
- top: 10,
- right: 20,
- bottom: 20
- },
- series: [
- {
- name: name,
- type: "bar",
- data: stats.map(function (v) {
- return v.count;
- }),
- itemStyle: {
- color: "#9DD3E8"
- },
- barWidth: "20em"
- }
- ],
- animation: true
- }
- chart.setOption(option)
- chart.resize()
- }
+ this.reloadBarChart = function (chartId, name, stats, xFunc, tooltipFunc, axis) {
+ let chartBox = document.getElementById(chartId)
+ if (chartBox == null) {
+ return
+ }
+ let chart = echarts.init(chartBox)
+ let option = {
+ xAxis: {
+ data: stats.map(xFunc)
+ },
+ yAxis: {
+ axisLabel: {
+ formatter: function (value) {
+ return value + axis.unit
+ }
+ }
+ },
+ tooltip: {
+ show: true,
+ trigger: "item",
+ formatter: tooltipFunc
+ },
+ grid: {
+ left: 40,
+ top: 10,
+ right: 20,
+ bottom: 20
+ },
+ series: [
+ {
+ name: name,
+ type: "bar",
+ data: stats.map(function (v) {
+ return v.count / axis.divider;
+ }),
+ itemStyle: {
+ color: "#9DD3E8"
+ },
+ barWidth: "20em"
+ }
+ ],
+ animation: true
+ }
+ chart.setOption(option)
+ chart.resize()
+ }
- this.resizeChart = function (chartId) {
- let chartBox = document.getElementById(chartId)
- if (chartBox == null) {
- return
- }
- let chart = echarts.init(chartBox)
- chart.resize()
- }
-
- this.processMaxUnit = function (stats) {
- let max = stats.$map(function (k, v) {
- return v.count
- }).$max()
- let divider = 0
- let unit = ""
- if (max >= 1000 * 1000 * 1000) {
- unit = "B"
- divider = 1000 * 1000 * 1000
- } else if (max >= 1000 * 1000) {
- unit = "M"
- divider = 1000 * 1000
- } else if (max >= 1000) {
- unit = "K"
- divider = 1000
- }
- stats.forEach(function (v) {
- v.rawCount = v.count
- if (divider > 0) {
- v.count /= divider
- }
- })
- return unit
- }
+ this.resizeChart = function (chartId) {
+ let chartBox = document.getElementById(chartId)
+ if (chartBox == null) {
+ return
+ }
+ let chart = echarts.init(chartBox)
+ chart.resize()
+ }
})
\ No newline at end of file