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

29 KiB
Raw Permalink Blame 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 克隆项目

git clone https://github.com/jiebanke/admin-system.git
cd admin-system

2.2.2 安装依赖

npm install
# 或
yarn install

2.2.3 配置环境变量

# 复制环境配置文件
cp .env.example .env.development
cp .env.example .env.production

# 编辑配置文件
vim .env.development

2.2.4 启动开发服务器

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-caseuser-management.vue
  • 组件命名使用PascalCaseUserManagement
  • 方法命名使用camelCasegetUserList
  • 常量命名使用UPPER_SNAKE_CASEAPI_BASE_URL

4.1.2 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服务封装

// 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客户端配置

// 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结构

// 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 路由配置

// 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配置

// .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 单元测试

// 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 端到端测试

// 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配置

// 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 环境配置

# .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

# .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 错误监控

// 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/CDGitHub Actions自动化部署
  • 监控日志:错误监控和性能分析
  • 环境管理:多环境配置和部署

通过严格按照本开发文档执行,可以确保管理后台的高质量交付和稳定运行。