parent
d9e8e6b578
commit
9629af961f
@ -0,0 +1,190 @@
|
||||
# 集群管理系统前端项目
|
||||
|
||||
基于 Hadoop 的集群管理系统前端界面,提供集群状态监控、日志查询、故障诊断和自动修复功能。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
src/fronted/
|
||||
├── index.html # 主页面文件(重构后)
|
||||
├── 原型图.html # 原始原型文件(已优化)
|
||||
├── assets/ # 静态资源目录
|
||||
│ ├── images/ # 图片资源
|
||||
│ ├── fonts/ # 字体文件
|
||||
│ └── icons/ # 图标文件
|
||||
├── components/ # 可复用组件
|
||||
│ ├── common/ # 通用组件
|
||||
│ ├── layout/ # 布局组件
|
||||
│ └── ui/ # UI 组件
|
||||
├── styles/ # 样式文件
|
||||
│ ├── base/ # 基础样式
|
||||
│ │ ├── reset.css # CSS 重置
|
||||
│ │ └── variables.css # CSS 变量
|
||||
│ ├── components/ # 组件样式
|
||||
│ │ ├── header.css # 头部样式
|
||||
│ │ ├── sidebar.css # 侧边栏样式
|
||||
│ │ ├── dashboard.css # 仪表板样式
|
||||
│ │ └── buttons.css # 按钮样式
|
||||
│ ├── layouts/ # 布局样式
|
||||
│ │ ├── main.css # 主布局
|
||||
│ │ └── responsive.css # 响应式布局
|
||||
│ ├── utils/ # 工具样式
|
||||
│ │ └── utilities.css # 原子类
|
||||
│ └── main.css # 主样式文件
|
||||
├── utils/ # 工具函数
|
||||
│ ├── charts.js # 图表管理
|
||||
│ ├── navigation.js # 导航管理
|
||||
│ └── responsive.js # 响应式交互
|
||||
└── views/ # 页面级组件
|
||||
```
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 🎯 核心功能
|
||||
- **集群状态监控**: 实时显示节点状态、CPU、内存使用情况
|
||||
- **日志查询**: 支持多条件筛选的日志查询功能
|
||||
- **故障诊断**: 自动检测和诊断系统故障
|
||||
- **自动修复**: 提供故障修复建议和自动修复功能
|
||||
|
||||
### 🎨 设计规范
|
||||
- **HTML5 语义化**: 使用 `<header>`, `<nav>`, `<main>`, `<aside>`, `<section>`, `<article>` 等语义化标签
|
||||
- **BEM 命名规范**: 所有 CSS 类名遵循 BEM (Block Element Modifier) 命名规范
|
||||
- **CSS 模块化**: 样式按功能模块拆分,便于维护和复用
|
||||
- **响应式设计**: 支持桌面端、平板端和移动端适配
|
||||
|
||||
### 📱 响应式特性
|
||||
- **移动端优先**: 采用移动端优先的响应式设计策略
|
||||
- **断点设计**:
|
||||
- 移动端: ≤ 768px
|
||||
- 平板端: 769px - 1024px
|
||||
- 桌面端: ≥ 1025px
|
||||
- **触摸手势**: 支持滑动手势操作侧边栏
|
||||
- **自适应布局**: 图表、表格、卡片等组件自动适配不同屏幕尺寸
|
||||
|
||||
### ♿ 无障碍访问
|
||||
- **ARIA 标签**: 完整的 ARIA 属性支持
|
||||
- **键盘导航**: 支持 Tab 键和 ESC 键操作
|
||||
- **屏幕阅读器**: 兼容主流屏幕阅读器
|
||||
- **焦点管理**: 清晰的焦点指示和管理
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **HTML5**: 语义化标签和现代 Web 标准
|
||||
- **CSS3**: Flexbox、Grid、CSS Variables、媒体查询
|
||||
- **JavaScript ES6+**: 模块化、类、箭头函数等现代语法
|
||||
- **ECharts**: 数据可视化图表库
|
||||
- **Font Awesome**: 图标库
|
||||
- **Tailwind CSS**: 原子化 CSS 框架(临时保留)
|
||||
|
||||
## 开发规范
|
||||
|
||||
### CSS 规范
|
||||
- **选择器特异性**: 不超过 3 级嵌套
|
||||
- **BEM 命名**: 严格遵循 BEM 命名规范
|
||||
- **CSS 变量**: 使用 CSS 自定义属性管理设计系统
|
||||
- **模块化**: 按功能拆分 CSS 文件
|
||||
|
||||
### JavaScript 规范
|
||||
- **ES6+ 语法**: 使用现代 JavaScript 语法
|
||||
- **模块化**: 功能按模块拆分
|
||||
- **类设计**: 使用 ES6 类组织代码
|
||||
- **事件管理**: 统一的事件绑定和解绑
|
||||
|
||||
### HTML 规范
|
||||
- **语义化**: 使用合适的 HTML5 语义化标签
|
||||
- **无障碍**: 完整的 ARIA 属性和无障碍支持
|
||||
- **SEO 友好**: 合理的 meta 标签和结构化数据
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 启动开发服务器
|
||||
|
||||
```bash
|
||||
cd /home/devbox/project/src/fronted
|
||||
python3 -m http.server 8080
|
||||
```
|
||||
|
||||
### 2. 访问应用
|
||||
|
||||
打开浏览器访问: `http://localhost:8080/index.html`
|
||||
|
||||
### 3. 功能测试
|
||||
|
||||
- **导航切换**: 点击顶部导航项切换不同页面
|
||||
- **响应式测试**: 调整浏览器窗口大小测试响应式布局
|
||||
- **移动端测试**: 使用浏览器开发者工具模拟移动设备
|
||||
- **无障碍测试**: 使用 Tab 键测试键盘导航
|
||||
|
||||
## 浏览器兼容性
|
||||
|
||||
- **现代浏览器**: Chrome 60+, Firefox 60+, Safari 12+, Edge 79+
|
||||
- **移动浏览器**: iOS Safari 12+, Chrome Mobile 60+
|
||||
- **特性支持**: CSS Grid, Flexbox, CSS Variables, ES6+
|
||||
|
||||
## 性能优化
|
||||
|
||||
- **CSS 优化**: 模块化加载,减少重复样式
|
||||
- **JavaScript 优化**: 按需加载,事件委托
|
||||
- **图片优化**: 使用 SVG 矢量图标
|
||||
- **缓存策略**: 合理的资源缓存设置
|
||||
|
||||
## 维护说明
|
||||
|
||||
### 添加新页面
|
||||
1. 在 `views/` 目录创建页面组件
|
||||
2. 在 `styles/components/` 添加对应样式
|
||||
3. 在 `utils/navigation.js` 中添加路由逻辑
|
||||
|
||||
### 添加新组件
|
||||
1. 在 `components/` 对应目录创建组件
|
||||
2. 在 `styles/components/` 添加组件样式
|
||||
3. 遵循 BEM 命名规范
|
||||
|
||||
### 样式修改
|
||||
1. 优先修改 CSS 变量 (`styles/base/variables.css`)
|
||||
2. 组件样式修改对应的组件 CSS 文件
|
||||
3. 确保响应式适配正常
|
||||
|
||||
## 部署说明
|
||||
|
||||
### 生产环境部署
|
||||
1. 移除 Tailwind CSS CDN 引用
|
||||
2. 压缩 CSS 和 JavaScript 文件
|
||||
3. 配置适当的 HTTP 缓存头
|
||||
4. 启用 Gzip 压缩
|
||||
|
||||
### 静态资源优化
|
||||
- 图片压缩和格式优化
|
||||
- CSS 和 JavaScript 文件合并压缩
|
||||
- 字体文件子集化
|
||||
- CDN 资源配置
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v2.0.0 (2025-10-31)
|
||||
- ✨ 完全重构项目结构
|
||||
- ✨ 实现 HTML5 语义化标签
|
||||
- ✨ 采用 BEM 命名规范
|
||||
- ✨ 模块化 CSS 架构
|
||||
- ✨ 响应式布局支持
|
||||
- ✨ 无障碍访问优化
|
||||
- ✨ 现代 JavaScript 重构
|
||||
|
||||
### v1.0.0 (2025-10-30)
|
||||
- 🎉 初始版本发布
|
||||
- 📊 基础仪表板功能
|
||||
- 🔍 日志查询功能
|
||||
- 🔧 故障诊断功能
|
||||
- 🛠️ 自动修复功能
|
||||
|
||||
## 贡献指南
|
||||
|
||||
1. Fork 项目
|
||||
2. 创建功能分支
|
||||
3. 提交代码变更
|
||||
4. 推送到分支
|
||||
5. 创建 Pull Request
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License - 详见 LICENSE 文件
|
||||
|
After Width: | Height: | Size: 35 KiB |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,60 @@
|
||||
/* CSS Reset and Base Styles */
|
||||
/* 基础重置样式 */
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
background-color: #f9fafb;
|
||||
color: #1e293b;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 移除默认样式 */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
input, textarea, select {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
/* CSS Custom Properties (Variables) */
|
||||
/* CSS 自定义属性(变量)定义 */
|
||||
|
||||
:root {
|
||||
/* 颜色系统 - Color System */
|
||||
--color-primary: #3b82f6;
|
||||
--color-primary-light: #60a5fa;
|
||||
--color-primary-dark: #2563eb;
|
||||
|
||||
--color-secondary: #64748b;
|
||||
--color-secondary-light: #94a3b8;
|
||||
--color-secondary-dark: #475569;
|
||||
|
||||
--color-success: #10b981;
|
||||
--color-warning: #f59e0b;
|
||||
--color-error: #ef4444;
|
||||
--color-info: #06b6d4;
|
||||
|
||||
/* 中性色 - Neutral Colors */
|
||||
--color-white: #ffffff;
|
||||
--color-gray-50: #f9fafb;
|
||||
--color-gray-100: #f3f4f6;
|
||||
--color-gray-200: #e5e7eb;
|
||||
--color-gray-300: #d1d5db;
|
||||
--color-gray-400: #9ca3af;
|
||||
--color-gray-500: #6b7280;
|
||||
--color-gray-600: #4b5563;
|
||||
--color-gray-700: #374151;
|
||||
--color-gray-800: #1f2937;
|
||||
--color-gray-900: #111827;
|
||||
|
||||
/* 字体系统 - Typography */
|
||||
--font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--font-family-logo: "Pacifico", serif;
|
||||
|
||||
--font-size-xs: 0.75rem; /* 12px */
|
||||
--font-size-sm: 0.875rem; /* 14px */
|
||||
--font-size-base: 1rem; /* 16px */
|
||||
--font-size-lg: 1.125rem; /* 18px */
|
||||
--font-size-xl: 1.25rem; /* 20px */
|
||||
--font-size-2xl: 1.5rem; /* 24px */
|
||||
--font-size-3xl: 1.875rem; /* 30px */
|
||||
|
||||
--font-weight-normal: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
||||
/* 间距系统 - Spacing */
|
||||
--spacing-1: 0.25rem; /* 4px */
|
||||
--spacing-2: 0.5rem; /* 8px */
|
||||
--spacing-3: 0.75rem; /* 12px */
|
||||
--spacing-4: 1rem; /* 16px */
|
||||
--spacing-5: 1.25rem; /* 20px */
|
||||
--spacing-6: 1.5rem; /* 24px */
|
||||
--spacing-8: 2rem; /* 32px */
|
||||
--spacing-10: 2.5rem; /* 40px */
|
||||
--spacing-12: 3rem; /* 48px */
|
||||
|
||||
/* 边框圆角 - Border Radius */
|
||||
--border-radius-none: 0px;
|
||||
--border-radius-sm: 2px;
|
||||
--border-radius-base: 4px;
|
||||
--border-radius-md: 8px;
|
||||
--border-radius-lg: 12px;
|
||||
--border-radius-xl: 16px;
|
||||
--border-radius-2xl: 20px;
|
||||
--border-radius-full: 9999px;
|
||||
|
||||
/* 阴影系统 - Shadow System */
|
||||
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--shadow-base: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
||||
|
||||
/* 过渡动画 - Transitions */
|
||||
--transition-fast: 150ms ease-in-out;
|
||||
--transition-base: 250ms ease-in-out;
|
||||
--transition-slow: 350ms ease-in-out;
|
||||
|
||||
/* 断点 - Breakpoints */
|
||||
--breakpoint-sm: 640px;
|
||||
--breakpoint-md: 768px;
|
||||
--breakpoint-lg: 1024px;
|
||||
--breakpoint-xl: 1280px;
|
||||
--breakpoint-2xl: 1536px;
|
||||
}
|
||||
@ -0,0 +1,299 @@
|
||||
/* Button Component Styles */
|
||||
/* 按钮组件样式 - 使用 BEM 命名规范 */
|
||||
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--spacing-2);
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 1.5;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--border-radius-base);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 按钮尺寸变体 */
|
||||
.btn--sm {
|
||||
padding: var(--spacing-1) var(--spacing-3);
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.btn--md {
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.btn--lg {
|
||||
padding: var(--spacing-3) var(--spacing-6);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
/* 主要按钮 */
|
||||
.btn--primary {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-white);
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.btn--primary:hover {
|
||||
background-color: var(--color-primary-dark);
|
||||
border-color: var(--color-primary-dark);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.btn--primary:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* 次要按钮 */
|
||||
.btn--secondary {
|
||||
background-color: var(--color-gray-100);
|
||||
color: var(--color-gray-700);
|
||||
border-color: var(--color-gray-300);
|
||||
}
|
||||
|
||||
.btn--secondary:hover {
|
||||
background-color: var(--color-gray-200);
|
||||
border-color: var(--color-gray-400);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.btn--secondary:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
/* 成功按钮 */
|
||||
.btn--success {
|
||||
background-color: var(--color-success);
|
||||
color: var(--color-white);
|
||||
border-color: var(--color-success);
|
||||
}
|
||||
|
||||
.btn--success:hover {
|
||||
background-color: #059669;
|
||||
border-color: #059669;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* 警告按钮 */
|
||||
.btn--warning {
|
||||
background-color: var(--color-warning);
|
||||
color: var(--color-white);
|
||||
border-color: var(--color-warning);
|
||||
}
|
||||
|
||||
.btn--warning:hover {
|
||||
background-color: #d97706;
|
||||
border-color: #d97706;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* 危险按钮 */
|
||||
.btn--danger {
|
||||
background-color: var(--color-error);
|
||||
color: var(--color-white);
|
||||
border-color: var(--color-error);
|
||||
}
|
||||
|
||||
.btn--danger:hover {
|
||||
background-color: #dc2626;
|
||||
border-color: #dc2626;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* 轮廓按钮 */
|
||||
.btn--outline {
|
||||
background-color: transparent;
|
||||
color: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.btn--outline:hover {
|
||||
background-color: var(--color-primary);
|
||||
color: var(--color-white);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* 幽灵按钮 */
|
||||
.btn--ghost {
|
||||
background-color: transparent;
|
||||
color: var(--color-gray-700);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.btn--ghost:hover {
|
||||
background-color: var(--color-gray-100);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
/* 链接样式按钮 */
|
||||
.btn--link {
|
||||
background-color: transparent;
|
||||
color: var(--color-primary);
|
||||
border-color: transparent;
|
||||
padding: 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn--link:hover {
|
||||
color: var(--color-primary-dark);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 圆形按钮 */
|
||||
.btn--rounded {
|
||||
border-radius: var(--border-radius-full);
|
||||
}
|
||||
|
||||
/* 方形按钮 */
|
||||
.btn--square {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* 图标按钮 */
|
||||
.btn--icon-only {
|
||||
padding: var(--spacing-2);
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.btn--icon-only.btn--sm {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: var(--spacing-1);
|
||||
}
|
||||
|
||||
.btn--icon-only.btn--lg {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
|
||||
/* 按钮图标 */
|
||||
.btn__icon {
|
||||
font-size: 1em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.btn__icon--left {
|
||||
margin-right: var(--spacing-2);
|
||||
}
|
||||
|
||||
.btn__icon--right {
|
||||
margin-left: var(--spacing-2);
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.btn--loading {
|
||||
position: relative;
|
||||
color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn--loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin: -0.5rem 0 0 -0.5rem;
|
||||
border: 2px solid currentColor;
|
||||
border-radius: var(--border-radius-full);
|
||||
border-top-color: transparent;
|
||||
animation: btn-spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes btn-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮组 */
|
||||
.btn-group {
|
||||
display: inline-flex;
|
||||
border-radius: var(--border-radius-base);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.btn-group .btn {
|
||||
border-radius: 0;
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.btn-group .btn:first-child {
|
||||
border-top-left-radius: var(--border-radius-base);
|
||||
border-bottom-left-radius: var(--border-radius-base);
|
||||
}
|
||||
|
||||
.btn-group .btn:last-child {
|
||||
border-top-right-radius: var(--border-radius-base);
|
||||
border-bottom-right-radius: var(--border-radius-base);
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.btn-group .btn:not(:first-child):not(:last-child) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.btn {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
.btn--sm {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.btn-group .btn {
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.btn-group .btn:first-child {
|
||||
border-radius: var(--border-radius-base) var(--border-radius-base) 0 0;
|
||||
}
|
||||
|
||||
.btn-group .btn:last-child {
|
||||
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,263 @@
|
||||
/* Dashboard Component Styles */
|
||||
/* 仪表板组件样式 - 使用 BEM 命名规范 */
|
||||
|
||||
.dashboard {
|
||||
padding: var(--spacing-6);
|
||||
background-color: var(--color-gray-50);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 仪表板标题区域 */
|
||||
.dashboard__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--spacing-6);
|
||||
}
|
||||
|
||||
.dashboard__title {
|
||||
font-size: var(--font-size-2xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
.dashboard__update-time {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-500);
|
||||
}
|
||||
|
||||
/* 统计卡片网格 */
|
||||
.dashboard__stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: var(--spacing-6);
|
||||
margin-bottom: var(--spacing-8);
|
||||
}
|
||||
|
||||
/* 统计卡片样式 */
|
||||
.dashboard__stat-card {
|
||||
background-color: var(--color-white);
|
||||
padding: var(--spacing-6);
|
||||
border-radius: var(--border-radius-xl);
|
||||
box-shadow: var(--shadow-base);
|
||||
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.dashboard__stat-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.dashboard__stat-card-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dashboard__stat-card-label {
|
||||
color: var(--color-gray-500);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
margin-bottom: var(--spacing-2);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-value {
|
||||
font-size: var(--font-size-3xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-value--success {
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-value--warning {
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-value--error {
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-icon {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-icon--primary {
|
||||
background-color: rgba(59, 130, 246, 0.1);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-icon--success {
|
||||
background-color: rgba(16, 185, 129, 0.1);
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-icon--warning {
|
||||
background-color: rgba(245, 158, 11, 0.1);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.dashboard__stat-card-icon--error {
|
||||
background-color: rgba(239, 68, 68, 0.1);
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
/* 图表网格 */
|
||||
.dashboard__charts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: var(--spacing-6);
|
||||
margin-bottom: var(--spacing-8);
|
||||
}
|
||||
|
||||
/* 图表卡片 */
|
||||
.dashboard__chart-card {
|
||||
background-color: var(--color-white);
|
||||
padding: var(--spacing-6);
|
||||
border-radius: var(--border-radius-xl);
|
||||
box-shadow: var(--shadow-base);
|
||||
}
|
||||
|
||||
.dashboard__chart-title {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-gray-900);
|
||||
margin-bottom: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__chart-container {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 表格容器 */
|
||||
.dashboard__table-container {
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--border-radius-xl);
|
||||
box-shadow: var(--shadow-base);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dashboard__table-header {
|
||||
padding: var(--spacing-6) var(--spacing-6) var(--spacing-4);
|
||||
border-bottom: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
.dashboard__table-title {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.dashboard__table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.dashboard__table-head {
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
.dashboard__table-th {
|
||||
padding: var(--spacing-3) var(--spacing-6);
|
||||
text-align: left;
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-gray-500);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.dashboard__table-td {
|
||||
padding: var(--spacing-4) var(--spacing-6);
|
||||
border-top: 1px solid var(--color-gray-200);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
.dashboard__table-row:hover {
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
/* 状态指示器 */
|
||||
.dashboard__status-indicator {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.dashboard__status-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: var(--border-radius-full);
|
||||
}
|
||||
|
||||
.dashboard__status-dot--running {
|
||||
background-color: var(--color-success);
|
||||
}
|
||||
|
||||
.dashboard__status-dot--warning {
|
||||
background-color: var(--color-warning);
|
||||
}
|
||||
|
||||
.dashboard__status-dot--error {
|
||||
background-color: var(--color-error);
|
||||
}
|
||||
|
||||
.dashboard__status-text {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1024px) {
|
||||
.dashboard__stats-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__charts-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dashboard {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.dashboard__stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.dashboard__stat-card {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__chart-card {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__table-container {
|
||||
overflow-x: auto;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,283 @@
|
||||
/* Header Component Styles */
|
||||
/* 头部组件样式 - 使用 BEM 命名规范 */
|
||||
|
||||
.header {
|
||||
background-color: var(--color-white);
|
||||
box-shadow: var(--shadow-sm);
|
||||
padding: var(--spacing-4) var(--spacing-6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative; /* 供移动端展开的导航定位 */
|
||||
}
|
||||
|
||||
/* 头部左侧区域 */
|
||||
.header__left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-10);
|
||||
}
|
||||
|
||||
/* 移动端菜单按钮(默认隐藏,移动端显示) */
|
||||
.header__mobile-menu-btn {
|
||||
display: none;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: var(--border-radius-md);
|
||||
background-color: var(--color-gray-200);
|
||||
color: var(--color-gray-600);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__mobile-menu-btn:hover {
|
||||
background-color: var(--color-gray-300);
|
||||
}
|
||||
|
||||
/* Logo 样式 */
|
||||
.header__logo {
|
||||
font-size: var(--font-size-xl);
|
||||
font-family: var(--font-family-logo);
|
||||
color: var(--color-primary);
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
|
||||
/* 主导航容器 */
|
||||
.header__nav {
|
||||
display: flex;
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
/* 导航项基础样式 */
|
||||
.header__nav-item {
|
||||
padding: var(--spacing-3) var(--spacing-3);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--color-gray-700);
|
||||
transition: color var(--transition-fast);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 导航项悬停和激活状态 */
|
||||
.header__nav-item:hover,
|
||||
.header__nav-item--active {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* 下拉菜单容器 */
|
||||
.header__dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header__dropdown-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.header__dropdown-icon {
|
||||
font-size: var(--font-size-xs);
|
||||
transition: transform var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__dropdown:hover .header__dropdown-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* 下拉菜单内容 */
|
||||
.header__dropdown-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin-top: var(--spacing-1);
|
||||
width: 12rem;
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--border-radius-md);
|
||||
box-shadow: var(--shadow-lg);
|
||||
z-index: 10;
|
||||
padding: var(--spacing-1) 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-8px);
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__dropdown:hover .header__dropdown-menu {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* 下拉菜单显隐状态(脚本控制) */
|
||||
.header__dropdown-menu--show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.header__dropdown--active .header__dropdown-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.header__dropdown-item {
|
||||
display: block;
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-700);
|
||||
transition: background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__dropdown-item:hover {
|
||||
background-color: var(--color-gray-100);
|
||||
}
|
||||
|
||||
/* 头部右侧区域 */
|
||||
.header__right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
/* 搜索框容器 */
|
||||
.header__search {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header__search-input {
|
||||
padding-left: var(--spacing-10);
|
||||
padding-right: var(--spacing-4);
|
||||
padding-top: var(--spacing-2);
|
||||
padding-bottom: var(--spacing-2);
|
||||
font-size: var(--font-size-sm);
|
||||
border: 1px solid var(--color-gray-300);
|
||||
border-radius: var(--border-radius-md);
|
||||
background-color: var(--color-white);
|
||||
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__search-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.header__search-icon {
|
||||
position: absolute;
|
||||
left: var(--spacing-3);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--color-gray-400);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
/* 用户菜单 */
|
||||
.header__user-menu {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header__user-avatar {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
background-color: var(--color-gray-200);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__user-avatar:hover {
|
||||
background-color: var(--color-gray-300);
|
||||
}
|
||||
|
||||
.header__user-avatar-icon {
|
||||
color: var(--color-gray-600);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
/* 用户下拉菜单 */
|
||||
.header__user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: var(--spacing-2);
|
||||
width: 12rem;
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--border-radius-md);
|
||||
box-shadow: var(--shadow-lg);
|
||||
z-index: 20;
|
||||
padding: var(--spacing-1) 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(-8px);
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__user-menu:hover .header__user-dropdown {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* 用户菜单显隐状态(脚本控制) */
|
||||
.header__user-dropdown--show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.header__user-dropdown-item {
|
||||
display: block;
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-700);
|
||||
transition: background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.header__user-dropdown-item:hover {
|
||||
background-color: var(--color-gray-100);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
}
|
||||
|
||||
.header__left {
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
/* 移动端显示菜单按钮 */
|
||||
.header__mobile-menu-btn {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* 移动端导航默认隐藏,展开时作为下拉面板显示 */
|
||||
.header__nav {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-2);
|
||||
background-color: var(--color-white);
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
box-shadow: var(--shadow-lg);
|
||||
z-index: 30;
|
||||
border-radius: var(--border-radius-md);
|
||||
}
|
||||
|
||||
.header__nav--mobile-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header__search {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,282 @@
|
||||
/* Main Layout Styles */
|
||||
/* 主布局样式 - 使用 BEM 命名规范 */
|
||||
|
||||
.layout {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
/* 主容器 */
|
||||
.layout__container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 主内容区域 */
|
||||
.layout__main {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
/* 内容包装器 */
|
||||
.layout__content {
|
||||
padding: var(--spacing-6);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* 页面标题区域 */
|
||||
.layout__page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--spacing-6);
|
||||
padding-bottom: var(--spacing-4);
|
||||
border-bottom: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
.layout__page-title {
|
||||
font-size: var(--font-size-2xl);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-gray-900);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.layout__page-subtitle {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-500);
|
||||
margin-top: var(--spacing-1);
|
||||
}
|
||||
|
||||
.layout__page-actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-3);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 网格系统 */
|
||||
.layout__grid {
|
||||
display: grid;
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
.layout__grid--1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.layout__grid--2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.layout__grid--3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
.layout__grid--auto {
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
}
|
||||
|
||||
/* 卡片布局 */
|
||||
.layout__card {
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--border-radius-xl);
|
||||
box-shadow: var(--shadow-base);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.layout__card-header {
|
||||
padding: var(--spacing-6) var(--spacing-6) var(--spacing-4);
|
||||
border-bottom: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
.layout__card-title {
|
||||
font-size: var(--font-size-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-gray-900);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.layout__card-description {
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--color-gray-500);
|
||||
margin-top: var(--spacing-1);
|
||||
}
|
||||
|
||||
.layout__card-body {
|
||||
padding: var(--spacing-6);
|
||||
}
|
||||
|
||||
.layout__card-footer {
|
||||
padding: var(--spacing-4) var(--spacing-6);
|
||||
background-color: var(--color-gray-50);
|
||||
border-top: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
/* 分隔符 */
|
||||
.layout__divider {
|
||||
height: 1px;
|
||||
background-color: var(--color-gray-200);
|
||||
margin: var(--spacing-6) 0;
|
||||
}
|
||||
|
||||
.layout__divider--vertical {
|
||||
width: 1px;
|
||||
height: auto;
|
||||
margin: 0 var(--spacing-6);
|
||||
}
|
||||
|
||||
/* 间距工具类 */
|
||||
.layout__section {
|
||||
margin-bottom: var(--spacing-10);
|
||||
}
|
||||
|
||||
.layout__section:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 滚动容器 */
|
||||
.layout__scroll-container {
|
||||
overflow: auto;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.layout__scroll-container--horizontal {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.layout__scroll-container--vertical {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* 粘性定位 */
|
||||
.layout__sticky-top {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
.layout__sticky-bottom {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
/* 居中容器 */
|
||||
.layout__centered {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.layout__centered-content {
|
||||
text-align: center;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
/* 响应式断点 */
|
||||
@media (max-width: 1280px) {
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.layout__content {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__grid--3,
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.layout__page-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__page-actions {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.layout__container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.layout__content {
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
|
||||
.layout__grid--2,
|
||||
.layout__grid--3,
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.layout__grid {
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__card-header,
|
||||
.layout__card-body,
|
||||
.layout__card-footer {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__page-title {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
.layout__section {
|
||||
margin-bottom: var(--spacing-6);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.layout__content {
|
||||
padding: var(--spacing-2);
|
||||
}
|
||||
|
||||
.layout__page-header {
|
||||
margin-bottom: var(--spacing-4);
|
||||
padding-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
.layout__card-header,
|
||||
.layout__card-body,
|
||||
.layout__card-footer {
|
||||
padding: var(--spacing-3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
@media print {
|
||||
.layout {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.layout__card {
|
||||
box-shadow: none;
|
||||
border: 1px solid var(--color-gray-300);
|
||||
}
|
||||
|
||||
.layout__page-actions {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,444 @@
|
||||
/* Responsive Layout Styles */
|
||||
/* 响应式布局样式 - 移动端适配和响应式设计 */
|
||||
|
||||
/* ==================== 移动端优先的响应式设计 ==================== */
|
||||
|
||||
/* 基础布局响应式调整 */
|
||||
.layout {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.layout__container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-height: 0; /* 防止 flex 子元素溢出 */
|
||||
}
|
||||
|
||||
/* ==================== 头部响应式设计 ==================== */
|
||||
|
||||
/* 移动端头部调整 */
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-3);
|
||||
}
|
||||
|
||||
.header__left {
|
||||
gap: var(--spacing-4);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.header__logo {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
/* 移动端导航隐藏,使用汉堡菜单 */
|
||||
.header__nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--color-white);
|
||||
box-shadow: var(--shadow-lg);
|
||||
flex-direction: column;
|
||||
padding: var(--spacing-4);
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.header__nav--mobile-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header__nav-item {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
border-radius: var(--border-radius-md);
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* 移动端汉堡菜单按钮 */
|
||||
.header__mobile-menu-btn {
|
||||
display: block;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: var(--font-size-lg);
|
||||
color: var(--color-gray-700);
|
||||
cursor: pointer;
|
||||
padding: var(--spacing-2);
|
||||
}
|
||||
|
||||
.header__right {
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.header__search {
|
||||
display: none; /* 移动端隐藏搜索框 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面端汉堡菜单隐藏 */
|
||||
@media (min-width: 769px) {
|
||||
.header__mobile-menu-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 侧边栏响应式设计 ==================== */
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
flex-shrink: 0;
|
||||
transition: transform var(--transition-normal);
|
||||
}
|
||||
|
||||
/* 移动端侧边栏 */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
z-index: 40;
|
||||
background-color: var(--color-white);
|
||||
transform: translateX(-100%);
|
||||
box-shadow: var(--shadow-xl);
|
||||
}
|
||||
|
||||
.sidebar--mobile-open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
/* 移动端遮罩层 */
|
||||
.sidebar-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 30;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity var(--transition-normal), visibility var(--transition-normal);
|
||||
}
|
||||
|
||||
.sidebar-overlay--show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* 调整主内容区域 */
|
||||
.layout__main {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板端侧边栏 */
|
||||
@media (min-width: 769px) and (max-width: 1024px) {
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 主内容区域响应式设计 ==================== */
|
||||
|
||||
.layout__main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.layout__content {
|
||||
padding: var(--spacing-6);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* 移动端主内容调整 */
|
||||
@media (max-width: 768px) {
|
||||
.layout__content {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__page-header {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-4);
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.layout__page-actions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.layout__page-actions .btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 仪表板响应式设计 ==================== */
|
||||
|
||||
/* 统计卡片网格 */
|
||||
.dashboard__stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
/* 移动端统计卡片 */
|
||||
@media (max-width: 640px) {
|
||||
.dashboard__stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--spacing-3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小屏幕单列显示 */
|
||||
@media (max-width: 480px) {
|
||||
.dashboard__stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
/* 图表网格响应式 */
|
||||
.dashboard__charts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: var(--spacing-6);
|
||||
}
|
||||
|
||||
/* 移动端图表 */
|
||||
@media (max-width: 768px) {
|
||||
.dashboard__charts-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.dashboard__chart-container {
|
||||
height: 250px; /* 移动端降低图表高度 */
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小屏幕图表 */
|
||||
@media (max-width: 480px) {
|
||||
.dashboard__charts-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.dashboard__chart-container {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 表格响应式设计 ==================== */
|
||||
|
||||
/* 移动端表格滚动 */
|
||||
@media (max-width: 768px) {
|
||||
.dashboard__table-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.dashboard__table {
|
||||
min-width: 600px; /* 确保表格有最小宽度 */
|
||||
}
|
||||
|
||||
.dashboard__table-th,
|
||||
.dashboard__table-td {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
}
|
||||
|
||||
/* 超小屏幕表格优化 */
|
||||
@media (max-width: 480px) {
|
||||
.dashboard__table {
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
.dashboard__table-th,
|
||||
.dashboard__table-td {
|
||||
padding: var(--spacing-2);
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
/* 隐藏不重要的列 */
|
||||
.dashboard__table-th:nth-child(6),
|
||||
.dashboard__table-td:nth-child(6) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 卡片响应式设计 ==================== */
|
||||
|
||||
.layout__card {
|
||||
margin-bottom: var(--spacing-6);
|
||||
}
|
||||
|
||||
/* 移动端卡片 */
|
||||
@media (max-width: 768px) {
|
||||
.layout__card {
|
||||
margin-bottom: var(--spacing-4);
|
||||
border-radius: var(--border-radius-lg);
|
||||
}
|
||||
|
||||
.layout__card-body {
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 网格系统响应式 ==================== */
|
||||
|
||||
.layout__grid {
|
||||
display: grid;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
.layout__grid--2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.layout__grid--3 {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
/* 移动端网格调整 */
|
||||
@media (max-width: 768px) {
|
||||
.layout__grid--2,
|
||||
.layout__grid--3,
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-3);
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板端网格调整 */
|
||||
@media (min-width: 769px) and (max-width: 1024px) {
|
||||
.layout__grid--3,
|
||||
.layout__grid--4 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 按钮响应式设计 ==================== */
|
||||
|
||||
/* 移动端按钮 */
|
||||
@media (max-width: 768px) {
|
||||
.btn {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.btn--large {
|
||||
padding: var(--spacing-4) var(--spacing-6);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
.btn--small {
|
||||
padding: var(--spacing-2) var(--spacing-3);
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 下拉菜单响应式设计 ==================== */
|
||||
|
||||
/* 移动端下拉菜单 */
|
||||
@media (max-width: 768px) {
|
||||
.header__dropdown-menu,
|
||||
.header__user-dropdown {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: none;
|
||||
border-radius: var(--border-radius-lg) var(--border-radius-lg) 0 0;
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 工具类响应式扩展 ==================== */
|
||||
|
||||
/* 移动端显示/隐藏 */
|
||||
@media (max-width: 640px) {
|
||||
.u-hidden-mobile {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-block-mobile {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.u-flex-mobile {
|
||||
display: flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板端显示/隐藏 */
|
||||
@media (min-width: 641px) and (max-width: 1024px) {
|
||||
.u-hidden-tablet {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-block-tablet {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.u-flex-tablet {
|
||||
display: flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面端显示/隐藏 */
|
||||
@media (min-width: 1025px) {
|
||||
.u-hidden-desktop {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-block-desktop {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.u-flex-desktop {
|
||||
display: flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 打印样式 ==================== */
|
||||
|
||||
@media print {
|
||||
.header,
|
||||
.sidebar,
|
||||
.layout__page-actions {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.layout__main {
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.layout__content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.dashboard__chart-container {
|
||||
height: 300px !important;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.layout__card {
|
||||
break-inside: avoid;
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,281 @@
|
||||
/* Main Stylesheet */
|
||||
/* 主样式表 - 导入所有模块化样式 */
|
||||
|
||||
/* 基础样式 */
|
||||
@import './base/reset.css';
|
||||
@import './base/variables.css';
|
||||
|
||||
/* 布局样式 */
|
||||
@import './layouts/main.css';
|
||||
@import './layouts/responsive.css';
|
||||
|
||||
/* 组件样式 */
|
||||
@import './components/header.css';
|
||||
@import './components/sidebar.css';
|
||||
@import './components/dashboard.css';
|
||||
@import './components/buttons.css';
|
||||
|
||||
/* 工具类 */
|
||||
@import './utils/utilities.css';
|
||||
|
||||
/* 全局样式补充 */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-family-base);
|
||||
background-color: var(--color-gray-50);
|
||||
color: var(--color-gray-900);
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* 焦点样式 */
|
||||
*:focus {
|
||||
outline: 2px solid var(--color-primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
*:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 选择文本样式 */
|
||||
::selection {
|
||||
background-color: rgba(59, 130, 246, 0.2);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: var(--color-gray-100);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-gray-300);
|
||||
border-radius: var(--border-radius-base);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--color-gray-400);
|
||||
}
|
||||
|
||||
/* 打印样式 */
|
||||
@media print {
|
||||
* {
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.header,
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.layout__main {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 高对比度模式支持 */
|
||||
@media (prefers-contrast: high) {
|
||||
:root {
|
||||
--color-gray-50: #ffffff;
|
||||
--color-gray-100: #f0f0f0;
|
||||
--color-gray-200: #e0e0e0;
|
||||
--color-gray-300: #c0c0c0;
|
||||
--color-gray-400: #808080;
|
||||
--color-gray-500: #606060;
|
||||
--color-gray-600: #404040;
|
||||
--color-gray-700: #202020;
|
||||
--color-gray-800: #101010;
|
||||
--color-gray-900: #000000;
|
||||
}
|
||||
}
|
||||
|
||||
/* 减少动画偏好 */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 诊断三栏布局优化 */
|
||||
#diagnosis-split {
|
||||
gap: 8px;
|
||||
min-height: 620px;
|
||||
}
|
||||
|
||||
#diag-left,
|
||||
#diag-middle,
|
||||
#diag-right {
|
||||
border-color: var(--color-gray-200);
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
#diag-divider-1,
|
||||
#diag-divider-2 {
|
||||
width: 6px;
|
||||
background-color: var(--color-gray-200);
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
#diag-divider-1:hover,
|
||||
#diag-divider-2:hover {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* 树形与搜索优化 */
|
||||
#diag-tree-search {
|
||||
border-color: var(--color-gray-300);
|
||||
}
|
||||
#diag-tree-search:focus {
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
|
||||
}
|
||||
|
||||
#diag-tree .btn[data-cluster] {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
background-color: #eaf2ff;
|
||||
border-color: #d6e8ff;
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
#diag-tree .btn[data-cluster]:hover {
|
||||
background-color: #d6e8ff;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
||||
border-color: #cfe0ff;
|
||||
}
|
||||
|
||||
.cluster-toggle-icon {
|
||||
margin-right: 6px;
|
||||
color: var(--color-primary);
|
||||
transition: color 0.2s ease, transform 0.2s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#diag-tree .diag-node-list {
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#diag-tree .diag-node-list li:not(:first-child) .diag-node-btn {
|
||||
border-top: 1px solid var(--color-gray-200);
|
||||
}
|
||||
|
||||
#diag-tree .diag-node-btn {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
background-color: #ffffff;
|
||||
border: none;
|
||||
padding: 8px 10px;
|
||||
cursor: grab;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
#diag-tree .diag-node-btn:hover {
|
||||
background-color: #f5fbff;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
||||
border-color: #cfe8ff;
|
||||
}
|
||||
|
||||
#diag-tree .btn[data-cluster]:hover .cluster-toggle-icon {
|
||||
color: var(--color-primary-dark);
|
||||
transform: translateY(-0.5px);
|
||||
}
|
||||
|
||||
/* 实时日志条目优化 */
|
||||
#diag-live-logs .u-text-sm {
|
||||
padding: 6px 8px;
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: 6px;
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
#diag-live-logs-list .diag-log-btn {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: 6px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
#diag-live-logs-list .diag-log-btn:hover {
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
|
||||
/* 日志预览文本优化 */
|
||||
#diag-preview-content {
|
||||
background-color: var(--color-gray-50);
|
||||
border-left: 4px solid var(--color-gray-200);
|
||||
min-height: 300px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 聊天历史块优化 */
|
||||
#chat-history .u-border {
|
||||
background-color: var(--color-gray-50);
|
||||
border-color: var(--color-gray-200);
|
||||
}
|
||||
|
||||
#chat-input {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
/* 聊天输入内置发送按钮布局 */
|
||||
.chat-input-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#chat-input {
|
||||
padding-right: 96px;
|
||||
}
|
||||
|
||||
.chat-send-btn {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
}
|
||||
#diag-tree .diag-node-list--collapsed {
|
||||
display: none;
|
||||
}
|
||||
.modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 50;
|
||||
}
|
||||
.modal__overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.35);
|
||||
}
|
||||
.modal__content {
|
||||
position: relative;
|
||||
max-width: 520px;
|
||||
margin: 10% auto 0;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
|
||||
}
|
||||
@ -0,0 +1,564 @@
|
||||
/* Utility Classes */
|
||||
/* 工具类样式 - 原子化 CSS */
|
||||
|
||||
/* 显示/隐藏 */
|
||||
.u-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-visible {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
.u-invisible {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
.u-sr-only {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
padding: 0 !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
clip: rect(0, 0, 0, 0) !important;
|
||||
white-space: nowrap !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
/* 文本对齐 */
|
||||
.u-text-left {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.u-text-center {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.u-text-right {
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
.u-text-justify {
|
||||
text-align: justify !important;
|
||||
}
|
||||
|
||||
/* 文本颜色 */
|
||||
.u-text-primary {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
.u-text-secondary {
|
||||
color: var(--color-secondary) !important;
|
||||
}
|
||||
|
||||
.u-text-success {
|
||||
color: var(--color-success) !important;
|
||||
}
|
||||
|
||||
.u-text-warning {
|
||||
color: var(--color-warning) !important;
|
||||
}
|
||||
|
||||
.u-text-error {
|
||||
color: var(--color-error) !important;
|
||||
}
|
||||
|
||||
.u-text-muted {
|
||||
color: var(--color-gray-500) !important;
|
||||
}
|
||||
|
||||
.u-text-white {
|
||||
color: var(--color-white) !important;
|
||||
}
|
||||
|
||||
/* 字体大小 */
|
||||
.u-text-xs {
|
||||
font-size: var(--font-size-xs) !important;
|
||||
}
|
||||
|
||||
.u-text-sm {
|
||||
font-size: var(--font-size-sm) !important;
|
||||
}
|
||||
|
||||
.u-text-base {
|
||||
font-size: var(--font-size-base) !important;
|
||||
}
|
||||
|
||||
.u-text-lg {
|
||||
font-size: var(--font-size-lg) !important;
|
||||
}
|
||||
|
||||
.u-text-xl {
|
||||
font-size: var(--font-size-xl) !important;
|
||||
}
|
||||
|
||||
.u-text-2xl {
|
||||
font-size: var(--font-size-2xl) !important;
|
||||
}
|
||||
|
||||
.u-text-3xl {
|
||||
font-size: var(--font-size-3xl) !important;
|
||||
}
|
||||
|
||||
/* 字体粗细 */
|
||||
.u-font-normal {
|
||||
font-weight: var(--font-weight-normal) !important;
|
||||
}
|
||||
|
||||
.u-font-medium {
|
||||
font-weight: var(--font-weight-medium) !important;
|
||||
}
|
||||
|
||||
.u-font-semibold {
|
||||
font-weight: var(--font-weight-semibold) !important;
|
||||
}
|
||||
|
||||
.u-font-bold {
|
||||
font-weight: var(--font-weight-bold) !important;
|
||||
}
|
||||
|
||||
/* 背景颜色 */
|
||||
.u-bg-primary {
|
||||
background-color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
.u-bg-secondary {
|
||||
background-color: var(--color-secondary) !important;
|
||||
}
|
||||
|
||||
.u-bg-success {
|
||||
background-color: var(--color-success) !important;
|
||||
}
|
||||
|
||||
.u-bg-warning {
|
||||
background-color: var(--color-warning) !important;
|
||||
}
|
||||
|
||||
.u-bg-error {
|
||||
background-color: var(--color-error) !important;
|
||||
}
|
||||
|
||||
.u-bg-white {
|
||||
background-color: var(--color-white) !important;
|
||||
}
|
||||
|
||||
.u-bg-gray-50 {
|
||||
background-color: var(--color-gray-50) !important;
|
||||
}
|
||||
|
||||
.u-bg-gray-100 {
|
||||
background-color: var(--color-gray-100) !important;
|
||||
}
|
||||
|
||||
.u-bg-transparent {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 边距 - Margin */
|
||||
.u-m-0 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.u-m-1 {
|
||||
margin: var(--spacing-1) !important;
|
||||
}
|
||||
|
||||
.u-m-2 {
|
||||
margin: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-m-3 {
|
||||
margin: var(--spacing-3) !important;
|
||||
}
|
||||
|
||||
.u-m-4 {
|
||||
margin: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.u-m-6 {
|
||||
margin: var(--spacing-6) !important;
|
||||
}
|
||||
|
||||
.u-m-8 {
|
||||
margin: var(--spacing-8) !important;
|
||||
}
|
||||
|
||||
/* 垂直边距 */
|
||||
.u-my-0 {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.u-my-2 {
|
||||
margin-top: var(--spacing-2) !important;
|
||||
margin-bottom: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-my-4 {
|
||||
margin-top: var(--spacing-4) !important;
|
||||
margin-bottom: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.u-my-6 {
|
||||
margin-top: var(--spacing-6) !important;
|
||||
margin-bottom: var(--spacing-6) !important;
|
||||
}
|
||||
|
||||
/* 水平边距 */
|
||||
.u-mx-auto {
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
}
|
||||
|
||||
.u-mx-2 {
|
||||
margin-left: var(--spacing-2) !important;
|
||||
margin-right: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-mx-4 {
|
||||
margin-left: var(--spacing-4) !important;
|
||||
margin-right: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
/* 内边距 - Padding */
|
||||
.u-p-0 {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.u-p-2 {
|
||||
padding: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-p-4 {
|
||||
padding: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.u-p-6 {
|
||||
padding: var(--spacing-6) !important;
|
||||
}
|
||||
|
||||
/* 垂直内边距 */
|
||||
.u-py-2 {
|
||||
padding-top: var(--spacing-2) !important;
|
||||
padding-bottom: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-py-4 {
|
||||
padding-top: var(--spacing-4) !important;
|
||||
padding-bottom: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
/* 水平内边距 */
|
||||
.u-px-2 {
|
||||
padding-left: var(--spacing-2) !important;
|
||||
padding-right: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-px-4 {
|
||||
padding-left: var(--spacing-4) !important;
|
||||
padding-right: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.u-px-6 {
|
||||
padding-left: var(--spacing-6) !important;
|
||||
padding-right: var(--spacing-6) !important;
|
||||
}
|
||||
|
||||
/* 弹性布局 */
|
||||
.u-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.u-inline-flex {
|
||||
display: inline-flex !important;
|
||||
}
|
||||
|
||||
.u-flex-col {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.u-flex-row {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.u-items-center {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.u-items-start {
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
|
||||
.u-items-end {
|
||||
align-items: flex-end !important;
|
||||
}
|
||||
|
||||
.u-justify-center {
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.u-justify-between {
|
||||
justify-content: space-between !important;
|
||||
}
|
||||
|
||||
.u-justify-start {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
|
||||
.u-justify-end {
|
||||
justify-content: flex-end !important;
|
||||
}
|
||||
|
||||
.u-flex-1 {
|
||||
flex: 1 1 0% !important;
|
||||
}
|
||||
|
||||
.u-flex-shrink-0 {
|
||||
flex-shrink: 0 !important;
|
||||
}
|
||||
|
||||
/* 网格布局 */
|
||||
.u-grid {
|
||||
display: grid !important;
|
||||
}
|
||||
|
||||
.u-grid-cols-1 {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
|
||||
}
|
||||
|
||||
.u-grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
|
||||
}
|
||||
|
||||
.u-grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
|
||||
}
|
||||
|
||||
.u-grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
|
||||
}
|
||||
|
||||
.u-gap-2 {
|
||||
gap: var(--spacing-2) !important;
|
||||
}
|
||||
|
||||
.u-gap-4 {
|
||||
gap: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.u-gap-6 {
|
||||
gap: var(--spacing-6) !important;
|
||||
}
|
||||
|
||||
/* 宽度 */
|
||||
.u-w-full {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.u-w-auto {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.u-w-fit {
|
||||
width: fit-content !important;
|
||||
}
|
||||
|
||||
/* 高度 */
|
||||
.u-h-full {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.u-h-auto {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.u-min-h-screen {
|
||||
min-height: 100vh !important;
|
||||
}
|
||||
|
||||
/* 边框 */
|
||||
.u-border {
|
||||
border: 1px solid var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
.u-border-0 {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.u-border-t {
|
||||
border-top: 1px solid var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
.u-border-b {
|
||||
border-bottom: 1px solid var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
.u-border-l {
|
||||
border-left: 1px solid var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
.u-border-r {
|
||||
border-right: 1px solid var(--color-gray-200) !important;
|
||||
}
|
||||
|
||||
/* 圆角 */
|
||||
.u-rounded {
|
||||
border-radius: var(--border-radius-base) !important;
|
||||
}
|
||||
|
||||
.u-rounded-md {
|
||||
border-radius: var(--border-radius-md) !important;
|
||||
}
|
||||
|
||||
.u-rounded-lg {
|
||||
border-radius: var(--border-radius-lg) !important;
|
||||
}
|
||||
|
||||
.u-rounded-xl {
|
||||
border-radius: var(--border-radius-xl) !important;
|
||||
}
|
||||
|
||||
.u-rounded-full {
|
||||
border-radius: var(--border-radius-full) !important;
|
||||
}
|
||||
|
||||
/* 阴影 */
|
||||
.u-shadow {
|
||||
box-shadow: var(--shadow-base) !important;
|
||||
}
|
||||
|
||||
.u-shadow-sm {
|
||||
box-shadow: var(--shadow-sm) !important;
|
||||
}
|
||||
|
||||
.u-shadow-md {
|
||||
box-shadow: var(--shadow-md) !important;
|
||||
}
|
||||
|
||||
.u-shadow-lg {
|
||||
box-shadow: var(--shadow-lg) !important;
|
||||
}
|
||||
|
||||
.u-shadow-none {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 溢出 */
|
||||
.u-overflow-hidden {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.u-overflow-auto {
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
.u-overflow-x-auto {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
|
||||
.u-overflow-y-auto {
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
/* 定位 */
|
||||
.u-relative {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.u-absolute {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
.u-fixed {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
.u-sticky {
|
||||
position: sticky !important;
|
||||
}
|
||||
|
||||
/* z-index */
|
||||
.u-z-10 {
|
||||
z-index: 10 !important;
|
||||
}
|
||||
|
||||
.u-z-20 {
|
||||
z-index: 20 !important;
|
||||
}
|
||||
|
||||
.u-z-50 {
|
||||
z-index: 50 !important;
|
||||
}
|
||||
|
||||
/* 过渡动画 */
|
||||
.u-transition {
|
||||
transition: all var(--transition-base) !important;
|
||||
}
|
||||
|
||||
.u-transition-fast {
|
||||
transition: all var(--transition-fast) !important;
|
||||
}
|
||||
|
||||
.u-transition-slow {
|
||||
transition: all var(--transition-slow) !important;
|
||||
}
|
||||
|
||||
/* 光标 */
|
||||
.u-cursor-pointer {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.u-cursor-not-allowed {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
/* 用户选择 */
|
||||
.u-select-none {
|
||||
user-select: none !important;
|
||||
}
|
||||
|
||||
.u-select-all {
|
||||
user-select: all !important;
|
||||
}
|
||||
|
||||
/* 响应式工具类 */
|
||||
@media (max-width: 768px) {
|
||||
.u-md-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-md-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.u-md-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.u-md-grid-cols-1 {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
|
||||
}
|
||||
|
||||
.u-md-text-center {
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.u-sm-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.u-sm-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.u-sm-text-sm {
|
||||
font-size: var(--font-size-sm) !important;
|
||||
}
|
||||
|
||||
.u-sm-p-2 {
|
||||
padding: var(--spacing-2) !important;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,284 @@
|
||||
/**
|
||||
* 图表管理工具类
|
||||
* 负责初始化和管理 ECharts 图表实例
|
||||
*/
|
||||
class ChartManager {
|
||||
constructor() {
|
||||
this.charts = new Map(); // 存储图表实例
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有图表
|
||||
*/
|
||||
init() {
|
||||
// 等待 DOM 加载完成后初始化图表
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
this.initAllCharts();
|
||||
});
|
||||
} else {
|
||||
this.initAllCharts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有图表
|
||||
*/
|
||||
initAllCharts() {
|
||||
this.initCpuChart();
|
||||
this.initMemoryChart();
|
||||
|
||||
// 监听窗口大小变化,自动调整图表大小
|
||||
window.addEventListener('resize', () => {
|
||||
this.resizeAllCharts();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 CPU 使用率趋势图
|
||||
*/
|
||||
initCpuChart() {
|
||||
const chartElement = document.getElementById('cpuChart');
|
||||
if (!chartElement) return;
|
||||
|
||||
const chart = echarts.init(chartElement);
|
||||
|
||||
// CPU 使用率图表配置
|
||||
const option = {
|
||||
title: {
|
||||
text: 'CPU 使用率 (%)',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'normal',
|
||||
color: '#374151'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function(params) {
|
||||
const data = params[0];
|
||||
return `${data.name}<br/>CPU 使用率: ${data.value}%`;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'],
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#E5E7EB'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#6B7280'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 100,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#E5E7EB'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#6B7280',
|
||||
formatter: '{value}%'
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#F3F4F6'
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'CPU 使用率',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
data: [20, 35, 45, 60, 55, 40, 30],
|
||||
lineStyle: {
|
||||
color: '#3B82F6',
|
||||
width: 2
|
||||
},
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: 'rgba(59, 130, 246, 0.3)'
|
||||
}, {
|
||||
offset: 1,
|
||||
color: 'rgba(59, 130, 246, 0.05)'
|
||||
}]
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
color: '#3B82F6'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
this.charts.set('cpu', chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化内存使用情况图
|
||||
*/
|
||||
initMemoryChart() {
|
||||
const chartElement = document.getElementById('memoryChart');
|
||||
if (!chartElement) return;
|
||||
|
||||
const chart = echarts.init(chartElement);
|
||||
|
||||
// 内存使用情况图表配置
|
||||
const option = {
|
||||
title: {
|
||||
text: '内存使用情况',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
fontWeight: 'normal',
|
||||
color: '#374151'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function(params) {
|
||||
return `${params.name}<br/>使用量: ${params.value} GB (${params.percent}%)`;
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
bottom: '0%',
|
||||
textStyle: {
|
||||
color: '#6B7280'
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: '内存使用',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
center: ['50%', '45%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 4,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '16',
|
||||
fontWeight: 'bold',
|
||||
color: '#374151'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: 8.5,
|
||||
name: '已使用',
|
||||
itemStyle: {
|
||||
color: '#EF4444'
|
||||
}
|
||||
},
|
||||
{
|
||||
value: 15.5,
|
||||
name: '可用',
|
||||
itemStyle: {
|
||||
color: '#10B981'
|
||||
}
|
||||
}
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
this.charts.set('memory', chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整所有图表大小
|
||||
*/
|
||||
resizeAllCharts() {
|
||||
this.charts.forEach(chart => {
|
||||
chart.resize();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新 CPU 图表数据
|
||||
* @param {Array} data - 新的数据数组
|
||||
*/
|
||||
updateCpuChart(data) {
|
||||
const chart = this.charts.get('cpu');
|
||||
if (chart && data) {
|
||||
chart.setOption({
|
||||
series: [{
|
||||
data: data
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新内存图表数据
|
||||
* @param {Object} data - 内存使用数据 {used: number, available: number}
|
||||
*/
|
||||
updateMemoryChart(data) {
|
||||
const chart = this.charts.get('memory');
|
||||
if (chart && data) {
|
||||
chart.setOption({
|
||||
series: [{
|
||||
data: [
|
||||
{
|
||||
value: data.used,
|
||||
name: '已使用',
|
||||
itemStyle: {
|
||||
color: '#EF4444'
|
||||
}
|
||||
},
|
||||
{
|
||||
value: data.available,
|
||||
name: '可用',
|
||||
itemStyle: {
|
||||
color: '#10B981'
|
||||
}
|
||||
}
|
||||
]
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁所有图表实例
|
||||
*/
|
||||
dispose() {
|
||||
this.charts.forEach(chart => {
|
||||
chart.dispose();
|
||||
});
|
||||
this.charts.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 创建全局图表管理器实例
|
||||
window.chartManager = new ChartManager();
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue