import { Injectable, BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common'; import { KnowledgeBaseRepository } from './knowledge-base.repository'; import { PrismaService } from '../../infrastructure/database/prisma.service'; import { ContentSafetyService } from '../content-safety/content-safety.service'; import { MAX_KNOWLEDGE_BASE_COUNT } from './constants/knowledge-base.constants'; @Injectable() export class KnowledgeBaseService { constructor( private readonly repository: KnowledgeBaseRepository, private readonly prisma: PrismaService, private readonly safety?: ContentSafetyService, ) {} async create(userId: string, dto: any) { const count = await this.repository.countByUserId(userId); if (count >= MAX_KNOWLEDGE_BASE_COUNT) { throw new BadRequestException('知识库数量已达到上限'); } if (dto.title) { const check = await this.safety?.check(dto.title, { userId, contentType: 'kb-title' }); if (check && !check.safe) throw new ForbiddenException('知识库名称包含违规内容'); } return this.repository.create(userId, dto); } async findAll(userId: string, pagination: { page?: number; limit?: number }) { return this.repository.findAllByUserId(userId, pagination); } async findOne(userId: string, id: string) { const kb = await this.repository.findById(id); if (!kb || String(kb.userId) !== userId) { throw new NotFoundException('知识库不存在'); } return kb; } async update(userId: string, id: string, dto: any) { const kb = await this.repository.findById(id); if (!kb || String(kb.userId) !== userId) { throw new NotFoundException('知识库不存在'); } if (dto.title) { const check = await this.safety?.check(dto.title, { userId, contentType: 'kb-title' }); if (check && !check.safe) throw new ForbiddenException('知识库名称包含违规内容'); } return this.repository.update(id, dto); } async remove(userId: string, id: string) { const kb = await this.repository.findById(id); if (!kb || String(kb.userId) !== userId) { throw new NotFoundException('知识库不存在'); } return this.repository.softDelete(id); } // ── Folder CRUD ── async createFolder(kbId: string, dto: { name: string; parentId?: string }) { return this.prisma.knowledgeFolder.create({ data: { knowledgeBaseId: kbId, name: dto.name, parentId: dto.parentId || null }, }); } async getFolders(kbId: string) { return this.prisma.knowledgeFolder.findMany({ where: { knowledgeBaseId: kbId, deletedAt: null }, orderBy: { sortOrder: 'asc' }, }); } async updateFolder(folderId: string, dto: { name?: string; parentId?: string | null }) { return this.prisma.knowledgeFolder.update({ where: { id: folderId }, data: dto }); } async deleteFolder(folderId: string) { // Soft-delete folder and children await this.prisma.knowledgeFolder.updateMany({ where: { OR: [{ id: folderId }, { parentId: folderId }] }, data: { deletedAt: new Date() }, }); return { success: true }; } }