"""迁移脚本:将 strategic_maps.dimensions JSON 中的目标同步到 map_objectives 表""" import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) from app.database import get_engine from sqlalchemy import text import json import logging logging.basicConfig(level=logging.INFO, format="%(message)s") logger = logging.getLogger("migrate_map_objectives") def sync_map_to_objectives(conn, map_id: int, dims: list) -> int: """将单个地图的 dimensions 同步到 map_objectives 表,返回同步的目标数""" # 删除该地图的旧目标 conn.execute( text("DELETE FROM map_objectives WHERE map_id = :mid"), {"mid": map_id}, ) count = 0 for dim in dims: dim_key = dim.get("key", "") for idx, obj in enumerate(dim.get("objectives", [])): name = obj.get("name", "").strip() if not name: continue conn.execute( text("""INSERT INTO map_objectives (map_id, dimension_key, name, description, icon, sort_order) VALUES (:mid, :dk, :name, :desc, :icon, :sort)"""), { "mid": map_id, "dk": dim_key, "name": name, "desc": obj.get("description", ""), "icon": obj.get("icon", "target"), "sort": idx, }, ) count += 1 return count def migrate(): engine = get_engine() with engine.begin() as conn: # 查询所有战略地图 maps = conn.execute( text("SELECT id, title, dimensions FROM strategic_maps ORDER BY id") ).fetchall() total_maps = 0 total_objectives = 0 for mid, title, dims_json in maps: if not dims_json: continue dims = json.loads(dims_json) if isinstance(dims_json, str) else dims_json if not isinstance(dims, list): continue count = sync_map_to_objectives(conn, mid, dims) if count > 0: total_maps += 1 total_objectives += count logger.info(f" 地图[{mid}] {title}: 同步 {count} 个目标") logger.info(f"\n✅ 迁移完成: {total_maps} 个地图, {total_objectives} 个目标已同步") if __name__ == "__main__": logger.info("=== 开始迁移 map_objectives ===") migrate() logger.info("=== 完成 ===")