增加了网络页面对 Neko Meui 主题的支持 (#322)
* 修改 Neko-mdui 主题的菜单栏 增加了“网络”选项卡 * 增加 Neko-mdui 主题的网络页面
This commit is contained in:
		
							parent
							
								
									dbfea9a00b
								
							
						
					
					
						commit
						00041c0ebd
					
				
							
								
								
									
										1
									
								
								resource/template/theme-mdui/menu.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								resource/template/theme-mdui/menu.html
									
									
									
									
										vendored
									
									
								
							@ -12,6 +12,7 @@
 | 
			
		||||
      {{else}}
 | 
			
		||||
      <a href="/" class='mdui-ripple mdui-ripple-white mdui-hoverable{{if eq .MatchedPath "/"}} mdui-tab-active{{end}}'><i class="mdui-icon material-icons">home</i>{{tr "Home"}}</a>
 | 
			
		||||
      <a href="/service" class='mdui-ripple mdui-ripple-white mdui-hoverable{{if eq .MatchedPath "/service"}} mdui-tab-active{{end}}'><i class="mdui-icon material-icons">accessibility</i>{{tr "Services"}}</a>
 | 
			
		||||
      <a href="/network" class='mdui-ripple mdui-ripple-white mdui-hoverable{{if eq .MatchedPath "/network"}} mdui-tab-active{{end}}'><i class="mdui-icon material-icons">network_check</i>{{tr "NetworkSpiter"}}</a>
 | 
			
		||||
      {{end}}
 | 
			
		||||
      <div class="mdui-toolbar-spacer"></div>
 | 
			
		||||
      {{if .Admin}}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										255
									
								
								resource/template/theme-mdui/network.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								resource/template/theme-mdui/network.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,255 @@
 | 
			
		||||
{{define "theme-mdui/network"}}
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html lang="{{.Conf.Language}}">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="utf-8">
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
 | 
			
		||||
  <title>{{.Title}}</title>
 | 
			
		||||
  <link rel="shortcut icon" type="image/png" href="/static/logo.svg?v20210804" />
 | 
			
		||||
 | 
			
		||||
  <!-- MDUI CSS -->
 | 
			
		||||
  <link rel="stylesheet" href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/mdui/1.0.2/css/mdui.min.css"/>
 | 
			
		||||
  <link rel="stylesheet" href="/static/theme-mdui/mdui.css" type="text/css">
 | 
			
		||||
  <style>
 | 
			
		||||
	.mdui-table td, .mdui-table th{padding: 6px;}
 | 
			
		||||
	.progress{width: 10%;min-width: 75px;}
 | 
			
		||||
	.progress-text{font-size: 16px;font-weight: 800;position: relative;top: 4px;left: 6px;}
 | 
			
		||||
	.offline st,.offline at,.offline gt,.offline .progress-text{color: grey;}
 | 
			
		||||
	a{text-decoration:none;color:#333;}.mdui-theme-layout-dark a{color:#fff;}
 | 
			
		||||
  </style>
 | 
			
		||||
  {{if ts .CustomCode}}
 | 
			
		||||
  {{.CustomCode|safe}}
 | 
			
		||||
  {{end}}
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
{{template "theme-mdui/menu" .}}
 | 
			
		||||
<div class="nb-container" id="app">
 | 
			
		||||
    <div class="ui container">
 | 
			
		||||
        <div class="service-status">
 | 
			
		||||
            <table class="ui celled table">
 | 
			
		||||
                <button
 | 
			
		||||
                    v-for="server in servers"
 | 
			
		||||
                    @click="redirectNetwork(server.ID)"
 | 
			
		||||
                    class="mdui-btn mdui-btn-raised mdui-color-theme mdui-color-indigo mdui-text-color-white"
 | 
			
		||||
                    style="margin-top: 6px;margin-left:5px">
 | 
			
		||||
                    <img :src="'https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/flag-icon-css/4.1.5/flags/4x3/' + (server.Host.CountryCode?server.Host.CountryCode:'cn') + '.svg'" alt="Flag Icon" style="vertical-align: middle;height:14px"> <span>@#server.Name#@  </span></button>
 | 
			
		||||
            </table>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="ui container" style="max-width: 95vw">
 | 
			
		||||
        <div ref="chartDom" style="border-radius: 28px; margin-top: 15px;height: 520px;max-width: 1400px;overflow: hidden"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{{template "theme-mdui/footer" .}}
 | 
			
		||||
  <script src="/static/theme-mdui/mdui.js"></script>
 | 
			
		||||
  <script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/mdui/1.0.2/js/mdui.min.js"></script>
 | 
			
		||||
  <script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/jquery/3.6.0/jquery.min.js"></script>
 | 
			
		||||
  <script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
 | 
			
		||||
 
 | 
			
		||||
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/echarts/5.3.0-rc.1/echarts.min.js"></script>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
    const monitorInfo =  JSON.parse('{{.MonitorInfos}}');
 | 
			
		||||
    const initData = JSON.parse('{{.Servers}}').servers;
 | 
			
		||||
    let MaxTCPPingValue = {{.MaxTCPPingValue}};
 | 
			
		||||
    if (MaxTCPPingValue == null) {
 | 
			
		||||
        MaxTCPPingValue = 1000;
 | 
			
		||||
    }
 | 
			
		||||
    new Vue({
 | 
			
		||||
        el: '#app',
 | 
			
		||||
        delimiters: ['@#', '#@'],
 | 
			
		||||
        data: {
 | 
			
		||||
            servers: initData,
 | 
			
		||||
            option: {
 | 
			
		||||
                tooltip: {
 | 
			
		||||
                    trigger: 'axis',
 | 
			
		||||
                    position: function (pt) {
 | 
			
		||||
                        return [pt[0], '10%'];
 | 
			
		||||
                    },
 | 
			
		||||
                    formatter: function(params){
 | 
			
		||||
                        let result = params[0].axisValueLabel + "<br />";
 | 
			
		||||
                        params.forEach(function(item){
 | 
			
		||||
                            result += item.marker + item.seriesName + ": " + item.value[1].toFixed(2) + " ms<br />";
 | 
			
		||||
                         })
 | 
			
		||||
                        return result;
 | 
			
		||||
                    },
 | 
			
		||||
                    confine: true,
 | 
			
		||||
                    transitionDuration: 0
 | 
			
		||||
                },
 | 
			
		||||
                title: {
 | 
			
		||||
                    left: 'center',
 | 
			
		||||
                    text: "",
 | 
			
		||||
                    textStyle: {}
 | 
			
		||||
                },
 | 
			
		||||
                legend: {
 | 
			
		||||
                    top: '5%',
 | 
			
		||||
                    data: [],
 | 
			
		||||
                    textStyle: {
 | 
			
		||||
                        fontSize: 14
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                backgroundColor: 'rgba(255, 255, 255, 0.8)',
 | 
			
		||||
                toolbox: {
 | 
			
		||||
                    feature: {
 | 
			
		||||
                        dataZoom: {
 | 
			
		||||
                            yAxisIndex: 'none'
 | 
			
		||||
                        },
 | 
			
		||||
                        restore: {},
 | 
			
		||||
                        saveAsImage: {}
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                dataZoom: [
 | 
			
		||||
                    {
 | 
			
		||||
                        start: 0,
 | 
			
		||||
                        end: 100
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                xAxis: {
 | 
			
		||||
                    type: 'time',
 | 
			
		||||
                    boundaryGap: false
 | 
			
		||||
                },
 | 
			
		||||
                yAxis: {
 | 
			
		||||
                    type: 'value',
 | 
			
		||||
                    boundaryGap: false
 | 
			
		||||
                },
 | 
			
		||||
                series: [],
 | 
			
		||||
            },
 | 
			
		||||
            chartOnOff: true,
 | 
			
		||||
        },
 | 
			
		||||
        mounted() {
 | 
			
		||||
            this.renderChart();
 | 
			
		||||
             this.parseMonitorInfo(monitorInfo);
 | 
			
		||||
        },
 | 
			
		||||
        methods: {
 | 
			
		||||
            getFontLogoClass(str) {
 | 
			
		||||
                if (["almalinux",
 | 
			
		||||
                        "alpine",
 | 
			
		||||
                        "aosc",
 | 
			
		||||
                        "apple",
 | 
			
		||||
                        "archlinux",
 | 
			
		||||
                        "archlabs",
 | 
			
		||||
                        "artix",
 | 
			
		||||
                        "budgie",
 | 
			
		||||
                        "centos",
 | 
			
		||||
                        "coreos",
 | 
			
		||||
                        "debian",
 | 
			
		||||
                        "deepin",
 | 
			
		||||
                        "devuan",
 | 
			
		||||
                        "docker",
 | 
			
		||||
                        "elementary",
 | 
			
		||||
                        "fedora",
 | 
			
		||||
                        "ferris",
 | 
			
		||||
                        "flathub",
 | 
			
		||||
                        "freebsd",
 | 
			
		||||
                        "gentoo",
 | 
			
		||||
                        "gnu-guix",
 | 
			
		||||
                        "illumos",
 | 
			
		||||
                        "kali-linux",
 | 
			
		||||
                        "linuxmint",
 | 
			
		||||
                        "mageia",
 | 
			
		||||
                        "mandriva",
 | 
			
		||||
                        "manjaro",
 | 
			
		||||
                        "nixos",
 | 
			
		||||
                        "openbsd",
 | 
			
		||||
                        "opensuse",
 | 
			
		||||
                        "pop-os",
 | 
			
		||||
                        "raspberry-pi",
 | 
			
		||||
                        "redhat",
 | 
			
		||||
                        "rocky-linux",
 | 
			
		||||
                        "sabayon",
 | 
			
		||||
                        "slackware",
 | 
			
		||||
                        "snappy",
 | 
			
		||||
                        "solus",
 | 
			
		||||
                        "tux",
 | 
			
		||||
                        "ubuntu",
 | 
			
		||||
                        "void",
 | 
			
		||||
                        "zorin"].indexOf(str)
 | 
			
		||||
                    > -1) {
 | 
			
		||||
                    return str;
 | 
			
		||||
                }
 | 
			
		||||
                if (['openwrt', 'linux', "immortalwrt"].indexOf(str) > -1) {
 | 
			
		||||
                    return 'tux';
 | 
			
		||||
                }
 | 
			
		||||
                if (str == 'amazon') {
 | 
			
		||||
                    return 'redhat';
 | 
			
		||||
                }
 | 
			
		||||
                if (str == 'arch') {
 | 
			
		||||
                    return 'archlinux';
 | 
			
		||||
                }
 | 
			
		||||
                return '';
 | 
			
		||||
            },
 | 
			
		||||
            redirectNetwork(id) {
 | 
			
		||||
                    this.getMonitorHistory(id)
 | 
			
		||||
                    .then(function(monitorInfo) {
 | 
			
		||||
                          var vm = app.__vue__;
 | 
			
		||||
                          vm.parseMonitorInfo(monitorInfo);
 | 
			
		||||
                    })
 | 
			
		||||
                    .catch(function(error){
 | 
			
		||||
                        window.location.href = "/404";
 | 
			
		||||
                    })
 | 
			
		||||
                },
 | 
			
		||||
            getMonitorHistory(id) {
 | 
			
		||||
                  return $.ajax({
 | 
			
		||||
                    url: "/api/v1/monitor/"+id,
 | 
			
		||||
                    method: "GET"
 | 
			
		||||
                  });
 | 
			
		||||
            },
 | 
			
		||||
            parseMonitorInfo(monitorInfo) {
 | 
			
		||||
                let tSeries = [];
 | 
			
		||||
                let tLegendData = [];
 | 
			
		||||
                for (let i = 0; i < monitorInfo.result.length; i++) {
 | 
			
		||||
                    let loss = 0;
 | 
			
		||||
                    let data = [];
 | 
			
		||||
                    for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
 | 
			
		||||
                        avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
 | 
			
		||||
                        if (avgDelay > 0.9 * MaxTCPPingValue) {
 | 
			
		||||
                            loss += 1
 | 
			
		||||
                        }
 | 
			
		||||
                        if (avgDelay > 0) {
 | 
			
		||||
                            data.push([monitorInfo.result[i].created_at[j], avgDelay]);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
 | 
			
		||||
                    legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
 | 
			
		||||
                    tLegendData.push(legendName);
 | 
			
		||||
                    tSeries.push({
 | 
			
		||||
                            name: legendName,
 | 
			
		||||
                            type: 'line',
 | 
			
		||||
                            smooth: true,
 | 
			
		||||
                            symbol: 'none',
 | 
			
		||||
                            data: data,
 | 
			
		||||
                            markPoint: {
 | 
			
		||||
                            data: [
 | 
			
		||||
                                    { type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: '#f00' } },
 | 
			
		||||
                                    { type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: '#0f0' } }
 | 
			
		||||
                                ]
 | 
			
		||||
                            }
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
                this.option.title.text = monitorInfo.result[0].server_name;
 | 
			
		||||
                this.option.series = tSeries;
 | 
			
		||||
                this.option.legend.data = tLegendData;
 | 
			
		||||
                this.myChart.clear();
 | 
			
		||||
                this.myChart.setOption(this.option);
 | 
			
		||||
            },
 | 
			
		||||
            isWindowsPlatform(str) {
 | 
			
		||||
                return str.includes('Windows')
 | 
			
		||||
            },
 | 
			
		||||
            renderChart() {
 | 
			
		||||
              this.myChart = echarts.init(this.$refs.chartDom);
 | 
			
		||||
              this.myChart.setOption(this.option);
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        beforeDestroy() {
 | 
			
		||||
            this.myChart.dispose();
 | 
			
		||||
            this.myChart = null;
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
{{end}}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user