feat(import): 添加区域字段支持和改进模板路径处理

- 在OLT设备导入功能中添加region字段支持,从Excel模板读取区域信息
- 修复模板文件路径问题,使用相对路径动态构建模板文件路径
- 更新导入服务中的验证错误格式,包含行号和MAC地址信息

feat(check): 增强设备检测服务的端口信息同步

- 在CheckService中添加端口和OLT归属信息的同步逻辑
- 改进设备状态检查时的端口信息更新策略,避免用None覆盖现有值
- 扩展返回数据结构,包含端口ID、槽位号、端口号和OLT位置信息

feat(frontend): 添加设备列表刷新冷却机制和端口验证

- 实现设备状态刷新的60秒冷却时间限制,防止频繁操作
- 改进业务下发按钮的启用条件,同时支持port_id或slot_number+port_number组合
- 优化导入结果显示,显示具体的MAC地址信息

feat(olt): 添加重复MAC记录批量清除功能

- 新增批量清除重复MAC记录的功能,支持按OLT分组处理
- 实现SSH端口清除和自动忽略的批量操作流程
- 添加批量操作的进度提示和错误处理机制
```
This commit is contained in:
2026-04-09 11:33:04 +08:00
parent dcb2435514
commit d222978ae4
9 changed files with 1016 additions and 15 deletions
+32 -2
View File
@@ -58,8 +58,17 @@ class CheckService:
else:
offline_count += 1
# 有值时同步端口和 OLT 归属(不用 None 覆盖现有值)
update_fields = {"olt_id": olt_id}
if onu_info.slot_number is not None:
update_fields["slot_number"] = onu_info.slot_number
if onu_info.port_number is not None:
update_fields["port_number"] = onu_info.port_number
if onu_info.port_id:
update_fields["port_id"] = onu_info.port_id
if onu_info.model and not onu_model:
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update({"model": onu_info.model})
update_fields["model"] = onu_info.model
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update(update_fields)
self.db.add(DeviceStatusHistory(
onu_device_id=onu_id,
@@ -116,6 +125,10 @@ class CheckService:
distance_m = parse_distance(info.distance_str)
if info.model and not device.model:
device.model = info.model
# 同步端口信息到数据库
device.slot_number = info.slot_number
device.port_number = info.port_number
device.port_id = info.port_id
self.db.add(DeviceStatusHistory(
onu_device_id=device.id,
@@ -125,7 +138,17 @@ class CheckService:
response_data=None,
))
self.db.commit()
return {"status": status, "distance_m": distance_m, "model": device.model}
olt_location = olt.location if olt else None
return {
"status": status,
"distance_m": distance_m,
"model": device.model,
"port_id": device.port_id,
"slot_number": device.slot_number,
"port_number": device.port_number,
"olt_location": olt_location,
}
finally:
ssh.close()
@@ -177,6 +200,13 @@ class CheckService:
onu_id = onu.id
else:
onu_id, onu_model = entry
# 同步端口和 OLT 归属(扫描结果以当前 OLT 为准)
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update({
"olt_id": olt_id,
"slot_number": onu_info.slot_number,
"port_number": onu_info.port_number,
"port_id": onu_info.port_id,
})
if onu_info.model and not onu_model:
self.db.query(ONUDevice).filter(ONUDevice.id == onu_id).update({"model": onu_info.model})
+2 -2
View File
@@ -53,7 +53,7 @@ class ImportService:
for idx, record in enumerate(records):
mac = record.get('mac_address', '').strip()
if not mac:
invalid.append({'record': record, 'error': f'{idx+2}行: MAC地址缺失'})
invalid.append({'row': idx + 2, 'mac': mac, 'reason': 'MAC地址缺失'})
continue
# 标准化MAC地址:统一使用横杠分隔小写格式
@@ -63,7 +63,7 @@ class ImportService:
# 验证基本格式:12个十六进制字符(可能有分隔符)
hex_chars = mac_clean.replace('-', '')
if len(hex_chars) != 12 or not all(c in '0123456789ABCDEF' for c in hex_chars):
invalid.append({'record': record, 'error': f'{idx+2}行: MAC地址格式错误 "{mac}"'})
invalid.append({'row': idx + 2, 'mac': mac, 'reason': f'MAC地址格式错误 "{mac}"'})
continue
# 转换为标准格式 34dc-99c8-56e0(小写4位分组)