import { Controller, Get, Post, Put, Delete, Body, Param, Query, HttpCode, HttpStatus, UploadedFile, UseInterceptors, BadRequestException, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { KnowledgeService } from '../../application/services/knowledge.service'; import { RAGService } from '../../application/services/rag.service'; import { TextExtractionService } from '../../application/services/text-extraction.service'; import { KnowledgeSource } from '../../domain/entities/knowledge-article.entity'; import { CreateArticleDto, UpdateArticleDto, SearchArticlesDto, RetrieveKnowledgeDto, ImportArticlesDto, FeedbackDto, ExtractedTextResponse, } from '../../application/dtos/knowledge.dto'; @Controller('knowledge') export class KnowledgeController { constructor( private knowledgeService: KnowledgeService, private ragService: RAGService, private textExtractionService: TextExtractionService, ) {} /** * 创建文章 */ @Post('articles') @HttpCode(HttpStatus.CREATED) async createArticle(@Body() dto: CreateArticleDto) { const article = await this.knowledgeService.createArticle({ ...dto, source: KnowledgeSource.MANUAL, }); return { success: true, data: article, }; } /** * 上传文件并提取文本(两步流程的第一步) * 返回提取的文本内容,管理员预览编辑后通过 createArticle 保存 */ @Post('articles/upload') @UseInterceptors( FileInterceptor('file', { limits: { fileSize: 200 * 1024 * 1024 }, }), ) async uploadAndExtract( @UploadedFile() file: Express.Multer.File, ): Promise<{ success: boolean; data: ExtractedTextResponse }> { if (!file) { throw new BadRequestException('未上传文件'); } const extracted = await this.textExtractionService.extractText(file); return { success: true, data: { extractedText: extracted.text, suggestedTitle: extracted.title, wordCount: extracted.wordCount, pageCount: extracted.pageCount, }, }; } /** * 获取文章详情 */ @Get('articles/:id') async getArticle(@Param('id') id: string) { const article = await this.knowledgeService.getArticle(id); if (!article) { return { success: false, error: 'Article not found', }; } return { success: true, data: article, }; } /** * 获取文章列表 */ @Get('articles') async listArticles( @Query('category') category?: string, @Query('publishedOnly') publishedOnly?: string, @Query('page') page?: string, @Query('pageSize') pageSize?: string, ) { const result = await this.knowledgeService.listArticles({ category, publishedOnly: publishedOnly === 'true', page: page ? parseInt(page) : 1, pageSize: pageSize ? parseInt(pageSize) : 20, }); return { success: true, data: result, }; } /** * 更新文章 */ @Put('articles/:id') async updateArticle( @Param('id') id: string, @Body() dto: UpdateArticleDto, ) { const article = await this.knowledgeService.updateArticle(id, dto); return { success: true, data: article, }; } /** * 删除文章 */ @Delete('articles/:id') @HttpCode(HttpStatus.NO_CONTENT) async deleteArticle(@Param('id') id: string) { await this.knowledgeService.deleteArticle(id); } /** * 发布文章 */ @Post('articles/:id/publish') async publishArticle(@Param('id') id: string) { await this.knowledgeService.publishArticle(id); return { success: true, message: 'Article published', }; } /** * 取消发布 */ @Post('articles/:id/unpublish') async unpublishArticle(@Param('id') id: string) { await this.knowledgeService.unpublishArticle(id); return { success: true, message: 'Article unpublished', }; } /** * 搜索文章 */ @Post('articles/search') async searchArticles(@Body() dto: SearchArticlesDto) { const results = await this.knowledgeService.searchArticles(dto); return { success: true, data: results, }; } /** * 记录反馈 */ @Post('articles/:id/feedback') async recordFeedback( @Param('id') id: string, @Body() dto: FeedbackDto, ) { await this.knowledgeService.recordFeedback(id, dto.helpful); return { success: true, message: 'Feedback recorded', }; } /** * 批量导入 */ @Post('articles/import') async importArticles(@Body() dto: ImportArticlesDto) { const result = await this.knowledgeService.importArticles(dto.articles); return { success: true, data: result, }; } /** * 获取统计信息 */ @Get('statistics') async getStatistics() { const stats = await this.knowledgeService.getStatistics(); return { success: true, data: stats, }; } // ========== RAG检索接口 ========== /** * RAG知识检索(供对话服务调用) */ @Post('retrieve') async retrieveKnowledge(@Body() dto: RetrieveKnowledgeDto) { const result = await this.ragService.retrieve(dto); return { success: true, data: result, }; } /** * 检索并格式化为提示词 */ @Post('retrieve/prompt') async retrieveForPrompt(@Body() dto: RetrieveKnowledgeDto) { const context = await this.ragService.retrieveForPrompt({ query: dto.query, userId: dto.userId, category: dto.category, }); return { success: true, data: { context }, }; } /** * 检查是否离题 */ @Post('check-off-topic') async checkOffTopic(@Body() body: { query: string }) { const result = await this.ragService.checkOffTopic(body.query); return { success: true, data: result, }; } }