{{define "theme-server-status/network"}} {{template "theme-server-status/header" .}} <div id="app"> {{template "theme-server-status/content-nav" .}} <div class="container table-responsive content" style="max-width: 95vw"> <table class="table table-striped table-condensed table-hover"> <button class="ui nezha-primary-btn button" v-for="server in servers" style="margin-top: 3px" @click="redirectNetwork(server.ID)"> @#server.Name#@ <i :class="'fi fi-' + server.Host.CountryCode"></i><span class="node-cell-location-text text-uppercase"> @#server.Host.CountryCode#@</span> </button> </table> </div> <div class="container table-responsive content" style="max-width: 95vw"> <div ref="chartDom" style="border-radius: 28px; margin-top: 15px;height: 520px;max-width: 1400px;overflow: hidden"></div> </div> {{template "theme-server-status/content-footer" .}} </div> <script> const monitorInfo = JSON.parse('{{.MonitorInfos}}'); const initData = JSON.parse('{{.Servers}}').servers; let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}}; new Vue({ el: '#app', delimiters: ['@#', '#@'], data: { page: 'network', defaultTemplate: {{.Conf.Site.Theme}}, templates: {{.Themes}}, 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, }, mixins: [mixinsVue], 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 = []; var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']; for (let i = 0; i < monitorInfo.result.length; i++) { var lcolor = lcolors[i % lcolors.length]; var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)'; var rgbaColorBar = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.35)'; let loss = 0; let data = []; let datal = []; for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) { avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]); if (avgDelay > 0 && avgDelay < MaxTCPPingValue) { data.push([monitorInfo.result[i].created_at[j], avgDelay]); } else { loss += 1; datal.push({ xAxis: monitorInfo.result[i].created_at[j], label: { show: false }, emphasis: { disabled: true }, lineStyle: { type: "solid", color: rgbaColorBar } }); } } lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1); if (lossRate > 99) { datal = []; } legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%"; tLegendData.push(legendName); tSeries.push({ name: legendName, type: 'line', smooth: true, symbol: 'none', data: data, markLine: { symbol: "none", symbolSize :0, data: datal }, markPoint: { data: [ { type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } }, { type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 } ] } }); } 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> {{template "theme-server-status/footer" .}} {{end}}