mirror of
https://github.com/Lydanne/spaceflow.git
synced 2026-03-11 19:52:45 +08:00
chore: 初始化仓库
This commit is contained in:
186
references/js&ts.base.md
Normal file
186
references/js&ts.base.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# 基础代码规范 `[JsTs.Base]`
|
||||
|
||||
下面是 JS/TS 的代码规范
|
||||
|
||||
## 常量名使用大写加下划线命名(UPPER_CASE),单词间以下划线分隔 `[JsTs.Base.ConstUpperCase]`
|
||||
|
||||
- 不检查 nodejs 的导包定义,比如 `const fs = require("fs")`
|
||||
- 常量检查只需检查 `const` 声明的静态值,但是不包含对象和函数
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const MAX_COUNT = 100;
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const maxCount = 100;
|
||||
```
|
||||
|
||||
## 函数名使用小驼峰命名 `[JsTs.Base.FuncLowerCamel]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
function getuserinfo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 禁止使用字面量魔法字符串和魔法数字 `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
- 只检查数字、字符串、正则字面量,不要检查其他(比如 布尔字面量、对象字面量、函数字面量、数组字面量)
|
||||
- 这块只检查含义不明确的字面量,比如 0 1 500 等,像是 'user' 'admin' 'active' 'inactive' 等是合理的
|
||||
- 无需检查单词是否完整拼写
|
||||
- throw 的错误信息无需审查
|
||||
- new Error 的错误信息无需审查
|
||||
- console.log 的打印代码无需审查
|
||||
- console.error 的错误信息无需审查
|
||||
- console.warn 的错误信息无需审查
|
||||
- console.info 的错误信息无需审查
|
||||
- console.debug 的错误信息无需审查
|
||||
- console.trace 的错误信息无需审查
|
||||
- 无需考虑类型是否合理匹配
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const MAX_COUNT = 100;
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const maxCount = 100;
|
||||
const userStatus = "active";
|
||||
```
|
||||
|
||||
## class 和 interface 命名使用大驼峰命名 `[JsTs.Base.ClassUpperCamel]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
class UserInfo {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
class userinfo {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 变量名使用小驼峰命名 `[JsTs.Base.VarLowerCamel]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
- 需要注意的是从 require 导入的变量不受检查
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
let userName = "John";
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
let username = "John";
|
||||
```
|
||||
|
||||
## 单文件代码不超过 700 行 `[JsTs.Base.CodeNotMoreThan700Lines]`
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// 代码不超过 700 行
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
// 代码超过 700 行
|
||||
```
|
||||
|
||||
## 单个函数或方法不能超出 200 行 `[JsTs.Base.FuncNotMoreThan200Lines]`
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
// ... 小于等于 200
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
function getUserInfo() {
|
||||
// ... 大于 200
|
||||
}
|
||||
```
|
||||
|
||||
## 复杂的逻辑判断要添加注释 `[JsTs.Base.ComplexLogic]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
- 逻辑判断的复杂度超过 2 个的要添加注释
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// 逻辑判断复杂度超过 2 个
|
||||
if (a && b || c) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
if (a && b && c && d) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 复杂的函数要添加注释 `[JsTs.Base.ComplexFunc]`
|
||||
|
||||
> - severity `warn`
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* 复杂的算法逻辑
|
||||
*/
|
||||
function complexFunc() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
function complexFunc() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
49
references/js&ts.file-name.md
Normal file
49
references/js&ts.file-name.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# 文件命名规范 `[JsTs.FileName]`
|
||||
|
||||
下面是 JS/TS 的文件命名规范.
|
||||
|
||||
## class 和 interface 文件使用大驼峰命名 `[JsTs.FileName.UpperCamel]`
|
||||
|
||||
- 文件名必须与主导类或接口名称完全一致。
|
||||
- 适用于定义单一主要实体的文件。
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// UserInfo.js
|
||||
class UserInfo {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
// userinfo.js
|
||||
class userinfo {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## 函数文件使用小驼峰命名 `[JsTs.FileName.LowerCamel]`
|
||||
|
||||
- 适用于导出一个或多个工具函数的文件。
|
||||
- 文件名应反映其包含的核心功能。
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// getUserInfo.js
|
||||
function getUserInfo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
// getuserinfo.js
|
||||
function getuserinfo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
250
references/js&ts.nest.md
Normal file
250
references/js&ts.nest.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# Nestjs 项目下的规范 `[JsTs.Nest]`
|
||||
|
||||
> - includes `*.controller.ts` `*.service.ts` `*.module.ts` `*.dto.ts` `*.pipe.ts` `*.guard.ts` `*.interceptor.ts` `*.filter.ts` `*.exception-filter.ts` `*.proxy.ts` `*.model.ts`
|
||||
> - override `[JsTs.FileName]`
|
||||
|
||||
## 目录框架规范 `[JsTs.Nest.DirStructure]`
|
||||
|
||||
- 使用下面的 Good 目录结构
|
||||
- 文件名使用小写加横线命名(如 `user-extends.module.ts`)
|
||||
- 每个模块的目录下必须包含 `module.ts` 文件
|
||||
- 每个模块的目录下必须包含 `controller.ts` 文件
|
||||
- 每个模块的目录下必须包含 `service.ts` 文件
|
||||
- 每个模块的目录下可以包含 `dto` 目录,用于存放数据传输对象
|
||||
- 每个模块的目录下可以包含 `pipe` 目录,用于存放管道
|
||||
- 每个模块的目录下可以包含 `guard` 目录,用于存放守卫
|
||||
- 每个模块的目录下可以包含 `interceptor` 目录,用于存放拦截器
|
||||
- 每个模块的目录下可以包含 `filter` 目录,用于存放异常过滤器
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
src/
|
||||
├── user/ # 用户模块
|
||||
│ ├── user.module.ts
|
||||
│ ├── user.controller.ts
|
||||
│ ├── user.service.ts
|
||||
│ ├── user.proxy.ts
|
||||
│ ├── user.model.ts
|
||||
│ └── dto/ # 数据传输对象
|
||||
├── auth/ # 认证模块
|
||||
│ ├── auth.module.ts
|
||||
│ ├── auth.controller.ts
|
||||
│ ├── auth.service.ts
|
||||
│ ├── auth.proxy.ts
|
||||
│ ├── auth.model.ts
|
||||
├── common/ # 公共模块
|
||||
│ ├── filters/ # 异常过滤器
|
||||
│ ├── guards/ # 守卫
|
||||
│ ├── interceptors/ # 拦截器
|
||||
│ └── pipes/ # 管道
|
||||
├── config/ # 配置文件
|
||||
├── app.module.ts # 根模块
|
||||
└── main.ts # 应用入口
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
src/
|
||||
├── user.controller.ts
|
||||
├── user.service.ts
|
||||
├── auth.controller.ts
|
||||
├── auth.service.ts
|
||||
├── filter.ts
|
||||
├── guard.ts
|
||||
└── main.ts
|
||||
```
|
||||
|
||||
## 控制器命名规范 `[JsTs.Nest.ControllerDefinition]`
|
||||
|
||||
- 该文件不能写业务逻辑,只能写调用 service 的代码
|
||||
- 文件名使用小写加横线命名(如 `user-extends.controller.ts`)
|
||||
- 文件名必须加 `.controller.ts` 后缀
|
||||
- 注解和装饰器上的静态值无需进行魔法值的提炼 `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
user-extends.controller.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
userController.ts
|
||||
```
|
||||
|
||||
## 服务命名规范 `[JsTs.Nest.ServiceDefinition]`
|
||||
|
||||
- 这个是目前业务代码核心编写的地方
|
||||
- 规定不能直接调用数据库查询,只能通过 model 来调用
|
||||
- 规定不能直接调用旧的业务代码,只能通过 proxy 来调用
|
||||
- 文件名使用小写加横线命名(如 `user-extends.service.ts`)
|
||||
- 文件名必须加 `.service.ts` 后缀
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
user-extends.service.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
userService.ts
|
||||
```
|
||||
|
||||
## 模块命名规范 `[JsTs.Nest.ModuleDefinition]`
|
||||
|
||||
- 文件名使用小写加横线命名(如 `user-extends.module.ts`)
|
||||
- 文件名必须加 `.module.ts` 后缀
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
user-extends.module.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
userModule.ts
|
||||
```
|
||||
|
||||
## Dto 命名规范 `[JsTs.Nest.DtoDefinition]`
|
||||
|
||||
> - override `[JsTs.Base.NoMagicStringsAndNumbers]`
|
||||
|
||||
- 文件名使用小写加横线命名(如 `user-extends.dto.ts`)
|
||||
- 文件名必须加 `.dto.ts` 后缀
|
||||
- dto 目录下必须包含 `dto.ts` 文件
|
||||
- dto 里的类的属性可以使用小驼峰或者下划线命名
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
user-extends.dto.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
userDto.ts
|
||||
```
|
||||
|
||||
## Proxy 编写规范 `[JsTs.Nest.ProxyDefinition]`
|
||||
|
||||
- 这是专门为了和旧的业务通讯而存在的和旧代码通讯使用的方式就是 SyncService
|
||||
- 文件名使用小写加横线命名(如 `user.proxy.ts`)
|
||||
- 文件名必须加 `.proxy.ts` 后缀
|
||||
- 内部只能写使用 syncService 调用的逻辑
|
||||
- SyncService 只能在 proxy.ts 中使用
|
||||
|
||||
### Good
|
||||
|
||||
```typescript
|
||||
// user.proxy.ts
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { User } from "@app/entity/models";
|
||||
import { SyncService } from "@app/sync";
|
||||
|
||||
@Injectable()
|
||||
export class UserProxy {
|
||||
constructor(private readonly syncService: SyncService) {}
|
||||
|
||||
getUsersByNames(names: string[], callback: (user: User) => void) {
|
||||
return this.syncService.call("userProxy").getUsersByNames(names, callback);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```typescript
|
||||
// user.proxy.ts
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { User } from "@app/entity/models";
|
||||
import { InjectModel } from "@app/entity/decorator";
|
||||
import { Model } from "mongoose";
|
||||
|
||||
@Injectable()
|
||||
export class UserProxy {
|
||||
constructor(@InjectModel(User) private readonly userModel: Model<User>) {}
|
||||
|
||||
getUsersByNames(names: string[], callback: (user: User) => void) {
|
||||
return this.userModel.find({ name: { $in: names } }, callback);
|
||||
// 不能写数据库查询,只能写和旧的业务通讯代码,数据库查询的逻辑要放在 user.model.ts
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Model 编写规范 `[JsTs.Nest.ModelDefinition]`
|
||||
|
||||
> - includes `*.model.ts`
|
||||
|
||||
- 内部只能写使用 model 数据库调用的逻辑
|
||||
- 文件名使用小写加横线命名(如 `user.model.ts`)
|
||||
- 文件名必须加 `.model.ts` 后缀
|
||||
|
||||
### Good
|
||||
|
||||
```typescript
|
||||
// user.model.ts
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { User } from "@app/entity/models";
|
||||
import { InjectModel } from "@app/entity/decorator";
|
||||
import { Model } from "mongoose";
|
||||
|
||||
@Injectable()
|
||||
export class UserProxy {
|
||||
constructor(@InjectModel(User) private readonly userModel: Model<User>) {}
|
||||
|
||||
getUsersByNames(names: string[], callback: (user: User) => void) {
|
||||
return this.userModel.find({ name: { $in: names } }, callback);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```typescript
|
||||
// user.model.ts
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { User } from "@app/entity/models";
|
||||
import { SyncService } from "@app/sync";
|
||||
|
||||
@Injectable()
|
||||
export class UserProxy {
|
||||
constructor(private readonly syncService: SyncService) {}
|
||||
|
||||
getUsersByNames(names: string[], callback: (user: User) => void) {
|
||||
return this.syncService.call("userProxy").getUsersByNames(names, callback);
|
||||
// 不能写和旧的业务通讯代码,只能写数据库查询的逻辑,和旧的业务通讯的代码要放在 proxy.ts 中
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 业务代码编写规范 `[JsTs.Nest.BusinessDefinition]`
|
||||
|
||||
- 目前所有的新代码都应该写在 nest 里
|
||||
|
||||
### Good
|
||||
|
||||
```typescript
|
||||
// nest-src/apps/app/src/user/user.controller.ts
|
||||
```
|
||||
|
||||
```typescript
|
||||
// nest-src/apps/app/src/user/user.service.ts
|
||||
```
|
||||
|
||||
```typescript
|
||||
// nest-src/apps/app/src/user/user.module.ts
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```typescript
|
||||
// proxy/user.js
|
||||
```
|
||||
85
references/js&ts.test-code.md
Normal file
85
references/js&ts.test-code.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# 测试代码规范 `[JsTs.TestCode]`
|
||||
|
||||
下面是 JS/TS 的测试代码规范.
|
||||
|
||||
## 测试文件命名 `[JsTs.TestCode.FileName]`
|
||||
|
||||
- 必须以 `.test.js` 或 `.test.ts`(或 `.spec.ts`)结尾。
|
||||
- 前缀部分应与被测试源文件名保持一致。
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
// userInfo.test.js
|
||||
describe("UserInfo", () => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
// userinfo.test.js
|
||||
describe("userinfo", () => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
## 测试代码块命名 `[JsTs.TestCode.BlockName]`
|
||||
|
||||
- 测试代码命名结构:`describe(文件名)` -> `describe(函数名/类名.方法名)` -> `it(场景描述)`。
|
||||
- 场景描述应使用 "should ..." 格式,描述预期行为。
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
// uUerInfo.js
|
||||
export class UserInfo {
|
||||
getUserInfo() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
// userInfo.test.js
|
||||
describe("UserInfo", () => {
|
||||
describe("UserInfo.getUserInfo", () => {
|
||||
it("should return user info", () => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
export function getUserInfo() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// userInfo.test.js
|
||||
describe("userInfo", () => {
|
||||
describe("getUserInfo", () => {
|
||||
it("should return user info", () => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
// userInfo.js
|
||||
export function getUserInfo() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// userInfo.test.js
|
||||
describe("userInfo", () => {
|
||||
it("should return user info", () => {
|
||||
// ...
|
||||
});
|
||||
});
|
||||
```
|
||||
325
references/js.models.md
Normal file
325
references/js.models.md
Normal file
@@ -0,0 +1,325 @@
|
||||
# mongoose 数据库模型 JS 规范 `[Js.Model]`
|
||||
|
||||
> - includes `*/models/*.js`
|
||||
> - override `[JsTs.Base]`
|
||||
|
||||
## 模型文件命名规范 `[Js.Model.FileName]`
|
||||
|
||||
> - override `[JsTs.FileName]`
|
||||
|
||||
- 文件名使用小写加下划线命名(如 `user_extends.js`),或者使用小写加横线命名(如 `user-extends.js`)
|
||||
- 文件名应与模型名称对应
|
||||
|
||||
### Good
|
||||
|
||||
```txt
|
||||
user.js
|
||||
user_extends.js
|
||||
user-profile.js
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```txt
|
||||
User.js
|
||||
userExtends.js
|
||||
UserProfile.js
|
||||
```
|
||||
|
||||
## Schema 字段命名规范 `[Js.Model.FieldName]`
|
||||
|
||||
- 字段名使用小写加下划线命名(snake_case)
|
||||
- 避免使用驼峰命名
|
||||
- 要补充字段注释
|
||||
- 要补充字段类型
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
user_name: { type: String },
|
||||
created_at: { type: Date },
|
||||
is_active: { type: Boolean },
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
userName: { type: String },
|
||||
createdAt: { type: Date },
|
||||
isActive: { type: Boolean },
|
||||
});
|
||||
```
|
||||
|
||||
## Schema 定义规范 `[Js.Model.SchemaDefinition]`
|
||||
|
||||
- 必须为每个字段指定类型
|
||||
- 必要时添加 `required`、`default` 等属性
|
||||
- 复杂类型应使用嵌套 Schema 或引用
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
user_name: { type: String, required: true },
|
||||
email: { type: String, required: true, unique: true },
|
||||
age: { type: Number, default: 0 },
|
||||
status: { type: String, enum: ["active", "inactive"], default: "active" },
|
||||
created_at: { type: Date, default: Date.now },
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
user_name: String,
|
||||
email: String,
|
||||
age: Number,
|
||||
status: String,
|
||||
created_at: Date,
|
||||
});
|
||||
```
|
||||
|
||||
## 索引定义规范 `[Js.Model.IndexDefinition]`
|
||||
|
||||
- 需要添加注释说明索引用途
|
||||
- 不能在 Schema 定义中直接添加索引,添加到索引要注释掉
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
user_id: { type: Schema.Types.ObjectId, ref: "User" },
|
||||
order_no: { type: String },
|
||||
created_at: { type: Date },
|
||||
});
|
||||
|
||||
// 用户订单查询索引
|
||||
// orderSchema.index({ user_id: 1, created_at: -1 });
|
||||
// 订单号唯一索引
|
||||
// orderSchema.index({ order_no: 1 }, { unique: true });
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
user_id: { type: Schema.Types.ObjectId, ref: "User", index: true },
|
||||
order_no: { type: String, index: true },
|
||||
created_at: { type: Date, index: true },
|
||||
});
|
||||
```
|
||||
|
||||
## 虚拟字段规范 `[Js.Model.VirtualField]`
|
||||
|
||||
- 虚拟字段命名使用小写加下划线
|
||||
- 虚拟字段应在 Schema 定义后声明
|
||||
- 需要添加注释说明虚拟字段用途
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
first_name: { type: String },
|
||||
last_name: { type: String },
|
||||
});
|
||||
|
||||
// 完整姓名虚拟字段
|
||||
userSchema.virtual("full_name").get(function () {
|
||||
return this.first_name + " " + this.last_name;
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
first_name: { type: String },
|
||||
last_name: { type: String },
|
||||
full_name: { type: String }, // 不应该存储可计算的字段
|
||||
});
|
||||
```
|
||||
|
||||
## 中间件/钩子规范 `[Js.Model.Middleware]`
|
||||
|
||||
- 中间件应在 Schema 定义后、模型导出前声明
|
||||
- 需要添加注释说明中间件用途
|
||||
- 避免在中间件中执行耗时操作
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
password: { type: String },
|
||||
updated_at: { type: Date },
|
||||
});
|
||||
|
||||
// 保存前更新时间戳
|
||||
userSchema.pre("save", function (next) {
|
||||
this.updated_at = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
// 保存前加密密码
|
||||
userSchema.pre("save", async function (next) {
|
||||
if (this.isModified("password")) {
|
||||
this.password = await bcrypt.hash(this.password, 10);
|
||||
}
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
password: { type: String },
|
||||
});
|
||||
|
||||
userSchema.pre("save", function (next) {
|
||||
// 没有注释说明用途
|
||||
this.password = bcrypt.hashSync(this.password, 10); // 使用同步方法阻塞
|
||||
next();
|
||||
});
|
||||
```
|
||||
|
||||
## 静态方法规范 `[Js.Model.StaticMethod]`
|
||||
|
||||
- 静态方法命名使用小驼峰
|
||||
- 静态方法应在 Schema 定义后声明
|
||||
- 需要添加注释说明方法用途
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
email: { type: String },
|
||||
status: { type: String },
|
||||
});
|
||||
|
||||
// 根据邮箱查找用户
|
||||
userSchema.statics.findByEmail = function (email) {
|
||||
return this.findOne({ email: email });
|
||||
};
|
||||
|
||||
// 查找所有活跃用户
|
||||
userSchema.statics.findActiveUsers = function () {
|
||||
return this.find({ status: "active" });
|
||||
};
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
email: { type: String },
|
||||
});
|
||||
|
||||
userSchema.statics.find_by_email = function (email) {
|
||||
// 方法名不应使用下划线
|
||||
return this.findOne({ email: email });
|
||||
};
|
||||
```
|
||||
|
||||
## 实例方法规范 `[Js.Model.InstanceMethod]`
|
||||
|
||||
- 实例方法命名使用小驼峰
|
||||
- 实例方法应在 Schema 定义后声明
|
||||
- 需要添加注释说明方法用途
|
||||
- 实例方法内部使用 `this` 访问文档属性
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
password: { type: String },
|
||||
login_count: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
// 验证密码
|
||||
userSchema.methods.comparePassword = async function (candidatePassword) {
|
||||
return bcrypt.compare(candidatePassword, this.password);
|
||||
};
|
||||
|
||||
// 增加登录次数
|
||||
userSchema.methods.incrementLoginCount = function () {
|
||||
this.login_count += 1;
|
||||
return this.save();
|
||||
};
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
password: { type: String },
|
||||
});
|
||||
|
||||
userSchema.methods.compare_password = function (candidatePassword) {
|
||||
// 方法名不应使用下划线
|
||||
return bcrypt.compareSync(candidatePassword, this.password);
|
||||
};
|
||||
```
|
||||
|
||||
## 关联引用规范 `[Js.Model.Reference]`
|
||||
|
||||
- 引用字段使用 `_id` 后缀命名
|
||||
- 必须指定 `ref` 属性
|
||||
- 需要添加注释说明关联关系
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
// 关联用户
|
||||
user_id: { type: Schema.Types.ObjectId, ref: "User", required: true },
|
||||
// 关联商品列表
|
||||
product_ids: [{ type: Schema.Types.ObjectId, ref: "Product" }],
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const orderSchema = new Schema({
|
||||
user: { type: Schema.Types.ObjectId }, // 缺少 ref,命名不规范
|
||||
products: [{ type: String }], // 应使用 ObjectId 引用
|
||||
});
|
||||
```
|
||||
|
||||
## 必须写明字段的类型 `[Js.Model.FieldType]`
|
||||
|
||||
- 字段定义必须使用对象形式,明确指定 `type` 属性
|
||||
- 禁止使用简写形式(如 `field: String`)
|
||||
- 不允许使用 Object 等模糊类型
|
||||
|
||||
### Good
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
// 用户名
|
||||
user_name: { type: String, required: true },
|
||||
// 年龄
|
||||
age: { type: Number, default: 0 },
|
||||
// 是否激活
|
||||
is_active: { type: Boolean, default: true },
|
||||
// 创建时间
|
||||
created_at: { type: Date, default: Date.now },
|
||||
});
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```javascript
|
||||
const userSchema = new Schema({
|
||||
user_name: String, // 缺少类型对象包装
|
||||
age: Number,
|
||||
is_active: Boolean,
|
||||
created_at: Date,
|
||||
ext: { type: Object, default: {} },
|
||||
ext2: {},
|
||||
});
|
||||
```
|
||||
39
references/vue.base.md
Normal file
39
references/vue.base.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Vue 基础代码 `[Vue.Base]`
|
||||
|
||||
> - includes `*.vue`
|
||||
|
||||
## Vue 自定义组件命名规则 `[Vue.Base.CustomComponentName]`
|
||||
|
||||
必须使用大驼峰命名并且使用的时候也是,并且至少两个单词。
|
||||
|
||||
### Good
|
||||
|
||||
```vue
|
||||
<!-- UserInfo.vue -->
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "UserInfo",
|
||||
// ...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```vue
|
||||
<!-- userinfo.vue -->
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "userinfo",
|
||||
// ...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
37
references/vue.file-name.md
Normal file
37
references/vue.file-name.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Vue 文件命名 `[Vue.FileName]`
|
||||
|
||||
> - includes `*.vue`
|
||||
|
||||
## Vue 组件文件使用大驼峰命名 `[Vue.FileName.UpperCamel]`
|
||||
|
||||
### Good
|
||||
|
||||
```vue
|
||||
<!-- UserInfo.vue -->
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "UserInfo",
|
||||
// ...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
### Bad
|
||||
|
||||
```vue
|
||||
<!-- userinfo.vue -->
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "userinfo",
|
||||
// ...
|
||||
};
|
||||
</script>
|
||||
```
|
||||
Reference in New Issue
Block a user