1268 lines
46 KiB
Plaintext
1268 lines
46 KiB
Plaintext
<?php
|
||
session_start();
|
||
// 禁止页面缓存,解决标题刷新不生效
|
||
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||
header("Pragma: no-cache");
|
||
header("Expires: Thu, 01 Jan 1970 00:00:00 GMT");
|
||
|
||
// 会话超时:30分钟无操作自动登出,与admin后台统一
|
||
$expire = 1800;
|
||
if (empty($_SESSION['user_id']) || (time() - $_SESSION['login_time'] > $expire)) {
|
||
session_destroy();
|
||
header("Location: login.php");
|
||
exit;
|
||
}
|
||
// 刷新登录计时
|
||
$_SESSION['login_time'] = time();
|
||
$userName = htmlspecialchars($_SESSION['username']);
|
||
$userRole = $_SESSION['role'];
|
||
$roleText = $userRole === 'admin' ? '管理员' : '只读用户';
|
||
|
||
// 读取全局系统配置(admin后台保存后同步生效)
|
||
$dbHost = "10.150.117.190";
|
||
$dbUser = "root";
|
||
$dbPwd = "hp93000";
|
||
$dbName = "alert_mail_stat";
|
||
$connConfig = mysqli_connect($dbHost, $dbUser, $dbPwd, $dbName);
|
||
mysqli_set_charset($connConfig, "utf8mb4");
|
||
$configSql = "SELECT k,v FROM sys_config";
|
||
$configRes = mysqli_query($connConfig, $configSql);
|
||
$sysConfig = [];
|
||
while ($row = mysqli_fetch_assoc($configRes)) {
|
||
$sysConfig[$row['k']] = $row['v'];
|
||
}
|
||
mysqli_close($connConfig);
|
||
|
||
// 赋值全局配置
|
||
$pageTitle = htmlspecialchars($sysConfig['page_title'] ?? "告警监控系统");
|
||
$themeColor = htmlspecialchars($sysConfig['theme_color'] ?? "#409eff");
|
||
$pageSize = $sysConfig['page_size'] ?? "20";
|
||
$footerText = htmlspecialchars($sysConfig['footer_text'] ?? "");
|
||
$sidebarRawLinks = $sysConfig['sidebar_links'] ?? "";
|
||
// 读取语言配置 zh=中文 en=英文
|
||
$currentLang = $sysConfig['lang'] ?? "zh";
|
||
|
||
// 全局多语言词典
|
||
$langMap = [
|
||
'zh' => [
|
||
'html_lang' => 'zh-CN',
|
||
'page_subtitle' => '爱德万测试 · 运维告警监控平台',
|
||
'monitor_panel' => '监控面板',
|
||
'alert_overview' => '告警监控总览',
|
||
'alert_list_page' => '告警明细分页',
|
||
'disk_capacity' => '服务器磁盘容量',
|
||
'quick_link' => '快捷外链',
|
||
'system_manage' => '系统管理',
|
||
'system_config' => '后台配置管理',
|
||
'current_user' => '当前用户:',
|
||
'sys_time' => '系统时间:',
|
||
'refresh_all' => '刷新全部数据',
|
||
'export_csv' => '导出告警CSV',
|
||
'logout' => '退出登录',
|
||
'lang_text' => '语言:',
|
||
'today_fire' => '今日触发告警',
|
||
'unresolved_now' => '当前未恢复告警',
|
||
'resolved_today' => '今日恢复告警',
|
||
'instance_total' => '故障实例总数',
|
||
'recovery_rate' => '告警恢复率',
|
||
'today_fire_sub' => 'Total Firing Today',
|
||
'unresolved_sub' => 'Unresolved Now',
|
||
'resolved_sub' => 'Resolved Today',
|
||
'instance_sub' => 'Affected Host Instance',
|
||
'rate_sub' => 'Daily Recovery Rate',
|
||
'top10_alert' => '今日告警频次 TOP 10',
|
||
'active_alert' => '当前未恢复活跃告警',
|
||
'alert_count' => '条未恢复故障',
|
||
'all_alert_log' => '告警全量明细',
|
||
'total_alert' => '条告警记录',
|
||
'tag' => '告警状态',
|
||
'alert_name' => '告警名称',
|
||
'instance_addr' => '实例地址',
|
||
'severity' => '告警级别',
|
||
'occur_time' => '故障发生时间',
|
||
'empty_normal' => '当前无未恢复告警,系统运行正常',
|
||
'empty_no_data' => '暂无告警数据',
|
||
'disk_stat' => '用户目录磁盘占用统计',
|
||
'filter_ip' => '筛选实例IP:',
|
||
'export_disk' => '导出当前表格CSV',
|
||
'all_instance' => '全部实例',
|
||
'disk_loading' => '磁盘数据加载中...',
|
||
'no_disk_data' => '暂无磁盘指标数据',
|
||
'no_ip_data' => '该实例下无目录数据',
|
||
'csv_tip' => '正在生成CSV报表,请稍候...',
|
||
'alert_axis' => '告警次数',
|
||
'data_fail' => '数据加载失败,请重新登录',
|
||
'server_fail' => '接口数据加载失败,请检查后端服务',
|
||
'disk_api_fail' => '磁盘接口异常:',
|
||
'disk_request_fail' => '请求df.php接口失败,请检查服务',
|
||
'no_export_data' => '无数据可导出',
|
||
// 分页新增文字
|
||
'page_title_list' => '告警分页列表',
|
||
'filter_date' => '日期筛选',
|
||
'filter_alert_name' => '告警名称',
|
||
'filter_severity' => '告警级别',
|
||
'filter_status' => '告警状态',
|
||
'btn_search' => '查询',
|
||
'btn_reset' => '重置',
|
||
'page_total' => '共',
|
||
'page_record' => '条记录',
|
||
'page_size' => '每页',
|
||
'page_prev' => '上一页',
|
||
'page_next' => '下一页',
|
||
'page_first' => '首页',
|
||
'page_last' => '末页'
|
||
],
|
||
'en' => [
|
||
'html_lang' => 'en',
|
||
'page_subtitle' => 'Advantest · O&M Alert Monitor Platform',
|
||
'monitor_panel' => 'Monitor Panel',
|
||
'alert_overview' => 'Alert Overview',
|
||
'alert_list_page' => 'Alert Pagination List',
|
||
'disk_capacity' => 'Server Disk Capacity',
|
||
'quick_link' => 'Quick Links',
|
||
'system_manage' => 'System Manage',
|
||
'system_config' => 'System Config',
|
||
'current_user' => 'User: ',
|
||
'sys_time' => 'System Time: ',
|
||
'refresh_all' => 'Refresh All Data',
|
||
'export_csv' => 'Export Alert CSV',
|
||
'logout' => 'Logout',
|
||
'lang_text' => 'Lang: ',
|
||
'today_fire' => 'Today Triggered Alerts',
|
||
'unresolved_now' => 'Unresolved Alerts',
|
||
'resolved_today' => 'Resolved Today',
|
||
'instance_total' => 'Affected Instances',
|
||
'recovery_rate' => 'Daily Recovery Rate',
|
||
'today_fire_sub' => 'Total Firing Today',
|
||
'unresolved_sub' => 'Unresolved Now',
|
||
'resolved_sub' => 'Resolved Today',
|
||
'instance_sub' => 'Affected Host Instance',
|
||
'rate_sub' => 'Daily Recovery Rate',
|
||
'top10_alert' => 'Top 10 Alert Frequency Today',
|
||
'active_alert' => 'Active Unresolved Alerts',
|
||
'alert_count' => ' unresolved alerts',
|
||
'all_alert_log' => 'Full Alert List',
|
||
'total_alert' => ' alert records',
|
||
'tag' => 'Status',
|
||
'alert_name' => 'Alert Name',
|
||
'instance_addr' => 'Instance IP',
|
||
'severity' => 'Severity',
|
||
'occur_time' => 'Occur Time',
|
||
'empty_normal' => 'No active alerts, system normal',
|
||
'empty_no_data' => 'No alert data',
|
||
'disk_stat' => 'User Directory Disk Usage',
|
||
'filter_ip' => 'Filter IP: ',
|
||
'export_disk' => 'Export Table CSV',
|
||
'all_instance' => 'All Instances',
|
||
'disk_loading' => 'Loading disk data...',
|
||
'no_disk_data' => 'No disk data available',
|
||
'no_ip_data' => 'No directory data for this instance',
|
||
'csv_tip' => 'Generating CSV file, please wait...',
|
||
'alert_axis' => 'Alert Count',
|
||
'data_fail' => 'Data load failed, please relogin',
|
||
'server_fail' => 'API request failed, check backend service',
|
||
'disk_api_fail' => 'Disk API Error: ',
|
||
'disk_request_fail' => 'Request df.php failed, check service',
|
||
'no_export_data' => 'No data to export',
|
||
// 分页英文
|
||
'page_title_list' => 'Alert Pagination List',
|
||
'filter_date' => 'Date',
|
||
'filter_alert_name' => 'Alert Name',
|
||
'filter_severity' => 'Severity',
|
||
'filter_status' => 'Status',
|
||
'btn_search' => 'Search',
|
||
'btn_reset' => 'Reset',
|
||
'page_total' => 'Total ',
|
||
'page_record' => ' records',
|
||
'page_size' => 'Per page',
|
||
'page_prev' => 'Prev',
|
||
'page_next' => 'Next',
|
||
'page_first' => 'First',
|
||
'page_last' => 'Last'
|
||
]
|
||
];
|
||
$t = $langMap[$currentLang];
|
||
|
||
// 解析侧边外链列表
|
||
$sidebarLinkList = [];
|
||
if (!empty($sidebarRawLinks)) {
|
||
$lines = explode("\n", $sidebarRawLinks);
|
||
foreach ($lines as $line) {
|
||
$line = trim($line);
|
||
if (empty($line)) continue;
|
||
$item = explode("|", $line, 2);
|
||
if (count($item) === 2) {
|
||
$sidebarLinkList[] = [
|
||
"name" => trim($item[0]),
|
||
"url" => trim($item[1])
|
||
];
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="<?php echo $t['html_lang']; ?>">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title><?php echo $pageTitle; ?> - Advantest <?php echo $t['page_subtitle']; ?></title>
|
||
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
|
||
<script src="/static/js/echarts.min.js"></script>
|
||
<script src="/static/js/jquery.min.js"></script>
|
||
<style>
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
body{
|
||
background:#f9fafc;
|
||
font-family:"Inter","PingFang SC","Microsoft YaHei";
|
||
color:#1d2939;
|
||
line-height:1.6;
|
||
display:flex;
|
||
flex-direction:column;
|
||
height:100vh;
|
||
overflow:hidden;
|
||
}
|
||
/* 侧边导航菜单 */
|
||
.wrap-main{
|
||
display:flex;
|
||
flex:1;
|
||
overflow:hidden;
|
||
}
|
||
.sidebar{
|
||
width:240px;
|
||
background:#152c5b;
|
||
color:#e2e8f0;
|
||
flex-shrink:0;
|
||
overflow-y:auto;
|
||
}
|
||
.sidebar-brand{
|
||
padding:26px 24px;
|
||
border-bottom:1px solid rgba(255,255,255,0.1);
|
||
}
|
||
.sidebar-brand-en{
|
||
font-size:20px;
|
||
font-weight:700;
|
||
letter-spacing:1px;
|
||
color:#fff;
|
||
}
|
||
.sidebar-brand-cn{
|
||
font-size:13px;
|
||
color:#a5b4fc;
|
||
margin-top:4px;
|
||
}
|
||
.sidebar-menu{
|
||
padding:16px 0;
|
||
}
|
||
.menu-title{
|
||
padding:10px 24px;
|
||
font-size:12px;
|
||
color:#94a3b8;
|
||
letter-spacing:1px;
|
||
}
|
||
.menu-item{
|
||
display:flex;
|
||
align-items:center;
|
||
gap:12px;
|
||
padding:14px 24px;
|
||
cursor:pointer;
|
||
font-size:14px;
|
||
transition:0.2s;
|
||
color:#cbd5e1;
|
||
}
|
||
.menu-item i{
|
||
font-size:16px;
|
||
width:20px;
|
||
text-align:center;
|
||
}
|
||
.menu-item.active{
|
||
background:rgba(255,255,255,0.12);
|
||
color:#fff;
|
||
border-left:4px solid #3b82f6;
|
||
}
|
||
.menu-item:hover:not(.active){
|
||
background:rgba(255,255,255,0.06);
|
||
color:#fff;
|
||
}
|
||
/* 主内容区域 */
|
||
.main-content{
|
||
flex:1;
|
||
overflow-y:auto;
|
||
display:flex;
|
||
flex-direction:column;
|
||
}
|
||
/* 顶部导航栏 高端纯白渐变 */
|
||
.header{
|
||
background:#ffffff;
|
||
border-bottom:1px solid #eef2fb;
|
||
color:#152c5b;
|
||
padding:20px 40px;
|
||
display:flex;
|
||
justify-content:space-between;
|
||
align-items:center;
|
||
box-shadow:0 2px 12px rgba(21,44,91,0.05);
|
||
flex-shrink:0;
|
||
}
|
||
.header-left{
|
||
display:flex;
|
||
align-items:center;
|
||
gap:14px;
|
||
}
|
||
.header-brand-en{
|
||
font-size:24px;
|
||
font-weight:700;
|
||
letter-spacing:2px;
|
||
color:#152c5b;
|
||
}
|
||
.header-brand-cn{
|
||
font-size:15px;
|
||
color:#64748b;
|
||
}
|
||
.header-right{
|
||
display:flex;
|
||
align-items:center;
|
||
gap:18px;
|
||
font-size:14px;
|
||
flex-wrap:wrap;
|
||
}
|
||
.user-info,.time-info,.lang-box{
|
||
color:#475569;
|
||
display:flex;
|
||
align-items:center;
|
||
gap:6px;
|
||
}
|
||
.lang-box select{
|
||
padding:4px 8px;
|
||
border:1px solid #cbd5e1;
|
||
border-radius:6px;
|
||
}
|
||
.btn-base{
|
||
border:none;
|
||
padding:9px 20px;
|
||
border-radius:8px;
|
||
cursor:pointer;
|
||
font-size:14px;
|
||
display:flex;
|
||
align-items:center;
|
||
gap:6px;
|
||
transition:all 0.2s ease;
|
||
}
|
||
.btn-outline{
|
||
background:#ffffff;
|
||
color:#152c5b;
|
||
border:1px solid #cbd5e1;
|
||
}
|
||
.btn-outline:hover{
|
||
background:#f7f8fc;
|
||
border-color:#152c5b;
|
||
}
|
||
.btn-primary{
|
||
background:#152c5b;
|
||
color:#fff;
|
||
}
|
||
.btn-primary:hover{
|
||
background:#0f1e42;
|
||
}
|
||
.btn-success{
|
||
background:#10b981;
|
||
color:#fff;
|
||
}
|
||
.btn-success:hover{
|
||
background:#059669;
|
||
}
|
||
/* 日期选择框样式 */
|
||
#csvDatePicker{
|
||
padding:8px 10px;
|
||
border:1px solid #cbd5e1;
|
||
border-radius:8px;
|
||
font-size:14px;
|
||
}
|
||
/* 加载遮罩 */
|
||
.mask{
|
||
position:fixed;
|
||
left:0;top:0;
|
||
width:100%;height:100%;
|
||
background:rgba(255,255,255,0.85);
|
||
display:none;
|
||
z-index:999;
|
||
align-items:center;
|
||
justify-content:center;
|
||
}
|
||
.mask-box{
|
||
background:#fff;
|
||
padding:30px 40px;
|
||
border-radius:14px;
|
||
font-size:15px;
|
||
display:flex;
|
||
gap:14px;
|
||
align-items:center;
|
||
box-shadow:0 8px 30px rgba(21,44,91,0.12);
|
||
border:1px solid #eef2fb;
|
||
}
|
||
.loading{
|
||
display:inline-block;
|
||
width:20px;height:20px;
|
||
border:2px solid #e2e8f0;
|
||
border-top-color:#152c5b;
|
||
border-radius:50%;
|
||
animation:spin 0.8s linear infinite;
|
||
}
|
||
@keyframes spin{to{transform:rotate(360deg)}}
|
||
/* 容器内边距 */
|
||
.container{
|
||
padding:36px 40px;
|
||
max-width:100%;
|
||
flex:1;
|
||
}
|
||
/* 页面面板控制(切换显示隐藏) */
|
||
.page-panel{
|
||
display:none;
|
||
}
|
||
.page-panel.active{
|
||
display:block;
|
||
}
|
||
/* 统计卡片区域 */
|
||
.stat-cards{
|
||
display:grid;
|
||
grid-template-columns:repeat(5,1fr);
|
||
gap:28px;
|
||
margin-bottom:36px;
|
||
}
|
||
.stat-card{
|
||
background:#fff;
|
||
border-radius:16px;
|
||
padding:32px;
|
||
box-shadow:0 3px 18px rgba(21,44,91,0.06);
|
||
border:1px solid #eef2fb;
|
||
transition:transform 0.26s,box-shadow 0.26s;
|
||
}
|
||
.stat-card:hover{
|
||
transform:translateY(-6px);
|
||
box-shadow:0 10px 32px rgba(21,44,91,0.09);
|
||
}
|
||
.stat-header{
|
||
display:flex;
|
||
justify-content:space-between;
|
||
align-items:flex-start;
|
||
margin-bottom:20px;
|
||
}
|
||
.stat-title{
|
||
font-size:14px;
|
||
color:#64748b;
|
||
}
|
||
.stat-icon{
|
||
width:46px;height:46px;
|
||
border-radius:12px;
|
||
display:flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
font-size:20px;
|
||
}
|
||
.stat-card.fire .stat-icon{background:#fee2e2;color:#dc2626}
|
||
.stat-card.active .stat-icon{background:#fef3c7;color:#d97706}
|
||
.stat-card.resolve .stat-icon{background:#dcfce7;color:#16a34a}
|
||
.stat-card.instance .stat-icon{background:#dbeafe;color:#2563eb}
|
||
.stat-card.rate .stat-icon{background:#ffedd5;color:#ea580c}
|
||
.stat-value{
|
||
font-size:44px;
|
||
font-weight:700;
|
||
color:#152c5b;
|
||
letter-spacing:1px;
|
||
line-height:1.1;
|
||
}
|
||
.stat-card.active .stat-value{color:#d97706}
|
||
.stat-sub{
|
||
font-size:12px;
|
||
color:#94a3b8;
|
||
margin-top:8px;
|
||
}
|
||
/* 图表、表格通用卡片 */
|
||
.chart-section,.active-alert-section,.table-section,.disk-section{
|
||
margin-bottom:36px;
|
||
}
|
||
.base-card{
|
||
background:#fff;
|
||
border-radius:16px;
|
||
padding:32px;
|
||
box-shadow:0 3px 18px rgba(21,44,91,0.06);
|
||
border:1px solid #eef2fb;
|
||
}
|
||
.title-wrap{
|
||
display:flex;
|
||
justify-content:space-between;
|
||
align-items:center;
|
||
margin-bottom:26px;
|
||
padding-bottom:16px;
|
||
border-bottom:1px solid #eef2fb;
|
||
}
|
||
.title-left{
|
||
display:flex;
|
||
align-items:center;
|
||
gap:12px;
|
||
font-size:19px;
|
||
font-weight:600;
|
||
color:#152c5b;
|
||
}
|
||
.title-left i{color:#2563eb;font-size:21px}
|
||
.table-count{font-size:14px;color:#64748b}
|
||
.filter-box{
|
||
display:flex;
|
||
align-items:center;
|
||
gap:10px;
|
||
}
|
||
.filter-box label{
|
||
font-size:14px;
|
||
color:#475569;
|
||
}
|
||
#ipSelect{
|
||
padding:6px 10px;
|
||
border:1px solid #cbd5e0;
|
||
border-radius:6px;
|
||
font-size:14px;
|
||
min-width:200px;
|
||
}
|
||
#diskExportBtn{
|
||
padding:6px 14px;
|
||
background:#2b6cb0;
|
||
color:#fff;
|
||
border:none;
|
||
border-radius:6px;
|
||
cursor:pointer;
|
||
font-size:14px;
|
||
}
|
||
#diskExportBtn:hover{
|
||
background:#2c5282;
|
||
}
|
||
#chart1{height:420px;width:100%}
|
||
.active-alert-section .base-card{border:1px solid #fee2e2}
|
||
/* 表格通用样式 */
|
||
.table-wrap{overflow-x:auto}
|
||
table{width:100%;border-collapse:collapse;font-size:14px}
|
||
th{
|
||
background:#f9fafc;
|
||
color:#475569;
|
||
font-weight:600;
|
||
padding:16px 18px;
|
||
text-align:left;
|
||
border-bottom:2px solid #e2e8f0;
|
||
white-space:nowrap;
|
||
}
|
||
th i{margin-right:6px;font-size:13px;color:#94a3b8}
|
||
td{
|
||
padding:18px;
|
||
border-bottom:1px solid #f1f5f9;
|
||
color:#334155;
|
||
}
|
||
tbody tr{transition:background 0.2s}
|
||
tbody tr:hover{background:#f7f8fc}
|
||
tbody tr:nth-child(even){background:#fbfcfe}
|
||
/* 状态标签 */
|
||
.status-tag{
|
||
display:inline-flex;
|
||
align-items:center;
|
||
gap:5px;
|
||
padding:6px 14px;
|
||
border-radius:24px;
|
||
font-size:13px;
|
||
font-weight:500;
|
||
}
|
||
.status-tag.fire{background:#fee2e2;color:#dc2626}
|
||
.status-tag.resolve{background:#dcfce7;color:#16a34a}
|
||
.severity-tag{
|
||
display:inline-block;
|
||
padding:5px 12px;
|
||
border-radius:8px;
|
||
font-size:13px;
|
||
font-weight:500;
|
||
}
|
||
.severity-critical{background:#fee2e2;color:#dc2626}
|
||
.severity-warning{background:#ffedd5;color:#ea580c}
|
||
.severity-info{background:#dbeafe;color:#2563eb}
|
||
.num-big {
|
||
color: #c53030;
|
||
font-weight: 500;
|
||
}
|
||
/* 空数据提示 */
|
||
.empty-state{
|
||
text-align:center;
|
||
padding:80px 20px;
|
||
color:#94a3b8;
|
||
font-size:15px;
|
||
}
|
||
.empty-icon{
|
||
font-size:56px;
|
||
margin-bottom:18px;
|
||
opacity:0.35;
|
||
}
|
||
/* 响应式适配 */
|
||
@media (max-width:1440px){.stat-cards{grid-template-columns:repeat(3,1fr)}}
|
||
@media (max-width:992px){
|
||
.wrap-main{flex-direction:column;}
|
||
.sidebar{width:100%;height:auto}
|
||
}
|
||
@media (max-width:768px){
|
||
.header{padding:16px 24px;flex-direction:column;gap:16px;align-items:flex-start}
|
||
.header-right{flex-wrap:wrap}
|
||
.container{padding:24px}
|
||
.stat-cards{grid-template-columns:1fr;gap:20px}
|
||
.stat-card{padding:24px}
|
||
.base-card{padding:24px}
|
||
.filter-box{flex-wrap:wrap;}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="mask" id="exportMask">
|
||
<div class="mask-box">
|
||
<span class="loading"></span>
|
||
<span><?php echo $t['csv_tip']; ?></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wrap-main">
|
||
<!-- 左侧侧边栏菜单 -->
|
||
<div class="sidebar">
|
||
<div class="sidebar-brand">
|
||
<div class="sidebar-brand-en">Advantest</div>
|
||
<div class="sidebar-brand-cn"><?php echo $t['page_subtitle']; ?></div>
|
||
</div>
|
||
<div class="sidebar-menu">
|
||
<div class="menu-title"><?php echo $t['monitor_panel']; ?></div>
|
||
<div class="menu-item active" data-page="alertPage">
|
||
<i class="fa fa-line-chart"></i>
|
||
<span><?php echo $t['alert_overview']; ?></span>
|
||
</div>
|
||
<!-- 新增告警分页菜单 -->
|
||
<div class="menu-item" data-page="alertListPage">
|
||
<i class="fa fa-list"></i>
|
||
<span><?php echo $t['alert_list_page']; ?></span>
|
||
</div>
|
||
<div class="menu-item" data-page="diskPage">
|
||
<i class="fa fa-hdd-o"></i>
|
||
<span><?php echo $t['disk_capacity']; ?></span>
|
||
</div>
|
||
<!-- 后台配置快捷外链自动渲染 -->
|
||
<?php if (!empty($sidebarLinkList)): ?>
|
||
<div class="menu-title"><?php echo $t['quick_link']; ?></div>
|
||
<?php foreach ($sidebarLinkList as $link): ?>
|
||
<div class="menu-item" onclick="window.open('<?php echo htmlspecialchars($link['url']); ?>')">
|
||
<i class="fa fa-external-link"></i>
|
||
<span><?php echo htmlspecialchars($link['name']); ?></span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
<div class="menu-title"><?php echo $t['system_manage']; ?></div>
|
||
<div class="menu-item" onclick="location.href='admin.php'">
|
||
<i class="fa fa-cog"></i>
|
||
<span><?php echo $t['system_config']; ?></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧主内容区 -->
|
||
<div class="main-content">
|
||
<div class="header">
|
||
<div class="header-left">
|
||
<div>
|
||
<div class="header-brand-en">Advantest</div>
|
||
<div class="header-brand-cn"><?php echo $t['page_subtitle']; ?></div>
|
||
</div>
|
||
</div>
|
||
<div class="header-right">
|
||
<span class="user-info"><i class="fa fa-user-circle"></i><?php echo $t['current_user']; ?><?php echo $userName; ?>(<?php echo $roleText; ?>)</span>
|
||
<span class="time-info"><i class="fa fa-clock-o"></i><?php echo $t['sys_time']; ?><span id="updateTime">--</span></span>
|
||
<!-- 语言切换下拉框 -->
|
||
<div class="lang-box">
|
||
<span><?php echo $t['lang_text']; ?></span>
|
||
<select id="langSwitch">
|
||
<option value="zh" <?php echo $currentLang==='zh'?'selected':''; ?>>中文</option>
|
||
<option value="en" <?php echo $currentLang==='en'?'selected':''; ?>>EN</option>
|
||
</select>
|
||
</div>
|
||
<button class="btn-base btn-outline" onclick="loadAllData()"><i class="fa fa-refresh"></i><?php echo $t['refresh_all']; ?></button>
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<input type="date" id="csvDatePicker">
|
||
<button class="btn-base btn-success" onclick="exportCsv()"><i class="fa fa-download"></i><?php echo $t['export_csv']; ?></button>
|
||
</div>
|
||
<button class="btn-base btn-primary" id="logoutBtn"><i class="fa fa-sign-out"></i><?php echo $t['logout']; ?></button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container">
|
||
<!-- 告警监控总览首页(移除原今日全量表格,仅保留统计、图表、未恢复告警) -->
|
||
<div class="page-panel active" id="alertPage">
|
||
<div class="stat-cards">
|
||
<div class="stat-card fire">
|
||
<div class="stat-header">
|
||
<div class="stat-title"><?php echo $t['today_fire']; ?></div>
|
||
<div class="stat-icon"><i class="fa fa-exclamation-triangle"></i></div>
|
||
</div>
|
||
<div class="stat-value" id="fire">0</div>
|
||
<div class="stat-sub"><?php echo $t['today_fire_sub']; ?></div>
|
||
</div>
|
||
<div class="stat-card active">
|
||
<div class="stat-header">
|
||
<div class="stat-title"><?php echo $t['unresolved_now']; ?></div>
|
||
<div class="stat-icon"><i class="fa fa-bolt"></i></div>
|
||
</div>
|
||
<div class="stat-value" id="activeAlert">0</div>
|
||
<div class="stat-sub"><?php echo $t['unresolved_sub']; ?></div>
|
||
</div>
|
||
<div class="stat-card resolve">
|
||
<div class="stat-header">
|
||
<div class="stat-title"><?php echo $t['resolved_today']; ?></div>
|
||
<div class="stat-icon"><i class="fa fa-check-circle"></i></div>
|
||
</div>
|
||
<div class="stat-value" id="resolve">0</div>
|
||
<div class="stat-sub"><?php echo $t['resolved_sub']; ?></div>
|
||
</div>
|
||
<div class="stat-card instance">
|
||
<div class="stat-header">
|
||
<div class="stat-title"><?php echo $t['instance_total']; ?></div>
|
||
<div class="stat-icon"><i class="fa fa-server"></i></div>
|
||
</div>
|
||
<div class="stat-value" id="instance">0</div>
|
||
<div class="stat-sub"><?php echo $t['instance_sub']; ?></div>
|
||
</div>
|
||
<div class="stat-card rate">
|
||
<div class="stat-header">
|
||
<div class="stat-title"><?php echo $t['recovery_rate']; ?></div>
|
||
<div class="stat-icon"><i class="fa fa-line-chart"></i></div>
|
||
</div>
|
||
<div class="stat-value" id="rate">0%</div>
|
||
<div class="stat-sub"><?php echo $t['rate_sub']; ?></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TOP10图表 -->
|
||
<div class="chart-section">
|
||
<div class="base-card">
|
||
<div class="title-wrap">
|
||
<div class="title-left"><i class="fa fa-bar-chart"></i><?php echo $t['top10_alert']; ?></div>
|
||
</div>
|
||
<div id="chart1"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 未恢复活跃告警 -->
|
||
<div class="active-alert-section">
|
||
<div class="base-card">
|
||
<div class="title-wrap">
|
||
<div class="title-left"><i class="fa fa-exclamation-circle"></i><?php echo $t['active_alert']; ?></div>
|
||
<div class="table-count"><?php echo $currentLang==='zh'?'共 ':' '; ?><span id="activeCount">0</span><?php echo $t['alert_count']; ?></div>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width:100px"><i class="fa fa-tag"></i><?php echo $t['tag']; ?></th>
|
||
<th><i class="fa fa-bullhorn"></i><?php echo $t['alert_name']; ?></th>
|
||
<th><i class="fa fa-desktop"></i><?php echo $t['instance_addr']; ?></th>
|
||
<th style="width:120px"><i class="fa fa-signal"></i><?php echo $t['severity']; ?></th>
|
||
<th style="width:200px"><i class="fa fa-calendar"></i><?php echo $t['occur_time']; ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="active-table-body">
|
||
<tr>
|
||
<td colspan="5">
|
||
<div class="empty-state">
|
||
<div class="empty-icon"><i class="fa fa-check"></i></div>
|
||
<div><?php echo $t['empty_normal']; ?></div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 告警分页明细独立页面(新增) -->
|
||
<div class="page-panel" id="alertListPage">
|
||
<div class="table-section">
|
||
<div class="base-card">
|
||
<div class="title-wrap">
|
||
<div class="title-left"><i class="fa fa-list"></i><?php echo $t['page_title_list']; ?></div>
|
||
</div>
|
||
<!-- 筛选栏 -->
|
||
<div style="display:flex;flex-wrap:wrap;gap:16px;margin-bottom:24px;align-items:center;">
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<label><?php echo $t['filter_date']; ?></label>
|
||
<input type="date" id="listDateFilter">
|
||
</div>
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<label><?php echo $t['filter_alert_name']; ?></label>
|
||
<input style="padding:6px 10px;border:1px solid #cbd5e1;border-radius:6px;" type="text" id="listNameFilter" placeholder="">
|
||
</div>
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<label><?php echo $t['filter_severity']; ?></label>
|
||
<select id="listSeverityFilter" style="padding:6px 10px;border:1px solid #cbd5e1;border-radius:6px;">
|
||
<option value="">--</option>
|
||
<option value="critical">Critical</option>
|
||
<option value="warning">Warning</option>
|
||
<option value="info">Info</option>
|
||
</select>
|
||
</div>
|
||
<div style="display:flex;align-items:center;gap:8px;">
|
||
<label><?php echo $t['filter_status']; ?></label>
|
||
<select id="listStatusFilter" style="padding:6px 10px;border:1px solid #cbd5e1;border-radius:6px;">
|
||
<option value="">--</option>
|
||
<option value="1"><?php echo $currentLang==='zh'?'触发':'Firing'; ?></option>
|
||
<option value="2"><?php echo $currentLang==='zh'?'恢复':'Resolved'; ?></option>
|
||
</select>
|
||
</div>
|
||
<button class="btn-base btn-success" id="listSearchBtn"><?php echo $t['btn_search']; ?></button>
|
||
<button class="btn-base btn-outline" id="listResetBtn"><?php echo $t['btn_reset']; ?></button>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width:100px"><i class="fa fa-tag"></i><?php echo $t['tag']; ?></th>
|
||
<th><i class="fa fa-bullhorn"></i><?php echo $t['alert_name']; ?></th>
|
||
<th><i class="fa fa-desktop"></i><?php echo $t['instance_addr']; ?></th>
|
||
<th style="width:120px"><i class="fa fa-signal"></i><?php echo $t['severity']; ?></th>
|
||
<th style="width:200px"><i class="fa fa-calendar"></i><?php echo $t['occur_time']; ?></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="list-table-body">
|
||
<tr>
|
||
<td colspan="5">
|
||
<div class="empty-state">
|
||
<div class="empty-icon"><i class="fa fa-folder-open-o"></i></div>
|
||
<div><?php echo $t['empty_no_data']; ?></div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页组件 -->
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:24px;flex-wrap:wrap;gap:12px;">
|
||
<div>
|
||
<?php echo $t['page_total']; ?><span id="listTotal">0</span><?php echo $t['page_record']; ?>
|
||
</div>
|
||
<div style="display:flex;gap:8px;align-items:center;">
|
||
<span><?php echo $t['page_size']; ?></span>
|
||
<select id="listPageSize" style="padding:4px 8px;border:1px solid #cbd5e1;border-radius:6px;">
|
||
<option value="10">10</option>
|
||
<option value="20" selected>20</option>
|
||
<option value="50">50</option>
|
||
</select>
|
||
<button class="btn-base btn-outline" id="pageFirst"><?php echo $t['page_first']; ?></button>
|
||
<button class="btn-base btn-outline" id="pagePrev"><?php echo $t['page_prev']; ?></button>
|
||
<span id="pageInfo">1 / 1</span>
|
||
<button class="btn-base btn-outline" id="pageNext"><?php echo $t['page_next']; ?></button>
|
||
<button class="btn-base btn-outline" id="pageLast"><?php echo $t['page_last']; ?></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 磁盘容量监控面板 -->
|
||
<div class="page-panel" id="diskPage">
|
||
<div class="disk-section">
|
||
<div class="base-card">
|
||
<div class="title-wrap">
|
||
<div class="title-left"><i class="fa fa-hdd-o"></i><?php echo $t['disk_stat']; ?></div>
|
||
<div class="filter-box">
|
||
<label><?php echo $t['filter_ip']; ?></label>
|
||
<select id="ipSelect">
|
||
<option value="all"><?php echo $t['all_instance']; ?></option>
|
||
</select>
|
||
<button id="diskExportBtn"><?php echo $t['export_disk']; ?></button>
|
||
</div>
|
||
</div>
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>IP</th>
|
||
<th>Username</th>
|
||
<th>Path</th>
|
||
<th>Size(GB)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="diskTableBody">
|
||
<tr>
|
||
<td colspan="4" class="empty-state">
|
||
<div class="empty-icon"><i class="fa fa-spinner fa-spin"></i></div>
|
||
<div><?php echo $t['disk_loading']; ?></div>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const api = "./api/index.php";
|
||
let chartInstance = null;
|
||
let diskSourceData = [];
|
||
let currentDiskIp = "all";
|
||
// 当前语言
|
||
const currentLang = "<?php echo $currentLang; ?>";
|
||
|
||
// 分页全局变量
|
||
let listPage = 1;
|
||
let listPageSize = 20;
|
||
let listTotal = 0;
|
||
let listFilter = {
|
||
date: "",
|
||
name: "",
|
||
severity: "",
|
||
status: ""
|
||
};
|
||
|
||
// 语言切换接口
|
||
$("#langSwitch").change(function(){
|
||
const newLang = $(this).val();
|
||
fetch(api,{
|
||
method:"POST",
|
||
headers:{"Content-Type":"application/x-www-form-urlencoded"},
|
||
body:"act=save_lang&lang="+newLang
|
||
}).then(()=>{
|
||
// 带随机参数清除缓存刷新页面
|
||
location.href = "dashboard.php?_t="+new Date().getTime();
|
||
})
|
||
})
|
||
|
||
// 侧边菜单切换
|
||
$(".menu-item").click(function(){
|
||
const pageId = $(this).data("page");
|
||
if (!pageId) return;
|
||
$(".menu-item").removeClass("active");
|
||
$(this).addClass("active");
|
||
$(".page-panel").removeClass("active");
|
||
$("#"+pageId).addClass("active");
|
||
if(pageId === "diskPage") loadDiskData();
|
||
if(pageId === "alertListPage") loadAlertList();
|
||
})
|
||
|
||
// 格式化时间
|
||
function formatTime(dateStr){
|
||
if(!dateStr || dateStr === '0001-01-01 00:00:00' || dateStr === null) return '-';
|
||
return dateStr;
|
||
}
|
||
// 告警级别标签
|
||
function getSeverityTag(severity){
|
||
const s = (severity || '').toLowerCase();
|
||
if(s==='critical') return `<span class="severity-tag severity-critical">${currentLang==='zh'?'严重':'Critical'}</span>`;
|
||
if(s==='warning') return `<span class="severity-tag severity-warning">${currentLang==='zh'?'警告':'Warning'}</span>`;
|
||
if(s==='info') return `<span class="severity-tag severity-info">${currentLang==='zh'?'信息':'Info'}</span>`;
|
||
return `<span class="severity-tag severity-info">${severity||'-'}</span>`;
|
||
}
|
||
|
||
// 加载未恢复告警
|
||
function loadActiveAlert(){
|
||
$.getJSON(api+"?act=active_firing",function(list){
|
||
$("#activeAlert").text(list.length);
|
||
$("#activeCount").text(list.length);
|
||
if(list.length===0){
|
||
$("#active-table-body").html(`<tr><td colspan="5"><div class="empty-state"><div class="empty-icon"><i class="fa fa-check"></i></div><div><?php echo $t['empty_normal']; ?></div></div></td></tr>`);
|
||
return;
|
||
}
|
||
let html="";
|
||
list.forEach(row=>{
|
||
const t=`<span class="status-tag fire"><i class="fa fa-bolt"></i>${currentLang==='zh'?'触发':'Firing'}</span>`;
|
||
html+=`<tr>
|
||
<td>${t}</td>
|
||
<td style="font-weight:500;color:#152c5b">${row.alert_name||'-'}</td>
|
||
<td style="font-family:Consolas,monospace;font-size:13px">${row.instance||'-'}</td>
|
||
<td>${getSeverityTag(row.severity)}</td>
|
||
<td style="color:#475569">${formatTime(row.receive_time)}</td>
|
||
</tr>`;
|
||
});
|
||
$("#active-table-body").html(html);
|
||
}).fail(()=>{
|
||
$("#activeAlert").text("-");
|
||
$("#active-table-body").html(`<tr><td colspan="5"><div class="empty-state" style="color:#dc2626"><div class="empty-icon"><i class="fa fa-exclamation-circle"></i></div><div><?php echo $t['data_fail']; ?></div></div></td></tr>`);
|
||
});
|
||
}
|
||
|
||
// 统计卡片数据
|
||
function loadStats(){
|
||
$.getJSON(api+"?act=day_total",function(res){
|
||
const fire=parseInt(res.fire_count)||0;
|
||
const resolve=parseInt(res.resolve_count)||0;
|
||
const ins=parseInt(res.instance_num)||0;
|
||
const rate=fire>0?Math.round((resolve/fire)*100):0;
|
||
$("#fire").text(fire);
|
||
$("#resolve").text(resolve);
|
||
$("#instance").text(ins);
|
||
$("#rate").text(rate+"%");
|
||
}).fail(()=>{$("#fire,#resolve,#instance,#rate").text("-");});
|
||
}
|
||
|
||
// 图表加载
|
||
function loadChart(){
|
||
$.getJSON(api+"?act=top_alert",function(list){
|
||
if(!chartInstance){
|
||
chartInstance=echarts.init(document.getElementById("chart1"));
|
||
window.addEventListener("resize",()=>chartInstance.resize());
|
||
}
|
||
const names=list.map(i=>i.alert_name);
|
||
const cnt=list.map(i=>i.cnt);
|
||
chartInstance.setOption({
|
||
tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},
|
||
grid:{left:"3%",right:"4%",bottom:"18%",top:"8%",containLabel:true},
|
||
xAxis:{
|
||
type:"category",
|
||
data:names,
|
||
axisLabel:{rotate:30,fontSize:12,color:"#64748b"},
|
||
axisLine:{lineStyle:{color:"#e2e8f0"}},
|
||
axisTick:{show:false}
|
||
},
|
||
yAxis:{
|
||
type:"value",
|
||
name:"<?php echo $t['alert_axis']; ?>",
|
||
nameTextStyle:{color:"#64748b",fontSize:13},
|
||
axisLabel:{color:"#64748b",fontSize:12},
|
||
splitLine:{lineStyle:{color:"#f1f5f9",type:"dashed"}},
|
||
axisLine:{show:false}
|
||
},
|
||
series:[{
|
||
type:"bar",
|
||
data:cnt,
|
||
barWidth:"48%",
|
||
itemStyle:{
|
||
color:new echarts.graphic.LinearGradient(0,0,0,1,[
|
||
{offset:0,color:"#3b82f6"},
|
||
{offset:1,color:"#1d4ed8"}
|
||
]),
|
||
borderRadius:[6,6,0,0]
|
||
},
|
||
label:{show:true,position:"top",fontSize:12,color:"#334155"}
|
||
}]
|
||
});
|
||
});
|
||
}
|
||
|
||
// 旧今日全量明细接口(首页已移除表格,保留函数兼容自动刷新)
|
||
function loadTable(){
|
||
return;
|
||
}
|
||
|
||
// 分页告警列表加载函数
|
||
function loadAlertList(){
|
||
const params = new URLSearchParams();
|
||
params.append("act","log_pagination");
|
||
params.append("page",listPage);
|
||
params.append("page_size",listPageSize);
|
||
params.append("date",listFilter.date);
|
||
params.append("alert_name",listFilter.name);
|
||
params.append("severity",listFilter.severity);
|
||
params.append("status",listFilter.status);
|
||
fetch(api,{
|
||
method:"POST",
|
||
headers:{"Content-Type":"application/x-www-form-urlencoded"},
|
||
body:params.toString()
|
||
}).then(r=>r.json()).then(res=>{
|
||
listTotal = res.total;
|
||
$("#listTotal").text(listTotal);
|
||
const totalPage = Math.ceil(listTotal / listPageSize) || 1;
|
||
$("#pageInfo").text(`${listPage} / ${totalPage}`);
|
||
const tbody = $("#list-table-body");
|
||
if(res.list.length === 0){
|
||
tbody.html(`<tr><td colspan="5"><div class="empty-state"><div class="empty-icon"><i class="fa fa-folder-open-o"></i></div><div><?php echo $t['empty_no_data']; ?></div></div></td></tr>`);
|
||
return;
|
||
}
|
||
let html = "";
|
||
res.list.forEach(row=>{
|
||
const typeText = row.alert_type == 1
|
||
? `<span class="status-tag fire"><i class="fa fa-bolt"></i>${currentLang==='zh'?'触发':'Firing'}</span>`
|
||
: `<span class="status-tag resolve"><i class="fa fa-check"></i>${currentLang==='zh'?'恢复':'Resolved'}</span>`;
|
||
html += `<tr>
|
||
<td>${typeText}</td>
|
||
<td style="font-weight:500;color:#152c5b">${row.alert_name || '-'}</td>
|
||
<td style="font-family:Consolas,monospace;font-size:13px">${row.instance || '-'}</td>
|
||
<td>${getSeverityTag(row.severity)}</td>
|
||
<td style="color:#475569">${formatTime(row.receive_time)}</td>
|
||
</tr>`;
|
||
})
|
||
tbody.html(html);
|
||
}).catch(()=>{
|
||
$("#list-table-body").html(`<tr><td colspan="5"><div class="empty-state" style="color:#dc2626"><div class="empty-icon"><i class="fa fa-exclamation-circle"></i></div><div><?php echo $t['server_fail']; ?></div></div></td></tr>`);
|
||
})
|
||
}
|
||
|
||
// 更新顶部时间
|
||
function updateTime() {
|
||
const now = new Date();
|
||
const Y = now.getFullYear();
|
||
const M = String(now.getMonth() + 1).padStart(2, '0');
|
||
const D = String(now.getDate()).padStart(2, '0');
|
||
const h = String(now.getHours()).padStart(2, '0');
|
||
const m = String(now.getMinutes()).padStart(2, '0');
|
||
const s = String(now.getSeconds()).padStart(2, '0');
|
||
$("#updateTime").text(`${Y}-${M}-${D} ${h}:${m}:${s}`);
|
||
}
|
||
|
||
// 刷新全部数据
|
||
function loadAllData() {
|
||
loadStats();
|
||
loadChart();
|
||
loadTable();
|
||
loadActiveAlert();
|
||
updateTime();
|
||
if($("#diskPage").hasClass("active")) loadDiskData();
|
||
if($("#alertListPage").hasClass("active")) loadAlertList();
|
||
}
|
||
|
||
// 导出CSV
|
||
function exportCsv(){
|
||
const mask = $("#exportMask");
|
||
mask.css("display","flex");
|
||
const selectDate = $("#csvDatePicker").val().trim();
|
||
let exportUrl = api + "?act=export_csv";
|
||
if(selectDate) exportUrl += "&date=" + encodeURIComponent(selectDate);
|
||
window.open(exportUrl, "_blank");
|
||
setTimeout(()=>mask.hide(),5000);
|
||
}
|
||
// 磁盘数据加载
|
||
function loadDiskData(){
|
||
const tbody = $("#diskTableBody");
|
||
tbody.html(`<tr><td colspan="4" class="empty-state"><div class="empty-icon"><i class="fa fa-spinner fa-spin"></i></div><div><?php echo $t['disk_loading']; ?></div></td></tr>`);
|
||
$.getJSON("./api/df.php").done(ret=>{
|
||
if(ret.code !== 0){
|
||
tbody.html(`<tr><td colspan="4" class="empty-state" style="color:#dc2626"><?php echo $t['disk_api_fail']; ?>${ret.msg}</td></tr>`);
|
||
return;
|
||
}
|
||
diskSourceData = ret.list;
|
||
if(diskSourceData.length === 0){
|
||
tbody.html(`<tr><td colspan="4" class="empty-state"><?php echo $t['no_disk_data']; ?></td></tr>`);
|
||
return;
|
||
}
|
||
const ipSel = $("#ipSelect");
|
||
ipSel.find("option:not([value='all'])").remove();
|
||
const ipSet = new Set();
|
||
diskSourceData.forEach(item=>ipSet.add(item.instance_ip));
|
||
ipSet.forEach(ip=>ipSel.append(`<option value="${ip}">${ip}</option>`));
|
||
currentDiskIp = "all";
|
||
renderDiskTable("all");
|
||
}).fail(()=>{
|
||
tbody.html(`<tr><td colspan="4" class="empty-state" style="color:#dc2626"><?php echo $t['disk_request_fail']; ?></td></tr>`);
|
||
})
|
||
}
|
||
// 渲染磁盘表格
|
||
function renderDiskTable(filterIp){
|
||
currentDiskIp = filterIp;
|
||
const tbody = $("#diskTableBody");
|
||
tbody.html("");
|
||
let showList = filterIp === "all" ? diskSourceData : diskSourceData.filter(i=>i.instance_ip === filterIp);
|
||
if(showList.length === 0){
|
||
tbody.html(`<tr><td colspan="4" class="empty-state"><?php echo $t['no_ip_data']; ?></td></tr>`);
|
||
return;
|
||
}
|
||
showList.forEach(row=>{
|
||
tbody.append(`
|
||
<tr>
|
||
<td>${row.instance_ip}</td>
|
||
<td>${row.username}</td>
|
||
<td>${row.directory}</td>
|
||
<td class="num-big">${row.size_gb}GB</td>
|
||
</tr>
|
||
`)
|
||
})
|
||
}
|
||
// 导出磁盘CSV
|
||
$("#diskExportBtn").click(function(){
|
||
let showList = currentDiskIp === "all" ? diskSourceData : diskSourceData.filter(i=>i.instance_ip === currentDiskIp);
|
||
if(showList.length === 0){
|
||
alert("<?php echo $t['no_export_data']; ?>");
|
||
return;
|
||
}
|
||
let csv = "\uFEFFIP,Username,Path,Size(GB)\n";
|
||
showList.forEach(item=>{
|
||
const line = [
|
||
`"${item.instance_ip}"`,
|
||
`"${item.username}"`,
|
||
`"${item.directory}"`,
|
||
`"${item.size_gb}GB"`
|
||
];
|
||
csv += line.join(",") + "\n";
|
||
})
|
||
const blob = new Blob([csv], {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);
|
||
})
|
||
// IP筛选切换
|
||
$("#ipSelect").change(function(){
|
||
renderDiskTable($(this).val());
|
||
})
|
||
|
||
// 分页筛选按钮事件
|
||
$("#listSearchBtn").click(function(){
|
||
listFilter.date = $("#listDateFilter").val();
|
||
listFilter.name = $("#listNameFilter").val().trim();
|
||
listFilter.severity = $("#listSeverityFilter").val();
|
||
listFilter.status = $("#listStatusFilter").val();
|
||
listPage = 1;
|
||
loadAlertList();
|
||
})
|
||
// 重置筛选
|
||
$("#listResetBtn").click(function(){
|
||
$("#listDateFilter").val("");
|
||
$("#listNameFilter").val("");
|
||
$("#listSeverityFilter").val("");
|
||
$("#listStatusFilter").val("");
|
||
listFilter = {date:"",name:"",severity:"",status:""};
|
||
listPage = 1;
|
||
loadAlertList();
|
||
})
|
||
// 每页条数切换
|
||
$("#listPageSize").change(function(){
|
||
listPageSize = parseInt($(this).val());
|
||
listPage = 1;
|
||
loadAlertList();
|
||
})
|
||
// 分页按钮
|
||
$("#pageFirst").click(function(){
|
||
if(listPage !== 1){
|
||
listPage = 1;
|
||
loadAlertList();
|
||
}
|
||
})
|
||
$("#pagePrev").click(function(){
|
||
if(listPage > 1){
|
||
listPage--;
|
||
loadAlertList();
|
||
}
|
||
})
|
||
$("#pageNext").click(function(){
|
||
const totalPage = Math.ceil(listTotal / listPageSize);
|
||
if(listPage < totalPage){
|
||
listPage++;
|
||
loadAlertList();
|
||
}
|
||
})
|
||
$("#pageLast").click(function(){
|
||
const totalPage = Math.ceil(listTotal / listPageSize);
|
||
if(listPage !== totalPage){
|
||
listPage = totalPage;
|
||
loadAlertList();
|
||
}
|
||
})
|
||
|
||
// 页面初始化
|
||
$(function() {
|
||
loadAllData();
|
||
setInterval(loadAllData, 60000);
|
||
setInterval(updateTime, 1000);
|
||
$("#logoutBtn").click(function(){
|
||
location.href="logout.php";
|
||
})
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|