Nest User 模块
Nest UserModule
ts
import { Module } from "@nestjs/common";
import { UserService } from "./user.service";
import { UserController } from "./user.controller";
// 增加Excel 动态模块
import { ExcelModule } from "../../commonModules/excel/excel.module";
// 增加上传模块
import { UploadModule } from "../../commonModules/upload/upload.module";
// 增加邮箱模块
import { EmailModule } from "../../commonModules/email/email.module";
// 增加加密解密模块
import { CryptoModule } from "../../commonModules/crypto/crypto.module";
@Module({
imports: [
ExcelModule.forRoot({ name: "testdemoexcel" }),
UploadModule,
EmailModule,
CryptoModule,
],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}Nest UserController
ts
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
UseGuards,
Req,
} from "@nestjs/common";
import { UserService } from "./user.service";
// 引入验证机制
import { AuthGuard } from "@nestjs/passport";
// 引入DTO
import { RegisterUserDto, SendEmailDto } from "./dto/register-user.dto";
import { LoginUserDto } from "./dto/login-user.dto";
import { GetInfoUserDto } from "./dto/getinfo-user.dto";
import { UpdateUserDto } from "./dto/update-user.dto";
import { UpdatePasswordDto } from "./dto/updatePassword.dto";
import { UpdateAdminDto } from "./dto/updateAdmin.dto";
import { GetListDto } from "./dto/getList.dto";
import { UpdateFrozenDto } from "./dto/updateFrozenDto.dto";
// 引入守卫
import { UserRegisterGuard } from "../user/guard/userregister.guard";
import { ByGuardpass } from "src/common/guard_pass.decorator";
import { RuleGuard } from "../../common/rule.guard";
// 引入装饰器
import { RBAC } from "../../common/rbac.decorator";
@Controller({
path: "user",
version: ["1"],
})
export class UserController {
constructor(private readonly userService: UserService) {}
// 发送邮件
/**
*
* @api {POST} /v1/user/sendEmail 发送邮件
* @apiName 发送邮件
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {String} email 邮箱地址
*
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {String} response.data 发送成功
*
* @apiParamExample {type} Request-Example:
* {
* email : 26650599@qq.com
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code : 200
* message : 操作成功
* data : 发送成功
* }
*
*
*/
@Post("sendEmail")
@ByGuardpass()
sendEmail(@Body() body: SendEmailDto) {
const result = this.userService.sendEmail(body.email);
return result;
}
// 注册
/**
*
* @api {POST} /v1/user/register 注册
* @apiName 注册
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {String} username 用户名
* @apiBody {String} password 密码
* @apiBody {String} email 邮箱
* @apiBody {String} captcha 验证码
* @apiBody {String} phone_number 手机号
* @apiBody {String} nick_name 昵称
* @apiBody {String} head_pic 头像
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {Object} response.data 返回数据
* @apiSuccess {String} response.data.token 生成token
* @apiSuccess {String} response.data.refreshToken 生成refreshToken
*
* @apiParamExample {type} Request-Example:
* {
* email : 26650599@qq.com
* username": myadmin,
* password: 123456,
* email: 26650599@qq.com,
* nick_name: 我就是管理员,
* captcha: RLHXai,
* phone_number:19000000011,
* head_pic:https://file.jsopy.com/IMAGES/avatarsmoke.jpg
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoiYWRtaW4iLCJpYXQiOjE3NjY5MTQxNTksImV4cCI6MTc2NjkxNzc1OX0.LUYrzPWzh6OXF-tCiV-euGvIjrHFxsbbE6092WMh894
* refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoiYWRtaW4iLCJpYXQiOjE3NjcwMDAwOTUsImV4cCI6MTc2NzAwMzY5NX0.4pK4YphVMQBxGA4w6tjStPIh_prOMkUCkWJLl7ROOU0
* }
*
*
*/
@Post("register")
@UseGuards(UserRegisterGuard)
@ByGuardpass()
register(@Body() body: RegisterUserDto) {
const result = this.userService.register(body);
return result;
}
/**
*
* @api {POST} /v1/user/login 登录
* @apiName 登录
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {String} username 用户名
* @apiBody {String} password 密码
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {Object} response.data 返回数据
* @apiSuccess {String} response.data.token 生成token
* @apiSuccess {String} response.data.refreshToken 生成refreshToken
*
* @apiParamExample {type} Request-Example:
* {
* username": myadmin,
* password: 123456,
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoiYWRtaW4iLCJpYXQiOjE3NjY5MTQxNTksImV4cCI6MTc2NjkxNzc1OX0.LUYrzPWzh6OXF-tCiV-euGvIjrHFxsbbE6092WMh894
* refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInVzZXJOYW1lIjoiYWRtaW4iLCJpYXQiOjE3NjcwMDAwOTUsImV4cCI6MTc2NzAwMzY5NX0.4pK4YphVMQBxGA4w6tjStPIh_prOMkUCkWJLl7ROOU0
* }
*
*
*/
@ByGuardpass()
@UseGuards(AuthGuard("local"))
@Post("login")
async login(@Req() req: any) {
//获取到user信息知道是谁了
console.log(req.user);
const result: LoginUserDto = {
userName: req.user.username,
userId: req.user.id,
};
return this.userService.login({
userName: result.userName,
userId: result.userId,
});
}
// 初始化数据
/**
*
* @api {POST} /v1/user/init 初始化
* @apiName 初始化
* @apiGroup user
* @apiVersion 0.0.0
*
*
*/
@ByGuardpass()
@Post("init")
async init() {
await this.userService.init();
return "初始化数据成功";
}
// 测试权限分级
/**
*
* @api {POST} /v1/user/rbac 权限分级
* @apiName 权限分级
* @apiGroup user
* @apiVersion 0.0.0
*
*/
@UseGuards(RuleGuard)
@RBAC(["guest"])
@Post("rbac")
async rbac(@Body() body: any) {
console.log("----");
console.log(body);
console.log("-------");
return "测试";
}
/**
*
* @api {POST} /v1/user/info 获取详情
* @apiName 获取个人详情
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {number} id 用户id
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {Object} response.data 返回数据
* @apiSuccess {number} response.data.id 生成的id
* @apiSuccess {String} response.data.username 用户名
* @apiSuccess {String} response.data.nick_name 昵称
* @apiSuccess {String} response.data.head_pic 头像
* @apiSuccess {String} response.data.phone_number 手机号
* @apiSuccess {String} response.data.email 邮箱
* @apiSuccess {String} response.data.is_frozen 2 代表未冻结 1代表冻结
* @apiSuccess {String} response.data.is_admin 1 代表超级管理员 2代表普通用户
*
* @apiParamExample {type} Request-Example:
* {
* id: 3,
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data: {
* id: 3,
* username: myadmin,
* nick_name: jsopy,
* email: 26650599@qq.com,
* head_pic: https://file.jsopy.com/IMAGES/avatarsmoke.jpg,
* phone_number: 19000000011,
* is_frozen: 2,
* is_admin: 2
* }
* }
*
*
*/
@Get("info")
async getinfo(@Body() body: GetInfoUserDto) {
const result = await this.userService.getInfo(body);
return result;
}
/**
*
* @api {POST} /v1/user/update 更新个人信息
* @apiName 更新个人信息
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {number} id 用户id
* @apiBody {String} nick_name 昵称
* @apiBody {String} head_pic 头像
* @apiBody {String} phone_number 手机号
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {String} response.data 返回数据
*
* @apiParamExample {type} Request-Example:
* {
* id: 3,
* nick_name:jsopy-updated,
* head_pic:https://file.jsopy.com/IMAGES/avatarmoney.jpg,
* phone_number:19000000012
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data: 更新成功
* }
*
*
*/
@Post("update")
async update(@Body() body: UpdateUserDto) {
const result = await this.userService.updateUser(body);
return result;
}
// 修改密码
/**
*
* @api {POST} /v1/user/update_password 更改密码
* @apiName 更改密码
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {String} oldPassword 旧密码
* @apiBody {String} newPassword 新密码
* @apiBody {String} confirmNewPassword 确认密码
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {String} response.data 更新成功
*
* @apiParamExample {type} Request-Example:
* {
* "oldPassword":"456789",
* "newPassword":"123456",
* "confirmNewPassword":"123456"
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data: 更新成功
*
*
*/
@Post("update_password")
async updatePassword(@Body() body: UpdatePasswordDto, @Req() req: any) {
console.log(req.userId);
const userId = req.userId;
const result = await this.userService.updatePassword(body, userId);
return result;
}
// 提升管理员
/**
*
* @api {POST} /v1/user/update_admin 提升为管理员
* @apiName 提升为管理员
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {number} id 用户id
* @apiBody {String} is_admin 是否是管理员 1就是管理员 2就是普通用户
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {String} response.data 更新成功
*
* @apiParamExample {type} Request-Example:
* {
* id:3,
* is_admin:1,
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data: 提升成功
*
*
*/
@Post("update_admin")
async updateAdmin(@Body() body: UpdateAdminDto) {
const result = await this.userService.updateAdmin(body);
return result;
}
// 用户列表
/**
*
* @api {GET} /v1/user/getlist 获取所有用户
* @apiName 获取所有用户
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {Object[]} response.data 数据汇总
* @apiSuccess {number} response.data.id 生成的id
* @apiSuccess {String} response.data.username 用户名
* @apiSuccess {String} response.data.nick_name 昵称
* @apiSuccess {String} response.data.head_pic 头像
* @apiSuccess {String} response.data.phone_number 手机号
* @apiSuccess {String} response.data.email 邮箱
* @apiSuccess {String} response.data.is_frozen 2 代表未冻结 1代表冻结
* @apiSuccess {String} response.data.is_admin 1 代表超级管理员 2代表普通用户
* @apiSuccess {Object} response.data.pagination 数据集合
* @apiSuccess {Number} response.data.pagination.total 总数
* @apiSuccess {Number} response.data.pagination.page 当前页
* @apiSuccess {Number} response.data.pagination.pageSize 每页个数
* @apiSuccess {Number} response.data.pagination.totalPages 总页数
* @apiSuccess {Boolean} response.data.pagination.hasNextPage 是否有下一页
* @apiSuccess {Boolean} response.data.pagination.hasPreviousPage 是否有上一页
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data:{
* list:[
* {
* id: 3,
* username: myadmin,
* nick_name: jsopy,
* email: 26650599@qq.com,
* head_pic: https://file.jsopy.com/IMAGES/avatarsmoke.jpg,
* phone_number: 19000000011,
* is_frozen: 2,
* is_admin: 2
* }
* ],
* pagination: {
* "total": 1,
* "page": 1,
* "pageSize": 10,
* "totalPages": 1,
* "hasNextPage": false,
* "hasPreviousPage": false
* }
* }
* }
*
*
*/
@Get("getlist")
async getList(@Body() body: GetListDto) {
const result = await this.userService.getList(body.page, body.pageSize);
return result;
}
/**
*
* @api {POST} /v1/user/update_frozen 冻结和解冻用户
* @apiName 冻结和解冻用户
* @apiGroup user
* @apiVersion 0.0.0
*
*
* @apiBody {number} id 用户id
* @apiBody {String} is_frozen 是否冻结 1就是冻结 2就是解冻
* @apiSuccess {Object} response 响应数据
* @apiSuccess {Number} response.code 200
* @apiSuccess {String} response.message 操作成功
* @apiSuccess {String} response.data 冻结成功
*
* @apiParamExample {type} Request-Example:
* {
* id:3,
* is_frozen:1,
* }
*
*
* @apiSuccessExample {type} Success-Response:
* {
* code: 200,
* message: "操作成功",
* data: "冻结成功"
*
*
*/
@Post("update_frozen")
async updateFrozen(@Body() body: UpdateFrozenDto) {
const result = await this.userService.updateFrozen(body);
return result;
}
}Nest UserService
ts
import { Inject, Injectable } from "@nestjs/common";
import { PrismadbService } from "../../commonModules/prisma/prisma.service";
import { RedisService } from "../../commonModules/redis/redis.service";
import { JwtAllService } from "../../commonModules/jwt/jwt.service";
import { ExcelService } from "../../commonModules/excel/excel.service";
import { UploadService } from "../../commonModules/upload/upload.service";
// 邮件发送
import { EmailService } from "../../commonModules/email/email.service";
import { customAlphabet } from "nanoid";
// 加密解密
import { CryptoService } from "../../commonModules/crypto/crypto.service";
// 实例化
import { RegisteruserEntity } from "./entities/Registeruser.entity";
import { LoginuserEntity } from "./entities/Loginuser.entity";
import { PermissionsEntity } from "./entities/Permissions.entity";
import { RulesEntity } from "./entities/Rules.entity";
import { GetInfoUserEntity } from "./entities/GetInfoUserEntity.entity";
import { UpdateUserEntity } from "./entities/UpdataUserEntity.entity";
import { UpdatePassWordEntity } from "./entities/UpdatePassWord.entity";
import { UpdateAdminDto } from "./dto/updateAdmin.dto";
// 抛出异常
import { GlobalCheckException } from "../../common/globalcheck.exception";
import { UpdateFrozenDto } from "./dto/updateFrozenDto.dto";
@Injectable()
export class UserService {
// 数据库
@Inject()
private readonly prisma: PrismadbService;
// redis
@Inject()
private readonly redisService: RedisService;
// JWT
@Inject()
private readonly jwtAllService: JwtAllService;
// Excel
@Inject()
private readonly ExcelService: ExcelService;
// 上传
@Inject()
private readonly UploadService: UploadService;
// 邮件发送
@Inject()
private readonly emailService: EmailService;
// 加密解密
@Inject()
private readonly cryptoService: CryptoService;
// 初始化数据
async init() {
// 用户列表
const user1 = new RegisteruserEntity();
user1.username = "admin";
user1.password = this.cryptoService.md5Encrypt("123456");
user1.email = "admin@qq.com";
user1.phone_number = "19000000001";
user1.nick_name = "jsopy_admin";
user1.head_pic = "https://file.jsopy.com/IMAGES/avatarsmoke.jpg";
user1.is_admin = 1; // 超级管理员
user1.is_frozen = 2; // 未冻结
const user2 = new RegisteruserEntity();
user2.username = "guest";
user2.password = this.cryptoService.md5Encrypt("123456");
user2.email = "guest@qq.com";
user2.phone_number = "19000000001";
user2.head_pic = "https://file.jsopy.com/IMAGES/avatarsmoke.jpg";
user2.is_admin = 2; //普通用户
user2.is_frozen = 2; // 未冻结
user2.nick_name = "jsopy_guest";
// 权限
const role1 = new RulesEntity();
role1.name = "超级管理员";
const role2 = new RulesEntity();
role2.name = "普通用户";
// 权限列表
const permissions1 = new PermissionsEntity();
permissions1.code = "admin";
permissions1.description = "admin";
const permissions2 = new PermissionsEntity();
permissions2.code = "guest";
permissions2.description = "user";
// 添加角色哪个没有外连哪个优先插入 creatMany 不支持嵌套插入 所有有外联不适用
const permissionarr = [permissions1, permissions2];
const permissionresult: any[] = [];
for (let i = 0; i < permissionarr.length; i++) {
const item = permissionarr[i];
const result = await this.prisma.permissions.create({ data: item });
permissionresult.push(result);
}
// 角色
role1.roles_permissions = {
create: [
{
permission_id: permissionresult[0].id,
},
{
permission_id: permissionresult[1].id,
},
],
};
role2.roles_permissions = {
create: [
{
permission_id: permissionresult[1].id,
},
],
};
// 添加角色
const rolearr = [role1, role2];
const roleresult: any[] = [];
for (let i = 0; i < rolearr.length; i++) {
const item = rolearr[i];
const result = await this.prisma.roles.create({ data: item });
roleresult.push(result);
}
console.log(roleresult);
// 外链 1
user1.user_roles = {
create: [
{
role_id: roleresult[0].id,
},
],
};
// 外链 2
user2.user_roles = {
create: [
{
role_id: roleresult[1].id,
},
],
};
// 添加用户
const userarr = [user1, user2];
const userresult: any[] = [];
for (let i = 0; i < userarr.length; i++) {
const item = userarr[i];
const result = await this.prisma.users.create({ data: item });
userresult.push(result);
}
console.log(userresult);
return "初始化成功";
}
// 注册
async register(body: RegisteruserEntity) {
console.log(body.email);
// 先去查询数据库里面有没有
const result = await this.prisma.users.findFirst({
where: {
email: body.email,
},
});
if (!result) {
// 去掉验证码 直接插入
let { captcha, ...result } = body;
// 密码必须md5 加密
result.password = this.cryptoService.md5Encrypt(result.password);
// 默认普通用户
const resultdata = {
...result,
user_roles: {
create: [
{
role_id: 2,
},
],
},
};
// 注册
const userresult = await this.prisma.users.create({
data: resultdata,
});
// 短 token
const token = await this.jwtAllService.setToken({
userId: userresult.id,
userName: userresult.username,
});
// 长 token
const refreshToken = await this.jwtAllService.setRefreshToken({
userId: userresult.id,
userName: userresult.username,
});
// 用过一次就删除
await this.redisService.delkey(`captcha_${body.captcha}`);
// 生成jwt
return {
token,
refreshToken,
};
} else {
throw new GlobalCheckException("邮箱已经存在");
}
}
// 发送邮件
async sendEmail(emialAddress: string) {
// 验证码
const nanoid = customAlphabet(
"1234567890abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ",
6
);
const randomId = nanoid();
const result = await this.emailService.sendEmail({
to: emialAddress, // 你要发送的邮件账号
subject: "邮箱", // 标题
html: `<h1>这是邮箱验证码${randomId}</h1>`, // 邮件内容
});
if (result.messageId) {
// 存入redis
const result = await this.redisService.setstr({
key: `captcha_${randomId}`,
value: emialAddress,
});
return "发送成功";
} else {
return "发送失败";
}
}
// 登录
async login(body: LoginuserEntity) {
// 短 token
const token = await this.jwtAllService.setToken({
userId: body.userId,
userName: body.userName,
});
// 长 token
const refreshToken = await this.jwtAllService.setRefreshToken({
userId: body.userId,
userName: body.userName,
});
return {
token,
refreshToken,
};
}
// 获取详情
async getInfo(body: GetInfoUserEntity) {
const result = await this.prisma.users.findFirst({
where: {
id: body.id,
},
select: {
...Object.fromEntries(
Object.keys(this.prisma.users.fields).map((key) => [key, true])
),
password: false,
creat_time: false,
update_time: false,
},
});
return result;
}
// 更新资料
async updateUser(data: UpdateUserEntity) {
// 先查询
const UserSelect = await this.prisma.users.findFirst({
where: {
id: data.id,
},
});
if (UserSelect) {
const updateResult = await this.prisma.users.update({
where: {
id: data.id,
},
data: {
...data,
},
});
if (updateResult) {
return "更新成功";
} else {
throw new GlobalCheckException("更新失败");
}
} else {
throw new GlobalCheckException("用户不存在");
}
}
// 修改密码
async updatePassword(data: UpdatePassWordEntity, userId: number) {
// 先查询
const UserSelect = await this.prisma.users.findFirst({
where: {
id: userId,
},
});
if (
UserSelect?.password == this.cryptoService.md5Encrypt(data.oldPassword)
) {
const result = await this.prisma.users.update({
where: {
id: userId,
},
data: {
password: this.cryptoService.md5Encrypt(data.newPassword),
},
});
if (result) {
return "修改成功";
} else {
throw new GlobalCheckException("修改失败");
}
} else {
throw new GlobalCheckException("旧密码错误");
}
}
// 提升管理员
async updateAdmin(data: UpdateAdminDto) {
// 先查询
const UserSelect = await this.prisma.users.findFirst({
where: {
id: data.id,
},
});
if (UserSelect?.is_admin !== 1) {
const result = await this.prisma.users.update({
where: {
id: data.id,
},
data: {
is_admin: 1,
},
});
if (result) {
return "提升成功";
} else {
throw new GlobalCheckException("提升失败");
}
} else {
throw new GlobalCheckException("该用户已经是管理员");
}
}
// 查询所有用户
async getList(page: number = 1, pageSize: number = 10) {
const result = await this.prisma.users.paginate(page, pageSize, {
select: {
...Object.fromEntries(
Object.keys(this.prisma.users.fields).map((key) => [key, true])
),
password: false,
creat_time: false,
update_time: false,
},
orderBy: {
id: "asc",
},
});
return result;
}
// 冻结用户
async updateFrozen(data: UpdateFrozenDto) {
// 先查询
const UserSelect = await this.prisma.users.findFirst({
where: {
id: data.id,
},
});
if (UserSelect) {
const result = await this.prisma.users.update({
where: {
id: data.id,
},
data: {
is_frozen: Number(data.is_frozen),
},
});
if (result.is_frozen == 1) {
return "冻结成功";
} else {
return "解冻成功";
}
} else {
throw new GlobalCheckException("用户不存在");
}
}
}User 模块 DTO
getinfo-user.dto.ts
ts
import { IsEmail, IsNotEmpty, MinLength, IsPhoneNumber } from "class-validator";
export class GetInfoUserDto {
@IsNotEmpty({
message: "id不能为空",
})
id: number;
}getList.dto.ts
ts
import { IsNotEmpty } from "class-validator";
export class GetListDto {
@IsNotEmpty({
message: "page不能为空",
})
page: number;
@IsNotEmpty({
message: "pagesize不能为空",
})
pageSize: number;
}login-user.dto.ts
ts
import { IsNotEmpty } from "class-validator";
/**
* 登录用户数据传输对象(DTO)
* 用于验证和传输登录相关的用户数据
*/
export class LoginUserDto {
/**
* 用户名属性
* 使用class-validator进行验证,确保用户名不为空
* @type {string}
*/
@IsNotEmpty({
message: "用户名不能为空",
})
userName: string;
/**
* 用户ID属性
* 使用class-validator进行验证,确保用户ID不为空
* @type {string}
*/
@IsNotEmpty({
message: "id不能为空",
})
userId: string;
}register-user.dto.ts
ts
import { IsEmail, IsNotEmpty, MinLength, IsPhoneNumber } from "class-validator";
export class RegisterUserDto {
/**
* 用户名字段
* 使用class-validator进行验证,确保用户名不为空
*/
@IsNotEmpty({
message: "用户名不能为空",
})
username: string;
/**
* 昵称字段
* 使用class-validator进行验证,确保昵称不为空
*/
@IsNotEmpty({
message: "昵称不能为空",
})
nick_name: string;
/**
* 密码字段
* 使用class-validator进行验证,确保密码不为空且长度不少于6位
*/
@IsNotEmpty({
message: "密码不能为空",
})
@MinLength(6, {
message: "密码不能少于 6 位",
})
password: string;
/**
* 邮箱字段
* 使用class-validator进行验证,确保邮箱不为空且格式正确
*/
@IsNotEmpty({
message: "邮箱不能为空",
})
@IsEmail(
{},
{
message: "不是合法的邮箱格式",
}
)
email: string;
/**
* 验证码字段
* 必填字段,用于验证用户注册的真实性和安全性
* 使用class-validator进行验证,确保验证码不为空
*/
@IsNotEmpty({
message: "验证码不能为空",
})
captcha: string;
/**
* 手机号字段
* 使用class-validator进行验证,确保手机号不为空且格式正确
*/
@IsNotEmpty({
message: "手机号不能为空",
})
@IsPhoneNumber("CN", {
message: "请输入正确的手机号",
})
phone_number: string;
/**
* 头像字段
* 使用class-validator进行验证,确保头像不为空
*/
@IsNotEmpty({
message: "头像不能为空",
})
head_pic: string;
}
/**
* 发送邮件的数据传输对象(DTO)类
* 用于验证和传输发送邮件所需的数据
* 使用TypeScript类实现,结合class-validator进行数据验证
*/
export class SendEmailDto {
/**
* 邮箱地址
* @example user@example.com
*/
@IsNotEmpty({
message: "用户名不能为空",
})
@IsEmail(
{},
{
message: "请输入正确的邮箱",
}
)
email: string;
}update-user.dto.ts
ts
import { IsNotEmpty } from "class-validator";
export class UpdateUserDto {
@IsNotEmpty({
message: "用户ID不能为空",
})
id: number;
@IsNotEmpty({
message: "昵称不能为空",
})
nick_name: string;
@IsNotEmpty({
message: "手机号不能为空",
})
phone_number: string;
@IsNotEmpty({
message: "头像不能为空",
})
head_pic: string;
}updateAdmin.dto.ts
ts
import { IsNotEmpty } from "class-validator";
export class UpdateAdminDto {
@IsNotEmpty({
message: "id不能为空",
})
id: number;
@IsNotEmpty({
message: "is_admin不能为空",
})
is_admin: string;
}updateFrozenDto.dto.ts
ts
import { IsNotEmpty } from "class-validator";
export class UpdateFrozenDto {
@IsNotEmpty({
message: "id不能为空",
})
id: number;
@IsNotEmpty({
message: "id不能为空",
})
is_frozen: string;
}updatePassword.dto.ts
ts
import { IsNotEmpty } from "class-validator";
import { Match } from "./checkpassword";
export class UpdatePasswordDto {
@IsNotEmpty({
message: "旧密码不能为空",
})
oldPassword: string;
@IsNotEmpty({
message: "新密码不能为空",
})
newPassword: string;
@IsNotEmpty({
message: "密码不能为空",
})
@Match("newPassword", { message: "两次输入的密码不一致" })
confirmNewPassword: string;
}补充自己写的验证装饰器
- checkpassword.ts
ts
import {
registerDecorator,
ValidationOptions,
ValidatorConstraint,
ValidatorConstraintInterface,
ValidationArguments,
} from "class-validator";
// 1. 定义验证逻辑的类
@ValidatorConstraint({ name: "match", async: false })
class MatchConstraint implements ValidatorConstraintInterface {
validate(value: any, args: ValidationArguments) {
// [property] 指的是被装饰的属性(例如 confirmPassword)
// 通过 args.object 获取整个类的实例
const relatedPropertyName = args.constraints[0]; // 获取传入的要对比的属性名(例如 'password')
const relatedValue = (args.object as any)[relatedPropertyName];
// 如果两者值相等,则验证通过
return value === relatedValue;
}
// 2. 自定义错误消息(可选,如果不实现则使用默认消息)
defaultMessage(args: ValidationArguments) {
const relatedPropertyName = args.constraints[0];
return `${args.property} 必须与 ${relatedPropertyName} 一致`;
}
}
// 3. 创建装饰器函数
export function Match(property: string, validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
target: object.constructor,
propertyName: propertyName,
options: validationOptions,
constraints: [property], // 传入要对比的属性名
validator: MatchConstraint,
});
};
}