From 3fa9ecc33a0370f45e4c1c053b3ebcf82ddcc75c Mon Sep 17 00:00:00 2001 From: liuyi Date: Wed, 4 Jun 2025 11:14:19 +0800 Subject: [PATCH] add base service --- .../controllers/category.controller.ts | 2 +- .../content/services/category.service.ts | 41 ++++--------------- .../content/services/comment.service.ts | 14 ++++--- src/modules/content/services/post.service.ts | 11 +++-- .../content/services/search.service.ts | 2 +- src/modules/content/services/tag.service.ts | 24 ++++------- src/modules/database/base/service.ts | 27 +++++++++++- 7 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/modules/content/controllers/category.controller.ts b/src/modules/content/controllers/category.controller.ts index 891b451..b709385 100644 --- a/src/modules/content/controllers/category.controller.ts +++ b/src/modules/content/controllers/category.controller.ts @@ -60,6 +60,6 @@ export class CategoryController { @Delete(':id') @SerializeOptions({ groups: ['category-detail'] }) async delete(@Param('id', new ParseUUIDPipe()) id: string) { - return this.service.delete(id); + return this.service.delete([id]); } } diff --git a/src/modules/content/services/category.service.ts b/src/modules/content/services/category.service.ts index 0d11535..09e0634 100644 --- a/src/modules/content/services/category.service.ts +++ b/src/modules/content/services/category.service.ts @@ -2,33 +2,23 @@ import { Injectable } from '@nestjs/common'; import { isNil, omit } from 'lodash'; import { EntityNotFoundError } from 'typeorm'; -import { - CreateCategoryDto, - QueryCategoryDto, - UpdateCategoryDto, -} from '@/modules/content/dtos/category.dto'; +import { CreateCategoryDto, UpdateCategoryDto } from '@/modules/content/dtos/category.dto'; import { CategoryEntity } from '@/modules/content/entities/category.entity'; import { CategoryRepository } from '@/modules/content/repositories/category.repository'; -import { treePaginate } from '@/modules/database/utils'; +import { BaseService } from '@/modules/database/base/service'; @Injectable() -export class CategoryService { - constructor(protected repository: CategoryRepository) {} +export class CategoryService extends BaseService { + protected enableTrash = true; + + constructor(protected repository: CategoryRepository) { + super(repository); + } async findTrees() { return this.repository.findTrees(); } - async paginate(options?: QueryCategoryDto) { - const tree = await this.findTrees(); - const data = await this.repository.toFlatTrees(tree); - return treePaginate(options, data); - } - - async detail(id: string) { - return this.repository.findOneOrFail({ where: { id }, relations: ['parent', 'children'] }); - } - async create(data: CreateCategoryDto) { const item = await this.repository.save({ ...data, @@ -56,21 +46,6 @@ export class CategoryService { return item; } - async delete(id: string) { - const item = await this.repository.findOneOrFail({ - where: { id }, - relations: ['parent', 'children'], - }); - if (!isNil(item.children) && item.children.length > 0) { - const childrenCategories = [...item.children].map((c) => { - c.parent = item.parent; - return item; - }); - await this.repository.save(childrenCategories, { reload: true }); - } - return this.repository.remove(item); - } - async getParent(current?: string, parentId?: string) { if (current === parentId) { return undefined; diff --git a/src/modules/content/services/comment.service.ts b/src/modules/content/services/comment.service.ts index a131c8d..831b46a 100644 --- a/src/modules/content/services/comment.service.ts +++ b/src/modules/content/services/comment.service.ts @@ -11,14 +11,14 @@ import { } from '@/modules/content/dtos/comment.dto'; import { CommentEntity } from '@/modules/content/entities/comment.entity'; import { CommentRepository, PostRepository } from '@/modules/content/repositories'; +import { BaseService } from '@/modules/database/base/service'; import { treePaginate } from '@/modules/database/utils'; @Injectable() -export class CommentService { - constructor( - protected repository: CommentRepository, - protected postRepository: PostRepository, - ) {} +export class CommentService extends BaseService { + constructor(protected repository: CommentRepository, protected postRepository: PostRepository) { + super(repository); + } async findTrees(options: QueryCommentTreeDto = {}) { return this.repository.findTrees({ @@ -91,4 +91,8 @@ export class CommentService { } return parent; } + + update(data: any, ...others: any[]): Promise { + throw new Error('Method not implemented.'); + } } diff --git a/src/modules/content/services/post.service.ts b/src/modules/content/services/post.service.ts index 85d86e6..4d7c461 100644 --- a/src/modules/content/services/post.service.ts +++ b/src/modules/content/services/post.service.ts @@ -11,6 +11,7 @@ import { CategoryRepository } from '@/modules/content/repositories'; import { PostRepository } from '@/modules/content/repositories/post.repository'; import { SearchService } from '@/modules/content/services/search.service'; import { SearchType } from '@/modules/content/types'; +import { BaseService } from '@/modules/database/base/service'; import { SelectTrashMode } from '@/modules/database/constants'; import { QueryHook } from '@/modules/database/types'; import { paginate } from '@/modules/database/utils'; @@ -24,7 +25,9 @@ type FindParams = { }; @Injectable() -export class PostService { +export class PostService extends BaseService { + protected enableTrash = true; + constructor( protected repository: PostRepository, protected categoryRepository: CategoryRepository, @@ -32,13 +35,15 @@ export class PostService { protected tagRepository: TagRepository, protected searchService?: SearchService, protected searchType: SearchType = 'mysql', - ) {} + ) { + super(repository); + } async paginate(options: QueryPostDto, callback?: QueryHook) { if (!isNil(this.searchService) && !isNil(options.search) && this.searchType === 'meili') { return this.searchService.search( options.search, - pick(options, ['trashed', 'page', 'limit']), + pick(options, ['trashed', 'page', 'limit', 'isPublished']), ); } const qb = await this.buildListQuery(this.repository.buildBaseQB(), options, callback); diff --git a/src/modules/content/services/search.service.ts b/src/modules/content/services/search.service.ts index 73a0e4b..7385c0c 100644 --- a/src/modules/content/services/search.service.ts +++ b/src/modules/content/services/search.service.ts @@ -47,7 +47,7 @@ export class SearchService implements OnModuleInit { return this.client; } - async search(text: string, param: SearchOption = {}) { + async search(text: string, param: SearchOption = {}): Promise { const option = { page: 1, limit: 10, trashed: SelectTrashMode.ONLY, ...param }; const limit = isNil(option.limit) || option.limit < 1 ? 1 : option.limit; const page = isNil(option.page) || option.page < 1 ? 1 : option.page; diff --git a/src/modules/content/services/tag.service.ts b/src/modules/content/services/tag.service.ts index 2887f92..d2483cb 100644 --- a/src/modules/content/services/tag.service.ts +++ b/src/modules/content/services/tag.service.ts @@ -1,19 +1,18 @@ import { Injectable } from '@nestjs/common'; import { omit } from 'lodash'; -import { In } from 'typeorm'; - -import { CreateTagDto, QueryTagDto, UpdateTagDto } from '@/modules/content/dtos/tag.dto'; +import { CreateTagDto, UpdateTagDto } from '@/modules/content/dtos/tag.dto'; import { TagRepository } from '@/modules/content/repositories/tag.repository'; -import { paginate } from '@/modules/database/utils'; +import { BaseService } from '@/modules/database/base/service'; + +import { TagEntity } from '../entities'; @Injectable() -export class TagService { - constructor(protected repository: TagRepository) {} +export class TagService extends BaseService { + protected enableTrash = true; - async paginate(options: QueryTagDto) { - const qb = this.repository.buildBaseQB(); - return paginate(qb, options); + constructor(protected repository: TagRepository) { + super(repository); } async detail(id: string) { @@ -31,11 +30,4 @@ export class TagService { await this.repository.update(data.id, omit(data, ['id'])); return this.detail(data.id); } - - async delete(ids: string[]) { - const items = await this.repository.find({ - where: { id: In(ids) }, - }); - return this.repository.remove(items); - } } diff --git a/src/modules/database/base/service.ts b/src/modules/database/base/service.ts index 09328a5..d299033 100644 --- a/src/modules/database/base/service.ts +++ b/src/modules/database/base/service.ts @@ -1,4 +1,4 @@ -import { NotFoundException } from '@nestjs/common'; +import { ForbiddenException, NotFoundException } from '@nestjs/common'; import { isNil } from 'lodash'; import { In, ObjectLiteral, SelectQueryBuilder } from 'typeorm'; @@ -127,4 +127,29 @@ export abstract class BaseService< } return this.repository.remove(items); } + + async restore(ids: string[]) { + if (!this.enableTrash) { + throw new ForbiddenException( + `Can not to retore ${this.repository.qbName},because trash not enabled!`, + ); + } + const items = await this.repository.find({ + where: { id: In(ids) as any }, + withDeleted: true, + }); + const trashIds = items.filter((o) => !isNil(o.deletedAt)).map((o) => o.id); + if (trashIds.length < 1) { + return []; + } + await this.repository.restore(trashIds); + const qb = await this.buildListQB(this.repository.buildBaseQB(), undefined, async (_) => + _.andWhereInIds(trashIds), + ); + return qb.getMany(); + } + + abstract create(data: any, ...others: any[]): Promise; + + abstract update(data: any, ...others: any[]): Promise; }