563 lines
11 KiB
Markdown
563 lines
11 KiB
Markdown
|
|
# 开发文档
|
||
|
|
|
||
|
|
## 开发环境搭建
|
||
|
|
|
||
|
|
### 环境要求
|
||
|
|
|
||
|
|
- **Node.js**: 18.0.0 或更高版本
|
||
|
|
- **pnpm**: 8.0.0 或更高版本
|
||
|
|
- **Git**: 2.0.0 或更高版本
|
||
|
|
|
||
|
|
### 安装步骤
|
||
|
|
|
||
|
|
1. **安装 Node.js**
|
||
|
|
```bash
|
||
|
|
# 下载并安装 Node.js 18+
|
||
|
|
# 验证安装
|
||
|
|
node --version
|
||
|
|
npm --version
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **安装 pnpm**
|
||
|
|
```bash
|
||
|
|
# 使用 npm 安装 pnpm
|
||
|
|
npm install -g pnpm
|
||
|
|
|
||
|
|
# 验证安装
|
||
|
|
pnpm --version
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **克隆项目**
|
||
|
|
```bash
|
||
|
|
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||
|
|
cd vue-vben-admin
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **安装依赖**
|
||
|
|
```bash
|
||
|
|
# 安装项目依赖
|
||
|
|
pnpm install
|
||
|
|
```
|
||
|
|
|
||
|
|
5. **启动开发服务器**
|
||
|
|
```bash
|
||
|
|
# 启动 Ant Design 版本
|
||
|
|
pnpm dev:antd
|
||
|
|
|
||
|
|
# 启动 Element Plus 版本
|
||
|
|
pnpm dev:ele
|
||
|
|
|
||
|
|
# 启动 Naive UI 版本
|
||
|
|
pnpm dev:naive
|
||
|
|
```
|
||
|
|
|
||
|
|
## 项目结构说明
|
||
|
|
|
||
|
|
### 目录结构详解
|
||
|
|
|
||
|
|
```
|
||
|
|
yudao-ui-admin-vben/
|
||
|
|
├── apps/ # 应用目录
|
||
|
|
│ ├── web-antd/ # Ant Design 版本
|
||
|
|
│ │ ├── src/ # 源代码
|
||
|
|
│ │ │ ├── api/ # API 接口
|
||
|
|
│ │ │ ├── components/ # 组件
|
||
|
|
│ │ │ ├── layouts/ # 布局
|
||
|
|
│ │ │ ├── router/ # 路由
|
||
|
|
│ │ │ ├── store/ # 状态管理
|
||
|
|
│ │ │ ├── utils/ # 工具函数
|
||
|
|
│ │ │ └── views/ # 页面视图
|
||
|
|
│ │ └── package.json # 应用配置
|
||
|
|
│ ├── web-ele/ # Element Plus 版本
|
||
|
|
│ ├── web-naive/ # Naive UI 版本
|
||
|
|
│ └── backend-mock/ # 后端模拟服务
|
||
|
|
├── packages/ # 共享包目录
|
||
|
|
│ ├── @core/ # 核心功能
|
||
|
|
│ ├── constants/ # 常量定义
|
||
|
|
│ ├── effects/ # 副作用管理
|
||
|
|
│ ├── icons/ # 图标库
|
||
|
|
│ ├── locales/ # 国际化
|
||
|
|
│ ├── stores/ # 状态管理
|
||
|
|
│ ├── styles/ # 样式文件
|
||
|
|
│ ├── types/ # 类型定义
|
||
|
|
│ └── utils/ # 工具函数
|
||
|
|
└── internal/ # 内部配置
|
||
|
|
├── lint-configs/ # 代码规范
|
||
|
|
├── tailwind-config/ # Tailwind 配置
|
||
|
|
├── tsconfig/ # TypeScript 配置
|
||
|
|
└── vite-config/ # Vite 配置
|
||
|
|
```
|
||
|
|
|
||
|
|
### 核心包说明
|
||
|
|
|
||
|
|
#### @core 包
|
||
|
|
- 基础组件封装
|
||
|
|
- 工具函数集合
|
||
|
|
- 类型定义扩展
|
||
|
|
|
||
|
|
#### stores 包
|
||
|
|
- 全局状态管理
|
||
|
|
- 用户信息存储
|
||
|
|
- 应用配置管理
|
||
|
|
|
||
|
|
#### utils 包
|
||
|
|
- 数据处理工具
|
||
|
|
- 日期时间工具
|
||
|
|
- 表单验证工具
|
||
|
|
|
||
|
|
## 开发规范
|
||
|
|
|
||
|
|
### 代码规范
|
||
|
|
|
||
|
|
#### 1. 命名规范
|
||
|
|
- **文件命名**: 使用 kebab-case (例如: user-info.vue)
|
||
|
|
- **组件命名**: 使用 PascalCase (例如: UserInfo)
|
||
|
|
- **变量命名**: 使用 camelCase (例如: userName)
|
||
|
|
- **常量命名**: 使用 UPPER_SNAKE_CASE (例如: API_BASE_URL)
|
||
|
|
|
||
|
|
#### 2. 组件规范
|
||
|
|
```typescript
|
||
|
|
// 组件结构示例
|
||
|
|
<script setup lang="ts">
|
||
|
|
// 导入
|
||
|
|
import { ref, computed } from 'vue'
|
||
|
|
import { useUserStore } from '@/stores/user'
|
||
|
|
|
||
|
|
// 类型定义
|
||
|
|
interface Props {
|
||
|
|
userId: number
|
||
|
|
userName: string
|
||
|
|
}
|
||
|
|
|
||
|
|
// Props 定义
|
||
|
|
const props = defineProps<Props>()
|
||
|
|
|
||
|
|
// 状态管理
|
||
|
|
const userStore = useUserStore()
|
||
|
|
const loading = ref(false)
|
||
|
|
|
||
|
|
// 计算属性
|
||
|
|
const fullName = computed(() => `${props.userName} (${props.userId})`)
|
||
|
|
|
||
|
|
// 方法
|
||
|
|
const handleSubmit = async () => {
|
||
|
|
loading.value = true
|
||
|
|
try {
|
||
|
|
await userStore.updateUser(props.userId, { name: props.userName })
|
||
|
|
} finally {
|
||
|
|
loading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="user-info">
|
||
|
|
<h3>{{ fullName }}</h3>
|
||
|
|
<button :disabled="loading" @click="handleSubmit">
|
||
|
|
{{ loading ? '保存中...' : '保存' }}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.user-info {
|
||
|
|
padding: 16px;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 3. API 调用规范
|
||
|
|
```typescript
|
||
|
|
// api/user.ts
|
||
|
|
import { request } from '@/utils/request'
|
||
|
|
|
||
|
|
export interface User {
|
||
|
|
id: number
|
||
|
|
name: string
|
||
|
|
email: string
|
||
|
|
}
|
||
|
|
|
||
|
|
export const userApi = {
|
||
|
|
// 获取用户列表
|
||
|
|
getUsers: (params: { page: number; size: number }) => {
|
||
|
|
return request.get<{ list: User[]; total: number }>('/api/users', { params })
|
||
|
|
},
|
||
|
|
|
||
|
|
// 创建用户
|
||
|
|
createUser: (data: Omit<User, 'id'>) => {
|
||
|
|
return request.post<User>('/api/users', data)
|
||
|
|
},
|
||
|
|
|
||
|
|
// 更新用户
|
||
|
|
updateUser: (id: number, data: Partial<User>) => {
|
||
|
|
return request.put<User>(`/api/users/${id}`, data)
|
||
|
|
},
|
||
|
|
|
||
|
|
// 删除用户
|
||
|
|
deleteUser: (id: number) => {
|
||
|
|
return request.delete(`/api/users/${id}`)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 样式规范
|
||
|
|
|
||
|
|
#### 1. CSS 类命名
|
||
|
|
- 使用 BEM 命名规范
|
||
|
|
- 避免使用全局样式
|
||
|
|
- 优先使用 Tailwind CSS
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* BEM 示例 */
|
||
|
|
.user-list {}
|
||
|
|
.user-list__item {}
|
||
|
|
.user-list__item--active {}
|
||
|
|
.user-list__item__avatar {}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 2. Tailwind CSS 使用
|
||
|
|
```vue
|
||
|
|
<template>
|
||
|
|
<div class="p-4 bg-white rounded-lg shadow-sm">
|
||
|
|
<h3 class="text-lg font-semibold text-gray-900 mb-4">用户信息</h3>
|
||
|
|
<div class="space-y-3">
|
||
|
|
<div class="flex items-center space-x-3">
|
||
|
|
<span class="text-sm text-gray-500 w-20">姓名:</span>
|
||
|
|
<span class="text-sm text-gray-900">{{ user.name }}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
```
|
||
|
|
|
||
|
|
## 功能开发指南
|
||
|
|
|
||
|
|
### 1. 新增页面
|
||
|
|
|
||
|
|
#### 步骤 1: 创建页面组件
|
||
|
|
```bash
|
||
|
|
# 在 apps/web-antd/src/views/ 下创建页面目录
|
||
|
|
mkdir -p apps/web-antd/src/views/user-management
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 步骤 2: 创建页面组件
|
||
|
|
```vue
|
||
|
|
<!-- apps/web-antd/src/views/user-management/index.vue -->
|
||
|
|
<script setup lang="ts">
|
||
|
|
import { ref, onMounted } from 'vue'
|
||
|
|
import { userApi } from '@/api/user'
|
||
|
|
|
||
|
|
interface User {
|
||
|
|
id: number
|
||
|
|
name: string
|
||
|
|
email: string
|
||
|
|
}
|
||
|
|
|
||
|
|
const users = ref<User[]>([])
|
||
|
|
const loading = ref(false)
|
||
|
|
|
||
|
|
const loadUsers = async () => {
|
||
|
|
loading.value = true
|
||
|
|
try {
|
||
|
|
const response = await userApi.getUsers({ page: 1, size: 10 })
|
||
|
|
users.value = response.data.list
|
||
|
|
} finally {
|
||
|
|
loading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
loadUsers()
|
||
|
|
})
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="user-management">
|
||
|
|
<h1>用户管理</h1>
|
||
|
|
<div v-if="loading">加载中...</div>
|
||
|
|
<div v-else>
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>ID</th>
|
||
|
|
<th>姓名</th>
|
||
|
|
<th>邮箱</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr v-for="user in users" :key="user.id">
|
||
|
|
<td>{{ user.id }}</td>
|
||
|
|
<td>{{ user.name }}</td>
|
||
|
|
<td>{{ user.email }}</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.user-management {
|
||
|
|
padding: 20px;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 步骤 3: 配置路由
|
||
|
|
```typescript
|
||
|
|
// apps/web-antd/src/router/routes.ts
|
||
|
|
import type { RouteRecordRaw } from 'vue-router'
|
||
|
|
|
||
|
|
export const routes: RouteRecordRaw[] = [
|
||
|
|
// ... 其他路由
|
||
|
|
{
|
||
|
|
path: '/user-management',
|
||
|
|
name: 'UserManagement',
|
||
|
|
component: () => import('@/views/user-management/index.vue'),
|
||
|
|
meta: {
|
||
|
|
title: '用户管理',
|
||
|
|
requiresAuth: true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 新增组件
|
||
|
|
|
||
|
|
#### 创建可复用组件
|
||
|
|
```vue
|
||
|
|
<!-- apps/web-antd/src/components/UserAvatar.vue -->
|
||
|
|
<script setup lang="ts">
|
||
|
|
interface Props {
|
||
|
|
user: {
|
||
|
|
name: string
|
||
|
|
avatar?: string
|
||
|
|
}
|
||
|
|
size?: 'small' | 'medium' | 'large'
|
||
|
|
}
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<Props>(), {
|
||
|
|
size: 'medium'
|
||
|
|
})
|
||
|
|
|
||
|
|
const sizeMap = {
|
||
|
|
small: 'w-8 h-8',
|
||
|
|
medium: 'w-12 h-12',
|
||
|
|
large: 'w-16 h-16'
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<div class="user-avatar flex items-center space-x-3">
|
||
|
|
<img
|
||
|
|
v-if="user.avatar"
|
||
|
|
:src="user.avatar"
|
||
|
|
:alt="user.name"
|
||
|
|
:class="['rounded-full', sizeMap[size]]"
|
||
|
|
/>
|
||
|
|
<div
|
||
|
|
v-else
|
||
|
|
:class="['bg-gray-200 rounded-full flex items-center justify-center', sizeMap[size]]"
|
||
|
|
>
|
||
|
|
<span class="text-gray-600 font-medium">{{ user.name.charAt(0) }}</span>
|
||
|
|
</div>
|
||
|
|
<span class="text-gray-900 font-medium">{{ user.name }}</span>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.user-avatar {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
```
|
||
|
|
|
||
|
|
## 开发计划
|
||
|
|
|
||
|
|
### 第一阶段:基础功能开发 (1-2周)
|
||
|
|
|
||
|
|
#### 任务清单
|
||
|
|
- [x] 项目环境搭建
|
||
|
|
- [x] 基础架构配置
|
||
|
|
- [x] 用户登录功能
|
||
|
|
- [x] 权限管理系统
|
||
|
|
- [x] 基础布局组件
|
||
|
|
|
||
|
|
#### 技术要点
|
||
|
|
- Vue3 Composition API 使用
|
||
|
|
- TypeScript 类型定义
|
||
|
|
- Pinia 状态管理
|
||
|
|
- Vue Router 路由配置
|
||
|
|
|
||
|
|
### 第二阶段:业务功能开发 (2-3周)
|
||
|
|
|
||
|
|
#### 任务清单
|
||
|
|
- [x] 用户管理模块
|
||
|
|
- [x] 角色管理模块
|
||
|
|
- [x] 菜单管理模块
|
||
|
|
- [x] 系统设置模块
|
||
|
|
- [x] 数据表格组件
|
||
|
|
|
||
|
|
#### 技术要点
|
||
|
|
- 表单验证处理
|
||
|
|
- 表格数据展示
|
||
|
|
- 分页查询优化
|
||
|
|
- 文件上传下载
|
||
|
|
|
||
|
|
### 第三阶段:优化完善 (1周)
|
||
|
|
|
||
|
|
#### 任务清单
|
||
|
|
- [x] 性能优化
|
||
|
|
- [x] 代码重构
|
||
|
|
- [x] 测试用例编写
|
||
|
|
- [x] 文档完善
|
||
|
|
|
||
|
|
#### 技术要点
|
||
|
|
- 代码分割优化
|
||
|
|
- 懒加载实现
|
||
|
|
- 单元测试覆盖
|
||
|
|
- 文档自动生成
|
||
|
|
|
||
|
|
## 常见问题解决
|
||
|
|
|
||
|
|
### 1. 依赖安装问题
|
||
|
|
|
||
|
|
**问题**: pnpm install 失败
|
||
|
|
**解决方案**:
|
||
|
|
```bash
|
||
|
|
# 清理缓存
|
||
|
|
pnpm store prune
|
||
|
|
|
||
|
|
# 重新安装
|
||
|
|
pnpm install --force
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 类型检查错误
|
||
|
|
|
||
|
|
**问题**: TypeScript 类型错误
|
||
|
|
**解决方案**:
|
||
|
|
```bash
|
||
|
|
# 检查类型错误
|
||
|
|
pnpm type-check
|
||
|
|
|
||
|
|
# 自动修复
|
||
|
|
pnpm lint:fix
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 构建失败
|
||
|
|
|
||
|
|
**问题**: 生产构建失败
|
||
|
|
**解决方案**:
|
||
|
|
```bash
|
||
|
|
# 清理构建缓存
|
||
|
|
pnpm clean
|
||
|
|
|
||
|
|
# 重新构建
|
||
|
|
pnpm build
|
||
|
|
```
|
||
|
|
|
||
|
|
## 测试指南
|
||
|
|
|
||
|
|
### 单元测试
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// __tests__/user.spec.ts
|
||
|
|
import { describe, it, expect } from 'vitest'
|
||
|
|
import { mount } from '@vue/test-utils'
|
||
|
|
import UserInfo from '@/components/UserInfo.vue'
|
||
|
|
|
||
|
|
describe('UserInfo', () => {
|
||
|
|
it('renders user name correctly', () => {
|
||
|
|
const wrapper = mount(UserInfo, {
|
||
|
|
props: {
|
||
|
|
user: {
|
||
|
|
name: '张三',
|
||
|
|
email: 'zhangsan@example.com'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
expect(wrapper.text()).toContain('张三')
|
||
|
|
})
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
### E2E 测试
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// __tests__/e2e/user.spec.ts
|
||
|
|
import { test, expect } from '@playwright/test'
|
||
|
|
|
||
|
|
test('user login flow', async ({ page }) => {
|
||
|
|
await page.goto('/login')
|
||
|
|
await page.fill('[data-testid="username"]', 'admin')
|
||
|
|
await page.fill('[data-testid="password"]', '123456')
|
||
|
|
await page.click('[data-testid="login-btn"]')
|
||
|
|
|
||
|
|
await expect(page).toHaveURL('/dashboard')
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## 部署指南
|
||
|
|
|
||
|
|
### 开发环境部署
|
||
|
|
```bash
|
||
|
|
# 启动开发服务器
|
||
|
|
pnpm dev:antd
|
||
|
|
|
||
|
|
# 访问地址
|
||
|
|
http://localhost:3000
|
||
|
|
```
|
||
|
|
|
||
|
|
### 生产环境部署
|
||
|
|
```bash
|
||
|
|
# 构建生产版本
|
||
|
|
pnpm build:antd
|
||
|
|
|
||
|
|
# 部署到服务器
|
||
|
|
# 将 dist 目录上传到 Web 服务器
|
||
|
|
```
|
||
|
|
|
||
|
|
## 性能优化
|
||
|
|
|
||
|
|
### 构建优化
|
||
|
|
- 代码分割
|
||
|
|
- 树摇优化
|
||
|
|
- 压缩资源
|
||
|
|
- 缓存策略
|
||
|
|
|
||
|
|
### 运行时优化
|
||
|
|
- 虚拟滚动
|
||
|
|
- 图片懒加载
|
||
|
|
- 组件懒加载
|
||
|
|
- 防抖节流
|
||
|
|
|
||
|
|
## 安全指南
|
||
|
|
|
||
|
|
### 前端安全
|
||
|
|
- XSS 防护
|
||
|
|
- CSRF 防护
|
||
|
|
- 输入验证
|
||
|
|
- 权限控制
|
||
|
|
|
||
|
|
### 代码安全
|
||
|
|
- 敏感信息加密
|
||
|
|
- API 密钥保护
|
||
|
|
- 代码混淆
|
||
|
|
- 安全审计
|
||
|
|
|
||
|
|
## 维护指南
|
||
|
|
|
||
|
|
### 日常维护
|
||
|
|
- 定期更新依赖
|
||
|
|
- 监控系统性能
|
||
|
|
- 备份重要数据
|
||
|
|
- 安全漏洞修复
|
||
|
|
|
||
|
|
### 版本管理
|
||
|
|
- 使用 Git 版本控制
|
||
|
|
- 遵循语义化版本
|
||
|
|
- 定期发布版本
|
||
|
|
- 维护更新日志
|