147 lines
4.2 KiB
Markdown
147 lines
4.2 KiB
Markdown
# 本项目使用cursou说明
|
||
|
||
## 服务注入
|
||
|
||
> 大部分服务已经全局注入,直接在service中使用即可
|
||
|
||
- 日志服务:private readonly logger: CustomLogger,
|
||
- redis服务:private readonly redis: RedisService,
|
||
- 配置服务:private readonly config: ConfigService,
|
||
- 工具服务:private readonly utils: UtilsService,
|
||
- 数据库服务:private readonly database: DatabaseService,
|
||
|
||
以上服务均已在appModule全局注入,不需要再向module中注入
|
||
|
||
## 路径别名
|
||
|
||
@代指src目录,请注意,引入任何文件采用路径别名,除开当前目录下的文件,不允许使用../获取上级目录
|
||
|
||
## 数据库
|
||
|
||
1. 数据库实体在@/drizzle/schema,通过这样导入:
|
||
```ts
|
||
import {
|
||
user,
|
||
userPassword,
|
||
userProfile,
|
||
userSignatureHistory,
|
||
} from '@/drizzle/schema';
|
||
```
|
||
|
||
**注意**操作数据严格按照数据库实体的定义
|
||
|
||
2. 数据库使用drizzle和mysql2,下面是使用示例
|
||
|
||
```ts
|
||
import { user } from '@/drizzle/schema';
|
||
// dto为参数
|
||
const userExists = await this.database.db
|
||
.select({
|
||
userId: user.userId,
|
||
})
|
||
.from(user)
|
||
.where(
|
||
or(
|
||
eq(user.email, dto.email),
|
||
eq(user.username, dto.username),
|
||
),
|
||
)
|
||
.execute();
|
||
if (userExists.length > 0) {
|
||
throw new BadRequestException('用户已存在');
|
||
}
|
||
```
|
||
|
||
## 注释
|
||
|
||
**非常重要** !!!!!!!!!!!
|
||
1. 编写代码已经要有非常详细的注释,最好每行都有注释
|
||
|
||
参考
|
||
```ts
|
||
// 检查邮箱是否可用
|
||
async checkEmail(dto: CheckEmailDto) {
|
||
const exists = await this.database.db
|
||
.select()
|
||
.from(user)
|
||
.where(and(eq(user.email, dto.email), eq(user.isDeleted, 0)))
|
||
.execute();
|
||
|
||
return { available: exists.length === 0 };
|
||
}
|
||
|
||
// 发送验证码
|
||
async sendEmailCode(dto: SendEmailCodeDto) {
|
||
// 邮箱验证码key
|
||
const codeKey = `${EmailCodeType[dto.type]}:${dto.email}`;
|
||
// 判断Key是否存在
|
||
const keyExists = await this.redis.exists(codeKey);
|
||
// 验证码过期时间
|
||
const codeEX = this.config.get<number>('email.codeEX') || 300;
|
||
// 验证码冷却时间
|
||
const codeEP = this.config.get<number>('email.codeEP') || 60;
|
||
// 判断是否存在验证码
|
||
if (keyExists) {
|
||
// 获取Key的过期时间
|
||
const ttl = await this.redis.ttl(codeKey);
|
||
if (ttl > codeEX - codeEP) {
|
||
// 再等等吧
|
||
throw new BadRequestException(`请等待${ttl}秒后再试`);
|
||
} else {
|
||
// 续杯
|
||
await this.redis.expire(codeKey, codeEX);
|
||
// 获取验证码
|
||
const code = await this.redis.get(codeKey);
|
||
// todo重新发送验证码
|
||
this.logger.debug(`重新发送验证码: ${code}`);
|
||
await this.utils.sendEmail({
|
||
to: dto.email,
|
||
subject: '账户注册验证码',
|
||
text: `您的验证码是:${code},5分钟内有效`,
|
||
});
|
||
}
|
||
} else {
|
||
// 生成验证码
|
||
const code = Math.random().toString().slice(2, 8);
|
||
// todo发送验证码
|
||
this.logger.debug(`发送验证码: ${code}`);
|
||
await this.utils.sendEmail({
|
||
to: dto.email,
|
||
subject: '账户注册验证码',
|
||
text: `您的验证码是:${code},5分钟内有效`,
|
||
});
|
||
// 存储验证码
|
||
await this.redis.set(codeKey, code, codeEX);
|
||
}
|
||
return { message: '验证码已发送' };
|
||
}
|
||
```
|
||
2. 每个方法前都要携带写作者、写作时间、方法描述,写作者为`Nie`
|
||
|
||
## 常量
|
||
|
||
常量这样导入 `import { EmailCodeType } from '@/type/enum';`
|
||
|
||
常量用于一些系统的关键字
|
||
|
||
|
||
## redis
|
||
|
||
使用参考
|
||
```ts
|
||
// 加锁
|
||
const lock = await this.redis.lock(
|
||
`${EmailCodeType.REGISTER}:${dto.email}`,
|
||
);
|
||
```
|
||
|
||
方法一般在RedisService中定义
|
||
|
||
## 文件命名
|
||
|
||
采用小驼峰加`.service`、`.dto`类似的方式命名,禁止使用中划线
|
||
|
||
错误示例
|
||
`add-user.dto.ts`
|
||
正确示例
|
||
`addUser.dto.ts |