# 健身房管理系统前端开发规范文档
> 文档编号: 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 提交信息格式
```
():
]