diff --git a/QUICKSTART.md b/QUICKSTART.md index 474e829..928fcf7 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -35,3 +35,5 @@ cp backend/.env.example backend/.env ## 下一步开发 参考 `开发计划.md` 继续第一阶段第2周任务 + +1. 定期检测还需要加入环路检测功能,并且将环路的状态记录到数据库中,在OLT界面上显示 diff --git a/backend/app/api/v1/import_data.py b/backend/app/api/v1/import_data.py index a1d755e..eb7abcd 100644 --- a/backend/app/api/v1/import_data.py +++ b/backend/app/api/v1/import_data.py @@ -12,7 +12,7 @@ router = APIRouter(prefix="/api/import", tags=["数据导入"]) @router.get("/template") -def download_template(_: dict = Depends(require_permission('device.import'))): +def download_template(): """下载导入数据模板""" wb = Workbook() ws = wb.active diff --git a/backend/app/api/v1/olt.py b/backend/app/api/v1/olt.py index 85f2896..1683bc3 100644 --- a/backend/app/api/v1/olt.py +++ b/backend/app/api/v1/olt.py @@ -170,6 +170,7 @@ async def import_devices( username=str(row['用户名']).strip(), password=str(row['密码']).strip(), slot_command=str(row['槽位命令']).strip() if '槽位命令' in df.columns and str(row['槽位命令']) != 'nan' else 'display onu slot', + region=str(row['区域']).strip() if '区域' in df.columns and str(row['区域']) != 'nan' else '城区', location=str(row['安装位置']).strip() if '安装位置' in df.columns and str(row['安装位置']) != 'nan' else '', description=str(row['描述']).strip() if '描述' in df.columns and str(row['描述']) != 'nan' else '', ) @@ -183,12 +184,13 @@ async def import_devices( @router.get("/template") -def download_template(_: dict = Depends(require_permission('olt.manage'))): +def download_template(): from fastapi.responses import FileResponse - return FileResponse( - path="/home/v6ole/pyproject/H3ConuMS2/backend/templates/OLT设备导入模板.xlsx", - filename="OLT设备导入模板.xlsx" - ) + import os + # __file__ is at /app/api/v1/olt.py → go up 4 levels to reach + base = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + path = os.path.join(base, "templates", "OLT设备导入模板.xlsx") + return FileResponse(path=path, filename="OLT设备导入模板.xlsx") @router.get("/duplicate-macs") diff --git a/backend/app/services/check_service.py b/backend/app/services/check_service.py index 8a89bf2..5ec7c8b 100644 --- a/backend/app/services/check_service.py +++ b/backend/app/services/check_service.py @@ -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}) diff --git a/backend/app/services/import_service.py b/backend/app/services/import_service.py index d2849f0..0f9e765 100644 --- a/backend/app/services/import_service.py +++ b/backend/app/services/import_service.py @@ -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位分组) diff --git a/backend/templates/OLT设备导入模板.xlsx b/backend/templates/OLT设备导入模板.xlsx index 740b2f6..9155f3f 100644 Binary files a/backend/templates/OLT设备导入模板.xlsx and b/backend/templates/OLT设备导入模板.xlsx differ diff --git a/docs/现场ONU故障排查指南.md b/docs/现场ONU故障排查指南.md new file mode 100644 index 0000000..d244330 --- /dev/null +++ b/docs/现场ONU故障排查指南.md @@ -0,0 +1,899 @@ +# H3ConuMS2 现场ONU故障排查指南 + +## 文档说明 + +**版本**: v1.0 +**适用对象**: 新入职维护人员 +**适用场景**: 用户报修处理、定期巡检发现问题 +**关联系统**: H3ConuMS2 OLT设备监控管理系统 +**最后更新**: 2026年4月8日 + +--- + +## 第一章:准备工作 + +### 1.1 工具准备清单 + +#### 必备工具 +1. **笔记本电脑** + - 安装SSH客户端(如PuTTY、SecureCRT) + - 安装H3C设备管理软件(如有) + - 确保能连接公司VPN或内网 + +2. **网络测试工具** + - 网线测试仪 + - 网络抓包工具(Wireshark) + - Ping工具 + +3. **光纤测试设备** + - 光功率计(带适配器) + - 红光笔(可视故障定位仪) + - 光纤清洁工具(清洁笔、酒精棉片) + - 备用光纤跳线(SC/LC接口) + +4. **维修工具** + - 十字/一字螺丝刀套装 + - 尖嘴钳、斜口钳 + - 剥线钳 + - 电工胶布、扎带 + - 防静电手环 + +5. **备用设备** + - 同型号ONU设备(至少1台) + - 电源适配器(12V/1A) + - 网线(Cat5e/Cat6,不同长度) + - 光纤跳线(SC/LC,不同长度) + +#### 软件准备 +1. **H3ConuMS2系统访问** + - 确保有系统登录权限 + - 熟悉设备查询界面 + - 了解历史状态查看功能 + +2. **文档资料** + - 本指南(打印版或电子版) + - ONU设备技术手册 + - OLT设备配置手册 + - 网络拓扑图 + +### 1.2 出发前检查 + +#### 信息收集 +1. **从H3ConuMS2系统获取信息** + ```bash + # 查询设备当前状态 + 设备名称: [从系统获取] + OLT位置: [从系统获取] + 最后在线时间: [从系统获取] + 历史故障记录: [从系统获取] + ``` + +2. **联系用户了解情况** + - 故障现象描述 + - 故障发生时间 + - 受影响范围(单用户/多用户) + - 是否尝试过重启 + +3. **确认现场信息** + - 具体地址和联系人 + - 设备安装位置 + - 现场环境(机房/用户端) + - 预计到达时间 + +#### 安全准备 +1. **个人防护** + - 穿戴工作服、安全鞋 + - 携带手电筒 + - 准备口罩、手套 + +2. **工作许可** + - 确认是否有进入权限 + - 是否需要用户陪同 + - 工作时间限制 + +### 1.3 故障预判 + +根据系统信息和用户描述,初步判断可能的问题: + +| 故障现象 | 可能原因 | 优先级 | +|---------|---------|--------| +| 完全无信号 | 电源故障、光纤断裂 | 高 | +| 信号弱/不稳定 | 光纤衰减大、连接器脏污 | 中 | +| 有光信号但无法上网 | 配置错误、网线问题 | 中 | +| 间歇性断线 | 设备过热、干扰 | 低 | + +--- + +## 第二章:现场排查流程 + +### 2.1 到达现场后的标准操作流程 + +#### 步骤1:现场环境评估 +1. **安全确认** + - 检查现场是否有安全隐患 + - 确认电源插座接地良好 + - 注意防静电措施 + +2. **设备定位** + - 找到故障ONU设备 + - 确认设备型号与系统记录一致 + - 检查设备安装位置是否合适 + +3. **环境检查** + - 温度是否过高(>40°C) + - 湿度是否合适(30%-70%) + - 通风是否良好 + - 是否有灰尘堆积 + +#### 步骤2:初步外观检查 +1. **电源检查** + - 电源指示灯状态 + - 电源适配器是否发热 + - 电源线连接是否牢固 + - 用万用表测量输出电压(应为12V±5%) + +2. **指示灯状态分析** + +| 指示灯 | 正常状态 | 故障状态 | 可能原因 | +|-------|---------|---------|---------| +| PWR | 常亮 | 不亮/闪烁 | 电源故障 | +| PON | 常亮 | 闪烁/不亮 | 光路问题 | +| LOS | 不亮 | 常亮/闪烁 | 光信号丢失 | +| LAN | 常亮/闪烁 | 不亮 | 网线/配置问题 | + +3. **物理连接检查** + - 光纤连接器是否插紧 + - 网线连接是否牢固 + - 所有接口是否有松动 + - 检查线缆是否有破损 + +#### 步骤3:光路测试 +1. **使用红光笔检查** + - 在OLT端发射红光 + - 在ONU端观察是否有红光 + - 确认光纤通路是否完整 + +2. **光功率测量** + - 连接光功率计到ONU接收端 + - 记录接收光功率 + - 参考标准值:-8dBm ~ -27dBm + + **光功率判断标准:** + - 优于-8dBm:光功率过强,可能损坏设备 + - -8dBm ~ -27dBm:正常范围 + - -27dBm ~ -30dBm:临界值,可能不稳定 + - 低于-30dBm:光功率不足 + +3. **光纤清洁** + - 使用专用清洁笔清洁光纤端面 + - 检查连接器是否有划伤 + - 重新插拔光纤连接器 + +#### 步骤4:网络连接测试 +1. **本地连接测试** + - 笔记本电脑直连ONU LAN口 + - 设置静态IP(如192.168.1.100) + - Ping ONU管理地址(通常192.168.1.1) + +2. **上网测试** + - 如果能够Ping通ONU,尝试访问网页 + - 测试DNS解析(nslookup www.baidu.com) + - 测试下载速度 + +3. **抓包分析(如需要)** + - 使用Wireshark抓取网络包 + - 分析DHCP、PPPoE等协议交互 + - 查找异常流量 + +#### 步骤5:设备诊断 +1. **登录ONU管理界面** + - 默认地址:192.168.1.1 + - 用户名/密码:admin/admin 或 查看设备标签 + - 检查设备状态信息 + +2. **查看关键信息** + - 光模块信息(发射/接收功率) + - 温度信息 + - 运行时间 + - 错误日志 + +3. **配置检查** + - VLAN配置是否正确 + - 业务VLAN是否匹配 + - MAC地址学习情况 + +#### 步骤6:OLT端检查 +1. **通过H3ConuMS2系统检查** + - 登录系统查看设备状态 + - 检查OLT端口状态 + - 查看ONU注册状态 + +2. **SSH登录OLT(如需要)** + ```bash + # 连接OLT + ssh admin@olt_ip + + # 查看ONU状态 + display onu slot X/X + + # 查看端口信息 + display interface gigabitethernet X/X/X + + # 查看告警信息 + display alarm active + ``` + +3. **OLT端诊断命令** + - `display ont info` - 查看ONU信息 + - `display ont optical-info` - 查看光信息 + - `display ont version` - 查看版本信息 + - `display ont statistic` - 查看统计信息 + +### 2.2 故障决策树 + +```mermaid +graph TD + A[开始排查] --> B{电源指示灯亮?} + B -->|否| C[检查电源] + B -->|是| D{PON指示灯状态?} + + D -->|不亮| E[检查光路] + D -->|闪烁| F[检查注册状态] + D -->|常亮| G{LAN指示灯状态?} + + G -->|不亮| H[检查网线/配置] + G -->|正常| I[测试网络连接] + + C --> J[更换电源适配器] + J --> K{问题解决?} + K -->|是| L[记录并结束] + K -->|否| M[更换ONU设备] + + E --> N[测试光功率] + N --> O{光功率正常?} + O -->|否| P[检查光纤/清洁连接器] + O -->|是| Q[检查OLT配置] + + F --> R[检查ONU注册] + R --> S{注册成功?} + S -->|否| T[检查SN/MAC绑定] + S -->|是| U[检查业务配置] + + H --> V[更换网线] + V --> W{问题解决?} + W -->|是| X[记录并结束] + W -->|否| Y[检查交换机配置] + + I --> Z[Ping测试] + Z --> AA{能Ping通?} + AA -->|否| BB[检查IP配置] + AA -->|是| CC[测试上网] + + CC --> DD{能上网?} + DD -->|否| EE[检查PPPoE/DHCP] + DD -->|是| FF[故障排除完成] +``` + +--- + +## 第三章:常见故障处理 + +### 3.1 电源类故障 + +#### 故障现象 +- 所有指示灯不亮 +- 设备无任何反应 +- 电源适配器发热异常 + +#### 处理步骤 +1. **检查电源插座** + - 使用其他设备测试插座 + - 检查插座电压(220V±10%) + +2. **检查电源适配器** + - 测量输出电压(应为12V) + - 检查输出电流(应≥1A) + - 观察指示灯状态 + +3. **检查设备电源接口** + - 检查接口是否松动 + - 检查内部保险丝 + - 检查电源电路 + +#### 解决方案 +1. **更换电源适配器** +2. **更换电源线** +3. **更换ONU设备** + +### 3.2 光路类故障 + +#### 故障现象 +- PON指示灯不亮或闪烁 +- LOS指示灯亮 +- 光功率异常 + +#### 处理步骤 +1. **检查光纤连接** + - 确认光纤类型(单模/多模) + - 检查连接器类型(SC/LC) + - 清洁光纤端面 + +2. **测量光功率** + - 在ONU端测量接收功率 + - 在分光器端测量输出功率 + - 计算链路衰减 + +3. **检查光纤质量** + - 检查光纤是否有弯折 + - 检查接头是否有损伤 + - 检查光纤长度是否超限 + +#### 解决方案 +1. **重新制作光纤接头** +2. **更换光纤跳线** +3. **调整光功率(增加衰减器)** +4. **重新熔接光纤** + +### 3.3 注册类故障 + +#### 故障现象 +- PON指示灯闪烁 +- OLT无法发现ONU +- 注册超时 + +#### 处理步骤 +1. **检查SN/MAC地址** + - 核对ONU标签上的SN + - 检查OLT端SN绑定 + - 检查MAC地址过滤 + +2. **检查OLT配置** + - 检查端口使能状态 + - 检查ONU模板 + - 检查带宽配置 + +3. **检查距离限制** + - 确认光纤长度 + - 检查光功率预算 + - 确认分光比 + +#### 解决方案 +1. **重新配置SN/MAC** +2. **重启ONU设备** +3. **重置ONU到出厂设置** +4. **修改OLT配置** + +### 3.4 业务类故障 + +#### 故障现象 +- PON灯常亮但无法上网 +- 能获取IP但无法访问外网 +- 网速慢或不稳定 + +#### 处理步骤 +1. **检查VLAN配置** + - 检查业务VLAN ID + - 检查VLAN透传 + - 检查优先级标记 + +2. **检查IP配置** + - 检查DHCP获取情况 + - 检查PPPoE拨号 + - 检查静态IP配置 + +3. **检查路由配置** + - 检查默认网关 + - 检查DNS服务器 + - 检查路由表 + +#### 解决方案 +1. **重新配置VLAN** +2. **重启网络服务** +3. **更新设备固件** +4. **优化网络配置** + +### 3.5 性能类故障 + +#### 故障现象 +- 网速达不到标称值 +- 延迟高、抖动大 +- 频繁掉线 + +#### 处理步骤 +1. **进行网络测试** + - 测试上下行带宽 + - 测试网络延迟 + - 测试丢包率 + +2. **检查设备负载** + - 检查CPU使用率 + - 检查内存使用率 + - 检查温度状态 + +3. **检查干扰因素** + - 检查同频干扰 + - 检查电源干扰 + - 检查环境干扰 + +#### 解决方案 +1. **优化设备位置** +2. **更换更高性能设备** +3. **调整信道/频率** +4. **增加散热措施** + +--- + +## 第四章:记录与报告 + +### 4.1 故障记录规范 + +#### 基本信息 +```yaml +故障单号: [系统生成] +报告人: [维护人员姓名] +报告时间: [YYYY-MM-DD HH:MM] +故障地点: [详细地址] +联系人: [用户姓名电话] +``` + +#### 故障信息 +```yaml +设备信息: + - 设备型号: [H3C XXX] + - 设备SN: [XXXXXXXX] + - MAC地址: [XX:XX:XX:XX:XX:XX] + - 安装日期: [YYYY-MM-DD] + +故障现象: + - 用户描述: [用户原话] + - 实际现象: [现场观察] + - 影响范围: [单用户/多用户] + +处理过程: + - 到达时间: [HH:MM] + - 开始处理: [HH:MM] + - 解决时间: [HH:MM] + - 总耗时: [X小时X分钟] +``` + +#### 技术数据 +```yaml +测试数据: + - 光功率: [接收: -XX dBm, 发射: -XX dBm] + - 网络测试: [下载: XX Mbps, 上传: XX Mbps] + - 延迟测试: [平均: XX ms, 最大: XX ms] + - 丢包率: [X%] + +更换部件: + - 部件名称: [如: 电源适配器] + - 部件型号: [如: H3C-12V-1A] + - 更换原因: [如: 输出电压不稳定] + - 旧件SN: [XXXXXXXX] + - 新件SN: [XXXXXXXX] +``` + +### 4.2 H3ConuMS2系统更新 + +#### 设备状态更新 +1. **登录系统** + - 进入设备管理界面 + - 找到故障设备 + +2. **更新信息** + - 更新设备状态(在线/离线) + - 更新最后检查时间 + - 更新维护记录 + +3. **添加备注** + - 描述故障现象 + - 记录处理过程 + - 添加技术数据 + +#### 生成报告 +1. **导出数据** + - 导出设备历史状态 + - 导出故障处理记录 + - 导出性能测试数据 + +2. **生成报告** + - 使用系统报告功能 + - 选择报告模板 + - 自定义报告内容 + +3. **提交报告** + - 提交给上级主管 + - 发送给用户确认 + - 归档到知识库 + +### 4.3 知识积累 + +#### 故障案例库 +1. **记录典型案例** + - 罕见故障现象 + - 复杂处理过程 + - 创新解决方案 + +2. **分析故障原因** + - 根本原因分析 + - 预防措施建议 + - 改进方案设计 + +3. **分享经验** + - 团队内部分享 + - 编写技术文档 + - 培训新员工 + +#### 持续改进 +1. **统计分析** + - 统计故障类型分布 + - 分析故障发生频率 + - 计算平均修复时间 + +2. **优化流程** + - 根据数据优化排查步骤 + - 改进工具配置 + - 更新技术标准 + +3. **预防维护** + - 制定定期检查计划 + - 预测性维护 + - 设备生命周期管理 + +--- + +## 第五章:预防措施 + +### 5.1 定期维护计划 + +#### 月度检查 +1. **设备清洁** + - 清洁设备表面灰尘 + - 清洁散热孔 + - 检查风扇运转 + +2. **连接检查** + - 检查所有连接器 + - 检查线缆状态 + - 检查标签完整性 + +3. **性能测试** + - 测试网络速度 + - 测试光功率 + - 测试设备温度 + +#### 季度检查 +1. **全面诊断** + - 完整的功能测试 + - 详细的性能测试 + - 安全漏洞扫描 + +2. **配置备份** + - 备份设备配置 + - 备份系统数据 + - 验证备份完整性 + +3. **固件更新** + - 检查固件版本 + - 评估更新必要性 + - 制定更新计划 + +#### 年度检查 +1. **设备评估** + - 评估设备性能 + - 预测剩余寿命 + - 制定更换计划 + +2. **环境评估** + - 评估安装环境 + - 检查配套设施 + - 提出改进建议 + +3. **文档更新** + - 更新技术文档 + - 更新操作手册 + - 更新维护记录 + +### 5.2 设备安装规范 + +#### 环境要求 +1. **温度控制** + - 工作温度:0°C ~ 40°C + - 存储温度:-40°C ~ 70°C + - 避免阳光直射 + +2. **湿度控制** + - 工作湿度:10% ~ 90% RH + - 避免冷凝 + - 保持通风 + +3. **电源要求** + - 稳定电压:220V ±10% + - 可靠接地 + - 防雷保护 + +#### 安装规范 +1. **设备固定** + - 使用合适支架 + - 保持水平安装 + - 预留散热空间 + +2. **线缆管理** + - 分类绑扎线缆 + - 预留适当余量 + - 避免弯折过度 + +3. **标签标识** + - 清晰设备标签 + - 完整线缆标签 + - 准确位置标签 + +### 5.3 备件管理 + +#### 备件库存 +1. **常用备件** + - ONU设备:按设备总数10%储备 + - 电源适配器:按设备总数15%储备 + - 光纤跳线:按设备总数20%储备 + - 网线:按需储备 + +2. **关键备件** + - 光模块 + - 分光器 + - 交换机 + +3. **工具备件** + - 测试工具 + - 维修工具 + - 安全装备 + +#### 库存管理 +1. **入库管理** + - 记录备件信息 + - 测试备件功能 + - 分类存放 + +2. **出库管理** + - 记录领用信息 + - 跟踪使用情况 + - 及时补充库存 + +3. **定期检查** + - 检查备件状态 + - 测试备件功能 + - 更新库存记录 + +### 5.4 培训计划 + +#### 新员工培训 +1. **基础培训(第1周)** + - 公司制度介绍 + - 安全规范培训 + - 工具使用培训 + +2. **技术培训(第2-3周)** + - 网络基础知识 + - 光纤通信原理 + - 设备操作培训 + +3. **实操培训(第4周)** + - 跟随老员工现场学习 + - 模拟故障处理 + - 独立完成简单任务 + +#### 在职培训 +1. **月度培训** + - 新技术介绍 + - 案例分享 + - 经验交流 + +2. **季度培训** + - 技能考核 + - 应急演练 + - 安全培训 + +3. **年度培训** + - 技术更新培训 + - 认证考试 + - 职业发展规划 + +--- + +## 第六章:应急处理 + +### 6.1 紧急情况处理 + +#### 重大故障 +1. **大面积断网** + - 立即上报主管 + - 启动应急预案 + - 协调多方资源 + +2. **设备损坏** + - 评估影响范围 + - 准备替代方案 + - 紧急采购设备 + +3. **安全事故** + - 确保人员安全 + - 保护现场证据 + - 按规定报告 + +#### 沟通协调 +1. **内部沟通** + - 建立应急联络群 + - 定期更新进展 + - 协调技术支持 + +2. **用户沟通** + - 及时通知用户 + - 说明处理进展 + - 提供临时方案 + +3. **供应商沟通** + - 联系技术支持 + - 协调备件供应 + - 请求现场支持 + +### 6.2 应急预案 + +#### 预案制定 +1. **风险评估** + - 识别潜在风险 + - 评估影响程度 + - 制定应对措施 + +2. **资源准备** + - 准备应急设备 + - 准备应急人员 + - 准备应急资金 + +3. **流程设计** + - 设计处理流程 + - 明确责任分工 + - 设定时间要求 + +#### 预案演练 +1. **桌面演练** + - 模拟故障场景 + - 讨论处理方案 + - 优化处理流程 + +2. **实战演练** + - 模拟真实故障 + - 实际处理操作 + - 评估处理效果 + +3. **演练总结** + - 分析演练过程 + - 发现存在问题 + - 提出改进建议 + +--- + +## 第七章:附录 + +### 7.1 常用命令参考 + +#### OLT常用命令 +```bash +# 查看ONU状态 +display onu slot X/X + +# 查看光信息 +display ont optical-info X/X/X X + +# 查看版本信息 +display ont version X/X/X X + +# 查看统计信息 +display ont statistic X/X/X X + +# 重启ONU +ont reboot X/X/X X + +# 查看告警 +display alarm active + +# 查看端口状态 +display interface gigabitethernet X/X/X +``` + +#### ONU管理命令 +```bash +# 登录ONU(Telnet/SSH) +telnet 192.168.1.1 + +# 查看系统信息 +show system + +# 查看接口状态 +show interface + +# 查看光模块信息 +show optical-module + +# 查看日志 +show log + +# 重启设备 +reboot + +# 恢复出厂设置 +factory-reset +``` + +### 7.2 技术参数参考 + +#### 光功率标准 +| 项目 | 标准值 | 警告值 | 危险值 | +|------|--------|--------|--------| +| 接收光功率 | -8 ~ -27 dBm | -27 ~ -30 dBm | < -30 dBm | +| 发射光功率 | 0 ~ +5 dBm | +5 ~ +7 dBm | > +7 dBm | +| 链路衰减 | < 25 dB | 25 ~ 28 dB | > 28 dB | + +#### 温度标准 +| 项目 | 正常范围 | 警告范围 | 危险范围 | +|------|----------|----------|----------| +| 工作温度 | 0°C ~ 40°C | 40°C ~ 50°C | > 50°C | +| 存储温度 | -40°C ~ 70°C | - | - | +| 表面温度 | < 60°C | 60°C ~ 70°C | > 70°C | + +### 7.3 联系信息 + +#### 内部联系人 +| 部门 | 联系人 | 电话 | 职责 | +|------|--------|------|------| +| 技术支持 | 张三 | 138XXXXXXX | 技术指导 | +| 备件管理 | 李四 | 139XXXXXXX | 备件供应 | +| 项目管理 | 王五 | 137XXXXXXX | 项目协调 | + +#### 供应商联系人 +| 供应商 | 产品 | 联系人 | 电话 | 支持时间 | +|--------|------|--------|------|----------| +| H3C | OLT设备 | 技术支持 | 400-XXXX | 7x24 | +| 华为 | ONU设备 | 技术支持 | 400-XXXX | 7x24 | +| 中兴 | 光模块 | 技术支持 | 400-XXXX | 工作日 | + +### 7.4 模板下载 + +#### 故障报告模板 +[下载链接:故障报告模板.docx] + +#### 维护记录模板 +[下载链接:维护记录模板.xlsx] + +#### 备件清单模板 +[下载链接:备件清单模板.xlsx] + +--- + +## 第八章:更新记录 + +| 版本 | 更新日期 | 更新内容 | 更新人 | +|------|----------|----------|--------| +| v1.0 | 2026-04-08 | 初始版本创建 | 系统团队 | +| v1.1 | - | 计划更新:添加更多案例 | - | +| v1.2 | - | 计划更新:优化流程图 | - | + +--- + +## 使用说明 + +1. **新员工必读**:入职后一周内完成学习 +2. **现场携带**:建议打印关键章节随身携带 +3. **定期复习**:每季度复习一次 +4. **反馈建议**:发现不足及时反馈 +5. **持续改进**:根据实际情况更新内容 + +## 版权声明 + +本指南版权归H3ConuMS2项目组所有,未经许可不得外传。 + +--- + +**祝您工作顺利,排查无忧!** + +如有任何问题或建议,请联系: +- 邮箱:support@h3conums2.com +- 电话:400-XXX-XXXX +- 内部通讯:企业微信/钉钉群 \ No newline at end of file diff --git a/frontend/src/views/DeviceList.vue b/frontend/src/views/DeviceList.vue index f92e54c..25b309b 100644 --- a/frontend/src/views/DeviceList.vue +++ b/frontend/src/views/DeviceList.vue @@ -10,8 +10,8 @@ 清空状态 - - {{ refreshing ? '更新中…' : '全部更新' }} + + {{ refreshing ? '更新中…' : refreshCooldown > 0 ? `冷却 ${refreshCooldown}s` : '全部更新' }} 数据导入 @@ -203,7 +203,7 @@ v-if="can('device.edit')" class="card-action-btn card-action-btn--primary" @click.stop="openProvisionFromCard(device)" - :disabled="device.status !== 'online' || !device.port_id" + :disabled="device.status !== 'online' || (!device.port_id && !(device.slot_number && device.port_number))" > @@ -347,7 +347,7 @@ 更新 更换 编辑 - + 业务下发 关闭 @@ -480,7 +480,7 @@ save force />
- 第 {{ f.row }} 行:{{ f.reason }} + 第 {{ f.row }} 行:{{ f.reason }}
@@ -521,6 +521,8 @@ const provisionVisible = ref(false) const provisionLoading = ref(false) const provisionResult = ref(null) const refreshing = ref(false) +const refreshCooldown = ref(0) +let cooldownTimer = null const clearing = ref(false) const editVisible = ref(false) @@ -636,6 +638,7 @@ const clearStatus = async () => { } const refreshAllStatus = async () => { + if (refreshCooldown.value > 0) return refreshing.value = true checkResultVisible.value = true checkInProgress.value = true @@ -654,6 +657,15 @@ const refreshAllStatus = async () => { } finally { checkInProgress.value = false refreshing.value = false + clearInterval(cooldownTimer) + refreshCooldown.value = 60 + cooldownTimer = setInterval(() => { + refreshCooldown.value-- + if (refreshCooldown.value <= 0) { + clearInterval(cooldownTimer) + refreshCooldown.value = 0 + } + }, 1000) } } @@ -691,6 +703,10 @@ const doRefreshDevice = async () => { selectedDevice.value.status = data.status selectedDevice.value.distance_m = data.distance_m if (data.model) selectedDevice.value.model = data.model + if (data.port_id !== undefined) selectedDevice.value.port_id = data.port_id + if (data.slot_number !== undefined) selectedDevice.value.slot_number = data.slot_number + if (data.port_number !== undefined) selectedDevice.value.port_number = data.port_number + if (data.olt_location !== undefined) selectedDevice.value.olt_location = data.olt_location ElMessage.success(`更新完成:${data.status === 'online' ? '在线' : '离线'}${data.distance_m ? ',距离 ' + formatDistance(data.distance_m) : ''}`) loadDevices() } catch (error) { diff --git a/frontend/src/views/OltManage.vue b/frontend/src/views/OltManage.vue index 05d88ed..aec78cf 100644 --- a/frontend/src/views/OltManage.vue +++ b/frontend/src/views/OltManage.vue @@ -454,6 +454,7 @@ @@ -533,6 +534,7 @@ const scanResult = ref({ total: 0, new: 0, devices: [], duplicates: [] }) const dupList = ref([]) const duplicateCount = ref(0) const clearingPort = ref('') +const batchClearing = ref(false) const newDevList = ref([]) const newDeviceCount = ref(0) const newDevVisible = ref(false) @@ -766,6 +768,56 @@ const deleteDupRecord = async (id) => { } } +const batchClearAll = async () => { + const total = dupList.value.length + if (total === 0) return + try { + await ElMessageBox.confirm( + `将对 ${total} 条重复 MAC 记录的所有离线端口执行 SSH 清除,然后自动忽略全部记录。此操作不可撤销,确认继续?`, + '批量清除确认', + { type: 'warning', confirmButtonText: '确认清除', confirmButtonClass: 'el-button--danger' } + ) + } catch { + return + } + batchClearing.value = true + + // 按 olt_id 分组 + const groups = {} + for (const row of dupList.value) { + const key = row.olt_id ?? '__unknown__' + if (!groups[key]) groups[key] = [] + groups[key].push(row) + } + + let cleared = 0, failed = 0 + + // 每个 OLT 一个并发任务,组内串行处理完所有重复 MAC 再结束 + await Promise.all( + Object.values(groups).map(async (rows) => { + for (const row of rows) { + const offlinePorts = (row.ports || []).filter(p => p.status !== 'online') + for (const p of offlinePorts) { + try { + await request.post(`/olt/duplicate-macs/${row.id}/clear-port`, { port_id: p.port_id }) + cleared++ + } catch { + failed++ + } + } + try { + await request.delete(`/olt/duplicate-macs/${row.id}`) + } catch {} + } + }) + ) + + dupList.value = [] + duplicateCount.value = 0 + batchClearing.value = false + ElMessage.success(`批量清除完成:清除 ${cleared} 个端口${failed ? `,${failed} 个失败` : ''},已忽略全部 ${total} 条记录`) +} + const fetchNewDeviceCount = async () => { try { const { data } = await request.get('/olt/new-devices')