mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 05:00:25 +08:00 
			
		
		
		
	节点列表增加下行流量,节点列表可以按CPU、内存、下行流量排序
This commit is contained in:
		@@ -44,7 +44,7 @@ func init() {
 | 
			
		||||
			Post("/up", new(node.UpAction)).
 | 
			
		||||
			Get("/thresholds", new(thresholds.IndexAction)).
 | 
			
		||||
			Get("/detail", new(node.DetailAction)).
 | 
			
		||||
			Get("/boards", new(nodeboards.IndexAction)).
 | 
			
		||||
			GetPost("/boards", new(nodeboards.IndexAction)).
 | 
			
		||||
 | 
			
		||||
			// 分组相关
 | 
			
		||||
			Prefix("/clusters/cluster/groups").
 | 
			
		||||
 
 | 
			
		||||
@@ -178,3 +178,31 @@ func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunPost(params struct {
 | 
			
		||||
	ClusterId int64
 | 
			
		||||
	NodeId    int64
 | 
			
		||||
}) {
 | 
			
		||||
	resp, err := this.RPC().ServerStatBoardRPC().ComposeServerStatNodeBoard(this.AdminContext(), &pb.ComposeServerStatNodeBoardRequest{NodeId: params.NodeId})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Data["board"] = maps.Map{
 | 
			
		||||
		"isActive":            resp.IsActive,
 | 
			
		||||
		"trafficInBytes":      resp.TrafficInBytes,
 | 
			
		||||
		"trafficOutBytes":     resp.TrafficOutBytes,
 | 
			
		||||
		"countConnections":    resp.CountConnections,
 | 
			
		||||
		"countRequests":       resp.CountRequests,
 | 
			
		||||
		"countAttackRequests": resp.CountAttackRequests,
 | 
			
		||||
		"cpuUsage":            resp.CpuUsage,
 | 
			
		||||
		"memoryUsage":         resp.MemoryUsage,
 | 
			
		||||
		"memoryTotalSize":     resp.MemoryTotalSize,
 | 
			
		||||
		"load":                resp.Load,
 | 
			
		||||
		"cacheDiskSize":       resp.CacheDiskSize,
 | 
			
		||||
		"cacheMemorySize":     resp.CacheMemorySize,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,11 @@ func (this *NodesAction) RunGet(params struct {
 | 
			
		||||
	InstalledState int
 | 
			
		||||
	ActiveState    int
 | 
			
		||||
	Keyword        string
 | 
			
		||||
 | 
			
		||||
	CpuOrder        string
 | 
			
		||||
	MemoryOrder     string
 | 
			
		||||
	TrafficInOrder  string
 | 
			
		||||
	TrafficOutOrder string
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["groupId"] = params.GroupId
 | 
			
		||||
	this.Data["regionId"] = params.RegionId
 | 
			
		||||
@@ -61,7 +66,7 @@ func (this *NodesAction) RunGet(params struct {
 | 
			
		||||
	page := this.NewPage(countResp.Count)
 | 
			
		||||
	this.Data["page"] = page.AsHTML()
 | 
			
		||||
 | 
			
		||||
	nodesResp, err := this.RPC().NodeRPC().ListEnabledNodesMatch(this.AdminContext(), &pb.ListEnabledNodesMatchRequest{
 | 
			
		||||
	var req = &pb.ListEnabledNodesMatchRequest{
 | 
			
		||||
		Offset:        page.Offset,
 | 
			
		||||
		Size:          page.Size,
 | 
			
		||||
		NodeClusterId: params.ClusterId,
 | 
			
		||||
@@ -70,7 +75,25 @@ func (this *NodesAction) RunGet(params struct {
 | 
			
		||||
		InstallState:  types.Int32(params.InstalledState),
 | 
			
		||||
		ActiveState:   types.Int32(params.ActiveState),
 | 
			
		||||
		Keyword:       params.Keyword,
 | 
			
		||||
	})
 | 
			
		||||
	}
 | 
			
		||||
	if params.CpuOrder == "asc" {
 | 
			
		||||
		req.CpuAsc = true
 | 
			
		||||
	} else if params.CpuOrder == "desc" {
 | 
			
		||||
		req.CpuDesc = true
 | 
			
		||||
	} else if params.MemoryOrder == "asc" {
 | 
			
		||||
		req.MemoryAsc = true
 | 
			
		||||
	} else if params.MemoryOrder == "desc" {
 | 
			
		||||
		req.MemoryDesc = true
 | 
			
		||||
	} else if params.TrafficInOrder == "asc" {
 | 
			
		||||
		req.TrafficInAsc = true
 | 
			
		||||
	} else if params.TrafficInOrder == "desc" {
 | 
			
		||||
		req.TrafficInDesc = true
 | 
			
		||||
	} else if params.TrafficOutOrder == "asc" {
 | 
			
		||||
		req.TrafficOutAsc = true
 | 
			
		||||
	} else if params.TrafficOutOrder == "desc" {
 | 
			
		||||
		req.TrafficOutDesc = true
 | 
			
		||||
	}
 | 
			
		||||
	nodesResp, err := this.RPC().NodeRPC().ListEnabledNodesMatch(this.AdminContext(), req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
@@ -153,6 +176,8 @@ func (this *NodesAction) RunGet(params struct {
 | 
			
		||||
				"cpuUsageText":    fmt.Sprintf("%.2f%%", status.CPUUsage*100),
 | 
			
		||||
				"memUsage":        status.MemoryUsage,
 | 
			
		||||
				"memUsageText":    fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
 | 
			
		||||
				"trafficInBytes":  status.TrafficInBytes,
 | 
			
		||||
				"trafficOutBytes": status.TrafficOutBytes,
 | 
			
		||||
			},
 | 
			
		||||
			"cluster": maps.Map{
 | 
			
		||||
				"id":   node.NodeCluster.Id,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								web/public/js/components/common/sort-arrow.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								web/public/js/components/common/sort-arrow.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// 排序使用的箭头
 | 
			
		||||
Vue.component("sort-arrow", {
 | 
			
		||||
	props: ["name"],
 | 
			
		||||
	data: function () {
 | 
			
		||||
		let url = window.location.toString()
 | 
			
		||||
		let order = ""
 | 
			
		||||
		let newArgs = []
 | 
			
		||||
		if (window.location.search != null && window.location.search.length > 0) {
 | 
			
		||||
			let queryString = window.location.search.substring(1)
 | 
			
		||||
			let pieces = queryString.split("&")
 | 
			
		||||
			let that = this
 | 
			
		||||
			pieces.forEach(function (v) {
 | 
			
		||||
				let eqIndex = v.indexOf("=")
 | 
			
		||||
				if (eqIndex > 0) {
 | 
			
		||||
					let argName = v.substring(0, eqIndex)
 | 
			
		||||
					let argValue = v.substring(eqIndex + 1)
 | 
			
		||||
					if (argName == that.name) {
 | 
			
		||||
						order = argValue
 | 
			
		||||
					} else if (argValue != "asc" && argValue != "desc") {
 | 
			
		||||
						newArgs.push(v)
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					newArgs.push(v)
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		if (order == "asc") {
 | 
			
		||||
			newArgs.push(this.name + "=")
 | 
			
		||||
		} else if (order == "desc") {
 | 
			
		||||
			newArgs.push(this.name + "=asc")
 | 
			
		||||
		} else {
 | 
			
		||||
			newArgs.push(this.name + "=desc")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let qIndex = url.indexOf("?")
 | 
			
		||||
		if (qIndex > 0) {
 | 
			
		||||
			url = url.substring(0, qIndex) + "?" + newArgs.join("&")
 | 
			
		||||
		} else {
 | 
			
		||||
			url = url + "?" + newArgs.join("&")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return {
 | 
			
		||||
			order: order,
 | 
			
		||||
			url: url
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	template: `<a :href="url" title="排序">  <i class="ui icon long arrow small" :class="{down: order == 'asc', up: order == 'desc', 'down grey': order == '' || order == null}"></i></a>`
 | 
			
		||||
})
 | 
			
		||||
@@ -21,6 +21,8 @@ form .fields {
 | 
			
		||||
table th.center,
 | 
			
		||||
table td.center {
 | 
			
		||||
  text-align: center !important;
 | 
			
		||||
  padding-left: 0 !important;
 | 
			
		||||
  padding-right: 0 !important;
 | 
			
		||||
}
 | 
			
		||||
table th.width10 {
 | 
			
		||||
  width: 10em;
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
{"version":3,"sources":["@layout_override.less"],"names":[],"mappings":"AACA,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,QAAO;EACrG,oCAAA;;AAGD,GAAG,OAAO,SAAU,MAAK,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,QAAS,QAAO;EACzF,oCAAA;;AAGD,GAAG,MAAM;EACR,kCAAA;;AAID,IACC;EACC,2BAAA;;AAKF,KAAK;EACJ,sBAAA;;AAGD,KAAK,KAAK;EACT,yBAAA;;AAID,KACC,GAAE;AADH,KACY,GAAE;EACZ,6BAAA;;AAFF,KAKC,GAAE;EACD,WAAA;;AANF,KASC,GAAE;EACD,UAAA;;AAVF,KAaC,GAAE;EACD,UAAA;;AAKF,QAAQ;EACP,qBAAA;;AAID,MAAM;EACL,uBAAA","file":"@layout_override.css"}
 | 
			
		||||
{"version":3,"sources":["@layout_override.less"],"names":[],"mappings":"AACA,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,QAAO;EACrG,oCAAA;;AAGD,GAAG,OAAO,SAAU,MAAK,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,QAAS,QAAO;EACzF,oCAAA;;AAGD,GAAG,MAAM;EACR,kCAAA;;AAID,IACC;EACC,2BAAA;;AAKF,KAAK;EACJ,sBAAA;;AAGD,KAAK,KAAK;EACT,yBAAA;;AAID,KACC,GAAE;AADH,KACY,GAAE;EACZ,6BAAA;EACA,0BAAA;EACA,2BAAA;;AAJF,KAOC,GAAE;EACD,WAAA;;AARF,KAWC,GAAE;EACD,UAAA;;AAZF,KAeC,GAAE;EACD,UAAA;;AAKF,QAAQ;EACP,qBAAA;;AAID,MAAM;EACL,uBAAA","file":"@layout_override.css"}
 | 
			
		||||
@@ -31,6 +31,8 @@ form {
 | 
			
		||||
table {
 | 
			
		||||
	th.center, td.center {
 | 
			
		||||
		text-align: center !important;
 | 
			
		||||
		padding-left: 0 !important;
 | 
			
		||||
		padding-right: 0 !important;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	th.width10 {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ Tea.context(function () {
 | 
			
		||||
		return (Math.round(count / 1000 / 1000 * 100) / 100) + "M"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.loadBoard = function () {
 | 
			
		||||
		this.board.trafficInBytes = teaweb.formatBytes(this.board.trafficInBytes)
 | 
			
		||||
		this.board.trafficOutBytes = teaweb.formatBytes(this.board.trafficOutBytes)
 | 
			
		||||
		this.board.countConnections = this.formatCount(this.board.countConnections)
 | 
			
		||||
@@ -20,6 +21,9 @@ Tea.context(function () {
 | 
			
		||||
		this.board.load = Math.round(this.board.load * 100) / 100
 | 
			
		||||
		this.board.cacheDiskSize = teaweb.formatBytes(this.board.cacheDiskSize)
 | 
			
		||||
		this.board.cacheMemorySize = teaweb.formatBytes(this.board.cacheMemorySize)
 | 
			
		||||
	}
 | 
			
		||||
	this.loadBoard()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 流量统计
 | 
			
		||||
@@ -32,6 +36,26 @@ Tea.context(function () {
 | 
			
		||||
		this.reloadTopDomainsChart()
 | 
			
		||||
		this.reloadCPUChart()
 | 
			
		||||
	})
 | 
			
		||||
	this.$delay(function() {
 | 
			
		||||
		this.refreshBoard()
 | 
			
		||||
	}, 30000)
 | 
			
		||||
 | 
			
		||||
	this.refreshBoard = function() {
 | 
			
		||||
		this.$post("$")
 | 
			
		||||
			.params({
 | 
			
		||||
				clusterId: this.clusterId,
 | 
			
		||||
				nodeId: this.node.id
 | 
			
		||||
			})
 | 
			
		||||
			.success(function (resp) {
 | 
			
		||||
				this.board = resp.data.board
 | 
			
		||||
				this.loadBoard()
 | 
			
		||||
			})
 | 
			
		||||
			.done(function () {
 | 
			
		||||
				this.$delay(function () {
 | 
			
		||||
					this.refreshBoard()
 | 
			
		||||
				}, 60000)
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.selectTrafficTab = function (tab) {
 | 
			
		||||
		this.trafficTab = tab
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
{$template "menu"}
 | 
			
		||||
 | 
			
		||||
<form class="ui form" action="/clusters/cluster" v-show="countAll > 0">
 | 
			
		||||
<form class="ui form" action="/clusters/cluster/nodes" v-show="countAll > 0">
 | 
			
		||||
	<input type="hidden" name="clusterId" :value="clusterId"/>
 | 
			
		||||
	<div class="ui fields inline">
 | 
			
		||||
        <div class="ui field" v-if="regions.length > 0">
 | 
			
		||||
@@ -35,7 +35,8 @@
 | 
			
		||||
			<input type="text" name="keyword" placeholder="关键词" v-model="keyword" style="width:10em"/>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="ui field">
 | 
			
		||||
			<button class="ui button" type="submit">搜索</button>
 | 
			
		||||
			<button class="ui button" type="submit">搜索</button>  
 | 
			
		||||
            <a :href="'/clusters/cluster/nodes?clusterId=' + clusterId" v-if="regionId >0 || groupId > 0 || installState > 0 || activeState > 0 || keyword.length > 0">[清除条件]</a>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</form>
 | 
			
		||||
@@ -55,27 +56,23 @@
 | 
			
		||||
	<thead>
 | 
			
		||||
	<tr>
 | 
			
		||||
		<th>节点名称</th>
 | 
			
		||||
        <th>所属区域</th>
 | 
			
		||||
		<th>所属分组</th>
 | 
			
		||||
		<th>IP</th>
 | 
			
		||||
		<th class="width10">DNS线路</th>
 | 
			
		||||
		<th class="width5 center">CPU</th>
 | 
			
		||||
		<th class="width5 center">内存</th>
 | 
			
		||||
		<!--<th>流量</th>
 | 
			
		||||
		<th>连接数</th>-->
 | 
			
		||||
		<th class="width5 center">CPU<sort-arrow name="cpuOrder"></sort-arrow></th>
 | 
			
		||||
		<th class="width5 center">内存<sort-arrow name="memoryOrder"></sort-arrow></th>
 | 
			
		||||
		<th class="center" style="width: 7em">下行流量<sort-arrow name="trafficOutOrder"></sort-arrow></th>
 | 
			
		||||
		<th class="two wide center">状态</th>
 | 
			
		||||
		<th class="two op">操作</th>
 | 
			
		||||
	</tr>
 | 
			
		||||
	</thead>
 | 
			
		||||
	<tr v-for="node in nodes">
 | 
			
		||||
		<td>{{node.name}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <span v-if="node.region != null">{{node.region.name}}</span>
 | 
			
		||||
            <span v-else class="disabled">-</span>
 | 
			
		||||
        </td>
 | 
			
		||||
		<td>
 | 
			
		||||
			<span v-if="node.group != null">{{node.group.name}}</span>
 | 
			
		||||
			<span v-else class="disabled">-</span>
 | 
			
		||||
		<td>{{node.name}}
 | 
			
		||||
            <div style="margin-top: 0.5em" v-if="node.region != null">
 | 
			
		||||
                <tiny-label class="basic">区域:{{node.region.name}}</tiny-label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div style="margin-top: 0.5em" v-if="node.group != null">
 | 
			
		||||
                <tiny-label class="basic">分组:{{node.group.name}}</tiny-label>
 | 
			
		||||
            </div>
 | 
			
		||||
        </td>
 | 
			
		||||
		<td>
 | 
			
		||||
			<span v-if="node.ipAddresses.length == 0" class="disabled">-</span>
 | 
			
		||||
@@ -104,6 +101,10 @@
 | 
			
		||||
			<span v-if="node.status.isActive" :class="{red:node.status.memUsage > 0.80}">{{node.status.memUsageText}}</span>
 | 
			
		||||
			<span v-else class="disabled">-</span>
 | 
			
		||||
		</td>
 | 
			
		||||
        <td class="center">
 | 
			
		||||
            <span v-if="node.status.isActive && node.status.trafficOutBytes > 0">{{teaweb.formatBytes(node.status.trafficOutBytes)}}<br/><span class="grey small">/分钟</span></span>
 | 
			
		||||
            <span v-else class="disabled">-</span>
 | 
			
		||||
        </td>
 | 
			
		||||
		<td class="center">
 | 
			
		||||
			<div v-if="!node.isUp">
 | 
			
		||||
				<span class="red">健康问题下线</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.teaweb = teaweb
 | 
			
		||||
 | 
			
		||||
	this.deleteNode = function (nodeId) {
 | 
			
		||||
		teaweb.confirm("确定要删除这个节点吗?", function () {
 | 
			
		||||
			this.$post("/nodes/delete")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user