#!/usr/bin/env python3 """服务器端修复脚本:解决内存计数器重启归零导致的主键冲突""" import os, sys APP_PATH = "/opt/zhitu/app.py" if not os.path.exists(APP_PATH): print(f"错误:找不到 {APP_PATH}") sys.exit(1) # 备份 bak = APP_PATH + ".bak." + str(int(os.time())) os.system(f"cp {APP_PATH} {bak}") print(f"已备份: {bak}") with open(APP_PATH, "r", encoding="utf-8") as f: s = f.read() # 1. 删除内存计数器 s = s.replace( "_demand_id_counter = 0\n_task_id_counter = 0\n_danger_id_counter = 0", "# 计数器已从内存变量改为数据库查询,避免服务重启后主键冲突" ) # 2. 添加辅助函数 helper = '''def _next_demand_id(): """从数据库查询当前最大需求ID,生成下一个(避免内存计数器重启归零导致主键冲突)""" conn = get_db() row = conn.execute("SELECT id FROM demands WHERE id LIKE 'REQ-%' ORDER BY id DESC LIMIT 1").fetchone() conn.close() if row: try: num = int(row["id"].replace("REQ-", "")) except ValueError: num = 0 else: num = 0 return "REQ-" + str(num + 1).zfill(3) def _next_task_id(): """从数据库查询当前最大任务ID,生成下一个""" conn = get_db() row = conn.execute("SELECT id FROM tasks WHERE id LIKE '#%' ORDER BY id DESC LIMIT 1").fetchone() conn.close() if row: try: num = int(row["id"].replace("#", "")) except ValueError: num = 0 else: num = 0 return "#" + str(num + 1).zfill(3) ''' marker = "# ===== REST API: 物资需求(单兵APP) =====" if marker in s and "_next_demand_id" not in s: s = s.replace(marker, helper + marker) # 3. 修改 post_demand s = s.replace( " global _demand_id_counter\n data = request.get_json(force=True)\n _demand_id_counter += 1", " data = request.get_json(force=True)" ) s = s.replace( ' demand_id = "REQ-" + str(_demand_id_counter).zfill(3)', ' demand_id = _next_demand_id()' ) # 4. 修改 add_danger_zone s = s.replace( ''' global _danger_id_counter data = request.get_json(force=True) _danger_id_counter += 1 zone = { "id": _danger_id_counter,''', ''' data = request.get_json(force=True) zone = {''' ) s = s.replace( ''' conn.execute(''' INSERT INTO danger_zones (lat, lng, radius, description, created_at) VALUES (?, ?, ?, ?, ?) ''', (zone["lat"], zone["lng"], zone["radius"], zone["description"], zone["created_at"])) conn.commit() conn.close() return jsonify({"ok": True, "id": zone["id"]})''', ''' cur = conn.execute(''' INSERT INTO danger_zones (lat, lng, radius, description, created_at) VALUES (?, ?, ?, ?, ?) ''', (zone["lat"], zone["lng"], zone["radius"], zone["description"], zone["created_at"])) zone_id = cur.lastrowid conn.commit() conn.close() return jsonify({"ok": True, "id": zone_id})''' ) # 5. 修改 dispatch_task s = s.replace( ''' global _task_id_counter data = request.get_json(force=True) soldier_id = data.get("soldier_id", "unknown") _task_id_counter += 1''', ''' data = request.get_json(force=True) soldier_id = data.get("soldier_id", "unknown")''' ) s = s.replace( ''' "id": "#" + str(_task_id_counter).zfill(3),''', ''' "id": _next_task_id(),''' ) # 6. 修改 sos s = s.replace( ''' # 同时标记为危险区域 global _danger_id_counter _danger_id_counter += 1 conn.execute('''', ''' # 同时标记为危险区域 conn.execute('''' ) with open(APP_PATH, "w", encoding="utf-8") as f: f.write(s) # 语法检查 result = os.system(f"python3 -m py_compile {APP_PATH}") if result == 0: print("✅ 修复完成,语法检查通过") else: print("❌ 语法检查失败,已恢复备份") os.system(f"cp {bak} {APP_PATH}") sys.exit(1)