# 前端视觉与样式系统重构设计

**日期**：2026-07-09
**范围**：`frontend/` （Vue 3 + Element Plus + Pinia）
**目标用户**：内部数据/算法工程师，桌面端浏览器使用

## 背景与动机

当前前端已用 Element Plus + 自定义 SCSS 变量搭起一套"深色侧边栏 + 浅色内容区"的现代 B 端布局，但实际页面观感"乱"且有功能性瑕疵，根因不是设计语言本身有问题，而是**设计系统没有真正落地**：

- 颜色散落硬编码（`#1e293b`、`#475569`、`#909399`、`#1890ff`、`#67c23a`…）
- Element Plus 旧默认色与新主题色（`#4f46e5`）并存
- 用了 FontAwesome **4.7.0**（2017 年停止维护），大量 `fa-cogs`/`fa-hdd-o` 这种短横线后缀命名
- 登录页（`LoginView.vue`）背景是纯色 `#dbe0f9`，与主应用玻璃拟态风格割裂
- `AppHeader.vue:189` 引用了主题里**不存在**的 `--warning-color` 变量，导致回退到默认值
- `index.scss` 内有 5+ 处 `!important`，说明覆盖策略不对
- 装饰性动画（按钮悬停 `translateY(-1px)`、`pulse` 动画、过度渐变）增加视觉噪音

本次重构目标是**收口样式系统**，让"主题改一处，全站生效"，并消除明显观感问题。

## 范围与非范围

### 范围内

1. 统一颜色变量系统（消除硬编码、补齐缺失变量）
2. 图标库迁移：FA4 → **Element Plus Icons**（`@element-plus/icons-vue`，已与 Element Plus 同步）
3. 重新设计登录页，与主应用视觉一致
4. 修复 `AppHeader.vue` 的 `--warning-color` 缺失问题
5. 整理 `index.scss` 的 `!important` 覆盖，改用更高特异性选择器
6. 适度降低装饰性效果：移除按钮悬停位移、统一卡片阴影阶梯

### 非范围（本次不做）

- 布局结构改动（保留 260px 侧边栏 + 60px 顶栏）
- 深色模式切换
- 任何业务逻辑修改
- 移动端适配（当前项目无移动端需求）
- `web/` 静态版不动

## 方案选型

### 选定方案：方案 A — 克制重塑

保留现有"深色侧边栏 + 浅色内容区"骨架，做样式系统收口。

**未选 方案 B（极简重做）**：改动面太广，10+ 视图都要适配，回报/风险比差。
**未选 方案 C（全深色科技感）**：Element Plus 暗色需要大量单独调校，工作量与当前诉求不匹配。

## 设计

### 1. 颜色变量系统（`src/styles/index.scss` 重构）

**目标**：所有颜色、阴影、圆角都走 CSS 变量；后续改主题只改 `:root` 即可。

**新增/补齐变量**（`src/styles/index.scss` 顶部）：

```scss
:root {
  /* Element Plus 主色（已有） */
  --el-color-primary: #4f46e5;
  --el-color-primary-light-3: #818cf8;
  --el-color-primary-light-5: #a5b4fc;
  --el-color-primary-light-7: #c7d2fe;
  --el-color-primary-light-8: #e0e7ff;
  --el-color-primary-light-9: #eef2ff;
  --el-color-primary-dark-2: #4338ca;

  /* 状态色（已有） */
  --el-color-success: #10b981;
  --el-color-warning: #f59e0b;       /* 修复：之前未显式定义 */
  --el-color-danger: #ef4444;
  --el-color-info: #64748b;

  /* 项目别名（已有 + 新增） */
  --primary-color: var(--el-color-primary);
  --primary-hover: var(--el-color-primary-light-3);
  --success-color: var(--el-color-success);
  --warning-color: var(--el-color-warning);   /* 新增：修复 AppHeader 引用 */
  --danger-color: var(--el-color-danger);

  /* 圆角（已有） */
  --el-border-radius-base: 8px;
  --el-border-radius-small: 6px;
  --el-border-radius-round: 20px;

  /* ========== 新增：项目语义化变量 ========== */

  /* 文字 */
  --text-primary: #1e293b;            /* 替代硬编码 #1e293b */
  --text-secondary: #475569;          /* 替代 #475569 */
  --text-tertiary: #64748b;           /* 替代 #64748b */
  --text-placeholder: #94a3b8;        /* 替代 #94a3b8 */

  /* 背景 */
  --bg-page: #f8fafc;                 /* 替代 --el-bg-color-page */
  --bg-card: #ffffff;
  --bg-subtle: #f1f5f9;               /* 替代硬编码 #f1f5f9 */
  --bg-hover: #f8fafc;                /* 替代硬编码 #f8fafc */

  /* 边框 */
  --border-subtle: #e2e8f0;           /* 替代硬编码 #e2e8f0 */
  --border-base: #f1f5f9;             /* 替代硬编码 #f1f5f9 */

  /* 侧边栏（已有） */
  --sidebar-bg: #0f172a;
  --sidebar-text: #94a3b8;
  --sidebar-active-bg: rgba(79, 70, 229, 0.15);
  --sidebar-active-text: #ffffff;
  --sidebar-section-title: #64748b;

  /* 阴影（统一阶梯） */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 2px 8px rgba(15, 23, 42, 0.06);   /* 替代 --card-shadow */
  --shadow-lg: 0 8px 24px rgba(15, 23, 42, 0.08);
  --shadow-dialog: 0 20px 40px rgba(15, 23, 42, 0.12);

  /* 尺寸 */
  --header-height: 60px;
  --sidebar-width: 260px;
  --content-padding-x: 32px;
  --content-padding-y: 32px;
}
```

**改动原则**：
- 组件 SCSS 内的硬编码颜色全部替换为对应变量
- 任何新增颜色需求都先在 `:root` 定义，再引用
- 不再使用 `!important`；如确需覆盖，提升特异性（如 `:deep(.el-button)`）

### 2. 图标库迁移：FA4 → Element Plus Icons

**为什么选 Element Plus Icons**：
- 零新增依赖成本（仅在 `package.json` 增加一行）
- 与 Element Plus 组件视觉风格天然一致
- 树摇友好，按需引入
- SVG 渲染，可继承 `currentColor` 与 `font-size`，比 FA 字体图标更现代

**实施**：
1. `npm i @element-plus/icons-vue`
2. `main.ts` 全局注册常用图标（按需在组件内 import 也可）
3. 替换规则（在每个 view/component 内做局部替换）：

| FA4 类名 | Element Plus 图标 | 用在哪 |
|---------|------------------|--------|
| `fa-cogs` | `Setting` | 侧边栏"模型调优" |
| `fa-line-chart` | `TrendCharts` | 侧边栏"模型评测" |
| `fa-server` | `Monitor` | 侧边栏"模型推理" |
| `fa-cube` | `Box` | 侧边栏"模型管理"、Logo |
| `fa-file-text` | `Document` | 侧边栏"数据集" |
| `fa-wrench` | `Tools` | 侧边栏"其他工具" |
| `fa-bar-chart` | `DataAnalysis` | 侧边栏"平台性能" |
| `fa-search` | `Search` | 搜索框前缀 |
| `fa-plus` | `Plus` | 新建按钮 |
| `fa-trash` | `Delete` | 删除按钮 |
| `fa-arrow-left` | `ArrowLeft` | 返回按钮 |
| `fa-microchip` | `Cpu` | 性能监控 |
| `fa-database` | `Files` | 内存监控（数据文件堆） |
| `fa-hdd-o` | `Box` | 磁盘监控（存储箱） |
| `fa-sign-out` | `SwitchButton` | 退出登录 |
| `fa-angle-down` | `ArrowDown` | 下拉箭头 |
| `fa-user-circle-o` | `User` | 个人中心 |
| `fa-cog` | `Setting` | 系统设置 |
| `fa-stop-circle-o` | `VideoPause` | 停止训练 |
| `fa-pencil` | `Edit` | 编辑 |
| `fa-times` | `Close` | 关闭 |
| `fa-globe` | `Connection` | 网络流量 |
| `fa-info-circle` | `InfoFilled` | 系统信息 |
| `fa-user-o` | `User` | 登录页账号图标 |
| `fa-lock-o` | `Lock` | 登录页密码图标 |
| `fa-sign-in` | `Right` | 登录按钮 |

**注意点**：
- 替换后调整图标尺寸（Element Plus Icons 用 `size` prop 或 CSS `font-size`）
- 部分 FA4 类名（如 `fa-file-text-o`）在 FA5/FA6 已无 `-o` 后缀
- `main.ts` 中删除 `import '@/assets/font-awesome/css/font-awesome.min.css'`
- 删 `src/assets/font-awesome/` 整个目录（字体文件 100+KB）

### 3. 登录页重新设计（`LoginView.vue`）

**目标**：与主应用保持一致的视觉语言，背景改用渐变 + 玻璃卡片。

**设计**：
- 背景：渐变 `linear-gradient(135deg, #4f46e5 0%, #818cf8 50%, #c7d2fe 100%)`
- 卡片：白色，圆角 16px，阴影 `var(--shadow-dialog)`
- Logo 区域：上下结构（Logo 48px → 标题 24px → 副标题 14px 灰色）
- 表单：单项之间 20px 间距，输入框 44px 高，圆角 8px
- 按钮：主色实心，44px 高，全宽
- 选项行：flex 布局，记住密码左、忘记密码右
- 整体居中，最大宽 420px

**关键 CSS 改动**：
- 背景从 `#dbe0f9` 改为 `linear-gradient(135deg, #4f46e5 0%, #818cf8 50%, #c7d2fe 100%)`
- 卡片圆角从 12px 提升到 16px
- 阴影替换为 `var(--shadow-dialog)`
- 所有内联颜色改用变量

### 4. 修复 `AppHeader.vue` 的 `--warning-color` 缺失

**问题**：`AppHeader.vue:189` 使用 `var(--warning-color)`，但 `index.scss` 里只定义了 `--danger-color`、`--success-color`，没有 `--warning-color`。

**修复**：在 `:root` 中新增 `--warning-color: var(--el-color-warning);`（已在第 1 节列入）。

### 5. 整理 `index.scss` 的 `!important`

**现有 `!important` 用法**（来自 `index.scss`）：

| 选择器 | 用途 | 现状 |
|--------|------|------|
| `.el-card { border: none !important; ... }` | 去掉 EP 默认边框 | 提升为 `.app-container .el-card` 或全局加 `:where()` 重置 |
| `.el-tag { border: none !important; ... }` | 去掉 EP 默认边框 | 同上 |
| `.el-dialog { border-radius: 16px !important; ... }` | 圆角和阴影 | 同上 |

**改写策略**：
- 用更高特异性选择器（如 `body .el-card`）替代 `!important`
- 或用 CSS Layer (`@layer reset, overrides, components`) 控制优先级

**本次采用**：直接提高特异性，避免引入 CSS Layer 复杂度（属于项目既定风格之外的引入，需要权衡）。

### 6. 降低装饰性效果

**调整清单**：
- `index.scss` 移除 `.el-button:hover { transform: translateY(-1px); box-shadow: ...; }` — 改为仅改变背景色
- `AppHeader.vue` 移除 `pulse` 动画，改为静态红色
- 侧边栏菜单图标的 `transform: scale(1.1)` 悬停动画保留（这是细节点缀，不算噪音）
- 卡片悬停 `transform` 动效保留（仅在 DataTablePage 等列表卡片上，目前没有，不新增）
- 顶栏 `backdrop-filter: blur(12px)` 保留（玻璃感是这个项目的风格语言）

## 实施步骤（落地顺序）

按风险从低到高，便于逐步验证：

1. **步骤 1**：扩展 `src/styles/index.scss` 变量（新增，不删除旧的）
2. **步骤 2**：安装 `@element-plus/icons-vue`，在 `main.ts` 注册
3. **步骤 3**：逐文件替换图标（按表格顺序）
4. **步骤 4**：逐文件替换硬编码颜色为变量
5. **步骤 5**：重新设计 `LoginView.vue`
6. **步骤 6**：删除 `src/assets/font-awesome/` 目录和 `main.ts` 的 import
7. **步骤 7**：运行 `npm run type-check` 和 `npm run build` 验证

每步完成后截图（手动）确认未引入新问题。

## 验证标准

- [ ] `npm run type-check` 通过
- [ ] `npm run build` 通过
- [ ] 浏览器控制台无 CSS 警告（无未定义变量）
- [ ] 全站不再有 `#1890ff`、`#67c23a`、`#e6a23c`、`#f56c6c` 这类 EP 旧色硬编码（grep 验证）
- [ ] 全站不再有 `class="fa fa-` 的引用（grep 验证）
- [ ] 全站不再有 `--warning-color` 这类指向不存在变量的引用
- [ ] `grep -c "!important" src/styles/index.scss` 数量从当前值下降 50% 以上
- [ ] 登录页与主应用风格一致

## 风险与回退

- **风险 1**：Element Plus Icons 不覆盖某些冷门 FA 图标（如 `fa-stop-circle-o` 训练停止）
  - **应对**：在替换前先做一次图标对照表，确认每个 FA 类名都有 EP 对应项；没有则保留 FA4（不删除 FA 资源），但推进用 EP 主流图标
- **风险 2**：CSS 变量替换漏掉某处导致视觉回退
  - **应对**：分阶段提交，每阶段都跑 build；如有遗漏，EP 会回退到自身默认色
- **风险 3**：`!important` 整理引入新覆盖问题
  - **应对**：整理前先 `git diff` 对比编译产物颜色变化，保留 `git stash` 能力

## 后续优化（不在本次范围）

- 抽出 Design Token 文件（`tokens.scss`）做 Figma → Code 同步
- 引入 UnoCSS 或 Windi CSS 做原子化样式（取决于团队接受度）
- 给所有列表页加 skeleton 加载态
- 暗色模式支持（需要先在 EP 主题层注册暗色）
