| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- """
- 图像翻译模块数据库迁移脚本
- 功能:
- 1. 创建 image_translation 表
- 2. 插入模型配置(model 和 model_price)
- 3. 插入百宝箱应用数据(toolbox_apps)
- 4. 验证数据完整性
- 从 .env 文件读取数据库连接信息
- """
- import os
- import sys
- from pathlib import Path
- from dotenv import load_dotenv
- import psycopg2
- from psycopg2 import sql
- # 添加项目根目录到路径
- sys.path.insert(0, str(Path(__file__).parent.parent))
- # 加载环境变量
- env_path = Path(__file__).parent.parent / '.env'
- load_dotenv(dotenv_path=env_path)
- def get_db_connection():
- """从环境变量获取数据库连接"""
- try:
- conn = psycopg2.connect(
- host=os.getenv("DB_HOST", "localhost"),
- port=int(os.getenv("DB_PORT", "5432")),
- database=os.getenv("DB_NAME", "aigcspace"),
- user=os.getenv("DB_USER", "postgres"),
- password=os.getenv("DB_PASSWORD", "")
- )
- return conn
- except Exception as e:
- print(f"❌ 数据库连接失败: {e}")
- sys.exit(1)
- def execute_sql_file(cursor, file_path: Path):
- """执行SQL文件"""
- try:
- with open(file_path, 'r', encoding='utf-8') as f:
- sql_content = f.read()
-
- # 执行SQL
- cursor.execute(sql_content)
- print(f"✓ 执行成功: {file_path.name}")
- return True
- except Exception as e:
- print(f"❌ 执行失败: {file_path.name}")
- print(f" 错误信息: {e}")
- return False
- def insert_model_data(cursor):
- """插入模型配置数据"""
- try:
- # 检查模型是否已存在
- cursor.execute("""
- SELECT id FROM aigcspace.model WHERE title = 'qwen-mt-image' LIMIT 1;
- """)
- existing_model = cursor.fetchone()
-
- if existing_model:
- print(f"✓ 模型 qwen-mt-image 已存在 (ID: {existing_model[0]})")
- model_id = existing_model[0]
- else:
- # 插入模型记录
- cursor.execute("""
- INSERT INTO aigcspace.model (
- title, description, provider, model_type,
- status, created_at, updated_at
- ) VALUES (
- 'qwen-mt-image',
- '通义千问图像翻译模型,支持多语种图像文字翻译',
- 'Alibaba',
- 'image-translation',
- 'active',
- NOW(),
- NOW()
- ) RETURNING id;
- """)
- model_id = cursor.fetchone()[0]
- print(f"✓ 模型 qwen-mt-image 插入成功 (ID: {model_id})")
-
- # 检查价格配置是否已存在
- cursor.execute("""
- SELECT id FROM aigcspace.model_price WHERE model_id = %s LIMIT 1;
- """, (model_id,))
- existing_price = cursor.fetchone()
-
- if existing_price:
- print(f"✓ 模型价格配置已存在 (ID: {existing_price[0]})")
- else:
- # 插入价格配置
- cursor.execute("""
- INSERT INTO aigcspace.model_price (
- model_id, input_price, output_price,
- created_at, updated_at
- ) VALUES (
- %s, 0.0000, 0.0200, NOW(), NOW()
- );
- """, (model_id,))
- print(f"✓ 模型价格配置插入成功(每张图片 0.02 元)")
-
- return True
- except Exception as e:
- print(f"❌ 模型数据插入失败: {e}")
- return False
- def insert_toolbox_app(cursor):
- """插入百宝箱应用数据"""
- try:
- # 检查应用是否已存在
- cursor.execute("""
- SELECT id FROM aigcspace.toolbox_apps
- WHERE app_key = 'qwen-image-translate' LIMIT 1;
- """)
- existing_app = cursor.fetchone()
-
- if existing_app:
- print(f"✓ 百宝箱应用 qwen-image-translate 已存在 (ID: {existing_app[0]})")
- return True
-
- # 插入应用记录
- cursor.execute("""
- INSERT INTO aigcspace.toolbox_apps (
- app_key, name, description, category, icon,
- is_new, is_hot, status, sort_order, version,
- created_at, updated_at
- ) VALUES (
- 'qwen-image-translate',
- '通义千问图像翻译',
- '支持多语种图像文字翻译,保持原图排版和风格',
- '图像处理',
- 'translate',
- true,
- true,
- 'active',
- 100,
- '1.0.0',
- NOW(),
- NOW()
- ) RETURNING id;
- """)
- app_id = cursor.fetchone()[0]
- print(f"✓ 百宝箱应用 qwen-image-translate 插入成功 (ID: {app_id})")
-
- return True
- except Exception as e:
- print(f"❌ 百宝箱应用插入失败: {e}")
- return False
- def verify_data(cursor):
- """验证数据是否正确插入"""
- try:
- print(f"\n📊 数据验证:")
-
- # 验证表是否创建
- cursor.execute("""
- SELECT EXISTS (
- SELECT FROM information_schema.tables
- WHERE table_schema = 'aigcspace'
- AND table_name = 'image_translation'
- );
- """)
- table_exists = cursor.fetchone()[0]
- print(f" ✓ image_translation 表: {'已创建' if table_exists else '❌ 未创建'}")
-
- # 验证模型配置
- cursor.execute("""
- SELECT m.id, m.title, mp.output_price
- FROM aigcspace.model m
- LEFT JOIN aigcspace.model_price mp ON m.id = mp.model_id
- WHERE m.title = 'qwen-mt-image';
- """)
- model_data = cursor.fetchone()
- if model_data:
- print(f" ✓ 模型配置: qwen-mt-image (ID: {model_data[0]}, 价格: {model_data[2]}元/张)")
- else:
- print(f" ❌ 模型配置未找到")
-
- # 验证百宝箱应用
- cursor.execute("""
- SELECT id, name, category, is_new, version, status
- FROM aigcspace.toolbox_apps
- WHERE app_key = 'qwen-image-translate';
- """)
- app_data = cursor.fetchone()
- if app_data:
- app_id, name, category, is_new, version, status = app_data
- new_tag = " [New]" if is_new else ""
- print(f" ✓ 百宝箱应用: {name}{new_tag} (版本: {version}, 状态: {status})")
- else:
- print(f" ❌ 百宝箱应用未找到")
-
- # 验证索引
- cursor.execute("""
- SELECT indexname FROM pg_indexes
- WHERE schemaname = 'aigcspace'
- AND tablename = 'image_translation';
- """)
- indexes = cursor.fetchall()
- print(f" ✓ 索引数量: {len(indexes)}")
- for idx in indexes:
- print(f" - {idx[0]}")
-
- return True
- except Exception as e:
- print(f"❌ 数据验证失败: {e}")
- return False
- def main():
- """主函数"""
- print("=" * 60)
- print("图像翻译模块数据库迁移脚本")
- print("=" * 60)
-
- # 获取迁移文件路径
- migrations_dir = Path(__file__).parent.parent / 'migrations'
- migration_file = migrations_dir / 'add_image_translation_table.sql'
-
- # 检查文件是否存在
- if not migration_file.exists():
- print(f"❌ 迁移文件不存在: {migration_file}")
- sys.exit(1)
-
- print(f"\n📁 找到迁移文件:")
- print(f" - {migration_file.name}")
-
- # 连接数据库
- print(f"\n🔌 连接数据库...")
- print(f" Host: {os.getenv('DB_HOST', 'localhost')}")
- print(f" Port: {os.getenv('DB_PORT', '5432')}")
- print(f" Database: {os.getenv('DB_NAME', 'aigcspace')}")
- print(f" User: {os.getenv('DB_USER', 'postgres')}")
-
- conn = get_db_connection()
- cursor = conn.cursor()
-
- print(f"✓ 数据库连接成功")
-
- # 执行迁移
- print(f"\n🚀 开始执行迁移...")
-
- # 1. 执行SQL文件(创建表)
- print(f"\n[1/3] 创建数据表...")
- if not execute_sql_file(cursor, migration_file):
- conn.rollback()
- cursor.close()
- conn.close()
- print(f"\n❌ 迁移失败,已回滚所有更改")
- sys.exit(1)
-
-
- # 提交事务
- conn.commit()
- print(f"\n✓ 所有迁移执行成功")
-
- # 验证数据
- verify_data(cursor)
-
- # 关闭连接
- cursor.close()
- conn.close()
-
- print(f"\n" + "=" * 60)
- print("✅ 图像翻译模块数据库迁移完成!")
- print("=" * 60)
- print(f"\n💡 下一步:")
- print(f" 1. 重启后端服务: cd backend && python main.py")
- print(f" 2. 访问百宝箱: http://localhost:5173/toolbox")
- print(f" 3. 点击「通义千问图像翻译」卡片的「立即使用」按钮")
- print(f" 4. 开始使用图像翻译功能")
- print()
- if __name__ == "__main__":
- try:
- main()
- except KeyboardInterrupt:
- print(f"\n\n⚠️ 用户中断执行")
- sys.exit(1)
- except Exception as e:
- print(f"\n\n❌ 执行过程中发生错误: {e}")
- import traceback
- traceback.print_exc()
- sys.exit(1)
|