# GameGroup 前端架构设计文档 **项目名称**: GameGroup 前端系统 **文档版本**: v1.0 **更新时间**: 2026-01-28 --- ## 📋 目录 - [1. 项目概述](#1-项目概述) - [2. 技术栈选型](#2-技术栈选型) - [3. 项目架构](#3-项目架构) - [4. 目录结构](#4-目录结构) - [5. 核心设计原则](#5-核心设计原则) - [6. 状态管理](#6-状态管理) - [7. 路由设计](#7-路由设计) - [8. API请求层](#8-api请求层) - [9. 性能优化](#9-性能优化) --- ## 1. 项目概述 GameGroup 是一个游戏社群管理平台,为玩家提供小组管理、游戏预约、积分系统、竞猜等功能。前端项目采用现代化的技术栈,注重用户体验和性能优化。 ### 核心功能模块 - **认证模块**: 用户注册、登录、令牌刷新 - **用户中心**: 个人资料管理、设置 - **小组管理**: 创建/加入小组、成员管理、权限控制 - **游戏库**: 游戏浏览、搜索、筛选 - **预约系统**: 创建预约、加入/退出预约、时间管理 - **账目管理**: 账目记录、统计分析 - **排班助手**: 空闲时间提交、共同时间查找 - **荣誉墙**: 荣誉展示、时间轴 - **资产管理**: 资产借用/归还、流转记录 - **积分系统**: 积分查询、排行榜 - **竞猜系统**: 创建竞猜、参与竞猜、结算 --- ## 2. 技术栈选型 ### 核心框架 ```json { "framework": "Vue 3", "buildTool": "Vite", "language": "TypeScript", "router": "Vue Router 4", "stateManagement": "Pinia", "uiFramework": "Element Plus / Ant Design Vue", "cssFramework": "Tailwind CSS / UnoCSS", "http": "Axios" } ``` ### 选型理由 #### Vue 3 + TypeScript - **组合式 API**: 更好的逻辑复用和代码组织 - **类型安全**: TypeScript提供完整的类型推导和检查 - **性能提升**: 更小的包体积、更快的渲染 - **生态成熟**: 丰富的插件和工具支持 #### Vite - **极速开发**: 基于ESM的即时热更新 - **快速构建**: Rollup打包,生产环境优化 - **现代化**: 原生支持ES模块、TypeScript、JSX #### Pinia - **Vue 3官方推荐**: 替代Vuex的下一代状态管理 - **类型友好**: 完整的TypeScript支持 - **轻量简洁**: API设计简洁,学习成本低 - **Devtools**: 优秀的开发者工具集成 #### Vue Router 4 - **官方路由**: Vue生态标准路由方案 - **动态路由**: 支持路由级代码分割 - **导航守卫**: 完善的权限控制 --- ## 3. 项目架构 ### 3.1 分层架构 ``` ┌─────────────────────────────────────┐ │ Presentation Layer │ │ (Components / Views / Layouts) │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Business Logic Layer │ │ (Composables / Stores / Hooks) │ └─────────────────────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ Data Access Layer │ │ (API Services / Local Storage) │ └─────────────────────────────────────┘ ``` ### 3.2 模块化设计 每个功能模块包含: - **Views**: 页面级组件 - **Components**: 模块内组件 - **Composables**: 业务逻辑复用 - **Stores**: 状态管理 - **API**: 接口请求 - **Types**: TypeScript类型定义 - **Utils**: 工具函数 --- ## 4. 目录结构 ``` GameGroupFE/ ├── public/ # 静态资源 │ ├── favicon.ico │ └── ... ├── src/ │ ├── assets/ # 资源文件 │ │ ├── images/ # 图片 │ │ ├── icons/ # 图标 │ │ └── styles/ # 全局样式 │ │ ├── variables.scss # 样式变量 │ │ ├── mixins.scss # 样式混入 │ │ └── global.scss # 全局样式 │ ├── components/ # 公共组件 │ │ ├── common/ # 通用组件 │ │ │ ├── Button/ │ │ │ ├── Input/ │ │ │ ├── Modal/ │ │ │ └── Loading/ │ │ ├── business/ # 业务组件 │ │ │ ├── UserCard/ │ │ │ ├── GroupCard/ │ │ │ └── GameCard/ │ │ └── layout/ # 布局组件 │ │ ├── Header/ │ │ ├── Sidebar/ │ │ └── Footer/ │ ├── composables/ # 组合式函数 │ │ ├── useAuth.ts # 认证相关 │ │ ├── useRequest.ts # 请求封装 │ │ ├── usePagination.ts # 分页逻辑 │ │ └── useWebSocket.ts # WebSocket │ ├── stores/ # Pinia状态管理 │ │ ├── auth.ts # 认证状态 │ │ ├── user.ts # 用户状态 │ │ ├── group.ts # 小组状态 │ │ └── app.ts # 应用状态 │ ├── api/ # API接口 │ │ ├── index.ts # Axios配置 │ │ ├── auth.ts # 认证接口 │ │ ├── user.ts # 用户接口 │ │ ├── group.ts # 小组接口 │ │ └── ... │ ├── router/ # 路由配置 │ │ ├── index.ts # 路由入口 │ │ ├── routes/ # 路由模块 │ │ └── guards.ts # 路由守卫 │ ├── views/ # 页面视图 │ │ ├── auth/ # 认证相关页面 │ │ │ ├── Login.vue │ │ │ └── Register.vue │ │ ├── home/ # 首页 │ │ │ └── index.vue │ │ ├── user/ # 用户中心 │ │ │ ├── Profile.vue │ │ │ └── Settings.vue │ │ ├── group/ # 小组管理 │ │ │ ├── List.vue │ │ │ ├── Detail.vue │ │ │ └── Create.vue │ │ ├── game/ # 游戏库 │ │ ├── appointment/ # 预约管理 │ │ └── ... │ ├── types/ # TypeScript类型定义 │ │ ├── api.ts # API响应类型 │ │ ├── user.ts # 用户类型 │ │ ├── group.ts # 小组类型 │ │ └── ... │ ├── utils/ # 工具函数 │ │ ├── request.ts # 请求工具 │ │ ├── storage.ts # 存储工具 │ │ ├── format.ts # 格式化工具 │ │ └── validate.ts # 验证工具 │ ├── constants/ # 常量定义 │ │ ├── enums.ts # 枚举 │ │ └── config.ts # 配置 │ ├── directives/ # 自定义指令 │ │ └── permission.ts │ ├── App.vue # 根组件 │ └── main.ts # 应用入口 ├── tests/ # 测试文件 │ ├── unit/ # 单元测试 │ └── e2e/ # E2E测试 ├── .env.development # 开发环境变量 ├── .env.production # 生产环境变量 ├── .eslintrc.cjs # ESLint配置 ├── .prettierrc # Prettier配置 ├── tsconfig.json # TypeScript配置 ├── vite.config.ts # Vite配置 ├── tailwind.config.js # Tailwind配置 └── package.json # 项目配置 ``` --- ## 5. 核心设计原则 ### 5.1 组件设计原则 #### 单一职责原则 每个组件只负责一个功能,保持组件的独立性和可复用性。 #### 组合优于继承 使用组合式API和props/events进行组件通信,避免复杂的继承关系。 #### 容器组件与展示组件分离 - **容器组件**: 处理业务逻辑和状态管理 - **展示组件**: 纯UI渲染,通过props接收数据 ### 5.2 代码规范 #### 命名规范 - **组件**: PascalCase (UserCard.vue) - **文件**: kebab-case (user-profile.ts) - **变量/函数**: camelCase (getUserInfo) - **常量**: UPPER_SNAKE_CASE (API_BASE_URL) - **类型/接口**: PascalCase (UserProfile) #### 文件组织 - 一个文件只导出一个主要内容 - 相关文件放在同一目录 - 使用index.ts统一导出 #### 注释规范 ```typescript /** * 获取用户信息 * @param userId - 用户ID * @returns 用户信息对象 */ async function getUserInfo(userId: string): Promise { // 实现 } ``` --- ## 6. 状态管理 ### 6.1 Pinia Store设计 #### 模块化Store 每个业务模块创建独立的Store: ```typescript // stores/user.ts export const useUserStore = defineStore('user', () => { // State const userInfo = ref(null) const isLoading = ref(false) // Getters const isLoggedIn = computed(() => !!userInfo.value) // Actions async function fetchUserInfo() { isLoading.value = true try { const data = await userApi.getProfile() userInfo.value = data } finally { isLoading.value = false } } return { userInfo, isLoading, isLoggedIn, fetchUserInfo } }) ``` #### 全局Store 应用级别的状态: ```typescript // stores/app.ts export const useAppStore = defineStore('app', () => { const theme = ref('light') const language = ref('zh-CN') const sidebarCollapsed = ref(false) function toggleTheme() { theme.value = theme.value === 'light' ? 'dark' : 'light' } return { theme, language, sidebarCollapsed, toggleTheme } }) ``` ### 6.2 持久化策略 使用`pinia-plugin-persistedstate`实现状态持久化: ```typescript // pinia.ts import { createPinia } from 'pinia' import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' const pinia = createPinia() pinia.use(piniaPluginPersistedstate) export default pinia ``` --- ## 7. 路由设计 ### 7.1 路由结构 ```typescript // router/index.ts const routes: RouteRecordRaw[] = [ { path: '/login', name: 'Login', component: () => import('@/views/auth/Login.vue'), meta: { requiresAuth: false } }, { path: '/', component: () => import('@/components/layout/MainLayout.vue'), meta: { requiresAuth: true }, children: [ { path: '', name: 'Home', component: () => import('@/views/home/index.vue') }, { path: 'groups', name: 'GroupList', component: () => import('@/views/group/List.vue') }, { path: 'groups/:id', name: 'GroupDetail', component: () => import('@/views/group/Detail.vue') }, // 更多路由... ] } ] ``` ### 7.2 路由守卫 ```typescript // router/guards.ts router.beforeEach((to, from, next) => { const authStore = useAuthStore() const requiresAuth = to.meta.requiresAuth !== false if (requiresAuth && !authStore.isLoggedIn) { // 未登录,跳转到登录页 next({ name: 'Login', query: { redirect: to.fullPath } }) } else { next() } }) ``` --- ## 8. API请求层 ### 8.1 Axios封装 ```typescript // api/index.ts import axios from 'axios' import { ElMessage } from 'element-plus' const service = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 15000 }) // 请求拦截器 service.interceptors.request.use( (config) => { const authStore = useAuthStore() if (authStore.token) { config.headers.Authorization = `Bearer ${authStore.token}` } return config }, (error) => { return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( (response) => { const { code, message, data } = response.data if (code === 0) { return data } else { ElMessage.error(message || '请求失败') return Promise.reject(new Error(message)) } }, (error) => { if (error.response?.status === 401) { // Token过期,刷新Token或跳转登录 const authStore = useAuthStore() authStore.logout() } return Promise.reject(error) } ) export default service ``` ### 8.2 API模块化 ```typescript // api/user.ts import request from './index' export const userApi = { // 获取用户信息 getProfile() { return request.get('/users/me') }, // 更新用户信息 updateProfile(data: UpdateProfileDto) { return request.put('/users/me', data) }, // 修改密码 changePassword(data: ChangePasswordDto) { return request.put('/users/me/password', data) } } ``` --- ## 9. 性能优化 ### 9.1 代码分割 #### 路由级代码分割 使用动态import实现路由懒加载: ```typescript { path: '/groups', component: () => import('@/views/group/List.vue') } ``` #### 组件级代码分割 ```vue ``` ### 9.2 资源优化 #### 图片优化 - 使用WebP格式 - 实现懒加载 - 响应式图片 #### 依赖优化 - Tree-shaking - 按需引入组件库 - 使用轻量级替代方案 ### 9.3 渲染优化 #### 虚拟滚动 长列表使用虚拟滚动: ```vue ``` #### 防抖与节流 ```typescript import { useDebounceFn } from '@vueuse/core' const search = useDebounceFn((keyword: string) => { // 执行搜索 }, 300) ``` ### 9.4 缓存策略 #### 接口缓存 ```typescript // api/cache.ts const cache = new Map() export async function cachedFetch( key: string, fetcher: () => Promise, ttl = 60000 ): Promise { const cached = cache.get(key) if (cached && Date.now() - cached.time < ttl) { return cached.data } const data = await fetcher() cache.set(key, { data, time: Date.now() }) return data } ``` #### 组件缓存 ```vue ``` --- ## 10. 开发工具链 ### 10.1 代码质量 - **ESLint**: 代码规范检查 - **Prettier**: 代码格式化 - **Stylelint**: 样式规范检查 - **TypeScript**: 类型检查 ### 10.2 Git规范 - **Husky**: Git hooks - **lint-staged**: 暂存文件检查 - **Commitlint**: 提交信息规范 ### 10.3 CI/CD - **GitHub Actions**: 自动化部署 - **Vercel/Netlify**: 前端托管 --- ## 11. 测试策略 ### 11.1 单元测试 使用Vitest进行单元测试: ```typescript // tests/utils/format.test.ts import { describe, it, expect } from 'vitest' import { formatDate } from '@/utils/format' describe('formatDate', () => { it('should format date correctly', () => { const date = new Date('2026-01-28') expect(formatDate(date)).toBe('2026-01-28') }) }) ``` ### 11.2 组件测试 使用Vue Test Utils: ```typescript import { mount } from '@vue/test-utils' import Button from '@/components/common/Button/Button.vue' describe('Button', () => { it('renders text', () => { const wrapper = mount(Button, { slots: { default: 'Click me' } }) expect(wrapper.text()).toBe('Click me') }) }) ``` --- ## 12. 部署方案 ### 12.1 构建配置 ```typescript // vite.config.ts export default defineConfig({ build: { target: 'es2015', outDir: 'dist', assetsDir: 'assets', sourcemap: false, minify: 'terser', terserOptions: { compress: { drop_console: true, drop_debugger: true } }, rollupOptions: { output: { manualChunks: { 'vendor': ['vue', 'vue-router', 'pinia'], 'ui': ['element-plus'] } } } } }) ``` ### 12.2 环境变量 ```bash # .env.development VITE_API_BASE_URL=http://localhost:3000/api # .env.production VITE_API_BASE_URL=https://api.gamegroup.com/api ``` --- ## 13. 总结 本架构设计遵循以下原则: - ✅ 模块化: 清晰的模块划分,职责明确 - ✅ 可维护性: 规范的代码组织,易于维护 - ✅ 可扩展性: 灵活的架构设计,便于扩展 - ✅ 性能优化: 多层次的优化策略 - ✅ 开发体验: 完善的工具链支持 --- **文档维护**: 本文档应随项目演进持续更新 **最后更新**: 2026-01-28