diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..638d98b Binary files /dev/null and b/.DS_Store differ diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 1f61f6d..2046a61 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -7,10 +7,9 @@ export class AuthService { constructor( private usersService: UsercenterService, private jwtService: JwtService, - ) { } + ) {} async signIn(username: string, pass: string): Promise { - const user = await this.usersService.findOne(username); // 直接使用用户密码进行验证 diff --git a/src/auth/guards/admin.guard.ts b/src/auth/guards/admin.guard.ts index f6b6158..9768060 100644 --- a/src/auth/guards/admin.guard.ts +++ b/src/auth/guards/admin.guard.ts @@ -25,7 +25,7 @@ export class AdminGuard implements CanActivate { // 获取用户信息 const userInfo = await this.usercenterService.findOne(user.sub); - + // 检查用户是否具有管理员权限 (userAuth === 2) if (userInfo.userAuth !== 2) { throw new ForbiddenException('需要管理员权限'); diff --git a/src/recruitment/dto/recruitment-response.dto.ts b/src/recruitment/dto/recruitment-response.dto.ts index c851b70..db96a17 100644 --- a/src/recruitment/dto/recruitment-response.dto.ts +++ b/src/recruitment/dto/recruitment-response.dto.ts @@ -72,7 +72,9 @@ export class RecruitmentResponseDto { this.recrType = recruitment.recrType; this.recrTypeText = this.getRecrTypeText(recruitment.recrType); this.officialResumeStatus = recruitment.officialResumeStatus; - this.officialResumeStatusText = this.getStatusText(recruitment.officialResumeStatus); + this.officialResumeStatusText = this.getStatusText( + recruitment.officialResumeStatus, + ); this.officialFeedbackInfromation = recruitment.officialFeedbackInfromation; this.resumeFilePath = recruitment.resumeFilePath; this.createTime = recruitment.createTime; diff --git a/src/recruitment/dto/update-recruitment.dto.ts b/src/recruitment/dto/update-recruitment.dto.ts index e6e7321..521ffc7 100644 --- a/src/recruitment/dto/update-recruitment.dto.ts +++ b/src/recruitment/dto/update-recruitment.dto.ts @@ -1,10 +1,4 @@ -import { - IsInt, - IsOptional, - IsString, - Min, - Max, -} from 'class-validator'; +import { IsInt, IsOptional, IsString, Min, Max } from 'class-validator'; import { Type } from 'class-transformer'; /** diff --git a/src/recruitment/entities/recruiment.entity.ts b/src/recruitment/entities/recruiment.entity.ts index 23b58c7..948a4e8 100644 --- a/src/recruitment/entities/recruiment.entity.ts +++ b/src/recruitment/entities/recruiment.entity.ts @@ -1,92 +1,92 @@ // 招聘模块数据表 import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, } from 'typeorm'; -@Entity("recruitment") +@Entity('recruitment') export class RecruitmentEntity { - // 官网简历投递ID - @PrimaryGeneratedColumn({ - name: 'official_resume_id', - }) - officialResumeId: number; + // 官网简历投递ID + @PrimaryGeneratedColumn({ + name: 'official_resume_id', + }) + officialResumeId: number; - // 用户ID - @Column({ - name: "user_id", - nullable: false, - type: "int", - }) - userId: number; + // 用户ID + @Column({ + name: 'user_id', + nullable: false, + type: 'int', + }) + userId: number; - // 求职类型 - @Column({ - name: "recr_type", - nullable: false, - type: "int", - default: 1, - }) - recrType: number; // 前端部门 1, UI部门 2,办公部门 3 + // 求职类型 + @Column({ + name: 'recr_type', + nullable: false, + type: 'int', + default: 1, + }) + recrType: number; // 前端部门 1, UI部门 2,办公部门 3 - // 简历投递状态 - @Column({ - name: "official_resume_status", - nullable: false, - type: "int", - default: 1, - }) - officialResumeStatus: number; // 1. 未处理 2. 淘汰 3. 面试 4. 通过面试 + // 简历投递状态 + @Column({ + name: 'official_resume_status', + nullable: false, + type: 'int', + default: 1, + }) + officialResumeStatus: number; // 1. 未处理 2. 淘汰 3. 面试 4. 通过面试 - // 官网简历反馈信息 - @Column({ - name: "official_feedback_infromation", - nullable: true, - type: "text", - }) - officialFeedbackInfromation: string; + // 官网简历反馈信息 + @Column({ + name: 'official_feedback_infromation', + nullable: true, + type: 'text', + }) + officialFeedbackInfromation: string; - // email - @Column({ - name: "email", - nullable: true, - type: "varchar", - default: "", - }) - email: string; + // email + @Column({ + name: 'email', + nullable: true, + type: 'varchar', + default: '', + }) + email: string; - // 电话号 - @Column({ - name: "phone", - nullable: true, - type: "varchar", - default: "", - }) - phone: string; + // 电话号 + @Column({ + name: 'phone', + nullable: true, + type: 'varchar', + default: '', + }) + phone: string; - // 简历文件地址 - @Column({ - name: "resume_file_path", - nullable: true, - type: "varchar", - default: "", - }) - resumeFilePath: string; + // 简历文件地址 + @Column({ + name: 'resume_file_path', + nullable: true, + type: 'varchar', + default: '', + }) + resumeFilePath: string; - // 创建时间 - @CreateDateColumn({ - name: "create_time", - nullable: false, - }) - createTime: Date; + // 创建时间 + @CreateDateColumn({ + name: 'create_time', + nullable: false, + }) + createTime: Date; - // 更新时间 - @UpdateDateColumn({ - name: "update_time", - nullable: false, - }) - updateTime: Date; + // 更新时间 + @UpdateDateColumn({ + name: 'update_time', + nullable: false, + }) + updateTime: Date; } diff --git a/src/recruitment/recruitment.controller.ts b/src/recruitment/recruitment.controller.ts index 944bf0a..d51fabc 100644 --- a/src/recruitment/recruitment.controller.ts +++ b/src/recruitment/recruitment.controller.ts @@ -119,7 +119,11 @@ export class RecruitmentController { @Body() updateRecruitmentDto: UpdateRecruitmentDto, @Request() req, ): Promise { - return this.recruitmentService.update(+id, updateRecruitmentDto, req.user.sub); + return this.recruitmentService.update( + +id, + updateRecruitmentDto, + req.user.sub, + ); } /** diff --git a/src/recruitment/recruitment.module.ts b/src/recruitment/recruitment.module.ts index a20dc7b..76a7376 100644 --- a/src/recruitment/recruitment.module.ts +++ b/src/recruitment/recruitment.module.ts @@ -6,10 +6,8 @@ import { RecruitmentEntity } from './entities/recruiment.entity'; import { UserEntity } from '../usercenter/entities/usercenter.entity'; @Module({ - imports: [ - TypeOrmModule.forFeature([RecruitmentEntity, UserEntity]), - ], + imports: [TypeOrmModule.forFeature([RecruitmentEntity, UserEntity])], controllers: [RecruitmentController], - providers: [RecruitmentService] + providers: [RecruitmentService], }) export class RecruitmentModule {} diff --git a/src/recruitment/recruitment.service.ts b/src/recruitment/recruitment.service.ts index 96b74a9..e33bc03 100644 --- a/src/recruitment/recruitment.service.ts +++ b/src/recruitment/recruitment.service.ts @@ -1,4 +1,8 @@ -import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common'; +import { + Injectable, + NotFoundException, + ForbiddenException, +} from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, Between } from 'typeorm'; import { RecruitmentEntity } from './entities/recruiment.entity'; @@ -61,7 +65,8 @@ export class RecruitmentService { const skip = (page - 1) * limit; // 创建查询构建器 - const queryBuilder = this.recruitmentRepository.createQueryBuilder('recruitment'); + const queryBuilder = + this.recruitmentRepository.createQueryBuilder('recruitment'); // 根据求职类型过滤 if (type) { @@ -70,17 +75,23 @@ export class RecruitmentService { // 根据简历状态过滤 if (status) { - queryBuilder.andWhere('recruitment.officialResumeStatus = :status', { status }); + queryBuilder.andWhere('recruitment.officialResumeStatus = :status', { + status, + }); } // 根据邮箱过滤 if (email) { - queryBuilder.andWhere('recruitment.email LIKE :email', { email: `%${email}%` }); + queryBuilder.andWhere('recruitment.email LIKE :email', { + email: `%${email}%`, + }); } // 根据电话过滤 if (phone) { - queryBuilder.andWhere('recruitment.phone LIKE :phone', { phone: `%${phone}%` }); + queryBuilder.andWhere('recruitment.phone LIKE :phone', { + phone: `%${phone}%`, + }); } // 根据时间范围过滤 @@ -162,7 +173,9 @@ export class RecruitmentService { const isAdmin = user.userAuth === 2; if (!isAdmin) { - throw new ForbiddenException('您没有权限修改这份简历,只有管理员可以进行此操作'); + throw new ForbiddenException( + '您没有权限修改这份简历,只有管理员可以进行此操作', + ); } const updatedRecruitment = await this.recruitmentRepository.save({ @@ -204,7 +217,9 @@ export class RecruitmentService { const isAdmin = user.userAuth === 2; if (!isAdmin) { - throw new ForbiddenException('您没有权限删除这份简历,只有管理员可以进行此操作'); + throw new ForbiddenException( + '您没有权限删除这份简历,只有管理员可以进行此操作', + ); } // 删除简历 diff --git a/src/upload/entities/upload.entity.ts b/src/upload/entities/upload.entity.ts index 3dda9fa..f0f7e05 100644 --- a/src/upload/entities/upload.entity.ts +++ b/src/upload/entities/upload.entity.ts @@ -1,4 +1,9 @@ -import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import { + Column, + CreateDateColumn, + Entity, + PrimaryGeneratedColumn, +} from 'typeorm'; @Entity('uploads') export class Upload { diff --git a/src/upload/upload.controller.ts b/src/upload/upload.controller.ts index 5b53d20..4b59eed 100644 --- a/src/upload/upload.controller.ts +++ b/src/upload/upload.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Post, Get, UploadedFile, UseInterceptors, Query, UseGuards } from '@nestjs/common'; +import { + Controller, + Post, + Get, + UploadedFile, + UseInterceptors, + Query, + UseGuards, +} from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { UploadService } from './upload.service'; import { Upload } from './entities/upload.entity'; diff --git a/src/upload/upload.service.ts b/src/upload/upload.service.ts index 39019be..124c140 100644 --- a/src/upload/upload.service.ts +++ b/src/upload/upload.service.ts @@ -5,6 +5,15 @@ import { Repository } from 'typeorm'; import * as qiniu from 'qiniu'; import { Upload } from './entities/upload.entity'; +interface QiniuResponse { + hash: string; + key: string; +} + +interface QiniuCallbackInfo { + statusCode: number; +} + @Injectable() export class UploadService { private mac: qiniu.auth.digest.Mac; @@ -32,27 +41,33 @@ export class UploadService { this.uploadToken = putPolicy.uploadToken(this.mac); } - async uploadFile(file: Express.Multer.File) { + async uploadFile(file: Express.Multer.File): Promise { const formUploader = new qiniu.form_up.FormUploader(this.config); const putExtra = new qiniu.form_up.PutExtra(); - + // 验证配置是否存在 - const accessKey = this.configService.get('kodo.ACCESS_KEY'); - const secretKey = this.configService.get('kodo.SECRET_KEY'); - const bucket = this.configService.get('kodo.BUCKET'); - const baseUrl = this.configService.get('kodo.BASE_URL'); + const accessKey = this.configService.get('kodo.ACCESS_KEY'); + const secretKey = this.configService.get('kodo.SECRET_KEY'); + const bucket = this.configService.get('kodo.BUCKET'); + const baseUrl = this.configService.get('kodo.BASE_URL'); if (!accessKey || !secretKey || !bucket || !baseUrl) { - throw new Error('Missing required Qiniu configuration. Please check your configuration file.'); + throw new Error( + 'Missing required Qiniu configuration. Please check your configuration file.', + ); } - + return new Promise((resolve, reject) => { formUploader.put( this.uploadToken, null, // 使用七牛云生成的文件名 file.buffer, putExtra, - async (err, body, info) => { + ( + err: Error | undefined, + body: QiniuResponse, + info: QiniuCallbackInfo, + ) => { try { // 检查是否有错误 if (err) { @@ -70,8 +85,9 @@ export class UploadService { `File upload failed with status code: ${info.statusCode}`, ), ); - } // 获取基础 URL 并构造上传对象 - const baseUrl = this.configService.get('kodo.BASE_URL'); + } + // 获取基础 URL 并构造上传对象 + const baseUrl = this.configService.get('kodo.BASE_URL'); const upload = new Upload(); upload.hash = body.hash; upload.key = body.key; @@ -79,8 +95,12 @@ export class UploadService { // 将上传信息保存到数据库 try { - const savedUpload = await this.uploadRepository.save(upload); - resolve(savedUpload); // 成功时返回保存的对象 + this.uploadRepository + .save(upload) + .then((savedUpload) => resolve(savedUpload)) + .catch((error) => + reject(new Error(`Failed to save upload: ${error.message}`)), + ); // 成功时返回保存的对象 } catch (dbError) { console.error('Database save error:', dbError); reject( diff --git a/src/usercenter/dto/create-usercenter.dto.ts b/src/usercenter/dto/create-usercenter.dto.ts index a0c835c..fc6e259 100644 --- a/src/usercenter/dto/create-usercenter.dto.ts +++ b/src/usercenter/dto/create-usercenter.dto.ts @@ -1,4 +1,13 @@ -import { IsEmail, IsString, Length, Matches, IsOptional, IsInt, Min, Max } from 'class-validator'; +import { + IsEmail, + IsString, + Length, + Matches, + IsOptional, + IsInt, + Min, + Max, +} from 'class-validator'; export class CreateUsercenterDto { @IsString() diff --git a/src/usercenter/dto/query-usercenter.dto.ts b/src/usercenter/dto/query-usercenter.dto.ts index a5eea7b..8f60cec 100644 --- a/src/usercenter/dto/query-usercenter.dto.ts +++ b/src/usercenter/dto/query-usercenter.dto.ts @@ -1,9 +1,4 @@ -import { - IsOptional, - IsInt, - Min, - Max, -} from 'class-validator'; +import { IsOptional, IsInt, Min, Max } from 'class-validator'; import { Type } from 'class-transformer'; /** diff --git a/src/usercenter/usercenter.controller.ts b/src/usercenter/usercenter.controller.ts index 0a2effa..eeba207 100644 --- a/src/usercenter/usercenter.controller.ts +++ b/src/usercenter/usercenter.controller.ts @@ -19,7 +19,7 @@ import { QueryUsercenterDto } from './dto/query-usercenter.dto'; @Controller('usercenter') export class UsercenterController { - constructor(private readonly usercenterService: UsercenterService) { } + constructor(private readonly usercenterService: UsercenterService) {} @Post() createUser(@Body() createUsercenterDto: CreateUsercenterDto) { @@ -34,10 +34,10 @@ export class UsercenterController { /** * 获取用户列表,支持分页和按角色筛选 * 需要管理员权限 - * + * * @param query 查询参数对象 * @returns 返回用户列表和总数 - * + * * @example * GET /usercenter/list?page=1&limit=10&role=1 */ @@ -46,13 +46,20 @@ export class UsercenterController { async findUsersByRole(@Query() query: QueryUsercenterDto) { // 确保传递给服务方法的是所需类型 const { page = 1, limit = 10, role } = query; - const data = await this.usercenterService.findUsersByRole({ page, limit, role }); + const data = await this.usercenterService.findUsersByRole({ + page, + limit, + role, + }); // 删除密码字段 const { data: users, ...rest } = data; - return { ...rest, data: users.map(user => ({ - ...user, - userPassword: undefined - })) }; + return { + ...rest, + data: users.map((user) => ({ + ...user, + userPassword: undefined, + })), + }; } @Get(':identifier') diff --git a/src/usercenter/usercenter.service.ts b/src/usercenter/usercenter.service.ts index c1b1313..291a288 100644 --- a/src/usercenter/usercenter.service.ts +++ b/src/usercenter/usercenter.service.ts @@ -15,10 +15,12 @@ export class UsercenterService { constructor( @InjectRepository(UserEntity) private readonly userRepository: Repository, - ) { } + ) {} async createUser(createUsercenterDto: CreateUsercenterDto) { // 验证密码是否匹配 - if (createUsercenterDto.userPassword !== createUsercenterDto.confirmPassword) { + if ( + createUsercenterDto.userPassword !== createUsercenterDto.confirmPassword + ) { throw new BadRequestException('两次输入的密码不匹配'); } @@ -84,7 +86,12 @@ export class UsercenterService { * @param query 查询参数,包含页码、每页条数和角色 * @returns 返回用户列表和总数 */ - async findUsersByRole(query: { page: number; limit: number; role?: number; sex?: number }) { + async findUsersByRole(query: { + page: number; + limit: number; + role?: number; + sex?: number; + }) { const { page, limit, role, sex } = query; const skip = (page - 1) * limit; // 计算跳过的记录数 @@ -109,7 +116,12 @@ export class UsercenterService { .getManyAndCount(); if (total === 0) { - return { total: 0, data: [], message: '没有找到符合条件的用户', status: 200 }; + return { + total: 0, + data: [], + message: '没有找到符合条件的用户', + status: 200, + }; } return { total, data }; @@ -137,7 +149,7 @@ export class UsercenterService { throw new InternalServerErrorException(`未找到匹配 ${identifier} 的记录`); } - return user + return user; } async update(id: number, updateUsercenterDto: UpdateUsercenterDto) {