From cf6844ad6e8472e4acbe47f6ecfd423fa0567ea1 Mon Sep 17 00:00:00 2001 From: imeepos Date: Thu, 4 Sep 2025 15:36:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E8=BF=81=E7=A7=BBAPI=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E4=B8=BAmigrations=E9=98=B6=E6=AE=B5=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 template-migration.service.ts 文件 - 移除控制器中的迁移相关API接口 (/migrate, /sync, /admin/migration-report) - 清理文档中的迁移服务相关内容 - 添加 data-source.ts 配置文件用于运行数据库迁移 - 模板迁移功能完全通过数据库migration脚本处理 --- data-source.ts | 16 ++ docs/template-hybrid-architecture.md | 86 +------ src/app.module.ts | 4 +- src/controllers/template.controller.ts | 69 +---- src/services/template-migration.service.ts | 280 --------------------- 5 files changed, 23 insertions(+), 432 deletions(-) create mode 100644 data-source.ts delete mode 100644 src/services/template-migration.service.ts diff --git a/data-source.ts b/data-source.ts new file mode 100644 index 0000000..8a42189 --- /dev/null +++ b/data-source.ts @@ -0,0 +1,16 @@ +import { DataSource } from 'typeorm'; + +export const AppDataSource = new DataSource({ + type: 'mysql', + host: 'mysql-6bc9094abd49-public.rds.volces.com', + port: 53305, + username: 'root', + password: 'WsJWXfwFx0bq6DE2kmB6', + database: 'nano_camera_miniapp', + entities: ['src/**/*.entity.ts'], + migrations: ['src/migrations/*.ts'], + synchronize: false, + logging: process.env.NODE_ENV === 'development', + charset: 'utf8mb4', + timezone: '+08:00', +}); \ No newline at end of file diff --git a/docs/template-hybrid-architecture.md b/docs/template-hybrid-architecture.md index 1eecb4f..46edc07 100644 --- a/docs/template-hybrid-architecture.md +++ b/docs/template-hybrid-architecture.md @@ -7,6 +7,7 @@ - **代码层**:抽象类定义执行逻辑和接口规范 - **数据库层**:存储具体模板的配置信息 - **Entity层**:动态从数据库加载配置,创建模板实例 +- **Migration层**:通过数据库迁移脚本初始化模板配置数据 ## 🏗️ 架构层次分析 @@ -373,18 +374,8 @@ export class TemplateController { @Param('templateId', ParseIntPipe) templateId: number, @Body() { imageUrl }: { imageUrl: string } ) { - // 动态创建模板实例并执行 - const config = await this.templateFactory.templateRepository.findOne({ - where: { id: templateId } - }); - - let template; - if (config.templateType === TemplateType.IMAGE) { - template = await this.templateFactory.createImageTemplate(templateId); - } else { - template = await this.templateFactory.createVideoTemplate(templateId); - } - + // 通过工厂服务创建模板实例并执行 + const template = await this.templateFactory.createTemplate(templateId); return await template.execute(imageUrl); } @@ -395,83 +386,16 @@ export class TemplateController { @Get('image') async getImageTemplates() { - return this.templateFactory.getTemplatesByType(TemplateType.IMAGE); + return this.templateFactory.getImageTemplates(); } @Get('video') async getVideoTemplates() { - return this.templateFactory.getTemplatesByType(TemplateType.VIDEO); + return this.templateFactory.getVideoTemplates(); } } ``` -### 3. 数据迁移脚本 -```typescript -// 将现有代码中的模板配置迁移到数据库 -// src/migrations/migrate-templates.ts -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { N8nTemplateEntity, TemplateType } from '../entities/n8n-template.entity'; - -// 导入现有模板 -import { PhotoRestoreTemplate } from '../templates/n8nTemplates/PhotoRestoreTemplate'; -import { CharacterFigurineTemplate } from '../templates/n8nTemplates/CharacterFigurineTemplate'; - -@Injectable() -export class TemplateMigrationService { - constructor( - @InjectRepository(N8nTemplateEntity) - private templateRepository: Repository, - ) {} - - async migrateExistingTemplates() { - // 迁移现有模板配置 - const templates = [ - new PhotoRestoreTemplate(), - new CharacterFigurineTemplate(), - // ... 其他模板 - ]; - - for (const template of templates) { - const existing = await this.templateRepository.findOne({ - where: { code: template.code } - }); - - if (!existing) { - const entity = new N8nTemplateEntity(); - entity.code = template.code; - entity.name = template.name; - entity.description = template.description; - entity.creditCost = template.creditCost; - entity.version = template.version; - entity.inputExampleUrl = template.input; - entity.outputExampleUrl = template.output; - entity.tags = template.tags; - - // 判断模板类型 - if (template instanceof N8nImageGenerateTemplate) { - entity.templateType = TemplateType.IMAGE; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - } else if (template instanceof N8nVideoGenerateTemplate) { - entity.templateType = TemplateType.VIDEO; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - entity.videoModel = template.videoModel; - entity.videoPrompt = template.videoPrompt; - entity.duration = template.duration; - entity.aspectRatio = template.aspectRatio; - } - - entity.templateClass = template.constructor.name; - - await this.templateRepository.save(entity); - } - } - } -} -``` ## ✅ 架构优势 diff --git a/src/app.module.ts b/src/app.module.ts index cd10d36..453c3f8 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,7 +6,6 @@ import { TemplateManager } from './templates/types'; import { typeOrmConfig } from './config/database.config'; import { N8nTemplateEntity } from './entities/n8n-template.entity'; import { N8nTemplateFactoryService } from './services/n8n-template-factory.service'; -import { TemplateMigrationService } from './services/template-migration.service'; import { TemplateController } from './controllers/template.controller'; @Module({ @@ -19,8 +18,7 @@ import { TemplateController } from './controllers/template.controller'; TemplateService, TemplateManager, N8nTemplateFactoryService, - TemplateMigrationService ], - exports: [N8nTemplateFactoryService, TemplateMigrationService] + exports: [N8nTemplateFactoryService] }) export class AppModule {} diff --git a/src/controllers/template.controller.ts b/src/controllers/template.controller.ts index 15e6863..6e716a7 100644 --- a/src/controllers/template.controller.ts +++ b/src/controllers/template.controller.ts @@ -10,7 +10,6 @@ import { HttpStatus } from '@nestjs/common'; import { N8nTemplateFactoryService } from '../services/n8n-template-factory.service'; -import { TemplateMigrationService } from '../services/template-migration.service'; /** * 模板控制器 @@ -19,8 +18,7 @@ import { TemplateMigrationService } from '../services/template-migration.service @Controller('templates') export class TemplateController { constructor( - private readonly templateFactory: N8nTemplateFactoryService, - private readonly migrationService: TemplateMigrationService + private readonly templateFactory: N8nTemplateFactoryService ) {} /** @@ -281,69 +279,4 @@ export class TemplateController { } } - /** - * 迁移现有代码模板到数据库 - * @returns 迁移结果 - */ - @Post('migrate') - async migrateTemplates() { - try { - await this.migrationService.migrateAllExistingTemplates(); - const report = await this.migrationService.getMigrationReport(); - - return { - success: true, - message: 'Templates migrated successfully', - data: report - }; - } catch (error) { - throw new HttpException( - error.message || 'Migration failed', - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - } - - /** - * 同步现有模板配置 - * @returns 同步结果 - */ - @Post('sync') - async syncTemplates() { - try { - await this.migrationService.syncExistingTemplates(); - const report = await this.migrationService.getMigrationReport(); - - return { - success: true, - message: 'Templates synchronized successfully', - data: report - }; - } catch (error) { - throw new HttpException( - error.message || 'Synchronization failed', - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - } - - /** - * 获取迁移状态报告 - * @returns 迁移状态报告 - */ - @Get('admin/migration-report') - async getMigrationReport() { - try { - const report = await this.migrationService.getMigrationReport(); - return { - success: true, - data: report - }; - } catch (error) { - throw new HttpException( - error.message || 'Failed to get migration report', - HttpStatus.INTERNAL_SERVER_ERROR - ); - } - } } \ No newline at end of file diff --git a/src/services/template-migration.service.ts b/src/services/template-migration.service.ts deleted file mode 100644 index 0e0a35f..0000000 --- a/src/services/template-migration.service.ts +++ /dev/null @@ -1,280 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { N8nTemplateEntity, TemplateType } from '../entities/n8n-template.entity'; -import { N8nImageGenerateTemplate, N8nVideoGenerateTemplate } from '../templates/n8nTemplate'; - -// 导入现有模板 -import { PhotoRestoreTemplate } from '../templates/n8nTemplates/PhotoRestoreTemplate'; -import { CharacterFigurineTemplate } from '../templates/n8nTemplates/CharacterFigurineTemplate'; -import { PetFigurineTemplate } from '../templates/n8nTemplates/PetFigurineTemplate'; -import { CosplayRealPersonTemplate } from '../templates/n8nTemplates/CosplayRealPersonTemplate'; -import { GarageOpeningTemplate } from '../templates/n8nTemplates/GarageOpeningTemplate'; -import { JapaneseMagazineTemplate } from '../templates/n8nTemplates/JapaneseMagazineTemplate'; -import { NuclearExplosionTemplate } from '../templates/n8nTemplates/NuclearExplosionTemplate'; - -/** - * 模板迁移服务 - * 负责将现有代码中的模板配置迁移到数据库 - */ -@Injectable() -export class TemplateMigrationService { - constructor( - @InjectRepository(N8nTemplateEntity) - private templateRepository: Repository, - ) {} - - /** - * 迁移所有现有模板到数据库 - */ - async migrateAllExistingTemplates(): Promise { - console.log('开始迁移现有模板到数据库...'); - - // 创建模板实例 - const templates = [ - new PhotoRestoreTemplate(), - new CharacterFigurineTemplate(), - new PetFigurineTemplate(), - new CosplayRealPersonTemplate(), - new GarageOpeningTemplate(), - new JapaneseMagazineTemplate(), - new NuclearExplosionTemplate(), - ]; - - let migratedCount = 0; - let skippedCount = 0; - - for (const template of templates) { - try { - const result = await this.migrateTemplate(template); - if (result) { - migratedCount++; - console.log(`✅ 成功迁移模板: ${template.code} - ${template.name}`); - } else { - skippedCount++; - console.log(`⏭️ 跳过已存在模板: ${template.code} - ${template.name}`); - } - } catch (error) { - console.error(`❌ 迁移模板失败: ${template.code}`, error); - } - } - - console.log(`\n📊 迁移完成统计:`); - console.log(` • 新增模板: ${migratedCount} 个`); - console.log(` • 跳过模板: ${skippedCount} 个`); - console.log(` • 总模板数: ${templates.length} 个\n`); - } - - /** - * 迁移单个模板 - * @param template 模板实例 - * @returns 是否创建了新记录 - */ - async migrateTemplate(template: any): Promise { - // 检查模板是否已存在 - const existing = await this.templateRepository.findOne({ - where: { code: template.code } - }); - - if (existing) { - return false; // 已存在,跳过 - } - - // 创建新的实体 - const entity = new N8nTemplateEntity(); - - // 基础属性 - entity.code = template.code; - entity.name = template.name; - entity.description = template.description; - entity.creditCost = template.creditCost; - entity.version = template.version; - entity.inputExampleUrl = template.input; - entity.outputExampleUrl = template.output; - entity.tags = template.tags; - entity.templateClass = template.constructor.name; - - // 判断模板类型并设置相应属性 - if (template instanceof N8nImageGenerateTemplate) { - entity.templateType = TemplateType.IMAGE; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - } else if (template instanceof N8nVideoGenerateTemplate) { - entity.templateType = TemplateType.VIDEO; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - entity.videoModel = template.videoModel; - entity.videoPrompt = template.videoPrompt; - entity.duration = template.duration; - entity.aspectRatio = template.aspectRatio; - } - - // 保存到数据库 - await this.templateRepository.save(entity); - return true; - } - - /** - * 清空所有模板数据(谨慎使用) - */ - async clearAllTemplates(): Promise { - console.log('⚠️ 清空所有模板数据...'); - await this.templateRepository.clear(); - console.log('✅ 所有模板数据已清空'); - } - - /** - * 同步现有模板配置(更新已存在的模板) - */ - async syncExistingTemplates(): Promise { - console.log('开始同步现有模板配置...'); - - const templates = [ - new PhotoRestoreTemplate(), - new CharacterFigurineTemplate(), - new PetFigurineTemplate(), - new CosplayRealPersonTemplate(), - new GarageOpeningTemplate(), - new JapaneseMagazineTemplate(), - new NuclearExplosionTemplate(), - ]; - - let updatedCount = 0; - let createdCount = 0; - - for (const template of templates) { - try { - const existing = await this.templateRepository.findOne({ - where: { code: template.code } - }); - - if (existing) { - // 更新现有模板 - await this.updateTemplateFromCode(existing, template); - updatedCount++; - console.log(`🔄 更新模板: ${template.code} - ${template.name}`); - } else { - // 创建新模板 - await this.migrateTemplate(template); - createdCount++; - console.log(`➕ 创建模板: ${template.code} - ${template.name}`); - } - } catch (error) { - console.error(`❌ 同步模板失败: ${template.code}`, error); - } - } - - console.log(`\n📊 同步完成统计:`); - console.log(` • 更新模板: ${updatedCount} 个`); - console.log(` • 创建模板: ${createdCount} 个`); - } - - /** - * 从代码模板更新数据库实体 - */ - private async updateTemplateFromCode(entity: N8nTemplateEntity, template: any): Promise { - // 更新基础属性 - entity.name = template.name; - entity.description = template.description; - entity.creditCost = template.creditCost; - entity.version = template.version; - entity.inputExampleUrl = template.input; - entity.outputExampleUrl = template.output; - entity.tags = template.tags; - entity.templateClass = template.constructor.name; - - // 更新类型特定属性 - if (template instanceof N8nImageGenerateTemplate) { - entity.templateType = TemplateType.IMAGE; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - } else if (template instanceof N8nVideoGenerateTemplate) { - entity.templateType = TemplateType.VIDEO; - entity.imageModel = template.imageModel; - entity.imagePrompt = template.imagePrompt; - entity.videoModel = template.videoModel; - entity.videoPrompt = template.videoPrompt; - entity.duration = template.duration; - entity.aspectRatio = template.aspectRatio; - } - - await this.templateRepository.save(entity); - } - - /** - * 获取迁移状态报告 - */ - async getMigrationReport(): Promise<{ - totalInDatabase: number; - totalInCode: number; - missingInDatabase: string[]; - extraInDatabase: string[]; - }> { - // 数据库中的模板 - const dbTemplates = await this.templateRepository.find({ - select: ['code', 'name'] - }); - - // 代码中的模板 - const codeTemplates = [ - new PhotoRestoreTemplate(), - new CharacterFigurineTemplate(), - new PetFigurineTemplate(), - new CosplayRealPersonTemplate(), - new GarageOpeningTemplate(), - new JapaneseMagazineTemplate(), - new NuclearExplosionTemplate(), - ]; - - const dbCodes = new Set(dbTemplates.map(t => t.code)); - const codeCodes = new Set(codeTemplates.map(t => t.code)); - - // 找出差异 - const missingInDatabase = codeTemplates - .filter(t => !dbCodes.has(t.code)) - .map(t => `${t.code} (${t.name})`); - - const extraInDatabase = dbTemplates - .filter(t => !codeCodes.has(t.code as any)) - .map(t => `${t.code} (${t.name})`); - - return { - totalInDatabase: dbTemplates.length, - totalInCode: codeTemplates.length, - missingInDatabase, - extraInDatabase - }; - } - - /** - * 打印迁移状态报告 - */ - async printMigrationReport(): Promise { - const report = await this.getMigrationReport(); - - console.log('\n📋 模板迁移状态报告:'); - console.log('='.repeat(50)); - console.log(`数据库中的模板数量: ${report.totalInDatabase}`); - console.log(`代码中的模板数量: ${report.totalInCode}`); - - if (report.missingInDatabase.length > 0) { - console.log('\n❌ 缺失在数据库中的模板:'); - report.missingInDatabase.forEach(template => { - console.log(` • ${template}`); - }); - } - - if (report.extraInDatabase.length > 0) { - console.log('\n⚠️ 数据库中多余的模板:'); - report.extraInDatabase.forEach(template => { - console.log(` • ${template}`); - }); - } - - if (report.missingInDatabase.length === 0 && report.extraInDatabase.length === 0) { - console.log('\n✅ 数据库与代码模板完全同步!'); - } - - console.log('='.repeat(50)); - } -} \ No newline at end of file