| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- 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<SolutionDesign> {
- private chapterRepository: Repository<SolutionChapter>;
- 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<SolutionDesign> {
- 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<void> {
- 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<SolutionChapter> {
- 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<SolutionChapter[]> {
- return this.chapterRepository.find({
- where: {
- solutionDesignId: designId,
- isDeleted: 0
- },
- order: { chapterNumber: 'ASC' }
- });
- }
- /**
- * 更新章节内容
- */
- async updateChapter(
- chapterId: number,
- data: any
- ): Promise<SolutionChapter> {
- 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<SolutionChapter>;
- }
- /**
- * 请求AI修改建议
- */
- async getAIModificationSuggestions(
- request: ChapterModificationRequest
- ): Promise<AIModificationSuggestion> {
- 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<SolutionChapter> {
- 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<SolutionChapter>;
- }
- /**
- * 更新方案设计进度
- */
- async updateProgress(designId: number): Promise<void> {
- 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<Buffer> {
- 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<string> {
- 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;
- }
- }
|