Files
gym-manage/docs/design/前端开发规范.md
T
2026-03-05 13:48:13 +08:00

19 KiB
Raw Blame History

健身房管理系统前端开发规范文档

文档编号: 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

// .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

// .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 变量命名

// 布尔值:使用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 {}

// 接口:使用PascalCaseI前缀可选
interface Member {}
interface IMember {}

// 类型别名:使用PascalCase
type MemberStatus = 'active' | 'inactive'

// 枚举:使用PascalCase
enum MemberLevel {
  BRONZE = 1,
  SILVER = 2,
  GOLD = 3
}

1.2.3 组件命名

<!-- 组件名称使用PascalCase -->
<template>
  <MemberList />
  <CourseCard />
</template>

<script setup lang="ts">
// 组件文件名与组件名一致
const componentName = 'MemberList'
</script>

1.3 代码格式

1.3.1 缩进与空格

// 使用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 引号使用

// 优先使用单引号
const name = 'John'
const message = 'Hello, world!'

// 字符串中包含单引号时使用双引号
const quote = "It's a beautiful day"

// 模板字符串使用反引号
const greeting = `Hello, ${name}!`

1.3.3 分号使用

// 不使用分号
const a = 1
const b = 2
function example() {
  return a + b
}

二、Vue组件规范

2.1 组件结构

<template>
  <!-- 模板内容 -->
</template>

<script setup lang="ts">
// 导入
import { ref, computed, onMounted } from 'vue'
import { useAuthStore } from '@/stores/auth'

// Props定义
interface Props {
  title: string
  count?: number
}

const props = withDefaults(defineProps<Props>(), {
  count: 0
})

// Emits定义
const emit = defineEmits<{
  click: [event: MouseEvent]
  change: [value: string]
}>()

// 响应式数据
const count = ref(0)
const message = ref('Hello')

// 计算属性
const doubled = computed(() => count.value * 2)

// 方法
const handleClick = (event: MouseEvent) => {
  emit('click', event)
}

// 生命周期
onMounted(() => {
  console.log('Component mounted')
})
</script>

<style scoped lang="scss">
/* 样式内容 */
</style>

2.2 Props定义

// 使用TypeScript接口定义Props
interface Props {
  title: string
  count?: number
  items: string[]
  config: {
    enabled: boolean
    timeout: number
  }
}

// 使用withDefaults设置默认值
const props = withDefaults(defineProps<Props>(), {
  count: 0,
  items: () => [],
  config: () => ({ enabled: true, timeout: 5000 })
})

2.3 Emits定义

// 使用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 响应式数据

// 使用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<any[]>([])
const largeObject = shallowReactive({})

2.5 组件通信

2.5.1 Props传递

<!-- 父组件 -->
<template>
  <child-component
    :title="pageTitle"
    :count="itemCount"
    @update="handleUpdate"
  />
</template>

<script setup lang="ts">
import ChildComponent from './ChildComponent.vue'

const pageTitle = ref('Dashboard')
const itemCount = ref(10)
const handleUpdate = (value: any) => {
  console.log('Update:', value)
}
</script>

2.5.2 事件传递

<!-- 子组件 -->
<template>
  <button @click="handleClick">Click me</button>
</template>

<script setup lang="ts">
const emit = defineEmits<{
  click: [event: MouseEvent]
}>()

const handleClick = (event: MouseEvent) => {
  emit('click', event)
}
</script>

2.5.3 Provide/Inject

// 父组件
import { provide } from 'vue'

const theme = ref('light')
provide('theme', theme)

// 子组件
import { inject } from 'vue'

const theme = inject<Ref<string>>('theme')

三、TypeScript规范

3.1 类型定义

3.1.1 基础类型

// 使用明确的类型
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 接口定义

// 定义接口
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 类型别名

// 定义类型别名
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 泛型

// 泛型函数
function identity<T>(arg: T): T {
  return arg
}

// 泛型接口
interface Response<T> {
  code: number
  data: T
  message: string
}

// 泛型类
class Storage<T> {
  private items: T[] = []
  
  add(item: T): void {
    this.items.push(item)
  }
  
  get(index: number): T | undefined {
    return this.items[index]
  }
}

3.2 类型断言

// 使用as关键字进行类型断言
const element = document.getElementById('app') as HTMLElement

// 使用尖括号语法(JSX中不可用)
const element2 = <HTMLElement>document.getElementById('app')

// 非空断言
const value = input.value!

3.3 类型守卫

// 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 文件注释

/**
 * 会员服务
 * 
 * 提供会员相关的业务逻辑处理
 * 
 * @example
 * const memberService = new MemberService()
 * const members = await memberService.getList()
 */
export class MemberService {
  // ...
}

4.2 函数注释

/**
 * 获取会员列表
 * 
 * @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<MemberListResponse> {
  // ...
}

4.3 类注释

/**
 * 会员验证器
 * 
 * 提供会员数据验证功能
 */
export class MemberValidator {
  /**
   * 验证手机号
   * 
   * @param phone - 手机号
   * @returns 验证结果
   */
  validatePhone(phone: string): ValidationResult {
    // ...
  }
}

4.4 行内注释

// 计算会员等级
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 文件导入顺序

// 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 导出规范

// 命名导出
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 提交信息格式

<type>(<scope>): <subject>

<body>

<footer>

6.2 Type类型

Type 描述 示例
feat 新功能 feat(member): add member list page
fix 修复bug fix(booking): resolve booking conflict
docs 文档更新 docs(readme): update installation guide
style 代码格式调整 style(member): format member component
refactor 重构 refactor(auth): simplify login logic
perf 性能优化 perf(list): optimize virtual scroll
test 测试相关 test(member): add member validator tests
chore 构建过程或辅助工具变动 chore(deps): update dependencies
ci CI配置文件更新 ci(github): add workflow config

6.3 Scope范围

Scope 描述
auth 认证相关
member 会员相关
booking 预约相关
checkin 签到相关
course 课程相关
finance 财务相关
data 数据相关
system 系统相关
ui UI组件
utils 工具函数

6.4 提交示例

# 新功能
git commit -m "feat(member): add member search functionality"

# 修复bug
git commit -m "fix(booking): resolve booking time conflict issue"

# 文档更新
git commit -m "docs(readme): update project setup instructions"

# 性能优化
git commit -m "perf(list): optimize virtual scroll performance"

# 重构
git commit -m "refactor(auth): simplify authentication flow"

七、代码审查规范

7.1 审查清单

7.1.1 功能性

  • 代码实现了需求文档中的功能
  • 代码逻辑正确,没有明显的bug
  • 边界情况得到处理
  • 错误处理完善

7.1.2 代码质量

  • 代码符合项目编码规范
  • 代码结构清晰,易于理解
  • 代码有适当的注释
  • 变量和函数命名准确

7.1.3 性能

  • 没有明显的性能问题
  • 使用了适当的优化技术
  • 没有不必要的重复计算
  • 大数据量处理使用了虚拟滚动

7.1.4 安全性

  • 输入验证完善
  • 敏感数据加密存储
  • 没有XSS、CSRF等安全漏洞
  • 权限控制正确

7.1.5 测试

  • 单元测试覆盖率达标
  • 测试用例充分
  • 测试通过
  • 没有测试警告

7.2 审查流程

  1. 提交Pull Request

    • 确保代码通过所有检查
    • 编写清晰的PR描述
    • 关联相关的Issue
  2. 代码审查

    • 至少一名审查者批准
    • 解决所有审查意见
    • 确保没有冲突
  3. 合并代码

    • 确保CI/CD通过
    • 删除功能分支
    • 更新相关文档

八、最佳实践

8.1 组件设计

8.1.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>

8.1.2 Props验证

// 使用TypeScript接口定义Props
interface Props {
  title: string
  count?: number
  items: string[]
}

const props = withDefaults(defineProps<Props>(), {
  count: 0,
  items: () => []
})

8.2 状态管理

8.2.1 合理使用状态

// 全局状态:用户信息、权限等
const authStore = useAuthStore()

// 模块状态:当前页面数据
const pageData = ref({})

// 组件状态:弹窗显示、加载状态
const showModal = ref(false)
const loading = ref(false)

8.2.2 避免状态冗余

// Bad: 冗余状态
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed(() => `${firstName.value} ${lastName.value}`)

// Good: 单一数据源
const user = reactive({
  firstName: 'John',
  lastName: 'Doe'
})
const fullName = computed(() => `${user.firstName} ${user.lastName}`)

8.3 错误处理

8.3.1 统一错误处理

// utils/errorHandler.ts
export function handleError(error: unknown): void {
  if (error instanceof Error) {
    console.error('Error:', error.message)
    // 显示错误提示
    showErrorToast(error.message)
  } else {
    console.error('Unknown error:', error)
    showErrorToast('发生未知错误')
  }
}

// 使用
try {
  await api.getMemberList()
} catch (error) {
  handleError(error)
}

8.3.2 错误边界

<template>
  <error-boundary @error="handleError">
    <router-view />
  </error-boundary>
</template>

<script setup lang="ts">
const handleError = (error: Error) => {
  console.error('Error caught by boundary:', error)
}
</script>

8.4 性能优化

8.4.1 避免不必要的响应式

// Bad: 所有数据都是响应式
const config = reactive({
  apiBaseUrl: 'https://api.example.com',
  timeout: 5000,
  maxRetries: 3
})

// Good: 常量不需要响应式
const API_BASE_URL = 'https://api.example.com'
const TIMEOUT = 5000
const MAX_RETRIES = 3

8.4.2 使用计算属性缓存

// Good: 使用computed缓存结果
const filteredMembers = computed(() => {
  return memberList.value.filter(member =>
    member.name.includes(searchKeyword.value)
  )
})

九、开发流程

9.1 分支管理

main (主分支)
├── develop (开发分支)
│   ├── feature/member-list (功能分支)
│   ├── feature/booking-system (功能分支)
│   └── fix/booking-bug (修复分支)
└── release/v1.0.0 (发布分支)

9.2 开发流程

  1. 创建功能分支

    git checkout develop
    git pull origin develop
    git checkout -b feature/member-list
    
  2. 开发功能

    • 按照编码规范编写代码
    • 编写单元测试
    • 本地测试通过
  3. 提交代码

    git add .
    git commit -m "feat(member): add member list page"
    git push origin feature/member-list
    
  4. 创建Pull Request

    • 编写清晰的PR描述
    • 关联相关的Issue
    • 请求代码审查
  5. 代码审查

    • 至少一名审查者批准
    • 解决所有审查意见
  6. 合并代码

    • 合并到develop分支
    • 删除功能分支

9.3 发布流程

  1. 创建发布分支

    git checkout develop
    git pull origin develop
    git checkout -b release/v1.0.0
    
  2. 发布准备

    • 更新版本号
    • 更新CHANGELOG
    • 运行完整测试
  3. 合并到main

    git checkout main
    git merge release/v1.0.0
    git tag v1.0.0
    git push origin main --tags
    
  4. 合并回develop

    git checkout develop
    git merge release/v1.0.0
    git push origin develop
    

十、总结

本文档详细描述了健身房管理系统前端的开发规范,包括:

  1. 编码规范:代码风格、命名规范、代码格式
  2. Vue组件规范:组件结构、Props定义、Emits定义、响应式数据、组件通信
  3. TypeScript规范:类型定义、类型断言、类型守卫
  4. 注释规范:文件注释、函数注释、类注释、行内注释
  5. 文件组织规范:目录结构、文件导入顺序、导出规范
  6. Git提交规范:提交信息格式、Type类型、Scope范围、提交示例
  7. 代码审查规范:审查清单、审查流程
  8. 最佳实践:组件设计、状态管理、错误处理、性能优化
  9. 开发流程:分支管理、开发流程、发布流程

通过遵循本文档的开发规范,可以确保代码质量、提高开发效率、降低维护成本。