# Aether 设计系统 v2.3
> 基于 shadcn/ui 和书本纸张主题的完整前端设计规范
**版本**: 2.3.0
**最后更新**: 2025-11-18
---
## 概述
本文档描述了 Aether 前端项目的设计系统,基于 shadcn/ui 和自定义主题构建。所有组件均已实现并在生产环境中使用。
### 核心理念
1. **一致性优先** - 所有组件遵循统一的视觉语言和交互模式
2. **响应式设计** - 组件自适应不同屏幕尺寸(移动端、平板、桌面)
3. **可访问性** - 遵循 WCAG 2.1 标准,支持键盘导航和屏幕阅读器
4. **性能优化** - 轻量级组件,按需加载,优化渲染性能
5. **开发体验** - TypeScript 类型安全,清晰的 API 设计,完善的文档
### 色彩体系
项目使用书本纸张主题色:
- **book-cloth** - 书籍封面布料色 (#cc785c / #d4a27f)
- **kraft** - 牛皮纸色 (#b97847 / #c9a26f)
- **manilla** - 马尼拉纸色 (#e8ddc5 / #d4c5a9)
- **cloud** - 云白色 (#f5f3ed / #2a2723)
详细配置见 [src/config/theme.ts](src/config/theme.ts)
---
## 技术栈
- **Vue 3** - Composition API
- **TypeScript** - 类型安全
- **Tailwind CSS** - 原子化 CSS
- **shadcn/ui** - 基础组件库
- **lucide-vue-next** - 图标库
- **Vite** - 构建工具
---
## 主题系统
### 主题配置
主题配置位于 [src/config/theme.ts](src/config/theme.ts),包含:
```ts
export const theme = {
colors: themeColors, // 颜色系统
spacing, // 间距系统(基于 8px 网格)
radius, // 圆角系统
shadows, // 阴影系统
typography, // 字体系统
animations, // 动画系统
breakpoints, // 响应式断点
zIndex, // 层级管理
components: componentDefaults // 组件默认配置
}
```
### CSS 变量
全局 CSS 变量定义在 `src/assets/index.css`,使用 HSL 色彩空间:
```css
:root {
--background: 0 0% 100%;
--foreground: 20 14.3% 4.1%;
--primary: 15 55% 58%;
--border: 20 5.9% 90%;
--muted: 60 4.8% 95.9%;
--muted-foreground: 25 5.3% 44.7%;
/* ... 更多变量 */
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 0 0% 95%;
--primary: 15 45% 68%;
/* ... 暗色模式变量 */
}
```
---
## 组件库
### 基础组件 (shadcn/ui)
所有基础组件位于 [src/components/ui/](src/components/ui/):
#### 布局组件
- **Card** - 卡片容器
- 变体:`default`、`outline`、`ghost`、`interactive`
- **Separator** - 分隔线(水平/垂直)
- **Tabs** - 选项卡容器
#### 表单组件
- **Button** - 按钮
- 变体:`default`、`destructive`、`outline`、`secondary`、`ghost`、`link`
- 大小:`sm`、`md`、`lg`、`icon`
- **Input** - 输入框
- **Textarea** - 多行文本框
- **Select** - 下拉选择框
- **Checkbox** - 复选框
- **Switch** - 开关
- **Label** - 表单标签
#### 反馈组件
- **Badge** - 徽章标签
- **Skeleton** - 骨架屏
- **Toast** - 消息提示
- **Dialog** - 对话框/模态框
- **Alert** - 警告提示
#### 数据展示
- **Table** 系列 - 表格组件
- Table、TableHeader、TableBody、TableRow、TableHead、TableCell
- **Avatar** - 头像
- **Progress** - 进度条
---
### 布局组件 (Layout Components)
位于 [src/components/layout/](src/components/layout/),所有组件支持从 `@/components/layout` 统一导入:
```ts
import { PageHeader, PageContainer, Section, CardSection, Grid, StatCard } from '@/components/layout'
```
#### PageHeader
页面头部组件,支持标题、描述、图标和操作按钮。
**使用示例:**
```vue
```
**Props:**
- `title: string` - 页面标题(必填)
- `description?: string` - 页面描述
- `icon?: Component` - 图标组件
**Slots:**
- `icon` - 自定义图标区域
- `actions` - 右侧操作按钮
---
#### PageContainer
页面容器,提供响应式的最大宽度和内边距。
**使用示例:**
```vue
```
**Props:**
- `maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'` - 最大宽度(默认: '2xl')
- `padding?: 'none' | 'sm' | 'md' | 'lg'` - 内边距(默认: 'md')
---
#### Section
区块容器,用于分隔页面不同区域。
**使用示例:**
```vue
```
**Props:**
- `title?: string` - 区块标题
- `description?: string` - 区块描述
- `spacing?: 'none' | 'sm' | 'md' | 'lg'` - 底部间距(默认: 'md')
**Slots:**
- `header` - 自定义头部
- `actions` - 右侧操作按钮
- `default` - 主内容
---
#### CardSection
卡片区块,基于 Card 组件的增强版。
**使用示例:**
```vue
```
**Props:**
- `title?: string` - 卡片标题
- `description?: string` - 卡片描述
- `variant?: 'default' | 'elevated' | 'glass'` - 卡片样式(默认: 'default')
- `padding?: 'none' | 'sm' | 'md' | 'lg'` - 内边距(默认: 'md')
**Slots:**
- `header` - 自定义头部
- `actions` - 头部右侧操作
- `default` - 主内容
- `footer` - 底部内容
---
#### Grid
响应式网格布局。
**使用示例:**
```vue
项目 1
项目 2
项目 3
```
---
#### StatCard
统计卡片,用于展示关键指标。
**使用示例:**
```vue
```
---
#### ShellHeader (待废弃)
旧版页面头部组件,建议迁移到 `PageHeader`。
---
### 业务组件 (Common Components)
位于 [src/components/common/](src/components/common/):
#### 1. PageLayout
页面布局容器,集成标题、筛选、分页等功能。
**使用示例:**
```vue
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `title` | `string` | - | 页面标题(必填) |
| `subtitle` | `string` | - | 页面副标题 |
| `showHeader` | `boolean` | `true` | 是否显示页面头部 |
| `showBackButton` | `boolean` | `false` | 是否显示返回按钮 |
| `maxWidth` | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'full'` | 内容最大宽度 |
| `spacing` | `'tight' \| 'normal' \| 'relaxed'` | `'normal'` | 内容间距 |
| `showFilters` | `boolean` | `false` | 是否显示筛选栏 |
| `showPagination` | `boolean` | `false` | 是否显示分页 |
**主要 Slots:**
- `toolbar` - 页面右上角工具栏
- `headerExtra` - 头部额外内容
- `filters` - 筛选条件
- `filterLeft` / `filterRight` - 筛选栏左右插槽
- `default` - 主内容区
- `footer` - 页面底部
---
#### 2. DataTable
响应式数据表格,桌面端显示表格,移动端自动切换为卡片视图。
**使用示例:**
```vue
{{ row.name }}
{{ row.email }}
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `columns` | `DataTableColumn[]` | - | 列配置(必填) |
| `data` | `T[]` | - | 数据源(必填) |
| `rowKey` | `string` | `'id'` | 行唯一标识字段 |
| `loading` | `boolean` | `false` | 是否加载中 |
| `clickable` | `boolean` | `false` | 是否可点击行 |
| `emptyTitle` | `string` | `'暂无数据'` | 空状态标题 |
**列配置(DataTableColumn):**
```ts
interface DataTableColumn {
key: string // 列标识(对应数据字段)
label: string // 列标题
width?: string // 列宽度
align?: 'left' | 'center' | 'right' // 对齐方式
sortable?: boolean // 是否可排序
formatter?: (value: any, row: T, index: number) => string // 值格式化
headerClass?: string // 表头样式类
cellClass?: string // 单元格样式类
showOnMobile?: boolean // 是否在移动端显示(默认 true)
}
```
**主要 Events:**
- `rowClick(row, index)` - 行点击事件
- `sort(sortBy, sortOrder)` - 排序事件
**主要 Slots:**
- `cell-{key}` - 自定义单元格内容(接收 `{ row, column, index, value }` 参数)
- `mobile-card` - 自定义移动端卡片布局(接收 `{ row, index }` 参数)
- `empty` - 自定义空状态
- `footer` - 表格底部内容
---
#### 3. SearchInput
智能搜索输入框,支持防抖、清除、建议列表。
**使用示例:**
```vue
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `modelValue` | `string` | - | 输入值(必填) |
| `placeholder` | `string` | `'搜索...'` | 占位符 |
| `clearable` | `boolean` | `true` | 是否显示清除按钮 |
| `loading` | `boolean` | `false` | 是否显示加载图标 |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 大小 |
| `suggestions` | `string[]` | `[]` | 搜索建议列表 |
| `debounce` | `number` | `300` | 防抖延迟(毫秒) |
---
#### 4. FilterBar
筛选栏容器,集成搜索和筛选条件。
**使用示例:**
```vue
```
---
#### 5. Pagination
分页组件,支持页码导航和每页数量选择。
**使用示例:**
```vue
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `currentPage` | `number` | `1` | 当前页码 |
| `pageSize` | `number` | `20` | 每页显示数量 |
| `total` | `number` | `0` | 总记录数 |
| `showPageSizeSelector` | `boolean` | `true` | 是否显示页面大小选择器 |
| `pageSizeOptions` | `number[]` | `[10, 20, 50, 100]` | 每页数量选项 |
---
#### 6. EmptyState
空状态组件,支持多种类型和自定义内容。
**使用示例:**
```vue
```
**类型(type):**
- `default` - 默认空状态
- `search` - 搜索无结果
- `filter` - 筛选无结果
- `error` - 加载错误
- `empty` - 空空如也
- `notFound` - 未找到资源
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `type` | `EmptyStateType` | `'default'` | 空状态类型 |
| `title` | `string` | - | 标题(自动根据类型设置) |
| `description` | `string` | - | 描述(自动根据类型设置) |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 大小 |
| `actionText` | `string` | - | 操作按钮文本 |
| `actionIcon` | `Component` | - | 操作按钮图标 |
| `actionVariant` | `ButtonVariant` | `'default'` | 按钮变体 |
---
#### 7. StatusBadge
状态徽章组件,用于显示不同状态。
**使用示例:**
```vue
```
**状态类型(status):**
| 状态 | 颜色 | 图标 | 用途 |
|------|------|------|------|
| `success` | 绿色 | CheckCircle2 | 成功、完成、已激活 |
| `error` | 红色 | XCircle | 错误、失败、已禁用 |
| `warning` | 黄色 | AlertCircle | 警告、待审核、需注意 |
| `info` | 蓝色 | Info | 信息、提示 |
| `pending` | 灰色 | Clock | 待处理、排队中 |
| `neutral` | 灰色 | Minus | 中性状态 |
| `active` | 主题色 | CheckCircle2 | 活跃、在线 |
| `inactive` | 灰色 | Minus | 未激活、离线 |
**变体(variant):**
- `solid` - 实心背景
- `soft` - 柔和背景(默认)
- `outline` - 描边样式
---
#### 8. LoadingState
加载状态组件,支持多种加载样式。
**使用示例:**
```vue
```
**变体(variant):**
- `spinner` - 旋转加载器(默认)
- `skeleton` - 骨架屏
- `pulse` - 脉冲点动画
---
#### 9. ConfirmButton
带确认对话框的按钮组件,简化危险操作的确认流程。
**使用示例:**
```vue
删除
重置
普通按钮
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `text` | `string` | - | 按钮文本 |
| `variant` | `ButtonVariant` | `'default'` | 按钮样式 |
| `size` | `ButtonSize` | `'md'` | 按钮大小 |
| `icon` | `Component` | - | 图标组件 |
| `disabled` | `boolean` | `false` | 是否禁用 |
| `confirmTitle` | `string` | `'确认操作'` | 确认对话框标题 |
| `confirmMessage` | `string` | `'确定要执行此操作吗?'` | 确认消息 |
| `confirmType` | `'default' \| 'danger' \| 'warning'` | `'default'` | 确认类型 |
| `requireConfirm` | `boolean` | `true` | 是否需要确认 |
**Events:**
- `click` - 不需要确认时触发
- `confirmed` - 确认后触发
- `cancelled` - 取消确认时触发
---
#### 10. ActionMenu
操作菜单下拉组件,用于集中展示多个操作选项。
**使用示例:**
```vue
```
**ActionMenuItem 接口:**
```ts
interface ActionMenuItem {
label?: string // 菜单项标签
icon?: Component // 图标
badge?: string | number // 徽章
variant?: 'default' | 'destructive' // 样式变体
disabled?: boolean // 是否禁用
separator?: boolean // 是否为分隔线
onClick?: () => void | Promise // 点击回调
}
```
**主要 Props:**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `items` | `ActionMenuItem[]` | - | 菜单项列表(必填) |
| `triggerText` | `string` | - | 触发按钮文本 |
| `triggerIcon` | `Component` | - | 触发按钮图标 |
| `triggerVariant` | `ButtonVariant` | `'outline'` | 触发按钮样式 |
| `triggerSize` | `ButtonSize` | `'sm'` | 触发按钮大小 |
| `showChevron` | `boolean` | `true` | 是否显示下拉箭头 |
| `placement` | `'bottom-start' \| 'bottom-end' \| 'top-start' \| 'top-end'` | `'bottom-end'` | 菜单位置 |
---
## 工具函数 (Composables)
位于 [src/composables/](src/composables/)
### useBreakpoints
响应式断点检测,用于实现响应式布局。
```ts
import { useBreakpoints } from '@/composables/useBreakpoints'
const {
windowWidth, // 窗口宽度
isSm, // >= 640px
isMd, // >= 768px
isLg, // >= 1024px
isXl, // >= 1280px
is2Xl, // >= 1536px
current, // 当前断点 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
isMobile, // < 768px
isTablet, // 768px ~ 1024px
isDesktop // >= 1024px
} = useBreakpoints()
// 示例:根据屏幕大小显示不同内容
移动端视图
平板视图
桌面视图
```
---
### useToast
消息提示管理,统一的 Toast 通知接口。
```ts
import { useToast } from '@/composables/useToast'
const { success, error, warning, info } = useToast()
// 成功消息(5秒后自动消失)
success('操作成功')
success('数据保存成功', '提示')
// 错误消息(8秒后自动消失)
error('操作失败')
error('保存失败,请检查网络连接', '错误')
// 警告消息(8秒后自动消失)
warning('该操作可能影响其他数据', '警告')
// 信息消息(5秒后自动消失)
info('系统将在 5 分钟后进行维护', '系统通知')
```
**接口定义:**
```ts
interface UseToast {
toasts: Ref
success(message: string, title?: string): string
error(message: string, title?: string): string
warning(message: string, title?: string): string
info(message: string, title?: string): string
showToast(options: Omit): string
removeToast(id: string): void
clearAll(): void
}
interface Toast {
id: string
title?: string
message?: string
variant?: 'success' | 'error' | 'warning' | 'info'
duration?: number
}
```
---
### useConfirm
确认对话框,用于危险操作确认。
```ts
import { useConfirm } from '@/composables/useConfirm'
const { confirm, confirmDanger, confirmWarning } = useConfirm()
// 普通确认
const ok = await confirm('确定要删除吗?', '确认删除')
if (ok) {
await deleteItem()
}
// 危险操作确认(红色按钮)
const ok = await confirmDanger(
'此操作不可撤销,确定继续吗?',
'删除确认'
)
// 警告确认(黄色主题)
const ok = await confirmWarning(
'该操作可能影响其他用户,是否继续?',
'警告'
)
```
---
### useClasses
类名工具函数,简化条件类名的生成。
```ts
import { useClasses } from '@/composables/useClasses'
const { cn, conditional, fromObject } = useClasses()
// 合并类名(过滤 falsy 值)
const className = cn(
'base-class',
isActive && 'active',
error && 'error',
'another-class'
)
// 结果: 'base-class active another-class' (假设 isActive=true, error=false)
// 条件类名
const className = conditional(isActive, 'bg-primary', 'bg-muted')
// 结果: isActive ? 'bg-primary' : 'bg-muted'
// 从对象生成类名
const className = fromObject({
'text-red-500': hasError,
'font-bold': isImportant,
'underline': isLink
})
// 结果: 只包含值为 true 的键
```
---
## 最佳实践
### 1. 组件开发规范
#### 使用 TypeScript
```vue
```
#### 遵循命名规范
- **组件文件**: PascalCase (如 `UserCard.vue`、`DataTable.vue`)
- **Composables**: camelCase + `use` 前缀 (如 `useAuth.ts`、`useBreakpoints.ts`)
- **工具函数**: camelCase (如 `formatDate.ts`、`validateEmail.ts`)
- **常量**: SCREAMING_SNAKE_CASE (如 `API_BASE_URL`、`MAX_FILE_SIZE`)
#### 合理使用插槽
```vue
默认标题
默认内容
```
#### 统一错误处理
```ts
import { useToast } from '@/composables/useToast'
import { apiClient } from '@/api/client'
const { error: showError, success: showSuccess } = useToast()
async function saveData() {
try {
await apiClient.post('/users', userData)
showSuccess('用户创建成功')
} catch (err: any) {
const message = err.response?.data?.detail || err.message || '操作失败'
showError(message, '错误')
console.error('Failed to create user:', err)
}
}
```
---
### 2. 样式规范
#### 优先使用 Tailwind 类
```vue
{{ user.name }}
{{ user.role }}
{{ user.active ? '在线' : '离线' }}
```
#### 使用主题 CSS 变量
```vue
```
#### 响应式设计
```vue
{{ item.name }}
移动端布局
桌面端布局
```
---
### 3. 性能优化
#### 按需导入组件
```ts
import { defineAsyncComponent } from 'vue'
// 异步加载重型组件
const HeavyChart = defineAsyncComponent(() =>
import('./components/HeavyChart.vue')
)
// 带加载状态的异步组件
const HeavyTable = defineAsyncComponent({
loader: () => import('./components/HeavyTable.vue'),
loadingComponent: LoadingState,
delay: 200,
errorComponent: ErrorState,
timeout: 3000
})
```
#### 使用 v-memo 优化列表
```vue
```
#### 虚拟滚动
对于超过 100 条的列表,使用虚拟滚动:
```bash
npm install vue-virtual-scroller
```
```vue
```
---
### 4. 可访问性 (a11y)
#### 语义化 HTML
```vue
页面标题
```
#### 键盘导航
```vue
自定义按钮
```
#### ARIA 属性
```vue
```
---
## 组件迁移检查清单
### 已完全迁移到 shadcn 的页面
- [x] Dashboard.vue
- [x] Users.vue
- [x] Settings.vue
- [x] SystemSettings.vue
- [x] Profile.vue
- [x] ActivityLogs.vue
- [x] Announcements.vue
- [x] ApiKeys.vue
- [x] AuditLogs.vue
- [x] MyApiKeys.vue
- [x] Usage.vue
- [x] ProviderList.vue
- [x] MyProviders.vue
- [x] CacheMonitoring.vue
- [x] ProviderDetailNew.vue
### 部分迁移或自定义样式
- [ ] Home.vue - 使用大量自定义动画和样式(不建议迁移)
---
## 更新日志
### v2.3.0 (2025-11-18)
**新增组件:**
- `ConfirmButton` - 带确认对话框的按钮组件
- `ActionMenu` - 操作菜单下拉组件
**优化导入系统:**
- 创建 `@/components/ui/index.ts` 统一导出所有 shadcn UI 组件
- 完善 `@/components/layout/index.ts` 和 `@/components/common/index.ts`
- 支持更简洁的组件导入方式
**导入方式优化:**
```ts
// 旧版导入 (繁琐)
import Button from '@/components/ui/button.vue'
import Input from '@/components/ui/input.vue'
import Card from '@/components/ui/card.vue'
// 新版导入 (推荐)
import { Button, Input, Card } from '@/components/ui'
import { PageHeader, Section, CardSection } from '@/components/layout'
import { DataTable, ConfirmButton, ActionMenu } from '@/components/common'
```
**文档:**
- 添加 `ConfirmButton` 和 `ActionMenu` 组件完整文档
- 更新组件导入最佳实践
### v2.2.0 (2025-11-18)
**重构:**
- 统一布局组件目录: 将 `layout-v2` 合并到 `layout`
- 所有布局组件现在从 `@/components/layout` 统一导入
- 删除冗余的 `layout-v2` 目录
**文档:**
- 添加完整的布局组件文档和使用示例
- 标记 `ShellHeader` 为待废弃组件
**迁移指南:**
```ts
// 旧版导入 (已废弃)
import { PageHeader } from '@/components/layout-v2'
// 新版导入 (推荐)
import { PageHeader } from '@/components/layout'
```
### v2.1.0 (2025-11-18)
**新增:**
- 完善所有组件文档和使用示例
- 添加完整的 TypeScript 类型定义
- 统一 Toast 工具函数接口(useToast)
- 完善响应式支持(useBreakpoints)
**修复:**
- 修复 CacheMonitoring.vue 的 toast 调用
- 统一所有页面的组件使用
**文档:**
- 更新所有组件的使用示例
- 添加最佳实践章节
- 添加性能优化指南
- 添加可访问性指南
### v2.0.0 (2025-11-17)
- 基础设计系统搭建
- 实现所有核心业务组件
- 建立主题系统
---
## 参考资源
- [shadcn/ui 官方文档](https://ui.shadcn.com/)
- [Tailwind CSS 文档](https://tailwindcss.com/docs)
- [Vue 3 文档](https://vuejs.org/)
- [Lucide Icons](https://lucide.dev/)
- [WCAG 2.1 标准](https://www.w3.org/WAI/WCAG21/quickref/)
- [主题配置文件](src/config/theme.ts)