759 lines
13 KiB
Markdown
759 lines
13 KiB
Markdown
# UI设计规范文档
|
||
|
||
## 1. 设计系统概述
|
||
|
||
本系统采用Ant Design风格,简洁专业,适合企业级应用。
|
||
|
||
## 2. 颜色系统
|
||
|
||
### 2.1 主色调
|
||
```css
|
||
/* 主品牌色 - 蓝色 */
|
||
--primary-color: #1890ff;
|
||
|
||
/* 功能色 */
|
||
--success-color: #52c41a; /* 成功/进行中 */
|
||
--warning-color: #fa8c16; /* 警告/暂停 */
|
||
--error-color: #ff4d4f; /* 错误/删除 */
|
||
--info-color: #1890ff; /* 信息/新建 */
|
||
```
|
||
|
||
### 2.2 中性色
|
||
```css
|
||
--text-primary: #333333; /* 主要文字 */
|
||
--text-secondary: #666666; /* 次要文字 */
|
||
--text-disabled: #999999; /* 禁用文字 */
|
||
--border-color: #e8e8e8; /* 边框颜色 */
|
||
--divider-color: #f0f0f0; /* 分割线颜色 */
|
||
```
|
||
|
||
### 2.3 背景色
|
||
```css
|
||
--layout-header-bg: #001529; /* 顶部导航背景 */
|
||
--layout-sidebar-bg: #ffffff; /* 侧边栏背景 */
|
||
--layout-content-bg: #f0f2f5; /* 内容区背景 */
|
||
--component-bg: #ffffff; /* 组件背景 */
|
||
```
|
||
|
||
## 3. 状态标签颜色
|
||
|
||
| 状态 | 背景色 | 文字颜色 | 适用场景 |
|
||
|------|--------|----------|----------|
|
||
| 新建 | #e6f7ff | #1890ff | 项目初始状态 |
|
||
| 进行中 | #f6ffed | #52c41a | 项目执行中 |
|
||
| 已完成 | #f5f5f5 | #999999 | 项目完成 |
|
||
| 已暂停 | #fff7e6 | #fa8c16 | 项目暂停 |
|
||
| 已取消 | #fff1f0 | #f5222d | 项目取消 |
|
||
| 正常 | #f6ffed | #52c41a | 用户状态正常 |
|
||
| 禁用 | #f5f5f5 | #999999 | 用户状态禁用 |
|
||
| 管理员 | #fff1f0 | #f5222d | 管理员角色 |
|
||
| 市场部 | #e6f7ff | #1890ff | 市场部角色 |
|
||
| 其他部门 | #e6f7ff | #1890ff | 其他部门角色 |
|
||
|
||
## 4. 字体系统
|
||
|
||
```css
|
||
/* 字体家族 */
|
||
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
|
||
/* 字体大小 */
|
||
--font-size-base: 14px;
|
||
--font-size-lg: 16px;
|
||
--font-size-sm: 12px;
|
||
--font-size-title: 18px;
|
||
--font-size-heading: 24px;
|
||
|
||
/* 字重 */
|
||
--font-weight-normal: 400;
|
||
--font-weight-medium: 500;
|
||
--font-weight-semibold: 600;
|
||
--font-weight-bold: 700;
|
||
```
|
||
|
||
## 5. 间距系统
|
||
|
||
```css
|
||
--spacing-xs: 4px;
|
||
--spacing-sm: 8px;
|
||
--spacing-md: 12px;
|
||
--spacing-lg: 16px;
|
||
--spacing-xl: 24px;
|
||
--spacing-xxl: 32px;
|
||
```
|
||
|
||
## 6. 组件样式
|
||
|
||
### 6.1 按钮
|
||
|
||
```css
|
||
/* 主按钮 */
|
||
.btn-primary {
|
||
background-color: #1890ff;
|
||
color: #ffffff;
|
||
border: none;
|
||
padding: 6px 16px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background-color: #40a9ff;
|
||
}
|
||
|
||
/* 默认按钮 */
|
||
.btn-default {
|
||
background-color: #ffffff;
|
||
color: #666666;
|
||
border: 1px solid #d9d9d9;
|
||
padding: 6px 16px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.btn-default:hover {
|
||
border-color: #1890ff;
|
||
color: #1890ff;
|
||
}
|
||
|
||
/* 链接按钮 */
|
||
.btn-link {
|
||
background: none;
|
||
color: #1890ff;
|
||
border: none;
|
||
padding: 0 8px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.btn-link:hover {
|
||
color: #40a9ff;
|
||
}
|
||
|
||
/* 危险按钮 */
|
||
.btn-danger {
|
||
background: none;
|
||
color: #ff4d4f;
|
||
border: none;
|
||
padding: 0 8px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
color: #ff7875;
|
||
}
|
||
```
|
||
|
||
### 6.2 输入框
|
||
|
||
```css
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 8px 12px;
|
||
border: 1px solid #d9d9d9;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
color: #333333;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.form-input:focus {
|
||
border-color: #1890ff;
|
||
outline: none;
|
||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||
}
|
||
|
||
.form-input::placeholder {
|
||
color: #cccccc;
|
||
}
|
||
```
|
||
|
||
### 6.3 选择框
|
||
|
||
```css
|
||
.form-select {
|
||
width: 100%;
|
||
padding: 8px 12px;
|
||
border: 1px solid #d9d9d9;
|
||
border-radius: 4px;
|
||
font-size: 14px;
|
||
color: #333333;
|
||
background-color: #ffffff;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.form-select:focus {
|
||
border-color: #1890ff;
|
||
outline: none;
|
||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||
}
|
||
```
|
||
|
||
### 6.4 卡片
|
||
|
||
```css
|
||
.card {
|
||
background: #ffffff;
|
||
border-radius: 8px;
|
||
padding: 24px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
margin-bottom: 20px;
|
||
border-bottom: 1px solid #e8e8e8;
|
||
padding-bottom: 12px;
|
||
}
|
||
```
|
||
|
||
### 6.5 表格
|
||
|
||
```css
|
||
.table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
.table thead th {
|
||
background: #fafafa;
|
||
padding: 12px 16px;
|
||
text-align: left;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
border-bottom: 1px solid #e8e8e8;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.table tbody td {
|
||
padding: 12px 16px;
|
||
border-bottom: 1px solid #e8e8e8;
|
||
color: #666666;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.table tbody tr:hover {
|
||
background: #fafafa;
|
||
}
|
||
```
|
||
|
||
### 6.6 标签
|
||
|
||
```css
|
||
.tag {
|
||
display: inline-block;
|
||
padding: 2px 8px;
|
||
border-radius: 2px;
|
||
font-size: 12px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.tag-blue {
|
||
background: #e6f7ff;
|
||
border: 1px solid #91d5ff;
|
||
color: #1890ff;
|
||
}
|
||
|
||
.tag-green {
|
||
background: #f6ffed;
|
||
border: 1px solid #b7eb8f;
|
||
color: #52c41a;
|
||
}
|
||
|
||
.tag-orange {
|
||
background: #fff7e6;
|
||
border: 1px solid #ffd591;
|
||
color: #fa8c16;
|
||
}
|
||
|
||
.tag-red {
|
||
background: #fff1f0;
|
||
border: 1px solid #ffa39e;
|
||
color: #f5222d;
|
||
}
|
||
|
||
.tag-gray {
|
||
background: #f5f5f5;
|
||
border: 1px solid #d9d9d9;
|
||
color: #999999;
|
||
}
|
||
```
|
||
|
||
### 6.7 头像
|
||
|
||
```css
|
||
.avatar {
|
||
width: 32px;
|
||
height: 32px;
|
||
background: #1890ff;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
color: #ffffff;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.avatar-lg {
|
||
width: 64px;
|
||
height: 64px;
|
||
font-size: 24px;
|
||
}
|
||
```
|
||
|
||
## 7. 布局系统
|
||
|
||
### 7.1 整体布局
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ Header (顶部导航) │
|
||
│ #001529 │
|
||
├──────────┬──────────────────────────────┤
|
||
│ │ │
|
||
│ Sidebar │ Content │
|
||
│ (侧边栏) │ (内容区) │
|
||
│ #ffffff │ #f0f2f5 │
|
||
│ 256px │ │
|
||
│ │ │
|
||
└──────────┴──────────────────────────────┘
|
||
```
|
||
|
||
### 7.2 顶部导航栏
|
||
|
||
```css
|
||
.layout-header {
|
||
height: 64px;
|
||
background: #001529;
|
||
padding: 0 24px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 1000;
|
||
}
|
||
```
|
||
|
||
### 7.3 侧边栏
|
||
|
||
```css
|
||
.layout-sider {
|
||
width: 256px;
|
||
background: #ffffff;
|
||
border-right: 1px solid #e8e8e8;
|
||
position: fixed;
|
||
left: 64px;
|
||
top: 64px;
|
||
bottom: 0;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* 菜单项 */
|
||
.menu-item {
|
||
padding: 12px 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
color: #666666;
|
||
cursor: pointer;
|
||
border-left: 3px solid transparent;
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.menu-item:hover {
|
||
background: #e6f7ff;
|
||
color: #1890ff;
|
||
}
|
||
|
||
.menu-item.active {
|
||
background: #e6f7ff;
|
||
color: #1890ff;
|
||
border-left-color: #1890ff;
|
||
}
|
||
```
|
||
|
||
### 7.4 内容区
|
||
|
||
```css
|
||
.layout-content {
|
||
margin-left: 256px;
|
||
margin-top: 64px;
|
||
padding: 24px;
|
||
background: #f0f2f5;
|
||
min-height: calc(100vh - 64px);
|
||
}
|
||
```
|
||
|
||
## 8. 统计卡片
|
||
|
||
```css
|
||
.stat-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 24px;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.stat-card {
|
||
background: #ffffff;
|
||
padding: 24px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 14px;
|
||
color: #666666;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 32px;
|
||
font-weight: 600;
|
||
color: #1890ff;
|
||
}
|
||
|
||
.stat-icon {
|
||
float: right;
|
||
font-size: 24px;
|
||
color: #1890ff;
|
||
opacity: 0.3;
|
||
}
|
||
```
|
||
|
||
## 9. 表单系统
|
||
|
||
### 9.1 表单组
|
||
|
||
```css
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
color: #333333;
|
||
font-weight: 500;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.form-label.required::after {
|
||
content: ' *';
|
||
color: #ff4d4f;
|
||
}
|
||
```
|
||
|
||
### 9.2 表单行(两列布局)
|
||
|
||
```css
|
||
.form-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 20px;
|
||
}
|
||
|
||
.form-row-3 {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20px;
|
||
}
|
||
```
|
||
|
||
## 10. 工具栏
|
||
|
||
```css
|
||
.toolbar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.toolbar-left {
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
}
|
||
```
|
||
|
||
## 11. Modal 弹窗
|
||
|
||
```css
|
||
.modal-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.45);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.modal {
|
||
background: #ffffff;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
width: 600px;
|
||
max-width: 90vw;
|
||
max-height: 90vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.modal-header {
|
||
padding: 16px 24px;
|
||
border-bottom: 1px solid #e8e8e8;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
}
|
||
|
||
.modal-body {
|
||
padding: 24px;
|
||
}
|
||
|
||
.modal-footer {
|
||
padding: 16px 24px;
|
||
border-top: 1px solid #e8e8e8;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 12px;
|
||
}
|
||
```
|
||
|
||
## 12. 响应式设计
|
||
|
||
```css
|
||
/* 平板 */
|
||
@media (max-width: 1024px) {
|
||
.stat-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
|
||
/* 移动端 */
|
||
@media (max-width: 768px) {
|
||
.layout-sider {
|
||
width: 200px;
|
||
}
|
||
|
||
.layout-content {
|
||
margin-left: 200px;
|
||
}
|
||
|
||
.stat-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.form-row {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.table {
|
||
font-size: 12px;
|
||
}
|
||
|
||
.toolbar {
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
align-items: stretch;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 13. 动画效果
|
||
|
||
```css
|
||
/* 过渡动画 */
|
||
.transition-all {
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* 悬停效果 */
|
||
.hover-scale:hover {
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
.hover-shadow:hover {
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
/* 淡入淡出 */
|
||
.fade-in {
|
||
animation: fadeIn 0.3s ease-in-out;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
```
|
||
|
||
## 14. React 组件实现参考
|
||
|
||
### 14.1 颜色配置 (config/colors.js)
|
||
|
||
```javascript
|
||
export const colors = {
|
||
primary: '#1890ff',
|
||
success: '#52c41a',
|
||
warning: '#fa8c16',
|
||
error: '#ff4d4f',
|
||
info: '#1890ff',
|
||
|
||
text: {
|
||
primary: '#333333',
|
||
secondary: '#666666',
|
||
disabled: '#999999',
|
||
},
|
||
|
||
border: {
|
||
base: '#e8e8e8',
|
||
light: '#f0f0f0',
|
||
},
|
||
|
||
bg: {
|
||
header: '#001529',
|
||
sidebar: '#ffffff',
|
||
content: '#f0f2f5',
|
||
component: '#ffffff',
|
||
},
|
||
};
|
||
```
|
||
|
||
### 14.2 状态标签组件 (components/Tag.jsx)
|
||
|
||
```jsx
|
||
import React from 'react';
|
||
import { colors } from '../config/colors';
|
||
|
||
const tagStyles = {
|
||
new: { bg: '#e6f7ff', color: '#1890ff', border: '#91d5ff' },
|
||
inProgress: { bg: '#f6ffed', color: '#52c41a', border: '#b7eb8f' },
|
||
completed: { bg: '#f5f5f5', color: '#999999', border: '#d9d9d9' },
|
||
paused: { bg: '#fff7e6', color: '#fa8c16', border: '#ffd591' },
|
||
cancelled: { bg: '#fff1f0', color: '#f5222d', border: '#ffa39e' },
|
||
};
|
||
|
||
export const Tag = ({ children, type = 'default' }) => {
|
||
const style = tagStyles[type] || { bg: '#f5f5f5', color: '#999999', border: '#d9d9d9' };
|
||
|
||
return (
|
||
<span style={{
|
||
display: 'inline-block',
|
||
padding: '2px 8px',
|
||
borderRadius: '2px',
|
||
fontSize: '12px',
|
||
lineHeight: 1.5,
|
||
background: style.bg,
|
||
color: style.color,
|
||
border: `1px solid ${style.border}`,
|
||
}}>
|
||
{children}
|
||
</span>
|
||
);
|
||
};
|
||
```
|
||
|
||
### 14.3 卡片组件 (components/Card.jsx)
|
||
|
||
```jsx
|
||
import React from 'react';
|
||
|
||
export const Card = ({ title, children, extra }) => (
|
||
<div style={{
|
||
background: '#ffffff',
|
||
borderRadius: '8px',
|
||
padding: '24px',
|
||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
|
||
marginBottom: '24px',
|
||
}}>
|
||
{title && (
|
||
<div style={{
|
||
fontSize: '16px',
|
||
fontWeight: 600,
|
||
color: '#333333',
|
||
marginBottom: '20px',
|
||
borderBottom: '1px solid #e8e8e8',
|
||
paddingBottom: '12px',
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
}}>
|
||
{title}
|
||
{extra}
|
||
</div>
|
||
)}
|
||
{children}
|
||
</div>
|
||
);
|
||
```
|
||
|
||
## 15. 图标使用
|
||
|
||
推荐使用以下图标库:
|
||
- **Ant Design Icons**:`@ant-design/icons`
|
||
- **React Icons**:`react-icons`
|
||
|
||
常用图标:
|
||
- Dashboard: `DashboardOutlined`
|
||
- Project: `FileTextOutlined`
|
||
- User: `UserOutlined`
|
||
- Settings: `SettingOutlined`
|
||
- Add: `PlusOutlined`
|
||
- Edit: `EditOutlined`
|
||
- Delete: `DeleteOutlined`
|
||
- View: `EyeOutlined`
|
||
- Logout: `LogoutOutlined`
|
||
|
||
## 16. 页面布局模板
|
||
|
||
```jsx
|
||
import React from 'react';
|
||
|
||
const PageLayout = ({ children, title }) => (
|
||
<div style={{
|
||
marginLeft: '256px',
|
||
marginTop: '64px',
|
||
padding: '24px',
|
||
background: '#f0f2f5',
|
||
minHeight: 'calc(100vh - 64px)',
|
||
}}>
|
||
{title && (
|
||
<h1 style={{
|
||
fontSize: '24px',
|
||
fontWeight: 600,
|
||
color: '#333333',
|
||
marginBottom: '24px',
|
||
}}>
|
||
{title}
|
||
</h1>
|
||
)}
|
||
{children}
|
||
</div>
|
||
);
|
||
```
|
||
|
||
## 17. 注意事项
|
||
|
||
1. **颜色使用**:统一使用预定义的颜色变量,不要使用硬编码的颜色值
|
||
2. **间距统一**:使用间距系统保持一致性
|
||
3. **响应式**:移动端、平板、桌面端都要适配
|
||
4. **可访问性**:确保对比度符合WCAG标准,最小对比度4.5:1
|
||
5. **性能**:避免过度使用动画,保持流畅的用户体验
|
||
6. **浏览器兼容**:确保在主流浏览器中正常显示
|