---
name: design-system
description: "比赛管理系统设计规范。当用户提出页面开发需求时自动应用。主色: #0958d9 蓝色主题。包含: 颜色系统、间距、圆角、阴影、字体、组件规范（按钮、卡片、表单、标签）、页面布局、动画效果。适用: 新增页面、修改样式、组件开发、UI调整。"
---

# 比赛管理系统 - 设计规范 Skill

当用户提出页面开发、UI修改、组件创建等需求时，**必须遵循以下设计规范**。

---

## 快速开始

每个新页面的 `<style scoped lang="scss">` 开头必须包含以下变量：

```scss
// ==========================================
// 项目统一设计变量 - 必须复制
// ==========================================
$primary: #1890ff;
$primary-dark: #0958d9;
$primary-light: #40a9ff;
$secondary: #4096ff;
$success: #52c41a;
$warning: #faad14;
$error: #ff4d4f;

$background: #f5f7fa;
$surface: #ffffff;

$text: rgba(0, 0, 0, 0.85);
$text-secondary: rgba(0, 0, 0, 0.65);
$text-muted: rgba(0, 0, 0, 0.45);

$border: #d9d9d9;
$border-light: #e8e8e8;

$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
```

---

## 色彩系统

### 主色（蓝色主题）

| 变量 | 色值 | 用途 |
|------|------|------|
| `$primary` | `#1890ff` | 主色、按钮、链接 |
| `$primary-dark` | `#0958d9` | 渐变深色、激活态 |
| `$primary-light` | `#40a9ff` | 悬停态、浅色 |
| `$secondary` | `#4096ff` | 辅助蓝 |

### 功能色

| 变量 | 色值 | 用途 |
|------|------|------|
| `$success` | `#52c41a` | 成功状态 |
| `$warning` | `#faad14` | 警告状态 |
| `$error` | `#ff4d4f` | 错误状态 |

### 中性色

| 变量 | 色值 | 用途 |
|------|------|------|
| `$background` | `#f5f5f5` | 页面背景 |
| `$surface` | `#ffffff` | 卡片/容器背景 |
| `$text` | `rgba(0,0,0,0.85)` | 主文本 |
| `$text-secondary` | `rgba(0,0,0,0.65)` | 次要文本 |
| `$text-muted` | `rgba(0,0,0,0.45)` | 弱化文本 |
| `$border-light` | `#e8e8e8` | 边框 |

---

## 间距规范

基于 **8px** 基准：

| 尺寸 | 值 | 场景 |
|------|------|------|
| xs | 4px | 图标间距 |
| sm | 8px | 元素内间距 |
| md | 12px | 卡片内元素 |
| base | 16px | 最常用 |
| lg | 20px | 区块间距 |
| xl | 24px | 大间距 |
| 2xl | 32px | 模块分隔 |

---

## 圆角规范

| 尺寸 | 值 | 场景 |
|------|------|------|
| sm | 4px | 小元素 |
| base | 6px | 默认 |
| md | 8px | 卡片 |
| lg | 10px | 返回按钮 |
| xl | 12px | 大卡片 |
| pill | 20px | 标签 |
| full | 50% | 头像 |

---

## 阴影规范

| 等级 | 定义 | 场景 |
|------|------|------|
| sm | `0 1px 2px rgba(0,0,0,0.03)` | 轻微 |
| base | `0 2px 8px rgba(0,0,0,0.06)` | 卡片默认 |
| md | `0 4px 12px rgba(0,0,0,0.08)` | 悬停 |
| lg | `0 8px 24px rgba(0,0,0,0.12)` | 弹窗 |

---

## 字体规范

| 层级 | 大小 | 权重 | 场景 |
|------|------|------|------|
| h1 | 36px | 700 | 大标题 |
| h2 | 26px | 700 | 区块标题 |
| h3 | 22px | 600 | 卡片标题 |
| h4 | 18px | 600 | 小标题 |
| body | 14px | 400 | 正文 |
| small | 12px | 400 | 标签 |

---

## 组件规范

### 返回按钮（统一样式）

```scss
.back-btn {
  width: 40px;
  height: 40px;
  border-radius: 10px !important;
  border: 1px solid rgba($primary, 0.3) !important;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease !important;

  &:hover {
    background: rgba($primary, 0.1) !important;
    border-color: $primary !important;
    transform: translateY(-1px);
  }
}
```

模板代码：
```vue
<a-button type="text" class="back-btn" @click="handleBack">
  <template #icon><ArrowLeftOutlined /></template>
</a-button>
```

### 主按钮（渐变样式）

```scss
.primary-btn,
.gradient-btn {
  background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
  border: none !important;
  color: #fff !important;
  font-weight: 500 !important;
  border-radius: 20px !important;
  padding: 6px 16px !important;
  transition: all 0.3s ease !important;
  box-shadow: 0 2px 8px rgba($primary, 0.3);

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba($primary, 0.4);
  }
}

// 用于 hero 区域的大按钮
.action-btn.primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 28px;
  border-radius: 24px;
  font-size: 15px;
  font-weight: 600;
  background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
  color: #fff;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 15px rgba($primary, 0.4);
  transition: all 0.3s;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba($primary, 0.5);
  }
}
```

### 卡片

```scss
.card {
  background: $surface;
  border: 1px solid $border-light;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  transition: all 0.3s ease;

  &:hover {
    border-color: rgba($primary, 0.3);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transform: translateY(-4px);
  }
}
```

### 标签

```scss
.tag {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;

  &.tag-success {
    background: rgba($success, 0.1);
    color: $success;
    border: 1px solid rgba($success, 0.3);
  }

  &.tag-primary {
    background: rgba($primary, 0.1);
    color: $primary;
    border: 1px solid rgba($primary, 0.3);
  }

  &.tag-error {
    background: rgba($error, 0.1);
    color: $error;
    border: 1px solid rgba($error, 0.3);
  }
}
```

### 面板/浮层

```scss
.panel {
  background: rgba($surface, 0.85);
  backdrop-filter: blur(20px);
  border: 1px solid rgba($primary, 0.2);
  border-radius: 12px;

  .panel-header {
    padding: 14px 16px;
    background: rgba($primary, 0.05);
    border-bottom: 1px solid rgba($primary, 0.1);
  }

  .panel-body {
    padding: 16px;
  }
}
```

---

## 页面布局规范

### 页面头部（64px 高）

```scss
.page-header {
  height: 64px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: $surface;
  border-bottom: 1px solid #e8e8e8;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
  position: relative;
  z-index: 10;

  .header-left {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .title {
    font-size: 18px;
    font-weight: 600;
    background: $gradient-primary;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
  }
}
```

### 全屏页面容器

```scss
.fullscreen-page {
  min-height: 100vh;
  background: $background;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}

.page-content {
  flex: 1;
  padding: 24px;
  overflow: auto;
}
```

### 卡片网格

```scss
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}
```

---

## 动画规范

### 过渡时间

- 标准过渡：`0.3s ease`
- 所有交互元素必须添加过渡

### 悬停效果

```scss
// 卡片悬停
transform: translateY(-4px);

// 按钮悬停
transform: translateY(-2px);

// 小元素悬停
transform: translateY(-1px);
```

### 常用动画

```scss
// 脉冲
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.5; transform: scale(0.8); }
}

// 旋转
@keyframes spin {
  to { transform: rotate(360deg); }
}
```

---

## 加载/错误状态

### 加载遮罩

```scss
.loading-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: $background;
  z-index: 10;
}
```

### 错误卡片

```scss
.error-card {
  text-align: center;
  padding: 40px;
  background: $surface;
  border: 1px solid #e8e8e8;
  border-radius: 16px;

  .error-icon {
    width: 60px;
    height: 60px;
    margin: 0 auto 20px;
    background: $error;
    border-radius: 50%;
    color: #fff;
  }
}
```

---

## 滚动条

```scss
&::-webkit-scrollbar {
  width: 6px;
}
&::-webkit-scrollbar-track {
  background: rgba($primary, 0.05);
}
&::-webkit-scrollbar-thumb {
  background: rgba($primary, 0.3);
  border-radius: 3px;
}
```

---

## 响应式断点

```scss
$breakpoint-sm: 640px;
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
$breakpoint-xl: 1280px;
```

---

## 开发检查清单

新增页面必须确认：

- [ ] 复制了颜色变量到 style 开头
- [ ] 返回按钮使用 40x40px + 10px 圆角
- [ ] 卡片悬停有 `translateY(-4px)` 效果
- [ ] 页面头部高度 64px
- [ ] 所有过渡动画 0.3s
- [ ] 使用 `$gradient-primary` 作为主渐变
- [ ] 加载状态使用蓝色系

---

## 参考页面

- `frontend/src/views/workbench/ai-3d/Index.vue` - 3D Lab 主页
- `frontend/src/views/workbench/ai-3d/Generate.vue` - 生成页
- `frontend/src/views/model/ModelViewer.vue` - 模型预览页
