Files
aler_dashboard_git/alert_dashboard/www/disk.html
T
2026-07-07 13:29:22 +08:00

247 lines
6.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>服务器磁盘目录容量监控 | Dashboard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft YaHei", system-ui, -apple-system, sans-serif;
}
body {
background-color: #f4f7fa;
padding: 24px;
color: #2d3748;
}
.dashboard-card {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 2px 16px rgba(0, 30, 80, 0.08);
padding: 24px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 16px;
flex-wrap: wrap;
gap:16px;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #1a202c;
}
.card-desc {
font-size: 13px;
color: #718096;
margin-top: 4px;
}
.filter-box{
display:flex;
align-items:center;
gap:10px;
}
.filter-box label{
font-size:14px;
}
#ipSelect{
padding:6px 10px;
border:1px solid #cbd5e0;
border-radius:6px;
font-size:14px;
min-width:200px;
}
#exportBtn{
padding:6px 14px;
background:#2b6cb0;
color:#fff;
border:none;
border-radius:6px;
cursor:pointer;
font-size:14px;
}
#exportBtn:hover{
background:#2c5282;
}
table {
width: 100%;
border-collapse: collapse;
margin-top:10px;
}
thead tr {
background-color: #2b6cb0;
color: #fff;
}
th, td {
padding: 14px 16px;
text-align: left;
font-size: 14px;
}
th {
font-weight: 500;
}
tbody tr {
border-bottom: 1px solid #edf2f7;
transition: background 0.2s;
}
tbody tr:hover {
background-color: #f7fafc;
}
.num-big {
color: #c53030;
font-weight: 500;
}
.loading {
text-align: center;
padding: 40px;
color: #718096;
}
</style>
</head>
<body>
<div class="dashboard-card">
<div class="card-header">
<div>
<h2 class="card-title">用户目录磁盘占用统计</h2>
<div class="card-desc">多服务器 /serverhome 目录容量实时采集,支持按实例IP筛选、导出表格</div>
</div>
<div class="filter-box">
<label>筛选实例IP</label>
<select id="ipSelect">
<option value="all">全部实例</option>
</select>
<button id="exportBtn">导出当前表格CSV</button>
</div>
</div>
<table>
<thead>
<tr>
<th>实例IP</th>
<th>用户名</th>
<th>目录路径</th>
<th>占用容量</th>
</tr>
</thead>
<tbody id="diskTableBody">
<tr>
<td colspan="4" class="loading">数据加载中...</td>
</tr>
</tbody>
</table>
</div>
<script>
let sourceData = [];
let currentFilterIp = "all";
const ipSelect = document.getElementById('ipSelect');
const tbody = document.getElementById('diskTableBody');
const exportBtn = document.getElementById('exportBtn');
// 拉取全量数据
fetch('/api/df.php', {
headers: {
"Accept": "application/json;charset=utf-8"
}
})
.then(res => res.json())
.then(ret => {
if(ret.code !== 0){
tbody.innerHTML = `<tr><td colspan="4" class="loading">接口异常:${ret.msg}</td></tr>`;
return;
}
sourceData = ret.list;
if(sourceData.length === 0){
tbody.innerHTML = `<tr><td colspan="4" class="loading">暂无磁盘指标数据</td></tr>`;
return;
}
// 提取所有不重复IP写入下拉框
const ipSet = new Set();
sourceData.forEach(item=>ipSet.add(item.instance_ip));
ipSet.forEach(ip=>{
let opt = document.createElement('option');
opt.value = ip;
opt.innerText = ip;
ipSelect.appendChild(opt);
})
// 初始渲染全部
renderTable("all");
})
.catch(err => {
tbody.innerHTML = `<tr><td colspan="4" class="loading">接口请求失败:${err}</td></tr>`;
})
// 筛选切换事件
ipSelect.addEventListener('change', function(){
currentFilterIp = this.value;
renderTable(currentFilterIp);
})
// 渲染表格
function renderTable(filterIp){
tbody.innerHTML = "";
let showList = [];
if(filterIp === "all"){
showList = sourceData;
}else{
showList = sourceData.filter(item=>item.instance_ip === filterIp);
}
if(showList.length === 0){
tbody.innerHTML = `<tr><td colspan="4" class="loading">该实例下无目录数据</td></tr>`;
return;
}
showList.forEach(row => {
let tr = document.createElement('tr');
tr.innerHTML = `
<td>${row.instance_ip}</td>
<td>${row.username}</td>
<td>${row.directory}</td>
<td class="num-big">${row.size_gb}GB</td>
`;
tbody.appendChild(tr);
})
}
// 导出CSV
exportBtn.addEventListener('click', function(){
let showList = [];
if(currentFilterIp === "all"){
showList = sourceData;
}else{
showList = sourceData.filter(item=>item.instance_ip === currentFilterIp);
}
if(showList.length === 0){
alert("无数据可导出");
return;
}
// CSV表头
let csvContent = "\uFEFF实例IP,用户名,目录路径,占用容量(GB)\n";
showList.forEach(item=>{
const line = [
`"${item.instance_ip}"`,
`"${item.username}"`,
`"${item.directory}"`,
`"${item.size_gb}GB"`
];
csvContent += line.join(",") + "\n";
});
// 下载文件
const blob = new Blob([csvContent], {type:"text/csv;charset=utf-8"});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "磁盘目录容量_"+new Date().getTime()+".csv";
a.click();
URL.revokeObjectURL(url);
})
</script>
</body>
</html>