Skip to content

Latest commit

 

History

History
1178 lines (957 loc) · 29.1 KB

File metadata and controls

1178 lines (957 loc) · 29.1 KB

开发规范

目录

  • 代码规范
  • Git规范
  • API规范
  • 数据库规范
  • 前端规范
  • 文档规范

代码规范

Go 代码规范

1. 命名规范
  • 包名:使用小写字母,不使用下划线,与目录名保持一致。
  • 变量名:使用驼峰命名法,首字母小写。
  • 常量名:使用驼峰命名法,首字母大写。
  • 函数名:使用驼峰命名法,首字母小写,公开函数首字母大写。
  • 结构体名:使用驼峰命名法,首字母大写。
  • 接口名:使用驼峰命名法,首字母大写,通常以 -er 结尾。
// 包名
package user

// 变量名
var userName string

// 常量名
const MaxCount = 100

// 函数名
func getUserInfo() UserInfo {
    // 函数体
}

// 公开函数名
func GetUserInfo() UserInfo {
    // 函数体
}

// 结构体名
type UserInfo struct {
    ID       int64
    Username string
}

// 接口名
type Reader interface {
    Read(p []byte) (n int, err error)
}
2. 注释规范
  • 包注释:放在包声明之前,描述包的功能。
  • 函数注释:放在函数声明之前,描述函数的功能、参数和返回值。
  • 结构体注释:放在结构体声明之前,描述结构体的功能。
  • 变量注释:放在变量声明之前,描述变量的用途。
// Package user 提供用户管理功能
package user

// GetUserInfo 获取用户信息
// 参数:
//   - id: 用户ID
// 返回值:
//   - UserInfo: 用户信息
//   - error: 错误信息
func GetUserInfo(id int64) (UserInfo, error) {
    // 函数体
}

// UserInfo 用户信息
type UserInfo struct {
    ID       int64  // 用户ID
    Username string // 用户名
}
3. 错误处理规范
  • 使用 errors.New 或 fmt.Errorf 创建错误。
  • 使用 errors.Is 或 errors.As 检查错误。
  • 错误信息应该小写,不以标点符号结尾。
import (
    "errors"
    "fmt"
)

// 定义错误
var ErrUserNotFound = errors.New("user not found")

// 创建错误
func getUser(id int64) (UserInfo, error) {
    if id <= 0 {
        return UserInfo{}, fmt.Errorf("invalid user id: %d", id)
    }
    
    // 查询用户
    user, err := queryUser(id)
    if err != nil {
        return UserInfo{}, fmt.Errorf("query user failed: %w", err)
    }
    
    if user.ID == 0 {
        return UserInfo{}, ErrUserNotFound
    }
    
    return user, nil
}

// 检查错误
func handleGetUser(id int64) {
    user, err := getUser(id)
    if err != nil {
        if errors.Is(err, ErrUserNotFound) {
            fmt.Println("user not found")
        } else {
            fmt.Printf("get user failed: %v\n", err)
        }
        return
    }
    
    fmt.Printf("user: %+v\n", user)
}
4. 导入规范
  • 按标准库、第三方库、本地库的顺序导入。
  • 每组导入之间用空行分隔。
  • 使用别名避免导入冲突。
import (
    "context"
    "fmt"
    "time"
    
    "github.com/gin-gonic/gin"
    "github.com/go-redis/redis/v8"
    "github.com/spf13/viper"
    
    "gin-fast/global"
    "gin-fast/models"
    "gin-fast/utils"
)
5. 结构体规范
  • 结构体字段使用驼峰命名法,首字母大写。
  • 结构体标签使用驼峰命名法,首字母小写。
  • 结构体标签应该放在同一行,如果太长可以换行。
// User 用户模型
type User struct {
    ID        int64     `json:"id" gorm:"primaryKey;autoIncrement;comment:用户ID"`
    Username  string    `json:"username" gorm:"type:varchar(50);uniqueIndex;not null;comment:用户名"`
    Password  string    `json:"-" gorm:"type:varchar(100);not null;comment:密码"`
    Nickname  string    `json:"nickname" gorm:"type:varchar(50);comment:昵称"`
    Email     string    `json:"email" gorm:"type:varchar(100);uniqueIndex;comment:邮箱"`
    Phone     string    `json:"phone" gorm:"type:varchar(20);uniqueIndex;comment:手机号"`
    Avatar    string    `json:"avatar" gorm:"type:varchar(255);comment:头像"`
    Status    int       `json:"status" gorm:"type:tinyint;default:1;comment:状态:1-启用,2-禁用"`
    CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"`
    UpdatedAt time.Time `json:"updatedAt" gorm:"comment:更新时间"`
}
6. 函数规范
  • 函数参数使用驼峰命名法,首字母小写。
  • 函数返回值使用驼峰命名法,首字母小写。
  • 函数参数和返回值应该有明确的类型。
  • 函数应该有明确的单一职责。
// GetUserByID 根据ID获取用户
func GetUserByID(ctx context.Context, id int64) (*User, error) {
    if id <= 0 {
        return nil, errors.New("invalid user id")
    }
    
    var user User
    if err := global.DB.WithContext(ctx).First(&user, id).Error; err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            return nil, errors.New("user not found")
        }
        return nil, fmt.Errorf("query user failed: %w", err)
    }
    
    return &user, nil
}
7. 接口规范
  • 接口名使用驼峰命名法,首字母大写,通常以 -er 结尾。
  • 接口方法使用驼峰命名法,首字母小写。
  • 接口应该有明确的单一职责。
// UserService 用户服务接口
type UserService interface {
    // GetUserByID 根据ID获取用户
    GetUserByID(ctx context.Context, id int64) (*User, error)
    
    // GetUserByUsername 根据用户名获取用户
    GetUserByUsername(ctx context.Context, username string) (*User, error)
    
    // CreateUser 创建用户
    CreateUser(ctx context.Context, user *User) error
    
    // UpdateUser 更新用户
    UpdateUser(ctx context.Context, user *User) error
    
    // DeleteUser 删除用户
    DeleteUser(ctx context.Context, id int64) error
}
8. 测试规范
  • 测试文件以 _test.go 结尾。
  • 测试函数以 Test 开头,接受 *testing.T 参数。
  • 测试用例应该覆盖正常情况和异常情况。
  • 使用表驱动测试。
package user

import (
    "context"
    "testing"
    
    "github.com/stretchr/testify/assert"
)

func TestGetUserByID(t *testing.T) {
    tests := []struct {
        name    string
        id      int64
        want    *User
        wantErr bool
    }{
        {
            name:    "valid id",
            id:      1,
            want:    &User{ID: 1, Username: "admin"},
            wantErr: false,
        },
        {
            name:    "invalid id",
            id:      0,
            want:    nil,
            wantErr: true,
        },
        {
            name:    "user not found",
            id:      999,
            want:    nil,
            wantErr: true,
        },
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := GetUserByID(context.Background(), tt.id)
            if tt.wantErr {
                assert.Error(t, err)
                assert.Nil(t, got)
            } else {
                assert.NoError(t, err)
                assert.Equal(t, tt.want, got)
            }
        })
    }
}

插件开发规范

1. 插件目录结构

插件统一放在 plugins/ 目录下,每个插件应具有以下标准结构:

plugins/
└── {plugin_name}/
    ├── controllers/     # 插件控制器
    ├── models/          # 插件数据模型和参数验证
    ├── routes/          # 插件路由注册
    └── {plugin_name}init.go  # 插件初始化文件

2. 插件开发步骤

2.1 创建插件目录结构

plugins/ 目录下创建插件文件夹,例如 plugins/example/

2.2 编写数据模型

plugins/{plugin_name}/models/ 目录下创建模型文件:

  • 继承 models.BaseModel 基础模型
  • 实现标准的 CRUD 方法(Create, Update, Delete, GetByID等)
  • 创建对应的参数验证模型(如 CreateRequest, UpdateRequest等)

示例:

// plugins/example/models/example.go
type Example struct {
    models.BaseModel
    Name        string `gorm:"type:varchar(255);comment:名称" json:"name"`
    Description string `gorm:"type:varchar(255);comment:描述" json:"description"`
    CreatedBy   uint   `gorm:"type:int(11);comment:创建者ID" json:"createdBy"`
}

// 实现标准方法
func (m *Example) GetByID(id uint) error {
    return app.DB().First(m, id).Error
}

func (m *Example) Create() error {
    return app.DB().Create(m).Error
}
2.3 编写控制器

plugins/{plugin_name}/controllers/ 目录下创建控制器文件:

  • 继承 controllers.Common 结构体以复用响应方法
  • 实现标准的 RESTful API 方法(Create, Update, Delete, GetByID, List等)
  • 使用参数验证模型进行输入验证
  • 使用统一的错误处理和响应格式

示例:

// plugins/example/controllers/example.go
type ExampleController struct {
    controllers.Common
}

func (ec *ExampleController) Create(c *gin.Context) {
    var req models.CreateRequest
    if err := req.Validate(c); err != nil {
        ec.FailAndAbort(c, err.Error(), err)
    }
    
    // 业务逻辑处理
    example := models.NewExample()
    example.Name = req.Name
    // ...
    
    if err := example.Create(); err != nil {
        ec.FailAndAbort(c, "创建示例失败", err)
    }
    
    ec.Success(c, gin.H{"id": example.ID})
}
2.4 注册路由

plugins/{plugin_name}/routes/routes.go 中注册插件路由:

  • 使用统一的路由前缀 /api/plugins/{plugin_name}
  • 应用必要的中间件(如 JWT 认证、Casbin 权限验证)
  • 注册控制器方法到对应路由

示例:

// plugins/example/routes/routes.go
func RegisterRoutes(engine *gin.Engine) {
    example := engine.Group("/api/plugins/example")
    example.Use(middleware.JWTAuthMiddleware())
    example.Use(middleware.CasbinMiddleware())
    {
        example.POST("/add", exampleControllers.Create)
        example.PUT("/edit", exampleControllers.Update)
        // ...
    }
}
2.5 插件初始化

创建 plugins/{plugin_name}/{plugin_name}init.go 文件,在 init() 函数中注册插件路由:

  • 使用 ginhelper.RegisterPluginRoutes 注册路由
  • 记录插件初始化日志

示例:

// plugins/example/exampleinit.go
func init() {
    ginhelper.RegisterPluginRoutes(func(engine *gin.Engine) {
        routes.RegisterRoutes(engine)
    })
    app.ZapLog.Info("示例插件初始化完成")
}
2.6 参数验证

plugins/{plugin_name}/models/ 中创建参数验证模型:

  • 继承 models.Validatormodels.BasePaging(分页查询时)
  • 实现 Validate 方法进行参数验证
  • 实现 Handle 方法处理查询条件

示例:

// plugins/example/models/exampleparam.go
type CreateRequest struct {
    models.Validator
    Name        string `json:"name" binding:"required"`
    Description string `json:"description" binding:"required"`
}

func (r *CreateRequest) Validate(c *gin.Context) error {
    return r.Validator.Check(c, r)
}

3. 插件规范要求

3.1 命名规范
  • 插件目录名应使用小写字母和下划线命名
  • 控制器、模型、路由文件名应与功能对应,使用小写字母和下划线
  • 结构体和方法名遵循 Go 语言命名规范
3.2 接口一致性
  • 插件控制器必须继承 controllers.Common 结构体
  • 插件模型应继承 models.BaseModel 基础模型
  • 使用统一的错误处理和响应格式
3.3 路由规范
  • 插件路由必须以 /api/plugins/{plugin_name} 为前缀
  • 必须应用 JWT 认证中间件确保安全性
  • 根据需要应用 Casbin 权限验证中间件
3.4 日志记录
  • 使用 app.ZapLog 记录插件相关日志
  • 在关键操作和初始化时添加日志记录
3.5 数据库操作
  • 使用 app.DB() 获取数据库连接
  • 遵循 GORM 的操作规范
  • 注意处理数据库错误

Git规范

1. 分支管理

  • master:主分支,用于生产环境,始终保持稳定可运行状态。
  • develop:开发分支,用于集成开发,始终保持最新开发状态。
  • feature/:功能分支,用于开发新功能,从 develop 分支创建,完成后合并到 develop 分支。
  • release/:发布分支,用于发布准备,从 develop 分支创建,完成后合并到 master 和 develop 分支。
  • hotfix/:修复分支,用于紧急修复,从 master 分支创建,完成后合并到 master 和 develop 分支。

2. 提交规范

  • 提交信息格式:<type>(<scope>): <subject>
  • 提交信息应该简明扼要,不超过 50 个字符。
  • 提交信息应该使用祈使语气,如 "fix bug" 而不是 "fixed bug"。
  • 提交信息应该描述做了什么,而不是为什么做。
# 提交信息格式
<type>(<scope>): <subject>

# 提交信息示例
feat(auth): add login function
fix(user): fix user list pagination error
docs(readme): update installation guide
style(format): format code with gofmt
refactor(user): refactor user service
perf(api): optimize api response time
test(user): add user service tests
chore(deps): update dependencies

3. 提交类型

  • feat: 新功能
  • fix: 修复bug
  • docs: 文档更新
  • style: 代码格式(不影响代码运行的变动)
  • refactor: 重构(既不是新增功能,也不是修改bug的代码变动)
  • perf: 性能优化
  • test: 增加测试
  • chore: 构建过程或辅助工具的变动

4. 提交范围

提交范围应该是一个名词,描述提交影响的模块或功能。

# 提交范围示例
feat(auth): add login function
fix(user): fix user list pagination error
docs(readme): update installation guide
style(format): format code with gofmt
refactor(user): refactor user service
perf(api): optimize api response time
test(user): add user service tests
chore(deps): update dependencies

5. 提交主体

提交主体应该描述做了什么,使用祈使语气,不超过 50 个字符。

# 提交主体示例
feat(auth): add login function
fix(user): fix user list pagination error
docs(readme): update installation guide
style(format): format code with gofmt
refactor(user): refactor user service
perf(api): optimize api response time
test(user): add user service tests
chore(deps): update dependencies

6. 提交正文

提交正文应该详细描述提交的内容,包括为什么做、怎么做的、有什么影响等。

# 提交正文示例
feat(auth): add login function

- Add login function with username and password
- Add JWT token generation and validation
- Add password encryption with bcrypt
- Add login rate limiting
- Add login logging

7. 提交脚注

提交脚注应该包含相关的引用、链接、问题编号等。

# 提交脚注示例
feat(auth): add login function

- Add login function with username and password
- Add JWT token generation and validation
- Add password encryption with bcrypt
- Add login rate limiting
- Add login logging

Closes #123

API规范

1. URL规范

  • 使用小写字母,不使用下划线,使用连字符分隔单词。
  • 使用名词复数形式表示资源集合。
  • 使用 HTTP 方法表示操作类型。
# URL规范示例
GET    /api/users          # 获取用户列表
POST   /api/users          # 创建用户
GET    /api/users/{id}     # 获取用户详情
PUT    /api/users/{id}     # 更新用户
DELETE /api/users/{id}     # 删除用户
GET    /api/users/{id}/roles # 获取用户角色
POST   /api/users/{id}/roles # 分配用户角色

2. 请求规范

  • 使用 JSON 格式传输数据。
  • 使用 Content-Type: application/json 标识请求体格式。
  • 使用 Accept: application/json 标识响应体格式。
# 请求规范示例
GET /api/users HTTP/1.1
Host: example.com
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{
  "username": "test",
  "password": "123456",
  "nickname": "测试用户",
  "email": "test@example.com",
  "phone": "13800138000"
}

3. 响应规范

  • 使用 JSON 格式传输数据。
  • 使用统一的响应格式。
// 响应格式示例
{
  "code": 0,
  "msg": "success",
  "data": {
    // 响应数据
  }
}

4. 状态码规范

  • 使用 HTTP 状态码表示请求结果。
  • 使用自定义状态码表示业务结果。
# HTTP状态码示例
200 OK                    # 请求成功
201 Created               # 资源创建成功
204 No Content            # 资源删除成功
400 Bad Request           # 请求参数错误
401 Unauthorized          # 未授权
403 Forbidden             # 禁止访问
404 Not Found             # 资源不存在
422 Unprocessable Entity  # 请求参数验证失败
500 Internal Server Error # 服务器内部错误

# 自定义状态码示例
0     # 成功
1001  # 参数错误
1002  # 用户不存在
1003  # 密码错误
1004  # 用户已存在
1005  # 验证码错误
1006  # 验证码过期
1007  # 令牌无效
1008  # 令牌过期
1009  # 权限不足
1010  # 系统错误

5. 分页规范

  • 使用 page 和 pageSize 参数表示分页。
  • 使用 total 表示总记录数。
  • 使用 list 表示数据列表。
// 分页响应示例
{
  "code": 0,
  "msg": "success",
  "data": {
    "list": [
      {
        "id": 1,
        "username": "admin",
        "nickname": "管理员",
        "email": "admin@example.com",
        "phone": "13800138000",
        "status": 1,
        "createdAt": "2023-01-01T00:00:00Z",
        "updatedAt": "2023-01-01T00:00:00Z"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 10
  }
}

6. 错误规范

  • 使用 code 和 msg 表示错误信息。
  • 使用 data 表示错误详情。
// 错误响应示例
{
  "code": 1002,
  "msg": "用户不存在",
  "data": null
}

数据库规范

1. 命名规范

  • 数据库名:使用小写字母,不使用下划线,使用连字符分隔单词。
  • 表名:使用小写字母,不使用下划线,使用连字符分隔单词,使用名词复数形式。
  • 字段名:使用小写字母,不使用下划线,使用连字符分隔单词。
  • 索引名:使用小写字母,不使用下划线,使用连字符分隔单词,以 idx_uniq_ 开头。
-- 数据库名
gin-fast

-- 表名
users
user-roles
sys-menus
sys-roles

-- 字段名
id
user-name
created-at
updated-at

-- 索引名
idx-user-name
uniq-user-name

2. 字段规范

  • 使用 id 作为主键,类型为 bigint,自增。
  • 使用 created-at 和 updated-at 作为时间戳,类型为 datetime。
  • 使用 deleted-at 作为软删除标记,类型为 datetime,允许为空。
  • 使用 status 作为状态标记,类型为 tinyint,默认值为 1。
-- 用户表
CREATE TABLE users (
  id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  user-name varchar(50) NOT NULL COMMENT '用户名',
  password varchar(100) NOT NULL COMMENT '密码',
  nick-name varchar(50) DEFAULT NULL COMMENT '昵称',
  email varchar(100) DEFAULT NULL COMMENT '邮箱',
  phone varchar(20) DEFAULT NULL COMMENT '手机号',
  avatar varchar(255) DEFAULT NULL COMMENT '头像',
  status tinyint(1) DEFAULT 1 COMMENT '状态:1-启用,2-禁用',
  created-at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  updated-at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  deleted-at datetime DEFAULT NULL COMMENT '删除时间',
  PRIMARY KEY (id),
  UNIQUE KEY uniq-user-name (user-name),
  UNIQUE KEY uniq-email (email),
  UNIQUE KEY uniq-phone (phone),
  KEY idx-status (status),
  KEY idx-created-at (created-at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

3. 索引规范

  • 主键使用聚簇索引。
  • 外键使用普通索引。
  • 唯一键使用唯一索引。
  • 查询条件使用普通索引。
  • 排序字段使用普通索引。
-- 主键索引
PRIMARY KEY (id)

-- 唯一索引
UNIQUE KEY uniq-user-name (user-name)

-- 普通索引
KEY idx-status (status)
KEY idx-created-at (created-at)

4. 注释规范

  • 表注释应该描述表的用途。
  • 字段注释应该描述字段的用途和取值范围。
-- 表注释
CREATE TABLE users (
  -- 字段定义
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 字段注释
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
user-name varchar(50) NOT NULL COMMENT '用户名',
status tinyint(1) DEFAULT 1 COMMENT '状态:1-启用,2-禁用',

前端规范

1. 命名规范

  • 文件名:使用 kebab-case 命名法,如 user-list.vue
  • 组件名:使用 PascalCase 命名法,如 UserList
  • 变量名:使用 camelCase 命名法,如 userName
  • 常量名:使用 UPPER_SNAKE_CASE 命名法,如 MAX_COUNT
  • 函数名:使用 camelCase 命名法,如 getUserList
  • 类名:使用 PascalCase 命名法,如 UserService
  • CSS类名:使用 kebab-case 命名法,如 user-list
// 文件名
user-list.vue

// 组件名
export default {
  name: 'UserList'
}

// 变量名
const userName = 'admin'

// 常量名
const MAX_COUNT = 100

// 函数名
function getUserList() {
  // 函数体
}

// 类名
class UserService {
  // 类定义
}

// CSS类名
.user-list {
  // 样式定义
}

2. 组件规范

  • 组件应该有明确的单一职责。
  • 组件应该使用 <script setup> 语法。
  • 组件应该使用 TypeScript 类型。
  • 组件应该使用 scoped 样式。
<template>
  <div class="user-list">
    <!-- 组件模板 -->
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import type { User } from '@/types/user'

// 组件逻辑
</script>

<style lang="scss" scoped>
.user-list {
  // 组件样式
}
</style>

3. API 规范

  • 使用 axios 发送 HTTP 请求。
  • 使用 TypeScript 类型定义请求参数和响应数据。
  • 使用统一的错误处理。
// API 定义
import request from '@/utils/request'
import type { User, UserListParams } from '@/types/user'

// 获取用户列表
export function getUserList(params: UserListParams) {
  return request({
    url: '/api/users',
    method: 'get',
    params
  })
}

// 创建用户
export function createUser(data: Partial<User>) {
  return request({
    url: '/api/users',
    method: 'post',
    data
  })
}

// 更新用户
export function updateUser(id: number, data: Partial<User>) {
  return request({
    url: `/api/users/${id}`,
    method: 'put',
    data
  })
}

// 删除用户
export function deleteUser(id: number) {
  return request({
    url: `/api/users/${id}`,
    method: 'delete'
  })
}

4. 状态管理规范

  • 使用 Pinia 进行状态管理。
  • 使用 TypeScript 类型定义状态。
  • 使用统一的错误处理。
// 状态定义
import { defineStore } from 'pinia'
import type { User } from '@/types/user'
import { getUserList, createUser, updateUser, deleteUser } from '@/api/user'

interface UserState {
  users: User[]
  total: number
  loading: boolean
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    users: [],
    total: 0,
    loading: false
  }),
  
  getters: {
    userList: (state) => state.users,
    userTotal: (state) => state.total,
    userLoading: (state) => state.loading
  },
  
  actions: {
    // 获取用户列表
    async getUserList(params: any) {
      this.loading = true
      try {
        const res = await getUserList(params)
        this.users = res.data.list
        this.total = res.data.total
      } catch (error) {
        console.error(error)
      } finally {
        this.loading = false
      }
    },
    
    // 创建用户
    async createUser(data: Partial<User>) {
      try {
        await createUser(data)
        // 重新获取用户列表
        await this.getUserList({})
      } catch (error) {
        console.error(error)
      }
    },
    
    // 更新用户
    async updateUser(id: number, data: Partial<User>) {
      try {
        await updateUser(id, data)
        // 重新获取用户列表
        await this.getUserList({})
      } catch (error) {
        console.error(error)
      }
    },
    
    // 删除用户
    async deleteUser(id: number) {
      try {
        await deleteUser(id)
        // 重新获取用户列表
        await this.getUserList({})
      } catch (error) {
        console.error(error)
      }
    }
  }
})

5. 路由规范

  • 使用 Vue Router 进行路由管理。
  • 使用 TypeScript 类型定义路由。
  • 使用路由守卫进行权限控制。
// 路由定义
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import type { RouteMeta } from '@/types/router'

const routes: Array<RouteRecordRaw> = [
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/auth/login.vue'),
    meta: {
      title: '登录',
      hidden: true
    } as RouteMeta
  },
  {
    path: '/',
    name: 'Layout',
    component: () => import('@/layout/index.vue'),
    redirect: '/dashboard',
    meta: {
      title: '首页',
      icon: 'dashboard'
    } as RouteMeta,
    children: [
      {
        path: 'dashboard',
        name: 'Dashboard',
        component: () => import('@/views/dashboard/index.vue'),
        meta: {
          title: '仪表盘',
          icon: 'dashboard',
          affix: true
        } as RouteMeta
      },
      {
        path: 'user',
        name: 'User',
        component: () => import('@/views/user/index.vue'),
        meta: {
          title: '用户管理',
          icon: 'user',
          roles: ['admin']
        } as RouteMeta
      }
    ]
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

6. 样式规范

  • 使用 SCSS 预处理器。
  • 使用 BEM 命名规范。
  • 使用变量定义颜色、字体等。
// 变量定义
$primary-color: #1890ff;
$success-color: #52c41a;
$warning-color: #faad14;
$error-color: #f5222d;
$text-color: rgba(0, 0, 0, 0.85);
$text-color-secondary: rgba(0, 0, 0, 0.45);
$border-color: #d9d9d9;
$background-color: #f0f2f5;
$font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
$font-size-base: 14px;
$line-height-base: 1.5;

// BEM 命名规范
.user-list {
  // Block
  display: flex;
  flex-direction: column;
  
  // Element
  &__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px;
    background-color: #fff;
    border-bottom: 1px solid $border-color;
  }
  
  &__title {
    margin: 0;
    font-size: 16px;
    font-weight: 500;
    color: $text-color;
  }
  
  &__actions {
    display: flex;
    gap: 8px;
  }
  
  &__content {
    flex: 1;
    padding: 16px;
    background-color: #fff;
  }
  
  // Modifier
  &--loading {
    opacity: 0.5;
    pointer-events: none;
  }
}

文档规范

1. 文档结构

  • README.md:项目说明文档,包含项目概述、功能特性、技术栈、安装说明等。
  • docs/:文档目录,包含详细的技术文档。
    • introduction.md:系统介绍文档,包含项目概述、核心特性、技术栈、系统架构、功能模块、适用场景等。
    • environment.md:环境搭建文档,包含环境要求、开发工具、环境配置、验证环境等。
    • installation.md:系统安装文档,包含安装概述、后端安装、前端安装、数据库初始化、系统配置、启动系统、验证安装等。
    • catalog.md:目录结构文档,包含项目结构、目录说明、文件说明、模块说明等。
    • exploit.md:开发规范文档,包含代码规范、Git规范、API规范、数据库规范、前端规范、文档规范等。
    • frontend-*.md:前端文档,包含前端介绍、前端环境、前端目录、前端指南等。
    • deployment.md:部署指南文档,包含部署概述、环境准备、后端部署、前端部署、Nginx配置、Docker部署、常见问题等。
    • faq.md:常见问题文档,包含开发环境问题、后端问题、前端问题、部署问题、数据库问题、权限问题、性能问题、其他问题等。

2. 文档格式

  • 使用 Markdown 格式编写文档。
  • 使用 TOC(目录)插件生成目录。
  • 使用代码块展示代码示例。
  • 使用表格展示数据。
  • 使用列表展示步骤。

3. 文档内容

  • 文档应该简明扼要,易于理解。
  • 文档应该包含必要的示例和说明。
  • 文档应该保持最新,与代码同步更新。
  • 文档应该使用统一的格式和风格。

4. 文档更新

  • 代码变更时,应该同步更新相关文档。
  • 文档更新时,应该提交单独的提交记录。
  • 文档更新时,应该包含更新说明。
# 文档更新提交示例
docs(readme): update installation guide

- Add Docker installation guide
- Update environment requirements
- Fix typos in installation steps

总结

通过以上规范,我们可以确保代码质量、提高开发效率、降低维护成本。在实际开发中,请严格遵守这些规范,确保项目的一致性和可维护性。