当自动爬取的时候前端没有传输设备绑定和iccid的关系,导致后端没有接收到,现在修改逻辑

This commit is contained in:
YueL1331
2026-01-15 14:06:38 +08:00
parent f043983d24
commit 9b7799b827

View File

@ -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_whitelistupdate 不会覆盖它,因为 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}")