import { GenericCrudService } from '@/server/utils/generic-crud.service'; import { DataSource, Repository, In } from 'typeorm'; import { SolutionDesign } from './solution-design.entity'; import { SolutionChapter } from './solution-chapter.entity'; import { DocumentService } from '@/server/modules/documents/document.service'; import { FileService } from '@/server/modules/files/file.service'; import { AIService } from '@/server/services/ai.service'; export interface ChapterModificationRequest { chapterId: number; instructions: string; currentContent: string; } export interface AIModificationSuggestion { suggestions: string[]; revisedContent: string; confidence: number; } export class SolutionDesignService extends GenericCrudService { private chapterRepository: Repository; private documentService: DocumentService; private fileService: FileService; private aiService: AIService; constructor(dataSource: DataSource) { super(dataSource, SolutionDesign); this.chapterRepository = dataSource.getRepository(SolutionChapter); this.documentService = new DocumentService(dataSource); this.fileService = new FileService(dataSource); this.aiService = new AIService(); } /** * 创建方案设计并初始化章节 */ async createSolutionDesign( data: any, userId: number, originalFileId?: number ): Promise { const solutionDesign = this.repository.create({ ...data, userId, originalFileId: originalFileId || null, status: 'draft', progress: 0, totalChapters: 0, completedChapters: 0 }); const savedDesign = await this.repository.save(solutionDesign); // 如果有原始文件,尝试自动提取章节 if (originalFileId) { await this.autoExtractChapters(savedDesign.id, originalFileId); } return this.getById(savedDesign.id, ['user', 'originalFile', 'chapters']); } /** * 自动从原始文件提取章节 */ private async autoExtractChapters(designId: number, fileId: number): Promise { try { const file = await this.fileService.getById(fileId); if (!file) return; // 这里可以集成文档解析逻辑,自动识别章节结构 // 暂时创建默认章节 const defaultChapters = [ { chapterNumber: 1, title: '项目概述', content: '请填写项目概述内容' }, { chapterNumber: 2, title: '需求分析', content: '请填写需求分析内容' }, { chapterNumber: 3, title: '技术方案', content: '请填写技术方案内容' }, { chapterNumber: 4, title: '实施计划', content: '请填写实施计划内容' }, { chapterNumber: 5, title: '预算估算', content: '请填写预算估算内容' } ]; for (const chapterData of defaultChapters) { const chapter = this.chapterRepository.create({ ...chapterData, solutionDesignId: designId, originalContent: chapterData.content, status: 'pending' }); await this.chapterRepository.save(chapter); } // 更新总章节数 await this.repository.update(designId, { totalChapters: defaultChapters.length }); } catch (error) { console.error('自动提取章节失败:', error); } } /** * 获取用户的方案设计列表 */ async getUserSolutionDesigns( userId: number, page: number = 1, pageSize: number = 10, status?: string ): Promise<[SolutionDesign[], number]> { const where: any = { userId, isDeleted: 0 }; if (status) { where.status = status; } return this.getList( page, pageSize, undefined, ['title', 'description'], where, ['user', 'originalFile'], { updatedAt: 'DESC' } ); } /** * 添加章节到方案设计 */ async addChapter( designId: number, data: any ): Promise { const design = await this.getById(designId); if (!design) { throw new Error('方案设计不存在'); } const chapter = this.chapterRepository.create({ ...data, solutionDesignId: designId, status: 'pending', version: 1 }); const savedChapter = await this.chapterRepository.save(chapter); // 更新总章节数 await this.repository.increment({ id: designId }, 'totalChapters', 1); return savedChapter; } /** * 获取方案设计的所有章节 */ async getChapters(designId: number): Promise { return this.chapterRepository.find({ where: { solutionDesignId: designId, isDeleted: 0 }, order: { chapterNumber: 'ASC' } }); } /** * 更新章节内容 */ async updateChapter( chapterId: number, data: any ): Promise { const chapter = await this.chapterRepository.findOne({ where: { id: chapterId, isDeleted: 0 } }); if (!chapter) { throw new Error('章节不存在'); } // 如果内容有更新,增加版本号 if (data.content && data.content !== chapter.content) { data.version = chapter.version + 1; } await this.chapterRepository.update(chapterId, data); return this.chapterRepository.findOneBy({ id: chapterId }) as Promise; } /** * 请求AI修改建议 */ async getAIModificationSuggestions( request: ChapterModificationRequest ): Promise { const prompt = ` 请对以下章节内容提供修改建议: 原始内容:${request.currentContent} 修改要求:${request.instructions} 请提供: 1. 具体的修改建议列表 2. 修改后的完整内容 3. 修改的置信度评分(0-1) 请以JSON格式返回,包含suggestions、revisedContent、confidence字段。 `; try { const response = await this.aiService.generateText(prompt); return JSON.parse(response); } catch (error) { console.error('AI修改建议生成失败:', error); throw new Error('AI服务暂时不可用'); } } /** * 应用AI修改建议 */ async applyAIModifications( chapterId: number, suggestions: AIModificationSuggestion ): Promise { const chapter = await this.chapterRepository.findOne({ where: { id: chapterId, isDeleted: 0 } }); if (!chapter) { throw new Error('章节不存在'); } const updateData = { content: suggestions.revisedContent, aiSuggestions: JSON.stringify(suggestions.suggestions), version: chapter.version + 1, status: 'reviewing' }; await this.chapterRepository.update(chapterId, updateData); return this.chapterRepository.findOneBy({ id: chapterId }) as Promise; } /** * 更新方案设计进度 */ async updateProgress(designId: number): Promise { const completedCount = await this.chapterRepository.count({ where: { solutionDesignId: designId, status: 'completed', isDeleted: 0 } }); const totalCount = await this.chapterRepository.count({ where: { solutionDesignId: designId, isDeleted: 0 } }); const progress = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0; await this.repository.update(designId, { completedChapters: completedCount, totalChapters: totalCount, progress, status: progress === 100 ? 'completed' : 'reviewing' }); } /** * 生成最终文档 */ async generateFinalDocument(designId: number): Promise { const design = await this.getById(designId, ['chapters']); if (!design) { throw new Error('方案设计不存在'); } if (design.progress < 100) { throw new Error('请先完成所有章节的修改'); } // 按章节顺序组织内容 const sortedChapters = design.chapters.sort((a, b) => a.chapterNumber - b.chapterNumber); const documentContent = sortedChapters .map(chapter => `# ${chapter.title}\n\n${chapter.content}`) .join('\n\n'); // 使用文档服务生成最终文档 const buffer = Buffer.from(documentContent, 'utf-8'); if (design.outputFormat === 'pdf') { return this.documentService.convertWordToPdf(buffer, `solution_${designId}`); } return buffer; } /** * 保存最终文档到文件系统 */ async saveFinalDocument(designId: number, buffer: Buffer): Promise { const design = await this.getById(designId); if (!design) { throw new Error('方案设计不存在'); } const fileName = `solution_${designId}_${Date.now()}.${design.outputFormat}`; const downloadUrl = await this.documentService.saveToMinio(buffer, fileName); // 创建文件记录 const file = await this.fileService.createFile({ originalName: fileName, size: buffer.length, mimeType: design.outputFormat === 'pdf' ? 'application/pdf' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', storagePath: downloadUrl }); // 更新方案设计的输出文件 await this.repository.update(designId, { outputFileId: file.id, status: 'completed' }); return downloadUrl; } }