Merge branch 'master' of github.com:naiba/nezha

This commit is contained in:
naiba 2021-01-30 19:06:17 +08:00
commit 061a9992ff
7 changed files with 277 additions and 266 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
function callAllJsFiles(t){var e=document.createElement("script");e.setAttribute("type","text/javascript"),e.setAttribute("src",t),document.getElementsByTagName("head")[0].appendChild(e)}callAllJsFiles("/static/theme-daynight/js/mode.js?v202101290086"),callAllJsFiles("/static/theme-daynight/js/navtop.js?v202101290086");
function callAllJsFiles(t){var e=document.createElement("script");e.setAttribute("type","text/javascript"),e.setAttribute("src",t),document.getElementsByTagName("head")[0].appendChild(e)}callAllJsFiles("/static/theme-daynight/js/mode.js?v202101301768"),callAllJsFiles("/static/theme-daynight/js/navtop.js?v202101301768");

View File

@ -1 +1 @@
$(document).ready((function(){$(".hamburger").click((function(){$(this).toggleClass("is-active"),$(".nav-menu").toggleClass("active"),$(".nav-bar").toggleClass("active")}))}));var btn=$("#back-to-top");$(window).scroll((function(){$(window).scrollTop()>300?btn.addClass("show"):btn.removeClass("show")})),btn.on("click",(function(o){o.preventDefault(),$(".service-mobile-toggle").hasClass("smt-active")&&($(".service-mobile-toggle ").removeClass("smt-active"),$("html, body").animate({scrollTop:0},"300")),$("html, body").animate({scrollTop:0},"300")}));
$(document).ready((function(){$(".hamburger").click((function(){$(this).toggleClass("is-active"),$(".nav-menu ul").slideToggle("500","linear")}))}));var btn=$("#back-to-top");$(window).scroll((function(){$(window).scrollTop()>300?btn.addClass("show"):btn.removeClass("show")})),$(document).ready((function(){btn.on("click",(function(o){o.preventDefault(),$(".service-mobile-toggle").hasClass("smt-active")&&($(".service-mobile-toggle ").removeClass("smt-active"),$("html, body").animate({scrollTop:0},"300")),$("html, body").animate({scrollTop:0},"300")}))}));

View File

@ -1 +1 @@
function callAllJsFiles(e){var t=document.createElement("script");t.setAttribute("type","text/javascript"),t.setAttribute("src",e),document.getElementsByTagName("head")[0].appendChild(t)}callAllJsFiles("/static/theme-daynight/js/navtop.js?v202101290086"),callAllJsFiles("/static/theme-daynight/js/mode.js?v202101290086"),callAllJsFiles("/static/theme-daynight/js/tooltip.js?v202101290086"),$(".corner").hover((function(){$(this).attr("aria-expanded","true"===$(this).attr("aria-expanded")?"false":"true")}));const hour=new Date(Date.now()).getHours();(hour>17||hour<4)&&(document.querySelector("input[name=service-theme]").checked=!0,document.getElementsByTagName("BODY")[0].setAttribute("data-theme","dark")),$(document).ready((function(){$(".fa-plus").click((function(){$(".service-mobile-toggle").toggleClass("smt-active")}))}));
function callAllJsFiles(e){var t=document.createElement("script");t.setAttribute("type","text/javascript"),t.setAttribute("src",e),document.getElementsByTagName("head")[0].appendChild(t)}callAllJsFiles("/static/theme-daynight/js/navtop.js?v202101301768"),callAllJsFiles("/static/theme-daynight/js/mode.js?v202101301768"),callAllJsFiles("/static/theme-daynight/js/tooltip.js?v202101301768"),$(".corner").hover((function(){$(this).attr("aria-expanded","true"===$(this).attr("aria-expanded")?"false":"true")}));const hour=new Date(Date.now()).getHours();(hour>17||hour<4)&&(document.querySelector("input[name=service-theme]").checked=!0,document.getElementsByTagName("BODY")[0].setAttribute("data-theme","dark")),$(document).ready((function(){$(".service-mobile-toggle ul li:first-of-type").click((function(){$(".service-mobile-toggle").toggleClass("smt-active")}))})),$(document).on("click",(function(e){0==$(e.target).closest(".service-mobile-toggle").length&&$(".service-mobile-toggle").hasClass("smt-active")&&$(".service-mobile-toggle").toggleClass("smt-active")}));

View File

@ -1,107 +1,122 @@
{{define "theme-daynight/home"}}
<!DOCTYPE html>
<!doctype html>
<html lang="zh-Hans">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>{{.Title}}</title>
<link rel="shortcut icon" type="image/png" href="/static/logo.png" />
<link rel="stylesheet" href="/static/theme-daynight/css/main.css?v202101290086" />
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet" />
<link rel="stylesheet" href="/static/theme-daynight/css/main.css?v202101301768">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{if ts .CustomCode}} {{.CustomCode|safe}} {{end}}
</head>
{{if ts .CustomCode}}
{{.CustomCode|safe}}
{{end}}
</head>
<body data-theme="light" data-gridlist="grid">
<header class="nav-bar clearfix">
<figure class="logo"><a href="/">{{.Conf.Site.Brand}}</a></figure>
<div class="icon-container">
<div class="row cf">
<div class="three col">
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span class="line"></span><span class="line"></span></div>
</div>
</div>
</div>
<nav class="nav-menu">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/service">服务状态</a></li>
{{if .Admin}}
<li><a href="/server" style="padding: 0.8em; text-align: center">管理后台</a></li>
{{else}}
<li><a href="/login">登录</a></li>
{{end}}
</ul>
</nav>
<body data-theme="light" data-gridlist="grid">
<header>
<section class="nav-bar clearfix">
<figure class="logo"><a href="/">{{.Conf.Site.Brand}}</a></figure>
<div class="icon-container">
<div class="row cf">
<div class="three col">
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span class="line"></span><span
class="line"></span></div>
</div>
</div>
</div>
<nav class="nav-menu">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/service">服务状态</a></li>
{{if .Admin}}
<li><a href="/server" style="padding:.8em;text-align:center;">管理后台</a></li>
{{else}}
<li><a href="/login">登录</a></li>
{{end}}
</ul>
</nav>
</section>
</header>
<main>
<div id="app">
<div class="server-info-container" v-for="server in servers" :id="server.ID">
<div class="info-body">
<ul class="server-info-body-container">
<li>
<div :class="'state-'+ (server.live?'online':'offline')">
<p>@#server.live?'Running':'Down'#@</p>
</div>
</li>
<li>
<h3>@#server.Name#@</h3>
</li>
<li><img :src="'/static/theme-daynight/img/flag/'+(server.Host&&server.Host.CountryCode?server.Host.CountryCode.toUpperCase():'CN')+'.png'" :title="server.Host.CountryCode.toUpperCase()" /></li>
<li>@#server.Host.Platform#@</li>
<li>@#server.Host.CountryCode.toUpperCase()#@</li>
<li>@#formatByteSize(server.State.MemUsed)#@ / @#formatByteSize(server.Host.MemTotal)#@</li>
<li>@#server.State?secondToDate(server.State.Uptime):'-'#@</li>
<li>@#formatByteSize(server.State.SwapUsed)#@ / @#formatByteSize(server.Host.SwapTotal)#@</li>
<li>@#formatByteSize(server.State.DiskUsed)#@ / @#formatByteSize(server.Host.DiskTotal)#@</li>
<li>@#formatByteSize(server.State.NetInTransfer)#@ (@#formatByteSize(server.State.NetInSpeed)#@/s)</li>
<li>@#formatByteSize(server.State.NetOutTransfer)#@ (@#formatByteSize(server.State.NetOutSpeed)#@/s)</li>
<li>
<div class="cpu-bar">
<div>
<h4>CPU</h4>
</div>
<div v-if="server.State" :class="formatPercent(server.live,server.State.CPU, 100).class" :title="formatPercent(server.live,server.State.CPU,100).percent+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="formatPercent(server.live,server.State.CPU,100).percent" aria-valuemin="0" aria-valuemax="100" :style="formatPercent(server.live,server.State.CPU, 100).style">
<p>@#formatPercent(server.live,server.State.CPU,100).percent#@%</p>
</div>
</div>
</div>
</li>
<li>
<div class="ram-bar">
<div>
<h4>RAM</h4>
</div>
<div v-if="server.State" :class="formatPercent(server.live,server.State.MemUsed, server.Host.MemTotal).class" :title="parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)" aria-valuemin="0" aria-valuemax="100" :style="formatPercent(server.live,server.State.MemUsed, server.Host.MemTotal).style">
<p>@#parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)#@%</p>
</div>
</div>
</div>
</li>
<li>
<div class="disk-bar">
<div>
<h4>硬盘</h4>
</div>
<div v-if="server.State" :class="formatPercent(server.live,server.State.DiskUsed, server.Host.DiskTotal).class" :title="parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)" aria-valuemin="0" aria-valuemax="100" :style="formatPercent(server.live,server.State.DiskUsed, server.Host.DiskTotal).style">
<p>@#parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)#@%</p>
</div>
</div>
</div>
</li>
</ul>
</div>
<main>
<div id="app">
<div class="server-info-container" v-for='server in servers' :id="server.ID">
<div class="info-body">
<ul class="server-info-body-container">
<li>
<div :class="'state-'+ (server.live?'online':'offline')">
<p>@#server.live?'Running':'Down'#@</p>
</div>
</li>
<li>
<h3>@#server.Name#@</h3>
</li>
<li><img :src="'/static/theme-daynight/img/flag/'+(server.Host&&server.Host.CountryCode?server.Host.CountryCode.toUpperCase():'CN')+'.png'"
:title="server.Host.CountryCode.toUpperCase()" /></li>
<li>@#server.Host.Platform#@</li>
<li>@#server.Host.CountryCode.toUpperCase()#@</li>
<li>@#formatByteSize(server.State.MemUsed)#@ / @#formatByteSize(server.Host.MemTotal)#@</li>
<li>@#server.State?secondToDate(server.State.Uptime):'-'#@</li>
<li>@#formatByteSize(server.State.SwapUsed)#@ / @#formatByteSize(server.Host.SwapTotal)#@</li>
<li>@#formatByteSize(server.State.DiskUsed)#@ / @#formatByteSize(server.Host.DiskTotal)#@</li>
<li>@#formatByteSize(server.State.NetInTransfer)#@ (@#formatByteSize(server.State.NetInSpeed)#@/s)</li>
<li>@#formatByteSize(server.State.NetOutTransfer)#@ (@#formatByteSize(server.State.NetOutSpeed)#@/s)</li>
<li>
<div class="cpu-bar">
<div>
<h4>CPU</h4>
</div>
<div v-if="server.State" :class="formatPercent(server.live,server.State.CPU, 100).class"
:title="formatPercent(server.live,server.State.CPU,100).percent+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="formatPercent(server.live,server.State.CPU,100).percent" aria-valuemin="0" aria-valuemax="100"
:style="formatPercent(server.live,server.State.CPU, 100).style">
<p>@#formatPercent(server.live,server.State.CPU,100).percent#@%</p>
</div>
</div>
</div>
</li>
<li>
<div class="ram-bar">
<div>
<h4>RAM</h4>
</div>
<div v-if="server.State"
:class="formatPercent(server.live,server.State.MemUsed, server.Host.MemTotal).class"
:title="parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)" aria-valuemin="0" aria-valuemax="100"
:style="formatPercent(server.live,server.State.MemUsed, server.Host.MemTotal).style">
<p>@#parseInt(server.State?server.State.MemUsed/server.Host.MemTotal*100:0)#@%</p>
</div>
</div>
</div>
</li>
<li>
<div class="disk-bar">
<div>
<h4>硬盘</h4>
</div>
<div v-if="server.State"
:class="formatPercent(server.live,server.State.DiskUsed, server.Host.DiskTotal).class"
:title="parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)+'%'">
<div class="progress-bar" role="progressbar" :aria-valuenow="parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)" aria-valuemin="0" aria-valuemax="100"
:style="formatPercent(server.live,server.State.DiskUsed, server.Host.DiskTotal).style">
<p>@#parseInt(server.State?server.State.DiskUsed/server.Host.DiskTotal*100:0)#@%</p>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="sidebar-container">
</div>
<div class="sidebar-container">
<ul>
<li><i class="fas fa-sun" title="白昼模式"></i><span>白昼模式</span></li>
<li><i class="fas fa-moon" title="暗黑模式"></i><span>暗黑模式</span></li>
@ -109,7 +124,7 @@
<li><i class="fas fa-list-ul" title="列表视图"></i><span>列表视图</span></li>
</ul>
</div>
</main>
</main>
<section class="dark-light-toggle">
<label class="switcher">
@ -119,155 +134,150 @@
</div>
</label>
</section>
<!-- Back to top button -->
<a id="back-to-top"></a>
<footer>
<div class="footer-container">
<div>
<a href="https://github.com/naiba/nezha" target="_blank">Powered by 哪吒面板 · {{.Version}}</a>
<p>
&copy;
<span id="copyright-date">
<script>
document.getElementById("copyright-date").appendChild(document.createTextNode(new Date().getFullYear()));
</script>
</span>
· <a href="https://blog.jackiesung.com" target="_blank">Theme designed by Jackie Sung</a>
</p>
<div class="footer-container">
<div><a href="https://github.com/naiba/nezha" target="_blank">Powered by 哪吒面板 · {{.Version}}</a>
<p>&copy; <span id="copyright-date">
<script>document.getElementById('copyright-date').appendChild(document.createTextNode(new Date().getFullYear()))</script>
</span> · <a href="https://blog.jackiesung.com" target="_blank">Theme designed by Jackie Sung</a>
</p>
</div>
</div>
</div>
</footer>
<script src="/static/theme-daynight/js/main.js?v202101290086"></script>
<script src="/static/theme-daynight/js/main.js?v202101301768" ></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
<script>
const initData = {{.Servers }};
var statusCards = new Vue({
el: '#app',
delimiters: ['@#', '#@'],
data: {
servers: initData,
cache: [],
},
mounted() {
this.DarkMode();
},
methods: {
mergeUsage(state, host) {
if (!state) {
return 0
}
if (!host) {
return state.CPU
}
return (state.CPU + (state.MemUsed / host.MemTotal * 100) + (state.DiskUsed / host.DiskTotal * 100)) / 3
},
formatPercent(live, used, total) {
const percent = live ? (parseInt(used / total * 100) || 0) : -1
if (!this.cache[percent]) {
this.cache[percent] = {
class: {
ui: true,
progress: true,
},
style: {
'transition-duration': '300ms',
'min-width': 'unset',
width: percent + '% !important',
},
percent,
}
if (percent < 0) {
this.cache[percent].style['background-color'] = 'slategray'
this.cache[percent].class.offline = true
} else if (percent < 51) {
this.cache[percent].style['background-color'] = '#53B449'
this.cache[percent].class.fine = true
} else if (percent < 81) {
this.cache[percent].style['background-color'] = '#FBB142'
this.cache[percent].class.warning = true
} else {
this.cache[percent].style['background-color'] = '#F23D34'
this.cache[percent].class.error = true
}
}
return this.cache[percent]
},
readableBytes(bytes) {
var i = Math.floor(Math.log(bytes) / Math.log(1024)),
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
return (bytes / Math.pow(1024, i)).toFixed(0) + ' ' + sizes[i];
},
DarkMode() {
const hour = new Date(Date.now()).getHours()
if (hour > 17 || hour < 4) {
document.querySelector("input[name=theme]").checked = true;
document.getElementsByTagName("BODY")[0].setAttribute('data-theme', 'dark');
}
},
secondToDate(s) {
var d = Math.floor(s / 3600 / 24);
if (d > 0) {
return d + "天"
}
var h = Math.floor(s / 3600 % 24);
var m = Math.floor(s / 60 % 60);
var s = Math.floor(s % 60);
return h + ":" + ("0" + m).slice(-2) + ":" + ("0" + s).slice(-2);
},
formatTimestamp(t) {
return new Date(t * 1000).toLocaleString()
},
formatByteSize(bs) {
const x = this.readableBytes(bs)
return x != "NaN undefined" ? x : '0 KB'
}
}
})
const wsProtocol = window.location.protocol == "https:" ? "wss" : "ws"
const ws = new WebSocket(wsProtocol + '://' + window.location.host + '/ws');
ws.onopen = function (evt) {
Swal.fire({
position: 'top',
icon: 'success',
title: '实时通道建立',
text: '可以实时获取最新监控数据啦',
showConfirmButton: false,
timer: 2000
});
}
ws.onmessage = function (evt) {
statusCards.servers = JSON.parse(evt.data)
const keys = Object.keys(statusCards.servers)
for (let i = 0; i < keys.length; i++) {
const ns = statusCards.servers[keys[i]];
if (!ns.Host) ns.live = false
else {
const lastActive = new Date(ns.LastActive).getTime()
if (Date.now() - lastActive > 20 * 1000) {
ns.live = false
} else {
ns.live = true
}
}
}
}
ws.onclose = function () {
Swal.fire({
position: 'top',
icon: 'error',
title: '实时通道断开',
text: '无法实时获取最新监控数据咯',
showConfirmButton: false,
timer: 2000
});
const initData = {{.Servers }};
var statusCards = new Vue({
el: '#app',
delimiters: ['@#', '#@'],
data: {
servers: initData,
cache: [],
},
mounted() {
this.DarkMode();
},
methods: {
mergeUsage(state, host) {
if (!state) {
return 0
}
if (!host) {
return state.CPU
}
return (state.CPU + (state.MemUsed / host.MemTotal * 100) + (state.DiskUsed / host.DiskTotal * 100)) / 3
},
formatPercent(live, used, total) {
const percent = live ? (parseInt(used / total * 100) || 0) : -1
if (!this.cache[percent]) {
this.cache[percent] = {
class: {
ui: true,
progress: true,
},
style: {
'transition-duration': '300ms',
'min-width': 'unset',
width: percent + '% !important',
},
percent,
}
if (percent < 0) {
this.cache[percent].style['background-color'] = 'slategray'
this.cache[percent].class.offline = true
} else if (percent < 51) {
this.cache[percent].style['background-color'] = '#53B449'
this.cache[percent].class.fine = true
} else if (percent < 81) {
this.cache[percent].style['background-color'] = '#FBB142'
this.cache[percent].class.warning = true
} else {
this.cache[percent].style['background-color'] = '#F23D34'
this.cache[percent].class.error = true
}
}
return this.cache[percent]
},
readableBytes(bytes) {
var i = Math.floor(Math.log(bytes) / Math.log(1024)),
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
return (bytes / Math.pow(1024, i)).toFixed(0) + ' ' + sizes[i];
},
DarkMode() {
const hour = new Date(Date.now()).getHours()
if (hour > 17 || hour < 4) {
document.querySelector("input[name=theme]").checked = true;
document.getElementsByTagName("BODY")[0].setAttribute('data-theme', 'dark');
}
},
secondToDate(s) {
var d = Math.floor(s / 3600 / 24);
if (d > 0) {
return d + "天"
}
var h = Math.floor(s / 3600 % 24);
var m = Math.floor(s / 60 % 60);
var s = Math.floor(s % 60);
return h + ":" + ("0" + m).slice(-2) + ":" + ("0" + s).slice(-2);
},
formatTimestamp(t) {
return new Date(t * 1000).toLocaleString()
},
formatByteSize(bs) {
const x = this.readableBytes(bs)
return x != "NaN undefined" ? x : '0 KB'
}
}
})
const wsProtocol = window.location.protocol == "https:" ? "wss" : "ws"
const ws = new WebSocket(wsProtocol + '://' + window.location.host + '/ws');
ws.onopen = function (evt) {
Swal.fire({
position: 'top',
icon: 'success',
title: '实时通道建立',
text: '可以实时获取最新监控数据啦',
showConfirmButton: false,
timer: 2000
});
}
ws.onmessage = function (evt) {
statusCards.servers = JSON.parse(evt.data)
const keys = Object.keys(statusCards.servers)
for (let i = 0; i < keys.length; i++) {
const ns = statusCards.servers[keys[i]];
if (!ns.Host) ns.live = false
else {
const lastActive = new Date(ns.LastActive).getTime()
if (Date.now() - lastActive > 20 * 1000) {
ns.live = false
} else {
ns.live = true
}
}
}
}
ws.onclose = function () {
Swal.fire({
position: 'top',
icon: 'error',
title: '实时通道断开',
text: '无法实时获取最新监控数据咯',
showConfirmButton: false,
timer: 2000
});
}
}
</script>
</body>
</body>
</html>
{{end}}

View File

@ -7,36 +7,40 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{.Title}}</title>
<link rel="shortcut icon" type="image/png" href="/static/logo.png" />
<link rel="stylesheet" href="/static/theme-daynight/css/service.css?v202101290086" />
<link rel="stylesheet" href="/static/theme-daynight/css/service.css?v202101301768" />
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet" />
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
{{if ts .CustomCode}} {{.CustomCode|safe}} {{end}}
{{if ts .CustomCode}}
{{.CustomCode|safe}}
{{end}}
</head>
<body data-theme="light" data-gridlist="list">
<article>
<header class="nav-bar clearfix">
<figure class="logo"><a href="/">{{.Conf.Site.Brand}}</a></figure>
<div class="icon-container">
<div class="row cf">
<div class="three col">
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span class="line"></span><span class="line"></span></div>
<header>
<section class="nav-bar clearfix">
<figure class="logo"><a href="/">{{.Conf.Site.Brand}}</a></figure>
<div class="icon-container">
<div class="row cf">
<div class="three col">
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span class="line"></span><span class="line"></span></div>
</div>
</div>
</div>
</div>
</div>
<nav class="nav-menu">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/service">服务状态</a></li>
{{if .Admin}}
<li><a href="/server" style="padding: 0.8em; text-align: center">管理后台</a></li>
{{else}}
<li><a href="/login">登录</a></li>
{{end}}
</ul>
</nav>
<nav class="nav-menu">
<ul>
<li><a href="/">首页</a></li>
<li><a href="/service">服务状态</a></li>
{{if .Admin}}
<li><a href="/server" style="padding:.8em;text-align:center;">管理后台</a></li>
{{else}}
<li><a href="/login">登录</a></li>
{{end}}
</ul>
</nav>
</section>
</header>
<main>
@ -69,7 +73,7 @@
{{end}}
</section>
</main>
<div class="sidebar-container">
<ul>
<li><i class="fas fa-sun" title="白昼模式"></i><span>白昼模式</span></li>
@ -92,7 +96,7 @@
</li>
<li>
<label class="switcher">
<input type="checkbox" name="service-grid" id="grid-list" checked />
<input type="checkbox" name="service-grid" id="grid-list" checked/>
<div>
<i class="fas fa-grip-horizontal"></i>
</div>
@ -117,12 +121,13 @@
</div>
</div>
</footer>
<!-- Back to top button -->
<a id="back-to-top"></a>
</article>
<script src="/static/theme-daynight/js/service.js?v202101290086"></script>
<script src="/static/theme-daynight/js/service.js?v202101301768"></script>
</body>
</html>
{{end}}