Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AuthModule } from './auth/auth.module';
import { ArticleModule } from './article/article.module';
import { UploadModule } from './upload/upload.module';
import { RecruitmentModule } from './recruitment/recruitment.module';
import { ResumeTemplateModule } from './resume-template/resume-template.module';
const envFilePath = ['.env'];
export const IS_DEV = process.env.RUNNING_ENV !== 'prod';

Expand Down Expand Up @@ -36,6 +37,7 @@ if (IS_DEV) {
ArticleModule,
UploadModule,
RecruitmentModule,
ResumeTemplateModule,
],
controllers: [AppController],
providers: [AppService],
Expand Down
10 changes: 10 additions & 0 deletions src/resume-template/dto/create-resume-template.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { IsJSON, IsNotEmpty, IsObject, IsString } from 'class-validator';
export class CreateResumeTemplateDto {
@IsString({ message: '简历模板名称必须为字符串' })
@IsNotEmpty({ message: '简历模板名称不能为空' })
resumeTemplateName: string;

@IsObject({ message: '简历模板内容必须为对象' })
@IsNotEmpty({ message: '简历模板内容不能为空' })
resumeTemplateContent: object;
}
15 changes: 15 additions & 0 deletions src/resume-template/dto/update-resume-template.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateResumeTemplateDto } from './create-resume-template.dto';
import { IsJSON, IsObject, IsOptional, IsString } from 'class-validator';

export class UpdateResumeTemplateDto extends PartialType(
CreateResumeTemplateDto,
) {
@IsOptional()
@IsString({ message: '简历模板名称必须是字符串' })
resumeTemplateName?: string;

@IsOptional()
@IsObject({ message: '简历模板内容必须是对象' })
resumeTemplateContent?: object;
}
52 changes: 52 additions & 0 deletions src/resume-template/entities/resume-template.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';

@Entity()
export class ResumeTemplateEntity {
// id 自增
@PrimaryGeneratedColumn({
type: 'int',
name: 'resume_template_id',
comment: '主键id',
})
resumeTemplateId: number;

// 简历模板名称
@Column({
type: 'varchar',
length: 255,
name: 'resume_template_name',
comment: '简历模板名称',
})
resumeTemplateName: string;

// 简历模板内容
@Column({
type: 'json',
name: 'resume_template_content',
nullable: false,
comment: '简历模板内容',
})
resumeTemplateContent: object;

// 创建时间
@CreateDateColumn({
type: 'datetime',
name: 'resume_template_create_time',
comment: '创建时间',
})
resumeTemplateCreateTime: Date;

// 更新时间
@UpdateDateColumn({
type: 'datetime',
name: 'resume_template_update_time',
comment: '更新时间',
})
resumeTemplateUpdateTime: Date;
}
20 changes: 20 additions & 0 deletions src/resume-template/resume-template.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ResumeTemplateController } from './resume-template.controller';
import { ResumeTemplateService } from './resume-template.service';

describe('ResumeTemplateController', () => {
let controller: ResumeTemplateController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ResumeTemplateController],
providers: [ResumeTemplateService],
}).compile();

controller = module.get<ResumeTemplateController>(ResumeTemplateController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
105 changes: 105 additions & 0 deletions src/resume-template/resume-template.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
UseGuards,
Query,
} from '@nestjs/common';
import { ResumeTemplateService } from './resume-template.service';
import { CreateResumeTemplateDto } from './dto/create-resume-template.dto';
import { UpdateResumeTemplateDto } from './dto/update-resume-template.dto';
import { AuthGuard } from '../auth/auth.guard';

/**
* 简历模板控制器
* 处理简历模板相关的http请求,如创建、查询、更新、删除简历模板
*/
@Controller('resumetemplate')
export class ResumeTemplateController {
/**
* 构造函数
* @param resumeTemplateService 简历模板服务
*/
constructor(private readonly resumeTemplateService: ResumeTemplateService) {}

/**
* 创建新的简历模板
* 需要用户登录认证权限
*
* @param createResumeTemplateDto 简历模板创建请求体
* @returns 返回创建的简历模板信息
*/
@Post()
@UseGuards(AuthGuard)
create(@Body() createResumeTemplateDto: CreateResumeTemplateDto) {
return this.resumeTemplateService.create(createResumeTemplateDto);
}

/**
* 获取所有简历模板
* 支持分页、按类型查找、按作者查找、按时间段查找
* @param query - 查询参数对象
* @returns 返回所有简历模板列表和总数
*/
@Get()
async findAll(
@Query('page') page?: number,
@Query('limit') limit?: number,
@Query('style') style?: string,
@Query('industry') industry?: string,
@Query('color') color?: string,
) {
return this.resumeTemplateService.findAll({
page,
limit,
style,
industry,
color,
});
}

/**
* 获取单个简历模板
*
* @param id - 简历模板id
* @returns 返回单个简历模板信息
*/
@Get(':id')
findOne(@Param('id') id: string) {
return this.resumeTemplateService.findOne(+id);
}

/**
* 更新简历模板
* 需要用户登录认证权限
*
* @param id - 简历模板id
* @param updateResumeTemplateDto - 简历模板更新请求体
* @returns 返回更新后的简历模板信息
*/
@Patch(':id')
@UseGuards(AuthGuard) // 需要用户登录认证权限
update(
@Param('id') id: string,
@Body() updateResumeTemplateDto: UpdateResumeTemplateDto,
) {
return this.resumeTemplateService.update(+id, updateResumeTemplateDto);
}

/**
* 删除简历模板
* 需要用户登录认证权限
*
* @param id - 简历模板id
* @returns 返回删除的简历模板信息
*/
@Delete(':id')
@UseGuards(AuthGuard) // 需要用户登录认证权限
remove(@Param('id') id: string) {
return this.resumeTemplateService.remove(+id);
}
}
13 changes: 13 additions & 0 deletions src/resume-template/resume-template.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { ResumeTemplateService } from './resume-template.service';
import { ResumeTemplateController } from './resume-template.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ResumeTemplateEntity } from './entities/resume-template.entity';

@Module({
imports: [TypeOrmModule.forFeature([ResumeTemplateEntity])],
controllers: [ResumeTemplateController],
providers: [ResumeTemplateService],
exports: [ResumeTemplateService],
})
export class ResumeTemplateModule {}
18 changes: 18 additions & 0 deletions src/resume-template/resume-template.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ResumeTemplateService } from './resume-template.service';

describe('ResumeTemplateService', () => {
let service: ResumeTemplateService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ResumeTemplateService],
}).compile();

service = module.get<ResumeTemplateService>(ResumeTemplateService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
131 changes: 131 additions & 0 deletions src/resume-template/resume-template.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ResumeTemplateEntity } from './entities/resume-template.entity';
import { CreateResumeTemplateDto } from './dto/create-resume-template.dto';
import { UpdateResumeTemplateDto } from './dto/update-resume-template.dto';

@Injectable()
export class ResumeTemplateService {
/**
* 构造函数
* @param resumeTemplateRepository - 简历模板仓库,用于操作简历模板数据
*/
constructor(
@InjectRepository(ResumeTemplateEntity)
private readonly resumeTemplateRepository: Repository<ResumeTemplateEntity>,
) {}

/**
* 创建新的简历模板
* @param createResumeTemplateDto - 创建简历模板的请求体
* @returns 返回创建的简历模板的信息
*/
async create(createResumeTemplateDto: CreateResumeTemplateDto) {
const ResumeTemplate = this.resumeTemplateRepository.create({
...createResumeTemplateDto,
});
const result = await this.resumeTemplateRepository.save(ResumeTemplate);
return result;
}

// 查找所有简历模板
async findAll(query: {
page?: number;
limit?: number;
style?: string;
industry?: string;
color?: string;
}) {
const { page = 1, limit = 10, style, industry, color } = query;

// 创建查询构建器
const queryBuilder =
this.resumeTemplateRepository.createQueryBuilder('resumeTemplate');

// 根据简历风格进行筛选
if (style) {
queryBuilder.andWhere(
"JSON_UNQUOTE(JSON_EXTRACT(resumeTemplate.resumeTemplateContent, '$.style')) = :style",
{ style },
);
}

// 根据简历行业进行筛选
if (industry) {
queryBuilder.andWhere(
"JSON_UNQUOTE(JSON_EXTRACT(resumeTemplate.resumeTemplateContent, '$.industry')) = :industry",
{
industry,
},
);
}

// 根据简历颜色进行筛选
if (color) {
queryBuilder.andWhere(
"JSON_UNQUOTE(JSON_EXTRACT(resumeTemplate.resumeTemplateContent, '$.color')) = :color",
{ color },
);
}

const [items, total] = await queryBuilder
.skip((page - 1) * limit)
.take(limit)
.getManyAndCount();

return {
items,
total,
};
}

/**
* 查询单个简历模板
* @param id - 简历模板id
* @returns 返回单个简历模板的信息
*/
async findOne(id: number) {
const result = await this.resumeTemplateRepository.findOne({
where: { resumeTemplateId: id },
});

if (!result) {
throw new NotFoundException(`简历模板ID ${id} 不存在`);
}

return result;
}

// 更新简历模板
async update(id: number, updateResumeTemplateDto: UpdateResumeTemplateDto) {
const result = await this.resumeTemplateRepository.update(id, {
...updateResumeTemplateDto,
});

// 检查是否更新成功
if (result.affected === 0) {
throw new NotFoundException(`简历模板ID ${id} 不存在`);
}

return result;
}

/**
* 删除简历模板
* 需要用户登录认证
*
* @param id - 简历模板id
* @returns 返回删除的简历模板的信息
*/
async remove(id: number) {
const result = await this.resumeTemplateRepository.delete(id);

// 检查是否删除成功
if (result.affected === 0) {
throw new NotFoundException(`简历模板ID ${id} 不存在`);
}

return result;
}
}