# 健身房管理系统前端开发规范文档 > 文档编号: GYM-FE-DEV-001 > 版本: v1.0 > 日期: 2026-03-04 > 作者: 张翔 > 状态: 初稿 --- ## 文档修订历史 | 版本 | 日期 | 作者 | 修订内容 | | ---- | ---------- | ---- | -------- | | v1.0 | 2026-03-04 | 张翔 | 创建前端开发规范 | --- ## 参考文档 - 《健身房管理系统前端技术架构详细设计》 GYM-FE-ARCH-001 - Vue 3 风格指南 - TypeScript 编码规范 - Airbnb JavaScript Style Guide --- ## 一、编码规范 ### 1.1 代码风格 #### 1.1.1 使用ESLint ```json // .eslintrc.json { "extends": [ "plugin:vue/vue3-recommended", "plugin:@typescript-eslint/recommended", "prettier" ], "rules": { "vue/multi-word-component-names": "off", "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "no-console": ["warn", { "allow": ["warn", "error"] }] } } ``` #### 1.1.2 使用Prettier ```json // .prettierrc { "semi": false, "singleQuote": true, "printWidth": 100, "trailingComma": "es5", "arrowParens": "avoid", "endOfLine": "lf" } ``` ### 1.2 命名规范 #### 1.2.1 文件命名 | 类型 | 命名规范 | 示例 | |------|---------|------| | **组件文件** | PascalCase | MemberList.vue, CourseCard.vue | | **工具文件** | camelCase | formatDate.ts, validator.ts | | **类型文件** | camelCase | api.ts, models.ts | | **常量文件** | UPPER_SNAKE_CASE | API_BASE_URL.ts | | **样式文件** | kebab-case | member-list.scss, button.css | #### 1.2.2 变量命名 ```typescript // 布尔值:使用is/has/can前缀 const isActive = true const hasPermission = false const canEdit = true // 常量:使用UPPER_SNAKE_CASE const API_BASE_URL = 'https://api.example.com' const MAX_RETRY_COUNT = 3 // 函数:使用camelCase,动词开头 function getMemberList() {} function validatePhoneNumber() {} function handleSearch() {} // 类:使用PascalCase class UserService {} class MemberValidator {} // 接口:使用PascalCase,I前缀可选 interface Member {} interface IMember {} // 类型别名:使用PascalCase type MemberStatus = 'active' | 'inactive' // 枚举:使用PascalCase enum MemberLevel { BRONZE = 1, SILVER = 2, GOLD = 3 } ``` #### 1.2.3 组件命名 ```vue ``` ### 1.3 代码格式 #### 1.3.1 缩进与空格 ```typescript // 使用2个空格缩进 function example() { if (condition) { doSomething() } } // 对象和数组使用空格 const obj = { a: 1, b: 2 } const arr = [1, 2, 3] // 运算符前后使用空格 const sum = a + b const result = a > b ? a : b ``` #### 1.3.2 引号使用 ```typescript // 优先使用单引号 const name = 'John' const message = 'Hello, world!' // 字符串中包含单引号时使用双引号 const quote = "It's a beautiful day" // 模板字符串使用反引号 const greeting = `Hello, ${name}!` ``` #### 1.3.3 分号使用 ```typescript // 不使用分号 const a = 1 const b = 2 function example() { return a + b } ``` --- ## 二、Vue组件规范 ### 2.1 组件结构 ```vue ``` ### 2.2 Props定义 ```typescript // 使用TypeScript接口定义Props interface Props { title: string count?: number items: string[] config: { enabled: boolean timeout: number } } // 使用withDefaults设置默认值 const props = withDefaults(defineProps(), { count: 0, items: () => [], config: () => ({ enabled: true, timeout: 5000 }) }) ``` ### 2.3 Emits定义 ```typescript // 使用TypeScript定义Emits const emit = defineEmits<{ click: [event: MouseEvent] change: [value: string] submit: [data: FormData] cancel: [] }>() // 触发事件 emit('click', event) emit('change', newValue) emit('submit', formData) emit('cancel') ``` ### 2.4 响应式数据 ```typescript // 使用ref定义基本类型 const count = ref(0) const message = ref('Hello') // 使用reactive定义对象 const user = reactive({ name: 'John', age: 30 }) // 使用computed定义计算属性 const fullName = computed(() => `${user.name} is ${user.age} years old`) // 使用readonly定义只读数据 const readonlyData = readonly({ id: 1, name: 'John' }) // 使用shallowRef和shallowReactive优化性能 const largeList = shallowRef([]) const largeObject = shallowReactive({}) ``` ### 2.5 组件通信 #### 2.5.1 Props传递 ```vue ``` #### 2.5.2 事件传递 ```vue ``` #### 2.5.3 Provide/Inject ```typescript // 父组件 import { provide } from 'vue' const theme = ref('light') provide('theme', theme) // 子组件 import { inject } from 'vue' const theme = inject>('theme') ``` --- ## 三、TypeScript规范 ### 3.1 类型定义 #### 3.1.1 基础类型 ```typescript // 使用明确的类型 const count: number = 10 const name: string = 'John' const isActive: boolean = true const items: string[] = ['a', 'b', 'c'] const user: { name: string; age: number } = { name: 'John', age: 30 } ``` #### 3.1.2 接口定义 ```typescript // 定义接口 interface Member { id: number name: string phone: string level: MemberLevel status: MemberStatus } // 可选属性 interface User { id: number name: string email?: string } // 只读属性 interface Config { readonly id: number name: string } // 索引签名 interface StringDictionary { [key: string]: string } ``` #### 3.1.3 类型别名 ```typescript // 定义类型别名 type MemberStatus = 'active' | 'inactive' | 'frozen' type MemberLevel = 1 | 2 | 3 | 4 | 5 // 联合类型 type ID = number | string // 交叉类型 type Name = { firstName: string; lastName: string } type Age = { age: number } type Person = Name & Age ``` #### 3.1.4 泛型 ```typescript // 泛型函数 function identity(arg: T): T { return arg } // 泛型接口 interface Response { code: number data: T message: string } // 泛型类 class Storage { private items: T[] = [] add(item: T): void { this.items.push(item) } get(index: number): T | undefined { return this.items[index] } } ``` ### 3.2 类型断言 ```typescript // 使用as关键字进行类型断言 const element = document.getElementById('app') as HTMLElement // 使用尖括号语法(JSX中不可用) const element2 = document.getElementById('app') // 非空断言 const value = input.value! ``` ### 3.3 类型守卫 ```typescript // typeof类型守卫 function processValue(value: string | number) { if (typeof value === 'string') { console.log(value.toUpperCase()) } else { console.log(value.toFixed(2)) } } // instanceof类型守卫 class Dog { bark() {} } class Cat { meow() {} } function makeSound(animal: Dog | Cat) { if (animal instanceof Dog) { animal.bark() } else { animal.meow() } } // 自定义类型守卫 interface Member { id: number name: string type: 'individual' | 'corporate' } function isCorporateMember(member: Member): member is Member & { type: 'corporate' } { return member.type === 'corporate' } ``` --- ## 四、注释规范 ### 4.1 文件注释 ```typescript /** * 会员服务 * * 提供会员相关的业务逻辑处理 * * @example * const memberService = new MemberService() * const members = await memberService.getList() */ export class MemberService { // ... } ``` ### 4.2 函数注释 ```typescript /** * 获取会员列表 * * @param params - 查询参数 * @param params.page - 页码 * @param params.pageSize - 每页数量 * @param params.keyword - 搜索关键词 * @returns 会员列表数据 * @throws {Error} 当API请求失败时抛出错误 * * @example * const result = await getMemberList({ page: 1, pageSize: 10 }) */ export async function getMemberList(params: { page: number pageSize: number keyword?: string }): Promise { // ... } ``` ### 4.3 类注释 ```typescript /** * 会员验证器 * * 提供会员数据验证功能 */ export class MemberValidator { /** * 验证手机号 * * @param phone - 手机号 * @returns 验证结果 */ validatePhone(phone: string): ValidationResult { // ... } } ``` ### 4.4 行内注释 ```typescript // 计算会员等级 const level = calculateLevel(exp) // TODO: 需要优化这个算法的性能 const result = complexCalculation(data) // FIXME: 这里有个bug,需要修复 const value = buggyFunction() // HACK: 临时解决方案,后续需要重构 const temp = workaround(data) ``` --- ## 五、文件组织规范 ### 5.1 目录结构 ``` src/ ├── api/ # API接口 │ ├── modules/ # API模块 │ │ ├── auth.ts │ │ ├── member.ts │ │ └── booking.ts │ └── request.ts # Axios封装 ├── assets/ # 静态资源 │ ├── images/ # 图片 │ ├── icons/ # 图标 │ └── styles/ # 样式 ├── components/ # 组件 │ ├── base/ # 基础组件 │ ├── business/ # 业务组件 │ └── layout/ # 布局组件 ├── composables/ # Composables ├── config/ # 配置 ├── directives/ # 自定义指令 ├── hooks/ # Hooks ├── layouts/ # 布局 ├── router/ # 路由 ├── stores/ # 状态管理 ├── types/ # 类型定义 ├── utils/ # 工具函数 ├── views/ # 页面 ├── App.vue └── main.ts ``` ### 5.2 文件导入顺序 ```typescript // 1. Vue相关导入 import { ref, computed, onMounted } from 'vue' import { useRouter } from 'vue-router' // 2. 第三方库导入 import axios from 'axios' import dayjs from 'dayjs' // 3. 内部模块导入 import { useAuthStore } from '@/stores/auth' import { formatDate } from '@/utils/formatter' // 4. 类型导入 import type { Member, MemberListParams } from '@/types/models' // 5. 样式导入 import './styles/index.scss' ``` ### 5.3 导出规范 ```typescript // 命名导出 export function formatDate(date: Date): string {} export function formatTime(time: Date): string {} // 默认导出(仅用于组件) export default defineComponent({ // ... }) // 类型导出 export type { Member, MemberStatus } export interface { MemberListParams } ``` --- ## 六、Git提交规范 ### 6.1 提交信息格式 ``` ():