alioth/star-tune/cursor.md
2025-06-04 22:44:02 +08:00

4.2 KiB
Raw Permalink Blame History

本项目使用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通过这样导入
import {
    user,
    userPassword,
    userProfile,
    userSignatureHistory,
} from '@/drizzle/schema';

注意操作数据严格按照数据库实体的定义

  1. 数据库使用drizzle和mysql2下面是使用示例
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. 编写代码已经要有非常详细的注释,最好每行都有注释

参考

    // 检查邮箱是否可用
    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: '验证码已发送' };
    }
  1. 每个方法前都要携带写作者、写作时间、方法描述,写作者为Nie

常量

常量这样导入 import { EmailCodeType } from '@/type/enum';

常量用于一些系统的关键字

redis

使用参考

// 加锁
        const lock = await this.redis.lock(
            `${EmailCodeType.REGISTER}:${dto.email}`,
        );

方法一般在RedisService中定义

文件命名

采用小驼峰加.service.dto类似的方式命名,禁止使用中划线

错误示例 add-user.dto.ts 正确示例 `addUser.dto.ts