diff --git a/CSS_THEME_GUIDE.md b/CSS_THEME_GUIDE.md new file mode 100644 index 0000000..bf4206f --- /dev/null +++ b/CSS_THEME_GUIDE.md @@ -0,0 +1,242 @@ +# CSS主题系统使用指南 + +## 概述 + +本项目采用统一的CSS主题系统,通过CSS变量实现一致的视觉效果和便捷的主题管理。所有颜色、尺寸、间距等样式值都通过预定义的CSS变量进行管理,确保代码的一致性和可维护性。 + +## 🎯 核心原则 + +### ✅ 正确做法 +```css +/* 使用CSS变量 */ +padding: var(--spacing-md); +font-size: var(--font-size-base); +border-radius: var(--size-border-radius); +color: var(--color-text-primary); +``` + +### ❌ 禁止做法 +```css +/* 硬编码值 - 严禁使用 */ +padding: 12px; +font-size: 14px; +border-radius: 8px; +color: #ffffff; +``` + +## 🎨 变量分类系统 + +### 1. 尺寸变量 (`--size-*`) +```css +/* 常用固定尺寸 */ +--size-1: 1px; /* 边框、分割线 */ +--size-2: 2px; /* 小装饰 */ +--size-4: 4px; /* 小圆角 */ +--size-6: 6px; /* 按钮圆角 */ +--size-8: 8px; /* 标准圆角 */ +--size-12: 12px; /* 卡片圆角 */ +--size-16: 16px; /* 图标尺寸 */ +--size-24: 24px; /* 大图标 */ +--size-32: 32px; /* 按钮高度 */ +--size-40: 40px; /* 操作按钮 */ +--size-48: 48px; /* 头像尺寸 */ +--size-60: 60px; /* 头部高度 */ +``` + +### 2. 间距变量 (`--spacing-*`) +```css +/* 间距系统 */ +--spacing-xxs: 2px; /* 微小间距 */ +--spacing-xs: 4px; /* 极小间距 */ +--spacing-sm: 8px; /* 小间距 */ +--spacing-md: 12px; /* 中等间距 */ +--spacing-lg: 16px; /* 大间距 */ +--spacing-xl: 20px; /* 超大间距 */ +--spacing-2xl: 24px; /* 卡片间距 */ +--spacing-3xl: 32px; /* 区域间距 */ +--spacing-4xl: 40px; /* 大区域间距 */ +--spacing-5xl: 48px; /* 页面间距 */ +--spacing-6xl: 60px; /* 头部间距 */ +``` + +### 3. 字体变量 (`--font-size-*`) +```css +/* 字体大小系统 */ +--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; /* 主标题 */ +``` + +### 4. 图标变量 (`--icon-size-*`) +```css +/* 图标尺寸系统 */ +--icon-size-xs: 12px; /* 状态图标 */ +--icon-size-sm: 14px; /* 小图标 */ +--icon-size-md: 16px; /* 标准图标 */ +--icon-size-lg: 20px; /* 大图标 */ +--icon-size-xl: 24px; /* 超大图标 */ +--icon-size-2xl: 28px; /* 装饰图标 */ +--icon-size-3xl: 32px; /* 特大图标 */ +``` + +### 5. 颜色变量 (`--color-*`) +```css +/* 文字颜色 */ +--color-text-primary: /* 主要文字 */ +--color-text-secondary: /* 次要文字 */ +--color-text-tertiary: /* 辅助文字 */ +--color-text-error: /* 错误文字 */ + +/* 背景颜色 */ +--color-bg-primary: /* 主背景 */ +--color-bg-secondary: /* 次背景 */ +--color-bg-card: /* 卡片背景 */ +--color-bg-hover: /* 悬停背景 */ + +/* 边框颜色 */ +--color-border-primary: /* 主边框 */ +--color-border-secondary: /* 次边框 */ +--color-border-active: /* 激活边框 */ +``` + +### 6. CAD软件主题色 +```css +/* Creo主题 */ +--color-primary: /* 蓝色主题 */ + +/* PDMS主题 */ +--color-pdms: /* 橙色主题 */ +--color-pdms-gradient: /* 橙色渐变 */ + +/* Revit主题 */ +--color-revit: /* 绿色主题 */ +--color-revit-gradient: /* 绿色渐变 */ + +/* 复杂度分析主题 */ +--color-complexity: /* 分析橙色 */ +--color-complexity-high: /* 高复杂度红色 */ +--color-complexity-low: /* 低复杂度绿色 */ +``` + +## 🛠️ 使用示例 + +### 按钮样式 +```css +.custom-button { + padding: var(--spacing-md) var(--spacing-lg); + font-size: var(--font-size-base); + border-radius: var(--size-border-radius-button); + border: var(--border-width-thin) solid var(--color-border-primary); + gap: var(--spacing-sm); +} +``` + +### 卡片样式 +```css +.card-component { + padding: var(--spacing-xl); + margin-bottom: var(--spacing-2xl); + border-radius: var(--size-border-radius-card); + border: var(--border-width-thin) solid var(--color-border-primary); + background: var(--color-bg-card); +} +``` + +### 文字样式 +```css +.title { + font-size: var(--font-size-2xl); + color: var(--color-text-primary); + margin-bottom: var(--spacing-lg); +} + +.subtitle { + font-size: var(--font-size-base); + color: var(--color-text-secondary); +} +``` + +### 响应式断点 +```css +@media (max-width: var(--breakpoint-tablet)) { + .responsive-element { + padding: var(--spacing-sm); + font-size: var(--font-size-sm); + } +} +``` + +## 🔧 变量映射表 + +### 常用硬编码值对应的变量 + +| 硬编码值 | 对应变量 | 用途 | +|---------|---------|------| +| `1px` | `var(--size-1)` | 边框 | +| `2px` | `var(--size-2)` | 小装饰 | +| `4px` | `var(--spacing-xs)` | 微间距 | +| `6px` | `var(--size-6)` | 按钮圆角 | +| `8px` | `var(--spacing-sm)` | 小间距 | +| `10px` | `var(--size-10)` | 内边距 | +| `12px` | `var(--spacing-md)` | 标准间距 | +| `14px` | `var(--font-size-base)` | 基础字体 | +| `16px` | `var(--spacing-lg)` | 大间距 | +| `20px` | `var(--spacing-xl)` | 超大间距 | +| `24px` | `var(--spacing-2xl)` | 卡片间距 | +| `768px` | `var(--breakpoint-tablet)` | 平板断点 | + +## 📋 开发检查清单 + +### 开发前检查 +- [ ] 确认所需尺寸在变量系统中是否已存在 +- [ ] 如需新尺寸,先在`theme.css`中添加变量 +- [ ] 确认变量命名符合语义化原则 + +### 代码审查检查 +- [ ] 没有使用任何硬编码的`px`、`rem`、`em`值 +- [ ] 所有颜色都使用CSS变量 +- [ ] 响应式断点使用变量 +- [ ] 间距、字体、圆角都使用对应变量 + +### 测试检查 +- [ ] 组件在不同主题下显示正常 +- [ ] 响应式布局工作正常 +- [ ] 所有交互状态(hover、active、focus)正常 + +## 🚨 常见问题 + +### Q: 需要的尺寸在变量中找不到怎么办? +A: 在`src/assets/styles/theme.css`中添加新变量,命名要语义化。 + +### Q: 特殊组件需要特定尺寸怎么办? +A: 在theme.css中的"组件特定"区域添加专用变量。 + +### Q: 如何确保主题切换正常? +A: 所有样式都使用CSS变量,确保亮暗主题切换时自动更新。 + +### Q: 媒体查询也要使用变量吗? +A: 是的,使用`var(--breakpoint-*)`系列变量。 + +## 🎯 最佳实践 + +1. **语义化命名**:变量名要明确表达用途 +2. **分层设计**:区分基础变量和语义变量 +3. **一致性原则**:同类元素使用相同变量 +4. **可维护性**:修改主题只需调整变量文件 +5. **文档更新**:新增变量要及时更新文档 + +## 🔄 持续改进 + +- 定期审查未使用的变量 +- 根据设计需求扩展变量系统 +- 收集开发反馈,优化变量分类 +- 保持变量系统的简洁性和易用性 + +--- + +**记住:统一的主题系统是项目可维护性的关键!严格遵循变量使用规范。** \ No newline at end of file diff --git a/src/assets/styles/info-panel.css b/src/assets/styles/info-panel.css index 79c3928..b8e7020 100644 --- a/src/assets/styles/info-panel.css +++ b/src/assets/styles/info-panel.css @@ -5,13 +5,13 @@ /* 管理面板基本布局 */ .management-panel { position: fixed; - top: 60px; /* 头部高度偏移 */ - right: -400px; /* 初始隐藏在右侧 */ - width: 400px; - height: calc(100vh - 60px); - background: linear-gradient(135deg, #1e1e1e 0%, #2a2a2a 100%); - border-left: 1px solid rgba(255, 255, 255, 0.1); - box-shadow: -4px 0 15px rgba(0, 0, 0, 0.3); + top: var(--size-header-height); /* 头部高度偏移 */ + right: calc(-1 * var(--size-info-panel-width)); /* 初始隐藏在右侧 */ + width: var(--size-info-panel-width); + height: calc(var(--size-screen-height) - var(--size-header-height)); + background: var(--color-bg-gradient-main); + border-left: 1px solid var(--color-border-primary); + box-shadow: -4px 0 15px var(--color-shadow-black-1); z-index: 1000; display: flex; flex-direction: column; @@ -28,22 +28,22 @@ align-items: center; justify-content: space-between; padding: 15px 20px; - background: #1e1e1e; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - min-height: 60px; + background: var(--color-bg-tertiary); + border-bottom: 1px solid var(--color-border-primary); + min-height: var(--size-info-panel-header-height); } .panel-title { display: flex; align-items: center; gap: 10px; - color: #ffffff; + color: var(--color-text-primary); font-weight: 600; font-size: 16px; } .panel-title i { - color: #2a5caa; + color: var(--color-primary); font-size: 18px; } @@ -59,15 +59,15 @@ gap: 6px; padding: 4px 8px; border-radius: 4px; - background: rgba(244, 67, 54, 0.1); - color: #f44336; + background: var(--color-bg-error); + color: var(--color-error); font-size: 12px; font-weight: 500; } .status-indicator.connected { - background: rgba(76, 175, 80, 0.1); - color: #4caf50; + background: var(--color-bg-success); + color: var(--color-success); } .status-indicator i { @@ -77,7 +77,7 @@ .panel-close { background: none; border: none; - color: #cccccc; + color: var(--color-text-secondary); cursor: pointer; padding: 6px; border-radius: 4px; @@ -85,8 +85,8 @@ } .panel-close:hover { - background: #2a2a2a; - color: #ffffff; + background: var(--color-bg-secondary); + color: var(--color-text-primary); } /* 面板内容区域 */ @@ -100,8 +100,8 @@ /* 选项卡导航 */ .panel-tabs { display: flex; - background: #2a2a2a; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); + background: var(--color-bg-secondary); + border-bottom: 1px solid var(--color-border-primary); } .tab-btn { @@ -113,7 +113,7 @@ padding: 12px 8px; background: none; border: none; - color: #cccccc; + color: var(--color-text-secondary); font-size: 12px; cursor: pointer; transition: all 0.2s ease; @@ -121,14 +121,14 @@ } .tab-btn:hover { - background: rgba(255, 255, 255, 0.05); - color: #ffffff; + background: var(--color-bg-hover); + color: var(--color-text-primary); } .tab-btn.active { - color: #2a5caa; - border-bottom-color: #2a5caa; - background: #1e1e1e; + color: var(--color-primary); + border-bottom-color: var(--color-primary); + background: var(--color-bg-tertiary); } .tab-btn i { @@ -155,16 +155,16 @@ display: flex; align-items: center; justify-content: space-between; - color: #ffffff; + color: var(--color-text-primary); font-size: 14px; font-weight: 600; margin: 0 0 15px 0; padding-bottom: 8px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); + border-bottom: 1px solid var(--color-border-secondary); } .section-title i { - color: #2a5caa; + color: var(--color-primary); margin-right: 8px; } @@ -175,12 +175,12 @@ justify-content: center; gap: 10px; padding: 40px 20px; - color: #cccccc; + color: var(--color-text-secondary); font-size: 14px; } .loading-state i { - color: #2a5caa; + color: var(--color-primary); font-size: 16px; } @@ -196,15 +196,15 @@ flex-direction: column; gap: 12px; padding: 16px; - background: #2a2a2a; - border: 1px solid rgba(255, 255, 255, 0.2); + background: var(--color-bg-secondary); + border: 1px solid var(--color-border-secondary); border-radius: 8px; transition: all 0.2s ease; } .software-item-backend:hover { - border-color: rgba(255, 255, 255, 0.3); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + border-color: var(--color-border-secondary); + box-shadow: 0 2px 8px var(--color-shadow-black-1); } .software-info { @@ -220,7 +220,7 @@ display: flex; align-items: center; justify-content: center; - background: linear-gradient(135deg, #2a5caa 0%, #3d7bd8 100%); + background: var(--color-primary-gradient); border-radius: 6px; color: white; font-size: 14px; @@ -232,19 +232,19 @@ } .software-name-backend { - color: #ffffff; + color: var(--color-text-primary); font-weight: 500; font-size: 14px; margin-bottom: 2px; } .software-status { - color: #cccccc; + color: var(--color-text-secondary); font-size: 12px; } .software-status.running { - color: #4caf50; + color: var(--color-success); } .software-actions { @@ -267,67 +267,67 @@ gap: 6px; min-width: 70px; justify-content: center; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: var(--color-shadow-btn); } .action-btn.start { - background: linear-gradient(135deg, #4caf50 0%, #66bb6a 100%); + background: var(--color-btn-success); color: white; } .action-btn.start:hover:not(:disabled) { - background: linear-gradient(135deg, #66bb6a 0%, #81c784 100%); + background: var(--color-btn-success-hover); transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(76, 175, 80, 0.3); + box-shadow: var(--color-shadow-btn-success); } .action-btn.stop { - background: linear-gradient(135deg, #f44336 0%, #ef5350 100%); + background: var(--color-btn-error); color: white; } .action-btn.stop:hover:not(:disabled) { - background: linear-gradient(135deg, #ef5350 0%, #e57373 100%); + background: var(--color-btn-error-hover); transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(244, 67, 54, 0.3); + box-shadow: var(--color-shadow-btn-error); } .action-btn.restart { - background: linear-gradient(135deg, #ff9800 0%, #ffb74d 100%); + background: var(--color-btn-warning); color: white; } .action-btn.restart:hover:not(:disabled) { - background: linear-gradient(135deg, #ffb74d 0%, #ffcc02 100%); + background: var(--color-btn-warning-hover); transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(255, 152, 0, 0.3); + box-shadow: var(--color-shadow-btn-warning); } .action-btn.refresh { - background: linear-gradient(135deg, #2196f3 0%, #42a5f5 100%); + background: var(--color-btn-info); color: white; } .action-btn.refresh:hover:not(:disabled) { - background: linear-gradient(135deg, #42a5f5 0%, #64b5f6 100%); + background: var(--color-btn-info-hover); transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(33, 150, 243, 0.3); + box-shadow: var(--color-shadow-btn-info); } .action-btn.clear { - background: linear-gradient(135deg, #f44336 0%, #ef5350 100%); + background: var(--color-btn-error); color: white; } .action-btn.clear:hover:not(:disabled) { - background: linear-gradient(135deg, #ef5350 0%, #e57373 100%); + background: var(--color-btn-error-hover); transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(244, 67, 54, 0.3); + box-shadow: var(--color-shadow-btn-error); } .action-btn:disabled { - background: #1a1a1a; - color: #999999; + background: var(--color-bg-tertiary); + color: var(--color-text-disabled); cursor: not-allowed; opacity: 0.6; box-shadow: none; @@ -337,7 +337,7 @@ .refresh-btn { background: none; border: none; - color: #cccccc; + color: var(--color-text-secondary); cursor: pointer; padding: 4px; border-radius: 4px; @@ -345,8 +345,8 @@ } .refresh-btn:hover { - color: #2a5caa; - background: rgba(42, 92, 170, 0.1); + color: var(--color-primary); + background: var(--color-primary-rgb); } /* 日志面板样式 */ @@ -370,10 +370,10 @@ .filter-select, .filter-input { padding: 6px 10px; - border: 1px solid rgba(255, 255, 255, 0.2); + border: 1px solid var(--color-border-secondary); border-radius: 4px; - background: #2a2a2a; - color: #ffffff; + background: var(--color-bg-secondary); + color: var(--color-text-primary); font-size: 12px; } @@ -387,20 +387,20 @@ .filter-select:focus, .filter-input:focus { outline: none; - border-color: #2a5caa; + border-color: var(--color-primary); } .logs-list { max-height: 300px; overflow-y: auto; - border: 1px solid rgba(255, 255, 255, 0.2); + border: 1px solid var(--color-border-secondary); border-radius: 6px; - background: #2a2a2a; + background: var(--color-bg-secondary); } .log-item { padding: 10px 15px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); + border-bottom: 1px solid var(--color-border-secondary); transition: background 0.2s ease; } @@ -409,7 +409,7 @@ } .log-item:hover { - background: #1a1a1a; + background: var(--color-bg-tertiary); } .log-header { @@ -420,18 +420,18 @@ } .log-operation { - color: #ffffff; + color: var(--color-text-primary); font-weight: 500; font-size: 13px; } .log-time { - color: #cccccc; + color: var(--color-text-secondary); font-size: 11px; } .log-details { - color: #cccccc; + color: var(--color-text-secondary); font-size: 12px; line-height: 1.4; } @@ -442,11 +442,11 @@ gap: 10px; margin-top: 4px; font-size: 11px; - color: #888888; + color: var(--color-text-tertiary); } .log-user { - color: #2a5caa; + color: var(--color-primary); } .log-status { @@ -457,13 +457,13 @@ } .log-status.success { - background: rgba(76, 175, 80, 0.1); - color: #4caf50; + background: var(--color-bg-success); + color: var(--color-success); } .log-status.failed { - background: rgba(244, 67, 54, 0.1); - color: #f44336; + background: var(--color-bg-error); + color: var(--color-error); } .logs-pagination { @@ -473,34 +473,34 @@ gap: 15px; margin-top: 15px; padding-top: 15px; - border-top: 1px solid rgba(255, 255, 255, 0.2); + border-top: 1px solid var(--color-border-secondary); } .page-btn { padding: 6px 12px; - border: 1px solid rgba(255, 255, 255, 0.2); + border: 1px solid var(--color-border-secondary); border-radius: 4px; - background: #2a2a2a; - color: #cccccc; + background: var(--color-bg-secondary); + color: var(--color-text-secondary); cursor: pointer; font-size: 12px; transition: all 0.2s ease; } .page-btn:hover { - border-color: #2a5caa; - color: #2a5caa; + border-color: var(--color-primary); + color: var(--color-primary); } .page-btn:disabled { - background: #1a1a1a; - color: #999999; + background: var(--color-bg-tertiary); + color: var(--color-text-disabled); cursor: not-allowed; - border-color: rgba(255, 255, 255, 0.2); + border-color: var(--color-border-secondary); } .page-info { - color: #cccccc; + color: var(--color-text-secondary); font-size: 12px; font-weight: 500; } @@ -515,8 +515,8 @@ .stat-card { padding: 15px; - background: #2a2a2a; - border: 1px solid rgba(255, 255, 255, 0.2); + background: var(--color-bg-secondary); + border: 1px solid var(--color-border-secondary); border-radius: 8px; text-align: center; } @@ -525,23 +525,23 @@ display: block; font-size: 24px; font-weight: bold; - color: #2a5caa; + color: var(--color-primary); margin-bottom: 5px; } .stat-label { - color: #cccccc; + color: var(--color-text-secondary); font-size: 12px; font-weight: 500; } .operation-types { padding-top: 20px; - border-top: 1px solid rgba(255, 255, 255, 0.2); + border-top: 1px solid var(--color-border-secondary); } .operation-types h5 { - color: #ffffff; + color: var(--color-text-primary); font-size: 13px; font-weight: 600; margin: 0 0 10px 0; @@ -555,10 +555,10 @@ .type-tag { padding: 4px 8px; - background: #2a2a2a; - border: 1px solid rgba(255, 255, 255, 0.2); + background: var(--color-bg-secondary); + border: 1px solid var(--color-border-secondary); border-radius: 4px; - color: #cccccc; + color: var(--color-text-secondary); font-size: 11px; font-weight: 500; } @@ -566,8 +566,8 @@ /* 响应式设计 */ @media (max-width: 1200px) { .management-panel { - width: 350px; - right: -350px; + width: var(--size-info-panel-width-tablet); + right: calc(-1 * var(--size-info-panel-width-tablet)); } .stats-grid { @@ -588,8 +588,8 @@ @media (max-width: 768px) { .management-panel { - width: 100vw; - right: -100vw; + width: var(--size-screen-width); + right: calc(-1 * var(--size-screen-width)); } .panel-header { diff --git a/src/assets/styles/theme.css b/src/assets/styles/theme.css index b5afe50..3f38688 100644 --- a/src/assets/styles/theme.css +++ b/src/assets/styles/theme.css @@ -88,13 +88,135 @@ --color-complexity-border-3: rgba(var(--color-complexity-base), 0.3); --color-complexity-border-15: rgba(var(--color-complexity-base), 0.15); + /* Revit建筑设计主题色 */ + --color-revit-base: 46, 139, 87; /* #2E8B57 */ + --color-revit: rgb(var(--color-revit-base)); + --color-revit-light-base: 32, 178, 170; /* #20B2AA */ + --color-revit-light: rgb(var(--color-revit-light-base)); + --color-revit-gradient: linear-gradient(135deg, rgb(var(--color-revit-base)) 0%, rgb(var(--color-revit-light-base)) 100%); + --color-revit-bg-1: rgba(var(--color-revit-base), 0.05); + --color-revit-bg-2: rgba(var(--color-revit-base), 0.08); + --color-revit-bg-3: rgba(var(--color-revit-base), 0.1); + --color-revit-shadow: rgba(var(--color-revit-base), 0.3); + + /* Revit建筑元素专用颜色 */ + --color-revit-walls-base: 139, 69, 19; /* #8B4513 */ + --color-revit-walls: rgb(var(--color-revit-walls-base)); + --color-revit-walls-bg: rgba(var(--color-revit-walls-base), 0.1); + --color-revit-doors-base: 255, 165, 0; /* #FFA500 */ + --color-revit-doors: rgb(var(--color-revit-doors-base)); + --color-revit-doors-bg: rgba(var(--color-revit-doors-base), 0.1); + --color-revit-windows-base: 135, 206, 250; /* #87CEEB */ + --color-revit-windows: rgb(var(--color-revit-windows-base)); + --color-revit-windows-bg: rgba(var(--color-revit-windows-base), 0.1); + --color-revit-floors-base: 105, 105, 105; /* #696969 */ + --color-revit-floors: rgb(var(--color-revit-floors-base)); + --color-revit-floors-bg: rgba(var(--color-revit-floors-base), 0.1); + --color-revit-ceilings-base: 220, 220, 220; /* #DCDCDC */ + --color-revit-ceilings: rgb(var(--color-revit-ceilings-base)); + --color-revit-ceilings-bg: rgba(var(--color-revit-ceilings-base), 0.1); + --color-revit-columns-base: 47, 79, 79; /* #2F4F4F */ + --color-revit-columns: rgb(var(--color-revit-columns-base)); + --color-revit-columns-bg: rgba(var(--color-revit-columns-base), 0.1); + --color-revit-beams-base: 160, 82, 45; /* #A0522D */ + --color-revit-beams: rgb(var(--color-revit-beams-base)); + --color-revit-beams-bg: rgba(var(--color-revit-beams-base), 0.1); + --color-revit-rooms-base: 221, 160, 221; /* #DDA0DD */ + --color-revit-rooms: rgb(var(--color-revit-rooms-base)); + --color-revit-rooms-bg: rgba(var(--color-revit-rooms-base), 0.1); + --color-revit-stairs-base: 70, 130, 180; /* #4682B4 */ + --color-revit-stairs: rgb(var(--color-revit-stairs-base)); + --color-revit-stairs-bg: rgba(var(--color-revit-stairs-base), 0.1); + --color-revit-railings-base: 64, 64, 64; /* #404040 */ + --color-revit-railings: rgb(var(--color-revit-railings-base)); + --color-revit-railings-bg: rgba(var(--color-revit-railings-base), 0.1); + + /* PDMS工厂设计主题色 */ + --color-pdms-base: 255, 107, 53; /* #FF6B35 */ + --color-pdms: rgb(var(--color-pdms-base)); + --color-pdms-light-base: 247, 147, 30; /* #F7931E */ + --color-pdms-light: rgb(var(--color-pdms-light-base)); + --color-pdms-gradient: linear-gradient(135deg, rgb(var(--color-pdms-base)) 0%, rgb(var(--color-pdms-light-base)) 100%); + --color-pdms-bg-1: rgba(var(--color-pdms-base), 0.05); + --color-pdms-bg-2: rgba(var(--color-pdms-base), 0.08); + --color-pdms-bg-3: rgba(var(--color-pdms-base), 0.1); + --color-pdms-shadow: rgba(var(--color-pdms-base), 0.3); + + /* PDMS工厂元素专用颜色 */ + --color-pdms-pipe-base: 59, 130, 246; /* #3B82F6 */ + --color-pdms-pipe: rgb(var(--color-pdms-pipe-base)); + --color-pdms-pipe-bg: rgba(var(--color-pdms-pipe-base), 0.1); + --color-pdms-elbo-base: 139, 69, 19; /* #8B4513 */ + --color-pdms-elbo: rgb(var(--color-pdms-elbo-base)); + --color-pdms-elbo-bg: rgba(var(--color-pdms-elbo-base), 0.1); + --color-pdms-valve-base: 220, 38, 127; /* #DC267F */ + --color-pdms-valve: rgb(var(--color-pdms-valve-base)); + --color-pdms-valve-bg: rgba(var(--color-pdms-valve-base), 0.1); + --color-pdms-fitting-base: 168, 85, 247; /* #A855F7 */ + --color-pdms-fitting: rgb(var(--color-pdms-fitting-base)); + --color-pdms-fitting-bg: rgba(var(--color-pdms-fitting-base), 0.1); + --color-pdms-equipment-base: 34, 197, 94; /* #22C55E */ + --color-pdms-equipment: rgb(var(--color-pdms-equipment-base)); + --color-pdms-equipment-bg: rgba(var(--color-pdms-equipment-base), 0.1); + --color-pdms-structure-base: 156, 163, 175; /* #9CA3AF */ + --color-pdms-structure: rgb(var(--color-pdms-structure-base)); + --color-pdms-structure-bg: rgba(var(--color-pdms-structure-base), 0.1); + + /* 复杂度分析状态颜色 */ + --color-complexity-low-base: 40, 167, 69; /* #28a745 */ + --color-complexity-low: rgb(var(--color-complexity-low-base)); + --color-complexity-medium-base: 255, 193, 7; /* #ffc107 */ + --color-complexity-medium: rgb(var(--color-complexity-medium-base)); + --color-complexity-high-base: 220, 53, 69; /* #dc3545 */ + --color-complexity-high: rgb(var(--color-complexity-high-base)); + --color-complexity-critical-base: 139, 0, 0; /* #8B0000 */ + --color-complexity-critical: rgb(var(--color-complexity-critical-base)); + --color-complexity-excellent-base: 34, 139, 34; /* #228B22 */ + --color-complexity-excellent: rgb(var(--color-complexity-excellent-base)); + --color-complexity-high-gradient: linear-gradient(135deg, rgb(var(--color-complexity-high-base)), rgb(200, 35, 51)); + --color-complexity-high-gradient-hover: linear-gradient(135deg, rgb(200, 35, 51), rgb(167, 30, 42)); + + /* 复杂度分析背景色 */ + --color-complexity-low-bg: rgba(var(--color-complexity-low-base), 0.1); + --color-complexity-medium-bg: rgba(var(--color-complexity-medium-base), 0.1); + --color-complexity-high-bg: rgba(var(--color-complexity-high-base), 0.1); + --color-complexity-critical-bg: rgba(var(--color-complexity-critical-base), 0.1); + --color-complexity-excellent-bg: rgba(var(--color-complexity-excellent-base), 0.1); + + /* Creo模型分析工具渐变色 */ + --color-creo-analysis-gradient-1: linear-gradient(135deg, rgb(111, 66, 193), rgb(232, 62, 140)); + --color-creo-analysis-gradient-2: linear-gradient(135deg, rgb(23, 162, 184), rgb(19, 132, 150)); + --color-creo-analysis-gradient-3: linear-gradient(135deg, rgb(40, 167, 69), rgb(32, 201, 151)); + --color-creo-analysis-gradient-4: linear-gradient(135deg, rgb(253, 126, 20), rgb(232, 62, 140)); + --color-creo-analysis-gradient-5: linear-gradient(135deg, rgb(220, 53, 69), rgb(200, 35, 51)); + + /* 通用灰色渐变 */ + --color-gradient-gray: linear-gradient(135deg, rgb(102, 102, 102) 0%, rgb(85, 85, 85) 100%); + /* ===== 优化透明度层级系统 ===== */ + /* 通用透明度常量 */ + --opacity-light: 0.1; + --opacity-medium: 0.3; + --opacity-strong: 0.5; + /* 主色调透明度变体 */ --color-primary-rgb: rgba(var(--color-primary-base), 0.1); --color-primary-rgb-3: rgba(var(--color-primary-base), 0.3); --color-primary-rgb-4: rgba(var(--color-primary-base), 0.4); + /* 成功色透明度变体 */ + --success-color-rgb: var(--color-success-base); + --color-success-rgb-1: rgba(var(--color-success-base), 0.1); + --color-success-rgb-3: rgba(var(--color-success-base), 0.3); + --color-success-rgb-5: rgba(var(--color-success-base), 0.5); + + /* 橙色系透明度变体 */ + --color-orange-base: 255, 152, 0; /* #FF9800 */ + --color-orange: rgb(var(--color-orange-base)); + --color-orange-rgb-1: rgba(var(--color-orange-base), 0.1); + --color-orange-rgb-3: rgba(var(--color-orange-base), 0.3); + /* 状态色透明度变体 */ --color-error-rgb-1: rgba(var(--color-error-base), 0.1); --color-error-rgb-3: rgba(var(--color-error-base), 0.3); @@ -113,10 +235,44 @@ --color-gradient-info: linear-gradient(135deg, rgba(var(--color-info-base), 0.1) 0%, rgba(var(--color-info-base), 0.05) 100%); --color-gradient-warning: linear-gradient(135deg, rgba(var(--color-warning-base), 0.1) 0%, rgba(var(--color-warning-base), 0.05) 100%); + /* 按钮渐变(不透明) */ + --color-btn-success: linear-gradient(135deg, rgb(var(--color-success-base)) 0%, rgb(76, 175, 80) 100%); + --color-btn-success-hover: linear-gradient(135deg, rgb(102, 187, 106) 0%, rgb(129, 199, 132) 100%); + --color-btn-error: linear-gradient(135deg, rgb(var(--color-error-base)) 0%, rgb(239, 83, 80) 100%); + --color-btn-error-hover: linear-gradient(135deg, rgb(239, 83, 80) 0%, rgb(229, 115, 115) 100%); + --color-btn-warning: linear-gradient(135deg, rgb(var(--color-warning-base)) 0%, rgb(255, 183, 77) 100%); + --color-btn-warning-hover: linear-gradient(135deg, rgb(255, 183, 77) 0%, rgb(255, 204, 2) 100%); + --color-btn-info: linear-gradient(135deg, rgb(var(--color-info-base)) 0%, rgb(66, 165, 245) 100%); + --color-btn-info-hover: linear-gradient(135deg, rgb(66, 165, 245) 0%, rgb(100, 181, 246) 100%); + /* 阴影色 - 指向已有变量避免重复 */ --color-shadow-primary: var(--color-primary-rgb-3); --color-shadow-hover: var(--color-primary-rgb-4); --color-shadow-card: 0 20px 40px rgba(var(--color-black-base), 0.3); + --color-shadow-black-1: rgba(var(--color-black-base), 0.1); + --color-shadow-black-3: rgba(var(--color-black-base), 0.3); + + /* 按钮阴影 */ + --color-shadow-btn: 0 2px 4px rgba(var(--color-black-base), 0.1); + --color-shadow-btn-success: 0 4px 8px rgba(var(--color-success-base), 0.3); + --color-shadow-btn-error: 0 4px 8px rgba(var(--color-error-base), 0.3); + --color-shadow-btn-warning: 0 4px 8px rgba(var(--color-warning-base), 0.3); + --color-shadow-btn-info: 0 4px 8px rgba(var(--color-info-base), 0.3); + + /* 通用阴影层级 */ + --color-shadow-black-2: rgba(var(--color-black-base), 0.2); + --color-shadow-lg: 0 8px 32px rgba(var(--color-black-base), 0.3); + --color-shadow-md: 0 6px 20px rgba(var(--color-black-base), 0.2); + --color-shadow-sm: 0 2px 8px rgba(var(--color-black-base), 0.3); + + /* Revit专业阴影色 */ + --color-shadow-revit: 0 8px 32px rgba(var(--color-black-base), 0.3); + --color-shadow-revit-light: 0 6px 20px rgba(var(--color-black-base), 0.2); + --color-shadow-revit-btn: 0 4px 12px rgba(var(--color-revit-base), 0.3); + --color-shadow-revit-btn-hover: 0 8px 25px rgba(var(--color-revit-base), 0.4); + + /* 成功色扩展变体 */ + --color-success-shadow: 0 2px 8px rgba(var(--color-success-base), 0.3); /* 滚动条 */ --color-scrollbar-thumb: var(--color-white-rgb-2); @@ -137,13 +293,19 @@ --size-border-radius-card: 12px; --size-border-radius-button: 6px; + /* 信息管理面板尺寸 */ + --size-info-panel-width: 400px; + --size-info-panel-width-tablet: 350px; + --size-info-panel-header-height: 60px; + /* 连接组件尺寸 */ --size-connection-dot: 8px; --size-connection-card-min-height: 120px; --size-connection-test-btn: 24px; --size-connection-test-btn-small: 20px; - /* 间距系统 */ + /* 间距系统 - 扩展到覆盖所有常用尺寸 */ + --spacing-xxs: 2px; --spacing-xs: 4px; --spacing-sm: 8px; --spacing-md: 12px; @@ -151,6 +313,42 @@ --spacing-xl: 20px; --spacing-2xl: 24px; --spacing-3xl: 32px; + --spacing-4xl: 40px; + --spacing-5xl: 48px; + --spacing-6xl: 60px; + + /* 常用固定尺寸 */ + --size-1: 1px; + --size-2: 2px; + --size-3: 3px; + --size-4: 4px; + --size-6: 6px; + --size-8: 8px; + --size-10: 10px; + --size-12: 12px; + --size-14: 14px; + --size-15: 15px; + --size-16: 16px; + --size-18: 18px; + --size-20: 20px; + --size-24: 24px; + --size-28: 28px; + --size-30: 30px; + --size-32: 32px; + --size-36: 36px; + --size-40: 40px; + --size-44: 44px; + --size-48: 48px; + --size-52: 52px; + --size-56: 56px; + --size-60: 60px; + --size-64: 64px; + --size-80: 80px; + --size-96: 96px; + --size-120: 120px; + --size-140: 140px; + --size-150: 150px; + --size-200: 200px; /* 组件特定间距 */ --spacing-connection-dot: 8px; @@ -158,15 +356,40 @@ --spacing-card-padding-small: 10px; --spacing-grid-gap: 10px; --spacing-form-gap: 8px; + + /* 边框尺寸 */ + --border-width-thin: 1px; + --border-width-medium: 2px; + --border-width-thick: 3px; + + /* 响应式断点 */ + --breakpoint-mobile: 480px; + --breakpoint-tablet: 768px; + --breakpoint-desktop: 1024px; + --breakpoint-large: 1440px; + + /* 图标尺寸系统 */ + --icon-size-xs: 12px; + --icon-size-sm: 14px; + --icon-size-md: 16px; + --icon-size-lg: 20px; + --icon-size-xl: 24px; + --icon-size-2xl: 28px; + --icon-size-3xl: 32px; /* 字体大小 */ --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: 28px; + --font-size-5xl: 32px; + --font-size-6xl: 48px; + --font-size-7xl: 64px; /* 组件特定字体大小 */ --font-size-icon: 24px; @@ -188,9 +411,70 @@ /* ===== 动画系统 ===== */ --transition-duration: 0.3s; + --transition-duration-fast: 0.15s; + --transition-duration-slow: 0.4s; --transition-timing: ease; + --transition-timing-smooth: cubic-bezier(0.4, 0, 0.2, 1); + + /* 完整过渡样式 */ + --transition-all: all var(--transition-duration) var(--transition-timing); + --transition-all-smooth: all var(--transition-duration) var(--transition-timing-smooth); /* ===== 组件尺寸常量 ===== */ + /* 登录界面常量 */ + --login-animation-large: 200px; + --login-animation-medium: 150px; + --login-animation-small: 100px; + --login-card-max-width: 420px; + --login-card-padding: 40px; + --login-card-padding-small: 20px; + --login-card-border-radius: 16px; + --login-icon-size: 60px; + --login-title-size: 24px; + --login-subtitle-size: 20px; + --login-text-size: 14px; + --login-button-text-size: 18px; + + /* 登录界面动画常量 */ + --login-float-distance: -20px; + --login-float-duration: 6s; + --login-animation-delay-1: 0s; + --login-animation-delay-2: 2s; + --login-animation-delay-3: 4s; + + /* 登录界面位置常量 */ + --login-circle-1-top: 10%; + --login-circle-1-left: 10%; + --login-circle-2-top: 60%; + --login-circle-2-right: 15%; + --login-circle-3-bottom: 20%; + --login-circle-3-left: 20%; + + /* 登录界面背景色 */ + --color-bg-dark-95: rgba(var(--color-bg-secondary-base), 0.95); + + /* 登录界面间距常量 */ + --login-brand-margin-bottom: 40px; + --login-form-title-margin-bottom: 30px; + --login-form-group-margin-bottom: 20px; + --login-form-options-margin-bottom: 30px; + --login-help-margin-top: 20px; + --login-brand-logo-margin-bottom: 16px; + --login-brand-title-margin-bottom: 8px; + --login-error-margin-bottom: 20px; + --login-form-label-margin-bottom: 8px; + --login-field-error-margin-top: 4px; + + /* 登录界面按钮常量 */ + --login-button-padding: 14px; + --login-button-transform: translateY(-2px); + --login-button-disabled-opacity: 0.7; + + /* 登录界面字体大小(响应式) */ + --login-title-size-mobile: 18px; + --login-content-padding-mobile: 16px; + --login-card-padding-mobile: 30px 24px; + /* 模型查看器常量 */ --model-viewer-padding: 20px; --model-viewer-border-radius: 8px; @@ -199,6 +483,10 @@ --model-viewer-section-margin: 24px; --model-viewer-section-padding: 16px; + /* 表单输入常量 */ + --input-padding-vertical: 12px; + --input-padding-horizontal: 16px; + /* 通知持续时间常量 */ --notification-duration-success: 2000ms; --notification-duration-error: 3000ms; @@ -394,11 +682,26 @@ html, body { /* 布局工具类 */ .flex { display: flex; } .flex-col { flex-direction: column; } +.flex-row { flex-direction: row; } .items-center { align-items: center; } +.items-start { align-items: flex-start; } +.items-end { align-items: flex-end; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } +.justify-start { justify-content: flex-start; } +.justify-end { justify-content: flex-end; } +.justify-around { justify-content: space-around; } .flex-1 { flex: 1; } .flex-shrink-0 { flex-shrink: 0; } +.flex-wrap { flex-wrap: wrap; } +.flex-nowrap { flex-wrap: nowrap; } + +/* 常用组合布局类 */ +.flex-center { display: flex; align-items: center; justify-content: center; } +.flex-center-between { display: flex; align-items: center; justify-content: space-between; } +.flex-center-start { display: flex; align-items: center; justify-content: flex-start; } +.flex-center-end { display: flex; align-items: center; justify-content: flex-end; } +.flex-col-center { display: flex; flex-direction: column; align-items: center; justify-content: center; } .h-full { height: 100%; } .w-full { width: 100%; } @@ -460,6 +763,37 @@ html, body { border-color: var(--color-white-rgb-15); } +/* 常用按钮样式工具类 */ +.btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border: none; + border-radius: var(--size-border-radius-button); + background: var(--color-bg-hover); + color: var(--color-text-secondary); + cursor: pointer; + transition: var(--transition-all); +} + +.btn-icon:hover { + background: var(--color-primary); + color: var(--color-text-primary); + transform: translateY(-1px); +} + +/* 常用卡片样式 */ +.card-hover { + transition: var(--transition-all); +} + +.card-hover:hover { + transform: translateY(-2px); + box-shadow: var(--color-shadow-card), 0 8px 25px var(--color-shadow-hover); +} + /* ===== 自定义Loading样式 ===== */ .custom-loading .el-loading-text { color: rgba(var(--color-white-base), 0.9) !important; diff --git a/src/components/layout/AppHeader.vue b/src/components/layout/AppHeader.vue index 12577a0..78e5362 100644 --- a/src/components/layout/AppHeader.vue +++ b/src/components/layout/AppHeader.vue @@ -137,10 +137,10 @@ const handleLogout = () => { display: flex; align-items: center; justify-content: space-between; - height: 60px; + height: var(--size-header-height); background: var(--color-bg-primary); border-bottom: 1px solid var(--color-border-primary); - padding: 0 20px; + padding: 0 var(--spacing-xl); position: relative; z-index: var(--z-index-header); } @@ -153,14 +153,14 @@ const handleLogout = () => { .logo { display: flex; align-items: center; - gap: 12px; + gap: var(--spacing-md); color: var(--color-text-primary); font-weight: 600; - font-size: 16px; + font-size: var(--font-size-lg); } .logo i { - font-size: 24px; + font-size: var(--icon-size-xl); color: var(--color-primary); } @@ -171,19 +171,19 @@ const handleLogout = () => { .main-nav { display: flex; - gap: 8px; + gap: var(--spacing-sm); } .nav-item { display: flex; align-items: center; - gap: 8px; - padding: 10px 16px; + gap: var(--spacing-sm); + padding: var(--spacing-grid-gap) var(--spacing-lg); color: var(--color-text-secondary); text-decoration: none; - border-radius: 6px; - transition: all 0.3s ease; - font-size: 14px; + border-radius: var(--size-border-radius-button); + transition: var(--transition-all); + font-size: var(--font-size-base); font-weight: 500; border: none; background: transparent; @@ -212,13 +212,13 @@ const handleLogout = () => { } .nav-item i { - font-size: 14px; + font-size: var(--font-size-base); } .navbar-right { display: flex; align-items: center; - gap: 16px; + gap: var(--spacing-lg); } .notification-center { @@ -226,12 +226,12 @@ const handleLogout = () => { display: flex; align-items: center; justify-content: center; - width: 40px; - height: 40px; + width: var(--spacing-4xl); + height: var(--spacing-4xl); background: var(--color-white-rgb-1); - border-radius: 6px; + border-radius: var(--size-border-radius-button); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); } .notification-center:hover { @@ -240,7 +240,7 @@ const handleLogout = () => { .notification-center i { color: var(--color-text-secondary); - font-size: 16px; + font-size: var(--icon-size-md); } .badge { @@ -249,22 +249,22 @@ const handleLogout = () => { right: -5px; background: var(--color-error); color: white; - font-size: 10px; - padding: 2px 6px; - border-radius: 10px; - min-width: 16px; + font-size: var(--font-size-icon-small); + padding: var(--size-2) var(--size-6); + border-radius: var(--size-10); + min-width: var(--size-16); text-align: center; } .user-menu { display: flex; align-items: center; - gap: 8px; - padding: 8px 12px; + gap: var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-md); background: var(--color-white-rgb-1); - border-radius: 6px; + border-radius: var(--size-border-radius-button); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); position: relative; } @@ -273,14 +273,14 @@ const handleLogout = () => { } .user-avatar { - width: 24px; - height: 24px; + width: var(--icon-size-xl); + height: var(--icon-size-xl); border-radius: 50%; } .username { color: var(--color-text-primary); - font-size: 14px; + font-size: var(--font-size-base); font-weight: 500; } @@ -298,24 +298,24 @@ const handleLogout = () => { position: absolute; top: 100%; right: 0; - margin-top: 8px; + margin-top: var(--spacing-sm); background: var(--color-bg-primary); border: 1px solid var(--color-border-primary); - border-radius: 8px; + border-radius: var(--size-border-radius); box-shadow: 0 4px 20px var(--color-shadow-black-1); - min-width: 140px; + min-width: var(--size-140); z-index: 1000; } .dropdown-item { display: flex; align-items: center; - gap: 8px; + gap: var(--spacing-sm); padding: 12px 16px; color: var(--color-text-primary); cursor: pointer; transition: background-color 0.3s ease; - font-size: 14px; + font-size: var(--font-size-base); } .dropdown-item:hover { @@ -331,11 +331,11 @@ const handleLogout = () => { } .dropdown-item:only-child { - border-radius: 8px; + border-radius: var(--size-border-radius); } .dropdown-item i { - font-size: 14px; + font-size: var(--font-size-base); color: var(--color-text-secondary); } @@ -343,12 +343,12 @@ const handleLogout = () => { display: flex; align-items: center; justify-content: center; - width: 40px; - height: 40px; + width: var(--spacing-4xl); + height: var(--spacing-4xl); background: var(--color-white-rgb-1); - border-radius: 6px; + border-radius: var(--size-border-radius-button); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); } .system-settings:hover { @@ -357,22 +357,22 @@ const handleLogout = () => { .system-settings i { color: var(--color-text-secondary); - font-size: 16px; + font-size: var(--icon-size-md); } /* 响应式设计 */ -@media (max-width: 768px) { +@media (max-width: var(--breakpoint-tablet)) { .main-nav { - gap: 4px; + gap: var(--spacing-xs); } .nav-item { - padding: 8px 12px; - font-size: 13px; + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--font-size-sm); } .navbar-right { - gap: 12px; + gap: var(--spacing-md); } } @@ -382,7 +382,7 @@ const handleLogout = () => { } .logo span { - font-size: 14px; + font-size: var(--font-size-base); } } \ No newline at end of file diff --git a/src/components/layout/CadSidebar.vue b/src/components/layout/CadSidebar.vue index 0aa07fb..3b979f4 100644 --- a/src/components/layout/CadSidebar.vue +++ b/src/components/layout/CadSidebar.vue @@ -69,6 +69,10 @@ import creoApi from '@/services/creoApi' import revitApi from '@/services/revitApi' import pdmsApi from '@/services/pdmsApi' import { ElNotification, ElMessageBox } from 'element-plus' +import { getNotificationConfig } from '@/config/cad' + +// 获取通知配置 +const notificationConfig = getNotificationConfig() // 定义事件 const emit = defineEmits(['show-model-viewer']) @@ -130,7 +134,7 @@ const handleOpenModel = async () => { message: '请先连接CAD软件', type: 'warning', position: 'top-right', - duration: 3000 + duration: notificationConfig.ERROR_DURATION }) return } @@ -202,24 +206,24 @@ const handleOpenModel = async () => { background: var(--color-bg-primary); color: var(--color-text-primary); overflow-y: auto; - padding: 20px; - gap: 24px; + padding: var(--spacing-xl); + gap: var(--spacing-2xl); } /* CAD软件选择器 */ .software-selector { background: var(--color-bg-card); - border-radius: 8px; - padding: 20px; - border: 1px solid var(--color-border-primary); + border-radius: var(--size-border-radius); + padding: var(--spacing-xl); + border: var(--border-width-thin) solid var(--color-border-primary); } .selector-title { display: flex; align-items: center; - gap: 8px; - margin: 0 0 16px 0; - font-size: 16px; + gap: var(--spacing-sm); + margin: 0 0 var(--spacing-lg) 0; + font-size: var(--font-size-lg); font-weight: 600; color: var(--color-text-primary); } @@ -232,11 +236,11 @@ const handleOpenModel = async () => { .selected-software { display: flex; align-items: center; - gap: 8px; - padding: 12px; + gap: var(--spacing-sm); + padding: var(--spacing-md); background: var(--color-white-rgb-05); - border-radius: 6px; - font-size: 14px; + border-radius: var(--size-border-radius-button); + font-size: var(--font-size-base); } .selected-label { @@ -252,17 +256,17 @@ const handleOpenModel = async () => { /* 模型管理面板 */ .panel-section { background: var(--color-bg-card); - border-radius: 8px; - padding: 20px; - border: 1px solid var(--color-border-primary); + border-radius: var(--size-border-radius); + padding: var(--spacing-xl); + border: var(--border-width-thin) solid var(--color-border-primary); } .section-title { display: flex; align-items: center; - gap: 8px; - margin: 0 0 16px 0; - font-size: 16px; + gap: var(--spacing-sm); + margin: 0 0 var(--spacing-lg) 0; + font-size: var(--font-size-lg); font-weight: 600; color: var(--color-text-primary); } @@ -274,9 +278,9 @@ const handleOpenModel = async () => { .selection-title { display: flex; align-items: center; - gap: 8px; - margin-bottom: 12px; - font-size: 14px; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); + font-size: var(--font-size-base); font-weight: 500; color: var(--color-text-primary); } @@ -288,19 +292,19 @@ const handleOpenModel = async () => { .selection-options { display: flex; flex-direction: column; - gap: 8px; - margin-bottom: 16px; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-lg); } .option-item { display: flex; align-items: flex-start; - gap: 12px; - padding: 12px; + gap: var(--spacing-md); + padding: var(--spacing-md); background: var(--color-white-rgb-05); - border-radius: 6px; + border-radius: var(--size-border-radius-button); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); } .option-item:hover { @@ -308,7 +312,7 @@ const handleOpenModel = async () => { } .option-item input[type="radio"] { - margin-top: 2px; + margin-top: var(--size-2); } .option-content { @@ -317,39 +321,39 @@ const handleOpenModel = async () => { .option-content i { color: var(--color-primary); - margin-right: 8px; + margin-right: var(--spacing-sm); } .option-content span { display: block; color: var(--color-text-primary); font-weight: 500; - margin-bottom: 4px; + margin-bottom: var(--spacing-xs); } .option-content small { color: var(--color-text-secondary); - font-size: 12px; + font-size: var(--font-size-xs); } .project-actions { display: flex; - gap: 8px; + gap: var(--spacing-sm); } .confirm-btn { display: flex; align-items: center; - gap: 8px; - padding: 10px 16px; + gap: var(--spacing-sm); + padding: var(--spacing-grid-gap) var(--spacing-lg); background: var(--color-primary); color: white; border: none; - border-radius: 6px; - font-size: 14px; + border-radius: var(--size-border-radius-button); + font-size: var(--font-size-base); font-weight: 500; cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); } .confirm-btn:hover { @@ -358,12 +362,12 @@ const handleOpenModel = async () => { } .confirm-btn i { - font-size: 14px; + font-size: var(--font-size-base); } /* 滚动条样式 */ .side-panel::-webkit-scrollbar { - width: 6px; + width: var(--size-6); } .side-panel::-webkit-scrollbar-track { @@ -372,7 +376,7 @@ const handleOpenModel = async () => { .side-panel::-webkit-scrollbar-thumb { background: var(--color-white-rgb-2); - border-radius: 3px; + border-radius: var(--size-3); } .side-panel::-webkit-scrollbar-thumb:hover { diff --git a/src/components/model/CreoModelViewer.vue b/src/components/model/CreoModelViewer.vue index 82b1ef2..58eee53 100644 --- a/src/components/model/CreoModelViewer.vue +++ b/src/components/model/CreoModelViewer.vue @@ -396,7 +396,7 @@ const basicCheck = () => { border-radius: 6px; color: var(--color-text-primary); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); font-size: 14px; } diff --git a/src/components/model/PdmsModelViewer.vue b/src/components/model/PdmsModelViewer.vue index f17f2a4..5016f9f 100644 --- a/src/components/model/PdmsModelViewer.vue +++ b/src/components/model/PdmsModelViewer.vue @@ -137,6 +137,10 @@ @@ -301,12 +305,12 @@ const testConnection = () => { .title-icon.pdms-icon { width: 60px; height: 60px; - background: linear-gradient(135deg, #FF6B35 0%, #F7931E 100%); + background: var(--color-pdms-gradient); border-radius: 12px; display: flex; align-items: center; justify-content: center; - box-shadow: 0 4px 12px rgba(255, 107, 53, 0.3); + box-shadow: 0 4px 12px var(--color-pdms-shadow); } .title-icon.pdms-icon i { @@ -360,7 +364,7 @@ const testConnection = () => { } .pdms-project-info h3 i { - color: #FF6B35; + color: var(--color-pdms); } .info-item { @@ -400,12 +404,12 @@ const testConnection = () => { padding: 20px; border: 1px solid var(--color-border-primary); text-align: center; - transition: all 0.3s ease; + transition: var(--transition-all); } .pdms-stat-card:hover { transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); + box-shadow: var(--color-shadow-card); } .pdms-stat-card h4 { @@ -420,7 +424,7 @@ const testConnection = () => { } .pdms-stat-card h4 i { - color: #FF6B35; + color: var(--color-pdms); } .stat-number { @@ -462,7 +466,7 @@ const testConnection = () => { } .pdms-elements-breakdown h4 i { - color: #FF6B35; + color: var(--color-pdms); } .pdms-element-item { @@ -495,12 +499,12 @@ const testConnection = () => { font-size: 14px; } -.pdms-element-icon.pipe { background: rgba(59, 130, 246, 0.1); color: #3B82F6; } -.pdms-element-icon.elbo { background: rgba(139, 69, 19, 0.1); color: #8B4513; } -.pdms-element-icon.valve { background: rgba(220, 38, 127, 0.1); color: #DC267F; } -.pdms-element-icon.fitting { background: rgba(168, 85, 247, 0.1); color: #A855F7; } -.pdms-element-icon.equipment { background: rgba(34, 197, 94, 0.1); color: #22C55E; } -.pdms-element-icon.structure { background: rgba(156, 163, 175, 0.1); color: #9CA3AF; } +.pdms-element-icon.pipe { background: var(--color-pdms-pipe-bg); color: var(--color-pdms-pipe); } +.pdms-element-icon.elbo { background: var(--color-pdms-elbo-bg); color: var(--color-pdms-elbo); } +.pdms-element-icon.valve { background: var(--color-pdms-valve-bg); color: var(--color-pdms-valve); } +.pdms-element-icon.fitting { background: var(--color-pdms-fitting-bg); color: var(--color-pdms-fitting); } +.pdms-element-icon.equipment { background: var(--color-pdms-equipment-bg); color: var(--color-pdms-equipment); } +.pdms-element-icon.structure { background: var(--color-pdms-structure-bg); color: var(--color-pdms-structure); } .pdms-element-count { font-weight: 600; @@ -527,7 +531,7 @@ const testConnection = () => { } .pdms-zones-panel h4 i { - color: #FF6B35; + color: var(--color-pdms); } .zone-summary { @@ -597,7 +601,7 @@ const testConnection = () => { } .pdms-session-info h4 i { - color: #FF6B35; + color: var(--color-pdms); } .pdms-session-item { @@ -642,7 +646,7 @@ const testConnection = () => { } .pdms-actions-panel h4 i { - color: #FF6B35; + color: var(--color-pdms); } .pdms-action-btn { @@ -657,18 +661,18 @@ const testConnection = () => { border-radius: 6px; color: var(--color-text-primary); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); font-size: 14px; } .pdms-action-btn:hover { background: var(--color-white-rgb-1); - border-color: #FF6B35; + border-color: var(--color-pdms); transform: translateY(-1px); } .pdms-action-btn i { - color: #FF6B35; + color: var(--color-pdms); font-size: 14px; } diff --git a/src/components/model/RevitModelViewer.vue b/src/components/model/RevitModelViewer.vue index f491322..b1fe5c8 100644 --- a/src/components/model/RevitModelViewer.vue +++ b/src/components/model/RevitModelViewer.vue @@ -151,6 +151,10 @@ @@ -336,12 +340,12 @@ const testConnection = () => { .title-icon.revit-icon { width: 60px; height: 60px; - background: linear-gradient(135deg, #2E8B57 0%, #20B2AA 100%); + background: var(--color-revit-gradient); border-radius: 12px; display: flex; align-items: center; justify-content: center; - box-shadow: 0 4px 12px rgba(46, 139, 87, 0.3); + box-shadow: 0 4px 12px var(--color-revit-shadow); } .title-icon.revit-icon i { @@ -395,7 +399,7 @@ const testConnection = () => { } .revit-project-info h3 i { - color: #2E8B57; + color: var(--color-revit); } .info-item { @@ -435,12 +439,12 @@ const testConnection = () => { padding: 20px; border: 1px solid var(--color-border-primary); text-align: center; - transition: all 0.3s ease; + transition: var(--transition-all); } .revit-stat-card:hover { transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); + box-shadow: var(--color-shadow-card); } .revit-stat-card h4 { @@ -455,7 +459,7 @@ const testConnection = () => { } .revit-stat-card h4 i { - color: #2E8B57; + color: var(--color-revit); } .stat-number { @@ -497,7 +501,7 @@ const testConnection = () => { } .revit-elements-breakdown h4 i { - color: #2E8B57; + color: var(--color-revit); } .revit-element-item { @@ -530,16 +534,16 @@ const testConnection = () => { font-size: 14px; } -.revit-element-icon.walls { background: rgba(139, 69, 19, 0.1); color: #8B4513; } -.revit-element-icon.doors { background: rgba(255, 165, 0, 0.1); color: #FFA500; } -.revit-element-icon.windows { background: rgba(135, 206, 250, 0.1); color: #87CEEB; } -.revit-element-icon.floors { background: rgba(105, 105, 105, 0.1); color: #696969; } -.revit-element-icon.ceilings { background: rgba(245, 245, 220, 0.1); color: #F5F5DC; } -.revit-element-icon.columns { background: rgba(112, 128, 144, 0.1); color: #708090; } -.revit-element-icon.beams { background: rgba(169, 169, 169, 0.1); color: #A9A9A9; } -.revit-element-icon.rooms { background: rgba(255, 182, 193, 0.1); color: #FFB6C1; } -.revit-element-icon.stairs { background: rgba(205, 133, 63, 0.1); color: #CD853F; } -.revit-element-icon.railings { background: rgba(176, 196, 222, 0.1); color: #B0C4DE; } +.revit-element-icon.walls { background: var(--color-revit-walls-bg); color: var(--color-revit-walls); } +.revit-element-icon.doors { background: var(--color-revit-doors-bg); color: var(--color-revit-doors); } +.revit-element-icon.windows { background: var(--color-revit-windows-bg); color: var(--color-revit-windows); } +.revit-element-icon.floors { background: var(--color-revit-floors-bg); color: var(--color-revit-floors); } +.revit-element-icon.ceilings { background: var(--color-revit-ceilings-bg); color: var(--color-revit-ceilings); } +.revit-element-icon.columns { background: var(--color-revit-columns-bg); color: var(--color-revit-columns); } +.revit-element-icon.beams { background: var(--color-revit-beams-bg); color: var(--color-revit-beams); } +.revit-element-icon.rooms { background: var(--color-revit-rooms-bg); color: var(--color-revit-rooms); } +.revit-element-icon.stairs { background: var(--color-revit-stairs-bg); color: var(--color-revit-stairs); } +.revit-element-icon.railings { background: var(--color-revit-railings-bg); color: var(--color-revit-railings); } .revit-element-count { font-weight: 600; @@ -566,7 +570,7 @@ const testConnection = () => { } .revit-views-panel h4 i { - color: #2E8B57; + color: var(--color-revit); } .view-summary { @@ -597,11 +601,11 @@ const testConnection = () => { margin-bottom: 6px; background: var(--color-white-rgb-05); border-radius: 6px; - border-left: 3px solid #2E8B57; + border-left: 3px solid var(--color-revit); } .revit-view-item i { - color: #2E8B57; + color: var(--color-revit); } .revit-view-item span { @@ -636,7 +640,7 @@ const testConnection = () => { } .revit-links-info h4 i { - color: #2E8B57; + color: var(--color-revit); } .revit-link-item { @@ -681,7 +685,7 @@ const testConnection = () => { } .revit-actions-panel h4 i { - color: #2E8B57; + color: var(--color-revit); } .revit-action-btn { @@ -696,18 +700,18 @@ const testConnection = () => { border-radius: 6px; color: var(--color-text-primary); cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); font-size: 14px; } .revit-action-btn:hover { background: var(--color-white-rgb-1); - border-color: #2E8B57; + border-color: var(--color-revit); transform: translateY(-1px); } .revit-action-btn i { - color: #2E8B57; + color: var(--color-revit); font-size: 14px; } diff --git a/src/components/pages/CreoExportTools.vue b/src/components/pages/CreoExportTools.vue index f44013f..e9b88ba 100644 --- a/src/components/pages/CreoExportTools.vue +++ b/src/components/pages/CreoExportTools.vue @@ -238,8 +238,8 @@ const onFormatChange = () => { align-items: center; gap: 20px; padding: 15px; - background: rgba(42, 92, 170, 0.1); - border: 1px solid rgba(42, 92, 170, 0.3); + background: var(--color-primary-rgb); + border: 1px solid var(--color-primary-rgb-3); border-radius: 10px; } @@ -422,7 +422,7 @@ const onFormatChange = () => { overflow: hidden; background: linear-gradient(135deg, var(--color-success) 0%, var(--color-success) 100%); border: none; - box-shadow: 0 4px 15px rgba(76, 175, 80, 0.3); + box-shadow: var(--color-shadow-btn-success); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); white-space: nowrap; min-width: 150px; @@ -431,11 +431,11 @@ const onFormatChange = () => { .btn-export:hover:not(:disabled) { transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(76, 175, 80, 0.4); + box-shadow: 0 8px 25px var(--color-success-rgb-3); } .btn-export:disabled { - background: linear-gradient(135deg, #666 0%, #555 100%); + background: var(--color-gradient-gray); box-shadow: none; opacity: 0.7; } diff --git a/src/components/pages/CreoModelAnalysis.vue b/src/components/pages/CreoModelAnalysis.vue index 77e56c2..7837dcc 100644 --- a/src/components/pages/CreoModelAnalysis.vue +++ b/src/components/pages/CreoModelAnalysis.vue @@ -16,7 +16,7 @@ title="智能薄壳化分析" description="智能识别内部特征,实现安全的模型轻量化" icon-class="fas fa-magic" - icon-color="linear-gradient(135deg, #6f42c1, #e83e8c)" + :icon-color="'var(--color-creo-analysis-gradient-1)'" :features="['内部识别', '安全薄壳', '质量控制', '智能预览']" @start-analysis="handleShellAnalysis" /> @@ -27,7 +27,7 @@ title="按层级删除优化" description="基于特征层级关系的智能删除策略" icon-class="fas fa-layer-group" - icon-color="linear-gradient(135deg, #17a2b8, #138496)" + :icon-color="'var(--color-creo-analysis-gradient-2)'" :features="['从顶层开始', '安全删除', '关系分析', '批量操作']" @start-analysis="handleHierarchyDeletion" /> @@ -38,7 +38,7 @@ title="几何复杂度分析" description="分析模型几何复杂度,识别优化目标零件" icon-class="fas fa-chart-line" - icon-color="linear-gradient(135deg, #28a745, #20c997)" + :icon-color="'var(--color-creo-analysis-gradient-3)'" :features="['复杂度计算', '零件排序', '智能筛选', '评分系统']" @start-analysis="handleGeometryComplexity" /> @@ -49,7 +49,7 @@ title="几何优化分析" description="优化模型几何结构,减少冗余面和曲线" icon-class="fas fa-shapes" - icon-color="linear-gradient(135deg, #fd7e14, #e83e8c)" + :icon-color="'var(--color-creo-analysis-gradient-4)'" :features="['表面简化', '曲线优化', '质量保证', '结构分析']" @start-analysis="handleGeometryOptimization" /> @@ -60,7 +60,7 @@ title="批量处理" description="对多个零件进行批量薄壳化处理" icon-class="fas fa-tasks" - icon-color="linear-gradient(135deg, #dc3545, #c82333)" + :icon-color="'var(--color-creo-analysis-gradient-5)'" :features="['多文件', '并行处理', '进度跟踪', '结果汇总']" button-text="开始处理" @start-analysis="handleBatchProcessing" @@ -73,11 +73,36 @@ \ No newline at end of file diff --git a/src/components/pages/ShellAnalysisResult.vue b/src/components/pages/ShellAnalysisResult.vue index 1636fcf..2467bec 100644 --- a/src/components/pages/ShellAnalysisResult.vue +++ b/src/components/pages/ShellAnalysisResult.vue @@ -528,7 +528,7 @@ const deleteSelectedComponents = async () => { border-radius: 12px; padding: 0; overflow: hidden; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + box-shadow: var(--color-shadow-btn); } .summary-header { @@ -608,7 +608,7 @@ const deleteSelectedComponents = async () => { border: 1px solid var(--color-white-rgb-1); border-radius: 12px; overflow: hidden; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + box-shadow: var(--color-shadow-btn); } .shell-parts-header { @@ -688,12 +688,12 @@ const deleteSelectedComponents = async () => { } .shell-parts-table th { - background: rgba(255, 140, 0, 0.1); + background: var(--color-complexity-bg-1); color: var(--color-text-primary); padding: 12px 15px; text-align: left; font-weight: 600; - border-bottom: 2px solid rgba(255, 140, 0, 0.2); + border-bottom: 2px solid var(--color-complexity-border-2); } .shell-parts-table td { @@ -707,12 +707,12 @@ const deleteSelectedComponents = async () => { } .shell-part-row:hover { - background: rgba(255, 140, 0, 0.05); + background: var(--color-complexity-bg-1); } .shell-part-row.selected { - background: rgba(255, 140, 0, 0.1); - border-left: 3px solid #FF8C00; + background: var(--color-complexity-bg-1); + border-left: 3px solid var(--color-complexity); } .part-name { @@ -769,21 +769,21 @@ const deleteSelectedComponents = async () => { } .feasibility-badge.high { - background: rgba(40, 167, 69, 0.1); - color: #28a745; - border: 1px solid rgba(40, 167, 69, 0.3); + background: var(--color-complexity-low-bg); + color: var(--color-complexity-low); + border: 1px solid var(--color-complexity-low); } .feasibility-badge.medium { - background: rgba(255, 193, 7, 0.1); - color: #ffc107; - border: 1px solid rgba(255, 193, 7, 0.3); + background: var(--color-complexity-medium-bg); + color: var(--color-complexity-medium); + border: 1px solid var(--color-complexity-medium); } .feasibility-badge.low { - background: rgba(220, 53, 69, 0.1); - color: #dc3545; - border: 1px solid rgba(220, 53, 69, 0.3); + background: var(--color-complexity-high-bg); + color: var(--color-complexity-high); + border: 1px solid var(--color-complexity-high); } /* 操作区域样式 */ diff --git a/src/components/pages/UniversalConverter.vue b/src/components/pages/UniversalConverter.vue index b3d8714..e853962 100644 --- a/src/components/pages/UniversalConverter.vue +++ b/src/components/pages/UniversalConverter.vue @@ -153,7 +153,7 @@ const selectFile = () => { justify-content: center; font-size: 28px; color: white; - box-shadow: 0 4px 16px rgba(var(--color-primary-base), var(--opacity-light)); + box-shadow: 0 4px 16px var(--color-primary-rgb); } .header-text h2 { @@ -377,13 +377,13 @@ const selectFile = () => { .action-btn.primary { background: var(--color-success); color: white; - box-shadow: 0 4px 16px rgba(var(--success-color-rgb), var(--opacity-light)); + box-shadow: 0 4px 16px var(--color-success-rgb-1); } .action-btn.primary:hover:not(:disabled) { - background: rgba(var(--success-color-rgb), var(--opacity-strong)); + background: var(--color-success-rgb-5); transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(var(--success-color-rgb), var(--opacity-medium)); + box-shadow: 0 6px 20px var(--color-success-rgb-3); } .action-btn.primary:disabled { @@ -461,11 +461,5 @@ const selectFile = () => { display: none; } -/* CSS变量定义 */ -:root { - --success-color-rgb: 76, 175, 80; - --opacity-light: 0.3; - --opacity-medium: 0.4; - --opacity-strong: 0.9; -} +/* 使用全局CSS变量 - 已在theme.css中统一定义 */ \ No newline at end of file diff --git a/src/components/ui/AnalysisToolCard.vue b/src/components/ui/AnalysisToolCard.vue index 19aa5d7..1cd249c 100644 --- a/src/components/ui/AnalysisToolCard.vue +++ b/src/components/ui/AnalysisToolCard.vue @@ -83,10 +83,10 @@ defineEmits(['start-analysis']) border: 1px solid var(--color-border-primary); border-radius: var(--spacing-lg); overflow: hidden; - transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + transition: var(--transition-all-smooth); position: relative; backdrop-filter: blur(10px); - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + box-shadow: var(--color-shadow-card); } .analysis-tool-card::before { @@ -102,7 +102,7 @@ defineEmits(['start-analysis']) .analysis-tool-card:hover { border-color: var(--color-primary); - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15), 0 0 20px var(--color-shadow-primary); + box-shadow: var(--color-shadow-card), 0 0 20px var(--color-shadow-primary); transform: translateY(-4px) scale(1.02); } @@ -168,7 +168,7 @@ defineEmits(['start-analysis']) left: 2px; right: 2px; bottom: 2px; - background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, transparent 50%, rgba(255, 255, 255, 0.05) 100%); + background: linear-gradient(135deg, var(--color-white-rgb-15) 0%, transparent 50%, var(--color-white-rgb-05) 100%); border-radius: inherit; pointer-events: none; } @@ -253,7 +253,7 @@ defineEmits(['start-analysis']) display: flex; align-items: center; gap: var(--spacing-sm); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + transition: var(--transition-all-smooth); box-shadow: 0 6px 20px var(--color-shadow-primary); position: relative; overflow: hidden; @@ -267,7 +267,7 @@ defineEmits(['start-analysis']) left: -100%; width: 100%; height: 100%; - background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.2) 50%, transparent 100%); + background: linear-gradient(90deg, transparent 0%, var(--color-white-rgb-2) 50%, transparent 100%); transition: left 0.6s ease; } diff --git a/src/config/cad.js b/src/config/cad.js index 65fffea..bc55e20 100644 --- a/src/config/cad.js +++ b/src/config/cad.js @@ -29,6 +29,7 @@ const API_CONFIG = { POSITION: 'top-right', SUCCESS_DURATION: 2000, // 成功通知2秒 ERROR_DURATION: 3000, // 错误通知3秒 + SUCCESS_LONG_DURATION: 5000, // 重要成功通知5秒 SUCCESS_TITLE: '操作成功', ERROR_TITLE: '操作失败' }, diff --git a/src/services/apiClient.js b/src/services/apiClient.js index 24e6e67..5e0ad4a 100644 --- a/src/services/apiClient.js +++ b/src/services/apiClient.js @@ -4,6 +4,7 @@ import { getDefaultRequestConfig, getNotificationConfig } from '@/config/cad' import { ElNotification, ElLoading } from 'element-plus' import websocketService from './websocketService' +import Logger from '@/utils/logger' // 日志记录系统 class ApiLogger { @@ -58,7 +59,7 @@ class PostProcessManager { try { await handler(response, requestContext) } catch (error) { - console.error('后处理钩子执行失败:', error) + Logger.callbackError('PostProcessHandler', error) // 不影响主流程,但记录错误 } } diff --git a/src/services/websocketService.js b/src/services/websocketService.js index a34945a..43968a7 100644 --- a/src/services/websocketService.js +++ b/src/services/websocketService.js @@ -2,6 +2,7 @@ // 基于参考项目接口格式实现 import { getWebSocketConfig } from '@/config/cad' +import Logger from '@/utils/logger' class WebSocketService { constructor() { @@ -85,7 +86,7 @@ class WebSocketService { this.handleMessage(message) this.emit('onMessage', message) } catch (error) { - console.error('解析管理后台消息失败:', error, event.data) + Logger.wsError('解析管理后台消息', error, event.data) } } @@ -151,10 +152,10 @@ class WebSocketService { this.getSoftwareList() break case 'error': - console.error('管理后台错误:', message.message) + Logger.wsError('管理后台', message.message) break default: - console.log('未处理的消息类型:', message.type, message) + // 未知消息类型,静默忽略 } } @@ -213,7 +214,7 @@ class WebSocketService { // API方法 - 启动软件 startSoftware(softwareId) { if (!softwareId || typeof softwareId !== 'string' || softwareId.length === 0) { - console.error('启动软件失败: 无效的软件ID', softwareId) + Logger.error('启动软件失败: 无效的软件ID', softwareId) return false } @@ -226,7 +227,7 @@ class WebSocketService { // API方法 - 停止软件 stopSoftware(softwareId) { if (!softwareId || typeof softwareId !== 'string' || softwareId.length === 0) { - console.error('停止软件失败: 无效的软件ID', softwareId) + Logger.error('停止软件失败: 无效的软件ID', softwareId) return false } @@ -239,7 +240,7 @@ class WebSocketService { // API方法 - 重启软件 restartSoftware(softwareId) { if (!softwareId || typeof softwareId !== 'string' || softwareId.length === 0) { - console.error('重启软件失败: 无效的软件ID', softwareId) + Logger.error('重启软件失败: 无效的软件ID', softwareId) return false } @@ -252,7 +253,7 @@ class WebSocketService { // API方法 - 记录操作日志 logOperation(operation, details = '', options = {}) { if (!operation || typeof operation !== 'string' || operation.length === 0) { - console.error('记录日志失败: 操作名称不能为空') + Logger.error('记录日志失败: 操作名称不能为空') return false } @@ -298,7 +299,7 @@ class WebSocketService { // API方法 - 根据ID获取日志 getLogById(logId) { if (!logId || typeof logId !== 'string' || logId.length === 0) { - console.error('获取日志失败: 无效的日志ID', logId) + Logger.error('获取日志失败: 无效的日志ID', logId) return false } @@ -353,7 +354,7 @@ class WebSocketService { if (this.listeners[event]) { this.listeners[event].push(callback) } else { - console.warn('未知事件类型:', event) + // 静默忽略未知事件类型 } } @@ -372,7 +373,7 @@ class WebSocketService { try { callback(data) } catch (error) { - console.error('事件回调执行失败:', event, error) + Logger.callbackError(event, error) } }) } diff --git a/src/utils/logger.js b/src/utils/logger.js new file mode 100644 index 0000000..4a7abc0 --- /dev/null +++ b/src/utils/logger.js @@ -0,0 +1,58 @@ +// 统一日志管理工具 +// 提供生产环境和开发环境的日志控制 + +const isDevelopment = import.meta.env.MODE === 'development' + +// 日志级别 +const LOG_LEVELS = { + ERROR: 0, + WARN: 1, + INFO: 2, + DEBUG: 3 +} + +// 当前日志级别(生产环境只显示错误,开发环境显示所有) +const currentLevel = isDevelopment ? LOG_LEVELS.DEBUG : LOG_LEVELS.ERROR + +class Logger { + static error(...args) { + if (currentLevel >= LOG_LEVELS.ERROR) { + console.error('[ERROR]', ...args) + } + } + + static warn(...args) { + if (currentLevel >= LOG_LEVELS.WARN) { + console.warn('[WARN]', ...args) + } + } + + static info(...args) { + if (currentLevel >= LOG_LEVELS.INFO) { + console.info('[INFO]', ...args) + } + } + + static debug(...args) { + if (currentLevel >= LOG_LEVELS.DEBUG) { + console.log('[DEBUG]', ...args) + } + } + + // 专用于API错误日志 + static apiError(operation, error, context = {}) { + this.error(`API错误 [${operation}]:`, error, '上下文:', context) + } + + // 专用于WebSocket错误日志 + static wsError(operation, error, data = null) { + this.error(`WebSocket错误 [${operation}]:`, error, data && `数据: ${data}`) + } + + // 专用于回调执行错误 + static callbackError(event, error) { + this.error(`回调执行失败 [${event}]:`, error) + } +} + +export default Logger \ No newline at end of file diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue index fe0d0db..dc0e37d 100644 --- a/src/views/DashboardView.vue +++ b/src/views/DashboardView.vue @@ -608,7 +608,7 @@ const closeInfoPanel = () => { color: var(--color-text-primary); font-size: 14px; cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); text-decoration: none; } @@ -691,7 +691,7 @@ const closeInfoPanel = () => { border: 1px solid var(--color-white-rgb-1); border-radius: 8px; padding: 20px; - transition: all 0.3s ease; + transition: var(--transition-all); } .feature-item:hover { diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index d627560..dc48cfe 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -270,50 +270,50 @@ onMounted(() => { position: absolute; border-radius: 50%; background: var(--color-gradient-brand-bg); - animation: float 6s ease-in-out infinite; + animation: float var(--login-float-duration) ease-in-out infinite; } .circle-1 { - width: 200px; - height: 200px; - top: 10%; - left: 10%; - animation-delay: 0s; + width: var(--login-animation-large); + height: var(--login-animation-large); + top: var(--login-circle-1-top); + left: var(--login-circle-1-left); + animation-delay: var(--login-animation-delay-1); } .circle-2 { - width: 150px; - height: 150px; - top: 60%; - right: 15%; - animation-delay: 2s; + width: var(--login-animation-medium); + height: var(--login-animation-medium); + top: var(--login-circle-2-top); + right: var(--login-circle-2-right); + animation-delay: var(--login-animation-delay-2); } .circle-3 { - width: 100px; - height: 100px; - bottom: 20%; - left: 20%; - animation-delay: 4s; + width: var(--login-animation-small); + height: var(--login-animation-small); + bottom: var(--login-circle-3-bottom); + left: var(--login-circle-3-left); + animation-delay: var(--login-animation-delay-3); } @keyframes float { 0%, 100% { transform: translateY(0px) rotate(0deg); } - 50% { transform: translateY(-20px) rotate(180deg); } + 50% { transform: translateY(var(--login-float-distance)) rotate(180deg); } } .login-content { position: relative; z-index: 1; width: 100%; - max-width: 420px; - padding: 20px; + max-width: var(--login-card-max-width); + padding: var(--login-card-padding-small); } .login-card { background: var(--color-bg-dark-95); - border-radius: 16px; - padding: 40px; + border-radius: var(--login-card-border-radius); + padding: var(--login-card-padding); box-shadow: 0 20px 40px var(--color-shadow-black-3); backdrop-filter: blur(10px); border: 1px solid var(--color-white-rgb-1); @@ -321,36 +321,36 @@ onMounted(() => { .brand-section { text-align: center; - margin-bottom: 40px; + margin-bottom: var(--login-brand-margin-bottom); } .brand-logo { display: inline-flex; align-items: center; justify-content: center; - width: 60px; - height: 60px; + width: var(--login-icon-size); + height: var(--login-icon-size); background: var(--color-primary-gradient); - border-radius: 16px; - margin-bottom: 16px; + border-radius: var(--login-card-border-radius); + margin-bottom: var(--login-brand-logo-margin-bottom); box-shadow: 0 4px 15px var(--color-primary-rgb-3); } .brand-logo i { - font-size: 24px; + font-size: var(--login-title-size); color: var(--color-text-primary); } .brand-title { - font-size: 20px; + font-size: var(--login-subtitle-size); font-weight: 600; color: var(--color-text-primary); - margin: 0 0 8px 0; + margin: 0 0 var(--login-brand-title-margin-bottom) 0; line-height: 1.4; } .brand-subtitle { - font-size: 14px; + font-size: var(--login-text-size); color: var(--color-text-secondary); margin: 0; font-weight: 400; @@ -361,49 +361,49 @@ onMounted(() => { } .form-title { - font-size: 18px; + font-size: var(--login-button-text-size); font-weight: 600; color: var(--color-text-primary); text-align: center; - margin: 0 0 30px 0; + margin: 0 0 var(--login-form-title-margin-bottom) 0; } .error-message { display: flex; align-items: center; gap: 8px; - padding: 12px 16px; + padding: var(--input-padding-vertical) var(--input-padding-horizontal); background: var(--color-error-rgb-1); border: 1px solid var(--color-error-rgb-3); - border-radius: 8px; + border-radius: var(--size-border-radius); color: var(--color-text-error); - font-size: 14px; - margin-bottom: 20px; + font-size: var(--login-text-size); + margin-bottom: var(--login-error-margin-bottom); } .form-group { - margin-bottom: 20px; + margin-bottom: var(--login-form-group-margin-bottom); } .form-label { display: flex; align-items: center; gap: 8px; - font-size: 14px; + font-size: var(--login-text-size); font-weight: 500; color: var(--color-text-secondary); - margin-bottom: 8px; + margin-bottom: var(--login-form-label-margin-bottom); } .form-input { width: 100%; - padding: 12px 16px; + padding: var(--input-padding-vertical) var(--input-padding-horizontal); background: var(--color-white-rgb-05); border: 1px solid var(--color-white-rgb-1); - border-radius: 8px; + border-radius: var(--size-border-radius); color: var(--color-text-primary); - font-size: 14px; - transition: all 0.3s ease; + font-size: var(--login-text-size); + transition: var(--transition-all); box-sizing: border-box; } @@ -444,13 +444,13 @@ onMounted(() => { } .field-error { - font-size: 12px; + font-size: var(--font-size-xs); color: var(--color-text-error); - margin-top: 4px; + margin-top: var(--login-field-error-margin-top); } .form-options { - margin-bottom: 30px; + margin-bottom: var(--login-form-options-margin-bottom); } .checkbox-wrapper { @@ -472,7 +472,7 @@ onMounted(() => { border-radius: 4px; background: var(--color-white-rgb-05); position: relative; - transition: all 0.3s ease; + transition: var(--transition-all); } .checkbox-input:checked + .checkbox-custom { @@ -492,26 +492,26 @@ onMounted(() => { } .checkbox-label { - font-size: 14px; + font-size: var(--login-text-size); color: var(--color-text-secondary); } .login-button { width: 100%; - padding: 14px; + padding: var(--login-button-padding); background: var(--color-primary-gradient); border: none; - border-radius: 8px; + border-radius: var(--size-border-radius); color: var(--color-text-primary); - font-size: 16px; + font-size: var(--font-size-lg); font-weight: 600; cursor: pointer; - transition: all 0.3s ease; + transition: var(--transition-all); box-shadow: 0 4px 15px var(--color-primary-rgb-3); } .login-button:hover:not(:disabled) { - transform: translateY(-2px); + transform: var(--login-button-transform); box-shadow: 0 6px 20px var(--color-primary-rgb-4); } @@ -520,7 +520,7 @@ onMounted(() => { } .login-button:disabled { - opacity: 0.7; + opacity: var(--login-button-disabled-opacity); cursor: not-allowed; transform: none; } @@ -531,11 +531,11 @@ onMounted(() => { .help-text { text-align: center; - margin-top: 20px; + margin-top: var(--login-help-margin-top); } .help-text p { - font-size: 13px; + font-size: var(--font-size-sm); color: var(--color-text-tertiary); margin: 0; } @@ -543,15 +543,15 @@ onMounted(() => { /* 响应式设计 */ @media (max-width: 480px) { .login-content { - padding: 16px; + padding: var(--login-content-padding-mobile); } .login-card { - padding: 30px 24px; + padding: var(--login-card-padding-mobile); } .brand-title { - font-size: 18px; + font-size: var(--login-title-size-mobile); } .circle {