# 健身房管理系统前端技术架构详细设计文档 > 文档编号: GYM-FE-ARCH-001 > 版本: v1.0 > 日期: 2026-03-04 > 作者: 张翔 > 状态: 初稿 --- ## 文档修订历史 | 版本 | 日期 | 作者 | 修订内容 | | ---- | ---------- | ---- | -------- | | v1.0 | 2026-03-04 | 张翔 | 创建前端技术架构详细设计 | --- ## 参考文档 - 《健身房管理系统基础版产品设计文档》 GYM-PRD-BASIC-001 - 《健身房管理系统基础版系统概要设计文档》 GYM-HLD-BASIC-001 - 《健身房管理系统基础版系统详细设计文档》 GYM-LLD-BASIC-001 - Vue 3 官方文档 - uniapp 官方文档 - TypeScript 官方文档 --- ## 一、架构概述 ### 1.1 架构目标 - **跨平台覆盖**:支持小程序、App、PC多端,满足不同用户角色需求 - **高性能**:首屏加载时间 < 2s,交互响应时间 < 100ms - **高安全性**:符合金融级安全标准,保障用户数据和交易安全 - **高可维护性**:代码结构清晰,模块化设计,便于团队协作 - **高扩展性**:支持订阅模块动态加载,适应业务快速变化 ### 1.2 客户端架构 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 前端客户端架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 会员小程序 (uniapp+Vue3) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 会员注册/登录 • 课程预约 • 扫码签到 • 会员卡管理 │ │ │ │ • 个人中心 • 消息通知 • 数据统计 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 教练端App (uniapp+Vue3) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 课程管理 • 排班管理 • 会员管理 • 签到管理 │ │ │ │ • 数据统计 • 消息通知 • 个人中心 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 管理后台PC (Vue3+Vite+Element Plus) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 会员管理 • 课程管理 • 预约管理 • 签到管理 │ │ │ │ • 财务管理 • 数据统计 • 系统管理 • 订阅管理 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 1.3 技术栈选型 #### 1.3.1 核心框架 | 技术 | 版本 | 用途 | 选型理由 | |------|------|------|----------| | **Vue 3** | 3.4+ | 前端框架 | Composition API、响应式系统、生态成熟 | | **uniapp** | 3.0+ | 跨平台框架 | 一次开发多端部署、性能优秀、生态完善 | | **TypeScript** | 5.0+ | 类型系统 | 类型安全、开发体验、代码可维护性 | | **Vite** | 5.0+ | 构建工具 | 快速热更新、优化的构建性能、插件生态 | #### 1.3.2 状态管理 | 技术 | 版本 | 用途 | 选型理由 | |------|------|------|----------| | **Pinia** | 2.1+ | 状态管理 | Vue3官方推荐、API简洁、TypeScript支持好、模块化设计 | #### 1.3.3 UI组件库 | 技术 | 版本 | 用途 | 选型理由 | |------|------|------|----------| | **Element Plus** | 2.5+ | PC端UI组件 | 功能完善、设计规范、TypeScript支持、文档齐全 | | **uni-ui** | 1.5+ | 小程序/App UI组件 | 官方组件库、跨平台兼容、性能优化 | #### 1.3.4 工具库 | 技术 | 版本 | 用途 | 选型理由 | |------|------|------|----------| | **Vue Router** | 4.2+ | 路由管理 | Vue官方路由、动态路由、路由守卫 | | **Axios** | 1.6+ | HTTP客户端 | 拦截器、请求取消、TypeScript支持 | | **Day.js** | 1.11+ | 日期处理 | 轻量级、API友好、国际化支持 | | **Lodash-es** | 4.17+ | 工具函数 | 按需加载、性能优化、功能完善 | #### 1.3.5 开发工具 | 技术 | 版本 | 用途 | 选型理由 | |------|------|------|----------| | **ESLint** | 8.56+ | 代码检查 | 规则完善、插件生态、自动修复 | | **Prettier** | 3.1+ | 代码格式化 | 统一风格、配置简单、编辑器集成 | | **Husky** | 8.0+ | Git钩子 | 提交前检查、自动化流程 | | **Commitlint** | 18.4+ | 提交规范 | 规范提交信息、自动化生成Changelog | --- ## 二、架构设计 ### 2.1 分层架构 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 前端分层架构 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 表现层 (Presentation Layer) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 页面组件 • 业务组件 • 基础组件 • 布局组件 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 状态管理层 (State Management Layer) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 全局状态 • 模块状态 • 组件状态 • 持久化状态 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 业务逻辑层 (Business Logic Layer) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • Composables • Hooks • Utils • Validators │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 数据访问层 (Data Access Layer) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • API Service • WebSocket • Cache • Storage │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 基础设施层 (Infrastructure Layer) │ │ │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ • 路由 • 拦截器 • 错误处理 • 日志 • 监控 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 2.2 模块划分 #### 2.2.1 会员端模块 ``` 会员端 (Member Mini Program) ├── 认证模块 (Auth) │ ├── 登录/注册 │ ├── 手机号验证 │ ├── 微信授权 │ └── 忘记密码 ├── 会员模块 (Member) │ ├── 个人信息 │ ├── 会员卡管理 │ ├── 权益管理 │ └── 等级体系 ├── 预约模块 (Booking) │ ├── 团课列表 │ ├── 课程详情 │ ├── 预约操作 │ └── 预约记录 ├── 签到模块 (CheckIn) │ ├── 扫码签到 │ ├── 签到记录 │ └── 签到统计 ├── 消息模块 (Message) │ ├── 系统通知 │ ├── 预约提醒 │ └── 消息中心 └── 个人中心 (Profile) ├── 设置 ├── 帮助 └── 关于 ``` #### 2.2.2 教练端模块 ``` 教练端 (Coach App) ├── 认证模块 (Auth) │ ├── 登录 │ └── 权限验证 ├── 课程模块 (Course) │ ├── 课程管理 │ ├── 排班管理 │ └── 课程统计 ├── 会员模块 (Member) │ ├── 会员列表 │ ├── 会员详情 │ └── 会员跟进 ├── 签到模块 (CheckIn) │ ├── 签到管理 │ ├── 代签操作 │ └── 签到统计 ├── 数据模块 (Data) │ ├── 课程数据 │ ├── 会员数据 │ └── 收入数据 └── 个人中心 (Profile) ├── 个人信息 ├── 设置 └── 帮助 ``` #### 2.2.3 管理后台模块 ``` 管理后台 (Admin PC) ├── 认证模块 (Auth) │ ├── 登录 │ ├── 权限管理 │ └── 角色管理 ├── 会员模块 (Member) │ ├── 会员管理 │ ├── 会员卡管理 │ ├── 权益管理 │ └── 等级管理 ├── 课程模块 (Course) │ ├── 课程管理 │ ├── 时段管理 │ └── 排班管理 ├── 预约模块 (Booking) │ ├── 预约管理 │ ├── 候补管理 │ └── 预约统计 ├── 签到模块 (CheckIn) │ ├── 签到记录 │ ├── 设备管理 │ └── 签到统计 ├── 财务模块 (Finance) │ ├── 订单管理 │ ├── 收入统计 │ └── 财务报表 ├── 数据模块 (Data) │ ├── 数据统计 │ ├── 数据分析 │ └── 报表导出 ├── 系统模块 (System) │ ├── 用户管理 │ ├── 角色权限 │ ├── 系统配置 │ └── 操作日志 └── 订阅模块 (Subscription) ├── 订阅管理 ├── 模块管理 └── 计费管理 ``` ### 2.3 目录结构 #### 2.3.1 会员端/教练端目录结构 ``` src/ ├── api/ # API接口 │ ├── modules/ │ │ ├── auth.ts │ │ ├── member.ts │ │ ├── booking.ts │ │ └── checkin.ts │ └── request.ts # Axios封装 ├── assets/ # 静态资源 │ ├── images/ │ ├── icons/ │ └── styles/ ├── components/ # 组件 │ ├── base/ # 基础组件 │ ├── business/ # 业务组件 │ └── layout/ # 布局组件 ├── composables/ # Composables │ ├── useAuth.ts │ ├── useBooking.ts │ └── useCheckIn.ts ├── config/ # 配置 │ ├── app.config.ts │ └── env.config.ts ├── hooks/ # Hooks │ ├── useRequest.ts │ └── useWebSocket.ts ├── pages/ # 页面 │ ├── index/ │ ├── auth/ │ ├── member/ │ ├── booking/ │ └── checkin/ ├── stores/ # 状态管理 │ ├── auth.ts │ ├── member.ts │ ├── booking.ts │ └── checkin.ts ├── types/ # 类型定义 │ ├── api.ts │ ├── models.ts │ └── index.ts ├── utils/ # 工具函数 │ ├── validator.ts │ ├── formatter.ts │ └── storage.ts ├── App.vue └── main.ts ``` #### 2.3.2 管理后台目录结构 ``` src/ ├── api/ # API接口 │ ├── modules/ │ │ ├── auth.ts │ │ ├── member.ts │ │ ├── course.ts │ │ ├── booking.ts │ │ ├── checkin.ts │ │ ├── finance.ts │ │ └── system.ts │ └── request.ts # Axios封装 ├── assets/ # 静态资源 │ ├── images/ │ ├── icons/ │ └── styles/ ├── components/ # 组件 │ ├── base/ # 基础组件 │ ├── business/ # 业务组件 │ └── layout/ # 布局组件 ├── composables/ # Composables │ ├── useAuth.ts │ ├── usePermission.ts │ └── useTable.ts ├── config/ # 配置 │ ├── app.config.ts │ └── env.config.ts ├── directives/ # 自定义指令 │ ├── permission.ts │ └── loading.ts ├── hooks/ # Hooks │ ├── useRequest.ts │ └── useWebSocket.ts ├── layouts/ # 布局 │ ├── BasicLayout.vue │ └── BlankLayout.vue ├── router/ # 路由 │ ├── index.ts │ └── modules/ │ ├── auth.ts │ ├── member.ts │ ├── course.ts │ └── system.ts ├── stores/ # 状态管理 │ ├── auth.ts │ ├── permission.ts │ ├── app.ts │ └── user.ts ├── types/ # 类型定义 │ ├── api.ts │ ├── models.ts │ └── index.ts ├── utils/ # 工具函数 │ ├── validator.ts │ ├── formatter.ts │ ├── storage.ts │ └── permission.ts ├── views/ # 页面 │ ├── auth/ │ ├── member/ │ ├── course/ │ ├── booking/ │ ├── checkin/ │ ├── finance/ │ ├── data/ │ ├── system/ │ └── subscription/ ├── App.vue └── main.ts ``` --- ## 三、数据流设计 ### 3.1 单向数据流 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 单向数据流设计 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 用户 │ ──▶│ 组件 │ ──▶│ Store │ ──▶│ API │ │ │ │ 操作 │ │ Action │ │ State │ │ Service │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ ┌─────────┐ │ │ │ │ │ │ 后端API │ │ │ │ │ │ └─────────┘ │ │ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ ┌─────────┐ │ │ │ │ │ │ 数据库 │ │ │ │ │ │ └─────────┘ │ │ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ ┌─────────┐ │ │ │ │ │ │ 返回数据 │ │ │ │ │ │ └─────────┘ │ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ ┌─────────┐ │ │ │ │ │ │ 更新 │◀─────────┘ │ │ │ │ │ State │ │ │ │ │ └─────────┘ │ │ │ │ │ │ │ │ ▼ ▼ │ │ │ ┌─────────────────────────┐ │ │ │ │ 重新渲染组件 │ │ │ │ └─────────────────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────────────────┐ │ │ │ 更新UI显示 │ │ │ └─────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 3.2 状态管理策略 #### 3.2.1 状态分类 | 状态类型 | 存储位置 | 持久化 | 示例 | |---------|----------|--------|------| | **全局状态** | Pinia Store | 是 | 用户信息、权限、配置 | | **模块状态** | Pinia Store | 否 | 当前页面数据、表单数据 | | **组件状态** | Component State | 否 | 弹窗显示、加载状态 | | **临时状态** | Component State | 否 | 输入框值、选择项 | #### 3.2.2 状态持久化 ```typescript // stores/auth.ts import { defineStore } from 'pinia' import { ref } from 'vue' export const useAuthStore = defineStore('auth', () => { const token = ref('') const user = ref(null) // 持久化到localStorage const $persist = () => { localStorage.setItem('auth_token', token.value) localStorage.setItem('auth_user', JSON.stringify(user.value)) } const login = async (credentials: LoginRequest) => { const response = await api.login(credentials) token.value = response.token user.value = response.user $persist() } const logout = () => { token.value = '' user.value = null localStorage.removeItem('auth_token') localStorage.removeItem('auth_user') } return { token, user, login, logout } }) ``` ### 3.3 实时数据处理 #### 3.3.1 WebSocket连接管理 ```typescript // hooks/useWebSocket.ts import { ref, onUnmounted } from 'vue' export function useWebSocket(url: string) { const ws = ref(null) const connected = ref(false) const messageHandler = ref<(data: any) => void>(() => {}) const connect = () => { ws.value = new WebSocket(url) ws.value.onopen = () => { connected.value = true startHeartbeat() } ws.value.onmessage = (event) => { const data = JSON.parse(event.data) messageHandler.value(data) } ws.value.onclose = () => { connected.value = false reconnect() } ws.value.onerror = (error) => { console.error('WebSocket error:', error) } } const disconnect = () => { if (ws.value) { ws.value.close() ws.value = null } } const send = (data: any) => { if (ws.value && connected.value) { ws.value.send(JSON.stringify(data)) } } const reconnect = () => { setTimeout(() => { connect() }, 3000) } const startHeartbeat = () => { setInterval(() => { send({ type: 'ping' }) }, 30000) } onUnmounted(() => { disconnect() }) return { connected, connect, disconnect, send, onMessage: (handler: (data: any) => void) => { messageHandler.value = handler } } } ``` #### 3.3.2 数据更新优化 ```typescript // composables/useRealTimeData.ts import { ref, computed } from 'vue' import { useWebSocket } from '@/hooks/useWebSocket' export function useRealTimeData(initialData: T, wsUrl: string) { const data = ref(initialData) const { connected, connect, send, onMessage } = useWebSocket(wsUrl) const updateData = (newData: Partial) => { data.value = { ...data.value, ...newData } } const subscribe = (channel: string) => { onMessage((message) => { if (message.channel === channel) { // 增量更新,减少重渲染 updateData(message.data) } }) } return { data, connected, connect, subscribe } } ``` --- ## 四、组件设计 ### 4.1 组件分类 #### 4.1.1 基础组件 | 组件名称 | 功能 | 适用端 | |---------|------|--------| | Button | 按钮 | 全端 | | Input | 输入框 | 全端 | | Select | 选择器 | 全端 | | DatePicker | 日期选择器 | 全端 | | Modal | 弹窗 | 全端 | | Loading | 加载 | 全端 | | Empty | 空状态 | 全端 | | ErrorPage | 错误页 | 全端 | #### 4.1.2 业务组件 | 组件名称 | 功能 | 适用端 | |---------|------|--------| | MemberCard | 会员卡展示 | 全端 | | CourseCard | 课程卡片 | 全端 | | BookingCard | 预约卡片 | 全端 | | CheckInCode | 签到码 | 会员端/教练端 | | QRCodeScanner | 二维码扫描 | 会员端/教练端 | | DataChart | 数据图表 | 管理后台 | | DataTable | 数据表格 | 管理后台 | #### 4.1.3 布局组件 | 组件名称 | 功能 | 适用端 | |---------|------|--------| | PageLayout | 页面布局 | 全端 | | TabBar | 底部导航 | 会员端/教练端 | | Sidebar | 侧边栏 | 管理后台 | | Header | 顶部导航 | 管理后台 | | Footer | 底部 | 管理后台 | ### 4.2 组件设计原则 #### 4.2.1 单一职责原则 每个组件只负责一个功能,保持组件的简洁和可复用性。 ```vue ``` #### 4.2.2 Props设计 ```typescript // components/base/Button.vue interface ButtonProps { type?: 'primary' | 'secondary' | 'danger' size?: 'small' | 'medium' | 'large' disabled?: boolean loading?: boolean block?: boolean } const props = withDefaults(defineProps(), { type: 'primary', size: 'medium', disabled: false, loading: false, block: false }) ``` #### 4.2.3 事件设计 ```typescript // components/base/DatePicker.vue const emit = defineEmits<{ change: [value: Date] confirm: [value: Date] cancel: [] }>() // 使用 emit('change', new Date()) emit('confirm', new Date()) emit('cancel') ``` ### 4.3 组件复用策略 #### 4.3.1 跨端组件 使用uniapp的条件编译实现跨端组件: ```vue ``` #### 4.3.2 业务组件封装 ```vue ``` --- ## 五、路由设计 ### 5.1 路由结构 #### 5.1.1 会员端路由 ```typescript // router/index.ts const routes = [ { path: '/pages/index/index', name: 'Home', meta: { title: '首页' } }, { path: '/pages/auth/login', name: 'Login', meta: { title: '登录' } }, { path: '/pages/member/profile', name: 'Profile', meta: { title: '个人中心', requiresAuth: true } }, { path: '/pages/booking/list', name: 'BookingList', meta: { title: '课程列表', requiresAuth: true } }, { path: '/pages/booking/detail', name: 'BookingDetail', meta: { title: '课程详情', requiresAuth: true } }, { path: '/pages/checkin/scan', name: 'CheckInScan', meta: { title: '扫码签到', requiresAuth: true } } ] ``` #### 5.1.2 管理后台路由 ```typescript // router/index.ts const routes = [ { path: '/login', name: 'Login', component: () => import('@/views/auth/Login.vue'), meta: { title: '登录' } }, { path: '/', component: () => import('@/layouts/BasicLayout.vue'), redirect: '/dashboard', children: [ { path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/Index.vue'), meta: { title: '仪表盘', requiresAuth: true } }, { path: 'member', name: 'Member', redirect: '/member/list', meta: { title: '会员管理', requiresAuth: true, permission: 'member:view' }, children: [ { path: 'list', name: 'MemberList', component: () => import('@/views/member/List.vue'), meta: { title: '会员列表' } }, { path: 'detail/:id', name: 'MemberDetail', component: () => import('@/views/member/Detail.vue'), meta: { title: '会员详情' } } ] } ] } ] ``` ### 5.2 路由守卫 #### 5.2.1 认证守卫 ```typescript // router/guards/auth.ts import { useAuthStore } from '@/stores/auth' router.beforeEach((to, from, next) => { const authStore = useAuthStore() if (to.meta.requiresAuth && !authStore.token) { next('/login') } else { next() } }) ``` #### 5.2.2 权限守卫 ```typescript // router/guards/permission.ts import { usePermissionStore } from '@/stores/permission' router.beforeEach((to, from, next) => { const permissionStore = usePermissionStore() if (to.meta.permission && !permissionStore.hasPermission(to.meta.permission as string)) { next('/403') } else { next() } }) ``` ### 5.3 动态路由 ```typescript // router/dynamic.ts import { usePermissionStore } from '@/stores/permission' export function setupDynamicRoutes() { const permissionStore = usePermissionStore() const routes = permissionStore.generateRoutes() routes.forEach(route => { router.addRoute(route) }) } ``` --- ## 六、API设计 ### 6.1 Axios封装 ```typescript // api/request.ts import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios' import { useAuthStore } from '@/stores/auth' class Request { private instance: AxiosInstance constructor(config: AxiosRequestConfig) { this.instance = axios.create(config) this.setupInterceptors() } private setupInterceptors() { // 请求拦截器 this.instance.interceptors.request.use( (config) => { const authStore = useAuthStore() if (authStore.token) { config.headers.Authorization = `Bearer ${authStore.token}` } return config }, (error) => { return Promise.reject(error) } ) // 响应拦截器 this.instance.interceptors.response.use( (response: AxiosResponse) => { const { code, data, message } = response.data if (code === 200) { return data } else { return Promise.reject(new Error(message)) } }, (error) => { if (error.response?.status === 401) { const authStore = useAuthStore() authStore.logout() window.location.href = '/login' } return Promise.reject(error) } ) } public get(url: string, config?: AxiosRequestConfig): Promise { return this.instance.get(url, config) } public post(url: string, data?: any, config?: AxiosRequestConfig): Promise { return this.instance.post(url, data, config) } public put(url: string, data?: any, config?: AxiosRequestConfig): Promise { return this.instance.put(url, data, config) } public delete(url: string, config?: AxiosRequestConfig): Promise { return this.instance.delete(url, config) } } export default new Request({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000 }) ``` ### 6.2 API模块化 ```typescript // api/modules/member.ts import request from '../request' export interface Member { id: number name: string phone: string avatar?: string level: number exp: number } export interface MemberListParams { page: number pageSize: number keyword?: string level?: number } export interface MemberListResponse { list: Member[] total: number } export const memberApi = { // 获取会员列表 getList: (params: MemberListParams) => { return request.get('/member/list', { params }) }, // 获取会员详情 getDetail: (id: number) => { return request.get(`/member/${id}`) }, // 创建会员 create: (data: Partial) => { return request.post('/member', data) }, // 更新会员 update: (id: number, data: Partial) => { return request.put(`/member/${id}`, data) }, // 删除会员 delete: (id: number) => { return request.delete(`/member/${id}`) } } ``` --- ## 七、性能优化 ### 7.1 加载性能优化 #### 7.1.1 代码分割 ```typescript // 路由懒加载 const routes = [ { path: '/member/list', component: () => import('@/views/member/List.vue') } ] ``` #### 7.1.2 资源优化 ```typescript // vite.config.ts export default defineConfig({ build: { rollupOptions: { output: { manualChunks: { 'vue-vendor': ['vue', 'vue-router', 'pinia'], 'element-plus': ['element-plus'], 'utils': ['lodash-es', 'dayjs'] } } } } }) ``` ### 7.2 运行时性能优化 #### 7.2.1 虚拟滚动 ```vue ``` #### 7.2.2 防抖节流 ```typescript // utils/debounce.ts export function debounce any>( fn: T, delay: number ): (...args: Parameters) => void { let timer: ReturnType return function(this: any, ...args: Parameters) { clearTimeout(timer) timer = setTimeout(() => { fn.apply(this, args) }, delay) } } // 使用 const handleSearch = debounce((keyword: string) => { searchMembers(keyword) }, 300) ``` ### 7.3 渲染性能优化 #### 7.3.1 减少重渲染 ```vue ``` #### 7.3.2 计算属性缓存 ```typescript const filteredMembers = computed(() => { return memberList.value.filter(member => member.name.includes(searchKeyword.value) ) }) ``` --- ## 八、安全设计 ### 8.1 XSS防护 ```typescript // utils/sanitize.ts import DOMPurify from 'dompurify' export function sanitizeHtml(html: string): string { return DOMPurify.sanitize(html) } // 使用 const safeHtml = sanitizeHtml(userInput) ``` ### 8.2 CSRF防护 ```typescript // api/request.ts instance.interceptors.request.use((config) => { const csrfToken = getCookie('csrf_token') if (csrfToken) { config.headers['X-CSRF-Token'] = csrfToken } return config }) ``` ### 8.3 数据加密 ```typescript // utils/crypto.ts import CryptoJS from 'crypto-js' const SECRET_KEY = 'your-secret-key' export function encrypt(text: string): string { return CryptoJS.AES.encrypt(text, SECRET_KEY).toString() } export function decrypt(ciphertext: string): string { const bytes = CryptoJS.AES.decrypt(ciphertext, SECRET_KEY) return bytes.toString(CryptoJS.enc.Utf8) } ``` ### 8.4 CSP策略 ```html ``` --- ## 九、测试策略 ### 9.1 单元测试 ```typescript // components/__tests__/Button.spec.ts import { mount } from '@vue/test-utils' import { describe, it, expect } from 'vitest' import Button from '@/components/base/Button.vue' describe('Button', () => { it('renders text correctly', () => { const wrapper = mount(Button, { slots: { default: 'Click me' } }) expect(wrapper.text()).toBe('Click me') }) it('emits click event', async () => { const wrapper = mount(Button) await wrapper.trigger('click') expect(wrapper.emitted('click')).toBeTruthy() }) }) ``` ### 9.2 E2E测试 ```typescript // e2e/booking.spec.ts import { test, expect } from '@playwright/test' test('user can book a course', async ({ page }) => { await page.goto('/booking/list') await page.click('[data-testid="course-card"]:first-child') await page.click('[data-testid="book-button"]') await expect(page.locator('[data-testid="success-message"]')).toBeVisible() }) ``` --- ## 十、监控与日志 ### 10.1 错误监控 ```typescript // utils/sentry.ts import * as Sentry from '@sentry/vue' export function setupSentry(app: App) { Sentry.init({ app, dsn: import.meta.env.VITE_SENTRY_DSN, environment: import.meta.env.MODE, tracesSampleRate: 1.0, beforeSend(event) { // 过滤敏感信息 if (event.request) { delete event.request.cookies } return event } }) } ``` ### 10.2 性能监控 ```typescript // utils/analytics.ts import { onCLS, onFID, onLCP } from 'web-vitals' export function setupPerformanceMonitoring() { onCLS((metric) => { console.log('CLS:', metric.value) }) onFID((metric) => { console.log('FID:', metric.value) }) onLCP((metric) => { console.log('LCP:', metric.value) }) } ``` --- ## 十一、部署策略 ### 11.1 构建配置 ```typescript // vite.config.ts export default defineConfig({ base: '/', build: { outDir: 'dist', assetsDir: 'assets', sourcemap: false, minify: 'terser', terserOptions: { compress: { drop_console: true, drop_debugger: true } } } }) ``` ### 11.2 环境配置 ```typescript // .env.development VITE_API_BASE_URL=http://localhost:8080/api VITE_APP_TITLE=健身房管理系统(开发环境) // .env.production VITE_API_BASE_URL=https://api.example.com/api VITE_APP_TITLE=健身房管理系统 ``` --- ## 十二、总结 本文档详细描述了健身房管理系统的前端技术架构,包括: 1. **技术栈选型**:Vue3 + uniapp + TypeScript + Pinia + Vite 2. **架构设计**:分层架构、模块划分、目录结构 3. **数据流设计**:单向数据流、状态管理、实时数据处理 4. **组件设计**:组件分类、设计原则、复用策略 5. **路由设计**:路由结构、路由守卫、动态路由 6. **API设计**:Axios封装、API模块化 7. **性能优化**:加载性能、运行时性能、渲染性能 8. **安全设计**:XSS防护、CSRF防护、数据加密、CSP策略 9. **测试策略**:单元测试、E2E测试 10. **监控与日志**:错误监控、性能监控 11. **部署策略**:构建配置、环境配置 该架构设计充分考虑了跨平台需求、性能优化、安全性、可维护性和可扩展性,为健身房管理系统的前端开发提供了完整的技术指导。