532 lines
20 KiB
HTML
532 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>首页</title>
|
|
{% include 'system/common/header.html' %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='system/admin/css/other/monitor.css') }}"/>
|
|
</head>
|
|
<body class="pear-container">
|
|
<div class="layui-row layui-col-space10">
|
|
<div class="layui-col-md8">
|
|
<div class="layui-row layui-col-space10">
|
|
<div class="layui-col-md6" id="host-info-card">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">
|
|
主机监控
|
|
</div>
|
|
<div class="layui-card-body">
|
|
<div class="layui-row layui-col-space10">
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">核心数</div>
|
|
<div class="count pear-text" id="cpu_count">-</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">空闲率</div>
|
|
<div class="count pear-text" id="cpu_idle_percent">-%</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">等待率</div>
|
|
<div class="count pear-text" id="cpu_wait_percent">-%</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">使用率</div>
|
|
<div class="count pear-text" id="cpus_percent">-%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">
|
|
内存监控
|
|
</div>
|
|
<div class="layui-card-body">
|
|
<div class="layui-row layui-col-space10">
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">空闲内存</div>
|
|
<div class="count pear-text" id="memory_free">-</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">最大内存</div>
|
|
<div class="count pear-text" id="memory_total">-</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">已用内存</div>
|
|
<div class="count pear-text" id="memory_used">-</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
|
|
<div class="pear-card2">
|
|
<div class="title">内存使用</div>
|
|
<div class="count pear-text" id="memory_usage">-%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md12">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">主机监控</div>
|
|
<div class="layui-card-body">
|
|
<div class="layui-tab custom-tab layui-tab-brief" lay-filter="docDemoTabBrief">
|
|
<div id="echarts-records" style="background-color:#ffffff;min-height:400px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="layui-col-md4">
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">主机信息</div>
|
|
<div class="layui-card-body">
|
|
<table class="layui-table">
|
|
<thead>
|
|
<tr>
|
|
<th>属性</th>
|
|
<th>值</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>名称</td>
|
|
<td id="hostname">{{ hostname }}</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>系统</td>
|
|
<td id="system_version">{{ system_version }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>开机时间</td>
|
|
<td id="boot_time">{{ boot_time }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>运行时长</td>
|
|
<td id="up_time_format">{{ up_time_format }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Python 版本</td>
|
|
<td id="python_version">{{ python_version }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>程序操作</td>
|
|
<td>
|
|
<a href="javascript:kill();"
|
|
class="layui-btn layui-btn-xs layui-btn-primary">关闭程序</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="layui-card">
|
|
<div class="layui-card-header">磁盘信息</div>
|
|
<div class="layui-card-body" id="disk-info-card">
|
|
加载中......
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="tooltip" style="background-color: unset !important;">
|
|
<div class="layui-card" style="box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);">
|
|
<div class="layui-card-body" style="text-align: center" id="tooltip-cpus">
|
|
加载中......
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
{% include 'system/common/footer.html' %}
|
|
<script>
|
|
var systemInfo = null; // 存储获取到的系统信息对象
|
|
|
|
function memoryFormat(memory) {
|
|
if (memory >= 1024 ** 4 * 2) {
|
|
return (memory / 1024 ** 4).toFixed(2) + 'TB';
|
|
} else if (memory >= 1024 ** 3 * 2) {
|
|
return (memory / 1024 ** 3).toFixed(2) + 'GB';
|
|
} else if (memory >= 1024 ** 2 * 2) {
|
|
return (memory / 1024 ** 2).toFixed(2) + 'MB';
|
|
} else if (memory >= 1024 ** 1 * 2) {
|
|
return (memory / 1024 ** 1).toFixed(2) + 'KB';
|
|
} else {
|
|
return memory + 'B';
|
|
}
|
|
}
|
|
|
|
function diskinfo(index) {
|
|
data = systemInfo.disk_partitions_list[index];
|
|
|
|
layui.laytpl(`
|
|
<ul>
|
|
<li>分区类型: <%= d.fstype %></li>
|
|
<li>磁盘大小: <%= memoryFormat(d.total) %></li>
|
|
<li>空闲大小: <%= memoryFormat(d.free) %></li>
|
|
<li>已经使用: <%= memoryFormat(d.used) %> (<%= d.percent %>%)</li>
|
|
</ul>
|
|
`, {
|
|
open: '<%',
|
|
close: '%>'
|
|
}).render(data, function (string) {
|
|
layui.layer.alert(string);
|
|
});
|
|
}
|
|
|
|
function kill() {
|
|
var success = true;
|
|
layui.$.ajax({
|
|
url: "/system/monitor/kill",
|
|
success: function (res) {
|
|
layui.popup.failure(res.msg);
|
|
success = false;
|
|
},
|
|
complete: function (xhr) {
|
|
if (success) layui.popup.success("已发送关闭命令。");
|
|
}
|
|
});
|
|
}
|
|
|
|
layui.use(['layer', 'echarts', 'popup'], function () {
|
|
var $ = layui.jquery,
|
|
echarts = layui.echarts;
|
|
let popup = layui.popup;
|
|
let laytpl = layui.laytpl;
|
|
|
|
var echartsRecords = echarts.init(document.getElementById('echarts-records'), 'walden');
|
|
|
|
|
|
$('#host-info-card').hover(
|
|
function () {
|
|
$('#tooltip').addClass('show');
|
|
|
|
// 获取 #cpus_percent-card 的位置、尺寸和宽度
|
|
const card = $(this);
|
|
const cardOffset = card.offset(); // 元素相对于文档的偏移量
|
|
const cardHeight = card.outerHeight(); // 元素的高度
|
|
const cardWidth = card.outerWidth(); // 元素的宽度
|
|
|
|
// 设置悬浮提示框的宽度和位置
|
|
$('#tooltip').css({
|
|
top: cardOffset.top + cardHeight + 2, // 放在元素下方 5px
|
|
left: cardOffset.left - 5, // 与元素左对齐
|
|
width: cardWidth - 10, // 宽度与元素一致
|
|
});
|
|
},
|
|
function () {
|
|
$('#tooltip').removeClass('show');
|
|
}
|
|
);
|
|
|
|
$("body").on("click", "[data-url]", function () {
|
|
parent.layui.tab.addTabOnlyByElem("content", {
|
|
id: $(this).attr("data-id"),
|
|
title: $(this).attr("data-title"),
|
|
url: $(this).attr("data-url"),
|
|
close: true
|
|
})
|
|
})
|
|
|
|
|
|
let color = [
|
|
"#0090FF",
|
|
"#36CE9E",
|
|
"#FFC005",
|
|
"#FF515A",
|
|
"#8B5CFF",
|
|
"#00CA69"
|
|
];
|
|
|
|
const hexToRgba = (hex, opacity) => {
|
|
let rgbaColor = "";
|
|
let reg = /^#[\da-f]{6}$/i;
|
|
if (reg.test(hex)) {
|
|
rgbaColor =
|
|
`rgba(${parseInt("0x" + hex.slice(1, 3))},${parseInt(
|
|
"0x" + hex.slice(3, 5)
|
|
)},${parseInt("0x" + hex.slice(5, 7))},${opacity})`;
|
|
}
|
|
return rgbaColor;
|
|
}
|
|
|
|
let echartData = [];
|
|
|
|
var option = {
|
|
backgroundColor: 'transparent',
|
|
color: color,
|
|
legend: {
|
|
right: 10,
|
|
top: 10
|
|
},
|
|
tooltip: {
|
|
trigger: "axis",
|
|
axisPointer: {
|
|
type: 'shadow',
|
|
shadowStyle: {
|
|
shadowColor: 'rgba(225,225,225,1)',
|
|
shadowBlur: 5
|
|
}
|
|
}
|
|
},
|
|
grid: {
|
|
backgroundColor: 'transparent',
|
|
top: 100,
|
|
containLabel: true
|
|
},
|
|
xAxis: [{
|
|
type: "category",
|
|
boundaryGap: false,
|
|
axisLabel: {
|
|
formatter: '{value}',
|
|
textStyle: {
|
|
color: "#333"
|
|
}
|
|
},
|
|
axisLine: {
|
|
lineStyle: {
|
|
color: "#D9D9D9"
|
|
}
|
|
},
|
|
data: null
|
|
}],
|
|
yAxis: [{
|
|
type: "value",
|
|
name: '单位:百分比',
|
|
axisLabel: {
|
|
textStyle: {
|
|
color: "#666"
|
|
}
|
|
},
|
|
nameTextStyle: {
|
|
color: "#666",
|
|
fontSize: 12,
|
|
lineHeight: 40
|
|
},
|
|
splitLine: {
|
|
lineStyle: {
|
|
type: "dashed",
|
|
color: "#E9E9E9"
|
|
}
|
|
},
|
|
axisLine: {
|
|
show: false
|
|
},
|
|
axisTick: {
|
|
show: false
|
|
}
|
|
}],
|
|
series: [{
|
|
name: "CPU",
|
|
type: "line",
|
|
smooth: true,
|
|
symbolSize: 8,
|
|
zlevel: 3,
|
|
lineStyle: {
|
|
normal: {
|
|
color: color[0],
|
|
shadowBlur: 3,
|
|
shadowColor: hexToRgba(color[0], 0.5),
|
|
shadowOffsetY: 8
|
|
}
|
|
},
|
|
areaStyle: {
|
|
normal: {
|
|
color: new echarts.graphic.LinearGradient(
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
[{
|
|
offset: 0,
|
|
color: hexToRgba(color[0], 0.3)
|
|
},
|
|
{
|
|
offset: 1,
|
|
color: hexToRgba(color[0], 0.1)
|
|
}
|
|
],
|
|
false
|
|
),
|
|
shadowColor: hexToRgba(color[0], 0.1),
|
|
shadowBlur: 10
|
|
}
|
|
},
|
|
data: null
|
|
}, {
|
|
name: '内存',
|
|
type: "line",
|
|
smooth: true,
|
|
symbolSize: 8,
|
|
zlevel: 3,
|
|
lineStyle: {
|
|
normal: {
|
|
color: color[1],
|
|
shadowBlur: 3,
|
|
shadowColor: hexToRgba(color[1], 0.5),
|
|
shadowOffsetY: 8
|
|
}
|
|
},
|
|
areaStyle: {
|
|
normal: {
|
|
color: new echarts.graphic.LinearGradient(
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
[{
|
|
offset: 0,
|
|
color: hexToRgba(color[1], 0.3)
|
|
},
|
|
{
|
|
offset: 1,
|
|
color: hexToRgba(color[1], 0.1)
|
|
}
|
|
],
|
|
false
|
|
),
|
|
shadowColor: hexToRgba(color[1], 0.1),
|
|
shadowBlur: 10
|
|
}
|
|
},
|
|
data: null
|
|
}]
|
|
};
|
|
|
|
echartsRecords.setOption(option);
|
|
|
|
window.onresize = function () {
|
|
echartsRecords.resize();
|
|
};
|
|
|
|
ajaxPolling();
|
|
setInterval(ajaxPolling, 1000 * 5);
|
|
|
|
function ajaxPolling() {
|
|
$.ajax({
|
|
url: "/system/monitor/polling",
|
|
success: function (result) {
|
|
data = result.data;
|
|
systemInfo = data;
|
|
|
|
|
|
// 更新使用率等信息
|
|
document.querySelector("#cpu_count").innerText = data.cpu_count;
|
|
document.querySelector("#cpus_percent").innerText = data.cpus_percent + "%";
|
|
document.querySelector("#cpu_idle_percent").innerText = data.cpu_idle_percent + "%";
|
|
document.querySelector("#cpu_wait_percent").innerText = data.cpu_wait_percent + "%";
|
|
|
|
document.querySelector("#memory_used").innerText = memoryFormat(data.memory_used);
|
|
document.querySelector("#memory_total").innerText = memoryFormat(data.memory_total);
|
|
document.querySelector("#memory_free").innerText = memoryFormat(data.memory_free);
|
|
document.querySelector("#memory_usage").innerText = data.memory_usage + "%";
|
|
|
|
// 基本信息
|
|
document.querySelector("#hostname").innerText = data.basic_info.hostname;
|
|
document.querySelector("#system_version").innerText = data.basic_info.system_version;
|
|
document.querySelector("#boot_time").innerText = data.basic_info.boot_time;
|
|
document.querySelector("#up_time_format").innerText = data.basic_info.up_time_format;
|
|
document.querySelector("#python_version").innerText = data.basic_info.python_version;
|
|
|
|
|
|
// 更新每一个CPU使用率
|
|
laytpl(`
|
|
<ul>
|
|
<%# layui.each(d, function(index, data){ %>
|
|
<li>
|
|
<span class="layui-badge layui-bg-blue">CPU <%= data[0] %>: <%= data[1] %>%</span>
|
|
</li>
|
|
<%# }); %>
|
|
</ul>
|
|
`, {
|
|
open: '<%',
|
|
close: '%>'
|
|
}).render(data.cpu_percent_per_core, function (string) {
|
|
document.querySelector("#tooltip-cpus").innerHTML = string;
|
|
});
|
|
|
|
|
|
// 更新硬盘信息
|
|
laytpl(`
|
|
<fieldset class="layui-elem-field layui-field-title"></fieldset>
|
|
<%# layui.each(d, function(index, data){ %>
|
|
<div class="layui-row" style="display: flex; align-items: center;">
|
|
<div class="progress-ring" style="margin-right: 50px;">
|
|
<svg class="circle" width="120" height="120" viewBox="0 0 120 120">
|
|
<circle class="circle-bg" cx="60" cy="60" r="54"/>
|
|
<circle class="circle-progress" cx="60" cy="60" r="54" style="--progress: <%= data.percent %>"/>
|
|
</svg>
|
|
<div class="progress-text"><%= data.device %></div>
|
|
</div>
|
|
<div class="layui-col-space10" style="display: flex; align-items: center;">
|
|
<ul>
|
|
<li>分区类型: <%= data.fstype %></li>
|
|
<li>磁盘大小: <%= memoryFormat(data.total) %></li>
|
|
<li>空闲大小: <%= memoryFormat(data.free) %></li>
|
|
<li>已经使用: <%= memoryFormat(data.used) %> (<%= data.percent %>%)</li>
|
|
<li>
|
|
<a href="javascript:diskinfo(<%= index %>)" data-id="1"
|
|
class="layui-btn layui-btn-xs layui-btn-primary pear-reply">查看详情
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<fieldset class="layui-elem-field layui-field-title"></fieldset>
|
|
<%# }) %>
|
|
`, {
|
|
open: '<%',
|
|
close: '%>'
|
|
}).render(data.disk_partitions_list, function (string) {
|
|
document.querySelector("#disk-info-card").innerHTML = string;
|
|
});
|
|
|
|
|
|
// 更新图表
|
|
echartData.push({
|
|
name: data.time_now,
|
|
cpu_percent: data.cpus_percent,
|
|
memory_percent: data.memory_usage
|
|
});
|
|
|
|
if (echartData.length > 8) {
|
|
echartData.shift();
|
|
}
|
|
|
|
xAxisData = echartData.map(v => v.name);
|
|
yAxisData1 = echartData.map(v => v.cpu_percent);
|
|
yAxisData2 = echartData.map(v => v.memory_percent);
|
|
|
|
option.xAxis[0].data = xAxisData;
|
|
option.series[0].data = yAxisData1;
|
|
option.series[1].data = yAxisData2;
|
|
|
|
echartsRecords.setOption(option);
|
|
|
|
},
|
|
error: function (xhr, type, errorThrown) {
|
|
}
|
|
})
|
|
|
|
}
|
|
|
|
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |