Files
kefu_cloud/docs/admin/P2-11-系统运维.html
yml2213 b424dfb9a0 docs: 设计稿按优先级重命名并调整目录归属
按需求文档模块优先级为 HTML 设计稿增加 P0/P1/P2 中文命名,
并将数据统计、系统设置从 admin 移至 agent,与客服端职责一致。
2026-07-15 10:57:38 +08:00

719 lines
46 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN" class="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统运维 — 客服云运营管理</title>
<style id="theme-vars">
/* Online Customer Service System — Brand CSS */
/* Professional & Efficient Style — Cool Blue-Gray */
:root {
/* === Brand Primary === */
--brand-primary: #2563eb;
--brand-primary-hover: #1d4ed8;
--brand-primary-active: #1e40af;
--brand-primary-light: #dbeafe;
--brand-primary-lighter: #eff6ff;
--brand-primary-dark: #1e3a8a;
/* === Neutrals === */
--neutral-0: #ffffff;
--neutral-50: #f8fafc;
--neutral-100: #f1f5f9;
--neutral-200: #e2e8f0;
--neutral-300: #cbd5e1;
--neutral-400: #94a3b8;
--neutral-500: #64748b;
--neutral-600: #475569;
--neutral-700: #334155;
--neutral-800: #1e293b;
--neutral-900: #0f172a;
--neutral-950: #020617;
/* === State Colors === */
--state-success: #16a34a;
--state-success-bg: #f0fdf4;
--state-warning: #d97706;
--state-warning-bg: #fffbeb;
--state-error: #dc2626;
--state-error-bg: #fef2f2;
--state-info: #0891b2;
--state-info-bg: #ecfeff;
/* === Typography === */
--font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--font-family-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
--font-size-xs: 12px;
--font-size-sm: 13px;
--font-size-base: 14px;
--font-size-md: 15px;
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-2xl: 20px;
--font-size-3xl: 24px;
--font-size-4xl: 30px;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.625;
/* === Spacing === */
--space-0: 0px;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
/* === Radius === */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* === Shadows (static: alpha <= 0.05; floating layers only may exceed) === */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.03);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.04);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.05);
--shadow-floating: 0 8px 24px rgba(0, 0, 0, 0.12);
/* === Transitions === */
--transition-fast: 150ms ease;
--transition-normal: 200ms ease;
--transition-slow: 300ms ease;
/* === Layout === */
--sidebar-width: 240px;
--sidebar-collapsed-width: 64px;
--header-height: 56px;
--panel-width: 320px;
--chat-panel-min: 300px;
--chat-panel-max: 600px;
}
/* Dark mode */
.dark {
--brand-primary: #3b82f6;
--brand-primary-hover: #60a5fa;
--brand-primary-active: #2563eb;
--brand-primary-light: #1e3a5f;
--brand-primary-lighter: #172554;
--brand-primary-dark: #93c5fd;
--neutral-0: #0f172a;
--neutral-50: #1e293b;
--neutral-100: #334155;
--neutral-200: #475569;
--neutral-300: #64748b;
--neutral-400: #94a3b8;
--neutral-500: #cbd5e1;
--neutral-600: #e2e8f0;
--neutral-700: #f1f5f9;
--neutral-800: #f8fafc;
--neutral-900: #ffffff;
--neutral-950: #ffffff;
--state-success-bg: #052e16;
--state-warning-bg: #451a03;
--state-error-bg: #450a0a;
--state-info-bg: #083344;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.35);
--shadow-floating: 0 8px 24px rgba(0, 0, 0, 0.5);
}
</style>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.3.1/dist/index.global.js"></script>
<script src="https://unpkg.com/lucide@1.8.0/dist/umd/lucide.min.js"></script>
<style type="text/tailwindcss">
@theme inline {
--color-primary: var(--brand-primary);
--color-primary-hover: var(--brand-primary-hover);
--color-primary-active: var(--brand-primary-active);
--color-primary-light: var(--brand-primary-light);
--color-primary-lighter: var(--brand-primary-lighter);
--color-primary-dark: var(--brand-primary-dark);
--color-background: var(--neutral-50);
--color-foreground: var(--neutral-900);
--color-card: var(--neutral-0);
--color-card-foreground: var(--neutral-900);
--color-muted: var(--neutral-100);
--color-muted-foreground: var(--neutral-500);
--color-border: var(--neutral-200);
--color-accent: var(--brand-primary-light);
--color-accent-foreground: var(--brand-primary-dark);
--color-destructive: var(--state-error);
--color-destructive-foreground: var(--state-error-bg);
--color-ring: var(--brand-primary);
--color-sidebar: var(--neutral-0);
--color-sidebar-foreground: var(--neutral-700);
--color-sidebar-primary: var(--brand-primary);
--color-sidebar-primary-foreground: var(--neutral-0);
--color-sidebar-accent: var(--brand-primary-lighter);
--color-sidebar-accent-foreground: var(--brand-primary-dark);
--color-success: var(--state-success);
--color-success-bg: var(--state-success-bg);
--color-warning: var(--state-warning);
--color-warning-bg: var(--state-warning-bg);
--color-error: var(--state-error);
--color-error-bg: var(--state-error-bg);
--color-info: var(--state-info);
--color-info-bg: var(--state-info-bg);
--color-neutral-0: var(--neutral-0);
--color-neutral-50: var(--neutral-50);
--color-neutral-100: var(--neutral-100);
--color-neutral-200: var(--neutral-200);
--color-neutral-300: var(--neutral-300);
--color-neutral-400: var(--neutral-400);
--color-neutral-500: var(--neutral-500);
--color-neutral-600: var(--neutral-600);
--color-neutral-700: var(--neutral-700);
--color-neutral-800: var(--neutral-800);
--color-neutral-900: var(--neutral-900);
--radius-sm: var(--radius-sm);
--radius-md: var(--radius-md);
--radius-lg: var(--radius-lg);
}
@layer base {
body { background: var(--neutral-50); color: var(--neutral-900); }
td, th { @apply break-words; word-break: break-all; word-break: auto-phrase; }
th { @apply whitespace-nowrap; }
}
</style>
<style>
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
[data-icon] {
display: inline-flex;
align-items: center;
justify-content: center;
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
background-color: currentColor;
}
</style>
</head>
<body class="min-h-screen antialiased" style="font-family: var(--font-family-base); font-size: var(--font-size-base); line-height: var(--line-height-normal); color: var(--neutral-900); background: var(--neutral-50);">
<main class="flex h-screen overflow-hidden">
<!-- ====== Left Sidebar (240px) — Admin Nav ====== -->
<aside class="shrink-0 flex flex-col h-full" style="width: var(--sidebar-width); background: var(--neutral-0); border-right: 1px solid var(--neutral-200);">
<!-- Logo Area -->
<div class="flex flex-col px-4 shrink-0" style="border-bottom: 1px solid var(--neutral-200); padding-top: 12px; padding-bottom: 12px;">
<div class="flex items-center gap-2.5">
<div class="flex items-center justify-center rounded-lg shrink-0" style="width: 32px; height: 32px; background: var(--brand-primary);">
<i data-lucide="headphones" style="width: 18px; height: 18px; color: var(--neutral-0);"></i>
</div>
<span class="font-semibold truncate" style="font-size: var(--font-size-lg); color: var(--neutral-900);">客服云</span>
</div>
<span class="inline-flex items-center self-start px-1.5 py-0.5 rounded mt-1.5 whitespace-nowrap" style="font-size: var(--font-size-xs); font-weight: 500; background: var(--brand-primary-light); color: var(--brand-primary);">管理端</span>
</div>
<!-- Navigation -->
<nav class="flex-1 overflow-y-auto py-3 px-2">
<ul class="flex flex-col gap-0.5">
<!-- 运营概览 -->
<li>
<a href="#" data-dom-id="admin-nav-dashboard" class="flex items-center gap-2.5 px-3 py-2 rounded-lg truncate" style="color: var(--neutral-600);">
<i data-lucide="layout-dashboard" style="width: 18px; height: 18px; flex-shrink: 0;"></i>
<span class="truncate" style="font-size: var(--font-size-base);">运营概览</span>
</a>
</li>
<!-- 租户管理 -->
<li>
<a href="#" data-dom-id="admin-nav-tenants" class="flex items-center gap-2.5 px-3 py-2 rounded-lg truncate" style="color: var(--neutral-600);">
<i data-lucide="building-2" style="width: 18px; height: 18px; flex-shrink: 0;"></i>
<span class="truncate" style="font-size: var(--font-size-base);">租户管理</span>
</a>
</li>
<!-- 套餐定价 -->
<li>
<a href="#" data-dom-id="admin-nav-plans" class="flex items-center gap-2.5 px-3 py-2 rounded-lg truncate" style="color: var(--neutral-600);">
<i data-lucide="credit-card" style="width: 18px; height: 18px; flex-shrink: 0;"></i>
<span class="truncate" style="font-size: var(--font-size-base);">套餐定价</span>
</a>
</li>
<!-- 系统运维 — Active -->
<li>
<a href="#" data-dom-id="admin-nav-ops" class="flex items-center gap-2.5 px-3 py-2 rounded-lg font-medium truncate" style="background: var(--brand-primary-light); color: var(--brand-primary);">
<i data-lucide="activity" style="width: 18px; height: 18px; flex-shrink: 0;"></i>
<span class="truncate" style="font-size: var(--font-size-base);">系统运维</span>
</a>
</li>
</ul>
</nav>
<!-- Sidebar Footer: Admin User -->
<div class="flex items-center gap-2.5 px-4 shrink-0" style="height: 52px; border-top: 1px solid var(--neutral-200);">
<div class="flex items-center justify-center rounded-full shrink-0" style="width: 32px; height: 32px; background: var(--brand-primary-light); color: var(--brand-primary); font-size: var(--font-size-sm); font-weight: 600;">
</div>
<div class="flex-1 min-w-0">
<div class="truncate font-medium" style="font-size: var(--font-size-sm); color: var(--neutral-800);">系统管理员</div>
<div class="truncate" style="font-size: var(--font-size-xs); color: var(--neutral-400);">超级管理员</div>
</div>
</div>
</aside>
<!-- ====== Main Content Area ====== -->
<section class="flex-1 flex flex-col min-w-0 h-full overflow-y-auto" style="background: var(--neutral-50);">
<!-- Page Header -->
<div class="shrink-0 px-6 pt-5 pb-4" style="background: var(--neutral-0); border-bottom: 1px solid var(--neutral-200);">
<div class="flex items-center justify-between">
<div class="min-w-0">
<h1 class="font-semibold truncate" style="font-size: var(--font-size-2xl); color: var(--neutral-900); text-wrap: balance;">系统运维</h1>
<p class="truncate mt-0.5" style="font-size: var(--font-size-sm); color: var(--neutral-500);">监控平台运行状态、查看操作日志、管理平台公告</p>
</div>
<div class="flex items-center gap-2 shrink-0 ml-4">
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success); border: 1px solid var(--state-success);">
<span class="inline-block rounded-full" style="width: 6px; height: 6px; background: var(--state-success);"></span>
系统正常运行
</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--neutral-400);">最后更新:2分钟前</span>
</div>
</div>
</div>
<!-- Scrollable Content -->
<div class="flex-1 overflow-y-auto px-6 py-5">
<!-- ====== Section 1: System Status Overview ====== -->
<div class="rounded-lg p-5 mb-5" style="background: var(--neutral-0); border: 1px solid var(--neutral-200);">
<!-- Service Status -->
<div class="flex items-center gap-1.5 mb-4">
<i data-lucide="server" style="width: 16px; height: 16px; color: var(--brand-primary);"></i>
<span class="font-semibold" style="font-size: var(--font-size-base); color: var(--neutral-800);">服务状态</span>
</div>
<div class="flex flex-wrap gap-x-6 gap-y-3 mb-5">
<!-- API Service -->
<div class="flex items-center gap-2">
<span class="inline-block rounded-full" style="width: 8px; height: 8px; background: var(--state-success);"></span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">API服务</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--state-success);">正常</span>
</div>
<!-- WebSocket -->
<div class="flex items-center gap-2">
<span class="inline-block rounded-full" style="width: 8px; height: 8px; background: var(--state-success);"></span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">WebSocket</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--state-success);">正常</span>
</div>
<!-- Database -->
<div class="flex items-center gap-2">
<span class="inline-block rounded-full" style="width: 8px; height: 8px; background: var(--state-success);"></span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">数据库</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--state-success);">正常</span>
</div>
<!-- Message Queue -->
<div class="flex items-center gap-2">
<span class="inline-block rounded-full" style="width: 8px; height: 8px; background: var(--state-success);"></span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">消息队列</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--state-success);">正常</span>
</div>
<!-- CDN -->
<div class="flex items-center gap-2">
<span class="inline-block rounded-full" style="width: 8px; height: 8px; background: var(--state-success);"></span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">CDN</span>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--state-success);">正常</span>
</div>
</div>
<!-- System Load -->
<div class="flex items-center gap-1.5 mb-3">
<i data-lucide="cpu" style="width: 16px; height: 16px; color: var(--brand-primary);"></i>
<span class="font-semibold" style="font-size: var(--font-size-base); color: var(--neutral-800);">系统负载</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<!-- CPU 23% -->
<div class="rounded-lg px-4 py-3" style="background: var(--neutral-50); border: 1px solid var(--neutral-100);">
<div class="flex items-center justify-between mb-2">
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">CPU</span>
<span class="font-semibold whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--state-success);">23%</span>
</div>
<div class="rounded-full overflow-hidden" style="height: 8px; background: var(--neutral-200);">
<div class="rounded-full" style="width: 23%; height: 100%; background: linear-gradient(90deg, var(--state-success) 0%, var(--state-success) 50%, var(--state-warning) 80%, var(--state-error) 100%); clip-path: inset(0 77% 0 0);"></div>
</div>
<p class="truncate mt-1" style="font-size: var(--font-size-xs); color: var(--neutral-400);">8核 / 使用1.84核</p>
</div>
<!-- Memory 61% -->
<div class="rounded-lg px-4 py-3" style="background: var(--neutral-50); border: 1px solid var(--neutral-100);">
<div class="flex items-center justify-between mb-2">
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">内存</span>
<span class="font-semibold whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--state-warning);">61%</span>
</div>
<div class="rounded-full overflow-hidden" style="height: 8px; background: var(--neutral-200);">
<div class="rounded-full" style="width: 61%; height: 100%; background: linear-gradient(90deg, var(--state-success) 0%, var(--state-warning) 70%, var(--state-error) 100%); clip-path: inset(0 39% 0 0);"></div>
</div>
<p class="truncate mt-1" style="font-size: var(--font-size-xs); color: var(--neutral-400);">16GB / 已用9.76GB</p>
</div>
<!-- Disk 45% -->
<div class="rounded-lg px-4 py-3" style="background: var(--neutral-50); border: 1px solid var(--neutral-100);">
<div class="flex items-center justify-between mb-2">
<span class="whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">磁盘</span>
<span class="font-semibold whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--state-success);">45%</span>
</div>
<div class="rounded-full overflow-hidden" style="height: 8px; background: var(--neutral-200);">
<div class="rounded-full" style="width: 45%; height: 100%; background: linear-gradient(90deg, var(--state-success) 0%, var(--state-success) 60%, var(--state-warning) 85%, var(--state-error) 100%); clip-path: inset(0 55% 0 0);"></div>
</div>
<p class="truncate mt-1" style="font-size: var(--font-size-xs); color: var(--neutral-400);">500GB / 已用225GB</p>
</div>
</div>
</div>
<!-- ====== Section 2: Monitoring Charts (2 columns) ====== -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5 mb-5">
<!-- Left: API Request Trend (CSS Bar Chart) -->
<div class="rounded-lg p-5" style="background: var(--neutral-0); border: 1px solid var(--neutral-200);">
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-1.5 min-w-0">
<i data-lucide="bar-chart-3" style="width: 16px; height: 16px; color: var(--brand-primary); flex-shrink: 0;"></i>
<span class="font-semibold truncate" style="font-size: var(--font-size-base); color: var(--neutral-800);">API请求量趋势</span>
</div>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--neutral-400);">近24小时</span>
</div>
<!-- Chart Area -->
<div class="flex items-end gap-1" style="height: 140px; padding-bottom: 24px; position: relative;">
<!-- Y-axis label -->
<div class="absolute left-0 top-0 bottom-6 flex flex-col justify-between" style="width: 36px;">
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">10K</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">5K</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">0</span>
</div>
<!-- Bars -->
<div class="flex items-end gap-1 flex-1" style="margin-left: 40px; height: calc(100% - 24px); border-bottom: 1px solid var(--neutral-200);">
<!-- Hour 00-03 (low) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 15%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 10%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 8%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 12%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<!-- Hour 04-07 (rising) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 20%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 35%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 55%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 72%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<!-- Hour 08-11 (peak) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 88%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 95%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 100%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 85%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<!-- Hour 12-15 (plateau) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 78%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 82%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 90%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 86%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<!-- Hour 16-19 (declining) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 70%; background: var(--brand-primary); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 58%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 45%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 35%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<!-- Hour 20-23 (low) -->
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 25%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 18%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
<div class="flex-1 flex flex-col items-center gap-0.5" style="height: 100%;">
<div class="w-full rounded-t" style="height: 14%; background: var(--brand-primary-light); min-height: 2px;"></div>
</div>
</div>
<!-- X-axis labels -->
<div class="absolute bottom-0 left-0 right-0 flex justify-between" style="padding-left: 40px; height: 20px;">
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">00</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">06</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">12</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">18</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">23</span>
</div>
</div>
</div>
<!-- Right: Error Rate Monitor (CSS Line Chart) -->
<div class="rounded-lg p-5" style="background: var(--neutral-0); border: 1px solid var(--neutral-200);">
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-1.5 min-w-0">
<i data-lucide="alert-triangle" style="width: 16px; height: 16px; color: var(--state-warning); flex-shrink: 0;"></i>
<span class="font-semibold truncate" style="font-size: var(--font-size-base); color: var(--neutral-800);">错误率监控</span>
</div>
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--neutral-400);">近24小时</span>
</div>
<!-- Chart Area -->
<div style="height: 140px; padding-bottom: 24px; position: relative;">
<!-- Y-axis label -->
<div class="absolute left-0 top-0 bottom-6 flex flex-col justify-between" style="width: 36px;">
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">5%</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">2.5%</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">0%</span>
</div>
<!-- SVG Line Chart -->
<svg class="absolute" style="left: 40px; top: 0; right: 0; bottom: 24px; width: calc(100% - 40px); height: calc(100% - 24px);" viewBox="0 0 200 100" preserveAspectRatio="none">
<!-- Warning threshold line -->
<line x1="0" y1="40" x2="200" y2="40" stroke="var(--state-warning)" stroke-width="0.5" stroke-dasharray="3,3" opacity="0.5"/>
<!-- Area fill -->
<polygon points="0,70 8,72 16,68 24,65 32,55 40,50 48,45 56,35 64,20 72,30 80,25 88,40 96,35 104,45 112,42 120,38 128,50 136,55 144,60 152,58 160,65 168,68 176,72 184,75 192,78 200,80 200,100 0,100" fill="var(--state-error)" opacity="0.08"/>
<!-- Line -->
<polyline points="0,70 8,72 16,68 24,65 32,55 40,50 48,45 56,35 64,20 72,30 80,25 88,40 96,35 104,45 112,42 120,38 128,50 136,55 144,60 152,58 160,65 168,68 176,72 184,75 192,78 200,80" fill="none" stroke="var(--state-error)" stroke-width="1.5" stroke-linejoin="round" stroke-linecap="round"/>
<!-- Data points -->
<circle cx="64" cy="20" r="2.5" fill="var(--state-error)"/>
<circle cx="80" cy="25" r="2" fill="var(--state-error)"/>
</svg>
<!-- X-axis labels -->
<div class="absolute bottom-0 left-0 right-0 flex justify-between" style="padding-left: 40px; height: 20px;">
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">00</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">06</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">12</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">18</span>
<span class="whitespace-nowrap" style="font-size: 10px; color: var(--neutral-400);">23</span>
</div>
</div>
</div>
</div>
<!-- ====== Section 3: Operation Logs Table ====== -->
<div class="rounded-lg mb-5 overflow-hidden" style="background: var(--neutral-0); border: 1px solid var(--neutral-200);">
<div class="flex items-center justify-between px-5 py-3.5" style="border-bottom: 1px solid var(--neutral-200);">
<div class="flex items-center gap-1.5 min-w-0">
<i data-lucide="scroll-text" style="width: 16px; height: 16px; color: var(--brand-primary); flex-shrink: 0;"></i>
<span class="font-semibold truncate" style="font-size: var(--font-size-base); color: var(--neutral-800);">操作日志</span>
</div>
<div class="flex items-center gap-2 shrink-0 ml-4">
<div class="flex items-center rounded-lg px-2.5" style="height: 32px; background: var(--neutral-100); border: 1px solid var(--neutral-200);">
<i data-lucide="search" style="width: 14px; height: 14px; flex-shrink: 0; color: var(--neutral-400); margin-right: 6px;"></i>
<input type="text" placeholder="搜索日志..." class="bg-transparent border-none outline-none" style="font-size: var(--font-size-sm); color: var(--neutral-900); width: 120px;">
</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full" style="min-width: 600px;">
<thead>
<tr style="background: var(--neutral-50);">
<th class="px-4 py-2.5 text-left font-medium" style="font-size: var(--font-size-xs); color: var(--neutral-500); min-width: 140px;">时间</th>
<th class="px-4 py-2.5 text-left font-medium" style="font-size: var(--font-size-xs); color: var(--neutral-500); min-width: 70px;">级别</th>
<th class="px-4 py-2.5 text-left font-medium" style="font-size: var(--font-size-xs); color: var(--neutral-500); min-width: 90px;">模块</th>
<th class="px-4 py-2.5 text-left font-medium" style="font-size: var(--font-size-xs); color: var(--neutral-500);">操作内容</th>
<th class="px-4 py-2.5 text-left font-medium" style="font-size: var(--font-size-xs); color: var(--neutral-500); min-width: 70px;">操作人</th>
</tr>
</thead>
<tbody>
<!-- Row 1 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 14:32:18</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">信息</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">API网关</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">健康检查通过,所有节点正常响应</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">系统</td>
</tr>
<!-- Row 2 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 14:15:03</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-warning-bg); color: var(--state-warning);">警告</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">消息队列</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">队列积压超过阈值,当前待处理消息 12,580 条</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">系统</td>
</tr>
<!-- Row 3 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 13:58:42</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-error-bg); color: var(--state-error);">错误</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">数据库</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">慢查询告警:会话表查询耗时 3.2s,已触发索引优化</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">DBA</td>
</tr>
<!-- Row 4 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 13:40:11</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">信息</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">CDN</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">CDN缓存刷新完成,共刷新 342 个资源节点</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">运维</td>
</tr>
<!-- Row 5 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 12:20:55</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">信息</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">系统</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">定时备份任务执行成功,备份文件大小 2.3GB</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">系统</td>
</tr>
<!-- Row 6 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 11:05:33</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-warning-bg); color: var(--state-warning);">警告</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">WebSocket</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">ws-node-03 连接数接近上限,当前活跃 4,892 / 5,000</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">系统</td>
</tr>
<!-- Row 7 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 10:30:07</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">信息</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">租户管理</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">新租户「星辰科技」注册审核通过并自动开通</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">管理员</td>
</tr>
<!-- Row 8 -->
<tr style="border-top: 1px solid var(--neutral-100);">
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">2026-07-09 09:15:22</td>
<td class="px-4 py-2.5">
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">信息</span>
</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-700);">系统</td>
<td class="px-4 py-2.5 truncate" style="font-size: var(--font-size-sm); color: var(--neutral-700);">SSL证书自动续期成功,有效期至 2027-07-09</td>
<td class="px-4 py-2.5 whitespace-nowrap" style="font-size: var(--font-size-sm); color: var(--neutral-600);">系统</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- ====== Section 4: Platform Announcement Management ====== -->
<div class="rounded-lg overflow-hidden" style="background: var(--neutral-0); border: 1px solid var(--neutral-200);">
<div class="flex items-center justify-between px-5 py-3.5" style="border-bottom: 1px solid var(--neutral-200);">
<div class="flex items-center gap-1.5 min-w-0">
<i data-lucide="megaphone" style="width: 16px; height: 16px; color: var(--brand-primary); flex-shrink: 0;"></i>
<span class="font-semibold truncate" style="font-size: var(--font-size-base); color: var(--neutral-800);">平台公告</span>
</div>
<button class="flex items-center gap-1.5 px-3 py-1.5 rounded-lg whitespace-nowrap shrink-0" style="font-size: var(--font-size-sm); font-weight: 500; background: var(--brand-primary); color: var(--neutral-0);">
<i data-lucide="plus" style="width: 14px; height: 14px;"></i>
发布公告
</button>
</div>
<!-- Announcement 1 -->
<div class="flex items-start gap-4 px-5 py-4" style="border-bottom: 1px solid var(--neutral-100);">
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<span class="truncate font-medium" style="font-size: var(--font-size-sm); color: var(--neutral-800);">关于7月10日凌晨系统维护的通知</span>
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap shrink-0" style="font-size: var(--font-size-xs); background: var(--state-success-bg); color: var(--state-success);">已发布</span>
</div>
<p class="line-clamp-2 mb-2" style="font-size: var(--font-size-sm); color: var(--neutral-500);">为提升系统性能与稳定性,平台将于2026年7月10日凌晨02:00-04:00进行系统维护升级,届时在线客服服务将暂停约2小时,请各租户提前做好安排。</p>
<div class="flex items-center gap-3">
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--neutral-400);">2026-07-09 10:00</span>
</div>
</div>
<div class="flex items-center gap-1 shrink-0">
<button class="flex items-center justify-center rounded-md" style="width: 28px; height: 28px; color: var(--neutral-400);" title="编辑">
<i data-lucide="pencil" style="width: 14px; height: 14px;"></i>
</button>
<button class="flex items-center justify-center rounded-md" style="width: 28px; height: 28px; color: var(--neutral-400);" title="撤回">
<i data-lucide="undo-2" style="width: 14px; height: 14px;"></i>
</button>
</div>
</div>
<!-- Announcement 2 -->
<div class="flex items-start gap-4 px-5 py-4">
<div class="flex-1 min-w-0">
<div class="flex items-center gap-2 mb-1">
<span class="truncate font-medium" style="font-size: var(--font-size-sm); color: var(--neutral-800);">新版知识库功能上线公告</span>
<span class="inline-flex items-center px-2 py-0.5 rounded whitespace-nowrap shrink-0" style="font-size: var(--font-size-xs); background: var(--state-warning-bg); color: var(--state-warning);">草稿</span>
</div>
<p class="line-clamp-2 mb-2" style="font-size: var(--font-size-sm); color: var(--neutral-500);">全新知识库管理模块已开发完成,支持富文本编辑、自动标签分类、智能搜索推荐等功能,预计下周正式发布,欢迎各租户提前体验反馈。</p>
<div class="flex items-center gap-3">
<span class="whitespace-nowrap" style="font-size: var(--font-size-xs); color: var(--neutral-400);">2026-07-08 16:30</span>
</div>
</div>
<div class="flex items-center gap-1 shrink-0">
<button class="flex items-center justify-center rounded-md" style="width: 28px; height: 28px; color: var(--neutral-400);" title="编辑">
<i data-lucide="pencil" style="width: 14px; height: 14px;"></i>
</button>
<button class="flex items-center justify-center rounded-md" style="width: 28px; height: 28px; color: var(--neutral-400);" title="撤回">
<i data-lucide="undo-2" style="width: 14px; height: 14px;"></i>
</button>
</div>
</div>
</div>
</div>
</section>
</main>
<script>lucide.createIcons();</script>
</body>
</html>