From 746a000e8ab44e6314865dfd2be320cfac659898 Mon Sep 17 00:00:00 2001 From: logan Date: Wed, 27 May 2026 01:59:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=A8=E9=9D=A2UI=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20=E2=80=94=205=E5=A5=97=E4=B8=BB=E9=A2=98=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=20+=20=E8=AE=BE=E8=AE=A1=E4=BD=93=E7=B3=BB=20+=20=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E9=87=8D=E7=BB=84=20+=20=E9=A1=B5=E9=9D=A2=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 主题系统扩展 (5套主题) - ocean-deep(深海蓝) / light-professional(明亮白) / midnight-purple(午夜紫) - pine-green(松林绿) / orange-vitality(活力橙) - useTheme hook 重写支持5主题 + 向后兼容 - AppearanceSettings 5主题预览卡片 2. 设计体系 (index.css) - 按钮系统: dg-btn-primary/secondary/ghost/danger + 尺寸变体 - 徽章系统: dg-badge-* (8色) - 卡片/表格: dg-card-section, dg-table-row, dg-table-header - 状态点: dg-status-dot-* (4色) - 动效关键帧: slideInLeft, scaleIn 3. 菜单重组 (menu.ts) - 5分组: 概览/数据源/工单/权限/系统 - 6个图标更新: Code2/FileEdit/ShieldCheck/FolderLock/ScrollText/Timer - 新增 permission 权限码字段 4. Layout 侧边栏增强 - 左侧渐变指示条 + 发光效果 - hover 微动画 + 图标变色 - 面包屑导航头部 - 主题切换循环5主题 5. 核心页面优化 - TicketsPage: 设计系统类 + 颜色对齐 - QueriesPage: 去Card依赖 + dg-table/dg-btn统一 - Breadcrumb组件 + useBreadcrumb hook --- .../SQL平台全面评估与UIUX优化方案.docx | Bin 0 -> 143269 bytes SQL平台评估与优化/plan.md | 23 + .../sql_platform_optimization.agent.final.md | 3420 +++++++++++++++++ ...sql_platform_optimization.agent.outline.md | 78 + .../sql_platform_optimization_sec01.md | 237 ++ .../sql_platform_optimization_sec02.md | 171 + .../sql_platform_optimization_sec03.md | 393 ++ .../sql_platform_optimization_sec04.md | 741 ++++ .../sql_platform_optimization_sec05.md | 533 +++ .../sql_platform_optimization_sec06.md | 1136 ++++++ .../sql_platform_optimization_sec07_08.md | 209 + frontend/src/components/Breadcrumb.tsx | 139 + frontend/src/components/Layout.tsx | 114 +- .../src/components/login/CenteredCard.tsx | 5 +- frontend/src/components/login/FullImage.tsx | 5 +- frontend/src/components/login/MinimalDark.tsx | 5 +- frontend/src/components/login/SidePanel.tsx | 5 +- frontend/src/components/login/SplitView.tsx | 5 +- frontend/src/constants/menu.ts | 31 +- frontend/src/hooks/useLogin.tsx | 11 +- frontend/src/hooks/useTheme.tsx | 51 +- frontend/src/index.css | 331 +- frontend/src/pages/AppearanceSettings.tsx | 54 +- frontend/src/pages/QueriesPage.tsx | 84 +- frontend/src/pages/TicketsPage.tsx | 115 +- 25 files changed, 7718 insertions(+), 178 deletions(-) create mode 100644 SQL平台评估与优化/SQL平台全面评估与UIUX优化方案.docx create mode 100644 SQL平台评估与优化/plan.md create mode 100644 SQL平台评估与优化/sql_platform_optimization.agent.final.md create mode 100644 SQL平台评估与优化/sql_platform_optimization.agent.outline.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec01.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec02.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec03.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec04.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec05.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec06.md create mode 100644 SQL平台评估与优化/sql_platform_optimization_sec07_08.md create mode 100644 frontend/src/components/Breadcrumb.tsx diff --git a/SQL平台评估与优化/SQL平台全面评估与UIUX优化方案.docx b/SQL平台评估与优化/SQL平台全面评估与UIUX优化方案.docx new file mode 100644 index 0000000000000000000000000000000000000000..d2598ebc7d796958eb0ed15ebd739a5a74c24fe4 GIT binary patch literal 143269 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�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的 Web 框架,其高性能路由与极简的 Middleware 设计非常适合 API 密集型企业应用。ORM 层选用 **GORM v1.26.0**,借助其 AutoMigrate、关联预加载与插件扩展能力,可显著降低数据库操作层的样板代码量。元数据库采用 **SQLite**(通过 `gorm.io/driver/sqlite` 驱动),这一设计决策使得平台在部署时**零依赖外部数据库**,极大降低了私有化部署的门槛——这对于中小团队或对运维复杂度敏感的企业极具吸引力。 + +认证层采用 **JWT HS256 + bcrypt** 方案,Token 默认 24h 过期,在安全性与用户体验之间取得合理平衡。RBAC 权限中间件的独立设计体现了安全架构的前置思维,建议后续版本考虑引入 Refresh Token 机制以降低长期会话的泄露风险。 + +**前端架构** + +前端基于 **React 19 + TypeScript**,构建工具采用 **Vite 7**,这一组合代表了 2024-2025 年 React 生态的技术前沿。React 19 的 Server Components 支持(尽管当前项目以 CSR 为主)、Compiler 自动优化以及改进的 Suspense 边界处理,为后续性能演进预留了充足空间。Vite 7 相较于 Webpack 在冷启动速度(提升约 10-20 倍)与 HMR 响应速度上具备代际优势,显著改善开发体验。 + +UI 层采用 **shadcn/ui + Tailwind CSS 4 + Radix UI** 的三层架构:Radix UI 提供无样式、无障碍(A11y)完备的底层原语;Tailwind CSS 4 提供原子化样式能力;shadcn/ui 则在此基础上封装了一套设计一致、可高度定制的高阶组件。这种"无头组件 + 原子样式 + 组件封装"的分层模式,是当前前端 UI 架构的最佳实践之一。 + +代码编辑器选用 **CodeMirror 6**(`@codemirror/lang-sql` 语言包),相较于 Monaco Editor,CodeMirror 6 在包体积(Tree-shakeable 后约 100KB vs Monaco 的 1MB+)、移动端适配以及主题定制灵活性上表现更优,非常适合本项目这种以 SQL 编辑为核心但非纯 IDE 场景的应用。 + +图表层采用 **Recharts**,作为 React 生态中最成熟的 D3 封装库,其与 React 组件模型的深度整合使得在仪表盘页面中构建数据可视化变得直观高效。 + +### 1.2.2 技术栈优势分析 + +1. **部署零依赖**:SQLite 作为元数据库 + Go 单二进制部署,使得整个平台可以编译为单一可执行文件分发,运维成本极低。 +2. **类型安全贯穿全栈**:TypeScript(前端)+ Go(后端)的双重静态类型保障,配合 GORM 的模型定义与前端接口类型的共享(可通过 OpenAPI/Swagger 代码生成进一步强化),可显著降低因类型不匹配导致的运行时错误。 +3. **组件体系可扩展性强**:shadcn/ui 的组件代码直接存在于项目源码中(非 npm 黑盒),团队可根据业务需求任意修改组件内部实现而不受上游版本锁定。 +4. **性能基线优秀**:Go 的 goroutine 并发模型 + Gin 的高性能路由 + Vite 的快速构建 + React.lazy 代码分割,从后端到前端形成了一条完整的性能优化链路。 + +### 1.2.3 潜在技术债务 + +| 风险点 | 影响等级 | 说明与建议 | +|--------|----------|-----------| +| GORM v1.26.0 版本锁定 | 中 | GORM v2 与 v1 存在 API 不兼容变更,长期停留在 v1 会阻碍安全补丁获取。建议规划迁移至 GORM v2。 | +| SQLite 并发写入瓶颈 | 中 | SQLite 在 WAL 模式下可支持多读单写,但在高并发工单场景下可能成为瓶颈。建议评估是否需要支持 PostgreSQL/MySQL 作为可选元数据库。 | +| React 19 生态适配 | 低-中 | React 19 尚属较新版本,部分第三方库可能存在兼容性问题。建议建立依赖版本锁定策略,并持续跟踪关键依赖的 React 19 适配进度。 | +| JWT 无 Refresh Token | 中 | 24h 固定过期时间导致用户需要频繁重新登录,影响体验。建议引入 Refresh Token + Access Token 双 Token 机制。 | +| 缺少 API 文档自动化 | 低 | 后端 120+ 路由缺乏自动化文档输出。建议集成 Swagger/OpenAPI 自动生成,降低前后端协作成本。 | + +--- + +## 1.3 前端架构现状评估 + +### 1.3.1 页面结构与路由设计 + +项目当前包含 **24+ 页面**,覆盖平台五大功能域,页面层级设计遵循"功能域 → 功能页 → 操作面板"的三层信息架构原则: + +``` +概览 +└── 仪表盘(Dashboard)— 运营指标总览 + +数据源 +└── 数据源管理(Instances)— CRUD + 连接测试 + +工单管理 +├── 数据变更(Tickets/Change)— 变更工单列表 + 审批流 +└── 查询数据(Tickets/Query)— 查询工单列表 + SQL 执行 + +权限管理 +├── 权限组(PermissionGroups)— 权限集合管理 +├── 角色权限(Roles)— RBAC 角色定义 +└── 用户管理(Users)— 用户生命周期管理 + +系统配置 +├── 审计日志(AuditLogs)— 操作记录检索 +├── 审批流程(ApprovalFlows)— 审批节点自定义 +└── 自动任务(ScheduledTasks)— 定时任务管理 + +配置平台 +└── 系统设置(Settings)— 全局参数配置 +``` + +路由设计层面,项目已采用 **React.lazy 进行代码分割**,这是一个重要的性能优化信号——通过将各功能域拆分为独立的异步 Chunk,可显著降低首屏加载时间。建议进一步结合 React Router v6 的 `loader` 与 `action` API 实现路由级的数据预取,减少页面切换时的感知延迟。 + +平台提供 **5 种登录页主题**(SplitView / CenteredCard / SidePanel / FullImage / MinimalDark),这一设计体现了对部署场景多样性的考虑——不同企业可根据自身品牌调性选择最适合的登录体验。从维护性角度,建议将这 5 种主题抽象为统一的 "LoginLayout" 组件,通过配置对象驱动渲染,减少重复逻辑。 + +### 1.3.2 组件化程度分析 + +项目组件体系可分为三个层级,整体呈现良好的分层架构: + +| 层级 | 组件数量 | 代表组件 | 职责说明 | +|------|----------|----------|----------| +| 基础组件 | 50+ | Button, Input, Dialog, Table, Dropdown | shadcn/ui 封装,平台无关,可复用性最高 | +| 业务组件 | 9 | Layout, SqlEditor, SchemaSidebar, EditInstanceDialog | 领域特定,封装业务逻辑与交互模式 | +| 页面组件 | 24+ | Dashboard, Instances, Tickets, Settings | 路由级入口,组合业务组件完成特定功能 | + +**值得肯定的方面**: +- 自定义组件的命名遵循 PascalCase + 语义化约定(如 `SchemaSidebar`、`EditInstanceDialog`),可读性良好。 +- `SqlEditor` 组件作为核心交互组件被独立封装,基于 CodeMirror 6 提供了 SQL 语法高亮、关键词补全等能力,是可复用性最高的业务资产之一。 +- `Layout` 组件的统一设计确保了全站导航结构的一致性。 + +**建议改进的方向**: +- 业务组件层当前仅有 9 个,相对于 24+ 页面的规模略显单薄,存在页面间逻辑重复的可能性。建议对高频交互模式(如表单创建/编辑、列表筛选/分页、审批操作确认等)进行进一步抽象。 +- 建议建立组件文档体系(如 Storybook),记录各组件的 Props 接口、使用示例与视觉规格,降低团队协作成本。 + +### 1.3.3 状态管理方案 + +基于代码架构分析,项目当前的状态管理呈现 **"React 内置状态 + 局部上下文"** 的轻量级模式。对于 SQL-Platform 这类以表单操作和列表管理为核心的应用,这种状态管理策略是合理且务实的: + +- **服务端状态**(工单列表、实例配置、用户数据等):通过 API 调用获取,建议引入 **TanStack Query (React Query)** 进行封装,可自动处理缓存、去重、重试、乐观更新等复杂逻辑。 +- **客户端状态**(UI 展开/折叠、编辑器内容、筛选条件):以 `useState` / `useReducer` 管理,复杂度可控。 +- **全局共享状态**(用户认证信息、主题偏好、权限节点):当前可能通过 React Context 或 Props Drilling 传递,建议评估是否需要引入轻量级全局状态库(如 **Zustand**)以避免深层嵌套组件的 Props 传递开销。 + +### 1.3.4 性能优化措施 + +目前已实施的优化措施: + +| 优化手段 | 实施状态 | 效果评估 | +|----------|----------|----------| +| React.lazy 代码分割 | 已实施 | 降低首屏 JS 体积,提升 FCP/LCP | +| Vite 7 快速构建 | 已实施 | 开发阶段 HMR < 50ms,构建产出高效 | +| Tailwind CSS 原子样式 | 已实施 | 无运行时开销,产物体积小 | + +建议补充的优化方向: + +1. **虚拟列表**:工单列表与审计日志在数据量较大时可能出现渲染性能瓶颈,建议对长列表引入 `@tanstack/react-virtual` 或类似方案。 +2. **编辑器按需加载**:CodeMirror 6 及其语言包体积不可忽视,建议确保编辑器组件仅在 SQL 相关路由中被异步加载。 +3. **Tree Shaking 审查**:定期使用 `rollup-plugin-visualizer` 或类似工具分析产物体积,剔除未使用的依赖代码。 +4. **图片资源优化**:如有图表截图、操作指南配图等静态资源,建议采用 WebP/AVIF 格式并配置懒加载。 + +--- + +## 1.4 现有 UI 设计体系梳理 + +### 1.4.1 CSS 变量体系评估 + +项目已建立一套以 `--dg-*` 为前缀的 **CSS 自定义属性体系**,覆盖了 Dark / Light 两种主题模式以及共享的渐变色系统。这一设计决策体现了良好的工程化思维——通过将颜色值抽象为语义化变量,可实现全站一键换肤并降低维护成本。 + +**Dark 主题色板**: + +| 变量名 | 色值 | 语义角色 | 评估 | +|--------|------|----------|------| +| `--dg-bg-primary` | `#0d1117` | 页面主背景 | GitHub Dark 同款基底,视觉深邃,适合长时间操作 | +| `--dg-bg-secondary` | `#161b22` | 卡片/面板背景 | 与主背景形成 7% 亮度差,层级感清晰 | +| `--dg-bg-tertiary` | `#21262d` | 输入框/悬停态背景 | 足够的对比度确保交互反馈可感知 | + +**Light 主题色板**: + +| 变量名 | 色值 | 语义角色 | 评估 | +|--------|------|----------|------| +| `--dg-bg-primary` | `#ffffff` | 页面主背景 | 纯白基底,经典稳妥 | +| `--dg-bg-secondary` | `#f8f9fb` | 卡片/面板背景 | 微冷灰调,避免纯白页面的单调感 | + +**共享渐变系统**: + +| 变量名 | 色值 | 使用场景 | +|--------|------|----------| +| `--dg-gradient-start` | `#2563eb`(蓝色) | 品牌主色 → 用于 Logo、主按钮、活跃状态 | +| `--dg-gradient-end` | `#9333ea`(紫色) | 品牌辅色 → 用于渐变过渡、装饰性元素 | + +蓝紫渐变在视觉上传递了**科技感与专业性**,与数据库管理工具的定位高度契合。该渐变目前被封装为 `.dg-gradient-text` 与 `.dg-gradient-bg` 两个工具类,使用便捷。 + +**语义化工具类**: + +项目还定义了 `.dg-card`、`.dg-input` 等高级工具类,将颜色变量、圆角、阴影、边框等属性聚合为语义化的样式单元。这种"变量 + 工具类"的双层体系兼顾了灵活性与开发效率,是可维护性设计的体现。 + +### 1.4.2 shadcn/ui 组件库使用情况 + +项目使用了 **50+ shadcn/ui 基础组件**,覆盖了表单控件(Input、Select、Checkbox、Radio)、数据展示(Table、Card、Badge、Tooltip)、反馈(Dialog、Toast、Alert、Skeleton)、导航(Tabs、Breadcrumb、Sidebar)等完整类别。 + +shadcn/ui 的核心优势在于**源码级可定制性**——组件代码直接存在于项目的 `components/ui/` 目录中,团队可以: +- 自由修改组件的默认样式、动画参数、无障碍属性 +- 根据品牌规范调整颜色、圆角、间距等设计 Token +- 添加业务特有的 Props 扩展(如在 Button 上增加 `isLoading` 的统一处理) + +当前需要关注的点:50+ 组件的规模意味着维护成本不可忽视,建议在升级 shadcn/ui 版本时建立变更日志审查机制,确保上游的 Bug 修复与安全更新能够及时同步。 + +### 1.4.3 主题系统设计 + +平台当前的主题系统具备以下特征: + +1. **双主题覆盖**:Dark / Light 两种模式,通过 CSS 变量切换实现,切换成本极低(仅需切换顶层 class)。 +2. **渐变色作为品牌标识**:蓝紫渐变(`#2563eb` → `#9333ea`)贯穿两种主题,形成了强烈的品牌视觉记忆点。 +3. **CSS 变量驱动**:所有主题相关属性均通过 `--dg-*` 变量管理,无硬编码色值散落在组件代码中。 + +**建议完善的方面**: +- 当前主题切换可能依赖 CSS 的 `prefers-color-scheme` 媒体查询或手动切换按钮,建议增加**主题偏好持久化**(localStorage)与**系统主题自动跟随**的双重机制。 +- 建议补充 **High Contrast(高对比度)** 模式,满足无障碍合规要求(WCAG 2.1 AA 级)。 +- 考虑引入 **主题 Token 文档**,明确定义每种语义色值的使用场景(如 `--dg-bg-primary` 仅用于页面级背景,不可用于卡片),防止变量滥用导致视觉不一致。 + +### 1.4.4 当前设计体系的优势与不足 + +**优势**: + +| 维度 | 表现 | +|------|------| +| 工程化成熟度 | CSS 变量 + 工具类的双层体系,shadcn/ui 的源码级可控性 | +| 品牌一致性 | 蓝紫渐变标识贯穿全站,Dark/Light 双主题覆盖完整 | +| 开发效率 | Tailwind 原子类 + 语义化工具类,编写样式快速直观 | +| 扩展能力 | 新增主题仅需定义一组 CSS 变量,无需修改组件代码 | + +**不足**: + +| 维度 | 问题描述 | 改进优先级 | +|------|----------|-----------| +| 设计 Token 粒度 | 当前变量主要集中在颜色维度,缺少间距、字体、阴影、动效的 Token 化定义 | 高 | +| 动效体系缺失 | 页面转场、组件出现/消失、状态切换等交互缺乏统一的动效规范 | 高 | +| 无障碍支持 | 缺少 ARIA 属性系统化检查、键盘导航测试、色彩对比度合规验证 | 中 | +| 响应式设计 | 平台以桌面端操作为主,但缺少不同分辨率下的布局适配策略 | 中 | +| 图标体系 | 未明确图标库选型(如 Lucide、Radix Icons)与使用规范 | 低 | + +综上,SQL-Platform 的 UI 设计体系已具备良好的基础骨架,特别是在 CSS 变量体系与组件化封装方面展现了专业水准。后续优化的核心方向应聚焦于**设计 Token 的维度扩展**(补充间距、动效、阴影 Token)、**交互动效体系的建立**以及**无障碍合规性的系统性提升**,这些内容将在后续章节中展开详细方案。 +## 2. 现状问题诊断 + +经过对 SQL-Platform 前端代码库的全面审阅与走查,我们共识别出 5 大维度、23 项具体问题。这些问题贯穿登录认证、主题系统、核心功能页面、菜单导航以及整体设计体系,严重程度从"视觉瑕疵"到"架构性债务"不等。以下按模块逐项展开诊断。 + +--- + +### 2.1 登录页面五大问题分析 + +平台提供了 5 种登录页面布局(`SplitView`、`CenteredCard`、`SidePanel`、`FullImage`、`MinimalDark`),位于 `/frontend/src/components/login/` 目录下。尽管数量丰富,但 5 个组件共享大量共性问题,且各布局存在特有的设计缺陷。以下从视觉层次、交互体验、品牌感知、组件化程度和动效反馈五个维度进行诊断。 + +#### 2.1.1 视觉层次薄弱 + +**共性问题**:5 个登录页均缺乏清晰的视觉焦点层级,背景、装饰元素与核心表单区域之间的对比关系处理随意。 + +| 布局组件 | 具体视觉问题 | 严重程度 | +|---|---|---| +| `SplitView.tsx` | 左侧特性列表采用简单 icon+文字网格排列,无卡片包裹、无分割线,各 feature 项视觉权重完全一致,用户难以快速扫描核心卖点 | 中 | +| `CenteredCard.tsx` | 渐变背景仅为单色线性过渡,无纹理或光晕层次;卡片阴影硬编码为 `0 8px 32px rgba(0,0,0,0.3)`,缺乏环境光感,呈现"浮空贴图"效果 | 中 | +| `SidePanel.tsx` | 装饰性圆圈使用 `borderRadius: 50%` 的 div 硬编码,无渐变填充、无模糊处理,视觉上如同"开发占位符";品牌区域仅放置 `Database` 图标,无品牌图形标识 | 高 | +| `FullImage.tsx` | 电路板网格背景使用 CSS `repeating-linear-gradient` 实现,线条粗细一致、无辉光效果,整体呈现"半成品 sketch"观感;毛玻璃效果 `backdrop-filter: blur(16px)` 未配合饱和度降低(` saturate`)与边缘高光,通透感不足 | 高 | +| `MinimalDark.tsx` | 几乎无任何装饰性设计元素,纯黑背景+白字表单的极简走向极端,缺乏辅助视觉引导线或光晕点缀,整体显得空旷冷清 | 中 | + +**根因分析**:各登录页的开发重心放在"布局差异化"上,却忽视了"视觉深度营造"。装饰元素的实现手段停留在 CSS 基础属性层面,未利用渐变、噪点纹理、多层阴影、边缘发光等现代视觉技法来建立前景/中景/背景的三层空间关系。 + +#### 2.1.2 交互体验不足 + +登录作为用户进入平台的第一触点,其交互体验直接影响用户对平台专业度的初始判断。当前 5 个登录组件在表单交互方面存在系统性缺陷: + +1. **表单验证视觉反馈缺失**:全部使用原生 `` 元素,未采用 shadcn/ui 的 `` 组件。输入框在 focus、error、success 三种状态下均无边框颜色变化、无图标提示、无 shake 动画。用户提交错误表单后,仅能看到简单的红色文字提示,错误字段本身没有任何视觉变化。 + +2. **"记住我"功能缺位**:5 个登录页均未提供"记住账号/保持登录"选项。对于企业级工具而言,频繁的会话过期与重复登录是显著的效率损耗点。 + +3. **"忘记密码"入口缺失**:没有提供密码找回或重置的链接入口,用户一旦遗忘密码将无从操作。 + +4. **安全提示文字缺失**:未展示"建议使用强密码"、"登录即表示同意服务条款"等合规性文案,降低了平台的安全可信度。 + +5. **版本号显示缺失**:登录页未展示当前平台版本号(如 `v2.4.1`),不利于运维排查与用户反馈时的版本确认。 + +#### 2.1.3 品牌感缺失 + +品牌名在所有 5 个登录页中统一硬编码为"SQL审核平台",名称过于直白、缺乏品牌辨识度与情感连接。对比业界标杆产品(如 Bytebase 的科技感命名、Archery 的品牌化 Logo),当前的命名策略停留在"功能描述"层面,未形成品牌记忆点。 + +更关键的是,5 个登录页均**未展示品牌标识**(Logo、品牌图形、吉祥物或标志性配色)。`SidePanel` 仅用 `Database` 通用图标代替品牌图形,`CenteredCard` 完全没有任何品牌标识。登录页作为品牌视觉锤的核心触点,未能承担品牌认知建设的职责。 + +#### 2.1.4 组件化程度低 + +从代码实现层面审视,5 个登录组件存在显著的工程化债务: + +- **未使用 shadcn/ui `` 组件**:全部直接使用原生 ``,导致表单样式无法继承主题系统的 CSS 变量,切换主题时可能出现颜色断层。 +- **内联样式泛滥**:表单样式大量使用内联 `style` 属性(如 `style={{ padding: '24px', borderRadius: '8px' }}`),而非 Tailwind CSS 工具类。这破坏了项目的样式一致性,也增加了主题切换的维护成本。 +- **按钮样式不统一**:有的登录按钮使用渐变背景,有的使用纯色,有的使用 outline 样式,5 个组件之间没有共享按钮规范。 +- **登录按钮 loading 状态简陋**:loading 状态仅通过文字变化(如"登录中...")体现,无 spinner 图标、无按钮宽度保持、无禁用状态视觉变化,用户可能因按钮"变形"而产生疑惑。 + +**改进方向**:应将登录表单抽象为可复用的 `` 组件,统一使用 shadcn/ui 的 `Input`、`Button`、`Checkbox`、`Label` 等原子组件,并通过 Tailwind class 管理所有样式。 + +#### 2.1.5 动效与反馈匮乏 + +当前登录页的动效设计几乎处于空白状态: + +| 交互场景 | 当前表现 | 期望表现 | +|---|---|---| +| 登录成功 | 直接跳转,无过渡动画 | 显示成功 checkmark 动画,延迟 400ms 后优雅跳转 | +| 登录失败 | 简单红色文字提示 | 表单 shake 动画 + 错误字段高亮 + 带图标的错误消息 | +| 输入框 focus | 无特殊效果 | 边框颜色过渡 + 柔和外发光(`ring`) | +| 按钮 hover/click | 无反馈或仅有透明度变化 | 微缩放 + 阴影加深 + 涟漪效果 | +| 页面加载 | 静态呈现 | 表单区域的 fade-in + translateY 入场动画 | + +**根因分析**:开发过程中未引入动画库(如 `framer-motion`),所有交互反馈停留在浏览器默认行为层面。登录页作为情感化设计的最佳载体,动效的缺失使得整体体验显得"机械"与"冰冷"。 + +--- + +### 2.2 主题系统局限性 + +当前主题系统仅支持 `dark` 与 `light` 两种模式,通过 `data-theme` HTML 属性进行切换,主题选择入口位于 `AppearanceSettings` 页面,以简单的按钮组形式呈现。 + +**核心局限点**: + +1. **色彩方案单一**:缺乏紫色系、绿色系、暖色系、高对比度等多元色彩方案。现代 SaaS 平台(如 Vercel、Notion、Linear)通常提供 4-8 种预设主题,以满足不同用户的审美偏好与无障碍需求。 + +2. **主题预览简陋**:预览区域仅以 4:3 比例的缩略图展示,用户无法直观感受主题在真实数据密度下的表现。建议提供可交互的实时预览(如展示表格、按钮、标签等组件的组合效果)。 + +3. **主题切换过渡生硬**:切换主题时无过渡动画,页面瞬间"闪切",视觉体验断裂。应加入 200-300ms 的颜色过渡动画(`transition: color, background-color`)。 + +4. **自定义能力缺失**:高级用户无法调整主色调、圆角大小、字体密度等参数。建议提供"自定义主题"模式,允许用户通过色盘选择器定义个性化的品牌色。 + +5. **CSS 变量覆盖范围不足**:部分组件仍使用硬编码颜色值,未完全纳入 CSS 变量体系,导致主题切换时存在"漏色"现象。 + +--- + +### 2.3 核心功能页面问题 + +#### 2.3.1 审批变更工单系统 + +工单系统包含 3 个核心页面,总计 2742 行代码,存在显著的 UX 债务: + +**审批变更页(`TicketsPage.tsx`,742 行)**: +- 表格使用原生 `` 元素,未使用 shadcn/ui 的 `Table` 组件,导致列头排序、列宽调整、行悬停效果等功能全部缺失。 +- 状态标签样式极其简单(如 `bg-blue-500/15 text-blue-400`),仅为色块+文字,无圆角规范、无图标辅助、无二态(solid/soft)区分。 +- 操作按钮采用简单文字链接形式("查看""编辑""删除"),无图标按钮、无操作菜单(dropdown menu),在窄屏下易折行。 +- **缺少批量操作功能**:用户无法对多条工单进行批量审批或批量关闭,效率低下。 +- 搜索框为原生 ``,无搜索图标、无清除按钮、无搜索建议。 +- 分页组件为手写实现,未使用 shadcn/ui `Pagination`,样式与平台其他分页区域不统一。 + +**工单创建页(`TicketCreatePage.tsx`,1192 行)**: +- 布局采用上下堆叠的线性结构,左侧 SQL 编辑器与右侧库表浏览面板的空间配比固定,未利用响应式网格最大化编辑区域。 +- SQL 编辑器下方的信息条(行数、字符数、语法状态)样式过于简单,无图标、无色彩状态区分。 +- 审核结果展示为扁平列表,缺乏视觉层次:通过/失败的规则未使用不同颜色或图标区分,高亮行与错误行的视觉权重相近。 +- 库表浏览面板的 tab 切换样式为基础样式,无活跃 tab 的指示器动画。 +- **无自动保存草稿功能**:用户误刷新页面后,已编写的 SQL 将全部丢失,这是企业级工具的高风险体验缺口。 + +**工单详情页(`TicketDetailPage.tsx`,808 行)**: +- 审批流程可视化使用简单圆形+直线实现,无节点状态图标(如 `Check`、`Clock`、`X`)、无连线动画、无进度百分比指示。 +- 信息网格采用 2 列 flex 布局直接裸露呈现,无卡片包裹、无分割线、无标签-值的对齐规范。 +- 执行结果直接展示原始 JSON 字符串,无格式化、无语法高亮、无可折叠区域,运维人员阅读极为困难。 +- 关联工单区域仅为简单的工单编号链接列表,无状态徽章、无优先级标识。 + +#### 2.3.2 查询数据页面 + +`QueriesPage.tsx`(896 行)作为数据查询的核心工作区,存在以下 UX 问题: + +- 查询结果表格同样使用原生 `
`,列宽不可调整(无拖拽调整功能),对于宽表(20+ 列)的浏览体验极差。 +- **缺少查询收藏夹功能**:用户无法保存常用的查询语句,每次需重新输入或从历史中翻找。 +- 历史记录面板为简单的文字列表,无查询耗时显示、无行数结果、无收藏/删除操作。 +- SQL 编辑器与结果表格之间的区域无明确的分割线或可调整拖拽条(resizer),用户无法按需求分配编辑区与结果区的屏幕空间。 + +#### 2.3.3 系统设置页面 + +`SettingsPage.tsx`(56 行)作为设置入口,问题尤为突出: + +- **Tab 图标使用 Emoji**(`🎨` 外观、`⚙️` 平台、`🛡️` 安全、`🔔` 通知、`🔐` 密码),与平台其他页面统一使用的 `lucide-react` 图标体系严重冲突,视觉风格割裂。Emoji 在不同操作系统下的渲染差异也会导致界面不统一。 +- Tab 切换无动画过渡,内容区域的切换为瞬间跳转,体验生硬。 +- 各设置子页面的表单设计不一致:有的使用 shadcn/ui 组件,有的(如 `PlatformConfigPage`)直接使用原生 ``,标签对齐方式、间距、按钮位置均不统一。 +- **缺少设置变更确认/撤销机制**:用户在修改敏感配置(如数据库连接参数)后,没有二次确认对话框;也没有"重置为默认值"或"撤销本次更改"的功能,误操作风险高。 + +--- + +### 2.4 菜单体系问题 + +平台的侧边栏导航菜单存在以下结构性问题: + +1. **图标体系不统一**:`Settings` 页面使用 Emoji 图标,而其他所有页面使用 `lucide-react` 图标库。这种混用破坏了导航的视觉一致性,也降低了专业感。 + +2. **菜单分组合理性不足**:当前菜单分为 6 个 section,但部分分类逻辑存在问题。例如"自动任务"被归类在"系统配置"分组下,而从用户心智模型来看,自动任务属于"运维操作"范畴,与"系统配置"(偏静态参数)的认知类别不同。建议重新审视信息架构,采用"按用户角色分组"或"按操作频率分组"的策略。 + +3. **面包屑导航缺失**:页面层级超过 2 层后(如 设置 > 平台配置 > 数据库参数),用户无法通过面包屑快速定位当前位置或返回上级,只能依赖浏览器后退按钮。 + +4. **Hover/Active 状态过渡动画缺失**:菜单项的悬停和激活状态切换为瞬间变化,无 150-200ms 的颜色/背景过渡动画,整体感觉"卡顿"而非"响应"。 + +5. **当前页面指示不够醒目**:激活菜单项仅通过轻微的颜色变化区分,缺乏左侧边框高亮(`border-left` accent)或背景色块等强指示手段。 + +--- + +### 2.5 设计体系不一致性 + +从代码层面审视,平台在整体 design system 的贯彻执行上存在严重的碎片化现象: + +**卡片组件混用**:部分页面使用 shadcn/ui 的 `` 组件(如 Dashboard),部分页面使用 `
` 手写卡片样式(如工单详情页的信息网格)。手写卡片的圆角、阴影、边框、背景色与 shadcn/ui Card 的默认参数存在细微差异,积累后形成显著的视觉噪音。 + +**按钮样式分裂**:平台内同时存在 3 种按钮风格——渐变按钮(部分登录页)、纯色填充按钮(shadcn/ui 默认)、outline 描边按钮(部分操作栏)。三种风格的使用没有明确的场景规范,同一页面内也可能混用,破坏了操作隐喻的一致性。 + +**表单输入框样式差异**:有的页面使用 shadcn/ui ``(带统一的 focus ring、圆角、高度),有的页面使用原生 ``(样式依赖浏览器默认),有的页面使用内联样式自定义的输入框。三种实现的视觉高度、边框粗细、焦点反馈均不相同。 + +**颜色管理混乱**:部分组件使用硬编码颜色值(如 `rgba(0,0,0,0.3)`、`#3b82f6`),部分组件使用 CSS 变量(如 `hsl(var(--primary))`),部分组件使用 Tailwind 的语义化 class(如 `bg-primary`)。当主题切换或品牌色调整时,硬编码的颜色值不会跟随变化,导致"漏色"与视觉断层。 + +**间距系统缺失**:各页面的 `padding` 和 `margin` 取值随意,无统一的 spacing scale。例如有的卡片内边距为 `16px`,有的为 `20px`,有的为 `24px`;页面级的外边距也无统一规范(`pagePadding` token 缺失)。这种不一致使得页面之间的"呼吸感"差异明显,整体缺乏精致感。 + +**根因总结**:以上不一致性的根本原因在于缺乏一个被严格执行的 Design Token 体系与组件使用规范。开发人员在实现新页面时,没有明确的"应该使用哪个组件、哪个 token"的指引,导致各页面"各自为政"。建议引入一套完整的 Design Token(颜色、间距、字体、阴影、圆角)并配合 ESLint 规则强制在组件层面统一规范。 + +--- + +> **本章小结**:SQL-Platform 的现状问题可归纳为"功能可用但体验粗糙"。登录页面作为品牌门面,在视觉层次、交互反馈、品牌感知上均有显著短板;核心功能页面(工单系统、查询页面、设置页面)在组件选型、布局效率、信息架构上存在系统性债务;主题系统与菜单体系的局限性则反映了设计体系在规划层面的不足。这些问题并非孤立存在,而是相互交织:设计体系的碎片化导致了各页面实现的不一致,组件化程度低导致了交互体验的简陋,主题系统的局限又加剧了视觉风格的单一。后续章节将针对这些问题提出具体的优化方案。 +## 3. 五套专业登录页设计方案 + +针对现有五个登录页组件(`SplitView.tsx`、`CenteredCard.tsx`、`SidePanel.tsx`、`FullImage.tsx`、`MinimalDark.tsx`)"不专业、太 low"的用户反馈,本章提供五套完整的专业级登录页重设计方案。每套方案均基于 React 19 + TypeScript + Tailwind CSS 4 + shadcn/ui + Lucide Icons 技术栈,保留现有的 `useLogin` 与 `useTheme` hook 架构,在视觉表现、交互体验与动效层次上实现全面升级。 + +五套方案分别对应五种截然不同的企业气质:科技互联、金融安全、云端 SaaS、极客代码、创意自然。设计方案遵循"一次一屏"(Single Screen)原则,确保登录流程简洁高效,同时在第一眼传递出强烈的品牌专业感。 + +--- + +### 3.1 方案一「极光科技」— 动态粒子科技风 + +#### 设计概念与灵感来源 + +「极光科技」方案的灵感源自现代科技公司的数据可视化美学——深空般的背景中,粒子如数据节点般流动、连接,暗示着数据库节点之间的网络拓扑关系。设计参考了 Vercel、PlanetScale 等现代 DevTools 产品的暗黑登录页风格,将"数据流动"这一抽象概念转化为可感知的视觉语言。深色背景配合冷色调粒子动画,营造出深邃、专注、充满科技张力的第一印象。 + +#### 适用场景 + +适合科技互联网公司、数据库工具产品、DevOps 平台、技术驱动型 SaaS 企业。这类企业的用户群体(开发者、DBA、技术人员)对科技感视觉有天然的好感度与信任预期。 + +#### 视觉规范 + +| 元素 | 规范值 | 说明 | +|------|--------|------| +| 背景渐变 | `#0a0e27` → `#1a1f4b` | 深邃的深蓝到暗蓝,比纯黑更有空间感 | +| 粒子数量 | 80 个 | 足够形成视觉密度,不过度抢占注意力 | +| 粒子颜色 | `#3b82f680`(半透蓝) | 与品牌蓝色系一致,带透明度避免喧宾夺主 | +| 连线距离 | 120px | 控制连线密度,确保画面不过于繁杂 | +| 卡片背景 | `rgba(255,255,255,0.03)` | 极微弱的白色,配合毛玻璃效果 | +| 卡片毛玻璃 | `backdrop-blur: 20px` | iOS 风格毛玻璃,现代感强烈 | +| 卡片边框 | `1px solid rgba(255,255,255,0.08)` | 微妙的发光边框勾勒卡片轮廓 | +| 卡片圆角 | `16px` | 现代感的较大圆角 | +| 卡片内边距 | `40px 32px` | 宽裕的内部空间 | +| Logo 底圆 | `56px`,渐变 `from #2563eb to #9333ea` | 渐变圆形底托提升品牌质感 | +| Logo 图标 | `Shield`(Lucide),白色,`24px` | 安全感的盾形图标 | +| 品牌名 | "DataGuard",`20px`,白色,字重 600 | 清晰的品牌露出 | +| 输入框高度 | `44px` | 符合现代表单的最佳点击高度 | +| 输入框圆角 | `10px` | 与卡片圆角协调 | +| 输入框聚焦 | 边框 `#3b82f6`,外发光 `0 0 0 3px rgba(59,130,246,0.15)` | 蓝色光晕聚焦指示 | +| 按钮渐变 | `from #2563eb to #7c3aed` | 蓝紫渐变,与现有品牌渐变一致 | +| 按钮高度 | `44px` | 与输入框等高,视觉对齐 | +| 按钮圆角 | `10px` | 与输入框统一 | +| 辅助链接色 | `#8b949e`,hover `#58a6ff` | GitHub 风格的灰色链接 | + +#### 动效规范 + +**粒子系统动画**:使用 Canvas 2D 实现 60fps 粒子系统。每个粒子以随机速度在画布内移动(速度范围 0.3~0.8px/frame),碰到边界反弹。当两个粒子距离小于 120px 时,绘制连线(线条透明度随距离衰减:`opacity = 1 - distance/120 * 0.7`)。鼠标位置额外产生一个"引力点",靠近鼠标的粒子连线距离阈值提升至 180px,形成交互反馈。 + +**卡片入场动画**: +```css +@keyframes cardEnter { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} +/* duration: 600ms, easing: cubic-bezier(0.16, 1, 0.3, 1) */ +``` +使用 `cubic-bezier(0.16, 1, 0.3, 1)` 缓动函数——初始阶段快速响应,结尾柔和减速,营造"丝滑吸附"的质感。 + +**输入框聚焦**:边框颜色过渡 `200ms ease`,外发光同步渐显,给用户明确的焦点反馈。 + +**按钮 Hover**:`transform: translateY(-1px)` 微上移,`box-shadow` 从 `0 4px 12px rgba(37,99,235,0.25)` 增强为 `0 8px 24px rgba(37,99,235,0.35)`,过渡 `200ms ease`。 + +**错误状态 Shake 动画**: +```css +@keyframes shake { + 0%, 100% { transform: translateX(0); } + 25% { transform: translateX(-5px); } + 50% { transform: translateX(5px); } + 75% { transform: translateX(-5px); } +} +/* duration: 300ms, 执行 1 次,同时边框变为 #ef4444 */ +``` + +#### 代码实现要点 + +1. **粒子系统**:使用 `useRef` 获取 Canvas 上下文,在 `useEffect` 中初始化粒子数组并启动 `requestAnimationFrame` 动画循环。粒子系统封装为独立的 `ParticleBackground.tsx` 组件,通过 props 接收 `particleCount`、`connectionDistance`、`color` 等参数。 + +2. **卡片结构**:使用 `Card`(shadcn/ui)作为容器,外层包裹 `div` 设置 `backdrop-blur-xl bg-white/[0.03] border border-white/[0.08]` 实现毛玻璃效果。 + +3. **表单组件**:`Input` 和 `Button` 直接使用 shadcn/ui 组件,通过 Tailwind 的 `className` 覆盖默认样式。输入框聚焦外发光使用 `focus:ring-[3px] focus:ring-blue-500/15 focus:border-blue-500`。 + +4. **状态管理**:继续使用现有的 `useLogin` hook(`username` / `password` / `loading` / `error`),错误触发时通过条件类名绑定 shake 动画。 + +--- + +### 3.2 方案二「企业金融」— 银行级安全可信风 + +#### 设计概念与灵感来源 + +金融类产品的登录页第一要务是传递"安全感"。「企业金融」方案借鉴了招商银行企业网银、Stripe Dashboard 以及 Bloomberg Terminal 的视觉语言——通过深沉的蓝色调、严谨的版式分割、明确的信任标识,在瞬间建立起用户对系统的信任。左右分屏的布局本身就是一种力量感的表达:左侧沉稳的品牌展示,右侧聚焦的表单操作,信息层级清晰,符合金融用户"高效、安全、专业"的心理预期。 + +#### 适用场景 + +金融、银行、保险、证券、支付等强监管行业企业。用户群体包括金融从业者、企业财务人员、风控人员,他们对安全标识(SSL、加密、审计)高度敏感。 + +#### 视觉规范 + +| 元素 | 规范值 | 说明 | +|------|--------|------| +| 左侧背景 | `#0c1a3c` → `#1a365d` | 深蓝渐变,传递权威与稳重 | +| 左侧宽度 | 60% | 大面积品牌展示区 | +| 右侧背景 | `#f8fafc` | 极浅灰白,与左侧形成清晰分割 | +| 右侧宽度 | 40% | 聚焦的表单操作区 | +| 品牌 Logo | 白色 Shield 图标 + "DataGuard" | 居中偏上布局 | +| Slogan | "安全的数据库变更管理",`18px`,`#94a3b8` | 简洁定位标语 | +| 信任指标 | 3 个:SSL 加密、权限隔离、审计追踪 | 带 CheckCircle 图标的列表 | +| 信任指标图标 | `CheckCircle2`(Lucide),`#22c55e` | 绿色对勾传递"已验证" | +| 信任指标文字 | `#cbd5e1`,`14px` | 柔和的说明文字 | +| 右侧卡片 | 白色背景,圆角 `16px` | 干净的表单容器 | +| 卡片阴影 | `0 4px 24px rgba(0,0,0,0.08)` | 微妙的浮起感 | +| 卡片内边距 | `48px 40px` | 金融级宽裕间距 | +| 登录标题 | "欢迎回来",`24px`,`#0f172a`,字重 700 | 亲切的问候 | +| 输入框样式 | 底部边框(Underline Input)| 类似 Material Design 的底线输入 | +| 输入框高度 | `48px` | 稍大以凸显重要感 | +| 输入框边框 | 默认 `border-b-2 border-slate-200`,聚焦 `border-[#1a365d]` | 底线聚焦变深蓝 | +| 按钮背景 | `#1a365d` | 沉稳深蓝,呼应左侧 | +| 按钮高度 | `48px` | 与输入框等高 | +| 按钮圆角 | `8px` | 相对克制的圆角,体现严谨 | +| 安全提示 | "🔒 您的连接已加密保护",`12px`,`#64748b` | 明确的安全信号 | + +#### 动效规范 + +**左右面板载入**:页面加载时,左侧面板从左侧滑入(`translateX(-40px) → 0`,`400ms ease-out`),右侧面板从右侧同步滑入(`translateX(40px) → 0`,`400ms ease-out`,延迟 `50ms`)。两侧同时汇聚中间,隐喻"安全通道的建立"。 + +**信任指标依次淡入**:3 个信任指标在左侧面板就位后依次显示,每个间隔 `150ms`: +```css +.trust-item:nth-child(1) { animation-delay: 200ms; } +.trust-item:nth-child(2) { animation-delay: 350ms; } +.trust-item:nth-child(3) { animation-delay: 500ms; } +/* 统一动画: opacity 0→1, translateX(-10px)→0, 300ms ease-out */ +``` + +**按钮 Hover**:背景色从 `#1a365d` 平滑过渡为 `#122a4a`(加深 10%),同时增加 `box-shadow: 0 4px 16px rgba(12,26,60,0.2)`,过渡 `200ms ease`。 + +**输入框聚焦**:底部边框从 `#e2e8f0` 变为 `#1a365d`,宽度有微妙的"延展"效果(使用 `scaleX` 从 0→1 配合 `transform-origin: left`),`200ms ease`。 + +#### 代码实现要点 + +1. **分屏布局**:使用 CSS Grid `grid-cols-[60%_40%]` 或 Flex `flex-[60]` / `flex-[40]` 实现左右分割。移动端(`< 1024px`)切换为上下布局,左侧折叠为顶部横幅。 + +2. **底线输入框**:不使用 shadcn/ui 默认的边框输入框,而是自定义 `div` 包裹 ``,通过 `border-b-2` + `bg-transparent` 实现底线样式,聚焦时切换 `border-color`。 + +3. **信任指标列表**:封装为 `TrustIndicators` 子组件,接收指标数组渲染,配合 `setTimeout` 或 CSS `animation-delay` 实现依次淡入。 + +4. **安全提示**:底部固定位置,使用 `flex items-center gap-2` 布局,锁图标使用 Lucide `Lock` 组件。 + +--- + +### 3.3 方案三「云端数据」— 云计算 SaaS 风 + +#### 设计概念与灵感来源 + +云计算和 SaaS 产品的登录页追求的是"轻盈、开放、无门槛"。「云端数据」方案汲取了 Snowflake、Figma、Notion 等现代 SaaS 产品的登录体验——明亮的浅色调、友好的圆角语言、丰富的 SSO 集成选项,向用户传递"即开即用"的产品气质。右上角的装饰性云朵图案是对"云端"概念的直接呼应,但处理为低对比度的纹理,避免过度具象化。 + +#### 适用场景 + +云服务商、SaaS 产品、互联网协作工具、中台系统、B2B 软件公司。用户群体包括产品经理、技术团队、普通企业用户,他们期望登录流程简单快捷,SSO 支持是加分项。 + +#### 视觉规范 + +| 元素 | 规范值 | 说明 | +|------|--------|------| +| 背景渐变 | `#f0f4f8` → `#e2e8f0` | 柔和的天空感浅灰蓝渐变 | +| 装饰云朵 | SVG 路径,右上角,`opacity: 0.3` | 微妙的云端意象,不干扰主体 | +| 卡片背景 | `#ffffff` 纯白 | 干净、明亮的中心焦点 | +| 卡片圆角 | `20px` | SaaS 产品偏爱的友好大圆角 | +| 卡片阴影 | `0 8px 32px rgba(148,163,184,0.15)` | 柔和的悬浮阴影 | +| 卡片宽度 | `420px` | 适中宽度,聚焦表单 | +| 卡片内边距 | `48px 40px` | 宽裕的内部空间 | +| 顶部品牌区 | `40px` 圆角矩形图标 + "SQL-Platform" | 清晰的身份标识 | +| 品牌图标背景 | `from #0ea5e9 to #2563eb` | 天蓝到蓝的渐变,呼应云端主题 | +| 副标题 | "数据库变更管理平台",`14px`,`#64748b` | 产品定位说明 | +| 输入框背景 | `#f8fafc` | 极浅灰底,区别于卡片白 | +| 输入框圆角 | `12px` | 圆角输入,友好感 | +| 输入框边框 | 默认无边框,聚焦 `1px solid #3b82f6` | 最小化视觉噪音 | +| 输入框高度 | `46px` | 略大于标准,易于点击 | +| 按钮渐变 | `from #0ea5e9 to #2563eb` | 天空蓝到标准蓝 | +| 按钮圆角 | `12px` | 与输入框统一 | +| 按钮高度 | `46px` | 与输入框等高对齐 | +| 分隔线 | "或使用以下方式登录",`13px`,`#94a3b8` | 经典的 SSO 分隔 | +| SSO 图标 | 企业微信/钉钉/飞书,`40px` 圆形按钮 | 图标化登录选项 | +| SSO 按钮背景 | `#f1f5f9`,hover `#e2e8f0` | 灰色底,不与主按钮竞争 | + +#### 动效规范 + +**卡片入场**:从上方轻柔落下,同时伴随微妙的缩放——`opacity 0→1`、`translateY(-16px)→0`、`scale(0.98)→1`,`500ms cubic-bezier(0.34, 1.56, 0.64, 1)`。使用弹性缓动函数(overshoot easing),营造 SaaS 产品特有的"活泼弹动感"。 + +**输入框聚焦**:无边框输入框在聚焦时,背景色从 `#f8fafc` 微妙提亮至 `#ffffff`,同时蓝色边框从 `opacity 0` 渐显至 `opacity 1`,过渡 `150ms ease`。 + +**按钮 Hover**:`translateY(-2px)` 上浮,`box-shadow` 增强,同时渐变产生微妙的位置偏移(使用 `background-position` 动画),`200ms ease`。 + +**SSO 图标 Hover**:圆形背景从 `#f1f5f9` 变为 `#e2e8f0`,图标 `scale(1.1)`,`150ms ease`。 + +**装饰云朵**:缓慢的水平飘移动画(`translateX(0) → translateX(20px) → translateX(0)`,`20s ease-in-out infinite`),赋予页面呼吸感。 + +#### 代码实现要点 + +1. **卡片弹性动画**:使用 Tailwind 的 `animate-in` 配合自定义 CSS keyframe 实现弹性入场。或使用 Framer Motion(如项目已引入)的 `initial/animate` props 配合 `type: "spring", stiffness: 200, damping: 15` 实现物理弹性效果。 + +2. **无边框输入框**:shadcn/ui 的 `Input` 组件默认有边框,需通过 `border-0 bg-slate-50 focus:bg-white focus:ring-1 focus:ring-blue-500` 覆盖样式。 + +3. **SSO 按钮组**:使用 Flex 布局 `flex gap-3 justify-center`,每个 SSO 按钮为 `button` 元素包裹品牌 SVG 图标。考虑到不同企业的 SSO 需求,SSO 区域应封装为 `SSOProviders` 组件,通过配置数组动态渲染。 + +4. **云朵装饰**:将云朵 SVG 设为 `position: absolute; top: -50px; right: -30px; pointer-events: none;`,确保不影响交互。 + +--- + +### 3.4 方案四「极简矩阵」— 开发者极客风 + +#### 设计概念与灵感来源 + +对于面向开发者的工具平台,过于" polished "的设计反而可能显得不够硬核。「极简矩阵」方案致敬了《黑客帝国》的数字雨(Matrix Rain)以及终端命令行的纯粹美学,将登录页转化为一个"进入系统"的仪式。纯黑背景上绿色字符如雨般落下,输入框如同终端命令行,每一个交互细节都在告诉用户:"这是一个为技术人员打造的严肃工具。" + +#### 适用场景 + +技术团队、开发者工具、DevOps 平台、开源项目、CLI/GUI 混合产品。用户群体是开发者、SRE、运维工程师,他们对终端界面有亲切感,极客风格的 UI 反而能唤起"同道中人"的认同感。 + +#### 视觉规范 + +| 元素 | 规范值 | 说明 | +|------|--------|------| +| 背景色 | `#000000` 纯黑 | 终端/命令行的经典底色 | +| 字符雨颜色 | `#22c55e`(绿色),`#16a34a`(深绿) | 双色调绿色增加层次 | +| 字符集 | 大小写字母 + 数字 + 日文片假名 | Matrix 经典字符集 | +| 字符密度 | 比原版 Matrix 减少 40% | 不过度干扰登录表单的可读性 | +| 字符下落速度 | 2~6 px/frame 随机 | 自然的不规则雨效 | +| 卡片背景 | `rgba(0,0,0,0.85)` | 高透明度黑底,字符隐约可见 | +| 卡片边框 | `1px solid rgba(34,197,94,0.3)` | 绿色发光边框,终端窗口感 | +| 卡片圆角 | `4px` | 极小圆角,锐利的技术感 | +| 标题字体 | `JetBrains Mono`,`22px`,`#22c55e` | 等宽字体是终端的灵魂 | +| 标题文字 | `> sql-platform login` | 命令行风格的标题 | +| 副标题 | "请输入您的凭据以继续",`13px`,`#4ade80` | 浅绿说明文字 | +| 输入框背景 | `#0a0a0a` | 深黑,区别于卡片 | +| 输入框边框 | `1px solid rgba(34,197,94,0.25)` | 微弱绿边 | +| 输入框圆角 | `4px` | 锐利 | +| 输入框字体 | `JetBrains Mono`,`14px` | 打字机般的输入体验 | +| 输入框文字色 | `#22c55e` | 绿色输入文字 | +| Placeholder | `#374151`(深灰)| 低调提示 | +| 输入框聚焦 | 边框变为 `rgba(34,197,94,0.6)` | 明亮的绿色边框 | +| 按钮背景 | `#22c55e` | 醒目绿色 | +| 按钮文字 | `#000000`,`JetBrains Mono`,字重 600 | 黑底绿字,高对比 | +| 按钮圆角 | `4px` | 锐利风格统一 | +| 光标 | 自定义绿色闪烁光标 | `2px` 宽竖线,每 `530ms` 闪烁 | +| 底部版本号 | "v2.4.1 — build 20240815",`11px`,`#374151` | 开发者熟悉的版本信息 | + +#### 动效规范 + +**字符雨动画**:使用 Canvas 2D 实现。初始化多列字符,每列以随机速度向下滚动。每个字符有随机的生命周期——新字符高亮(`#4ade80`),旧字符渐暗(`#15803d` → `#166534`),超出画布底部后重置到顶部。字符雨在登录卡片后方运行,使用 `z-index` 分层。 + +**卡片入场**:模拟终端启动——先显示 `> sql-platform login_`(带闪烁光标),停顿 `300ms` 后表单元素逐行"打印"出现。每个元素使用 `opacity 0→1`,间隔 `80ms`,模拟打字机效果。 + +**输入框聚焦**:边框绿色亮度提升(`opacity 0.25 → 0.6`),同时产生微弱的绿色外发光 `0 0 8px rgba(34,197,94,0.15)`,`150ms ease`。 + +**按钮 Hover**:背景色从 `#22c55e` 变为 `#4ade80`(更亮),同时按钮产生 `box-shadow: 0 0 16px rgba(34,197,94,0.3)` 绿光晕染,`150ms ease`。 + +**光标闪烁**: +```css +@keyframes blink { + 0%, 49% { opacity: 1; } + 50%, 100% { opacity: 0; } +} +/* animation: blink 1.06s step-end infinite */ +``` +使用 `step-end` 时序函数实现硬切闪烁,更接近真实终端光标。 + +**错误状态**:终端风格的错误提示——输入框边框变为 `#ef4444`,下方显示红色文字 `[ERROR] 用户名或密码不正确`,字体 `JetBrains Mono`,`12px`。无 shake 动画,用冷静的错误信息替代。 + +#### 代码实现要点 + +1. **字符雨 Canvas**:独立的 `MatrixRain.tsx` 组件。核心逻辑:创建 `columns` 数组,每列跟踪当前字符和 y 坐标。在 `requestAnimationFrame` 循环中,以半透明黑色 (`rgba(0,0,0,0.05)`) 覆盖画布而非完全清除,形成字符拖尾效果。字符从预定义字符集中随机选取。 + +2. **等宽字体**:通过 Google Fonts 或本地引入 JetBrains Mono。Tailwind 配置中添加 `fontFamily: { mono: ['JetBrains Mono', 'monospace'] }`。 + +3. **打字机入场**:使用自定义 hook `useTypewriterEffect`,控制子元素依次显示。或直接使用 `setTimeout` 链实现简单的延迟序列。 + +4. **终端光标**:使用一个 `span` 元素(`w-[2px] h-[1.2em] bg-green-500 inline-block`)配合 CSS 动画实现闪烁。可封装为 `TerminalCursor` 小组件。 + +5. **密码输入**:密码框仍使用 `type="password"`,但自定义样式使圆点/星号也呈现绿色(通过 `color: #22c55e` 和 `caret-color: #22c55e`)。 + +--- + +### 3.5 方案五「自然流动」— 有机渐变自然风 + +#### 设计概念与灵感来源 + +并非所有企业都喜欢冷峻的科技风。「自然流动」方案面向创意公司、设计团队和文化企业,从自然界的极光、晨曦、水波中汲取配色灵感。三个巨大的模糊色块在背景中缓慢漂移、交叠,产生不断变化的有机渐变——这种"活着的"背景打破了登录页的单调,将等待时间转化为一种视觉享受。设计参考了 Linear、Arc Browser 等产品的有机渐变美学,以及 Blobs 设计趋势。 + +#### 适用场景 + +创意设计公司、数字营销机构、文化传媒企业、生活方式品牌、内部创意工具。用户群体包括设计师、创意总监、市场人员,他们对视觉美感有较高要求,偏好温暖、有情感的界面。 + +#### 视觉规范 + +| 元素 | 规范值 | 说明 | +|------|--------|------| +| 背景底色 | `#0f0e1a` | 深紫黑,衬托前景彩色光晕 | +| 渐变圆 1 | `#f472b6`(粉色),直径 `600px`,blur `120px` | 左上区域 | +| 渐变圆 2 | `#a78bfa`(紫色),直径 `500px`,blur `120px` | 右侧中部 | +| 渐变圆 3 | `#60a5fa`(蓝色),直径 `550px`,blur `120px` | 底部中央 | +| 模糊方式 | CSS `filter: blur(120px)` 或 SVG `feGaussianBlur` | 产生柔和的色块融合 | +| 卡片背景 | `rgba(255,255,255,0.1)` | 半透明白 | +| 卡片毛玻璃 | `backdrop-blur: 24px` | 更强的模糊,突出背后的色彩流动 | +| 卡片圆角 | `24px` | 有机的大圆角 | +| 卡片边框 | `1px solid rgba(255,255,255,0.15)` | 半透明白色边框 | +| 卡片内边距 | `48px 40px` | 宽裕的空间 | +| 品牌图标 | `64px` 大圆角矩形,`border-radius: 20px` | 渐变背景 `from #f472b6 to #a78bfa` | +| 品牌名 | "DataGuard",`22px`,白色,字重 600 | 居中展示 | +| 品牌标语 | "数据之美,流动不息",`14px`,`rgba(255,255,255,0.6)` | 诗意化标语 | +| 输入框背景 | `rgba(255,255,255,0.08)` | 毛玻璃输入 | +| 输入框边框 | `1px solid rgba(255,255,255,0.12)` | 微妙的边框 | +| 输入框圆角 | `14px` | 圆润 | +| 输入框高度 | `46px` | 舒适点击高度 | +| 输入框文字 | 白色,`rgba(255,255,255,0.9)` | 高对比度 | +| 输入框聚焦 | 边框变为 `rgba(255,255,255,0.4)` | 白色高亮 | +| 按钮背景 | `#ffffff` | 白色主按钮 | +| 按钮文字 | `#0f0e1a`,字重 600 | 深色文字 | +| 按钮圆角 | `12px` | 现代圆角 | +| 按钮高度 | `46px` | 与输入框等高 | +| 卡片外光晕 | `box-shadow: 0 0 80px rgba(167,139,250,0.15)` | 微妙的紫色光晕包裹卡片 | + +#### 动效规范 + +**渐变圆漂移**:三个彩色模糊圆以不同的速度和轨迹缓慢移动,形成不断变化的背景: +- 粉圆:`translate` 在 `(0,0) → (30px,-20px) → (-20px,30px) → (0,0)` 之间循环,`15s ease-in-out infinite` +- 紫圆:`translate` 在 `(0,0) → (-25px,25px) → (20px,-15px) → (0,0)`,`18s ease-in-out infinite` +- 蓝圆:`translate` 在 `(0,0) → (20px,20px) → (-30px,-10px) → (0,0)`,`12s ease-in-out infinite` + +三个圆的运动周期互质(15s/18s/12s),确保组合图案永不重复。 + +**卡片入场**:`opacity 0→1`、`translateY(24px)→0`、`scale(0.96)→1`,`700ms cubic-bezier(0.22, 1, 0.36, 1)`。较长的时间和柔和的缓动,配合背景的流动感,营造"浮出水面"的诗意体验。 + +**输入框聚焦**:边框透明度提升,同时产生微弱的白色外发光 `0 0 0 3px rgba(255,255,255,0.08)`,`200ms ease`。 + +**按钮 Hover**:`scale(1.02)` 微放大(而非上移,更柔和),`box-shadow` 增强为 `0 8px 24px rgba(255,255,255,0.2)`,过渡 `200ms ease`。白色按钮在暗色背景下产生"发光"效果。 + +**光晕脉动**:卡片外层的紫色光晕以 `4s ease-in-out infinite` 的节奏在 `opacity 0.1 ↔ 0.2` 之间呼吸,赋予页面生命力。 + +#### 代码实现要点 + +1. **SVG 渐变网格**:使用绝对定位的 `div` 元素包裹三个 `div`(每个设置 `border-radius: 50%`、`filter: blur(120px)`、对应背景色),通过 CSS `@keyframes` 分别控制 `transform` 动画。或使用 SVG `` 配合 `` 实现同样的模糊色块效果。 + +2. **强毛玻璃卡片**:`backdrop-blur-2xl bg-white/10 border border-white/15 rounded-3xl shadow-[0_0_80px_rgba(167,139,250,0.15)]`。注意 `backdrop-blur` 需要浏览器支持,可考虑添加 `-webkit-backdrop-blur` 前缀。 + +3. **白色主按钮**:在深色背景下,白色按钮天然具有高对比度。Hover 效果避免使用 `translateY`(上移动效偏科技感),改用 `scale(1.02)`(更柔和、有机)。 + +4. **性能优化**:`blur(120px)` 大模糊是 GPU 密集型操作。建议使用 `will-change: transform` 提示浏览器优化,同时确保动画元素使用 `transform` 而非 `top/left` 属性。在低性能设备上可通过 `@media (prefers-reduced-motion: reduce)` 关闭背景动画。 + +--- + +### 3.6 各方案组件设计要点(对比表) + +| 设计维度 | 方案一「极光科技」 | 方案二「企业金融」 | 方案三「云端数据」 | 方案四「极简矩阵」 | 方案五「自然流动」 | +|:---------|:------------------|:------------------|:------------------|:------------------|:------------------| +| **布局结构** | 居中卡片 + 全屏粒子背景 | 左右分屏 60:40 | 居中卡片 + 浅色背景 | 居中卡片 + 全屏字符雨 | 居中卡片 + 动态渐变背景 | +| **背景实现** | Canvas 2D 粒子系统 | CSS 渐变 + 纯色分割 | CSS 渐变 + SVG 装饰 | Canvas 2D Matrix Rain | SVG/CSS 模糊渐变圆 | +| **卡片材质** | 毛玻璃 `backdrop-blur: 20px` | 纯白实色 | 纯白实色 | 半透明黑 `rgba(0,0,0,0.85)` | 强毛玻璃 `backdrop-blur: 24px` | +| **卡片圆角** | `16px` | `16px` | `20px` | `4px`(锐利) | `24px`(最大) | +| **卡片边框** | `1px solid rgba(255,255,255,0.08)` | 无 | 无 | `1px solid rgba(34,197,94,0.3)` | `1px solid rgba(255,255,255,0.15)` | +| **主色调** | 蓝 `#2563eb` + 紫 `#7c3aed` | 深蓝 `#1a365d` | 天蓝 `#0ea5e9` | 绿 `#22c55e` | 粉 `#f472b6` + 紫 `#a78bfa` + 蓝 `#60a5fa` | +| **背景色** | `#0a0e27` → `#1a1f4b` | 左 `#0c1a3c` 右 `#f8fafc` | `#f0f4f8` → `#e2e8f0` | `#000000` | `#0f0e1a` | +| **输入框样式** | 标准边框式 | 底部底线式 | 无边框 + 灰底 | 等宽字体 + 绿边框 | 毛玻璃半透明 | +| **按钮样式** | 渐变蓝紫 | 纯色深蓝 | 渐变天蓝 | 纯色绿 | 纯白 | +| **按钮圆角** | `10px` | `8px` | `12px` | `4px` | `12px` | +| **字体选择** | 系统默认 sans-serif | 系统默认 sans-serif | 系统默认 sans-serif | JetBrains Mono 等宽 | 系统默认 sans-serif | +| **SSO 支持** | 无 | 无 | 有(企业微信/钉钉/飞书) | 无 | 无 | +| **安全标识** | Shield 图标暗示 | SSL/权限/审计 明确列出 | 无 | 版本号信息 | 无 | +| **品牌展示** | 渐变圆 + Shield 图标 | 左侧大面积品牌区 | 顶部品牌图标 | 终端命令行风格 | 大圆角渐变图标 | +| **移动端适配** | 卡片全宽 + 边距 | 上下布局折叠 | 卡片全宽 | 卡片全宽 | 卡片全宽 | + +### 3.7 各方案动效设计规范(汇总表) + +| 动效维度 | 方案一「极光科技」 | 方案二「企业金融」 | 方案三「云端数据」 | 方案四「极简矩阵」 | 方案五「自然流动」 | +|:---------|:------------------|:------------------|:------------------|:------------------|:------------------| +| **背景动画** | 粒子连线 60fps | 无 | 云朵缓慢水平漂移 | 字符雨下落 | 三圆渐变漂移 | +| **入场动画** | 卡片淡入+上移 `600ms` | 左右滑入 `400ms` | 弹性下落 `500ms` | 打字机逐行 `80ms/行` | 柔和浮现 `700ms` | +| **入场缓动** | `cubic-bezier(0.16,1,0.3,1)` | `ease-out` | `cubic-bezier(0.34,1.56,0.64,1)` | `step-end` 风格 | `cubic-bezier(0.22,1,0.36,1)` | +| **输入框聚焦** | 蓝边框+光晕 `200ms` | 底线延展 `200ms` | 背景提亮+边框渐显 `150ms` | 绿边框亮度提升 `150ms` | 白边框透明度提升 `200ms` | +| **按钮 Hover** | 上移 `1px` + 阴影增强 | 背景加深 + 阴影 | 上移 `2px` + 渐变偏移 | 绿光晕染 + 背景变亮 | 缩放 `1.02` + 白影 | +| **错误反馈** | Shake 抖动 `300ms` | 边框变红 + 提示文字 | 边框变红 + 弹性抖动 | 红色终端错误信息 | 边框变红 + 光晕转红 | +| **特殊交互** | 鼠标粒子引力 | 信任指标依次淡入 | SSO 图标放大 | 光标闪烁 | 光晕呼吸脉动 | +| **动画性能** | `requestAnimationFrame` | CSS 过渡 | CSS 过渡/Framer Motion | `requestAnimationFrame` | CSS `transform` + `will-change` | +| **减弱动效** | 保留静态粒子 | 无需处理 | 保留静态布局 | 保留静态字符背景 | 保留静态模糊色块 | + +--- + +#### 方案选型建议 + +五套方案并非"五选一"的关系,而是为不同的部署场景提供针对性选择: + +- **对外技术产品**(如数据库管理工具、开发者平台)→ 方案一「极光科技」或方案四「极简矩阵」 +- **金融/政企客户私有化部署** → 方案二「企业金融」 +- **SaaS 订阅产品/云端服务** → 方案三「云端数据」 +- **创意团队/设计公司内部系统** → 方案五「自然流动」 + +建议在系统设置中提供登录页主题切换功能,允许管理员根据企业 VI 选择合适的方案,或在不同的子域名/入口自动匹配不同风格(如 `dev.dataguard.com` 使用极客风,`finance.dataguard.com` 使用金融风)。所有方案共享 `useLogin` 和 `useTheme` hook,切换主题仅涉及 UI 层组件的替换,业务逻辑零改动。 +## 4. 五套登录后主题设计方案 + +为满足不同用户群体在不同使用场景下的视觉偏好,本章为 SQL-Platform 设计五套完整的登录后主题方案。每套主题均包含完整的 CSS 变量规范、色彩心理学依据及典型应用场景说明。五套主题涵盖从专业沉稳到活力温暖的全方位视觉谱系,确保平台在各类企业环境中都能提供最佳的用户体验。 + +--- + +### 4.1 主题一「深蓝专业」— 默认深色增强版 + +**设计定位**:深蓝专业主题是在现有深色主题基础上的全面增强版本,定位为平台的默认主题。设计目标是在保持深色模式优势(降低眼部疲劳、突出内容)的同时,通过更纯正深邃的蓝色调提升整体品质感,并强化视觉层次与可读性。 + +**色彩设计理念**:该主题摒弃了原主题中偏灰的杂色倾向,将背景色收敛到更纯正的深蓝谱系。主背景色 `#070d19` 接近纯黑但带有微弱的蓝色相,营造出深邃而稳定的基底。次背景色 `#0f172a` 参考了 Slate 色板中最深沉的蓝色调,既保证了与主背景的层次区分,又维持了蓝色谱系的纯粹性。文字色彩采用 `#f8fafc`(极亮蓝白)作为主文字色,相比纯白色更具温润感,长时间阅读不易产生刺眼感。次文字色 `#94a3b8` 提供了充分的对比度,确保辅助信息的可读性。 + +**强调色体系**:蓝色系强调色选用 `#3b82f6`(Tailwind Blue 500),这是一个饱和度适中、辨识度高的蓝色,在深色背景上呈现明亮但不刺眼的视觉效果。状态色(成功、错误、警告)均经过深色背景适配,确保各色彩在深蓝底上都有足够的明度对比。 + +**适用场景**:作为默认主题,适用于绝大多数使用场景,特别适合技术团队日常操作、数据库管理、权限配置等需要长时间专注的工作界面。 + +```css +/* === 主题一:深蓝专业 ocean-deep === */ +[data-theme="ocean-deep"] { + /* shadcn/ui 基础变量 */ + --background: 222 47% 4%; + --foreground: 210 40% 98%; + --card: 222 47% 7%; + --card-foreground: 210 40% 98%; + --popover: 222 47% 7%; + --popover-foreground: 210 40% 98%; + --primary: 217 91% 60%; + --primary-foreground: 0 0% 100%; + --secondary: 217 33% 17%; + --secondary-foreground: 210 40% 98%; + --muted: 217 33% 17%; + --muted-foreground: 215 20% 65%; + --accent: 217 33% 17%; + --accent-foreground: 210 40% 98%; + --destructive: 0 84% 60%; + --destructive-foreground: 0 0% 100%; + --border: 217 33% 17%; + --input: 217 33% 17%; + --ring: 217 91% 60%; + --radius: 0.5rem; + + /* DataGuard 自定义变量 */ + --dg-bg-primary: #070d19; + --dg-bg-secondary: #0f172a; + --dg-bg-tertiary: #172033; + --dg-bg-hover: #233049; + --dg-border: #1e293b; + --dg-border-light: #172033; + --dg-text-primary: #f8fafc; + --dg-text-secondary: #94a3b8; + --dg-text-muted: #64748b; + --dg-blue: #3b82f6; + --dg-green: #22c55e; + --dg-red: #ef4444; + --dg-orange: #f97316; + --dg-purple: #8b5cf6; + --dg-cyan: #06b6d4; + --dg-yellow: #eab308; + --dg-gradient-start: #3b82f6; + --dg-gradient-end: #2563eb; +} +``` + +--- + +### 4.2 主题二「浅色商务」— 企业办公风 + +**设计定位**:浅色商务主题面向白天办公环境优化,采用温暖的灰白色调替代常见的冷白背景,营造舒适、专业且不刺眼的工作界面。该主题适合不习惯深色模式的用户,或在明亮办公室环境中使用。 + +**色彩设计理念**:背景色摒弃了纯白的冷峻感,主背景色 `#fafaf9` 选用带有微弱暖色相的" zinc white",在显示器上呈现柔和的纸质感。次背景色 `#f5f5f4` 和三级背景色 `#e7e5e4` 构成自然的层次递进,避免了传统浅色主题中背景层次过于平淡的问题。边框色 `#d6d3d1` 同样带有暖色调,使界面分割更加自然和谐。文字色彩方面,主文字色 `#1c1917` 是带有微弱棕色相的深黑色,相比纯黑在暖白背景上对比度更舒适,避免了"黑字白纸"的刺眼感。 + +**强调色体系**:强调色选用稳重的 `#2563eb`(Tailwind Blue 600),这是一个偏深的标准蓝色,传达专业、可信赖的企业形象。状态色均调整为适合浅色背景的版本,成功绿 `#16a34a`、错误红 `#dc2626`、警告橙 `#ca8a04` 在浅色背景上均保持良好的可读性。 + +**适用场景**:适合白天办公环境、管理人员日常审批查看、客户演示投屏等场景。浅色界面在投影设备上的显示效果通常优于深色界面,因此该主题也是会议室演示的首选。 + +```css +/* === 主题二:浅色商务 light-professional === */ +[data-theme="light-professional"] { + /* shadcn/ui 基础变量 */ + --background: 40 9% 98%; + --foreground: 24 10% 10%; + --card: 40 9% 96%; + --card-foreground: 24 10% 10%; + --popover: 40 9% 96%; + --popover-foreground: 24 10% 10%; + --primary: 221 83% 53%; + --primary-foreground: 0 0% 100%; + --secondary: 40 6% 90%; + --secondary-foreground: 24 10% 10%; + --muted: 40 6% 90%; + --muted-foreground: 25 5% 45%; + --accent: 40 6% 90%; + --accent-foreground: 24 10% 10%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 100%; + --border: 24 6% 83%; + --input: 24 6% 83%; + --ring: 221 83% 53%; + --radius: 0.5rem; + + /* DataGuard 自定义变量 */ + --dg-bg-primary: #fafaf9; + --dg-bg-secondary: #f5f5f4; + --dg-bg-tertiary: #e7e5e4; + --dg-bg-hover: #d6d3d1; + --dg-border: #d6d3d1; + --dg-border-light: #e7e5e4; + --dg-text-primary: #1c1917; + --dg-text-secondary: #78716c; + --dg-text-muted: #a8a29e; + --dg-blue: #2563eb; + --dg-green: #16a34a; + --dg-red: #dc2626; + --dg-orange: #ea580c; + --dg-purple: #7c3aed; + --dg-cyan: #0891b2; + --dg-yellow: #ca8a04; + --dg-gradient-start: #2563eb; + --dg-gradient-end: #4f46e5; +} +``` + +--- + +### 4.3 主题三「午夜紫韵」— 高端紫色调 + +**设计定位**:午夜紫韵主题以深紫黑色为基底,搭配明亮的紫色渐变强调色,营造高端、神秘且富有科技感的视觉氛围。该主题适合作为给客户演示时的展示主题,能够传达产品的技术领先性和品质感。 + +**色彩设计理念**:主背景色 `#0a0612` 是带有明显紫色相的极深色,接近"午夜黑"的概念,为整个界面奠定了神秘而高贵的基调。次背景色 `#130c21` 和三级背景色 `#1c1330` 沿紫色谱系逐步提亮,形成清晰的层次结构。悬停背景色 `#2d1f4a` 是一个中等深度的紫色,在交互时能够产生明显的视觉反馈,同时保持整体色调的一致性。文字色彩方面,主文字色 `#faf5ff` 带有微弱的紫色调,使文字在深色背景上更加柔和雅致。 + +**强调色体系**:该主题的核心亮点在于紫色渐变强调体系。渐变起点 `#9333ea`(Tailwind Purple 600)到渐变终点 `#c084fc`(Tailwind Purple 400)构成了一段明亮且富有活力的紫色渐变,用于品牌标识、主要按钮和重要数据高亮。蓝色调整为偏紫的靛蓝色 `#818cf8`,绿色调整为翠绿色 `#34d399`,红色调整为玫红色 `#fb7185`,所有状态色都经过紫色调环境的协调适配。 + +**适用场景**:产品发布会演示、客户汇报展示、高端企业部署、技术峰会展台等需要彰显产品品质的正式场合。 + +```css +/* === 主题三:午夜紫韵 midnight-purple === */ +[data-theme="midnight-purple"] { + /* shadcn/ui 基础变量 */ + --background: 264 56% 4%; + --foreground: 280 100% 98%; + --card: 264 48% 8%; + --card-foreground: 280 100% 98%; + --popover: 264 48% 8%; + --popover-foreground: 280 100% 98%; + --primary: 270 91% 65%; + --primary-foreground: 0 0% 100%; + --secondary: 264 40% 20%; + --secondary-foreground: 280 100% 98%; + --muted: 264 40% 20%; + --muted-foreground: 280 30% 60%; + --accent: 264 40% 20%; + --accent-foreground: 280 100% 98%; + --destructive: 348 100% 72%; + --destructive-foreground: 264 56% 4%; + --border: 264 40% 20%; + --input: 264 40% 20%; + --ring: 270 91% 65%; + --radius: 0.5rem; + + /* DataGuard 自定义变量 */ + --dg-bg-primary: #0a0612; + --dg-bg-secondary: #130c21; + --dg-bg-tertiary: #1c1330; + --dg-bg-hover: #2d1f4a; + --dg-border: #2d1f4a; + --dg-border-light: #1c1330; + --dg-text-primary: #faf5ff; + --dg-text-secondary: #b794c7; + --dg-text-muted: #7c5a8a; + --dg-blue: #818cf8; + --dg-green: #34d399; + --dg-red: #fb7185; + --dg-orange: #fb923c; + --dg-purple: #c084fc; + --dg-cyan: #22d3ee; + --dg-yellow: #facc15; + --dg-gradient-start: #9333ea; + --dg-gradient-end: #c084fc; +} +``` + +--- + +### 4.4 主题四「松绿自然」— 护眼绿调 + +**设计定位**:松绿自然主题面向长时间使用平台的开发团队设计,以墨绿色为基调,利用绿色光谱对人眼最为友好的特性,最大程度降低长时间注视屏幕带来的视觉疲劳。 + +**色彩设计理念**:该主题的核心设计原则是"护眼优先"。主背景色 `#0a1210` 是带有明显绿色相的极深色,类似深夜松林深处的颜色,极低明度确保了基础视觉负荷的最小化。次背景色 `#111f1a`(深墨绿)和三级背景色 `#192c24`(墨绿灰)沿绿色谱系递进,在保持低明度的同时构建清晰的视觉层次。悬停背景色 `#253d32` 选用了中等深度的松绿色,交互时呈现自然、柔和的状态变化。边框色 `#253d32` 与悬停色共用,确保交互反馈与界面分割的视觉统一。主文字色 `#f0fdf4` 是极淡的薄荷白,在墨绿背景上明亮而不刺眼,具有极佳的阅读舒适度。 + +**强调色体系**:绿色系强调色选用 `#4ade80`(Tailwind Green 400),这是一个明亮、清新的绿色,在墨绿暗底上如同松针上的晨露般醒目。信息色 `#2dd4bf` 偏向青绿色,与主色调完美协调。蓝色调整为天蓝色 `#38bdf8`,在绿调环境中起到色彩平衡的作用,避免界面过于单调。 + +**适用场景**:开发团队日常长时间使用、DBA 持续监控数据库状态、运维人员驻屏值班等需要长时间面对屏幕的工作场景。 + +```css +/* === 主题四:松绿自然 pine-green === */ +[data-theme="pine-green"] { + /* shadcn/ui 基础变量 */ + --background: 150 25% 5%; + --foreground: 140 60% 97%; + --card: 150 25% 9%; + --card-foreground: 140 60% 97%; + --popover: 150 25% 9%; + --popover-foreground: 140 60% 97%; + --primary: 142 71% 45%; + --primary-foreground: 150 25% 5%; + --secondary: 150 20% 18%; + --secondary-foreground: 140 60% 97%; + --muted: 150 20% 18%; + --muted-foreground: 150 20% 55%; + --accent: 150 20% 18%; + --accent-foreground: 140 60% 97%; + --destructive: 0 90% 72%; + --destructive-foreground: 150 25% 5%; + --border: 150 20% 18%; + --input: 150 20% 18%; + --ring: 142 71% 45%; + --radius: 0.5rem; + + /* DataGuard 自定义变量 */ + --dg-bg-primary: #0a1210; + --dg-bg-secondary: #111f1a; + --dg-bg-tertiary: #192c24; + --dg-bg-hover: #253d32; + --dg-border: #253d32; + --dg-border-light: #192c24; + --dg-text-primary: #f0fdf4; + --dg-text-secondary: #86b8a0; + --dg-text-muted: #5a7c6b; + --dg-blue: #38bdf8; + --dg-green: #4ade80; + --dg-red: #f87171; + --dg-orange: #fb923c; + --dg-purple: #c084fc; + --dg-cyan: #2dd4bf; + --dg-yellow: #facc15; + --dg-gradient-start: #059669; + --dg-gradient-end: #10b981; +} +``` + +--- + +### 4.5 主题五「橙光活力」— 活力暖色调 + +**设计定位**:橙光活力主题以深棕暗橙为基底,搭配明亮的橙色渐变,传递温暖、积极、富有活力的品牌情绪。该主题面向年轻化团队和创新型企业,打破传统数据安全平台冰冷刻板的印象。 + +**色彩设计理念**:主背景色 `#110d08` 是带有明显棕色相的极深色,类似深烘焙咖啡豆的颜色,温暖而沉稳。次背景色 `#1d1610` 和三级背景色 `#2b1f16` 沿棕色谱系递进,营造出如同暖色调咖啡馆般的舒适感。悬停背景色 `#3d2d20` 是一个中等深度的暖棕色,交互反馈如同木材被温暖光线照亮。文字色彩方面,主文字色 `#fef7ed` 是极淡的暖白色,如同烛光下的纸张,在暗棕底上既明亮又温暖。 + +**强调色体系**:核心渐变从 `#ea580c`(Tailwind Orange 600)到 `#f59e0b`(Tailwind Amber 500),这是一段充满能量感的橙黄渐变,用于重要按钮、品牌标识和数据高亮时极具视觉冲击力。蓝色调整为柔和的 `#60a5fa`,在暖色调环境中起到中和平衡的作用。紫色调整为偏暖的 `#a78bfa`,与整体暖调和谐共存。 + +**适用场景**:互联网创业公司、年轻化的技术团队、创意型企业、产品内部分享会等追求活力与创新氛围的使用场景。 + +```css +/* === 主题五:橙光活力 orange-vitality === */ +[data-theme="orange-vitality"] { + /* shadcn/ui 基础变量 */ + --background: 30 35% 5%; + --foreground: 30 100% 97%; + --card: 30 30% 9%; + --card-foreground: 30 100% 97%; + --popover: 30 30% 9%; + --popover-foreground: 30 100% 97%; + --primary: 25 95% 53%; + --primary-foreground: 0 0% 100%; + --secondary: 30 25% 18%; + --secondary-foreground: 30 100% 97%; + --muted: 30 25% 18%; + --muted-foreground: 30 25% 55%; + --accent: 30 25% 18%; + --accent-foreground: 30 100% 97%; + --destructive: 0 80% 70%; + --destructive-foreground: 30 35% 5%; + --border: 30 25% 18%; + --input: 30 25% 18%; + --ring: 25 95% 53%; + --radius: 0.5rem; + + /* DataGuard 自定义变量 */ + --dg-bg-primary: #110d08; + --dg-bg-secondary: #1d1610; + --dg-bg-tertiary: #2b1f16; + --dg-bg-hover: #3d2d20; + --dg-border: #3d2d20; + --dg-border-light: #2b1f16; + --dg-text-primary: #fef7ed; + --dg-text-secondary: #d4a574; + --dg-text-muted: #9c7a54; + --dg-blue: #60a5fa; + --dg-green: #4ade80; + --dg-red: #f87171; + --dg-orange: #fb923c; + --dg-purple: #a78bfa; + --dg-cyan: #2dd4bf; + --dg-yellow: #fcd34d; + --dg-gradient-start: #ea580c; + --dg-gradient-end: #f59e0b; +} +``` + +--- + +### 4.6 各主题 CSS 变量规范对比表 + +下表汇总了五套主题的全部 DataGuard 自定义 CSS 变量值,便于开发实现时快速查阅与对比。 + +| CSS 变量 | 深蓝专业 | 浅色商务 | 午夜紫韵 | 松绿自然 | 橙光活力 | +|:---|:---|:---|:---|:---|:---| +| `--dg-bg-primary` | `#070d19` | `#fafaf9` | `#0a0612` | `#0a1210` | `#110d08` | +| `--dg-bg-secondary` | `#0f172a` | `#f5f5f4` | `#130c21` | `#111f1a` | `#1d1610` | +| `--dg-bg-tertiary` | `#172033` | `#e7e5e4` | `#1c1330` | `#192c24` | `#2b1f16` | +| `--dg-bg-hover` | `#233049` | `#d6d3d1` | `#2d1f4a` | `#253d32` | `#3d2d20` | +| `--dg-border` | `#1e293b` | `#d6d3d1` | `#2d1f4a` | `#253d32` | `#3d2d20` | +| `--dg-border-light` | `#172033` | `#e7e5e4` | `#1c1330` | `#192c24` | `#2b1f16` | +| `--dg-text-primary` | `#f8fafc` | `#1c1917` | `#faf5ff` | `#f0fdf4` | `#fef7ed` | +| `--dg-text-secondary` | `#94a3b8` | `#78716c` | `#b794c7` | `#86b8a0` | `#d4a574` | +| `--dg-text-muted` | `#64748b` | `#a8a29e` | `#7c5a8a` | `#5a7c6b` | `#9c7a54` | +| `--dg-blue` | `#3b82f6` | `#2563eb` | `#818cf8` | `#38bdf8` | `#60a5fa` | +| `--dg-green` | `#22c55e` | `#16a34a` | `#34d399` | `#4ade80` | `#4ade80` | +| `--dg-red` | `#ef4444` | `#dc2626` | `#fb7185` | `#f87171` | `#f87171` | +| `--dg-orange` | `#f97316` | `#ea580c` | `#fb923c` | `#fb923c` | `#fb923c` | +| `--dg-purple` | `#8b5cf6` | `#7c3aed` | `#c084fc` | `#c084fc` | `#a78bfa` | +| `--dg-cyan` | `#06b6d4` | `#0891b2` | `#22d3ee` | `#2dd4bf` | `#2dd4bf` | +| `--dg-yellow` | `#eab308` | `#ca8a04` | `#facc15` | `#facc15` | `#fcd34d` | +| `--dg-gradient-start` | `#3b82f6` | `#2563eb` | `#9333ea` | `#059669` | `#ea580c` | +| `--dg-gradient-end` | `#2563eb` | `#4f46e5` | `#c084fc` | `#10b981` | `#f59e0b` | + +**shadcn/ui 基础变量对比表** + +| HSL 变量 | 深蓝专业 | 浅色商务 | 午夜紫韵 | 松绿自然 | 橙光活力 | +|:---|:---|:---|:---|:---|:---| +| `--background` | `222 47% 4%` | `40 9% 98%` | `264 56% 4%` | `150 25% 5%` | `30 35% 5%` | +| `--foreground` | `210 40% 98%` | `24 10% 10%` | `280 100% 98%` | `140 60% 97%` | `30 100% 97%` | +| `--card` | `222 47% 7%` | `40 9% 96%` | `264 48% 8%` | `150 25% 9%` | `30 30% 9%` | +| `--primary` | `217 91% 60%` | `221 83% 53%` | `270 91% 65%` | `142 71% 45%` | `25 95% 53%` | +| `--secondary` | `217 33% 17%` | `40 6% 90%` | `264 40% 20%` | `150 20% 18%` | `30 25% 18%` | +| `--muted` | `217 33% 17%` | `40 6% 90%` | `264 40% 20%` | `150 20% 18%` | `30 25% 18%` | +| `--muted-foreground` | `215 20% 65%` | `25 5% 45%` | `280 30% 60%` | `150 20% 55%` | `30 25% 55%` | +| `--destructive` | `0 84% 60%` | `0 72% 51%` | `348 100% 72%` | `0 90% 72%` | `0 80% 70%` | +| `--border` | `217 33% 17%` | `24 6% 83%` | `264 40% 20%` | `150 20% 18%` | `30 25% 18%` | +| `--ring` | `217 91% 60%` | `221 83% 53%` | `270 91% 65%` | `142 71% 45%` | `25 95% 53%` | + +--- + +### 4.7 主题切换实现方案 + +#### 4.7.1 CSS 变量组织方式 + +五套主题的 CSS 变量采用 **"分散定义、统一命名空间"** 的组织策略。每套主题的所有变量定义在一个独立的 `data-theme` 属性选择器下,避免变量冲突和覆盖混乱。 + +**文件结构建议**: + +``` +frontend/src/styles/ +├── themes/ +│ ├── index.css /* 主题入口文件,导入所有主题 */ +│ ├── ocean-deep.css /* 主题一:深蓝专业 */ +│ ├── light-professional.css /* 主题二:浅色商务 */ +│ ├── midnight-purple.css /* 主题三:午夜紫韵 */ +│ ├── pine-green.css /* 主题四:松绿自然 */ +│ └── orange-vitality.css /* 主题五:橙光活力 */ +└── index.css /* 现有主样式文件 */ +``` + +**入口文件 `themes/index.css` 内容**: + +```css +/* ===== SQL-Platform 主题系统入口 ===== */ +/* 按加载顺序:默认主题(深蓝专业)无需 data-theme 属性 */ + +@import "./ocean-deep.css"; +@import "./light-professional.css"; +@import "./midnight-purple.css"; +@import "./pine-green.css"; +@import "./orange-vitality.css"; +``` + +> **实现说明**:`ocean-deep.css` 同时提供 `:root` 级别的默认变量(确保无 `data-theme` 属性时回退到默认主题)和 `[data-theme="ocean-deep"]` 选择器下的显式定义,保证其他主题切换回来时变量能正确覆盖。 + +#### 4.7.2 useTheme Hook 增强实现 + +现有的 `useTheme` hook 需要从双值切换(dark/light)扩展为多主题选择。以下是增强后的实现方案: + +```typescript +// frontend/src/hooks/useTheme.ts +import { useState, useEffect, useCallback } from 'react'; + +/** 支持的主题标识列表 */ +export const THEMES = [ + { id: 'ocean-deep', label: '深蓝专业', description: '默认深色增强版' }, + { id: 'light-professional', label: '浅色商务', description: '企业办公风' }, + { id: 'midnight-purple', label: '午夜紫韵', description: '高端紫色调' }, + { id: 'pine-green', label: '松绿自然', description: '护眼绿调' }, + { id: 'orange-vitality', label: '橙光活力', description: '活力暖色调' }, +] as const; + +export type ThemeId = typeof THEMES[number]['id']; + +const STORAGE_KEY = 'sqlp-theme-id'; +const DEFAULT_THEME: ThemeId = 'ocean-deep'; + +/** + * 从 localStorage 读取保存的主题 + */ +function getSavedTheme(): ThemeId { + try { + const saved = localStorage.getItem(STORAGE_KEY); + if (saved && THEMES.some(t => t.id === saved)) { + return saved as ThemeId; + } + } catch { + // localStorage 不可用时忽略 + } + return DEFAULT_THEME; +} + +/** + * 检测系统色彩偏好 + */ +function getSystemPreference(): 'dark' | 'light' { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +} + +/** + * 根据系统偏好映射默认主题 + */ +function getDefaultBySystem(): ThemeId { + return getSystemPreference() === 'dark' ? 'ocean-deep' : 'light-professional'; +} + +export function useTheme() { + const [theme, setThemeState] = useState(() => { + const saved = getSavedTheme(); + return saved || getDefaultBySystem(); + }); + + /** + * 切换主题的核心方法 + */ + const setTheme = useCallback((newTheme: ThemeId) => { + setThemeState(newTheme); + document.documentElement.setAttribute('data-theme', newTheme); + try { + localStorage.setItem(STORAGE_KEY, newTheme); + } catch { + // localStorage 不可用时静默处理 + } + }, []); + + /** + * 初始化主题:首次加载时应用 + */ + useEffect(() => { + const saved = getSavedTheme(); + const initial = saved || getDefaultBySystem(); + document.documentElement.setAttribute('data-theme', initial); + setThemeState(initial); + }, []); + + /** + * 监听系统主题变化,仅在用户未手动选择主题时自动切换 + */ + useEffect(() => { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handler = (e: MediaQueryListEvent) => { + // 检查用户是否已手动设置过主题 + const hasUserPreference = localStorage.getItem(STORAGE_KEY) !== null; + if (!hasUserPreference) { + const newTheme = e.matches ? 'ocean-deep' : 'light-professional'; + setTheme(newTheme); + } + }; + mediaQuery.addEventListener('change', handler); + return () => mediaQuery.removeEventListener('change', handler); + }, [setTheme]); + + return { theme, setTheme, themes: THEMES }; +} +``` + +#### 4.7.3 主题预览组件设计 + +AppearanceSettings 页面需新增主题选择区域,包含五张主题预览卡片。每张卡片展示主题的核心色彩样本和简要描述。 + +```typescript +// frontend/src/components/settings/ThemePreviewCard.tsx +import { Check } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import type { ThemeId } from '@/hooks/useTheme'; + +interface ThemePreviewCardProps { + themeId: ThemeId; + label: string; + description: string; + colors: { + bg: string; + secondary: string; + accent: string; + text: string; + }; + isActive: boolean; + onClick: () => void; +} + +export function ThemePreviewCard({ + label, + description, + colors, + isActive, + onClick, +}: ThemePreviewCardProps) { + return ( + + ); +} +``` + +**AppearanceSettings 页面中的主题选择区域布局**: + +```tsx +// 在 AppearanceSettings 页面中使用 +import { useTheme, THEMES } from '@/hooks/useTheme'; +import { ThemePreviewCard } from '@/components/settings/ThemePreviewCard'; + +// 各主题预览色值配置 +const THEME_PREVIEW_COLORS: Record = { + 'ocean-deep': { bg: '#070d19', secondary: '#0f172a', accent: '#3b82f6', text: '#f8fafc' }, + 'light-professional': { bg: '#fafaf9', secondary: '#f5f5f4', accent: '#2563eb', text: '#1c1917' }, + 'midnight-purple': { bg: '#0a0612', secondary: '#130c21', accent: '#c084fc', text: '#faf5ff' }, + 'pine-green': { bg: '#0a1210', secondary: '#111f1a', accent: '#4ade80', text: '#f0fdf4' }, + 'orange-vitality': { bg: '#110d08', secondary: '#1d1610', accent: '#fb923c', text: '#fef7ed' }, +}; + +function ThemeSelector() { + const { theme: activeTheme, setTheme } = useTheme(); + + return ( +
+

界面主题

+
+ {THEMES.map((t) => ( + setTheme(t.id)} + /> + ))} +
+
+ ); +} +``` + +#### 4.7.4 localStorage 持久化方案 + +主题持久化遵循以下策略: + +| 策略项 | 说明 | +|:---|:---| +| **存储键名** | `sqlp-theme-id`,与现有 `theme` 键分离,避免升级冲突 | +| **存储值** | 主题标识字符串,如 `ocean-deep`、`light-professional` | +| **回退逻辑** | 读取不到有效值时,检测 `prefers-color-scheme` 系统偏好,暗色默认 `ocean-deep`,亮色默认 `light-professional` | +| **版本兼容** | 首次升级时,若检测到旧版 `theme: "dark"` 键,自动迁移至 `ocean-deep`;`theme: "light"` 迁移至 `light-professional`,随后删除旧键 | +| **异常处理** | localStorage 不可用时(隐私模式、存储已满),降级为仅内存状态,不抛出错误 | +| **跨设备同步** | 通过 `storage` 事件监听同源其他标签页的主题变更,实现多标签页同步: | + +```typescript +/** + * 跨标签页主题同步 + */ +useEffect(() => { + const handler = (e: StorageEvent) => { + if (e.key === STORAGE_KEY && e.newValue) { + const newTheme = e.newValue as ThemeId; + if (THEMES.some(t => t.id === newTheme)) { + setThemeState(newTheme); + document.documentElement.setAttribute('data-theme', newTheme); + } + } + }; + window.addEventListener('storage', handler); + return () => window.removeEventListener('storage', handler); +}, []); +``` + +#### 4.7.5 系统主题偏好检测 + +平台需响应操作系统的 `prefers-color-scheme` 媒体查询,提供智能化的默认主题推荐。 + +**检测逻辑**: + +```typescript +// 检测系统暗色/浅色偏好 +const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; +const prefersLight = window.matchMedia('(prefers-color-scheme: light)').matches; +``` + +**偏好映射规则**: + +| 系统偏好 | 默认推荐主题 | 推荐逻辑 | +|:---|:---|:---| +| `prefers-color-scheme: dark` | **深蓝专业** (`ocean-deep`) | 暗色系统偏好用户通常偏好深色界面 | +| `prefers-color-scheme: light` | **浅色商务** (`light-professional`) | 亮色系统偏好用户通常偏好浅色界面 | +| 未指定(no-preference) | **深蓝专业** (`ocean-deep`) | 默认采用平台默认主题 | + +**动态响应机制**: + +```typescript +/** + * 系统主题偏好动态响应 + * 仅在用户未手动设置主题时自动跟随系统 + */ +useEffect(() => { + const darkQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const lightQuery = window.matchMedia('(prefers-color-scheme: light)'); + + const handleChange = () => { + const hasUserPreference = localStorage.getItem(STORAGE_KEY) !== null; + if (hasUserPreference) return; // 用户已手动选择,不自动切换 + + if (darkQuery.matches) { + setTheme('ocean-deep'); + } else if (lightQuery.matches) { + setTheme('light-professional'); + } + }; + + darkQuery.addEventListener('change', handleChange); + lightQuery.addEventListener('change', handleChange); + + return () => { + darkQuery.removeEventListener('change', handleChange); + lightQuery.removeEventListener('change', handleChange); + }; +}, [setTheme]); +``` + +**重要原则**:系统偏好仅影响**首次访问**或**清除 localStorage 后**的默认主题选择。一旦用户手动选择了主题,该选择将被持久化并优先于系统偏好,避免在用户主动选择后因系统时间变化(如 macOS 自动切换暗色模式)导致界面意外变更。 + +#### 4.7.6 切换过渡动效 + +主题切换时应提供平滑的视觉过渡,避免色彩突变带来的不适感。 + +```css +/* 全局主题过渡效果 —— 添加到 index.css */ +html { + /* 对所有 CSS 变量变化应用 200ms 缓动过渡 */ + transition: background-color 200ms ease, color 200ms ease; +} + +html *, html *::before, html *::after { + /* 谨慎使用:仅对关键属性过渡,避免性能问题 */ + transition: background-color 200ms ease, + border-color 200ms ease, + color 150ms ease; +} + +/* 可选:切换瞬间的淡入效果 */ +[data-theme] { + animation: themeFadeIn 200ms ease; +} + +@keyframes themeFadeIn { + from { opacity: 0.92; } + to { opacity: 1; } +} +``` + +**性能优化建议**:全局 `*` 过渡规则可能影响大型列表渲染性能。生产环境中建议仅对需要过渡的元素添加过渡规则,或通过 JavaScript 在切换主题时临时添加过渡 class,切换完成后再移除: + +```typescript +/** + * 带过渡动画的主题切换 + */ +const setThemeWithTransition = useCallback((newTheme: ThemeId) => { + const root = document.documentElement; + root.classList.add('theme-transitioning'); + setTheme(newTheme); + // 300ms 后移除过渡 class + setTimeout(() => { + root.classList.remove('theme-transitioning'); + }, 300); +}, [setTheme]); +``` + +```css +/* 仅在切换时启用过渡 */ +html.theme-transitioning, +html.theme-transitioning * { + transition: background-color 200ms ease, + border-color 200ms ease, + color 150ms ease !important; +} +``` + +以上实现方案确保五套主题能够稳定、高效、优雅地在平台中运行,为用户提供丰富的个性化选择。 +## 5. 核心功能页面优化方案 + +本章针对 SQL-Platform 三个核心功能模块——审批变更(工单系统)、查询数据、系统设置——进行逐页拆解分析,提出可落地的 UI/UX 优化方案。每个方案均包含具体的组件选型、布局参数、交互细节与视觉规范,确保开发团队能够直接转化为实现任务。 + +--- + +### 5.1 审批变更工单系统优化 + +审批变更是平台的核心业务流,涉及工单列表、工单创建、工单详情三个主要页面。当前实现存在布局松散、信息层级不清、操作流程割裂等问题。以下按页面逐一给出优化方案。 + +#### 5.1.1 工单列表页优化 + +**组件选型与布局重构** + +将原生 `
` 全面替换为 `@tanstack/react-table` + `shadcn/ui DataTable` 组合。DataTable 内置列排序、列过滤、行选择、分页等能力,可显著减少 742 行中的手写逻辑。表格容器采用 `rounded-xl border border-border/60 bg-card` 样式,阴影参数为 `shadow-sm`。 + +**状态卡片升级** + +原状态卡片(全部/待审批/执行中/完成/失败)改为 Stats Cards。每张卡片包含:状态图标(`Lucide`)、工单数量(`text-2xl font-bold`)、环比趋势箭头(绿色上升/红色下降)、环比百分比(`text-xs text-muted-foreground`)。卡片使用 `cn()` 动态绑定激活状态的边框色——激活时边框为 `ring-2 ring-primary/40 border-primary`,未激活为 `border-transparent hover:border-border/80`。卡片网格采用 `grid grid-cols-5 gap-4`,在 < 1024px 下退化为 `grid-cols-3` + `grid-cols-2`。 + +**高级筛选栏** + +在状态卡片下方新增折叠式筛选栏,包含以下控件: + +| 筛选项 | 组件 | 说明 | +|---------|------|------| +| 实例 | `Select`(多选) | 从实例列表异步加载 | +| 数据库类型 | `Select`(多选) | MySQL/PostgreSQL/MongoDB 等 | +| 提交人 | `Input` + `Avatar` | 支持用户名/邮箱搜索 | +| 时间范围 | `DateRangePicker` | shadcn/ui 官方组件 | +| 优先级 | `ToggleGroup` | 高/中/低三态切换 | + +筛选栏默认折叠,点击"高级筛选"按钮展开,展开高度动画 `duration-300 ease-in-out`。所有筛选条件通过 URL query params 同步,支持刷新后状态保持。 + +**表格交互增强** + +- **优先级标识**:每行左侧增加 4px 宽色条,高=`bg-red-500`、中=`bg-amber-500`、低=`bg-slate-400`,使用绝对定位贴左边框。 +- **行 Hover 效果**:`hover:bg-muted/60`,同时左侧出现 `border-l-2 border-primary` 指示条,过渡 `transition-colors duration-150`。 +- **操作列优化**:将分散的查看/通过/拒绝/执行/撤销按钮收缩为图标按钮组(`Eye`, `CheckCircle`, `XCircle`, `Play`, `RotateCcw`)。当操作超过 3 个时,溢出部分收入 `DropdownMenu`。按钮使用 `variant="ghost" size="icon"`。 +- **批量操作**:顶部新增批量操作栏,选中行后出现(`AnimatePresence` 滑入),包含"批量审批"、"批量拒绝"、"导出选中"三个主操作,危险操作使用 `variant="destructive"`。 +- **列自定义**:列头右键菜单支持"隐藏此列"、"重置列宽",列宽拖拽使用 `react-resizable` 实现,拖拽手柄 4px 宽,hover 时显示 `bg-primary/30`。 + +**搜索与分页** + +搜索框使用 `Input` + `Search` 图标,支持 `Cmd+K` 快捷键聚焦。分页组件采用 `shadcn/ui Pagination`,页码按钮尺寸 `h-9 w-9`,当前页 `bg-primary text-primary-foreground`。每页条数可选 10/25/50/100。 + +--- + +#### 5.1.2 工单创建页优化 + +**布局重构:左右分栏** + +将当前 1192 行的单栏布局改为左右分栏:左侧编辑器区占 `w-3/5`(60%),右侧辅助信息面板占 `w-2/5`(40%),中间分隔线 `border-r border-border/60`。两栏均独立滚动,避免编辑器滚动时右侧信息丢失。分栏在 < 1280px 下退化为上下堆叠布局。 + +**步骤指示器(Step Indicator)** + +在分栏顶部增加横向步骤条,共三步: + +``` +① 填写信息 ──→ ② SQL 审核 ──→ ③ 提交审批 +``` + +步骤条使用 `shadcn/ui` 风格的自定义组件。已完成步骤圆圈 `bg-primary text-primary-foreground`,当前步骤 `bg-primary ring-4 ring-primary/20`,未到达步骤 `bg-muted text-muted-foreground`。连线使用 `h-0.5 w-16`,已完成段 `bg-primary`,未完成段 `bg-border`。步骤切换允许回退(已填写内容保留),但前进需通过当前步骤的验证(如 SQL 审核必须通过才能到第三步)。 + +**左侧编辑器区** + +- **顶部工具栏**:实例选择 + 数据库选择使用 `Popover` + `Command` 组合(支持搜索筛选),定时执行使用 `Switch` + `DateTimePicker`,格式化按钮(`AlignLeft` 图标)使用 `variant="outline" size="sm"`。工具栏使用 `flex items-center gap-3 p-3 border-b border-border/60 bg-muted/30`。 +- **SQL 编辑器**:保留 CodeMirror 6,新增配置:行号显示(`lineNumbers()`)、迷你地图(`@codemirror/view showMinimap` 或自定义 SVG 缩略图)、当前行高亮(`highlightActiveLineGutter()`)。编辑器高度 `h-[480px]`,边框 `border-0`(融入容器)。 +- **SQL 模板快捷插入**:编辑器左下角增加"模板"按钮,点击弹出 `Popover`,内含分类模板列表(DDL/DML/查询),点击后 `editor.dispatch()` 插入模板 SQL。 + +**右侧辅助面板** + +- **审核结果卡片**:使用三个独立卡片分别展示 Error(`bg-red-50 border-red-200`)、Warning(`bg-amber-50 border-amber-200`)、Info(`bg-blue-50 border-blue-200`)。每张卡片包含:数量 badge(`rounded-full px-2 py-0.5 text-xs font-medium`)、发现项列表(每项包含行号、规则名、描述)、展开/折叠按钮。Error 卡片默认展开,其他折叠。 +- **变更原因输入**:将 `

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 W=O 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 M4P2; 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