""" 数据库迁移脚本 v2 - 直接执行 ALTER TABLE """ import os import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from sqlalchemy import text from app.database import engine def run_migration(): print("=" * 50) print("蜂鸟Pro v2.1 数据库迁移 (ALTER TABLE)") print("=" * 50) # 需要添加的列 alter_statements = [ # ===== cursor_accounts 表 ===== # 重命名 access_token -> token (如果存在) ("cursor_accounts", "ALTER TABLE cursor_accounts CHANGE COLUMN access_token token TEXT NOT NULL"), # 添加新列 ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN account_type VARCHAR(20) DEFAULT 'unknown'"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN membership_type VARCHAR(50) NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN billing_cycle_start DATETIME NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN billing_cycle_end DATETIME NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN trial_days_remaining INT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN usage_limit INT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN usage_used INT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN usage_remaining INT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN usage_percent DECIMAL(5,2) DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN total_requests INT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN total_input_tokens BIGINT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN total_output_tokens BIGINT DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN total_cost_cents DECIMAL(10,2) DEFAULT 0"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN locked_by_key_id INT NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN locked_at DATETIME NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN last_analyzed_at DATETIME NULL"), ("cursor_accounts", "ALTER TABLE cursor_accounts ADD COLUMN analyze_error VARCHAR(500) NULL"), # ===== activation_keys 表 ===== ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN master_key_id INT NULL"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN merged_count INT DEFAULT 0"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN merged_at DATETIME NULL"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN duration_days INT DEFAULT 30"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN quota_contribution INT DEFAULT 500"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN seamless_enabled BOOLEAN DEFAULT FALSE"), ("activation_keys", "ALTER TABLE activation_keys ADD COLUMN last_active_at DATETIME NULL"), # ===== global_settings 表 ===== ("global_settings", "ALTER TABLE global_settings ADD COLUMN value_type VARCHAR(20) DEFAULT 'string'"), ("global_settings", "ALTER TABLE global_settings ADD COLUMN description VARCHAR(500) NULL"), ] print("\n[1/3] 添加缺失的列...") with engine.connect() as conn: for table, sql in alter_statements: try: conn.execute(text(sql)) conn.commit() print(f"✓ [{table}] 成功") except Exception as e: err = str(e) if "Duplicate column" in err or "Unknown column" in err: print(f"⊘ [{table}] 跳过 (列已存在或源列不存在)") else: print(f"⚠ [{table}] {err[:60]}") print("\n[2/3] 更新状态枚举值...") update_sqls = [ "UPDATE cursor_accounts SET status = 'available' WHERE status = 'active'", "UPDATE cursor_accounts SET status = 'exhausted' WHERE status = 'expired'", "UPDATE cursor_accounts SET status = 'pending' WHERE status IS NULL OR status = ''", "UPDATE activation_keys SET membership_type = 'auto' WHERE membership_type = 'free'", ] with engine.connect() as conn: for sql in update_sqls: try: conn.execute(text(sql)) conn.commit() print(f"✓ {sql[:50]}...") except Exception as e: print(f"⚠ 跳过: {str(e)[:50]}") print("\n[3/3] 初始化全局设置...") settings_sql = """ INSERT IGNORE INTO global_settings (`key`, value, value_type, description) VALUES ('key_max_devices', '2', 'int', '主密钥最大设备数'), ('auto_merge_enabled', 'true', 'bool', '是否启用同类型密钥自动合并'), ('auto_analyze_enabled', 'false', 'bool', '是否启用自动账号分析'), ('auto_switch_enabled', 'true', 'bool', '是否启用自动换号'), ('account_analyze_interval', '300', 'int', '账号分析间隔(秒)'), ('account_analyze_batch_size', '10', 'int', '每批分析账号数量'), ('auto_switch_threshold', '98', 'int', 'Auto池自动换号阈值'), ('pro_switch_threshold', '98', 'int', 'Pro池自动换号阈值'), ('max_switch_per_day', '50', 'int', '每日最大换号次数'), ('auto_daily_switches', '999', 'int', 'Auto密钥每日换号次数限制'), ('pro_quota_per_switch', '1', 'int', 'Pro密钥每次换号消耗积分') """ with engine.connect() as conn: try: conn.execute(text(settings_sql)) conn.commit() print("✓ 全局设置初始化完成") except Exception as e: print(f"⚠ {e}") print("\n" + "=" * 50) print("迁移完成! 请重启后端服务") print("=" * 50) if __name__ == "__main__": run_migration()