美化三网延迟界面 (#335)

* Update network.html

修复以下问题:
- 延迟默认最高300ms,超过后默认抹平
- 曲线上有很多ping值为0的无效散点,导致毛刺很多,干扰效果
- 图标的y轴比例失调,上方大片留白,大大降低了有效显示区域
- 默认只显示最近不到半小时左右的延迟表现,想看全天需要拖动,影响效果
- 曲线不显示极大极小值,不够直观

* Update config.go

修复了以下问题:
- 延迟默认最高300ms,超过后默认抹平
- 曲线上有很多ping值为0的无效散点,导致毛刺很多,干扰效果
- 图标的y轴比例失调,上方大片留白,大大降低了有效显示区域
- 默认只显示最近不到半小时左右的延迟表现,想看全天需要拖动,影响效果
- 曲线不显示极大极小值,不够直观

* Update network.html

美化了三网延迟界面:
1. 将Marker缩小降低曲线遮挡
2. 设置为曲线对应的颜色使其更加直观
3. 设置Marker透明度降低对画面的影响
4. 将延迟极小值的Marker倒置显示以快速区别极大值
5. 将超过MaxTCPPingValue的点删除
6. 显示丢包分布(细线),以及服务器断流区间(粗线)

* Update network.html

* Update network.html

* Update network.html

* Update network.html
This commit is contained in:
xykt 2024-03-24 13:33:19 +08:00 committed by GitHub
parent 7d85c4c4a5
commit 3a733c85ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 331 additions and 146 deletions

View File

@ -113,15 +113,14 @@
if (MaxTCPPingValue == null) { if (MaxTCPPingValue == null) {
MaxTCPPingValue = 1000; MaxTCPPingValue = 1000;
} }
// 基于准备好的dom初始化echarts实例 new Vue({
var myChart = echarts.init(document.getElementById('monitor-info-container')); el: '#app',
// 使用刚指定的配置项和数据显示图表。
var statusCards = new Vue({
el: '#network',
delimiters: ['@#', '#@'], delimiters: ['@#', '#@'],
data: { data: {
page: 'network',
defaultTemplate: {{.Conf.Site.Theme}},
templates: {{.Themes}},
servers: initData, servers: initData,
cache: [],
option: { option: {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
@ -150,6 +149,11 @@
fontSize: 14 fontSize: 14
} }
}, },
grid: {
left: '8%',
right: '8%',
},
backgroundColor: 'rgba(255, 255, 255, 0.8)',
toolbox: { toolbox: {
feature: { feature: {
dataZoom: { dataZoom: {
@ -161,7 +165,7 @@
}, },
dataZoom: [ dataZoom: [
{ {
start: 94, start: 0,
end: 100 end: 100
} }
], ],
@ -171,13 +175,15 @@
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
boundaryGap: [0, '100%'] boundaryGap: false
}, },
series: [], series: [],
}
}, },
chartOnOff: true,
},
mixins: [mixinsVue],
mounted() { mounted() {
this.DarkMode(); this.renderChart();
this.parseMonitorInfo(monitorInfo); this.parseMonitorInfo(monitorInfo);
window.addEventListener('resize', this.resizeHandle); window.addEventListener('resize', this.resizeHandle);
}, },
@ -185,18 +191,67 @@
window.removeEventListener('resize', this.resizeHandle) window.removeEventListener('resize', this.resizeHandle)
}, },
methods: { methods: {
DarkMode() { getFontLogoClass(str) {
const hour = new Date(Date.now()).getHours() if (["almalinux",
if (hour > 17 || hour < 4) { "alpine",
document.querySelector("input[name=theme]").checked = true; "aosc",
document.getElementsByTagName("BODY")[0].setAttribute('data-theme', 'dark'); "apple",
document.getElementById("monitor-info-container").style.backgroundColor = "#1E1E1E"; "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) { redirectNetwork(id) {
this.getMonitorHistory(id) this.getMonitorHistory(id)
.then(function(monitorInfo) { .then(function(monitorInfo) {
var vm = network.__vue__; var vm = app.__vue__;
vm.parseMonitorInfo(monitorInfo); vm.parseMonitorInfo(monitorInfo);
}) })
.catch(function(error){ .catch(function(error){
@ -212,17 +267,37 @@
parseMonitorInfo(monitorInfo) { parseMonitorInfo(monitorInfo) {
let tSeries = []; let tSeries = [];
let tLegendData = []; let tLegendData = [];
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
let maxPing = 0;
for (let i = 0; i < monitorInfo.result.length; i++) { for (let i = 0; i < monitorInfo.result.length; i++) {
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
maxPing = avgDelay;
}
}
}
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 loss = 0;
let data = []; let data = [];
let datal = [];
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) { for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
avgDelay = monitorInfo.result[i].avg_delay[j]; avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
if (avgDelay > 0.9 * MaxTCPPingValue) { if (avgDelay > 0 && avgDelay < MaxTCPPingValue) {
loss += 1
}
data.push([monitorInfo.result[i].created_at[j], avgDelay]); data.push([monitorInfo.result[i].created_at[j], avgDelay]);
} }
else {
loss += 1;
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
}
}
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1); lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
if (lossRate > 99) {
datal = [];
}
legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%"; legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
tLegendData.push(legendName); tLegendData.push(legendName);
tSeries.push({ tSeries.push({
@ -230,24 +305,50 @@
type: 'line', type: 'line',
smooth: true, smooth: true,
symbol: 'none', symbol: 'none',
data: data data: data,
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 }
]
}
});
tSeries.push({
name: legendName,
type: 'bar',
smooth: true,
symbol: 'none',
data: datal,
itemStyle: { color: rgbaColorBar }
}); });
} }
this.option.title.text = monitorInfo.result[0].server_name; this.option.title.text = monitorInfo.result[0].server_name;
this.option.series = tSeries; this.option.series = tSeries;
this.option.legend.data = tLegendData; this.option.legend.data = tLegendData;
const hour = new Date(Date.now()).getHours() this.myChart.clear();
if (hour > 17 || hour < 4) { this.myChart.setOption(this.option);
this.option.legend.textStyle.color = "#F1F1F2"; },
this.option.title.textStyle.color = "#ccc"; this.option.title.text = monitorInfo.result[0].server_name;
} this.option.series = tSeries;
myChart.clear(); this.option.legend.data = tLegendData;
myChart.setOption(this.option); 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);
}, },
resizeHandle () { resizeHandle () {
this.myChart.resize(); this.myChart.resize();
}, },
} },
beforeDestroy() {
this.myChart.dispose();
this.myChart = null;
},
}); });
</script> </script>
</body> </body>

View File

@ -185,19 +185,37 @@
parseMonitorInfo(monitorInfo) { parseMonitorInfo(monitorInfo) {
let tSeries = []; let tSeries = [];
let tLegendData = []; let tLegendData = [];
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
let maxPing = 0;
for (let i = 0; i < monitorInfo.result.length; i++) { 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++) { for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]); avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
if (avgDelay > 0.9 * MaxTCPPingValue) { if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
loss += 1 maxPing = avgDelay;
} }
if (avgDelay > 0) { }
}
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]); data.push([monitorInfo.result[i].created_at[j], avgDelay]);
} }
else {
loss += 1;
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
}
} }
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1); lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
if (lossRate > 99) {
datal = [];
}
legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%"; legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
tLegendData.push(legendName); tLegendData.push(legendName);
tSeries.push({ tSeries.push({
@ -208,17 +226,31 @@
data: data, data: data,
markPoint: { markPoint: {
data: [ data: [
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: '#f00' } }, { type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
{ type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: '#0f0' } } { type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 }
] ]
} }
}); });
tSeries.push({
name: legendName,
type: 'bar',
smooth: true,
symbol: 'none',
data: datal,
itemStyle: { color: rgbaColorBar }
});
} }
this.option.title.text = monitorInfo.result[0].server_name; this.option.title.text = monitorInfo.result[0].server_name;
this.option.series = tSeries; this.option.series = tSeries;
this.option.legend.data = tLegendData; this.option.legend.data = tLegendData;
this.myChart.clear(); this.myChart.clear();
this.myChart.setOption(this.option); this.myChart.setOption(this.option);
},
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) { isWindowsPlatform(str) {
return str.includes('Windows') return str.includes('Windows')

View File

@ -208,19 +208,37 @@
parseMonitorInfo(monitorInfo) { parseMonitorInfo(monitorInfo) {
let tSeries = []; let tSeries = [];
let tLegendData = []; let tLegendData = [];
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
let maxPing = 0;
for (let i = 0; i < monitorInfo.result.length; i++) { 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++) { for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]); avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
if (avgDelay > 0.9 * MaxTCPPingValue) { if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
loss += 1 maxPing = avgDelay;
} }
if (avgDelay > 0) { }
}
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]); data.push([monitorInfo.result[i].created_at[j], avgDelay]);
} }
else {
loss += 1;
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
}
} }
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1); lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
if (lossRate > 99) {
datal = [];
}
legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%"; legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
tLegendData.push(legendName); tLegendData.push(legendName);
tSeries.push({ tSeries.push({
@ -231,11 +249,19 @@
data: data, data: data,
markPoint: { markPoint: {
data: [ data: [
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: '#f00' } }, { type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
{ type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: '#0f0' } } { type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 }
] ]
} }
}); });
tSeries.push({
name: legendName,
type: 'bar',
smooth: true,
symbol: 'none',
data: datal,
itemStyle: { color: rgbaColorBar }
});
} }
this.option.title.text = monitorInfo.result[0].server_name; this.option.title.text = monitorInfo.result[0].server_name;
this.option.series = tSeries; this.option.series = tSeries;

View File

@ -171,19 +171,37 @@
parseMonitorInfo(monitorInfo) { parseMonitorInfo(monitorInfo) {
let tSeries = []; let tSeries = [];
let tLegendData = []; let tLegendData = [];
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
let maxPing = 0;
for (let i = 0; i < monitorInfo.result.length; i++) { 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++) { for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]); avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
if (avgDelay > 0.9 * MaxTCPPingValue) { if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
loss += 1 maxPing = avgDelay;
} }
if (avgDelay > 0) { }
}
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]); data.push([monitorInfo.result[i].created_at[j], avgDelay]);
} }
else {
loss += 1;
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
}
} }
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1); lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
if (lossRate > 99) {
datal = [];
}
legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%"; legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
tLegendData.push(legendName); tLegendData.push(legendName);
tSeries.push({ tSeries.push({
@ -194,11 +212,19 @@
data: data, data: data,
markPoint: { markPoint: {
data: [ data: [
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: '#f00' } }, { type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
{ type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: '#0f0' } } { type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 }
] ]
} }
}); });
tSeries.push({
name: legendName,
type: 'bar',
smooth: true,
symbol: 'none',
data: datal,
itemStyle: { color: rgbaColorBar }
});
} }
this.option.title.text = monitorInfo.result[0].server_name; this.option.title.text = monitorInfo.result[0].server_name;
this.option.series = tSeries; this.option.series = tSeries;