当自动爬取的时候前端没有传输设备绑定和iccid的关系,导致后端没有接收到,现在修改逻辑
This commit is contained in:
@ -7,7 +7,9 @@ from sqlalchemy import desc, or_
|
||||
from extensions import db
|
||||
from models import Device, DeviceHistory, MaintenanceLog
|
||||
|
||||
# --- 尝试导入服务模块 ---
|
||||
# =========================================================
|
||||
# 模块动态导入 (防止循环引用或缺失报错)
|
||||
# =========================================================
|
||||
try:
|
||||
from services.core import execute_monitor_task
|
||||
except ImportError:
|
||||
@ -28,6 +30,7 @@ api_bp = Blueprint('api', __name__, url_prefix='/api')
|
||||
def calculate_offset(latest_time_str):
|
||||
"""
|
||||
计算时间滞后天数
|
||||
用于前端展示设备数据是否过时
|
||||
"""
|
||||
if not latest_time_str or latest_time_str == "N/A":
|
||||
return "从未同步"
|
||||
@ -44,6 +47,7 @@ def calculate_offset(latest_time_str):
|
||||
def check_data_quality(content_data, source_type, data_time_str=None):
|
||||
"""
|
||||
数据质量分析算法 (融合版:旧版核心规则 + 新版夜间/IoT过滤)
|
||||
用于判断设备状态颜色 (绿色ok/黄色warning/红色error)
|
||||
"""
|
||||
if not content_data:
|
||||
return 'ok'
|
||||
@ -169,49 +173,61 @@ def check_data_quality(content_data, source_type, data_time_str=None):
|
||||
|
||||
def save_iot_cards_to_db(card_list):
|
||||
"""
|
||||
[新功能] IoT数据入库逻辑
|
||||
[核心修复] IoT数据入库逻辑 - 增量更新模式
|
||||
1. 只操作 source='iot_card' 的记录。
|
||||
2. 必须保留 is_whitelist 状态,防止被自动同步覆盖。
|
||||
2. 核心:使用 'update' 逻辑而不是 'replace' 逻辑。
|
||||
即使自动任务运行,也不会弄丢白名单 (is_whitelist) 或其他已存在的数据。
|
||||
"""
|
||||
if not card_list: return 0, None
|
||||
update_count = 0
|
||||
|
||||
try:
|
||||
for card in card_list:
|
||||
iccid = card.get('iccid')
|
||||
iccid = card.get('iccid') or card.get('card_id') # 兼容字段名
|
||||
if not iccid: continue
|
||||
|
||||
# 1. 查找是否存在
|
||||
# 1. 查找是否存在该 SIM 卡记录
|
||||
sim_record = Device.query.filter_by(name=iccid, source='iot_card').first()
|
||||
current_whitelist = False
|
||||
|
||||
# 初始化旧数据容器
|
||||
old_json = {}
|
||||
|
||||
if not sim_record:
|
||||
# 插入新数据
|
||||
# 插入新卡片
|
||||
sim_record = Device(name=iccid, source='iot_card', install_site="IoT库")
|
||||
db.session.add(sim_record)
|
||||
db.session.flush()
|
||||
db.session.flush() # 立即获取ID
|
||||
else:
|
||||
# 旧卡:读取并保留旧的白名单设置
|
||||
# 旧卡:尝试读取现有 JSON,确保不丢失之前的数据
|
||||
try:
|
||||
old_json = json.loads(sim_record.json_data)
|
||||
current_whitelist = old_json.get('is_whitelist', False)
|
||||
if sim_record.json_data:
|
||||
old_json = json.loads(sim_record.json_data)
|
||||
except:
|
||||
current_whitelist = False
|
||||
old_json = {}
|
||||
|
||||
# 2. 更新字段
|
||||
sim_record.status = str(card.get('cardStatus', ''))
|
||||
|
||||
card_data = {
|
||||
# 2. 准备需要更新的 API 数据 (只更新变动的字段)
|
||||
api_updates = {
|
||||
"iccid": iccid,
|
||||
"usedTraffic": str(card.get('usedTraffic') or '0'),
|
||||
"stopDate": card.get('stopDate', 'N/A'),
|
||||
"cardStatus": card.get('cardStatus'),
|
||||
"tag": card.get('tag', ''),
|
||||
"is_whitelist": current_whitelist # 写回保留的状态
|
||||
"tag": card.get('tag', '')
|
||||
}
|
||||
|
||||
sim_record.json_data = json.dumps(card_data, ensure_ascii=False)
|
||||
# 3. [关键步骤] 合并数据
|
||||
# 如果 old_json 里有 is_whitelist,update 不会覆盖它,因为 api_updates 里没有这个key
|
||||
old_json.update(api_updates)
|
||||
|
||||
# 4. 兜底保障:如果这是新卡,或者旧卡丢失了 whitelist 字段,默认设为 False
|
||||
if 'is_whitelist' not in old_json:
|
||||
old_json['is_whitelist'] = False
|
||||
|
||||
# 5. 更新数据库字段
|
||||
sim_record.status = str(card.get('cardStatus', ''))
|
||||
# 序列化并写回
|
||||
sim_record.json_data = json.dumps(old_json, ensure_ascii=False)
|
||||
sim_record.check_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
update_count += 1
|
||||
|
||||
return update_count, None
|
||||
@ -429,15 +445,19 @@ def run_monitor():
|
||||
device.latest_time = target_time
|
||||
device.check_time = current_time
|
||||
|
||||
# [新代码逻辑] 合并模式 (update),防止覆盖掉 bound_iccid
|
||||
# [关键逻辑] 合并模式 (update),防止覆盖掉 bound_iccid
|
||||
# 先读取数据库里已有的 json_data
|
||||
old_json = {}
|
||||
try:
|
||||
old_json = json.loads(device.json_data)
|
||||
if device.json_data:
|
||||
old_json = json.loads(device.json_data)
|
||||
except:
|
||||
pass
|
||||
old_json = {}
|
||||
|
||||
# 只有当 raw_json 是字典时才进行合并
|
||||
new_json = d_raw if isinstance(d_raw, dict) else item.get('raw_json', {})
|
||||
if isinstance(new_json, dict):
|
||||
# 使用 update 方法,这样 old_json 里存在的 bound_iccid 不会被删掉
|
||||
old_json.update(new_json)
|
||||
|
||||
device.json_data = json.dumps(old_json, ensure_ascii=False)
|
||||
@ -461,6 +481,7 @@ def run_monitor():
|
||||
# --- B. 执行 IoT 同步 (写入数据库) ---
|
||||
if sync_iot_data_service:
|
||||
iot_list = sync_iot_data_service()
|
||||
# 复用已修复的 save_iot_cards_to_db,确保不会丢失数据
|
||||
c, e = save_iot_cards_to_db(iot_list)
|
||||
if e:
|
||||
msg_list.append(f"IoT错: {e}")
|
||||
|
||||
Reference in New Issue
Block a user