backend v2.1: 公告管理功能 + 系统重构
- 新增 Announcement 数据模型,支持公告的增删改查 - 后台管理新增"公告管理"Tab(创建/编辑/删除/启用禁用) - 客户端 /api/announcement 改为从数据库读取 - 账号服务重构,新增无感换号、自动分析等功能 - 新增后台任务调度器、数据库迁移脚本 - Schema/Service/Config 全面升级至 v2.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
112
backend/run_migration_v2.py
Normal file
112
backend/run_migration_v2.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
数据库迁移脚本 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()
|
||||
Reference in New Issue
Block a user