mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	对服务增加基础的数据统计
This commit is contained in:
		@@ -14,3 +14,6 @@
 | 
			
		||||
 | 
			
		||||
## 联系我们
 | 
			
		||||
有什么问题和建议都可以加入QQ群 `659832182`。
 | 
			
		||||
 | 
			
		||||
## 感谢
 | 
			
		||||
* 感谢[JetBrains公司](https://www.jetbrains.com/)提供免费的IDE开发Licence。
 | 
			
		||||
@@ -91,6 +91,30 @@ func (this *RPCClient) ServerRPC() pb.ServerServiceClient {
 | 
			
		||||
	return pb.NewServerServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerClientSystemMonthlyStatRPC() pb.ServerClientSystemMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerClientSystemMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerClientBrowserMonthlyStatRPC() pb.ServerClientBrowserMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerClientBrowserMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerRegionCountryMonthlyStatRPC() pb.ServerRegionCountryMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerRegionCountryMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerRegionProvinceMonthlyStatRPC() pb.ServerRegionProvinceMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerRegionProvinceMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerRegionCityMonthlyStatRPC() pb.ServerRegionCityMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerRegionCityMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerRegionProviderMonthlyStatRPC() pb.ServerRegionProviderMonthlyStatServiceClient {
 | 
			
		||||
	return pb.NewServerRegionProviderMonthlyStatServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *RPCClient) ServerGroupRPC() pb.ServerGroupServiceClient {
 | 
			
		||||
	return pb.NewServerGroupServiceClient(this.pickConn())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -70,10 +70,10 @@ func (this *UpdateSchedulingPopupAction) RunGet(params struct {
 | 
			
		||||
		if !types.IsSlice(networks) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if (serverConfig.IsHTTP() && lists.Contains(networks, "http")) ||
 | 
			
		||||
			(serverConfig.IsTCP() && lists.Contains(networks, "tcp")) ||
 | 
			
		||||
			(serverConfig.IsUDP() && lists.Contains(networks, "udp")) ||
 | 
			
		||||
			(serverConfig.IsUnix() && lists.Contains(networks, "unix")) {
 | 
			
		||||
		if (serverConfig.IsHTTPFamily() && lists.Contains(networks, "http")) ||
 | 
			
		||||
			(serverConfig.IsTCPFamily() && lists.Contains(networks, "tcp")) ||
 | 
			
		||||
			(serverConfig.IsUDPFamily() && lists.Contains(networks, "udp")) ||
 | 
			
		||||
			(serverConfig.IsUnixFamily() && lists.Contains(networks, "unix")) {
 | 
			
		||||
			schedulingTypes = append(schedulingTypes, m)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								internal/web/actions/default/servers/server/stat/clients.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								internal/web/actions/default/servers/server/stat/clients.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
package stat
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	timeutil "github.com/iwind/TeaGo/utils/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ClientsAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ClientsAction) Init() {
 | 
			
		||||
	this.Nav("", "stat", "")
 | 
			
		||||
	this.SecondMenu("client")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ClientsAction) RunGet(params struct {
 | 
			
		||||
	ServerId int64
 | 
			
		||||
	Month    string
 | 
			
		||||
}) {
 | 
			
		||||
	month := params.Month
 | 
			
		||||
	if len(month) != 6 {
 | 
			
		||||
		month = timeutil.Format("Ym")
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["month"] = month
 | 
			
		||||
 | 
			
		||||
	serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	serverType := serverTypeResp.Type
 | 
			
		||||
 | 
			
		||||
	statIsOn := false
 | 
			
		||||
 | 
			
		||||
	// 是否已开启
 | 
			
		||||
	if serverconfigs.IsHTTPServerType(serverType) {
 | 
			
		||||
		webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if webConfig != nil && webConfig.StatRef != nil {
 | 
			
		||||
			statIsOn = webConfig.StatRef.IsOn
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		this.WriteString("此类型服务暂不支持统计")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["statIsOn"] = statIsOn
 | 
			
		||||
 | 
			
		||||
	// 统计数据
 | 
			
		||||
	systemMaps := []maps.Map{}
 | 
			
		||||
	browserMaps := []maps.Map{}
 | 
			
		||||
 | 
			
		||||
	if statIsOn {
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerClientSystemMonthlyStatRPC().FindTopServerClientSystemMonthlyStats(this.AdminContext(), &pb.FindTopServerClientSystemMonthlyStatsRequest{
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				systemMaps = append(systemMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"system": maps.Map{
 | 
			
		||||
						"id":   stat.ClientSystem.Id,
 | 
			
		||||
						"name": stat.ClientSystem.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerClientBrowserMonthlyStatRPC().FindTopServerClientBrowserMonthlyStats(this.AdminContext(), &pb.FindTopServerClientBrowserMonthlyStatsRequest{
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				browserMaps = append(browserMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"browser": maps.Map{
 | 
			
		||||
						"id":   stat.ClientBrowser.Id,
 | 
			
		||||
						"name": stat.ClientBrowser.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["systemStats"] = systemMaps
 | 
			
		||||
	this.Data["browserStats"] = browserMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,13 @@
 | 
			
		||||
package stat
 | 
			
		||||
 | 
			
		||||
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	timeutil "github.com/iwind/TeaGo/utils/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type IndexAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
@@ -11,6 +18,133 @@ func (this *IndexAction) Init() {
 | 
			
		||||
	this.SecondMenu("index")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunGet(params struct{}) {
 | 
			
		||||
func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
	ServerId int64
 | 
			
		||||
	Month    string
 | 
			
		||||
}) {
 | 
			
		||||
	month := params.Month
 | 
			
		||||
	if len(month) != 6 {
 | 
			
		||||
		month = timeutil.Format("Ym")
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["month"] = month
 | 
			
		||||
 | 
			
		||||
	serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	serverType := serverTypeResp.Type
 | 
			
		||||
 | 
			
		||||
	statIsOn := false
 | 
			
		||||
 | 
			
		||||
	// 是否已开启
 | 
			
		||||
	if serverconfigs.IsHTTPServerType(serverType) {
 | 
			
		||||
		webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if webConfig != nil && webConfig.StatRef != nil {
 | 
			
		||||
			statIsOn = webConfig.StatRef.IsOn
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		this.WriteString("此类型服务暂不支持统计")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["statIsOn"] = statIsOn
 | 
			
		||||
 | 
			
		||||
	// 统计数据
 | 
			
		||||
	countryStatMaps := []maps.Map{}
 | 
			
		||||
	provinceStatMaps := []maps.Map{}
 | 
			
		||||
	cityStatMaps := []maps.Map{}
 | 
			
		||||
 | 
			
		||||
	if statIsOn {
 | 
			
		||||
		// 地区
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerRegionCountryMonthlyStatRPC().FindTopServerRegionCountryMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionCountryMonthlyStatsRequest{
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				countryStatMaps = append(countryStatMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"country": maps.Map{
 | 
			
		||||
						"id":   stat.RegionCountry.Id,
 | 
			
		||||
						"name": stat.RegionCountry.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 省份
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerRegionProvinceMonthlyStatRPC().FindTopServerRegionProvinceMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionProvinceMonthlyStatsRequest{
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				provinceStatMaps = append(provinceStatMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"country": maps.Map{
 | 
			
		||||
						"id":   stat.RegionCountry.Id,
 | 
			
		||||
						"name": stat.RegionCountry.Name,
 | 
			
		||||
					},
 | 
			
		||||
					"province": maps.Map{
 | 
			
		||||
						"id":   stat.RegionProvince.Id,
 | 
			
		||||
						"name": stat.RegionProvince.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// 城市
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerRegionCityMonthlyStatRPC().FindTopServerRegionCityMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionCityMonthlyStatsRequest{
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				cityStatMaps = append(cityStatMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"country": maps.Map{
 | 
			
		||||
						"id":   stat.RegionCountry.Id,
 | 
			
		||||
						"name": stat.RegionCountry.Name,
 | 
			
		||||
					},
 | 
			
		||||
					"province": maps.Map{
 | 
			
		||||
						"id":   stat.RegionProvince.Id,
 | 
			
		||||
						"name": stat.RegionProvince.Name,
 | 
			
		||||
					},
 | 
			
		||||
					"city": maps.Map{
 | 
			
		||||
						"id":   stat.RegionCity.Id,
 | 
			
		||||
						"name": stat.RegionCity.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["countryStats"] = countryStatMaps
 | 
			
		||||
	this.Data["provinceStats"] = provinceStatMaps
 | 
			
		||||
	this.Data["cityStats"] = cityStatMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@ func init() {
 | 
			
		||||
			Helper(serverutils.NewServerHelper()).
 | 
			
		||||
			Prefix("/servers/server/stat").
 | 
			
		||||
			Get("", new(IndexAction)).
 | 
			
		||||
			Get("/providers", new(ProvidersAction)).
 | 
			
		||||
			Get("/clients", new(ClientsAction)).
 | 
			
		||||
			EndAll()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,86 @@
 | 
			
		||||
package stat
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	timeutil "github.com/iwind/TeaGo/utils/time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ProvidersAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ProvidersAction) Init() {
 | 
			
		||||
	this.Nav("", "stat", "")
 | 
			
		||||
	this.SecondMenu("provider")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *ProvidersAction) RunGet(params struct {
 | 
			
		||||
	ServerId int64
 | 
			
		||||
	Month    string
 | 
			
		||||
}) {
 | 
			
		||||
	month := params.Month
 | 
			
		||||
	if len(month) != 6 {
 | 
			
		||||
		month = timeutil.Format("Ym")
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["month"] = month
 | 
			
		||||
 | 
			
		||||
	serverTypeResp, err := this.RPC().ServerRPC().FindEnabledServerType(this.AdminContext(), &pb.FindEnabledServerTypeRequest{ServerId: params.ServerId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	serverType := serverTypeResp.Type
 | 
			
		||||
 | 
			
		||||
	statIsOn := false
 | 
			
		||||
 | 
			
		||||
	// 是否已开启
 | 
			
		||||
	if serverconfigs.IsHTTPServerType(serverType) {
 | 
			
		||||
		webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			this.ErrorPage(err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if webConfig != nil && webConfig.StatRef != nil {
 | 
			
		||||
			statIsOn = webConfig.StatRef.IsOn
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		this.WriteString("此类型服务暂不支持统计")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["statIsOn"] = statIsOn
 | 
			
		||||
 | 
			
		||||
	// 统计数据
 | 
			
		||||
	providerMaps := []maps.Map{}
 | 
			
		||||
 | 
			
		||||
	if statIsOn {
 | 
			
		||||
		{
 | 
			
		||||
			resp, err := this.RPC().ServerRegionProviderMonthlyStatRPC().FindTopServerRegionProviderMonthlyStats(this.AdminContext(), &pb.FindTopServerRegionProviderMonthlyStatsRequest{
 | 
			
		||||
				Month:    month,
 | 
			
		||||
				ServerId: params.ServerId,
 | 
			
		||||
				Offset:   0,
 | 
			
		||||
				Size:     10,
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				this.ErrorPage(err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			for _, stat := range resp.Stats {
 | 
			
		||||
				providerMaps = append(providerMaps, maps.Map{
 | 
			
		||||
					"count": stat.Count,
 | 
			
		||||
					"provider": maps.Map{
 | 
			
		||||
						"id":   stat.RegionProvider.Id,
 | 
			
		||||
						"name": stat.RegionProvider.Name,
 | 
			
		||||
					},
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["providerStats"] = providerMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
@@ -77,13 +77,13 @@ func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
 | 
			
		||||
 | 
			
		||||
	// 协议簇
 | 
			
		||||
	family := ""
 | 
			
		||||
	if serverConfig.IsHTTP() {
 | 
			
		||||
	if serverConfig.IsHTTPFamily() {
 | 
			
		||||
		family = "http"
 | 
			
		||||
	} else if serverConfig.IsTCP() {
 | 
			
		||||
	} else if serverConfig.IsTCPFamily() {
 | 
			
		||||
		family = "tcp"
 | 
			
		||||
	} else if serverConfig.IsUnix() {
 | 
			
		||||
	} else if serverConfig.IsUnixFamily() {
 | 
			
		||||
		family = "unix"
 | 
			
		||||
	} else if serverConfig.IsUDP() {
 | 
			
		||||
	} else if serverConfig.IsUDPFamily() {
 | 
			
		||||
		family = "udp"
 | 
			
		||||
	}
 | 
			
		||||
	action.Data["serverFamily"] = family
 | 
			
		||||
@@ -94,7 +94,9 @@ func (this *ServerHelper) createLeftMenu(action *actions.ActionObject) {
 | 
			
		||||
	tabbar.Add("服务列表", "", "/servers", "", false)
 | 
			
		||||
	//tabbar.Add("看板", "", "/servers/server/board?serverId="+serverIdString, "dashboard", selectedTabbar == "board")
 | 
			
		||||
	tabbar.Add("日志", "", "/servers/server/log?serverId="+serverIdString, "history", selectedTabbar == "log")
 | 
			
		||||
	//tabbar.Add("统计", "", "/servers/server/stat?serverId="+serverIdString, "chart area", selectedTabbar == "stat")
 | 
			
		||||
	if family == "http" {
 | 
			
		||||
		tabbar.Add("统计", "", "/servers/server/stat?serverId="+serverIdString, "chart area", selectedTabbar == "stat")
 | 
			
		||||
	}
 | 
			
		||||
	tabbar.Add("设置", "", "/servers/server/settings?serverId="+serverIdString, "setting", selectedTabbar == "setting")
 | 
			
		||||
	tabbar.Add("删除", "", "/servers/server/delete?serverId="+serverIdString, "trash", selectedTabbar == "delete")
 | 
			
		||||
	{
 | 
			
		||||
@@ -155,10 +157,20 @@ func (this *ServerHelper) createLogMenu(secondMenuItem string, serverIdString st
 | 
			
		||||
func (this *ServerHelper) createStatMenu(secondMenuItem string, serverIdString string, serverConfig *serverconfigs.ServerConfig) []maps.Map {
 | 
			
		||||
	menuItems := []maps.Map{}
 | 
			
		||||
	menuItems = append(menuItems, maps.Map{
 | 
			
		||||
		"name":     "统计",
 | 
			
		||||
		"name":     "地域分布",
 | 
			
		||||
		"url":      "/servers/server/stat?serverId=" + serverIdString,
 | 
			
		||||
		"isActive": secondMenuItem == "index",
 | 
			
		||||
	})
 | 
			
		||||
	menuItems = append(menuItems, maps.Map{
 | 
			
		||||
		"name":     "运营商",
 | 
			
		||||
		"url":      "/servers/server/stat/providers?serverId=" + serverIdString,
 | 
			
		||||
		"isActive": secondMenuItem == "provider",
 | 
			
		||||
	})
 | 
			
		||||
	menuItems = append(menuItems, maps.Map{
 | 
			
		||||
		"name":     "终端",
 | 
			
		||||
		"url":      "/servers/server/stat/clients?serverId=" + serverIdString,
 | 
			
		||||
		"isActive": secondMenuItem == "client",
 | 
			
		||||
	})
 | 
			
		||||
	return menuItems
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -179,7 +191,7 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// HTTP
 | 
			
		||||
	if serverConfig.IsHTTP() {
 | 
			
		||||
	if serverConfig.IsHTTPFamily() {
 | 
			
		||||
		menuItems = append(menuItems, maps.Map{
 | 
			
		||||
			"name":     "域名",
 | 
			
		||||
			"url":      "/servers/server/settings/serverNames?serverId=" + serverIdString,
 | 
			
		||||
@@ -294,7 +306,7 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
			
		||||
			"isActive": secondMenuItem == "websocket",
 | 
			
		||||
			"isOn":     serverConfig.Web != nil && serverConfig.Web.WebsocketRef != nil && serverConfig.Web.WebsocketRef.IsOn,
 | 
			
		||||
		})
 | 
			
		||||
	} else if serverConfig.IsTCP() {
 | 
			
		||||
	} else if serverConfig.IsTCPFamily() {
 | 
			
		||||
		menuItems = append(menuItems, maps.Map{
 | 
			
		||||
			"name":     "TCP",
 | 
			
		||||
			"url":      "/servers/server/settings/tcp?serverId=" + serverIdString,
 | 
			
		||||
@@ -313,14 +325,14 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
			
		||||
			"isActive": secondMenuItem == "reverseProxy",
 | 
			
		||||
			"isOn":     serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
 | 
			
		||||
		})
 | 
			
		||||
	} else if serverConfig.IsUnix() {
 | 
			
		||||
	} else if serverConfig.IsUnixFamily() {
 | 
			
		||||
		menuItems = append(menuItems, maps.Map{
 | 
			
		||||
			"name":     "Unix",
 | 
			
		||||
			"url":      "/servers/server/settings/unix?serverId=" + serverIdString,
 | 
			
		||||
			"isActive": secondMenuItem == "unix",
 | 
			
		||||
			"isOn":     serverConfig.Unix != nil && serverConfig.Unix.IsOn && len(serverConfig.Unix.Listen) > 0,
 | 
			
		||||
		})
 | 
			
		||||
	} else if serverConfig.IsUDP() {
 | 
			
		||||
	} else if serverConfig.IsUDPFamily() {
 | 
			
		||||
		menuItems = append(menuItems, maps.Map{
 | 
			
		||||
			"name":     "UDP",
 | 
			
		||||
			"url":      "/servers/server/settings/udp?serverId=" + serverIdString,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ Vue.component("http-stat-config-box", {
 | 
			
		||||
		if (stat == null) {
 | 
			
		||||
			stat = {
 | 
			
		||||
				isPrior: false,
 | 
			
		||||
				isOn: true
 | 
			
		||||
				isOn: false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ Vue.component("http-websocket-box", {
 | 
			
		||||
		if (websocketConfig == null) {
 | 
			
		||||
			websocketConfig = {
 | 
			
		||||
				id: 0,
 | 
			
		||||
				isOn: true,
 | 
			
		||||
				isOn: false,
 | 
			
		||||
				handshakeTimeout: {
 | 
			
		||||
					count: 30,
 | 
			
		||||
					unit: "second"
 | 
			
		||||
 
 | 
			
		||||
@@ -88,7 +88,9 @@ window.teaweb = {
 | 
			
		||||
        }
 | 
			
		||||
        return (Math.ceil(bytes * 100 / 1024 / 1024) / 100) + " m";
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    formatNumber: function (x) {
 | 
			
		||||
        return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ", ");
 | 
			
		||||
    },
 | 
			
		||||
    popup: function (url, options) {
 | 
			
		||||
        if (options == null) {
 | 
			
		||||
            options = {};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{$var "header"}
 | 
			
		||||
<!-- echart -->
 | 
			
		||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								web/views/@default/servers/server/stat/clients.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/views/@default/servers/server/stat/clients.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=clients.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								web/views/@default/servers/server/stat/clients.css.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								web/views/@default/servers/server/stat/clients.css.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{"version":3,"sources":["clients.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"clients.css"}
 | 
			
		||||
							
								
								
									
										21
									
								
								web/views/@default/servers/server/stat/clients.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								web/views/@default/servers/server/stat/clients.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
 | 
			
		||||
{$var "header"}
 | 
			
		||||
<!-- echart -->
 | 
			
		||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
 | 
			
		||||
{$end}
 | 
			
		||||
 | 
			
		||||
{$template "/left_menu"}
 | 
			
		||||
<div class="right-box">
 | 
			
		||||
    {$ if eq .statIsOn false}
 | 
			
		||||
	<p class="ui message">
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
    <h4>操作系统排行</h4>
 | 
			
		||||
    <div class="chart-box" id="system-chart"></div>
 | 
			
		||||
 | 
			
		||||
    <h4>浏览器排行</h4>
 | 
			
		||||
    <div class="chart-box" id="browser-chart"></div>
 | 
			
		||||
    {$end}
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										108
									
								
								web/views/@default/servers/server/stat/clients.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								web/views/@default/servers/server/stat/clients.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
    this.$delay(function () {
 | 
			
		||||
        let that = this
 | 
			
		||||
 | 
			
		||||
        let systemUnit = this.processMaxUnit(this.systemStats)
 | 
			
		||||
        this.reloadChart("system-chart", "操作系统", this.systemStats, function (v) {
 | 
			
		||||
            return v.system.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.systemStats[args.dataIndex].system.name + ": " + teaweb.formatNumber(that.systemStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, systemUnit)
 | 
			
		||||
        window.addEventListener("resize", function () {
 | 
			
		||||
            that.resizeChart("system-chart")
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        let browserUnit = this.processMaxUnit(this.browserStats)
 | 
			
		||||
        this.reloadChart("browser-chart", "浏览器", this.browserStats, function (v) {
 | 
			
		||||
            return v.browser.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.browserStats[args.dataIndex].browser.name + ": " + teaweb.formatNumber(that.browserStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, browserUnit)
 | 
			
		||||
 | 
			
		||||
        window.addEventListener("resize", function () {
 | 
			
		||||
            that.resizeChart("system-chart")
 | 
			
		||||
            that.resizeChart("browser-chart")
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    this.reloadChart = 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.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
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										3
									
								
								web/views/@default/servers/server/stat/clients.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								web/views/@default/servers/server/stat/clients.less
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=index.css.map */
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
undefined
 | 
			
		||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"index.css"}
 | 
			
		||||
@@ -1,6 +1,30 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
 | 
			
		||||
{$var "header"}
 | 
			
		||||
<!-- echart -->
 | 
			
		||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
 | 
			
		||||
{$end}
 | 
			
		||||
 | 
			
		||||
{$template "/left_menu"}
 | 
			
		||||
<div class="right-box">
 | 
			
		||||
	<div class="ui message">此功能暂未开放,敬请期待。</div>
 | 
			
		||||
    {$ if eq .statIsOn false}
 | 
			
		||||
	<p class="ui message">
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
        <h4>地区排行</h4>
 | 
			
		||||
        <div class="chart-box" id="country-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <h4>省市排行</h4>
 | 
			
		||||
        <div class="chart-box" id="province-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <h4>城市排行</h4>
 | 
			
		||||
        <div class="chart-box" id="city-chart">
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    {$end}
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										113
									
								
								web/views/@default/servers/server/stat/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								web/views/@default/servers/server/stat/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
    this.$delay(function () {
 | 
			
		||||
        let that = this
 | 
			
		||||
 | 
			
		||||
        let countryUnit = this.processMaxUnit(this.countryStats)
 | 
			
		||||
        this.reloadChart("country-chart", "地区", this.countryStats, function (v) {
 | 
			
		||||
            return v.country.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.countryStats[args.dataIndex].country.name + ": " + teaweb.formatNumber(that.countryStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, countryUnit)
 | 
			
		||||
 | 
			
		||||
        let provinceUnit = this.processMaxUnit(this.provinceStats)
 | 
			
		||||
        this.reloadChart("province-chart", "省市", this.provinceStats, function (v) {
 | 
			
		||||
            return v.province.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.provinceStats[args.dataIndex].country.name + ": " + that.provinceStats[args.dataIndex].province.name + " " + teaweb.formatNumber(that.provinceStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, provinceUnit)
 | 
			
		||||
 | 
			
		||||
        let cityUnit = this.processMaxUnit(this.cityStats)
 | 
			
		||||
        this.reloadChart("city-chart", "城市", this.cityStats, function (v) {
 | 
			
		||||
            return v.city.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.cityStats[args.dataIndex].country.name + ": " + that.cityStats[args.dataIndex].province.name + " " + that.cityStats[args.dataIndex].city.name + " " + teaweb.formatNumber(that.cityStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, cityUnit)
 | 
			
		||||
 | 
			
		||||
        window.addEventListener("resize", function () {
 | 
			
		||||
            that.resizeChart("country-chart")
 | 
			
		||||
            that.resizeChart("province-chart")
 | 
			
		||||
            that.resizeChart("city-chart")
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    this.reloadChart = 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.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
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								web/views/@default/servers/server/stat/providers.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/views/@default/servers/server/stat/providers.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
  height: 20em;
 | 
			
		||||
}
 | 
			
		||||
/*# sourceMappingURL=providers.css.map */
 | 
			
		||||
							
								
								
									
										1
									
								
								web/views/@default/servers/server/stat/providers.css.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								web/views/@default/servers/server/stat/providers.css.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
{"version":3,"sources":["providers.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"providers.css"}
 | 
			
		||||
							
								
								
									
										18
									
								
								web/views/@default/servers/server/stat/providers.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								web/views/@default/servers/server/stat/providers.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
 | 
			
		||||
{$var "header"}
 | 
			
		||||
<!-- echart -->
 | 
			
		||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
 | 
			
		||||
{$end}
 | 
			
		||||
 | 
			
		||||
{$template "/left_menu"}
 | 
			
		||||
<div class="right-box">
 | 
			
		||||
    {$ if eq .statIsOn false}
 | 
			
		||||
    <p class="ui message">
 | 
			
		||||
        要想查看统计数据,需要先开启统计功能,<a :href="'/servers/server/settings/stat?serverId=' + serverId">[点击这里]</a>修改配置。
 | 
			
		||||
    </p>
 | 
			
		||||
    {$else}
 | 
			
		||||
    <h4>运营商排行</h4>
 | 
			
		||||
    <div class="chart-box" id="provider-chart"></div>
 | 
			
		||||
    {$end}
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										96
									
								
								web/views/@default/servers/server/stat/providers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								web/views/@default/servers/server/stat/providers.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
    this.$delay(function () {
 | 
			
		||||
        let that = this
 | 
			
		||||
 | 
			
		||||
        let providerUnit = this.processMaxUnit(this.providerStats)
 | 
			
		||||
        this.reloadChart("provider-chart", "运营商", this.providerStats, function (v) {
 | 
			
		||||
            return v.provider.name
 | 
			
		||||
        }, function (args) {
 | 
			
		||||
            return that.providerStats[args.dataIndex].provider.name + ": " + teaweb.formatNumber(that.providerStats[args.dataIndex].rawCount)
 | 
			
		||||
        }, providerUnit)
 | 
			
		||||
        window.addEventListener("resize", function () {
 | 
			
		||||
            that.resizeChart("provider-chart")
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    this.reloadChart = 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.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
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										3
									
								
								web/views/@default/servers/server/stat/providers.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								web/views/@default/servers/server/stat/providers.less
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
.chart-box {
 | 
			
		||||
	height: 20em;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user