💥 v2.0 必须更新面板,新增服务监控

This commit is contained in:
naiba
2021-01-16 00:45:49 +08:00
parent 0ce8017875
commit a41c792577
38 changed files with 1015 additions and 453 deletions

View File

@@ -76,4 +76,57 @@
line-height: 1.75em;
color: rgba(255, 255, 255, .7);
font-weight: 700;
}
.service-status .round>i {
width: 1rem;
height: 1rem;
border-radius: .5rem;
display: inline-block;
margin-right: .3rem;
background-color: slategray;
}
.service-status .danger.button {
background-color: crimson;
}
.service-status .good.button {
background-color: rgb(0, 235, 139);
}
.service-status .warning.button {
background-color: orange;
}
.service-status .danger>i {
background-color: crimson;
}
.service-status .good>i {
background-color: rgb(0, 235, 139);
}
.service-status .warning>i {
background-color: orange;
}
.service-status .three.column p {
display: inline-block;
}
.service-status .three.column p:last-child {
float: right;
font-size: smaller;
}
.service-status .eleven.column {
text-align: center;
}
.service-status .eleven.column>.ui.button {
width: 8px !important;
padding: unset !important;
margin-top: unset !important;
margin-bottom: unset !important;
}

View File

@@ -39,7 +39,7 @@ function showFormModal(modelSelector, formID, URL, getData) {
obj[item.name] = (item.name.endsWith('_id') ||
item.name === 'id' || item.name === 'ID' ||
item.name === 'RequestType' || item.name === 'RequestMethod' ||
item.name === 'DisplayIndex') ? parseInt(item.value) : item.value;
item.name === 'DisplayIndex' || item.name === 'Type') ? parseInt(item.value) : item.value;
return obj;
}, {});
$.post(URL, JSON.stringify(data)).done(function (resp) {
@@ -118,6 +118,17 @@ function addOrEditServer(server) {
showFormModal('.server.modal', '#serverForm', '/api/server')
}
function addOrEditMonitor(monitor) {
const modal = $('.monitor.modal')
modal.children('.header').text((monitor ? '修改' : '添加') + '监控')
modal.find('.positive.button').html(monitor ? '修改<i class="edit icon"></i>' : '添加<i class="add icon"></i>')
modal.find('input[name=ID]').val(monitor ? monitor.ID : null)
modal.find('input[name=Name]').val(monitor ? monitor.Name : null)
modal.find('input[name=Target]').val(monitor ? monitor.Target : null)
modal.find('select[name=Type]').val(monitor ? monitor.Type : 1)
showFormModal('.monitor.modal', '#monitorForm', '/api/monitor')
}
function deleteRequest(api) {
$.ajax({
url: api,

View File

@@ -1,8 +1,7 @@
{{define "common/footer"}}
<div class="ui inverted vertical footer segment">
<div class="ui center aligned is-size-7 container">
Powered by <a href="https://github.com/naiba/nezha" style="color: white;" target="_blank">哪吒面板</a> build ·
{{.Version}}
Powered by <a href="https://github.com/naiba/nezha" style="color: white;" target="_blank">哪吒面板</a> {{.Version}}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>

View File

@@ -9,7 +9,7 @@
<title>{{.Title}}</title>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.1/dist/semantic.min.css">
<link rel="stylesheet" type="text/css" href="/static/semantic-ui-alerts.min.css">
<link rel="stylesheet" type="text/css" href="/static/main.css?v202012252026">
<link rel="stylesheet" type="text/css" href="/static/main.css?v202101160044">
<link rel="shortcut icon" type="image/png" href="/static/logo.png" />
</head>

View File

@@ -5,13 +5,14 @@
<img src="/static/logo.png">
</div>
<a class="item{{if eq .MatchedPath " /"}} active{{end}}" href="/">首页</a>
<a class="item{{if eq .MatchedPath " /service"}} active{{end}}" href="/service">服务状态</a>
{{if .Admin}}
<a class="item{{if eq .MatchedPath " /server"}} active{{end}}" href="/server">服务器</a>
<a class="item{{if eq .MatchedPath " /monitor"}} active{{end}}" href="/monitor">监控</a>
<a class="item{{if eq .MatchedPath " /notification"}} active{{end}}" href="/notification">通知</a>
<a class="item{{if eq .MatchedPath " /setting"}} active{{end}}" href="/setting">设置</a>
{{end}}
<div class="right menu">
<a class="item" href="https://github.com/naiba/nezha/issues" target="_blank">反馈</a>
<div class="item">
{{if .Admin}}
<div class="ui simple dropdown">

View File

@@ -0,0 +1,31 @@
{{define "component/monitor"}}
<div class="ui tiny monitor modal transition hidden">
<div class="header">添加监控</div>
<div class="content">
<form id="monitorForm" class="ui form">
<input type="hidden" name="ID">
<div class="field">
<label>备注</label>
<input type="text" name="Name" placeholder="博客">
</div>
<div class="field">
<label>目标</label>
<input type="text" name="Target" placeholder="https://t.tt,t.tt,t.tt:80">
</div>
<div class="field">
<label>类型</label>
<select name="Type" class="ui fluid dropdown">
<option value="1">HTTP-GET</option>
<option value="2">ICMP-Ping</option>
<option value="3">TCP-Ping</option>
</select>
</div>
</form>
</div>
<div class=" actions">
<div class="ui negative button">取消</div>
<button class="ui positive right labeled icon button">确认<i class="checkmark icon"></i>
</button>
</div>
</div>
{{end}}

View File

@@ -0,0 +1,49 @@
{{define "dashboard/monitor"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">
<div class="ui container">
<div class="ui grid">
<div class="right floated right aligned twelve wide column">
<button class="ui right labeled positive icon button" onclick="addOrEditMonitor()"><i
class="add icon"></i> 添加监控
</button>
</div>
</div>
<table class="ui very basic table">
<thead>
<tr>
<th>ID</th>
<th>备注</th>
<th>类型</th>
<th>目标</th>
<th>管理</th>
</tr>
</thead>
<tbody>
{{range $monitor := .Monitors}}
<tr>
<td>{{$monitor.ID}}</td>
<td>{{$monitor.Name}}</td>
<td>{{$monitor.Target}}</td>
<td>{{$monitor.Type}}</td>
<td>
<div class="ui mini icon buttons">
<button class="ui button" onclick="addOrEditMonitor({{$monitor}})">
<i class="edit icon"></i>
</button>
<button class="ui button"
onclick="showConfirm('删除监控','确认删除此监控?',deleteRequest,'/api/monitor/'+{{$monitor.ID}})">
<i class="delete icon"></i>
</button>
</div>
</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
{{template "component/monitor"}}
{{template "common/footer" .}}
{{end}}

View File

@@ -14,8 +14,8 @@
</div>
<div class="field">
<select name="Theme">
<option value="default">默认主题</option>
<option value="hotaru">CakeMine-Hotaru</option>
<option value="default"{{if eq .Conf.Site.Theme "default"}} selected="selected"{{end}}>默认主题</option>
<option value="hotaru"{{if eq .Conf.Site.Theme "hotaru"}} selected="selected"{{end}}>CokeMine Hotaru</option>
</select>
</div>
<div class="field">

View File

@@ -0,0 +1,42 @@
{{define "theme-default/service"}}
{{template "common/header" .}}
{{template "common/menu" .}}
<div class="nb-container">
<div class="ui container">
<div class="ui segment service-status">
{{range $service := .Services}}
<div class="ui grid">
<div class="three wide column">
<p>{{$service.Monitor.Name}}</p>
<p>30天在线率{{divU64 $service.TotalDown (addU64 $service.TotalUp $service.TotalDown)}}%</p>
</div>
<div class="eleven wide column">
{{range $i,$d := $service.Delay}}
<div class="ui icon button{{if gt (add (index $service.Up $i) (index $service.Down $i)) 0}}
{{if gt (div (index $service.Down $i) (add (index $service.Up $i) (index $service.Down $i))) 30.0}}danger
{{else if gt (div (index $service.Down $i) (add (index $service.Up $i) (index $service.Down $i))) 10.0}}
warning{{else}}good{{end}}
{{end}}" data-tooltip="{{dayBefore $i}},平均延迟:{{$d}}ms">
<i class="delay"></i>
</div>
{{end}}
</div>
<div class="two wide column round{{if gt (addU64 $service.TotalUp $service.TotalDown) 0}}
{{if gt (divU64 $service.TotalDown (addU64 $service.TotalUp $service.TotalDown)) 30.0}}danger{{else if gt (divU64 $service.TotalDown (addU64 $service.TotalUp $service.TotalDown)) 10.0}}warning{{else}}good{{end}}
{{end}}">
<i></i>
{{if gt (addU64 $service.TotalUp $service.TotalDown) 0}}
{{if gt (divU64 $service.TotalDown (addU64 $service.TotalUp $service.TotalDown)) 30.0}}故障
{{else if gt (divU64 $service.TotalDown (addU64 $service.TotalUp $service.TotalDown)) 10.0}}
低可用{{else}}良好{{end}}
{{else}}无数据
{{end}}
</div>
</div>
<div class="ui divider"></div>
{{end}}
</div>
</div>
</div>
{{template "common/footer" .}}
{{end}}