Files
jiebanke/docs/管理后台开发文档.md

1184 lines
29 KiB
Markdown
Raw Normal View History

# 管理后台开发文档
## 1. 项目概述
### 1.1 项目简介
解班客管理后台是一个基于Vue 3的现代化Web管理系统为运营人员提供用户管理、内容管理、数据分析等功能。
### 1.2 技术栈
- **前端框架**Vue 3.x + TypeScript
- **构建工具**Vite 4.x
- **UI组件库**Element Plus
- **状态管理**Pinia
- **路由管理**Vue Router 4.x
- **HTTP客户端**Axios
- **图表库**ECharts
- **富文本编辑器**Quill.js
- **表格组件**Element Plus Table
- **代码规范**ESLint + Prettier
- **CSS预处理器**SCSS
### 1.3 项目结构
```
admin-system/
├── public/ # 静态资源
├── src/
│ ├── api/ # API接口
│ ├── assets/ # 资源文件
│ ├── components/ # 通用组件
│ │ ├── common/ # 基础组件
│ │ └── business/ # 业务组件
│ ├── composables/ # 组合式函数
│ ├── layouts/ # 布局组件
│ ├── pages/ # 页面组件
│ │ ├── dashboard/ # 仪表盘
│ │ ├── user/ # 用户管理
│ │ ├── travel/ # 旅行管理
│ │ ├── animal/ # 动物管理
│ │ ├── order/ # 订单管理
│ │ └── system/ # 系统管理
│ ├── router/ # 路由配置
│ ├── stores/ # 状态管理
│ ├── styles/ # 样式文件
│ ├── types/ # 类型定义
│ ├── utils/ # 工具函数
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
├── tests/ # 测试文件
├── docs/ # 文档
├── .env.development # 开发环境配置
├── .env.production # 生产环境配置
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md
```
## 2. 开发环境搭建
### 2.1 环境要求
- Node.js >= 16.0.0
- npm >= 8.0.0 或 yarn >= 1.22.0
- Git >= 2.0.0
### 2.2 环境搭建步骤
#### 2.2.1 克隆项目
```bash
git clone https://github.com/jiebanke/admin-system.git
cd admin-system
```
#### 2.2.2 安装依赖
```bash
npm install
# 或
yarn install
```
#### 2.2.3 配置环境变量
```bash
# 复制环境配置文件
cp .env.example .env.development
cp .env.example .env.production
# 编辑配置文件
vim .env.development
```
#### 2.2.4 启动开发服务器
```bash
npm run dev
# 或
yarn dev
```
### 2.3 开发工具配置
#### 2.3.1 VSCode配置
推荐安装以下插件:
- Vue Language Features (Volar)
- TypeScript Importer
- ESLint
- Prettier
- Auto Rename Tag
- Bracket Pair Colorizer
#### 2.3.2 浏览器开发工具
- Vue.js devtools
- Chrome DevTools
- 网络调试工具
## 3. 开发计划与任务分解
### 3.1 开发阶段划分
#### 阶段一基础框架搭建预计6个工作日
- 项目初始化和环境配置
- 基础组件开发
- 路由和权限配置
- 通用工具类开发
#### 阶段二核心页面开发预计18个工作日
- 登录和权限管理
- 仪表盘页面
- 用户管理页面
- 内容管理页面
#### 阶段三业务功能开发预计15个工作日
- 旅行管理功能
- 动物管理功能
- 订单管理功能
- 数据统计功能
#### 阶段四系统功能和优化预计8个工作日
- 系统设置功能
- 性能优化
- 测试和修复
- 部署准备
### 3.2 详细任务分解
#### 3.2.1 阶段一:基础框架搭建
##### 任务1.1项目初始化2个工作日
**负责人**:前端架构师 + 前端开发工程师
**工时估算**16人时
**任务描述**
- 创建Vue 3项目结构
- 配置TypeScript和构建工具
- 设置代码规范和Git hooks
- 配置开发环境
**具体子任务**
1. 创建Vite + Vue 3项目4人时
2. 配置TypeScript和类型定义4人时
3. 设置ESLint、Prettier和Git hooks4人时
4. 配置环境变量和构建脚本4人时
**验收标准**
- 项目可以正常启动和热重载
- 代码规范检查通过
- TypeScript编译无错误
##### 任务1.2基础组件开发2个工作日
**负责人**:前端开发工程师
**工时估算**16人时
**任务描述**
- 开发通用UI组件
- 创建布局组件
- 开发表单组件
- 创建数据展示组件
**具体子任务**
1. 页面布局组件Header、Sidebar、Footer6人时
2. 表单组件封装Input、Select、DatePicker等4人时
3. 数据展示组件Table、Card、Tag等4人时
4. 反馈组件Dialog、Message、Loading等2人时
**验收标准**
- 组件功能完整且可复用
- 样式符合设计规范
- 支持TypeScript类型定义
##### 任务1.3路由和权限配置1个工作日
**负责人**:前端开发工程师
**工时估算**8人时
**任务描述**
- 配置Vue Router
- 实现路由守卫
- 设计权限控制系统
- 创建菜单管理
**具体子任务**
1. 配置路由结构和懒加载3人时
2. 实现登录验证和路由守卫3人时
3. 设计基于角色的权限控制2人时
**验收标准**
- 路由跳转正常
- 权限控制生效
- 菜单动态生成
##### 任务1.4通用工具类开发1个工作日
**负责人**:前端开发工程师
**工时估算**8人时
**任务描述**
- HTTP请求封装
- 工具函数开发
- 常量和枚举定义
- 类型定义完善
**具体子任务**
1. Axios请求拦截器和响应处理4人时
2. 日期、字符串、数组等工具函数2人时
3. 常量定义和TypeScript类型2人时
**验收标准**
- HTTP请求功能完整
- 工具函数覆盖常用场景
- 类型定义准确完整
#### 3.2.2 阶段二:核心页面开发
##### 任务2.1登录和权限管理3个工作日
**负责人**:前端开发工程师
**工时估算**24人时
**任务描述**
- 登录页面开发
- 权限管理页面
- 角色管理功能
- 用户会话管理
**具体子任务**
1. 登录页面UI和验证逻辑8人时
2. 权限管理页面角色、菜单、按钮权限10人时
3. 用户会话管理和自动登出4人时
4. 密码修改和安全设置2人时
**验收标准**
- 登录流程完整
- 权限控制精确
- 会话管理安全
##### 任务2.2仪表盘页面4个工作日
**负责人**:前端开发工程师
**工时估算**32人时
**任务描述**
- 数据概览展示
- 图表组件集成
- 实时数据更新
- 快捷操作入口
**具体子任务**
1. 数据统计卡片组件8人时
2. ECharts图表集成和配置12人时
3. 实时数据更新机制6人时
4. 快捷操作和通知中心6人时
**验收标准**
- 数据展示准确
- 图表交互流畅
- 实时更新正常
##### 任务2.3用户管理页面5个工作日
**负责人**:前端开发工程师
**工时估算**40人时
**任务描述**
- 用户列表和搜索
- 用户详情和编辑
- 用户状态管理
- 批量操作功能
**具体子任务**
1. 用户列表页面表格、分页、搜索12人时
2. 用户详情和编辑表单10人时
3. 用户状态管理启用、禁用、删除8人时
4. 批量操作和导入导出6人时
5. 用户行为日志查看4人时
**验收标准**
- 列表功能完整
- 编辑操作准确
- 批量操作安全
##### 任务2.4内容管理页面6个工作日
**负责人**:前端开发工程师
**工时估算**48人时
**任务描述**
- 文章内容管理
- 图片和文件管理
- 内容审核功能
- 分类和标签管理
**具体子任务**
1. 文章列表和编辑器集成15人时
2. 富文本编辑器配置和图片上传12人时
3. 内容审核工作流10人时
4. 分类标签管理6人时
5. 内容发布和定时发布5人时
**验收标准**
- 编辑器功能完整
- 审核流程清晰
- 发布功能正常
#### 3.2.3 阶段三:业务功能开发
##### 任务3.1旅行管理功能4个工作日
**负责人**:前端开发工程师
**工时估算**32人时
**任务描述**
- 旅行活动管理
- 参与者管理
- 活动审核功能
- 数据统计分析
**具体子任务**
1. 旅行活动列表和详情页面12人时
2. 活动创建和编辑功能8人时
3. 参与者管理和审核8人时
4. 活动数据统计和分析4人时
**验收标准**
- 活动管理功能完整
- 审核流程顺畅
- 数据统计准确
##### 任务3.2动物管理功能4个工作日
**负责人**:前端开发工程师
**工时估算**32人时
**任务描述**
- 动物信息管理
- 认领记录管理
- 动物状态跟踪
- 照片和视频管理
**具体子任务**
1. 动物信息列表和详情10人时
2. 动物信息编辑和状态管理8人时
3. 认领记录和历史跟踪8人时
4. 多媒体文件管理6人时
**验收标准**
- 动物信息管理完整
- 认领流程清晰
- 文件管理便捷
##### 任务3.3订单管理功能4个工作日
**负责人**:前端开发工程师
**工时估算**32人时
**任务描述**
- 订单列表和查询
- 订单详情和处理
- 支付状态管理
- 退款处理功能
**具体子任务**
1. 订单列表和高级搜索10人时
2. 订单详情和状态管理8人时
3. 支付信息和流水查看8人时
4. 退款申请和处理流程6人时
**验收标准**
- 订单查询功能强大
- 状态管理准确
- 退款流程安全
##### 任务3.4数据统计功能3个工作日
**负责人**:前端开发工程师
**工时估算**24人时
**任务描述**
- 用户数据统计
- 业务数据分析
- 财务数据报表
- 自定义报表功能
**具体子任务**
1. 用户增长和活跃度统计8人时
2. 业务数据分析图表8人时
3. 财务收支报表6人时
4. 自定义报表生成器2人时
**验收标准**
- 统计数据准确
- 图表展示清晰
- 报表功能实用
#### 3.2.4 阶段四:系统功能和优化
##### 任务4.1系统设置功能2个工作日
**负责人**:前端开发工程师
**工时估算**16人时
**任务描述**
- 系统配置管理
- 参数设置功能
- 日志查看功能
- 系统监控面板
**具体子任务**
1. 系统配置参数管理6人时
2. 操作日志和系统日志查看6人时
3. 系统监控和健康检查4人时
**验收标准**
- 配置管理完整
- 日志查看便捷
- 监控信息准确
##### 任务4.2性能优化2个工作日
**负责人**:前端开发工程师
**工时估算**16人时
**任务描述**
- 代码分割和懒加载
- 图片和资源优化
- 缓存策略优化
- 打包体积优化
**具体子任务**
1. 路由懒加载和代码分割6人时
2. 图片压缩和CDN配置4人时
3. HTTP缓存和本地存储优化4人时
4. Webpack打包优化2人时
**验收标准**
- 页面加载速度提升30%
- 打包体积减少20%
- 缓存策略有效
##### 任务4.3测试和修复2个工作日
**负责人**:前端开发工程师 + 测试工程师
**工时估算**16人时
**任务描述**
- 功能测试和修复
- 兼容性测试
- 性能测试
- 安全测试
**具体子任务**
1. 功能测试和Bug修复8人时
2. 浏览器兼容性测试4人时
3. 性能和安全测试4人时
**验收标准**
- 功能测试通过率>95%
- 主流浏览器兼容
- 性能指标达标
##### 任务4.4部署准备2个工作日
**负责人**:前端开发工程师 + 运维工程师
**工时估算**16人时
**任务描述**
- 生产环境配置
- CI/CD流程配置
- 监控和日志配置
- 文档整理
**具体子任务**
1. 生产环境构建和配置6人时
2. CI/CD流程配置6人时
3. 监控和日志配置2人时
4. 部署文档整理2人时
**验收标准**
- 生产环境部署成功
- CI/CD流程正常
- 监控配置完整
## 4. 开发规范
### 4.1 代码规范
#### 4.1.1 命名规范
- **文件命名**使用kebab-case`user-management.vue`
- **组件命名**使用PascalCase`UserManagement`
- **方法命名**使用camelCase`getUserList`
- **常量命名**使用UPPER_SNAKE_CASE`API_BASE_URL`
#### 4.1.2 Vue组件规范
```vue
<template>
<div class="user-management">
<div class="user-management__header">
<el-button type="primary" @click="handleAdd">
添加用户
</el-button>
</div>
<div class="user-management__content">
<el-table :data="userList" v-loading="loading">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="username" label="用户名" />
<el-table-column prop="email" label="邮箱" />
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button size="small" @click="handleEdit(row)">
编辑
</el-button>
<el-button
size="small"
type="danger"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { userApi } from '@/api/user'
import type { User } from '@/types/user'
// 响应式数据
const userList = ref<User[]>([])
const loading = ref(false)
// 方法定义
const getUserList = async () => {
try {
loading.value = true
const { data } = await userApi.getList()
userList.value = data
} catch (error) {
ElMessage.error('获取用户列表失败')
} finally {
loading.value = false
}
}
const handleAdd = () => {
// 添加用户逻辑
}
const handleEdit = (user: User) => {
// 编辑用户逻辑
}
const handleDelete = async (user: User) => {
try {
await ElMessageBox.confirm('确定要删除该用户吗?', '提示')
await userApi.delete(user.id)
ElMessage.success('删除成功')
getUserList()
} catch (error) {
if (error !== 'cancel') {
ElMessage.error('删除失败')
}
}
}
// 生命周期
onMounted(() => {
getUserList()
})
</script>
<style lang="scss" scoped>
.user-management {
padding: 20px;
&__header {
margin-bottom: 20px;
}
&__content {
background: #fff;
border-radius: 4px;
padding: 20px;
}
}
</style>
```
### 4.2 API调用规范
#### 4.2.1 API服务封装
```typescript
// api/user.ts
import { http } from '@/utils/http'
import type { User, UserQuery, UserForm } from '@/types/user'
import type { PageResult, ApiResponse } from '@/types/api'
export const userApi = {
/**
* 获取用户列表
*/
getList(params?: UserQuery): Promise<ApiResponse<PageResult<User>>> {
return http.get('/admin/users', { params })
},
/**
* 获取用户详情
*/
getDetail(id: number): Promise<ApiResponse<User>> {
return http.get(`/admin/users/${id}`)
},
/**
* 创建用户
*/
create(data: UserForm): Promise<ApiResponse<User>> {
return http.post('/admin/users', data)
},
/**
* 更新用户
*/
update(id: number, data: Partial<UserForm>): Promise<ApiResponse<User>> {
return http.put(`/admin/users/${id}`, data)
},
/**
* 删除用户
*/
delete(id: number): Promise<ApiResponse<void>> {
return http.delete(`/admin/users/${id}`)
},
/**
* 批量删除用户
*/
batchDelete(ids: number[]): Promise<ApiResponse<void>> {
return http.post('/admin/users/batch-delete', { ids })
}
}
```
#### 4.2.2 HTTP客户端配置
```typescript
// utils/http.ts
import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/stores/user'
import router from '@/router'
class HttpClient {
private instance: AxiosInstance
constructor() {
this.instance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
this.setupInterceptors()
}
private setupInterceptors() {
// 请求拦截器
this.instance.interceptors.request.use(
(config) => {
const userStore = useUserStore()
if (userStore.token) {
config.headers.Authorization = `Bearer ${userStore.token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
const { data } = response
if (data.code === 200) {
return data
} else {
ElMessage.error(data.message || '请求失败')
return Promise.reject(new Error(data.message))
}
},
(error) => {
if (error.response?.status === 401) {
const userStore = useUserStore()
userStore.logout()
router.push('/login')
ElMessage.error('登录已过期,请重新登录')
} else if (error.response?.status === 403) {
ElMessage.error('没有权限访问该资源')
} else if (error.response?.status >= 500) {
ElMessage.error('服务器错误,请稍后重试')
} else {
ElMessage.error(error.message || '网络错误')
}
return Promise.reject(error)
}
)
}
get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.instance.get(url, config)
}
post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.instance.post(url, data, config)
}
put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
return this.instance.put(url, data, config)
}
delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.instance.delete(url, config)
}
}
export const http = new HttpClient()
```
### 4.3 状态管理规范
#### 4.3.1 Pinia Store结构
```typescript
// stores/user.ts
import { defineStore } from 'pinia'
import { userApi } from '@/api/user'
import type { User, LoginForm } from '@/types/user'
interface UserState {
userInfo: User | null
token: string
permissions: string[]
roles: string[]
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
userInfo: null,
token: localStorage.getItem('token') || '',
permissions: [],
roles: []
}),
getters: {
isLoggedIn: (state) => !!state.token,
hasPermission: (state) => (permission: string) => {
return state.permissions.includes(permission)
},
hasRole: (state) => (role: string) => {
return state.roles.includes(role)
}
},
actions: {
async login(loginForm: LoginForm) {
try {
const { data } = await userApi.login(loginForm)
this.token = data.access_token
this.userInfo = data.user_info
this.permissions = data.permissions
this.roles = data.roles
localStorage.setItem('token', this.token)
localStorage.setItem('userInfo', JSON.stringify(this.userInfo))
return data
} catch (error) {
throw error
}
},
async getUserInfo() {
try {
const { data } = await userApi.getProfile()
this.userInfo = data
this.permissions = data.permissions
this.roles = data.roles
localStorage.setItem('userInfo', JSON.stringify(this.userInfo))
} catch (error) {
this.logout()
throw error
}
},
logout() {
this.token = ''
this.userInfo = null
this.permissions = []
this.roles = []
localStorage.removeItem('token')
localStorage.removeItem('userInfo')
}
}
})
```
### 4.4 路由和权限规范
#### 4.4.1 路由配置
```typescript
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import { useUserStore } from '@/stores/user'
const routes: RouteRecordRaw[] = [
{
path: '/login',
name: 'Login',
component: () => import('@/pages/login/Login.vue'),
meta: { requiresAuth: false }
},
{
path: '/',
name: 'Layout',
component: () => import('@/layouts/MainLayout.vue'),
redirect: '/dashboard',
meta: { requiresAuth: true },
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/pages/dashboard/Dashboard.vue'),
meta: {
title: '仪表盘',
icon: 'dashboard',
permissions: ['dashboard:view']
}
},
{
path: 'users',
name: 'UserManagement',
component: () => import('@/pages/user/UserManagement.vue'),
meta: {
title: '用户管理',
icon: 'user',
permissions: ['user:view']
}
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
// 路由守卫
router.beforeEach(async (to, from, next) => {
const userStore = useUserStore()
if (to.meta.requiresAuth !== false) {
if (!userStore.isLoggedIn) {
next('/login')
return
}
if (!userStore.userInfo) {
try {
await userStore.getUserInfo()
} catch (error) {
next('/login')
return
}
}
// 权限检查
if (to.meta.permissions) {
const hasPermission = (to.meta.permissions as string[]).some(
permission => userStore.hasPermission(permission)
)
if (!hasPermission) {
ElMessage.error('没有权限访问该页面')
next(from.path)
return
}
}
}
next()
})
export default router
```
## 5. 质量保证
### 5.1 代码质量检查
#### 5.1.1 ESLint配置
```javascript
// .eslintrc.js
module.exports = {
extends: [
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/prettier/@typescript-eslint'
],
rules: {
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn',
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
'vue/no-unused-components': 'error',
'vue/multi-word-component-names': 'off'
}
}
```
#### 5.1.2 代码审查流程
1. 开发者提交Pull Request
2. 自动化检查ESLint、TypeScript、构建测试
3. 同行代码审查
4. 技术负责人审查
5. 合并到主分支
### 5.2 测试策略
#### 5.2.1 单元测试
```typescript
// tests/components/UserTable.spec.ts
import { mount } from '@vue/test-utils'
import { ElTable } from 'element-plus'
import UserTable from '@/components/UserTable.vue'
describe('UserTable', () => {
const mockUsers = [
{ id: 1, username: 'test1', email: 'test1@example.com' },
{ id: 2, username: 'test2', email: 'test2@example.com' }
]
it('renders user data correctly', () => {
const wrapper = mount(UserTable, {
props: { users: mockUsers },
global: {
components: { ElTable }
}
})
expect(wrapper.text()).toContain('test1')
expect(wrapper.text()).toContain('test1@example.com')
})
it('emits edit event when edit button clicked', async () => {
const wrapper = mount(UserTable, {
props: { users: mockUsers }
})
await wrapper.find('[data-testid="edit-button-1"]').trigger('click')
expect(wrapper.emitted('edit')).toBeTruthy()
expect(wrapper.emitted('edit')[0]).toEqual([mockUsers[0]])
})
})
```
#### 5.2.2 端到端测试
```typescript
// tests/e2e/user-management.spec.ts
describe('User Management', () => {
beforeEach(() => {
cy.login('admin', 'password')
cy.visit('/users')
})
it('should display user list', () => {
cy.get('[data-testid="user-table"]').should('be.visible')
cy.get('[data-testid="user-row"]').should('have.length.greaterThan', 0)
})
it('should create new user', () => {
cy.get('[data-testid="add-user-button"]').click()
cy.get('[data-testid="user-form"]').should('be.visible')
cy.get('[data-testid="username-input"]').type('newuser')
cy.get('[data-testid="email-input"]').type('newuser@example.com')
cy.get('[data-testid="submit-button"]').click()
cy.get('.el-message--success').should('be.visible')
})
})
```
### 5.3 性能要求
#### 5.3.1 页面性能指标
- **首屏加载时间**<3s
- **页面切换时间**<500ms
- **表格渲染时间**<1s1000条数据
- **接口响应时间**<2s
#### 5.3.2 打包体积要求
- **初始包大小**<500KB
- **懒加载模块**<200KB
- **第三方库**<1MB
- **静态资源**<2MB
## 6. 部署和运维
### 6.1 构建配置
#### 6.1.1 Vite配置
```typescript
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
build: {
target: 'es2015',
outDir: 'dist',
assetsDir: 'assets',
sourcemap: false,
rollupOptions: {
output: {
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
assetFileNames: '[ext]/[name]-[hash].[ext]'
}
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
```
#### 6.1.2 环境配置
```bash
# .env.production
VITE_API_BASE_URL=https://api.jiebanke.com
VITE_CDN_BASE_URL=https://cdn.jiebanke.com
VITE_APP_TITLE=解班客管理后台
```
### 6.2 CI/CD配置
#### 6.2.1 GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm run test
- name: Build
run: npm run build
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.5
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/admin
git pull origin main
npm ci
npm run build
pm2 restart admin
```
### 6.3 监控和日志
#### 6.3.1 错误监控
```typescript
// utils/monitor.ts
export class ErrorMonitor {
static init() {
// 全局错误处理
window.addEventListener('error', (event) => {
this.reportError({
type: 'javascript',
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
stack: event.error?.stack
})
})
// Promise错误处理
window.addEventListener('unhandledrejection', (event) => {
this.reportError({
type: 'promise',
message: event.reason?.message || event.reason,
stack: event.reason?.stack
})
})
// Vue错误处理
app.config.errorHandler = (error, instance, info) => {
this.reportError({
type: 'vue',
message: error.message,
stack: error.stack,
componentInfo: info
})
}
}
static reportError(error: any) {
// 上报错误到监控平台
fetch('/api/monitor/error', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...error,
url: location.href,
userAgent: navigator.userAgent,
timestamp: Date.now()
})
})
}
}
```
## 7. 总结
本开发文档详细规划了解班客管理后台的开发计划,包括:
### 7.1 开发计划
- **总工期**47个工作日
- **团队规模**2-3名前端开发工程师
- **关键里程碑**:基础框架、核心页面、业务功能、系统优化
### 7.2 技术架构
- **前端框架**Vue 3 + TypeScript + Vite
- **UI组件库**Element Plus
- **状态管理**Pinia
- **构建工具**Vite
### 7.3 质量保证
- **代码规范**ESLint + Prettier
- **测试策略**:单元测试 + 端到端测试
- **性能优化**:懒加载、代码分割、缓存
- **监控体系**:错误监控 + 性能监控
### 7.4 部署运维
- **构建优化**Vite构建配置
- **CI/CD**GitHub Actions自动化部署
- **监控日志**:错误监控和性能分析
- **环境管理**:多环境配置和部署
通过严格按照本开发文档执行,可以确保管理后台的高质量交付和稳定运行。