Files
gym-manage/docs/design/前端技术架构详细设计.md
T
2026-03-05 13:48:13 +08:00

42 KiB
Raw Blame History

健身房管理系统前端技术架构详细设计文档

文档编号: 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 状态持久化

// stores/auth.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  const token = ref<string>('')
  const user = ref<User | null>(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连接管理

// hooks/useWebSocket.ts
import { ref, onUnmounted } from 'vue'

export function useWebSocket(url: string) {
  const ws = ref<WebSocket | null>(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 数据更新优化

// composables/useRealTimeData.ts
import { ref, computed } from 'vue'
import { useWebSocket } from '@/hooks/useWebSocket'

export function useRealTimeData<T>(initialData: T, wsUrl: string) {
  const data = ref<T>(initialData)
  const { connected, connect, send, onMessage } = useWebSocket(wsUrl)

  const updateData = (newData: Partial<T>) => {
    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 单一职责原则

每个组件只负责一个功能,保持组件的简洁和可复用性。

<!-- Bad: 职责过多 -->
<template>
  <div>
    <input v-model="form.name" />
    <input v-model="form.phone" />
    <button @click="submit">提交</button>
    <div v-if="showChart">
      <chart :data="chartData" />
    </div>
  </div>
</template>

<!-- Good: 职责单一 -->
<template>
  <member-form :model="form" @submit="handleSubmit" />
  <data-chart v-if="showChart" :data="chartData" />
</template>

4.2.2 Props设计

// components/base/Button.vue
interface ButtonProps {
  type?: 'primary' | 'secondary' | 'danger'
  size?: 'small' | 'medium' | 'large'
  disabled?: boolean
  loading?: boolean
  block?: boolean
}

const props = withDefaults(defineProps<ButtonProps>(), {
  type: 'primary',
  size: 'medium',
  disabled: false,
  loading: false,
  block: false
})

4.2.3 事件设计

// 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的条件编译实现跨端组件:

<template>
  <view class="button">
    <!-- #ifdef MP-WEIXIN -->
    <button open-type="getUserInfo" @getuserinfo="handleGetUserInfo">
      {{ text }}
    </button>
    <!-- #endif -->
    
    <!-- #ifdef APP-PLUS -->
    <button @click="handleClick">
      {{ text }}
    </button>
    <!-- #endif -->
  </view>
</template>

4.3.2 业务组件封装

<!-- components/business/CourseCard.vue -->
<template>
  <view class="course-card" @click="handleClick">
    <image :src="course.coverImage" mode="aspectFill" />
    <view class="course-info">
      <text class="course-name">{{ course.name }}</text>
      <text class="course-time">{{ course.startTime }}</text>
      <text class="course-capacity">
        {{ course.bookedCount }}/{{ course.capacity }}
      </text>
    </view>
  </view>
</template>

<script setup lang="ts">
interface Course {
  id: number
  name: string
  coverImage: string
  startTime: string
  bookedCount: number
  capacity: number
}

interface Props {
  course: Course
}

const props = defineProps<Props>()
const emit = defineEmits<{
  click: [course: Course]
}>()

const handleClick = () => {
  emit('click', props.course)
}
</script>

五、路由设计

5.1 路由结构

5.1.1 会员端路由

// 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 管理后台路由

// 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 认证守卫

// 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 权限守卫

// 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 动态路由

// 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封装

// 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<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.get(url, config)
  }

  public post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.post(url, data, config)
  }

  public put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.put(url, data, config)
  }

  public delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.delete(url, config)
  }
}

export default new Request({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000
})

6.2 API模块化

// 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<MemberListResponse>('/member/list', { params })
  },
  
  // 获取会员详情
  getDetail: (id: number) => {
    return request.get<Member>(`/member/${id}`)
  },
  
  // 创建会员
  create: (data: Partial<Member>) => {
    return request.post<Member>('/member', data)
  },
  
  // 更新会员
  update: (id: number, data: Partial<Member>) => {
    return request.put<Member>(`/member/${id}`, data)
  },
  
  // 删除会员
  delete: (id: number) => {
    return request.delete(`/member/${id}`)
  }
}

七、性能优化

7.1 加载性能优化

7.1.1 代码分割

// 路由懒加载
const routes = [
  {
    path: '/member/list',
    component: () => import('@/views/member/List.vue')
  }
]

7.1.2 资源优化

// 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 虚拟滚动

<template>
  <virtual-list
    :data="memberList"
    :item-size="80"
    :buffer="10"
  >
    <template #default="{ item }">
      <member-item :member="item" />
    </template>
  </virtual-list>
</template>

7.2.2 防抖节流

// utils/debounce.ts
export function debounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number
): (...args: Parameters<T>) => void {
  let timer: ReturnType<typeof setTimeout>
  
  return function(this: any, ...args: Parameters<T>) {
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

// 使用
const handleSearch = debounce((keyword: string) => {
  searchMembers(keyword)
}, 300)

7.3 渲染性能优化

7.3.1 减少重渲染

<template>
  <member-item
    v-for="member in memberList"
    :key="member.id"
    :member="member"
    @click="handleMemberClick"
  />
</template>

<script setup lang="ts">
import { shallowRef } from 'vue'

// 使用shallowRef减少响应式开销
const memberList = shallowRef<Member[]>([])
</script>

7.3.2 计算属性缓存

const filteredMembers = computed(() => {
  return memberList.value.filter(member => 
    member.name.includes(searchKeyword.value)
  )
})

八、安全设计

8.1 XSS防护

// utils/sanitize.ts
import DOMPurify from 'dompurify'

export function sanitizeHtml(html: string): string {
  return DOMPurify.sanitize(html)
}

// 使用
const safeHtml = sanitizeHtml(userInput)

8.2 CSRF防护

// 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 数据加密

// 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策略

<!-- index.html -->
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; 
               script-src 'self' 'unsafe-inline' 'unsafe-eval'; 
               style-src 'self' 'unsafe-inline'; 
               img-src 'self' data: https:;">

九、测试策略

9.1 单元测试

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

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

// 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 性能监控

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

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

// .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. 部署策略:构建配置、环境配置

该架构设计充分考虑了跨平台需求、性能优化、安全性、可维护性和可扩展性,为健身房管理系统的前端开发提供了完整的技术指导。