From 388ab50718f8c7570a0fcdd30a6a9b931915794d Mon Sep 17 00:00:00 2001 From: liuyi Date: Wed, 21 May 2025 16:14:36 +0800 Subject: [PATCH] add service --- .../content/services/category.service.ts | 89 +++++++++++++++++++ src/modules/content/services/tag.service.ts | 35 ++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/modules/content/services/category.service.ts create mode 100644 src/modules/content/services/tag.service.ts diff --git a/src/modules/content/services/category.service.ts b/src/modules/content/services/category.service.ts new file mode 100644 index 0000000..6ea741c --- /dev/null +++ b/src/modules/content/services/category.service.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@nestjs/common'; +import { isNil, omit } from 'lodash'; +import { EntityNotFoundError } from 'typeorm'; + +import { CreateCategoryDto, QueryCategoryDto } from '@/modules/content/dtos/category.dto'; +import { CategoryEntity } from '@/modules/content/entities/CategoryEntity'; +import { CategoryRepository } from '@/modules/content/repositories/category.repository'; +import { treePaginate } from '@/modules/database/utils'; + +@Injectable() +export class CategoryService { + constructor(protected repository: CategoryRepository) {} + + 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.findOneByOrFail({ where: { id }, relations: ['parent'] }); + } + + async create(data: CreateCategoryDto) { + const item = await this.repository.save({ + ...data, + parent: await this.getParent(undefined, data.parent), + }); + return this.detail(item.id); + } + + async update(data: UpdateCategoryDto) { + await this.repository.update(data.id, omit(data, ['id', 'parent'])); + const item = await this.repository.findOneByOrFail({ + where: { id: data.id }, + relations: ['parent'], + }); + const parent = await this.getParent(item.parent?.id, data.parent); + const shouldUpdateParent = + (!isNil(item.parent) && !isNil(parent) && item.parent.id !== parent.id) || + (!isNil(item.parent) && !isNil(parent)) || + (!isNil(item.parent) && isNil(parent)); + + if (shouldUpdateParent && parent !== undefined) { + item.parent = parent; + await this.repository.save(item, { reload: true }); + } + return item; + } + + async delete(id: string) { + const item = await this.repository.findOneByOrFail({ + 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; + } + let parent: CategoryEntity | undefined; + if (parentId !== undefined) { + if (parentId === null) { + return null; + } + parent = await this.repository.findOne({ where: { id: parentId } }); + if (!parent) { + throw new EntityNotFoundError( + CategoryEntity, + `Parent category with id ${parentId} not exists!`, + ); + } + } + return parent; + } +} diff --git a/src/modules/content/services/tag.service.ts b/src/modules/content/services/tag.service.ts new file mode 100644 index 0000000..97458d8 --- /dev/null +++ b/src/modules/content/services/tag.service.ts @@ -0,0 +1,35 @@ +import { omit } from 'lodash'; + +import { CreateTagDto, QueryTagDto } from '@/modules/content/dtos/tag.dto'; +import { TagRepository } from '@/modules/content/repositories/tag.repository'; +import { paginate } from '@/modules/database/utils'; + +export class TagService { + constructor(protected repository: TagRepository) {} + + async paginate(options: QueryTagDto) { + const qb = this.repository.buildBaseQB(); + return paginate(qb, options); + } + + async detail(id: string) { + const qb = this.repository.buildBaseQB(); + qb.where(`tag.id = :id`, { id }); + return qb.getOneOrFail(); + } + + async create(data: CreateTagDto) { + const item = await this.repository.save(data); + return this.detail(item.id); + } + + async update(data: UpdateTagDto) { + await this.repository.update(data.id, omit(data, ['id'])); + return this.detail(data.id); + } + + async delete(id: string) { + const item = this.repository.findOneByOrFail({ id }); + return this.repository.remove(item); + } +}