Procházet zdrojové kódy

文件共享中心报表汇总功能及界面优化调整,多灾融合预警图表样式优化调整-提交

lxh před 2 dny
rodič
revize
982fdf2556

+ 0 - 0
docs/README.md


binární
docs/UI_Defect_Report_FullRetest.xlsx


+ 530 - 0
docs/_agent_alarm_gas.json

@@ -0,0 +1,530 @@
+[
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/common.api.ts",
+    "lines": "3-10,46",
+    "title": "bjlist 引用不存在的 Api.bjlist",
+    "severity": "致命",
+    "type": "undefined_api_ref",
+    "symptom": "瓦斯管道故障诊断轮询请求 url 为 undefined,列表/曲线无法加载",
+    "root_cause": "enum Api 无 bjlist 成员,但 bjlist() 仍使用 Api.bjlist",
+    "repro": "宝德矿打开瓦斯预警→管道故障诊断,抓包看请求 URL",
+    "fix_hint": "恢复 bjlist='/safety/ventanalyAlarmLog/list' 或改用 warningHistoryList 路径"
+  },
+  {
+    "module": "bundleSpyTable",
+    "file": "vent/bundleSpy/bundleSpyTable/index.vue",
+    "lines": "134-147",
+    "title": "色谱仪报表被硬编码 mock 覆盖真实 API",
+    "severity": "致命",
+    "type": "mock_override",
+    "symptom": "页面恒显示写死的 10月2日假报表,真实 queryReportData 不调用",
+    "root_cause": "getbundleSpyInfoList 被注释,改为本地写死 res",
+    "repro": "打开色谱仪报表分析,网络面板无真实报表请求仍能看到固定数据",
+    "fix_hint": "恢复 await getbundleSpyInfoList(...),删除硬编码 res"
+  },
+  {
+    "module": "workingFace",
+    "file": "vent/deviceManager/workingFace/workingFace.api.ts",
+    "lines": "18-21,79-90",
+    "title": "智能管控批量删除/导入导出误指向 /sys/user/*",
+    "severity": "致命",
+    "type": "wrong_endpoint",
+    "symptom": "批删打到用户批量删除接口,可能删错资源或失败;单删走 managesys 正确路径",
+    "root_cause": "deleteBatch/importExcel/exportXls 从用户模块拷贝未改",
+    "repro": "预警联动勾选多条批删,抓包确认 /sys/user/deleteBatch",
+    "fix_hint": "改为 /safety/ventanalyManageSystem/deleteBatch 及对应导入导出路径"
+  },
+  {
+    "module": "gasPumpMonitor",
+    "file": "vent/monitorManager/gasPumpMonitor/components/gasPumpHome.vue",
+    "lines": "159-178,355-375,329-333",
+    "title": "就地/远程与检修控制 paramcode 对调且入参分支不匹配",
+    "severity": "致命",
+    "type": "inverted_control_mapping",
+    "symptom": "点就地/远程下发 jxmsqh;点检修下发 ykjdqh;传 0 时 handlerType 不赋值仍弹密码框",
+    "root_cause": "changeCtr 写死 jxmsqh、changeMode 写死 ykjdqh;模板传 0/1,函数判 1/2",
+    "repro": "抽采泵站管控点就地/远程/检修开闭→确认密码→抓包 paramcode",
+    "fix_hint": "changeCtr→ykjdqh,changeMode→jxmsqh;统一 0/1 分支"
+  },
+  {
+    "module": "gasReportInspect",
+    "file": "vent/gas/gasReportInspect/index-time.vue",
+    "lines": "62-82",
+    "title": "空 records 时先访问 [0] 导致挂载崩溃",
+    "severity": "致命",
+    "type": "crash_on_mount",
+    "symptom": "无日报数据时 Cannot read properties of undefined,页面白屏",
+    "root_cause": "先读 tableList[0].id/content,后才判 length;JSON.parse 无空保护",
+    "repro": "瓦斯日报分析在 queryReportList 返回空 records 时进入页面",
+    "fix_hint": "先判空 return;JSON.parse 包 try/catch(index-type/index-lt 同改)"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "5",
+    "title": "返回按钮权限取反",
+    "severity": "严重",
+    "type": "inverted_permission",
+    "symptom": "有 gasWarn:return 权限看不到返回;无权限反而显示",
+    "root_cause": "v-if=\"!hasPermission(...)\";对照 deviceMonitorWarn 为正逻辑",
+    "repro": "分配 gasWarn:return 后对比返回按钮显隐",
+    "fix_hint": "改为 hasPermission;fire/dust/ventilate/device/waterLevel 同步"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/fireWarn.vue",
+    "lines": "4",
+    "title": "火灾预警返回按钮权限取反",
+    "severity": "严重",
+    "type": "inverted_permission",
+    "symptom": "有 fireWarn:return 看不到返回按钮",
+    "root_cause": "v-if=\"!hasPermission('fireWarn:return')\"",
+    "repro": "分配权限后打开火灾监测预警",
+    "fix_hint": "去掉取反"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/dustWarn.vue",
+    "lines": "6",
+    "title": "粉尘预警返回按钮权限取反",
+    "severity": "严重",
+    "type": "inverted_permission",
+    "symptom": "有 dustWarn:return 看不到返回",
+    "root_cause": "v-if=\"!hasPermission('dustWarn:return')\"",
+    "repro": "分配权限后打开粉尘监测预警",
+    "fix_hint": "改为正逻辑 hasPermission"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue",
+    "lines": "10",
+    "title": "通风预警返回按钮权限取反",
+    "severity": "严重",
+    "type": "inverted_permission",
+    "symptom": "有 ventilateWarn:return 看不到返回",
+    "root_cause": "v-if=\"!hasPermission('ventilateWarn:return')\"",
+    "repro": "分配权限后打开通风监测预警",
+    "fix_hint": "改为正逻辑"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "193",
+    "title": "甲烷显示运算符优先级错误",
+    "severity": "严重",
+    "type": "wrong_operator_precedence",
+    "symptom": "gasC 为空时显示 \"undefined%\" 而非 '--'",
+    "root_cause": "el.readData.gasC + '%' || '--' 中字符串恒 truthy",
+    "repro": "测点 gasC 缺失时看左侧甲烷值",
+    "fix_hint": "(gasC!=null&&gasC!=='') ? gasC+'%' : '--'"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "346-365",
+    "title": "宝德矿第三 Tab 映射到瓦斯参数而非预警指标",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "菜单第三项「预警指标」点击却渲染 gasParamter(wscs)",
+    "root_cause": "getMonitorComponent(宝德)=[预警监测,故障诊断,预警指标];btnClick ind===2 固定 isShow='wscs'",
+    "repro": "sysOrgCode=sdmtjtbdmk 打开瓦斯预警点第三个类型按钮",
+    "fix_hint": "宝德 ind===2 → yjzb;布尔台 ind===2 保持 wscs"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "368-377",
+    "title": "宝德预警监测卡片误走故障诊断轮询",
+    "severity": "严重",
+    "type": "wrong_comparison",
+    "symptom": "预警监测点卡片会走 bjlist,菜单被故障设备覆盖",
+    "root_cause": "cardClick 仅按 isflag=='1' 分支,未看 isShow/activeIndex",
+    "repro": "宝德→预警监测→切换工作面卡片,观察是否请求 bjlist",
+    "fix_hint": "yjjc→getMonitor;gzzd→getMonitor1"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "311",
+    "title": "gasGlFaultDia 无防护 JSON.parse 可抛错",
+    "severity": "严重",
+    "type": "crash_on_mount",
+    "symptom": "缺/非法 gasGlFaultDia 时脚本异常,故障诊断页中断",
+    "root_cause": "JSON.parse(data.readData.gasGlFaultDia) 无空值与 try/catch",
+    "repro": "故障诊断选中无 gasGlFaultDia 的设备",
+    "fix_hint": "JSON.parse(x||'{}') 并 catch 给默认坐标"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/dustWarn.vue",
+    "lines": "131-143,166-176",
+    "title": "粉尘预测曲线每轮 push 不清理导致无限膨胀",
+    "severity": "严重",
+    "type": "timer_state_leak",
+    "symptom": "停留越久曲线点越多、内存升高",
+    "root_cause": "fillChartByIndex 每秒 echartYc.push;仅 topAreaClick 会清空",
+    "repro": "粉尘预警停留数分钟观察 echartYc 长度",
+    "fix_hint": "每次 fill 前重置 echartYc,或替换最新点"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue",
+    "lines": "239-250",
+    "title": "从巷道阻力分析切回通风监测后轮询不恢复",
+    "severity": "严重",
+    "type": "timer_not_restarted",
+    "symptom": "切回通风监测后顶部/测点停止自动刷新",
+    "root_cause": "btnClick(0) 只 clearNetTimer+getMenuList,未 getMonitor(true)",
+    "repro": "通风监测→巷道阻力→再点通风监测,等待>3s 看是否更新",
+    "fix_hint": "ind===0 时调用 getMonitor(true)"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/fireWarn.vue",
+    "lines": "74-83,148-157,173-185,215-217",
+    "title": "匿名 setTimeout 未清理且 getMonitor 不先 clear",
+    "severity": "严重",
+    "type": "timer_leak",
+    "symptom": "快速切换/离开后仍请求 sysTypeWarn;可能双轮询",
+    "root_cause": "cardClick/reset 的 setTimeout 无句柄;getMonitor 赋值前不清旧 timer",
+    "repro": "火灾预警连点内因/外因后返回首页,抓包仍见请求",
+    "fix_hint": "保存 delay timer 并在 unmount clear;getMonitor 开头 clearPollTimer"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/common/external-threec.vue",
+    "lines": "118-124",
+    "title": "温度传感器列表误绑 fireval",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "外因火灾温度卡片显示火焰字段/空值",
+    "root_cause": "temperature.map 使用 readData.fireval;mainWell 正确用 temperature",
+    "repro": "外因火灾 temperature 有值、fireval 空时看温度卡",
+    "fix_hint": "改为 el.readData.temperature(fourc:147-153 同步)"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/common/external-fourc.vue",
+    "lines": "147-153",
+    "title": "四参外因温度误绑 fireval",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "温度监测显示错误/空",
+    "root_cause": "与 threec 相同拷贝错误 val: el.readData.fireval",
+    "repro": "打开外因四参温度列表",
+    "fix_hint": "改为 temperature"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/alarmHistoryTable.vue",
+    "lines": "166-167",
+    "title": "未传 deviceType 时 strtype 变成 \"undefined*\"",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "设备预警报警历史过滤错误,列表空或错数据",
+    "root_cause": "beforeFetch: props.deviceType + '*';deviceWarn.vue:43 未传 deviceType",
+    "repro": "设备监测预警→报警历史,检查请求 strtype",
+    "fix_hint": "传入正确 deviceType,或空时不拼 strtype"
+  },
+  {
+    "module": "gasAssessment",
+    "file": "vent/gas/gasAssessment/index.vue",
+    "lines": "43",
+    "title": "进入抽采单元页未传入 unitId",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "侧栏 list({ids}) 为空,实时数据无法对应选中单元",
+    "root_cause": "<gasUnit/> 未绑定 :unitId=\"activeUnitId\"",
+    "repro": "达标评判点选单元后看 list 请求 ids",
+    "fix_hint": "<gasUnit :unitId=\"activeUnitId\" />"
+  },
+  {
+    "module": "gasAssessment",
+    "file": "vent/gas/gasAssessment/components/gasUnit.vue",
+    "lines": "27,55,73-75",
+    "title": "单元混量/纯量图表写死 mock",
+    "severity": "严重",
+    "type": "mock_override",
+    "symptom": "图表恒为本地假数据,真实监测不驱动",
+    "root_cause": "CustomChart 绑定 mockGasUnitHlData/mockGasUnitClData",
+    "repro": "打开抽采单元对比接口与图表数据源",
+    "fix_hint": "用接口历史数据替换 mock"
+  },
+  {
+    "module": "gasPumpMonitor",
+    "file": "vent/gas/gasPumpMonitor/index.vue",
+    "lines": "57-68",
+    "title": "井下泵模型切换后被无条件覆盖为地上泵",
+    "severity": "严重",
+    "type": "copy_paste_bug",
+    "symptom": "选中 pump_under* 仍加载地上 gasPump 三维",
+    "root_cause": "if/else 设类型后末尾又 setModelType('gasPump')",
+    "repro": "抽采泵站监测切到井下泵站设备",
+    "fix_hint": "删除末尾无条件 setModelType('gasPump')"
+  },
+  {
+    "module": "gasPumpMonitor",
+    "file": "vent/gas/gasPumpMonitor/components/monitorChart.vue",
+    "lines": "50-65",
+    "title": "setInterval 用 clearTimeout 清理导致泄漏",
+    "severity": "严重",
+    "type": "timer_not_cleared",
+    "symptom": "离开监测图表后仍每 2s 推数据",
+    "root_cause": "setInterval + onUnmounted clearTimeout",
+    "repro": "进入监测图表后切走,观察回调是否继续",
+    "fix_hint": "改为 clearInterval(timer)"
+  },
+  {
+    "module": "gasZk",
+    "file": "vent/gas/gasZk/index.vue",
+    "lines": "61-79",
+    "title": "setInterval 回调内再 startPolling 造成重叠轮询",
+    "severity": "严重",
+    "type": "timer_logic_bug",
+    "symptom": "慢网时 /drill/get/status 并发堆积",
+    "root_cause": "interval 不等待完成可再次触发;成功后又 stop+new interval",
+    "repro": "打开钻孔监测并限速网络观察并发",
+    "fix_hint": "改为 await 后 setTimeout 串行轮询"
+  },
+  {
+    "module": "gasInspect",
+    "file": "vent/gas/gasInspect/index.vue",
+    "lines": "66-75",
+    "title": "早/中/晚是否巡检真假分支都渲染「是」",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "未巡检也显示「是」,状态失真",
+    "root_cause": "text=='1' 与 v-else 内均写「是」",
+    "repro": "NFC 地点管理查看未巡检班次列",
+    "fix_hint": "else 显示「否」;对齐 Nonfc 字段约定"
+  },
+  {
+    "module": "gasInspectNonfc",
+    "file": "vent/gas/gasInspectNonfc/components/inspectEdit.vue",
+    "lines": "12-14,79-81,71-76",
+    "title": "区队下拉缺 value 且整对象重赋值打断响应式",
+    "severity": "严重",
+    "type": "nfc_nonfc_copy_paste",
+    "symptom": "提交可能把区队名当 id;二次编辑表单不刷新",
+    "root_cause": "option 无 :value;formStateEdit=Object.assign 重赋值丢失 reactive 绑定",
+    "repro": "Nonfc 编辑改区队提交看 payload;连续编辑两条",
+    "fix_hint": "补 :value=\"item.value\";Object.assign(formStateEdit, newV) 原地更新"
+  },
+  {
+    "module": "gasReport",
+    "file": "vent/gas/gasReport/index.vue",
+    "lines": "357-440",
+    "title": "审核/导出异常校验 else-if 导致任一气体合格即放行",
+    "severity": "严重",
+    "type": "inverted_validation_logic",
+    "symptom": "O2 超限但 CO 合格仍可审核通过;多行以最后一行结果为准",
+    "root_cause": "getTs 对 O2/CO/CO2/T/CH4 用 else-if;forEach return 不能结束函数",
+    "repro": "仅 O2 异常其余合格→点审核通过",
+    "fix_hint": "全部字段均在阈内才放行;任异常即 true"
+  },
+  {
+    "module": "gasReport",
+    "file": "vent/gas/gasReport/index.vue",
+    "lines": "271-274",
+    "title": "巡检图片 Blob 二次封装错误",
+    "severity": "严重",
+    "type": "wrong_blob_usage",
+    "symptom": "查看班次图片失败或 Failed to construct 'Blob'",
+    "root_cause": "gasServerImg 已是 blob,又 new Blob(res,...);构造需 Array",
+    "repro": "日报管理点夜/早/中班「查看」",
+    "fix_hint": "URL.createObjectURL(res) 或 new Blob([res],...)"
+  },
+  {
+    "module": "gasAnalysis",
+    "file": "vent/gas/gasAnalysis/index.vue",
+    "lines": "177-182,216-219",
+    "title": "列表成功后强制 pagination.current=1 导致分页失效",
+    "severity": "严重",
+    "type": "pagination_logic_bug",
+    "symptom": "翻到第 2 页后被打回第 1 页",
+    "root_cause": "gasReportLogLists 在有 records 时无条件 current=1",
+    "repro": "业务分析多页数据点第 2 页",
+    "fix_hint": "删除该赋值;仅查询/重置时置 1"
+  },
+  {
+    "module": "gasPipeNet",
+    "file": "vent/gas/gasPipeNet/index.vue",
+    "lines": "142-147",
+    "title": "管网阀门控制提交未调控制接口",
+    "severity": "严重",
+    "type": "undefined_api_call",
+    "symptom": "点确定只 toast 表单 JSON,阀门无动作",
+    "root_cause": "submitHandler 仅 message.success,无 deviceControl",
+    "repro": "管网管控→阀门控制→提交",
+    "fix_hint": "接入泵站同款控制 API"
+  },
+  {
+    "module": "bundleSpyTable",
+    "file": "vent/bundleSpy/bundleSpyTable/index.vue",
+    "lines": "237-241,386-390",
+    "title": "活鸡兔/寸草塔二矿图表 O₂闭内 误绑 CH₄ 数据",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "图例 O₂闭内 柱状与 CH₄闭内完全相同",
+    "root_cause": "name:'O₂闭内' 的 data 写成 ch4AveValues",
+    "repro": "对应矿打开色谱仪报表对比 o2_ave 与图",
+    "fix_hint": "改为 o2AveValues"
+  },
+  {
+    "module": "bundleSpy+bundleMonitor",
+    "file": "vent/bundleSpy/bundleSpyTable/index.vue; vent/bundle/bundleMonitorTable/index.vue",
+    "lines": "bundleSpy:108-109; bundle:101-102",
+    "title": "保德 sysOrgCode 大小写错误导致专用列永不命中",
+    "severity": "严重",
+    "type": "copy_paste_orgcode",
+    "symptom": "保德落到 default 列配置,专用字段不显示",
+    "root_cause": "写 case 'sdmtjtBdmk';全库其余为 'sdmtjtbdmk'",
+    "repro": "sysOrgCode=sdmtjtbdmk 打开色谱仪/束管日报",
+    "fix_hint": "统一改为 sdmtjtbdmk"
+  },
+  {
+    "module": "bundleMonitorTable",
+    "file": "vent/bundle/bundleMonitorTable/index.vue",
+    "lines": "103-104,453",
+    "title": "补连塔图表分支 orgCode 写成 sdmtjtBltmk",
+    "severity": "严重",
+    "type": "copy_paste_orgcode",
+    "symptom": "表格用 Bltcolumns 正确,柱状图落入 default",
+    "root_cause": "computedColumns 用 sdmtjtbltmk,getSeriesConfig 用 sdmtjtBltmk",
+    "repro": "sysOrgCode=sdmtjtbltmk 对比表头与图例",
+    "fix_hint": "图表 case 改为 sdmtjtbltmk"
+  },
+  {
+    "module": "bundleMonitorTable",
+    "file": "vent/bundle/bundleMonitorTable/bundle-table.data.ts",
+    "lines": "595-610",
+    "title": "保德束管 NO₂ 最小值 dataIndex 写成 no22_max",
+    "severity": "严重",
+    "type": "wrong_column_dataIndex",
+    "symptom": "NO₂最小值空白或错值",
+    "root_cause": "最小值 dataIndex:'no22_max',key/dataIndex 交叉贴错",
+    "repro": "保德束管日报对比 no2_min/no2_max 与三列",
+    "fix_hint": "最大值 no2_max;最小值 no2_min"
+  },
+  {
+    "module": "bundleMonitorTable",
+    "file": "vent/bundle/bundleMonitorTable/bundle-table.data.ts",
+    "lines": "1465-1472,1848-1855",
+    "title": "寸草塔一矿/哈拉沟 O₂最大值列绑定 o2_min",
+    "severity": "严重",
+    "type": "wrong_column_dataIndex",
+    "symptom": "标题最大值实际显示最小值",
+    "root_cause": "title:最大值 却 dataIndex:'o2_min'",
+    "repro": "对应矿打开束管日报对比 o2_max/o2_min",
+    "fix_hint": "改为 dataIndex:'o2_max'"
+  },
+  {
+    "module": "betKy",
+    "file": "vent/monitorManager/betKy/index.vue",
+    "lines": "112-146,148-154,258-262",
+    "title": "矿压轮询 push 不重置 + setTimeout/clearInterval 错用",
+    "severity": "严重",
+    "type": "timer_leak",
+    "symptom": "图表与行索引错位、内存增长;卸载后仍可能请求",
+    "root_cause": "chartData 每轮 push 不清空;timer=setTimeout 却 clearInterval;重启只置 null 不 clear",
+    "repro": "矿压页多次刷新后切行;快速进出页观察请求",
+    "fix_hint": "每轮 chartData=[];统一 clearTimeout 并先 clear 再置空"
+  },
+  {
+    "module": "dustMonitorTable",
+    "file": "vent/dust/dustMonitorTable/index.vue",
+    "lines": "317-320,510-513",
+    "title": "保德当日粉尘总体最大值误用 zcjqpj/hcjqpj",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "当日分析最大值恒 -Infinity 或字段映射失败",
+    "root_cause": "BdMaxValues 用 qc/hc;overallBdMaxValues 误用布尔台字段",
+    "repro": "保德粉尘报表切「当日粉尘情况分析」",
+    "fix_hint": "overallBdMaxValues 改为 qc/hc"
+  },
+  {
+    "module": "dustMonitorTable",
+    "file": "vent/dust/dustMonitorTable/index.vue",
+    "lines": "269-270,429-436,472-475",
+    "title": "哈拉沟分组键 ccdd 被最大值循环改写成 jcdd",
+    "severity": "严重",
+    "type": "logic_state",
+    "symptom": "工作场所下拉变成测点名,过滤错乱",
+    "root_cause": "分组 gzcs=ccdd,HlgMaxValues 更新时 gzcs=item.jcdd 覆盖",
+    "repro": "哈拉沟粉尘报表看工作场所下拉与过滤",
+    "fix_hint": "更新最大值时不要用 jcdd 覆盖 gzcs"
+  },
+  {
+    "module": "workingFace",
+    "file": "vent/deviceManager/workingFace/CustomNormalTable.vue",
+    "lines": "250-251",
+    "title": "批量删除未传 handleSuccess 回调",
+    "severity": "一般",
+    "type": "undefined_api_ref",
+    "symptom": "确认后 handleSuccess is not a function,列表不刷新",
+    "root_cause": "batchDeleteById(params, handleSuccess) 被调用为 batchDelete({ids})",
+    "repro": "预警联动批删点确认看控制台",
+    "fix_hint": "传入 reload 作为第二参"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/dustWarn.vue",
+    "lines": "255",
+    "title": "巷道温度单位错误依赖 humidity",
+    "severity": "一般",
+    "type": "wrong_field_binding",
+    "symptom": "有温度无湿度时单位空白",
+    "root_cause": "dw: el.humidity ? '(℃)' : ''",
+    "repro": "temperature 有值 humidity 空时看单位",
+    "fix_hint": "dw: el.temperature ? '(℃)' : ''"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue",
+    "lines": "207",
+    "title": "warnDes 为空时 indexOf 抛错中断菜单构建",
+    "severity": "一般",
+    "type": "crash_on_mount",
+    "symptom": "左侧菜单空白且轮询中断",
+    "root_cause": "el.warnDes.indexOf('预警') 无空保护",
+    "repro": "sysTypeWarn 返回 warnDes 缺失条目",
+    "fix_hint": "(el.warnDes||'').indexOf(...)"
+  },
+  {
+    "module": "alarmMonitor",
+    "file": "vent/monitorManager/alarmMonitor/warn/gasWarn.vue",
+    "lines": "189-190",
+    "title": "strinstallpos 为空时 indexOf 抛错",
+    "severity": "一般",
+    "type": "crash_on_mount",
+    "symptom": "getDetailList 抛错,监测卡片不更新",
+    "root_cause": "假定 strinstallpos 必为 string",
+    "repro": "gas 明细 strinstallpos 为 null",
+    "fix_hint": "const pos=el.strinstallpos||'' 再操作"
+  },
+  {
+    "module": "gasInspect",
+    "file": "vent/gas/gasInspect/index.vue",
+    "lines": "331-342",
+    "title": "筛「两次」误把 pagination.current 写成 2",
+    "severity": "一般",
+    "type": "copy_paste_bug",
+    "symptom": "筛选两次后分页状态错乱",
+    "root_cause": "case '2': pagination.current=2",
+    "repro": "地点管理→巡检次数筛选→两次",
+    "fix_hint": "两次也 current=1"
+  },
+  {
+    "module": "bundleMonitorTable",
+    "file": "vent/bundle/bundleMonitorTable/bundle-table.data.ts",
+    "lines": "412-435",
+    "title": "保德 N₂ 子列重复两个平均值缺少最小值",
+    "severity": "一般",
+    "type": "wrong_column_dataIndex",
+    "symptom": "N₂ 两列相同平均值;最小值无法展示",
+    "root_cause": "第二、三列均为 title:平均值 + n2_ave",
+    "repro": "保德束管日报看氮气表头",
+    "fix_hint": "中间列改为最小值/n2_min"
+  }
+]

+ 338 - 0
docs/_agent_fire_dust.json

@@ -0,0 +1,338 @@
+[
+  {
+    "module": "喷淋监控系统",
+    "file": "src/views/vent/monitorManager/sprayMonitor/index.vue",
+    "lines": "68-140",
+    "title": "多路控制按钮共用同一 paramcode/value",
+    "severity": "critical",
+    "type": "wrong_control_payload",
+    "symptom": "除急停外,补水阀/搅拌阀/组化泵/上料机/喷洒自动等按钮下发完全相同的指令,设备无法按按钮区分控制,存在误控风险",
+    "root_cause": "operations 全部使用 key='run_auto_sign',且多数 value='0';BasicMonitoring.deviceControl 仅按 key/value 下发",
+    "repro": "打开喷淋监控→输入密码点击“补水阀启停”与“喷洒自动”→抓包可见 paramcode/value 相同",
+    "fix_hint": "为每个操作配置独立 paramcode,并按启停状态设置正确 value(参考业务点表)"
+  },
+  {
+    "module": "喷淋监控系统",
+    "file": "src/components/vent/BasicMonitoring.vue",
+    "lines": "19,193-201",
+    "title": "操作列表 :key 冲突 + 空场景崩溃",
+    "severity": "high",
+    "type": "vue_key_collision/null_crash",
+    "symptom": "喷淋多个按钮共用 key 导致 DOM 复用异常;无场景数据时页面直接抛错白屏",
+    "root_cause": "v-for 使用 item.key 作唯一键但喷淋键重复;getSysDataSource 无空数组守卫直接取 options[0].id",
+    "repro": "1) 打开喷淋页观察按钮交互状态错乱;2) 后端返回空 records 时进入页面立即报错",
+    "fix_hint": "key 使用 label 或唯一 id;取首项前判断 records.length"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/index.vue",
+    "lines": "93-126",
+    "title": "空列表崩溃且 modalType 未随系统类型切换",
+    "severity": "high",
+    "type": "null_crash/stale_config",
+    "symptom": "无注氮系统时白屏;依赖 modalType 的矿端组件始终按 nitrogenUnderground 建模",
+    "root_cause": "options.value[0]['id'] 无空判断;changeModalType 中 modalType 赋值被注释,仅改了 moduleTypeName",
+    "repro": "空数据进页崩溃;潞宁等使用 modalType 的矿切换空压机/制氮机后模型类型不变",
+    "fix_hint": "空 records 提前 return;恢复按 strsystype 设置 modalType"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/components/nitrogenHome_ln.vue",
+    "lines": "341-349",
+    "title": "监测数据忽略选中系统ID",
+    "severity": "high",
+    "type": "wrong_data_binding",
+    "symptom": "切换注氮系统后仍展示 msgTxt[0] 数据,监控内容与下拉选择不一致",
+    "root_cause": "getDataSource(systemID) 入参未用于请求,固定取 res.msgTxt[0].datalist",
+    "repro": "配置≥2套注氮系统→切换下拉→数据不随 systemId 变化",
+    "fix_hint": "按 systemID/deviceId 过滤或带参请求对应系统数据"
+  },
+  {
+    "module": "智能注浆系统",
+    "file": "src/views/vent/monitorManager/groutMonitor/index.vue",
+    "lines": "110-119,67,86",
+    "title": "空数据崩溃且 currentDeviceType 永不赋值",
+    "severity": "high",
+    "type": "null_crash/dead_state",
+    "symptom": "无注浆系统时白屏;传给 groutHome 的 device-type 恒为空字符串",
+    "root_cause": "options.value[0]['id'] 无守卫;deviceChange 只写 deviceType,从未写入 currentDeviceType",
+    "repro": "空列表进页崩溃;有数据时检查 groutHome props.deviceType 为空",
+    "fix_hint": "空 records 保护;deviceChange/getSelectRow 同步 currentDeviceType"
+  },
+  {
+    "module": "密闭监测系统",
+    "file": "src/views/vent/monitorManager/obfurageMonitor/index.vue",
+    "lines": "89-138",
+    "title": "空数据崩溃且切换系统不刷新关联设备",
+    "severity": "high",
+    "type": "null_crash/stale_state",
+    "symptom": "无密闭系统/无关联设备时崩溃;切换密闭点后历史页设备 Tab 仍是旧设备",
+    "root_cause": "直接访问 msgTxt[0]、deviceArr[0];getSelectRow 只改 optionValue,未调用 getDeviceList",
+    "repro": "空数据进页;有多套密闭→切换后打开历史监测看设备按钮未更新",
+    "fix_hint": "空数组守卫;getSelectRow 内调用 getDeviceList()"
+  },
+  {
+    "module": "防火门智能管控",
+    "file": "src/views/vent/home/configurable/firedoor/fireDoorMonitor.vue",
+    "lines": "76-99",
+    "title": "场景列表为空仍继续后续逻辑且配置增强未启用",
+    "severity": "medium",
+    "type": "incomplete_init",
+    "symptom": "无防火门场景时下拉为空、模块无有效数据;服务端配置未走 updateEnhancedConfigs",
+    "root_cause": "records 为空时仍调用 loadFireGateData;updateEnhancedConfigs 被注释",
+    "repro": "manageFireList 返回空→页面无场景可选且面板无数据",
+    "fix_hint": "无 records 时提示并 return;恢复 updateEnhancedConfigs(configs)"
+  },
+  {
+    "module": "机电硐室管控",
+    "file": "src/views/vent/home/configurable/electroChamber.vue",
+    "lines": "86-99,29-50",
+    "title": "拉取配置后强制覆盖为本地测试配置且历史无设备ID",
+    "severity": "high",
+    "type": "hardcoded_override/missing_param",
+    "symptom": "线上始终使用 testConfigElectro;切历史 Tab 时 deviceId 常为空导致查询无效",
+    "root_cause": "fetchConfigs 成功后 configs.value=testConfigElectro;optionValue 仅来自路由 query,无设备选择赋值",
+    "repro": "非 A02A02 环境打开页面看配置是否被测试数据覆盖;无 query.id 切历史记录",
+    "fix_hint": "生产去掉测试覆盖;补充硐室/系统选择并写入 optionValue"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/reportMap.vue",
+    "lines": "82-119,135-145",
+    "title": "reactive 表单被整体重赋值 + 部门树空 children 崩溃",
+    "severity": "high",
+    "type": "reactivity_break/null_crash",
+    "symptom": "新增/编辑后表单状态异常;部门节点无 children 时查询部门树直接报错",
+    "root_cause": "formState= {...} 丢弃 reactive 代理;el.children.forEach 未判空",
+    "repro": "编辑一条映射再点新增观察表单残留;部门树缺 children 的节点触发加载",
+    "fix_hint": "用 Object.assign(formState, ...) 或重置字段;forEach 前守卫 children"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/report-modal.vue",
+    "lines": "135-151",
+    "title": "编辑时 JSON.parse(mineCells) 在非字符串时抛错",
+    "severity": "high",
+    "type": "type_error",
+    "symptom": "编辑已有映射弹窗打开失败或控制台 TypeError",
+    "root_cause": "watch 中无条件 JSON.parse(formStates.mineCells);接口若已反序列化为数组则解析失败;且 Object.assign 不会清除旧 id",
+    "repro": "打开编辑,当 record.mineCells 为数组或空时复现",
+    "fix_hint": "typeof===string 再 parse,数组则直接使用;新增时显式清空 id"
+  },
+  {
+    "module": "安全监控分站管理",
+    "file": "src/views/vent/safetyList/index.vue",
+    "lines": "234-257,408-417",
+    "title": "卸载引用未定义 timer + children 空指针 + 分页 total 错误",
+    "severity": "high",
+    "type": "reference_error/null_crash",
+    "symptom": "离开页面报 timer is not defined;devInfoList 为空时列表渲染崩溃;分页总数异常",
+    "root_cause": "timer 声明被注释但 onUnmounted 仍引用;el.children=el.devInfoList 后直接 forEach;res.total 在数组结果上常为 undefined",
+    "repro": "进入页再离开;返回含 null devInfoList 的分站;观察 pagination.total",
+    "fix_hint": "删除或恢复 timer;`(el.devInfoList||[]).forEach`;按接口实际结构取 records/total"
+  },
+  {
+    "module": "158分站监测",
+    "file": "src/views/vent/safetyList/common/detail.vue",
+    "lines": "977-1002,1013-1022",
+    "title": "devInfoList 为空时 forEach 崩溃",
+    "severity": "high",
+    "type": "null_crash",
+    "symptom": "部分分站无子设备时详细信息表加载失败",
+    "root_cause": "el.children = el.devInfoList 后未判空直接 forEach(getStationList1/getStationListAll)",
+    "repro": "选择无测点的分站查看详细信息",
+    "fix_hint": "使用可选链或默认空数组后再遍历"
+  },
+  {
+    "module": "130分站监测",
+    "file": "src/views/vent/safetyList/common/detail-130.vue",
+    "lines": "865-892",
+    "title": "devInfoList 空指针(同 index/detail)",
+    "severity": "high",
+    "type": "null_crash",
+    "symptom": "130 分站无子设备时列表处理抛错",
+    "root_cause": "el.children.forEach 未处理 null/undefined devInfoList",
+    "repro": "打开 130 详情页并选中无设备分站",
+    "fix_hint": "遍历前 `el.children = el.devInfoList || []`"
+  },
+  {
+    "module": "235分站监测",
+    "file": "src/views/vent/safetyList/common/detail-235.vue",
+    "lines": "352-369,608-768,888,958-1013",
+    "title": "235 页面误用 130 协议 API",
+    "severity": "critical",
+    "type": "wrong_api",
+    "symptom": "235 分站参数下发、改名、删除等操作打到 130 接口,控制/配置失败或污染错误协议设备",
+    "root_cause": "从 detail-130 复制后未替换:set130StationData/update130DevName/remove130Device/remove130Substation;api 中亦无对应 235 写接口",
+    "repro": "在 235 监测详情编辑并下发任意参数,观察请求 URL 含 130 路径",
+    "fix_hint": "补齐并改用 235 专用读写/删除 API,移除 130 引用"
+  },
+  {
+    "module": "用户日志管理",
+    "file": "src/views/monitor/log/index.vue",
+    "lines": "2,56-84",
+    "title": "v-modal 拼写错误 + 登录统计破坏 searchInfo 响应式",
+    "severity": "high",
+    "type": "typo/reactivity_break",
+    "symptom": "Tab 无法双向绑定;切到“登录统计”后查询条件失效、列表参数丢失 logType",
+    "root_cause": "模板写 v-modal 而非 v-model;case '4' 执行 searchInfo={} 丢掉 reactive 代理",
+    "repro": "打开日志页切换 Tab;切到登录统计后再查询",
+    "fix_hint": "改为 v-model;用 Object.keys 清空或重置字段,禁止重赋 searchInfo"
+  },
+  {
+    "module": "用户日志管理",
+    "file": "src/views/monitor/log/index.vue",
+    "lines": "34,61-66",
+    "title": "初始 fieldMapToTime 格式与切换后不一致",
+    "severity": "medium",
+    "type": "config_mismatch",
+    "symptom": "首次进入登录日志时时间范围映射可能无效,切 Tab 后才正常",
+    "root_cause": "paramTime 初始为扁平数组,tabChange 才设为 [[field,[begin,end],fmt]] 结构",
+    "repro": "首次进入不切 Tab,使用时间筛选对比切 Tab 后行为",
+    "fix_hint": "初始化即使用与 case '1' 相同的 fieldMapToTime 结构"
+  },
+  {
+    "module": "文件共享中心",
+    "file": "src/views/vent/performance/fileDetail/index.vue",
+    "lines": "292-314,367-377,387",
+    "title": "空树上标崩溃 + 可空文件上传 + nodeParam 丢失响应式",
+    "severity": "high",
+    "type": "null_crash/invalid_upload",
+    "symptom": "无目录时白屏;未选文件仍可点确定上传;树节点切换后表格参数可能异常",
+    "root_cause": "listArr[0] 无守卫;handleOk 不校验 fileList;nodeParam=node 重赋放弃 reactive",
+    "repro": "空目录数据进页;打开上传不选文件点确定;切换目录观察列表 parentId",
+    "fix_hint": "空树提示;上传前校验 fileList.length;Object.assign(nodeParam, node)"
+  },
+  {
+    "module": "文件共享中心",
+    "file": "src/views/vent/performance/fileDetail/index.vue",
+    "lines": "243-261",
+    "title": "setInterval 用 clearTimeout 清理",
+    "severity": "medium",
+    "type": "resource_leak",
+    "symptom": "汇总报表轮询可能无法可靠停止,关闭弹窗后仍请求",
+    "root_cause": "timer=setInterval 但 handleCancelHz/onUnmounted 使用 clearTimeout",
+    "repro": "打开汇总报表后关闭弹窗,观察是否仍持续请求 queryVentMonReportJd",
+    "fix_hint": "统一使用 clearInterval(timer)"
+  },
+  {
+    "module": "视频墙",
+    "file": "src/views/vent/monitorManager/camera/index.vue",
+    "lines": "100-128,172-178",
+    "title": "设备树加载与分页 paramKind 计算脆弱",
+    "severity": "high",
+    "type": "null_crash/wrong_param",
+    "symptom": "itemValue 无 '&' 或 msgTxt 结构异常时树展开/翻页失败或请求错误类型",
+    "root_cause": "假定 msgTxt[0].datalist 存在;分页用 searchParam.devKind.indexOf('&') 对 nodeData.itemValue 做 substring,缺 '&' 得空串",
+    "repro": "点击 itemValue 不含 '&' 的分类再翻页;或返回空 datalist 的节点",
+    "fix_hint": "安全解析 itemValue;访问 datalist 前判空;分页直接用 nodeData.itemValue"
+  },
+  {
+    "module": "需风量分析系统",
+    "file": "src/components/vent/micro/createSubApp.vue",
+    "lines": "15-37",
+    "title": "非 micro-* 路径组件恒为 null",
+    "severity": "high",
+    "type": "shell_mount_failure",
+    "symptom": "菜单若未挂在 micro-need-air/micro-vent-doc 前缀下则壳空白",
+    "root_cause": "resetComponent 仅识别有限 appType",
+    "repro": "用非 micro 路径打开需风量/核定",
+    "fix_hint": "按实际菜单 path 扩展映射"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/router/helper/routeHelper.ts",
+    "lines": "21-28,98-113,122-146",
+    "title": "layouts/RouteView 组件文件缺失导致路由无法解析",
+    "severity": "critical",
+    "type": "missing_component",
+    "symptom": "菜单 component 配为 layouts/RouteView 的父级打开空白/路由失败",
+    "root_cause": "src/layouts 下无 RouteView.vue;LayoutMap 未注册;dynamicImport 只扫 views/components",
+    "repro": "后端菜单配置 component=layouts/RouteView 后进入喷雾降尘父路由",
+    "fix_hint": "新增 layouts/RouteView.vue 并加入 LayoutMap;菜单改为已存在布局"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/views/vent/home/configurable/dust.vue",
+    "lines": "87-93",
+    "title": "服务端配置被测试数据覆盖且只用 Mock",
+    "severity": "high",
+    "type": "hardcoded_override",
+    "symptom": "粉尘首页始终展示 testConfigDust + BDDustMock,真实监测数据不刷新",
+    "root_cause": "fetchConfigs('dust') 后强制 configs=testConfigDust,并用 Promise.resolve(BDDustMock) 代替 getHomeData",
+    "repro": "任意环境打开粉尘可配置首页,对比接口与页面数据源",
+    "fix_hint": "生产移除测试覆盖,恢复 getHomeData 轮询"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/views/vent/home/configurable/dustControl.vue",
+    "lines": "53-54",
+    "title": "错误 pageType 拉取后再覆盖测试配置",
+    "severity": "high",
+    "type": "wrong_param/hardcoded_override",
+    "symptom": "降尘管控页配置与粉尘业务不匹配,最终仍被本地测试配置覆盖",
+    "root_cause": "fetchConfigs('mine_fire') 后 configs.value=testConfigDustControl",
+    "repro": "打开 dustControl 页检查 configuration 请求 pageType 与最终 configs",
+    "fix_hint": "使用正确粉尘 pageType,并按环境决定是否使用测试配置"
+  },
+  {
+    "module": "安全监控分站管理",
+    "file": "src/views/vent/safetyList/index.vue",
+    "lines": "144-146,71-76",
+    "title": "调试风向取值与展示映射不一致",
+    "severity": "medium",
+    "type": "value_mismatch",
+    "symptom": "调试选“反向”写入 '0',列表展示逻辑把反风映射为 '2',显示异常",
+    "root_cause": "derictList 反向 value='0',而 valueJc 渲染把 '2' 当作反风",
+    "repro": "调试设备选反向并确认,查看列表风向展示",
+    "fix_hint": "统一风向枚举(建议 1 正/2 反)并同步调试与展示"
+  },
+  {
+    "module": "报表管理",
+    "file": "src/views/vent/reportManager/index.vue",
+    "lines": "89-106",
+    "title": "三类根节点重复挂载同一套子树",
+    "severity": "medium",
+    "type": "wrong_tree_build",
+    "symptom": "系统/手动/模板三类下出现完全相同的业务分类,筛选易混淆",
+    "root_cause": "getTreeList 对 listArr 每个根节点都 push 完整 res 树,未按业务类型分流",
+    "repro": "打开报表管理对比三个根节点的 children",
+    "fix_hint": "按返回字段或接口分类型填充到对应根节点"
+  },
+  {
+    "module": "智能注浆系统",
+    "file": "src/views/vent/monitorManager/groutMonitor/index.vue",
+    "lines": "1-35",
+    "title": "2D 模型与 groutHome 同时渲染可能叠层",
+    "severity": "medium",
+    "type": "ui_logic",
+    "symptom": "is2DModel 为 true 时流程图与监控壳同时存在,交互/遮罩异常",
+    "root_cause": "v-if is2DModel 渲染 modelComponent,同时 activeKey==monitor 仍挂载 groutHome",
+    "repro": "开启全局 is2DModel 进入注浆监控页",
+    "fix_hint": "2D 时由单一容器负责模型,或让 groutHome 在 2D 模式跳过三维初始化"
+  },
+  {
+    "module": "机电硐室管控",
+    "file": "src/views/vent/home/configurable/configurable.data.ts",
+    "lines": "6164,6217",
+    "title": "electro-champer / electro-chamber pageType 拼写分裂",
+    "severity": "medium",
+    "type": "config_typo",
+    "symptom": "部分配置按错误 pageType 入库后,fetchConfigs('electro-champer') 只能拿到半套模块",
+    "root_cause": "同一业务存在 champer/chamber 两种 pageType 字面量",
+    "repro": "在配置表按两种 pageType 各查一次 records 数量",
+    "fix_hint": "统一为一种拼写并做数据迁移"
+  },
+  {
+    "module": "密闭监测系统",
+    "file": "src/views/vent/monitorManager/obfurageMonitor/index.vue",
+    "lines": "107-113",
+    "title": "forEach 内 data=Object.assign 未回写",
+    "severity": "medium",
+    "type": "dead_assignment",
+    "symptom": "readData 字段未合并进列表项,监测展示缺字段",
+    "root_cause": "dataSource.forEach 中 `data = Object.assign(data, readData)` 只改局部绑定,未写回数组元素",
+    "repro": "对比接口 readData 与页面 options 字段是否缺失",
+    "fix_hint": "改为 Object.assign(data, readData) 不重绑,或显式写回"
+  }
+]

+ 132 - 0
docs/_agent_fire_dust.raw.txt

@@ -0,0 +1,132 @@
+[
+  {
+    "module": "喷淋监控系统",
+    "file": "src/views/vent/monitorManager/sprayMonitor/index.vue",
+    "lines": "68-140",
+    "title": "多路控制按钮共用同一 paramcode/value",
+    "severity": "critical",
+    "type": "wrong_control_payload",
+    "symptom": "除急停外,补水阀/搅拌阀/组化泵/上料机/喷洒自动等按钮下发完全相同的指令,设备无法按按钮区分控制,存在误控风险",
+    "root_cause": "operations 全部使用 key='run_auto_sign',且多数 value='0';BasicMonitoring.deviceControl 仅按 key/value 下发",
+    "repro": "打开喷淋监控→输入密码点击“补水阀启停”与“喷洒自动”→抓包可见 paramcode/value 相同",
+    "fix_hint": "为每个操作配置独立 paramcode,并按启停状态设置正确 value(参考业务点表)"
+  },
+  {
+    "module": "喷淋监控系统",
+    "file": "src/components/vent/BasicMonitoring.vue",
+    "lines": "19,193-201",
+    "title": "操作列表 :key 冲突 + 空场景崩溃",
+    "severity": "high",
+    "type": "vue_key_collision/null_crash",
+    "symptom": "喷淋多个按钮共用 key 导致 DOM 复用异常;无场景数据时页面直接抛错白屏",
+    "root_cause": "v-for 使用 item.key 作唯一键但喷淋键重复;getSysDataSource 无空数组守卫直接取 options[0].id",
+    "repro": "1) 打开喷淋页观察按钮交互状态错乱;2) 后端返回空 records 时进入页面立即报错",
+    "fix_hint": "key 使用 label 或唯一 id;取首项前判断 records.length"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/index.vue",
+    "lines": "93-126",
+    "title": "空列表崩溃且 modalType 未随系统类型切换",
+    "severity": "high",
+    "type": "null_crash/stale_config",
+    "symptom": "无注氮系统时白屏;依赖 modalType 的矿端组件始终按 nitrogenUnderground 建模",
+    "root_cause": "options.value[0]['id'] 无空判断;changeModalType 中 modalType 赋值被注释,仅改了 moduleTypeName",
+    "repro": "空数据进页崩溃;潞宁等使用 modalType 的矿切换空压机/制氮机后模型类型不变",
+    "fix_hint": "空 records 提前 return;恢复按 strsystype 设置 modalType"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/components/nitrogenHome_ln.vue",
+    "lines": "341-349",
+    "title": "监测数据忽略选中系统ID",
+    "severity": "high",
+    "type": "wrong_data_binding",
+    "symptom": "切换注氮系统后仍展示 msgTxt[0] 数据,监控内容与下拉选择不一致",
+    "root_cause": "getDataSource(systemID) 入参未用于请求,固定取 res.msgTxt[0].datalist",
+    "repro": "配置≥2套注氮系统→切换下拉→数据不随 systemId 变化",
+    "fix_hint": "按 systemID/deviceId 过滤或带参请求对应系统数据"
+  },
+  {
+    "module": "智能注浆系统",
+    "file": "src/views/vent/monitorManager/groutMonitor/index.vue",
+    "lines": "110-119,67,86",
+    "title": "空数据崩溃且 currentDeviceType 永不赋值",
+    "severity": "high",
+    "type": "null_crash/dead_state",
+    "symptom": "无注浆系统时白屏;传给 groutHome 的 device-type 恒为空字符串",
+    "root_cause": "options.value[0]['id'] 无守卫;deviceChange 只写 deviceType,从未写入 currentDeviceType",
+    "repro": "空列表进页崩溃;有数据时检查 groutHome props.deviceType 为空",
+    "fix_hint": "空 records 保护;deviceChange/getSelectRow 同步 currentDeviceType"
+  },
+  {
+    "module": "密闭监测系统",
+    "file": "src/views/vent/monitorManager/obfurageMonitor/index.vue",
+    "lines": "89-138",
+    "title": "空数据崩溃且切换系统不刷新关联设备",
+    "severity": "high",
+    "type": "null_crash/stale_state",
+    "symptom": "无密闭系统/无关联设备时崩溃;切换密闭点后历史页设备 Tab 仍是旧设备",
+    "root_cause": "直接访问 msgTxt[0]、deviceArr[0];getSelectRow 只改 optionValue,未调用 getDeviceList",
+    "repro": "空数据进页;有多套密闭→切换后打开历史监测看设备按钮未更新",
+    "fix_hint": "空数组守卫;getSelectRow 内调用 getDeviceList()"
+  },
+  {
+    "module": "防火门智能管控",
+    "file": "src/views/vent/home/configurable/firedoor/fireDoorMonitor.vue",
+    "lines": "76-99",
+    "title": "场景列表为空仍继续后续逻辑且配置增强未启用",
+    "severity": "medium",
+    "type": "incomplete_init",
+    "symptom": "无防火门场景时下拉为空、模块无有效数据;服务端配置未走 updateEnhancedConfigs",
+    "root_cause": "records 为空时仍调用 loadFireGateData;updateEnhancedConfigs 被注释",
+    "repro": "manageFireList 返回空→页面无场景可选且面板无数据",
+    "fix_hint": "无 records 时提示并 return;恢复 updateEnhancedConfigs(configs)"
+  },
+  {
+    "module": "机电硐室管控",
+    "file": "src/views/vent/home/configurable/electroChamber.vue",
+    "lines": "86-99,29-50",
+    "title": "拉取配置后强制覆盖为本地测试配置且历史无设备ID",
+    "severity": "high",
+    "type": "hardcoded_override/missing_param",
+    "symptom": "线上始终使用 testConfigElectro;切历史 Tab 时 deviceId 常为空导致查询无效",
+    "root_cause": "fetchConfigs 成功后 configs.value=testConfigElectro;optionValue 仅来自路由 query,无设备选择赋值",
+    "repro": "非 A02A02 环境打开页面看配置是否被测试数据覆盖;无 query.id 切历史记录",
+    "fix_hint": "生产去掉测试覆盖;补充硐室/系统选择并写入 optionValue"
+  },
+  {
+    "module": "报表管理",
+    "file": "src/views/vent/reportManager/comment/reportMap.vue",
+    "lines": "82-119,135-145",
+    "title": "reactive 表单被整体重赋值 + 部门树空 children 崩溃",
+    "severity": "high",
+    "type": "reactivity_break/null_crash",
+    "symptom": "新增/编辑后表单状态异常;部门节点无 children 时查询部门树直接报错",
+    "root_cause": "formState= {...} 丢弃 reactive 代理;el.children.forEach 未判空",
+    "repro": "编辑一条映射再点新增观察表单残留;部门树缺 children 的节点触发加载",
+    "fix_hint": "用 Object.assign(formState, ...) 或重置字段;forEach 前守卫 children"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/report-modal.vue",
+    "lines": "135-151",
+    "title": "编辑时 JSON.parse(mineCells) 在非字符串时抛错",
+    "severity": "high",
+    "type": "type_error",
+    "symptom": "编辑已有映射弹窗打开失败或控制台 TypeError",
+    "root_cause": "watch 中无条件 JSON.parse(formStates.mineCells);接口若已反序列化为数组则解析失败;且 Object.assign 不会清除旧 id",
+    "repro": "打开编辑,当 record.mineCells 为数组或空时复现",
+    "fix_hint": "typeof===string 再 parse,数组则直接使用;新增时显式清空 id"
+  },
+  {
+    "module": "安全监控分站管理",
+    "file": "src/views/vent/safetyList/index.vue",
+    "lines": "234-257,408-417",
+    "title": "卸载引用未定义 timer + children 空指针 + 分页 total 错误",
+    "severity": "high",
+    "type": "reference_error/null_crash",
+    "symptom": "离开页面报 timer is not defined;devInfoList 为空时列表渲染崩溃;分页总数异常",
+    "root_cause": "timer 声明被注释但 onUnmounted 仍引用;el.children=el.devInfoList 后直接 forEach;res.total 在数组结果上常为 undefined",
+    "repro": "进入页再离开;返回含 null devInfoList 的分站;观察 pagination.total",
+    "fix_hint": "删除或恢复 timer;

+ 302 - 0
docs/_agent_monitor.json

@@ -0,0 +1,302 @@
+[
+  {
+    "id-suggestion": "MON-WINDRECT-EXPORT-IMPORT-API",
+    "module": "测风装置管控",
+    "file path with line ranges": "src/views/vent/monitorManager/windrectMonitor/windrect.api.ts:59; src/views/vent/monitorManager/windrectMonitor/index.vue:769-771",
+    "title": "测风导出函数实际请求导入接口",
+    "severity": "致命",
+    "type": "export calling wrong import API",
+    "symptom": "一键测风结果导出不会调用 /safety/testwindDetail/exportXls,而是 POST /sys/user/importExcel,导出失败或误触发用户导入接口",
+    "root_cause": "exportXls 实现写成 defHttp.post({ url: Api.importExcel }),而 index.vue 的 exportExcel 直接调用该函数(未使用正确的 getExportUrl)",
+    "repro": "打开测风装置管控 → 触发 exportExcel(id) / 结果导出 → 抓包可见请求 importExcel",
+    "fix_hint": "将 exportXls 的 url 改为 Api.exportXls,或改为使用 getExportUrl 走正确导出下载链路"
+  },
+  {
+    "id-suggestion": "MON-MAINFAN-CHANGE-SMOKE1-SHARED-PARAM",
+    "module": "主风机管控",
+    "file path with line ranges": "src/views/vent/monitorManager/mainFanMonitor/index.vue:1609-1662",
+    "title": "倒机正转/反转共用同一 paramcode",
+    "severity": "致命",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "changeSmoke1 场景下正启动与反启动都下发 CtrlFan1ToFan2 / CtrlFan2ToFan1,无法区分正反转倒机指令",
+    "root_cause": "同文件 changeSmoke 分支正确使用 CtrlFan1ToFan2Forward/Reverse 与 CtrlFan2ToFan1Forward/Reverse,但 changeSmoke1 分支正反转都调用无方向后缀的同一点位",
+    "repro": "风机处于正转/反转运行态触发一键倒机(modalType=changeSmoke1)→ 对比下发 paramcode",
+    "fix_hint": "与 changeSmoke 分支对齐,正转用 *Forward、反转用 *Reverse"
+  },
+  {
+    "id-suggestion": "MON-WINDOW-REAR-GATE-LABEL-MISMATCH",
+    "module": "风窗管控",
+    "file path with line ranges": "src/views/vent/monitorManager/windowMonitor/index.vue:37-41",
+    "title": "后门控制按钮文案错写成前门",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode / mislabeled control",
+    "symptom": "界面显示“打开前门/关闭前门”,实际下发 rearGateOpen_S/rearGateClose_S,操作员会误控后门",
+    "root_cause": "按钮展示文案复制前门未改,第二参数标题已是后门,UI 文本与指令不一致",
+    "repro": "具备 window:gateControl 且 ndoorcount==2 → 看后两颗按钮文案与 setControl 参数",
+    "fix_hint": "将后两颗按钮文案改为“打开后门/关闭后门”"
+  },
+  {
+    "id-suggestion": "MON-WINDOW-AREA-ANGLE-SHARED-PARAM",
+    "module": "风窗管控",
+    "file path with line ranges": "src/views/vent/monitorManager/windowMonitor/index.vue:11-14,623-651",
+    "title": "窗面积与窗角度控制共用 paramcode 1/2",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "窗1/窗2 面积设定与角度设定最终都下发 paramcode='1'/'2',后端无法区分面积/角度",
+    "root_cause": "twoAreaControl 与 twoAngleControl 都 setControl('1'|'2'),handleOK else 分支直接 data.paramcode=handlerState",
+    "repro": "同时开启 window:twoAreaControl 与 window:twoAngleControl → 分别设定面积/角度 → 抓包对比 paramcode",
+    "fix_hint": "角度使用独立点位(如 frontSetAngle1),或在 value/附加字段中区分控制类型"
+  },
+  {
+    "id-suggestion": "MON-WINDOW-SHOWANGLEAREA-USES-SETANGLE",
+    "module": "风窗管控",
+    "file path with line ranges": "src/views/vent/monitorManager/windowMonitor/index.vue:31-33,504-520",
+    "title": "设定风窗面积误走角度弹窗流程",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "权限 window:showAngleArea 的“设定风窗面积”调用 setAngle(1),弹窗标题按角度生成,但点位仍 frontSetValue",
+    "root_cause": "面积按钮错误绑定 setAngle 而非 setArea",
+    "repro": "开启 window:showAngleArea → 点击“设定风窗面积” → 观察 modalTitle 与下发参数",
+    "fix_hint": "改为 setArea(1),或单独实现面积设定入口"
+  },
+  {
+    "id-suggestion": "MON-FANLOCAL-DUP-DIAMETER-BTN",
+    "module": "局部风机管控",
+    "file path with line ranges": "src/views/vent/monitorManager/fanLocalMonitor/index.vue:782-791",
+    "title": "风筒直径控制按钮重复且同 key",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "控制区出现两个相同“风筒直径”按钮,key 均为 diameter,行为完全重复",
+    "root_cause": "leftBtnArr 中 diameter 配置项被复制粘贴两次",
+    "repro": "开启 fanLocal:diameter → 顶部控制按钮可见重复项",
+    "fix_hint": "删除重复配置;若本意为主/备直径,需不同 key 与 paramcode"
+  },
+  {
+    "id-suggestion": "MON-NETWORK-DHLOCAL-WRONG-FIELD",
+    "module": "通风系统监测/通风网络解算",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/network/index.vue:403-405",
+    "title": "局部阻力字段误读自然风压",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "巷道表“局部阻力”与“自然风压”显示相同值,局部阻力失真",
+    "root_cause": "dHLocal 赋值使用 item['dHNature'],与 dHNature 同源",
+    "repro": "打开网络解算结果表 → 对比局部阻力与自然风压列",
+    "fix_hint": "改为读取 item['dHLocal'](或后端真实局部阻力字段)"
+  },
+  {
+    "id-suggestion": "MON-EMERGENCY-DHLOCAL-WRONG-FIELD",
+    "module": "灾变应急控制",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:273-275",
+    "title": "应急解算局部阻力同样误绑 dHNature",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "灾变应急巷道阻力表局部阻力错误",
+    "root_cause": "与 network 相同的复制错误:dHLocal: item['dHNature']",
+    "repro": "进入灾变应急页加载解算结果 → 查看巷道阻力列",
+    "fix_hint": "改为 item['dHLocal']"
+  },
+  {
+    "id-suggestion": "MON-EMERGENCY-SHARED-DETAIL-CODES",
+    "module": "灾变应急控制",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:196-226",
+    "title": "工作面详情多项共用同一数据 code",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "工作面编号/采区/煤层都显示 dTotalArea;长度/走向/采高都显示 totallength",
+    "root_cause": "analysisDetailDataList 多项复用相同 code,未映射独立字段",
+    "repro": "打开灾变应急分析详情区 → 观察多行数值是否雷同",
+    "fix_hint": "为每项配置正确业务字段 code,并在 pageData 中补齐对应值"
+  },
+  {
+    "id-suggestion": "MON-NETWORK-READDATA-NULL-DEREF",
+    "module": "通风系统监测/通风网络解算",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/network/index.vue:447-454",
+    "title": "传感器列表未判空直接读 readData",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "monitors 中某条缺少 readData 时 analyzePageResult 抛错,页面解算结果渲染中断",
+    "root_cause": "直接访问 item['readData']['va']/['m3'],无空保护",
+    "repro": "构造 monitors 项 readData=null 的解算推送 → 打开网络页",
+    "fix_hint": "先取 const rd=item.readData||{} 再读字段"
+  },
+  {
+    "id-suggestion": "MON-EMERGENCY-READDATA-NULL-DEREF",
+    "module": "灾变应急控制",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:314-321",
+    "title": "应急页传感器 readData 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "同网络页,缺 readData 时应急页崩溃",
+    "root_cause": "item['readData']['va'] 无空判断",
+    "repro": "推送缺 readData 的 monitors → 打开应急页",
+    "fix_hint": "对 readData 做空对象兜底"
+  },
+  {
+    "id-suggestion": "MON-FIBER-HARDCODE-WARN",
+    "module": "光纤测温监测",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:49,169-188,232-257",
+    "title": "光纤详情风险等级与预警历史写死假数据",
+    "severity": "严重",
+    "type": "mock hardcode replacing real API",
+    "symptom": "风险等级恒为“低风险”,预警历史永远是测点6/318℃等假记录,不随真实报警变化",
+    "root_cause": "模板写死低风险;warningConfig.data 硬编码数组,watch 未用真实告警填充",
+    "repro": "打开光纤测温弹窗 → 对比真实告警与滚动板内容",
+    "fix_hint": "绑定设备真实风险字段与告警历史接口/数据"
+  },
+  {
+    "id-suggestion": "MON-FIBER-READDATA-NULL-DEREF",
+    "module": "光纤测温监测",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:239-243",
+    "title": "光纤弹窗 Object.keys(readData) 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "设备无 readData 时打开弹窗直接 TypeError",
+    "root_cause": "未判断 item.readData 即 Object.keys(item.readData)",
+    "repro": "选中 readData 为空的光纤设备打开详情",
+    "fix_hint": "if (!item.readData) return; 后再解析分段温度"
+  },
+  {
+    "id-suggestion": "MON-DUST-HARDCODE-WARN",
+    "module": "防尘系统监测",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/dust.modal.vue:216-238",
+    "title": "粉尘弹窗测点状态/预警历史硬编码",
+    "severity": "严重",
+    "type": "mock hardcode replacing real API",
+    "symptom": "测点状态 customRender 永远返回“正常”;预警滚动板为固定假数据",
+    "root_cause": "columns.state 写死正常;warningConfig.data 硬编码",
+    "repro": "打开粉尘监测详情弹窗观察状态与预警列表",
+    "fix_hint": "状态取真实字段;预警列表接真实告警数据"
+  },
+  {
+    "id-suggestion": "MON-FIREMON-TEMP-UNIT-WRONG",
+    "module": "防灭火系统监测",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/firemon.modal.vue:63-65",
+    "title": "智慧球温度值单位误标为 %",
+    "severity": "一般",
+    "type": "logic/display bug",
+    "symptom": "温度值旁显示 % 而非 ℃,监控读数语义错误",
+    "root_cause": "模板单位复制错误",
+    "repro": "打开 firemon 详情查看温度项单位",
+    "fix_hint": "将单位改为 ℃"
+  },
+  {
+    "id-suggestion": "MON-ATOMIZING-LOCATION-UNIT-WRONG",
+    "module": "喷雾降尘/防尘系统监测",
+    "file path with line ranges": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/atomizing.modal.vue:33-42",
+    "title": "主机位置字段错误附加 ℃ 单位",
+    "severity": "一般",
+    "type": "logic/display bug",
+    "symptom": "位置类字段后显示温度单位,信息误导",
+    "root_cause": "holderLocation 展示模板误加 ℃",
+    "repro": "打开喷雾监测详情查看“主机位置”",
+    "fix_hint": "去掉 ℃,位置字段无需单位"
+  },
+  {
+    "id-suggestion": "MON-BETKY-MOCK-AND-POLL-BUG",
+    "module": "工作面来压预警",
+    "file path with line ranges": "src/views/vent/monitorManager/betKy/index.vue:110-146,253-263",
+    "title": "矿压监测轮询逻辑错误且特定矿用假数据",
+    "severity": "严重",
+    "type": "mock hardcode + setInterval/setTimeout poll without proper clear",
+    "symptom": "A02A02 矿强制使用 ceshi.json;轮询前把 timer 置 null 未 clearTimeout,chartData 每次 push 不清理导致曲线数据膨胀错乱;卸载用 clearInterval 清 setTimeout",
+    "root_cause": "getDataSource 用本地 json 替换真实 list;timer 管理与 chartData 累积错误",
+    "repro": "进入 betKy 页(尤其 A02A02)观察请求与图表随时间变化",
+    "fix_hint": "去掉矿别假数据分支;轮询用 clearTimeout;每次刷新重置 chartData"
+  },
+  {
+    "id-suggestion": "MON-BETKY-READDATA-NULL",
+    "module": "工作面来压预警",
+    "file path with line ranges": "src/views/vent/monitorManager/betKy/index.vue:127-131",
+    "title": "矿压轮询 Object.values(readData) 空指针",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "设备缺 readData 时页面轮询崩溃,后续刷新停止",
+    "root_cause": "未判空直接 Object.values(readData)",
+    "repro": "返回含 readData=null 的 Minepressure 列表",
+    "fix_hint": "if (!readData) continue; 后再处理"
+  },
+  {
+    "id-suggestion": "MON-AIRDOOR-TIPMODAL-TIMER-LEAK",
+    "module": "风门集中同控",
+    "file path with line ranges": "src/views/vent/monitorManager/airDoor/components/tipModal.vue:28-54",
+    "title": "倒计时弹窗 setTimeout 递归不清理",
+    "severity": "严重",
+    "type": "setInterval/setTimeout poll without clear on unmount",
+    "symptom": "提示弹窗显示后每秒递归创建定时器;关闭/卸载后仍继续;timeout<=0 时先 timer=undefined 再 clearTimeout(undefined) 无效,且仍调用 getMonitor()",
+    "root_cause": "无 onUnmounted/Visible=false 时 clear;递归无退出;clear 顺序错误",
+    "repro": "触发 visibleTs30=true → 关闭弹窗或离开页面 → 观察仍有定时回调",
+    "fix_hint": "保存 timerId;Visible 变 false 与 onUnmounted 时 clearTimeout;倒计时结束停止递归"
+  },
+  {
+    "id-suggestion": "MON-AIRDOOR-MSGTXT-NULL-DEREF",
+    "module": "风门集中同控",
+    "file path with line ranges": "src/views/vent/monitorManager/airDoor/index.vue:44-51",
+    "title": "风门同控菜单拉取未判空 msgTxt[0]",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "接口返回空/异常结构时 getMenuList 抛错,左侧菜单无法加载",
+    "root_cause": "直接访问 res.msgTxt[0].datalist.length",
+    "repro": "mock /monitor/device 返回无 msgTxt 或空数组 → 打开风门集中同控",
+    "fix_hint": "使用可选链与默认 []:res?.msgTxt?.[0]?.datalist || []"
+  },
+  {
+    "id-suggestion": "MON-WORKFACE-WARNINFO-KEY-BUG",
+    "module": "综采面智能管控",
+    "file path with line ranges": "src/views/vent/monitorManager/workFaceMonitor/components/workFaceHome.vue:262-276",
+    "title": "综合预警判断键错误且可能空指针",
+    "severity": "严重",
+    "type": "null deref / wrong field mapping",
+    "symptom": "用 warnInfo.warnInfo 判断却读取 synthesizeS;键不匹配时综合预警不更新,或 synthesizeS 缺失时崩溃;surface_history/sysInfo 亦缺保护",
+    "root_cause": "条件写成 res['warnInfo']['warnInfo'];并对 surface_history[0]、sysInfo.readData 无空保护",
+    "repro": "返回缺 synthesizeS 或 surface_history 为空的综采面数据",
+    "fix_hint": "条件改为 synthesizeS;对各嵌套字段做空判断"
+  },
+  {
+    "id-suggestion": "MON-TUNFACE-WARN-NULL-DEREF",
+    "module": "掘进面智能管控",
+    "file path with line ranges": "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceHome.vue:254,262-271",
+    "title": "掘进面首页无条件解包 warnInfo/readData",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "缺 dustS/fireS/gasS/synthesizeS/ventS、缺 surface_history、或缺 location.readData 时页面直接崩溃",
+    "root_cause": "无守卫直接访问 res['warnInfo'][x]['devices']、res['surface_history'][0]、data['readData']['flen']",
+    "repro": "接口缺任一 warn 分组或 location.readData → 打开掘进面主页",
+    "fix_hint": "逐层可选链;缺省赋空数组/空对象"
+  },
+  {
+    "id-suggestion": "MON-BELTTUN-WARN-NULL-DEREF",
+    "module": "皮带巷管控系统",
+    "file path with line ranges": "src/views/vent/monitorManager/beltTunMonitor/components/beltTunHome.vue:260-268",
+    "title": "皮带巷首页 warnInfo/sysInfo 无空保护",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "sysInfo 或某类 warn 分组缺失时页面加载失败",
+    "root_cause": "直接 Object.assign(res['sysInfo'], res['sysInfo']['readData']) 与 warnInfo.*.devices",
+    "repro": "返回不完整 beltTun 监测包 → 打开皮带巷主页",
+    "fix_hint": "增加空判断与默认值"
+  },
+  {
+    "id-suggestion": "MON-WORKFACE-LOCATION-FLEN-NULL",
+    "module": "综采面智能管控",
+    "file path with line ranges": "src/views/vent/monitorManager/workFaceMonitor/components/workFaceHome.vue:251-254",
+    "title": "定位列表读取 readData.flen 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "location 设备无 readData 时过滤阶段抛错,后续监控数据不完整",
+    "root_cause": "locationData.push 中直接 data['readData']['flen']",
+    "repro": "location.datalist 含 readData=null 的项",
+    "fix_hint": "使用 data?.readData?.flen ?? '-'"
+  },
+  {
+    "id-suggestion": "MON-MAINFAN-AREA-SIM-INTERVAL-LEAK",
+    "module": "主风机管控",
+    "file path with line ranges": "src/views/vent/monitorManager/mainFanMonitor/hooks/useAreaSetSimulation.ts:37-109; useMainFanSimulation.ts:25-72",
+    "title": "天窗/闸板面积模拟 setInterval 卸载未清理",
+    "severity": "一般",
+    "type": "setInterval/setTimeout poll without clear on unmount",
+    "symptom": "开启 fanSwitchoverSimulation 后设定面积过程中离开页面,interval 仍改 selectData,可能写已销毁状态",
+    "root_cause": "useAreaSetSimulation 仅在过程结束 clear;无 onUnmounted 遍历 activeProcesses 清理(对比 useFanSwitchoverSimulation 有 stopTick)",
+    "repro": "开启模拟 → 设定天窗面积 → 过渡未完成即路由离开",
+    "fix_hint": "在 composable 增加 dispose/onUnmounted,清理 Map 内全部 interval"
+  }
+]

+ 569 - 0
docs/_coverage.json

@@ -0,0 +1,569 @@
+[
+  {
+    "module": "主风机管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue;src\\views\\vent\\monitorManager\\mainFanMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-002,BUG-088",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "局部风机管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue;src\\views\\vent\\monitorManager\\fanLocalMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-034,BUG-095",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "测风装置管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue;src\\views\\vent\\monitorManager\\windrectMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-007",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "风门管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue;src\\views\\vent\\monitorManager\\gateMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "风窗管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue;src\\views\\vent\\monitorManager\\windowMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-083,BUG-084,BUG-085",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "气压温湿度监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\sensorMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "风门集中同控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\airDoor\\index.vue",
+    "static": "已静态审查;关联 BUG-086,BUG-087",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "需风量分析系统",
+    "map_status": "micro",
+    "paths": "src\\components\\vent\\micro\\createSubApp.vue",
+    "static": "已静态审查;关联 BUG-082",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "通风参数一张表",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\ventilateSheet.vue",
+    "static": "已静态审查;关联 BUG-015,BUG-077",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "通风能力核定",
+    "map_status": "micro",
+    "paths": "src\\components\\vent\\micro\\createSubApp.vue",
+    "static": "微前端壳已映射;壳层已审查",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "130分站监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\safetyList\\common\\detail-130.vue",
+    "static": "已静态审查;关联 BUG-012,BUG-013",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "158分站监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\safetyList\\common\\detail.vue",
+    "static": "已静态审查;关联 BUG-014",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "235分站监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\safetyList\\common\\detail-235.vue",
+    "static": "已静态审查;关联 BUG-001",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "通风系统监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "通风网络解算",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-079,BUG-080",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "关键通风路线",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "实时网络解算",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "控风方案决策",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "多灾融合预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-005,BUG-021,BUG-022,BUG-023,BUG-024,BUG-025,BUG-026,BUG-027,BUG-028,BUG-029…",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "通风监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\ventilateWarn.vue",
+    "static": "已静态审查;关联 BUG-078",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "火灾监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\fireWarn.vue",
+    "static": "已静态审查;关联 BUG-054",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "粉尘监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\dustWarn.vue",
+    "static": "已静态审查;关联 BUG-071",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\gasWarn.vue",
+    "static": "已静态审查;关联 BUG-009,BUG-063",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "灾变应急控制",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-055,BUG-056,BUG-057",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "设备监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitorWarn\\index.vue",
+    "static": "已静态审查;关联 BUG-076",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "工作面来压预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\betKy\\index.vue",
+    "static": "已静态审查;关联 BUG-035",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "预警联动控制",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\deviceManager\\workingFace\\index.vue",
+    "static": "已静态审查;关联 BUG-011,BUG-109,BUG-110",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "光纤测温监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-016,BUG-017",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "束管监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "防火门监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "密闭监测系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\obfurageMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-033,BUG-094",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "喷淋监控系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\sprayMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-003,BUG-018",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "智能注氮系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\compressor\\index.vue",
+    "static": "已静态审查;关联 BUG-046,BUG-047",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "智能注浆系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\groutMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-048,BUG-100",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "火灾监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\fireWarn.vue",
+    "static": "已静态审查;关联 BUG-054",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "防灭火系统监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-108",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "色谱仪报表分析",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\bundleSpy\\bundleSpyTable\\index.vue",
+    "static": "已静态审查;关联 BUG-010,BUG-074,BUG-105",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "束管日报分析",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\bundle\\bundleMonitorTable\\index.vue",
+    "static": "已静态审查;关联 BUG-050,BUG-051,BUG-052,BUG-053,BUG-102",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯监测",
+    "map_status": "mapped",
+    "paths": "src\\layouts\\default\\index.vue",
+    "static": "已静态审查;关联 BUG-009,BUG-063",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\gasWarn.vue",
+    "static": "已静态审查;关联 BUG-009,BUG-063",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "抽采泵站管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\gasPumpMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-006,BUG-038,BUG-039",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "抽采达标评判",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasAssessment\\index.vue",
+    "static": "已静态审查;关联 BUG-040,BUG-041,BUG-042,BUG-043",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "抽采综合管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasHome\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯抽采单元",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasAssessment\\components\\gasUnit.vue",
+    "static": "已静态审查;关联 BUG-043",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯管网管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasPipeNet\\index.vue",
+    "static": "已静态审查;关联 BUG-064",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "抽采泵站监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasPumpMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-098",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯日报历史详情",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasReportInspect\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯钻孔监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasZk\\index.vue",
+    "static": "已静态审查;关联 BUG-065",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯巡检设备",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯人工巡检报表管理",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasReport\\index.vue",
+    "static": "已静态审查;关联 BUG-061,BUG-062,BUG-097",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯人工巡检地点管理(NFC)",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasInspect\\index.vue",
+    "static": "已静态审查;关联 BUG-059,BUG-060,BUG-103",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯人工巡检业务分析",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasAnalysis\\index.vue",
+    "static": "已静态审查;关联 BUG-058",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯人工巡检地点管理",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasInspectNonfc\\index.vue",
+    "static": "已静态审查;关联 BUG-059,BUG-060,BUG-103",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "一张表",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\gasSheet.vue",
+    "static": "已静态审查;关联 BUG-015,BUG-068,BUG-077",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "评判参数设置",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasPumpSetting\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "瓦斯日报分析",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\gas\\gasReportInspect\\index.vue",
+    "static": "已静态审查;关联 BUG-008",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "map_status": "weak",
+    "paths": "src\\views\\vent\\home\\configurable\\dust.vue",
+    "static": "已静态审查;关联 BUG-004,BUG-019,BUG-020",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "除尘风机",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\dedustMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "粉尘监测预警",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\dustWarn.vue",
+    "static": "已静态审查;关联 BUG-071",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "粉尘参数一张表",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\dustSheet.vue",
+    "static": "已静态审查;关联 BUG-015,BUG-068",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "防尘系统监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-081,BUG-106",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "粉尘报表分析",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\dust\\dustMonitorTable\\index.vue",
+    "static": "已静态审查;关联 BUG-069,BUG-070",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "综采面智能管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\workFaceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-072,BUG-073",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "掘进面智能管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\tunFaceMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-044",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "防火门智能管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\home\\configurable\\firedoor\\fireDoorMonitor.vue",
+    "static": "已静态审查;关联 BUG-107",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "皮带巷管控系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\beltTunMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-067",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "机电硐室管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\chamberMonitor\\index.vue",
+    "static": "已静态审查;关联 BUG-049,BUG-101",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "均压与低氧管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\balancePressMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "机电硐室管控",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\home\\configurable\\electroChamber.vue",
+    "static": "已静态审查;关联 BUG-049,BUG-101",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "压风管控系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\nitrogen\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "温度压差监测",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\sensorMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "安全监控系统",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\safetyMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "设备预警历史",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\warningMonitor\\index-mine.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "设备操作历史",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\handlerMonitor\\index.vue",
+    "static": "已静态审查入口与关键逻辑;本次未发现新增高置信缺陷",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "视频墙",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\monitorManager\\camera\\index.vue",
+    "static": "已静态审查;关联 BUG-075",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "文件共享中心",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\performance\\fileDetail\\index.vue",
+    "static": "已静态审查;关联 BUG-045,BUG-099",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "报表管理",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\reportManager\\index.vue",
+    "static": "已静态审查;关联 BUG-061,BUG-062,BUG-097",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "安全监控分站管理",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\safetyList\\index.vue",
+    "static": "已静态审查;关联 BUG-032,BUG-093",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "安全监控分站管理详情",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\safetyList\\common\\detail.vue",
+    "static": "已静态审查;关联 BUG-032,BUG-093",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "用户日志管理",
+    "map_status": "mapped",
+    "paths": "src\\views\\monitor\\log\\index.vue",
+    "static": "已静态审查;关联 BUG-066,BUG-104",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  },
+  {
+    "module": "报表数据映射",
+    "map_status": "mapped",
+    "paths": "src\\views\\vent\\reportManager\\comment\\reportMap.vue",
+    "static": "已静态审查;关联 BUG-036,BUG-037,BUG-096",
+    "runtime": "阻塞-前端不可达:192.168.1.29:3100 ConnectionRefused;本机 vite 缺 public/index.html 崩溃;后端9999可达但登录需验证码/加密失败,菜单冒烟未执行"
+  }
+]

+ 1652 - 0
docs/_defects.json

@@ -0,0 +1,1652 @@
+[
+  {
+    "module": "235分站监测",
+    "file": "src/views/vent/safetyList/common/detail-235.vue:352-369,608-768,888,958-1013",
+    "title": "235 页面误用 130 协议 API",
+    "severity": "致命",
+    "type": "wrong_api",
+    "symptom": "235 分站参数下发、改名、删除等操作打到 130 接口,控制/配置失败或污染错误协议设备",
+    "root_cause": "从 detail-130 复制后未替换:set130StationData/update130DevName/remove130Device/remove130Substation;api 中亦无对应 235 写接口",
+    "repro": "在 235 监测详情编辑并下发任意参数,观察请求 URL 含 130 路径",
+    "fix_hint": "补齐并改用 235 专用读写/删除 API,移除 130 引用",
+    "id": "BUG-001",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "主风机管控",
+    "file": "src/views/vent/monitorManager/mainFanMonitor/index.vue:1609-1662",
+    "title": "倒机正转/反转共用同一 paramcode",
+    "severity": "致命",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "changeSmoke1 场景下正启动与反启动都下发 CtrlFan1ToFan2 / CtrlFan2ToFan1,无法区分正反转倒机指令",
+    "root_cause": "同文件 changeSmoke 分支正确使用 CtrlFan1ToFan2Forward/Reverse 与 CtrlFan2ToFan1Forward/Reverse,但 changeSmoke1 分支正反转都调用无方向后缀的同一点位",
+    "repro": "风机处于正转/反转运行态触发一键倒机(modalType=changeSmoke1)→ 对比下发 paramcode",
+    "fix_hint": "与 changeSmoke 分支对齐,正转用 *Forward、反转用 *Reverse",
+    "id": "BUG-002",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "喷淋监控系统",
+    "file": "src/views/vent/monitorManager/sprayMonitor/index.vue:68-140",
+    "title": "多路控制按钮共用同一 paramcode/value",
+    "severity": "致命",
+    "type": "wrong_control_payload",
+    "symptom": "急停/补水阀/搅拌阀/组化泵/上料机/搅拌电机/上料自动/喷洒自动等按钮下发同一 paramcode,无法区分控制对象",
+    "root_cause": "operations 全部使用 key='run_auto_sign',且多数 value='0';BasicMonitoring.deviceControl 仅按 key/value 下发",
+    "repro": "打开喷淋监控 → 分别点击不同操作按钮 → 抓包/日志观察 paramcode 全为 run_auto_sign",
+    "fix_hint": "为每个操作配置真实设备参数码(如急停、补水阀、搅拌阀等各自 key),并核对 value 语义",
+    "id": "BUG-003",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/router/helper/routeHelper.ts:21-28,98-113,122-146",
+    "title": "layouts/RouteView 组件文件缺失导致路由无法解析",
+    "severity": "致命",
+    "type": "missing_component",
+    "symptom": "菜单 component 配为 layouts/RouteView 的父级打开空白/路由失败",
+    "root_cause": "src/layouts 下无 RouteView.vue;LayoutMap 未注册;dynamicImport 只扫 views/components",
+    "repro": "后端菜单配置 component=layouts/RouteView 后进入喷雾降尘父路由",
+    "fix_hint": "新增 layouts/RouteView.vue 并加入 LayoutMap;菜单改为已存在布局",
+    "id": "BUG-004",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/common.api.ts:3-10,46",
+    "title": "bjlist 引用不存在的 Api.bjlist",
+    "severity": "致命",
+    "type": "undefined_api_ref",
+    "symptom": "瓦斯管道故障诊断轮询请求 url 为 undefined,列表/曲线无法加载",
+    "root_cause": "enum Api 无 bjlist 成员,但 bjlist() 仍使用 Api.bjlist",
+    "repro": "宝德矿打开瓦斯预警→管道故障诊断,抓包看请求 URL",
+    "fix_hint": "恢复 bjlist='/safety/ventanalyAlarmLog/list' 或改用 warningHistoryList 路径",
+    "id": "BUG-005",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采泵站管控",
+    "file": "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHome.vue:159-178,355-375,329-333",
+    "title": "就地/远程与检修控制 paramcode 对调且入参分支不匹配",
+    "severity": "致命",
+    "type": "inverted_control_mapping",
+    "symptom": "点就地/远程下发 jxmsqh;点检修下发 ykjdqh;传 0 时 handlerType 不赋值仍弹密码框",
+    "root_cause": "changeCtr 写死 jxmsqh、changeMode 写死 ykjdqh;模板传 0/1,函数判 1/2",
+    "repro": "抽采泵站管控点就地/远程/检修开闭→确认密码→抓包 paramcode",
+    "fix_hint": "changeCtr→ykjdqh,changeMode→jxmsqh;统一 0/1 分支",
+    "id": "BUG-006",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "测风装置管控",
+    "file": "src/views/vent/monitorManager/windrectMonitor/windrect.api.ts:59; src/views/vent/monitorManager/windrectMonitor/index.vue:769-771",
+    "title": "测风导出函数实际请求导入接口",
+    "severity": "致命",
+    "type": "export calling wrong import API",
+    "symptom": "一键测风结果导出不会调用 /safety/testwindDetail/exportXls,而是 POST /sys/user/importExcel,导出失败或误触发用户导入接口",
+    "root_cause": "exportXls 实现写成 defHttp.post({ url: Api.importExcel }),而 index.vue 的 exportExcel 直接调用该函数(未使用正确的 getExportUrl)",
+    "repro": "打开测风装置管控 → 触发 exportExcel(id) / 结果导出 → 抓包可见请求 importExcel",
+    "fix_hint": "改为 defHttp.post({ url: Api.exportXls, params }),并确认 method/responseType 与导出一致",
+    "id": "BUG-007",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯日报分析",
+    "file": "src/views/vent/gas/gasReportInspect/index-time.vue:62-82",
+    "title": "空 records 时先访问 [0] 导致挂载崩溃",
+    "severity": "致命",
+    "type": "crash_on_mount",
+    "symptom": "无日报数据时 Cannot read properties of undefined,页面白屏",
+    "root_cause": "先读 tableList[0].id/content,后才判 length;JSON.parse 无空保护",
+    "repro": "瓦斯日报分析在 queryReportList 返回空 records 时进入页面",
+    "fix_hint": "先判空 return;JSON.parse 包 try/catch(index-type/index-lt 同改)",
+    "id": "BUG-008",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/common.api.ts:3-10,46",
+    "title": "bjlist 引用未定义的 Api.bjlist",
+    "severity": "致命",
+    "type": "api",
+    "symptom": "gasWarn 拉取报警历史时 url 为 undefined,请求失败",
+    "root_cause": "enum Api 未声明 bjlist,但 bjlist() 使用 Api.bjlist",
+    "repro": "进入瓦斯监测预警并触发 bjlist 调用 → 控制台/网络见 undefined URL",
+    "fix_hint": "在 Api 中补齐报警历史路径(并与后端对齐),或改为已有正确枚举字段",
+    "id": "BUG-009",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "色谱仪报表分析",
+    "file": "src/views/vent/bundleSpy/bundleSpyTable/index.vue:134-147",
+    "title": "色谱仪报表被硬编码 mock 覆盖真实 API",
+    "severity": "致命",
+    "type": "mock_override",
+    "symptom": "页面恒显示写死的 10月2日假报表,真实 queryReportData 不调用",
+    "root_cause": "getbundleSpyInfoList 被注释,改为本地写死 res 对象",
+    "repro": "打开色谱仪报表分析首页列表 → 数据固定为 10月2日样例,与后端无关",
+    "fix_hint": "恢复 await getbundleSpyInfoList({ type: 'bundleSpy', ...params }) 并删除硬编码",
+    "id": "BUG-010",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "预警联动控制",
+    "file": "src/views/vent/deviceManager/workingFace/workingFace.api.ts:18-21,79-90",
+    "title": "智能管控批量删除/导入导出误指向 /sys/user/*",
+    "severity": "致命",
+    "type": "wrong_endpoint",
+    "symptom": "批删打到用户批量删除接口,可能删错资源或失败;单删走 managesys 正确路径",
+    "root_cause": "deleteBatch/importExcel/exportXls 从用户模块拷贝未改",
+    "repro": "预警联动勾选多条批删,抓包确认 /sys/user/deleteBatch",
+    "fix_hint": "改为 /safety/ventanalyManageSystem/deleteBatch 及对应导入导出路径",
+    "id": "BUG-011",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "130分站监测",
+    "file": "src/views/vent/safetyList/common/detail-130.vue:865-892",
+    "title": "devInfoList 空指针(同 index/detail)",
+    "severity": "严重",
+    "type": "null_crash",
+    "symptom": "130 分站无子设备时列表处理抛错",
+    "root_cause": "el.children.forEach 未处理 null/undefined devInfoList",
+    "repro": "打开 130 详情页并选中无设备分站",
+    "fix_hint": "遍历前 `el.children = el.devInfoList || []`",
+    "id": "BUG-012",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "130分站监测",
+    "file": "src/views/vent/safetyList/safetyList.api.ts:23-25,72,76",
+    "title": "删除130分站/传感器误调158删除接口",
+    "severity": "严重",
+    "type": "api",
+    "symptom": "130 分站删除可能删错资源或后端拒绝,与 158 接口串用",
+    "root_cause": "remove130Substation/remove130Device 分别使用 Api.remove158Substation/Api.remove158Device,尽管 enum 已定义 remove130*",
+    "repro": "130 分站详情执行删除分站或传感器 → 查看请求 URL 是否含 remove158*",
+    "fix_hint": "改为 Api.remove130Substation / Api.remove130Device",
+    "id": "BUG-013",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "158分站监测",
+    "file": "src/views/vent/safetyList/common/detail.vue:977-1002,1013-1022",
+    "title": "devInfoList 为空时 forEach 崩溃",
+    "severity": "严重",
+    "type": "null_crash",
+    "symptom": "部分分站无子设备时详细信息表加载失败",
+    "root_cause": "el.children = el.devInfoList 后未判空直接 forEach(getStationList1/getStationListAll)",
+    "repro": "选择无测点的分站查看详细信息",
+    "fix_hint": "使用可选链或默认空数组后再遍历",
+    "id": "BUG-014",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "一张表",
+    "file": "src/views/vent/monitorManager/deviceMonitor/staticSheets/gasSheet.vue:1-151",
+    "title": "瓦斯一张表静态硬编码 HTML,无实时数据",
+    "severity": "严重",
+    "type": "data",
+    "symptom": "瓦斯参数表固定静态内容,非实时监测",
+    "root_cause": "硬编码表格,无数据请求",
+    "repro": "打开瓦斯一张表观察数据不更新",
+    "fix_hint": "接入瓦斯监测/抽采接口动态填充",
+    "id": "BUG-015",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "光纤测温监测",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:239-243",
+    "title": "光纤弹窗 Object.keys(readData) 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "设备无 readData 时打开弹窗直接 TypeError",
+    "root_cause": "未判断 item.readData 即 Object.keys(item.readData)",
+    "repro": "选中 readData 为空的光纤设备打开详情",
+    "fix_hint": "if (!item.readData) return; 后再解析分段温度",
+    "id": "BUG-016",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "光纤测温监测",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:49,169-188,232-257",
+    "title": "光纤详情风险等级与预警历史写死假数据",
+    "severity": "严重",
+    "type": "mock hardcode replacing real API",
+    "symptom": "风险等级恒为“低风险”,预警历史永远是测点6/318℃等假记录,不随真实报警变化",
+    "root_cause": "模板写死低风险;warningConfig.data 硬编码数组,watch 未用真实告警填充",
+    "repro": "打开光纤测温弹窗 → 对比真实告警与滚动板内容",
+    "fix_hint": "绑定设备真实风险字段与告警历史接口/数据",
+    "id": "BUG-017",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "喷淋监控系统",
+    "file": "src/components/vent/BasicMonitoring.vue:19,193-201",
+    "title": "操作列表 :key 冲突 + 空场景崩溃",
+    "severity": "严重",
+    "type": "vue_key_collision/null_crash",
+    "symptom": "喷淋多个按钮共用 key 导致 DOM 复用异常;无场景数据时页面直接抛错白屏",
+    "root_cause": "v-for 使用 item.key 作唯一键但喷淋键重复;getSysDataSource 无空数组守卫直接取 options[0].id",
+    "repro": "1) 打开喷淋页观察按钮交互状态错乱;2) 后端返回空 records 时进入页面立即报错",
+    "fix_hint": "key 使用 label 或唯一 id;取首项前判断 records.length",
+    "id": "BUG-018",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/views/vent/home/configurable/dust.vue:87-93",
+    "title": "服务端配置被测试数据覆盖且只用 Mock",
+    "severity": "严重",
+    "type": "hardcoded_override",
+    "symptom": "粉尘首页始终展示 testConfigDust + BDDustMock,真实监测数据不刷新",
+    "root_cause": "fetchConfigs('dust') 后强制 configs=testConfigDust,并用 Promise.resolve(BDDustMock) 代替 getHomeData",
+    "repro": "任意环境打开粉尘可配置首页,对比接口与页面数据源",
+    "fix_hint": "生产移除测试覆盖,恢复 getHomeData 轮询",
+    "id": "BUG-019",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "喷雾降尘监控",
+    "file": "src/views/vent/home/configurable/dustControl.vue:53-54",
+    "title": "错误 pageType 拉取后再覆盖测试配置",
+    "severity": "严重",
+    "type": "wrong_param/hardcoded_override",
+    "symptom": "降尘管控页配置与粉尘业务不匹配,最终仍被本地测试配置覆盖",
+    "root_cause": "fetchConfigs('mine_fire') 后 configs.value=testConfigDustControl",
+    "repro": "打开 dustControl 页检查 configuration 请求 pageType 与最终 configs",
+    "fix_hint": "使用正确粉尘 pageType,并按环境决定是否使用测试配置",
+    "id": "BUG-020",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:311",
+    "title": "gasGlFaultDia 无防护 JSON.parse 可抛错",
+    "severity": "严重",
+    "type": "crash_on_mount",
+    "symptom": "缺/非法 gasGlFaultDia 时脚本异常,故障诊断页中断",
+    "root_cause": "JSON.parse(data.readData.gasGlFaultDia) 无空值与 try/catch",
+    "repro": "故障诊断选中无 gasGlFaultDia 的设备",
+    "fix_hint": "JSON.parse(x||'{}') 并 catch 给默认坐标",
+    "id": "BUG-021",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:239-250",
+    "title": "从巷道阻力分析切回通风监测后轮询不恢复",
+    "severity": "严重",
+    "type": "timer_not_restarted",
+    "symptom": "切回通风监测后顶部/测点停止自动刷新",
+    "root_cause": "btnClick(0) 只 clearNetTimer+getMenuList,未 getMonitor(true)",
+    "repro": "通风监测→巷道阻力→再点通风监测,等待>3s 看是否更新",
+    "fix_hint": "ind===0 时调用 getMonitor(true)",
+    "id": "BUG-022",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/fireWarn.vue:74-83,148-157,173-185,215-217",
+    "title": "匿名 setTimeout 未清理且 getMonitor 不先 clear",
+    "severity": "严重",
+    "type": "timer_leak",
+    "symptom": "快速切换/离开后仍请求 sysTypeWarn;可能双轮询",
+    "root_cause": "cardClick/reset 的 setTimeout 无句柄;getMonitor 赋值前不清旧 timer",
+    "repro": "火灾预警连点内因/外因后返回首页,抓包仍见请求",
+    "fix_hint": "保存 delay timer 并在 unmount clear;getMonitor 开头 clearPollTimer",
+    "id": "BUG-023",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/common/external-fourc.vue:147-153",
+    "title": "四参外因温度误绑 fireval",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "温度监测显示错误/空",
+    "root_cause": "与 threec 相同拷贝错误 val: el.readData.fireval",
+    "repro": "打开外因四参温度列表",
+    "fix_hint": "改为 temperature",
+    "id": "BUG-024",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:346-365",
+    "title": "宝德矿第三 Tab 映射到瓦斯参数而非预警指标",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "菜单第三项「预警指标」点击却渲染 gasParamter(wscs)",
+    "root_cause": "getMonitorComponent(宝德)=[预警监测,故障诊断,预警指标];btnClick ind===2 固定 isShow='wscs'",
+    "repro": "sysOrgCode=sdmtjtbdmk 打开瓦斯预警点第三个类型按钮",
+    "fix_hint": "宝德 ind===2 → yjzb;布尔台 ind===2 保持 wscs",
+    "id": "BUG-025",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:368-377",
+    "title": "宝德预警监测卡片误走故障诊断轮询",
+    "severity": "严重",
+    "type": "wrong_comparison",
+    "symptom": "预警监测点卡片会走 bjlist,菜单被故障设备覆盖",
+    "root_cause": "cardClick 仅按 isflag=='1' 分支,未看 isShow/activeIndex",
+    "repro": "宝德→预警监测→切换工作面卡片,观察是否请求 bjlist",
+    "fix_hint": "yjjc→getMonitor;gzzd→getMonitor1",
+    "id": "BUG-026",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/alarmHistoryTable.vue:166-167",
+    "title": "未传 deviceType 时 strtype 变成 \"undefined*\"",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "设备预警报警历史过滤错误,列表空或错数据",
+    "root_cause": "beforeFetch: props.deviceType + '*';deviceWarn.vue:43 未传 deviceType",
+    "repro": "设备监测预警→报警历史,检查请求 strtype",
+    "fix_hint": "传入正确 deviceType,或空时不拼 strtype",
+    "id": "BUG-027",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/common/external-threec.vue:118-124",
+    "title": "温度传感器列表误绑 fireval",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "外因火灾温度卡片显示火焰字段/空值",
+    "root_cause": "temperature.map 使用 readData.fireval;mainWell 正确用 temperature",
+    "repro": "外因火灾 temperature 有值、fireval 空时看温度卡",
+    "fix_hint": "改为 el.readData.temperature(fourc:147-153 同步)",
+    "id": "BUG-028",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:193",
+    "title": "甲烷显示运算符优先级错误",
+    "severity": "严重",
+    "type": "wrong_operator_precedence",
+    "symptom": "gasC 为空时显示 \"undefined%\" 而非 '--'",
+    "root_cause": "el.readData.gasC + '%' || '--' 中字符串恒 truthy",
+    "repro": "测点 gasC 缺失时看左侧甲烷值",
+    "fix_hint": "(gasC!=null&&gasC!=='') ? gasC+'%' : '--'",
+    "id": "BUG-029",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/dustWarn.vue:131-143,166-176",
+    "title": "粉尘预测曲线每轮 push 不清理导致无限膨胀",
+    "severity": "严重",
+    "type": "timer_state_leak",
+    "symptom": "停留越久曲线点越多、内存升高",
+    "root_cause": "fillChartByIndex 每秒 echartYc.push;仅 topAreaClick 会清空",
+    "repro": "粉尘预警停留数分钟观察 echartYc 长度",
+    "fix_hint": "每次 fill 前重置 echartYc,或替换最新点",
+    "id": "BUG-030",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:10",
+    "title": "返回按钮权限取反",
+    "severity": "严重",
+    "type": "inverted_permission",
+    "symptom": "有 gasWarn:return 权限看不到返回;无权限反而显示",
+    "root_cause": "v-if=\"!hasPermission(...)\";对照 deviceMonitorWarn 为正逻辑",
+    "repro": "分配 gasWarn:return 后对比返回按钮显隐",
+    "fix_hint": "改为 hasPermission;fire/dust/ventilate/device/waterLevel 同步",
+    "id": "BUG-031",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "安全监控分站管理",
+    "file": "src/views/vent/safetyList/index.vue:234-257,408-417",
+    "title": "卸载引用未定义 timer + children 空指针 + 分页 total 错误",
+    "severity": "严重",
+    "type": "reference_error/null_crash",
+    "symptom": "离开页面报 timer is not defined;devInfoList 为空时列表渲染崩溃;分页总数异常",
+    "root_cause": "timer 声明被注释但 onUnmounted 仍引用;el.children=el.devInfoList 后直接 forEach;res.total 在数组结果上常为 undefined",
+    "repro": "进入页再离开;返回含 null devInfoList 的分站;观察 pagination.total",
+    "fix_hint": "删除或恢复 timer;`(el.devInfoList||[]).forEach`;按接口实际结构取 records/total",
+    "id": "BUG-032",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "密闭监测系统",
+    "file": "src/views/vent/monitorManager/obfurageMonitor/index.vue:89-138",
+    "title": "空数据崩溃且切换系统不刷新关联设备",
+    "severity": "严重",
+    "type": "null_crash/stale_state",
+    "symptom": "无密闭系统/无关联设备时崩溃;切换密闭点后历史页设备 Tab 仍是旧设备",
+    "root_cause": "直接访问 msgTxt[0]、deviceArr[0];getSelectRow 只改 optionValue,未调用 getDeviceList",
+    "repro": "空数据进页;有多套密闭→切换后打开历史监测看设备按钮未更新",
+    "fix_hint": "空数组守卫;getSelectRow 内调用 getDeviceList()",
+    "id": "BUG-033",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "局部风机管控",
+    "file": "src/views/vent/monitorManager/fanLocalMonitor/index.vue:782-791",
+    "title": "风筒直径控制按钮重复且同 key",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "控制区出现两个相同“风筒直径”按钮,key 均为 diameter,行为完全重复",
+    "root_cause": "leftBtnArr 中 diameter 配置项被复制粘贴两次",
+    "repro": "开启 fanLocal:diameter → 顶部控制按钮可见重复项",
+    "fix_hint": "删除重复配置;若本意为主/备直径,需不同 key 与 paramcode",
+    "id": "BUG-034",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "工作面来压预警",
+    "file": "src/views/vent/monitorManager/betKy/index.vue:112-146,148-154,258-262",
+    "title": "矿压监测轮询逻辑错误且特定矿用假数据",
+    "severity": "严重",
+    "type": "mock hardcode + setInterval/setTimeout poll without proper clear",
+    "symptom": "A02A02 矿强制使用 ceshi.json;轮询前把 timer 置 null 未 clearTimeout,chartData 每次 push 不清理导致曲线数据膨胀错乱;卸载用 clearInterval 清 setTimeout",
+    "root_cause": "chartData 每轮 push 不清空;timer=setTimeout 却 clearInterval;重启只置 null 不 clear",
+    "repro": "返回含 readData=null 的 Minepressure 列表",
+    "fix_hint": "每轮 chartData=[];统一 clearTimeout 并先 clear 再置空",
+    "id": "BUG-035",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/reportMap.vue:82-119,135-145",
+    "title": "reactive 表单被整体重赋值 + 部门树空 children 崩溃",
+    "severity": "严重",
+    "type": "reactivity_break/null_crash",
+    "symptom": "新增/编辑后表单状态异常;部门节点无 children 时查询部门树直接报错",
+    "root_cause": "handleAdd/handleEdit 执行 formState = { ... },替换了 reactive 代理",
+    "repro": "编辑一条映射再点新增观察表单残留;部门树缺 children 的节点触发加载",
+    "fix_hint": "用 Object.assign(formState, ...) 或重置字段;forEach 前守卫 children",
+    "id": "BUG-036",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/report-modal.vue:135-151",
+    "title": "编辑时 JSON.parse(mineCells) 在非字符串时抛错",
+    "severity": "严重",
+    "type": "type_error",
+    "symptom": "编辑已有映射弹窗打开失败或控制台 TypeError",
+    "root_cause": "watch 中无条件 JSON.parse(formStates.mineCells);接口若已反序列化为数组则解析失败;且 Object.assign 不会清除旧 id",
+    "repro": "打开编辑,当 record.mineCells 为数组或空时复现",
+    "fix_hint": "typeof===string 再 parse,数组则直接使用;新增时显式清空 id",
+    "id": "BUG-037",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采泵站管控",
+    "file": "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:50-65",
+    "title": "setInterval 用 clearTimeout 清理导致泄漏",
+    "severity": "严重",
+    "type": "timer_not_cleared",
+    "symptom": "离开监测图表后仍每 2s 推数据",
+    "root_cause": "setInterval + onUnmounted clearTimeout",
+    "repro": "进入监测图表后切走,观察回调是否继续",
+    "fix_hint": "改为 clearInterval(timer)",
+    "id": "BUG-038",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采泵站管控",
+    "file": "src/views/vent/gas/gasPumpMonitor/index.vue:57-68",
+    "title": "井下泵模型切换后被无条件覆盖为地上泵",
+    "severity": "严重",
+    "type": "copy_paste_bug",
+    "symptom": "选中 pump_under* 仍加载地上 gasPump 三维",
+    "root_cause": "if/else 设类型后末尾又 setModelType('gasPump')",
+    "repro": "抽采泵站监测切到井下泵站设备",
+    "fix_hint": "删除末尾无条件 setModelType('gasPump')",
+    "id": "BUG-039",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采达标评判",
+    "file": "src/views/vent/gas/gasAssessment/components/gasUnit.vue:27,55,73-75",
+    "title": "单元混量/纯量图表写死 mock",
+    "severity": "严重",
+    "type": "mock_override",
+    "symptom": "图表恒为本地假数据,真实监测不驱动",
+    "root_cause": "CustomChart 绑定 mockGasUnitHlData/mockGasUnitClData",
+    "repro": "打开抽采单元对比接口与图表数据源",
+    "fix_hint": "用接口历史数据替换 mock",
+    "id": "BUG-040",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采达标评判",
+    "file": "src/views/vent/gas/gasAssessment/components/gasControl.vue:32-40,88-112",
+    "title": "调控页 getMonitor 空转且阀门无绑定",
+    "severity": "严重",
+    "type": "incomplete",
+    "symptom": "测点值始终为空;阀门开度输入/控制按钮无事件与接口",
+    "root_cause": "getMonitor 仅 setTimeout 自调用不请求数据;阀门区无 @click/API",
+    "repro": "打开抽采达标评判-调控相关页 → 测点 '-'、按钮无响应",
+    "fix_hint": "接入监测 list API 填充 dataSource;为阀门控制绑定下发接口",
+    "id": "BUG-041",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采达标评判",
+    "file": "src/views/vent/gas/gasAssessment/index.vue:43",
+    "title": "进入抽采单元页未传入 unitId",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "侧栏 list({ids}) 为空,实时数据无法对应选中单元",
+    "root_cause": "<gasUnit/> 未绑定 :unitId=\"activeUnitId\"",
+    "repro": "达标评判点选单元后看 list 请求 ids",
+    "fix_hint": "<gasUnit :unitId=\"activeUnitId\" />",
+    "id": "BUG-042",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采达标评判/瓦斯抽采单元",
+    "file": "src/views/vent/gas/gasAssessment/components/{gasEcharts,gasUnit,gasPipingEcharts}.vue:gasEcharts 14-47; gasUnit 27,55; gasPipingEcharts 13-99",
+    "title": "图表永久绑定 mock* 数据",
+    "severity": "严重",
+    "type": "data",
+    "symptom": "抽采单元/管网相关图表始终显示 gasAssessment.data 中的 mock 曲线/饼图,即使列表接口已取到真实测点",
+    "root_cause": "模板 :chart-data/:dataSource 直接绑定 mockGasUnitData/mockPieData/mockGasPiping* 等,未接入接口结果",
+    "repro": "进入抽采达标评判相关子页 → 图表不随实时监测变化",
+    "fix_hint": "用接口返回历史/累计数据替换 mock 绑定;gasUnit 已有 list(),应生成 chart-data",
+    "id": "BUG-043",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "掘进面智能管控",
+    "file": "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceHome.vue:254,262-271",
+    "title": "掘进面首页无条件解包 warnInfo/readData",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "缺 dustS/fireS/gasS/synthesizeS/ventS、缺 surface_history、或缺 location.readData 时页面直接崩溃",
+    "root_cause": "无守卫直接访问 res['warnInfo'][x]['devices']、res['surface_history'][0]、data['readData']['flen']",
+    "repro": "接口缺任一 warn 分组或 location.readData → 打开掘进面主页",
+    "fix_hint": "逐层可选链;缺省赋空数组/空对象",
+    "id": "BUG-044",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "文件共享中心",
+    "file": "src/views/vent/performance/fileDetail/index.vue:292-314,367-377,387",
+    "title": "空树上标崩溃 + 可空文件上传 + nodeParam 丢失响应式",
+    "severity": "严重",
+    "type": "null_crash/invalid_upload",
+    "symptom": "无目录时白屏;未选文件仍可点确定上传;树节点切换后表格参数可能异常",
+    "root_cause": "listArr[0] 无守卫;handleOk 不校验 fileList;nodeParam=node 重赋放弃 reactive",
+    "repro": "空目录数据进页;打开上传不选文件点确定;切换目录观察列表 parentId",
+    "fix_hint": "空树提示;上传前校验 fileList.length;Object.assign(nodeParam, node)",
+    "id": "BUG-045",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/components/nitrogenHome_ln.vue:341-349",
+    "title": "监测数据忽略选中系统ID",
+    "severity": "严重",
+    "type": "wrong_data_binding",
+    "symptom": "切换注氮系统后仍展示 msgTxt[0] 数据,监控内容与下拉选择不一致",
+    "root_cause": "getDataSource(systemID) 入参未用于请求,固定取 res.msgTxt[0].datalist",
+    "repro": "配置≥2套注氮系统→切换下拉→数据不随 systemId 变化",
+    "fix_hint": "按 systemID/deviceId 过滤或带参请求对应系统数据",
+    "id": "BUG-046",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "智能注氮系统",
+    "file": "src/views/vent/monitorManager/compressor/index.vue:93-126",
+    "title": "空列表崩溃且 modalType 未随系统类型切换",
+    "severity": "严重",
+    "type": "null_crash/stale_config",
+    "symptom": "无注氮系统时白屏;依赖 modalType 的矿端组件始终按 nitrogenUnderground 建模",
+    "root_cause": "options.value[0]['id'] 无空判断;changeModalType 中 modalType 赋值被注释,仅改了 moduleTypeName",
+    "repro": "空数据进页崩溃;潞宁等使用 modalType 的矿切换空压机/制氮机后模型类型不变",
+    "fix_hint": "空 records 提前 return;恢复按 strsystype 设置 modalType",
+    "id": "BUG-047",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "智能注浆系统",
+    "file": "src/views/vent/monitorManager/groutMonitor/index.vue:110-119,67,86",
+    "title": "空数据崩溃且 currentDeviceType 永不赋值",
+    "severity": "严重",
+    "type": "null_crash/dead_state",
+    "symptom": "无注浆系统时白屏;传给 groutHome 的 device-type 恒为空字符串",
+    "root_cause": "options.value[0]['id'] 无守卫;deviceChange 只写 deviceType,从未写入 currentDeviceType",
+    "repro": "空列表进页崩溃;有数据时检查 groutHome props.deviceType 为空",
+    "fix_hint": "空 records 保护;deviceChange/getSelectRow 同步 currentDeviceType",
+    "id": "BUG-048",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "机电硐室管控",
+    "file": "src/views/vent/home/configurable/electroChamber.vue:86-99,29-50",
+    "title": "拉取配置后强制覆盖为本地测试配置且历史无设备ID",
+    "severity": "严重",
+    "type": "hardcoded_override/missing_param",
+    "symptom": "线上始终使用 testConfigElectro;切历史 Tab 时 deviceId 常为空导致查询无效",
+    "root_cause": "fetchConfigs 成功后 configs.value=testConfigElectro;optionValue 仅来自路由 query,无设备选择赋值",
+    "repro": "非 A02A02 环境打开页面看配置是否被测试数据覆盖;无 query.id 切历史记录",
+    "fix_hint": "生产去掉测试覆盖;补充硐室/系统选择并写入 optionValue",
+    "id": "BUG-049",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "束管日报分析",
+    "file": "src/views/vent/bundleSpy/bundleSpyTable/index.vue; vent/bundle/bundleMonitorTable/index.vue:bundleSpy:108-109; bundle:101-102",
+    "title": "保德 sysOrgCode 大小写错误导致专用列永不命中",
+    "severity": "严重",
+    "type": "copy_paste_orgcode",
+    "symptom": "保德落到 default 列配置,专用字段不显示",
+    "root_cause": "写 case 'sdmtjtBdmk';全库其余为 'sdmtjtbdmk'",
+    "repro": "sysOrgCode=sdmtjtbdmk 打开色谱仪/束管日报",
+    "fix_hint": "统一改为 sdmtjtbdmk",
+    "id": "BUG-050",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "束管日报分析",
+    "file": "src/views/vent/bundle/bundleMonitorTable/bundle-table.data.ts:595-610",
+    "title": "保德束管 NO₂ 最小值 dataIndex 写成 no22_max",
+    "severity": "严重",
+    "type": "wrong_column_dataIndex",
+    "symptom": "NO₂最小值空白或错值",
+    "root_cause": "最小值 dataIndex:'no22_max',key/dataIndex 交叉贴错",
+    "repro": "保德束管日报对比 no2_min/no2_max 与三列",
+    "fix_hint": "最大值 no2_max;最小值 no2_min",
+    "id": "BUG-051",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "束管日报分析",
+    "file": "src/views/vent/bundle/bundleMonitorTable/bundle-table.data.ts:1465-1472,1848-1855",
+    "title": "寸草塔一矿/哈拉沟 O₂最大值列绑定 o2_min",
+    "severity": "严重",
+    "type": "wrong_column_dataIndex",
+    "symptom": "标题最大值实际显示最小值",
+    "root_cause": "title:最大值 却 dataIndex:'o2_min'",
+    "repro": "对应矿打开束管日报对比 o2_max/o2_min",
+    "fix_hint": "改为 dataIndex:'o2_max'",
+    "id": "BUG-052",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "束管日报分析",
+    "file": "src/views/vent/bundle/bundleMonitorTable/index.vue:103-104,453",
+    "title": "补连塔图表分支 orgCode 写成 sdmtjtBltmk",
+    "severity": "严重",
+    "type": "copy_paste_orgcode",
+    "symptom": "表格用 Bltcolumns 正确,柱状图落入 default",
+    "root_cause": "computedColumns 用 sdmtjtbltmk,getSeriesConfig 用 sdmtjtBltmk",
+    "repro": "sysOrgCode=sdmtjtbltmk 对比表头与图例",
+    "fix_hint": "图表 case 改为 sdmtjtbltmk",
+    "id": "BUG-053",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "火灾监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/fireWarn.vue:4",
+    "title": "返回按钮权限判断取反(!hasPermission('fireWarn:return'))",
+    "severity": "严重",
+    "type": "权限逻辑错误",
+    "symptom": "有 *:return 权限的用户看不到返回;无权限用户反而可见(与 deviceMonitorWarn 正确写法相反)",
+    "root_cause": "使用 v-if=\"!hasPermission('xxx:return')\";对照 deviceMonitorWarn 应为正向 hasPermission",
+    "repro": "分别用有/无 gasWarn:return 等权限账号打开预警页,观察返回按钮显隐",
+    "fix_hint": "去掉 !,改为 v-if=\"hasPermission('...:return')\"",
+    "id": "BUG-054",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "灾变应急控制",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:196-226",
+    "title": "工作面详情多项共用同一数据 code",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "工作面编号/采区/煤层都显示 dTotalArea;长度/走向/采高都显示 totallength",
+    "root_cause": "analysisDetailDataList 多项复用相同 code,未映射独立字段",
+    "repro": "打开灾变应急分析详情区 → 观察多行数值是否雷同",
+    "fix_hint": "为每项配置正确业务字段 code,并在 pageData 中补齐对应值",
+    "id": "BUG-055",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "灾变应急控制",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:273-275",
+    "title": "应急解算局部阻力同样误绑 dHNature",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "灾变应急巷道阻力表局部阻力错误",
+    "root_cause": "与 network 相同的复制错误:dHLocal: item['dHNature']",
+    "repro": "进入灾变应急页加载解算结果 → 查看巷道阻力列",
+    "fix_hint": "改为 item['dHLocal']",
+    "id": "BUG-056",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "灾变应急控制",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/emergency/index.vue:314-321",
+    "title": "应急页传感器 readData 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "同网络页,缺 readData 时应急页崩溃",
+    "root_cause": "item['readData']['va'] 无空判断",
+    "repro": "推送缺 readData 的 monitors → 打开应急页",
+    "fix_hint": "对 readData 做空对象兜底",
+    "id": "BUG-057",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检业务分析",
+    "file": "src/views/vent/gas/gasAnalysis/index.vue:177-182,216-219",
+    "title": "列表成功后强制 pagination.current=1 导致分页失效",
+    "severity": "严重",
+    "type": "pagination_logic_bug",
+    "symptom": "翻到第 2 页后被打回第 1 页",
+    "root_cause": "gasReportLogLists 在有 records 时无条件 current=1",
+    "repro": "业务分析多页数据点第 2 页",
+    "fix_hint": "删除该赋值;仅查询/重置时置 1",
+    "id": "BUG-058",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检地点管理",
+    "file": "src/views/vent/gas/gasInspectNonfc/components/inspectEdit.vue:12-14,79-81,71-76",
+    "title": "区队下拉缺 value 且整对象重赋值打断响应式",
+    "severity": "严重",
+    "type": "nfc_nonfc_copy_paste",
+    "symptom": "提交可能把区队名当 id;二次编辑表单不刷新",
+    "root_cause": "option 无 :value;formStateEdit=Object.assign 重赋值丢失 reactive 绑定",
+    "repro": "Nonfc 编辑改区队提交看 payload;连续编辑两条",
+    "fix_hint": "补 :value=\"item.value\";Object.assign(formStateEdit, newV) 原地更新",
+    "id": "BUG-059",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检地点管理(NFC)",
+    "file": "src/views/vent/gas/gasInspect/index.vue:66-75",
+    "title": "早/中/晚是否巡检真假分支都渲染「是」",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "未巡检也显示「是」,状态失真",
+    "root_cause": "text=='1' 与 v-else 内均写「是」",
+    "repro": "NFC 地点管理查看未巡检班次列",
+    "fix_hint": "else 显示「否」;对齐 Nonfc 字段约定",
+    "id": "BUG-060",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检报表管理",
+    "file": "src/views/vent/gas/gasReport/index.vue:357-440",
+    "title": "审核/导出异常校验 else-if 导致任一气体合格即放行",
+    "severity": "严重",
+    "type": "inverted_validation_logic",
+    "symptom": "O2 超限但 CO 合格仍可审核通过;多行以最后一行结果为准",
+    "root_cause": "getTs 对 O2/CO/CO2/T/CH4 用 else-if;forEach return 不能结束函数",
+    "repro": "仅 O2 异常其余合格→点审核通过",
+    "fix_hint": "全部字段均在阈内才放行;任异常即 true",
+    "id": "BUG-061",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检报表管理",
+    "file": "src/views/vent/gas/gasReport/index.vue:271-274",
+    "title": "巡检图片 Blob 二次封装错误",
+    "severity": "严重",
+    "type": "wrong_blob_usage",
+    "symptom": "查看班次图片失败或 Failed to construct 'Blob'",
+    "root_cause": "gasServerImg 已是 blob,又 new Blob(res,...);构造需 Array",
+    "repro": "日报管理点夜/早/中班「查看」",
+    "fix_hint": "URL.createObjectURL(res) 或 new Blob([res],...)",
+    "id": "BUG-062",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:5",
+    "title": "返回按钮权限判断取反(!hasPermission('gasWarn:return'))",
+    "severity": "严重",
+    "type": "权限逻辑错误",
+    "symptom": "有 *:return 权限的用户看不到返回;无权限用户反而可见(与 deviceMonitorWarn 正确写法相反)",
+    "root_cause": "使用 v-if=\"!hasPermission('xxx:return')\";对照 deviceMonitorWarn 应为正向 hasPermission",
+    "repro": "分别用有/无 gasWarn:return 等权限账号打开预警页,观察返回按钮显隐",
+    "fix_hint": "去掉 !,改为 v-if=\"hasPermission('...:return')\"",
+    "id": "BUG-063",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯管网管控",
+    "file": "src/views/vent/gas/gasPipeNet/index.vue:142-147",
+    "title": "管网阀门控制提交未调控制接口",
+    "severity": "严重",
+    "type": "undefined_api_call",
+    "symptom": "点确定只 toast 表单 JSON,阀门无动作",
+    "root_cause": "submitHandler 仅 message.success,无 deviceControl",
+    "repro": "管网管控→阀门控制→提交",
+    "fix_hint": "接入泵站同款控制 API",
+    "id": "BUG-064",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯钻孔监测",
+    "file": "src/views/vent/gas/gasZk/index.vue:61-79",
+    "title": "setInterval 回调内再 startPolling 造成重叠轮询",
+    "severity": "严重",
+    "type": "timer_logic_bug",
+    "symptom": "慢网时 /drill/get/status 并发堆积",
+    "root_cause": "interval 不等待完成可再次触发;成功后又 stop+new interval",
+    "repro": "打开钻孔监测并限速网络观察并发",
+    "fix_hint": "改为 await 后 setTimeout 串行轮询",
+    "id": "BUG-065",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "用户日志管理",
+    "file": "src/views/monitor/log/index.vue:2,56-84",
+    "title": "v-modal 拼写错误 + 登录统计破坏 searchInfo 响应式",
+    "severity": "严重",
+    "type": "typo/reactivity_break",
+    "symptom": "Tab 无法双向绑定;切到“登录统计”后查询条件失效、列表参数丢失 logType",
+    "root_cause": "模板写 v-modal 而非 v-model;case '4' 执行 searchInfo={} 丢掉 reactive 代理",
+    "repro": "打开日志页切换 Tab;切到登录统计后再查询",
+    "fix_hint": "改为 v-model;用 Object.keys 清空或重置字段,禁止重赋 searchInfo",
+    "id": "BUG-066",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "皮带巷管控系统",
+    "file": "src/views/vent/monitorManager/beltTunMonitor/components/beltTunHome.vue:260-268",
+    "title": "皮带巷首页 warnInfo/sysInfo 无空保护",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "sysInfo 或某类 warn 分组缺失时页面加载失败",
+    "root_cause": "直接 Object.assign(res['sysInfo'], res['sysInfo']['readData']) 与 warnInfo.*.devices",
+    "repro": "返回不完整 beltTun 监测包 → 打开皮带巷主页",
+    "fix_hint": "增加空判断与默认值",
+    "id": "BUG-067",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "粉尘参数一张表",
+    "file": "src/views/vent/monitorManager/deviceMonitor/staticSheets/dustSheet.vue:1-103",
+    "title": "粉尘参数一张表静态硬编码 HTML,无实时数据",
+    "severity": "严重",
+    "type": "data",
+    "symptom": "粉尘参数表固定静态内容,非实时监测",
+    "root_cause": "硬编码表格,无数据请求",
+    "repro": "打开粉尘参数一张表观察数据不更新",
+    "fix_hint": "接入粉尘监测接口动态填充",
+    "id": "BUG-068",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "粉尘报表分析",
+    "file": "src/views/vent/dust/dustMonitorTable/index.vue:317-320,510-513",
+    "title": "保德当日粉尘总体最大值误用 zcjqpj/hcjqpj",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "当日分析最大值恒 -Infinity 或字段映射失败",
+    "root_cause": "BdMaxValues 用 qc/hc;overallBdMaxValues 误用布尔台字段",
+    "repro": "保德粉尘报表切「当日粉尘情况分析」",
+    "fix_hint": "overallBdMaxValues 改为 qc/hc",
+    "id": "BUG-069",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "粉尘报表分析",
+    "file": "src/views/vent/dust/dustMonitorTable/index.vue:269-270,429-436,472-475",
+    "title": "哈拉沟分组键 ccdd 被最大值循环改写成 jcdd",
+    "severity": "严重",
+    "type": "logic_state",
+    "symptom": "工作场所下拉变成测点名,过滤错乱",
+    "root_cause": "分组 gzcs=ccdd,HlgMaxValues 更新时 gzcs=item.jcdd 覆盖",
+    "repro": "哈拉沟粉尘报表看工作场所下拉与过滤",
+    "fix_hint": "更新最大值时不要用 jcdd 覆盖 gzcs",
+    "id": "BUG-070",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "粉尘监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/dustWarn.vue:6",
+    "title": "返回按钮权限判断取反(!hasPermission('dustWarn:return'))",
+    "severity": "严重",
+    "type": "权限逻辑错误",
+    "symptom": "有 *:return 权限的用户看不到返回;无权限用户反而可见(与 deviceMonitorWarn 正确写法相反)",
+    "root_cause": "使用 v-if=\"!hasPermission('xxx:return')\";对照 deviceMonitorWarn 应为正向 hasPermission",
+    "repro": "分别用有/无 gasWarn:return 等权限账号打开预警页,观察返回按钮显隐",
+    "fix_hint": "去掉 !,改为 v-if=\"hasPermission('...:return')\"",
+    "id": "BUG-071",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "综采面智能管控",
+    "file": "src/views/vent/monitorManager/workFaceMonitor/components/workFaceHome.vue:251-254",
+    "title": "定位列表读取 readData.flen 空指针",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "location 设备无 readData 时过滤阶段抛错,后续监控数据不完整",
+    "root_cause": "locationData.push 中直接 data['readData']['flen']",
+    "repro": "location.datalist 含 readData=null 的项",
+    "fix_hint": "使用 data?.readData?.flen ?? '-'",
+    "id": "BUG-072",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "综采面智能管控",
+    "file": "src/views/vent/monitorManager/workFaceMonitor/components/workFaceHome.vue:262-276",
+    "title": "综合预警判断键错误且可能空指针",
+    "severity": "严重",
+    "type": "null deref / wrong field mapping",
+    "symptom": "用 warnInfo.warnInfo 判断却读取 synthesizeS;键不匹配时综合预警不更新,或 synthesizeS 缺失时崩溃;surface_history/sysInfo 亦缺保护",
+    "root_cause": "条件写成 res['warnInfo']['warnInfo'];并对 surface_history[0]、sysInfo.readData 无空保护",
+    "repro": "返回缺 synthesizeS 或 surface_history 为空的综采面数据",
+    "fix_hint": "条件改为 synthesizeS;对各嵌套字段做空判断",
+    "id": "BUG-073",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "色谱仪报表分析",
+    "file": "src/views/vent/bundleSpy/bundleSpyTable/index.vue:237-241,386-390",
+    "title": "活鸡兔/寸草塔二矿图表 O₂闭内 误绑 CH₄ 数据",
+    "severity": "严重",
+    "type": "wrong_field_binding",
+    "symptom": "图例 O₂闭内 柱状与 CH₄闭内完全相同",
+    "root_cause": "name:'O₂闭内' 的 data 写成 ch4AveValues",
+    "repro": "对应矿打开色谱仪报表对比 o2_ave 与图",
+    "fix_hint": "改为 o2AveValues",
+    "id": "BUG-074",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "视频墙",
+    "file": "src/views/vent/monitorManager/camera/index.vue:100-128,172-178",
+    "title": "设备树加载与分页 paramKind 计算脆弱",
+    "severity": "严重",
+    "type": "null_crash/wrong_param",
+    "symptom": "itemValue 无 '&' 或 msgTxt 结构异常时树展开/翻页失败或请求错误类型",
+    "root_cause": "假定 msgTxt[0].datalist 存在;分页用 searchParam.devKind.indexOf('&') 对 nodeData.itemValue 做 substring,缺 '&' 得空串",
+    "repro": "点击 itemValue 不含 '&' 的分类再翻页;或返回空 datalist 的节点",
+    "fix_hint": "安全解析 itemValue;访问 datalist 前判空;分页直接用 nodeData.itemValue",
+    "id": "BUG-075",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "设备监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/deviceWarn.vue:5",
+    "title": "返回按钮权限判断取反(!hasPermission('deviceWarn:return'))",
+    "severity": "严重",
+    "type": "权限逻辑错误",
+    "symptom": "有 *:return 权限的用户看不到返回;无权限用户反而可见(与 deviceMonitorWarn 正确写法相反)",
+    "root_cause": "使用 v-if=\"!hasPermission('xxx:return')\";对照 deviceMonitorWarn 应为正向 hasPermission",
+    "repro": "分别用有/无 gasWarn:return 等权限账号打开预警页,观察返回按钮显隐",
+    "fix_hint": "去掉 !,改为 v-if=\"hasPermission('...:return')\"",
+    "id": "BUG-076",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "通风参数一张表",
+    "file": "src/views/vent/monitorManager/deviceMonitor/staticSheets/ventilateSheet.vue:1-263",
+    "title": "通风参数一张表为静态硬编码 HTML,无实时数据",
+    "severity": "严重",
+    "type": "data",
+    "symptom": "页面展示固定矿井参数表(如明安木独等),不刷新监测值",
+    "root_cause": "纯静态 table;script 仅注释转换工具,无 API/绑定",
+    "repro": "打开通风参数一张表 → 任意时刻数据不变、与监测无关",
+    "fix_hint": "改为接口驱动渲染;若仅为示意文档页需在需求中降级为非监测页",
+    "id": "BUG-077",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "通风监测预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:10",
+    "title": "返回按钮权限判断取反(!hasPermission('ventilateWarn:return'))",
+    "severity": "严重",
+    "type": "权限逻辑错误",
+    "symptom": "有 *:return 权限的用户看不到返回;无权限用户反而可见(与 deviceMonitorWarn 正确写法相反)",
+    "root_cause": "使用 v-if=\"!hasPermission('xxx:return')\";对照 deviceMonitorWarn 应为正向 hasPermission",
+    "repro": "分别用有/无 gasWarn:return 等权限账号打开预警页,观察返回按钮显隐",
+    "fix_hint": "去掉 !,改为 v-if=\"hasPermission('...:return')\"",
+    "id": "BUG-078",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "通风网络解算",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/network/index.vue:447-454",
+    "title": "传感器列表未判空直接读 readData",
+    "severity": "严重",
+    "type": "null deref on mount/update",
+    "symptom": "monitors 中某条缺少 readData 时 analyzePageResult 抛错,页面解算结果渲染中断",
+    "root_cause": "直接访问 item['readData']['va']/['m3'],无空保护",
+    "repro": "构造 monitors 项 readData=null 的解算推送 → 打开网络页",
+    "fix_hint": "先取 const rd=item.readData||{} 再读字段",
+    "id": "BUG-079",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "通风网络解算",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/network/index.vue:403-405",
+    "title": "局部阻力字段误读自然风压",
+    "severity": "严重",
+    "type": "wrong field mapping / logic bug",
+    "symptom": "巷道表“局部阻力”与“自然风压”显示相同值,局部阻力失真",
+    "root_cause": "dHLocal 赋值使用 item['dHNature'],与 dHNature 同源",
+    "repro": "打开网络解算结果表 → 对比局部阻力与自然风压列",
+    "fix_hint": "改为读取 item['dHLocal'](或后端真实局部阻力字段)",
+    "id": "BUG-080",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "防尘系统监测",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/dust.modal.vue:216-238",
+    "title": "粉尘弹窗测点状态/预警历史硬编码",
+    "severity": "严重",
+    "type": "mock hardcode replacing real API",
+    "symptom": "测点状态 customRender 永远返回“正常”;预警滚动板为固定假数据",
+    "root_cause": "columns.state 写死正常;warningConfig.data 硬编码",
+    "repro": "打开粉尘监测详情弹窗观察状态与预警列表",
+    "fix_hint": "状态取真实字段;预警列表接真实告警数据",
+    "id": "BUG-081",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "需风量分析系统",
+    "file": "src/components/vent/micro/createSubApp.vue:15-37",
+    "title": "非 micro-* 路径组件恒为 null",
+    "severity": "严重",
+    "type": "shell_mount_failure",
+    "symptom": "菜单若未挂在 micro-need-air/micro-vent-doc 前缀下则壳空白",
+    "root_cause": "resetComponent 仅识别有限 appType",
+    "repro": "用非 micro 路径打开需风量/核定",
+    "fix_hint": "按实际菜单 path 扩展映射",
+    "id": "BUG-082",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "风窗管控",
+    "file": "src/views/vent/monitorManager/windowMonitor/index.vue:37-41",
+    "title": "后门控制按钮文案错写成前门",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode / mislabeled control",
+    "symptom": "界面显示“打开前门/关闭前门”,实际下发 rearGateOpen_S/rearGateClose_S,操作员会误控后门",
+    "root_cause": "按钮展示文案复制前门未改,第二参数标题已是后门,UI 文本与指令不一致",
+    "repro": "具备 window:gateControl 且 ndoorcount==2 → 看后两颗按钮文案与 setControl 参数",
+    "fix_hint": "将后两颗按钮文案改为“打开后门/关闭后门”",
+    "id": "BUG-083",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "风窗管控",
+    "file": "src/views/vent/monitorManager/windowMonitor/index.vue:11-14,623-651",
+    "title": "窗面积与窗角度控制共用 paramcode 1/2",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "窗1/窗2 面积设定与角度设定最终都下发 paramcode='1'/'2',后端无法区分面积/角度",
+    "root_cause": "twoAreaControl 与 twoAngleControl 都 setControl('1'|'2'),handleOK else 分支直接 data.paramcode=handlerState",
+    "repro": "同时开启 window:twoAreaControl 与 window:twoAngleControl → 分别设定面积/角度 → 抓包对比 paramcode",
+    "fix_hint": "角度使用独立点位(如 frontSetAngle1),或在 value/附加字段中区分控制类型",
+    "id": "BUG-084",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "风窗管控",
+    "file": "src/views/vent/monitorManager/windowMonitor/index.vue:31-33,504-520",
+    "title": "设定风窗面积误走角度弹窗流程",
+    "severity": "严重",
+    "type": "control buttons sharing same paramcode",
+    "symptom": "权限 window:showAngleArea 的“设定风窗面积”调用 setAngle(1),弹窗标题按角度生成,但点位仍 frontSetValue",
+    "root_cause": "面积按钮错误绑定 setAngle 而非 setArea",
+    "repro": "开启 window:showAngleArea → 点击“设定风窗面积” → 观察 modalTitle 与下发参数",
+    "fix_hint": "改为 setArea(1),或单独实现面积设定入口",
+    "id": "BUG-085",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "风门集中同控",
+    "file": "src/views/vent/monitorManager/airDoor/components/tipModal.vue:28-54",
+    "title": "倒计时弹窗 setTimeout 递归不清理",
+    "severity": "严重",
+    "type": "setInterval/setTimeout poll without clear on unmount",
+    "symptom": "提示弹窗显示后每秒递归创建定时器;关闭/卸载后仍继续;timeout<=0 时先 timer=undefined 再 clearTimeout(undefined) 无效,且仍调用 getMonitor()",
+    "root_cause": "getMonitor 无论 timeout 是否归零都递归调用;clearTimeout 写在 timer=undefined 之后;无取消句柄、watchEffect 可见时重复启动",
+    "repro": "触发 visibleTs30=true → 关闭弹窗或离开页面 → 观察仍有定时回调",
+    "fix_hint": "timeout<=0 时 return 不再递归;保存并 clearTimeout;Visible=false 时清理;避免 watchEffect 重复启动",
+    "id": "BUG-086",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "风门集中同控",
+    "file": "src/views/vent/monitorManager/airDoor/index.vue:44-51",
+    "title": "风门同控菜单拉取未判空 msgTxt[0]",
+    "severity": "严重",
+    "type": "null deref on mount",
+    "symptom": "接口返回空/异常结构时 getMenuList 抛错,左侧菜单无法加载",
+    "root_cause": "直接访问 res.msgTxt[0].datalist.length",
+    "repro": "mock /monitor/device 返回无 msgTxt 或空数组 → 打开风门集中同控",
+    "fix_hint": "使用可选链与默认 []:res?.msgTxt?.[0]?.datalist || []",
+    "id": "BUG-087",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "主风机管控",
+    "file": "src/views/vent/monitorManager/mainFanMonitor/hooks/useAreaSetSimulation.ts:37-109; useMainFanSimulation.ts:25-72",
+    "title": "天窗/闸板面积模拟 setInterval 卸载未清理",
+    "severity": "一般",
+    "type": "setInterval/setTimeout poll without clear on unmount",
+    "symptom": "开启 fanSwitchoverSimulation 后设定面积过程中离开页面,interval 仍改 selectData,可能写已销毁状态",
+    "root_cause": "useAreaSetSimulation 仅在过程结束 clear;无 onUnmounted 遍历 activeProcesses 清理(对比 useFanSwitchoverSimulation 有 stopTick)",
+    "repro": "开启模拟 → 设定天窗面积 → 过渡未完成即路由离开",
+    "fix_hint": "在 composable 增加 dispose/onUnmounted,清理 Map 内全部 interval",
+    "id": "BUG-088",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:189-190",
+    "title": "strinstallpos 为空时 indexOf 抛错",
+    "severity": "一般",
+    "type": "crash_on_mount",
+    "symptom": "getDetailList 抛错,监测卡片不更新",
+    "root_cause": "假定 strinstallpos 必为 string",
+    "repro": "gas 明细 strinstallpos 为 null",
+    "fix_hint": "const pos=el.strinstallpos||'' 再操作",
+    "id": "BUG-089",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:207",
+    "title": "warnDes 为空时 indexOf 抛错中断菜单构建",
+    "severity": "一般",
+    "type": "crash_on_mount",
+    "symptom": "左侧菜单空白且轮询中断",
+    "root_cause": "el.warnDes.indexOf('预警') 无空保护",
+    "repro": "sysTypeWarn 返回 warnDes 缺失条目",
+    "fix_hint": "(el.warnDes||'').indexOf(...)",
+    "id": "BUG-090",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/warn/dustWarn.vue:255",
+    "title": "巷道温度单位错误依赖 humidity",
+    "severity": "一般",
+    "type": "wrong_field_binding",
+    "symptom": "有温度无湿度时单位空白",
+    "root_cause": "dw: el.humidity ? '(℃)' : ''",
+    "repro": "temperature 有值 humidity 空时看单位",
+    "fix_hint": "dw: el.temperature ? '(℃)' : ''",
+    "id": "BUG-091",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "多灾融合预警",
+    "file": "src/views/vent/monitorManager/alarmMonitor/alarm.data.ts:483-780",
+    "title": "散点图动画 setInterval/resize 监听未清理",
+    "severity": "一般",
+    "type": "resource-leak",
+    "symptom": "调用 setScatterEcharts 后即使销毁图表,30ms 动画与 window resize 监听仍存活",
+    "root_cause": "setInterval(... ,30) 与 addEventListener('resize') 无返回清理函数",
+    "repro": "进入使用 setScatterEcharts 的预警可视化 → 离开页面后 interval 仍跑",
+    "fix_hint": "返回 { dispose }:clearInterval + removeEventListener + wwbzl.dispose()",
+    "id": "BUG-092",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "安全监控分站管理",
+    "file": "src/views/vent/safetyList/index.vue:144-146,71-76",
+    "title": "调试风向取值与展示映射不一致",
+    "severity": "一般",
+    "type": "value_mismatch",
+    "symptom": "调试选“反向”写入 '0',列表展示逻辑把反风映射为 '2',显示异常",
+    "root_cause": "derictList 反向 value='0',而 valueJc 渲染把 '2' 当作反风",
+    "repro": "调试设备选反向并确认,查看列表风向展示",
+    "fix_hint": "统一风向枚举(建议 1 正/2 反)并同步调试与展示",
+    "id": "BUG-093",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "密闭监测系统",
+    "file": "src/views/vent/monitorManager/obfurageMonitor/index.vue:107-113",
+    "title": "forEach 内 data=Object.assign 未回写",
+    "severity": "一般",
+    "type": "dead_assignment",
+    "symptom": "readData 字段未合并进列表项,监测展示缺字段",
+    "root_cause": "dataSource.forEach 中 `data = Object.assign(data, readData)` 只改局部绑定,未写回数组元素",
+    "repro": "对比接口 readData 与页面 options 字段是否缺失",
+    "fix_hint": "改为 Object.assign(data, readData) 不重绑,或显式写回",
+    "id": "BUG-094",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "局部风机管控",
+    "file": "src/views/vent/monitorManager/{fanLocalMonitor,gateMonitor,windowMonitor,mainFanMonitor,balancePressMonitor,compressor,windrectMonitor}/**; src/views/vent/gas/gasAssessment/threejs/gasAssessmen.threejs.ts:多处 active debugger",
+    "title": "生产路径残留 debugger 断点",
+    "severity": "一般",
+    "type": "debug-leftover",
+    "symptom": "DevTools 打开时模型切换/动画初始化/工况辅助计算会暂停页面",
+    "root_cause": "遗留未注释 debugger;(如 fanLocal.threejs.Two.ts:40-42, gate.threejs.two.ssl.ts:190, dandaoFcBd3.threejs.ts:170, mainWind.xj.threejs.ts:768/795, balancePress.threejs.ts:60, nitrogenHome_dtyj.vue:326, windrect.threejs.ts:366, gasAssessmen.threejs.ts:69, conditionAssistance.vue:207, fanLocal/index.vue:1549 等)",
+    "repro": "打开 DevTools → 进入对应三维监控页触发模型加载/动画",
+    "fix_hint": "删除全部 active debugger,或统一用开发开关包裹",
+    "id": "BUG-095",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "报表数据映射",
+    "file": "src/views/vent/reportManager/comment/report-modal.vue:135-138",
+    "title": "formStates 被重新赋值为 Object.assign 返回值",
+    "severity": "一般",
+    "type": "reactivity",
+    "symptom": "极端情况下表单代理引用混乱;与父级 reportMap 的 formState 断裂叠加更易丢字段",
+    "root_cause": "formStates = Object.assign(formStates, newV) 不必要地重绑定 let",
+    "repro": "编辑映射记录时反复打开弹窗观察字段回填",
+    "fix_hint": "仅 Object.assign(formStates, newV) 或 for..in 赋值,不要重赋值 let",
+    "id": "BUG-096",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "报表管理",
+    "file": "src/views/vent/reportManager/index.vue:89-106",
+    "title": "三类根节点重复挂载同一套子树",
+    "severity": "一般",
+    "type": "wrong_tree_build",
+    "symptom": "系统/手动/模板三类下出现完全相同的业务分类,筛选易混淆",
+    "root_cause": "getTreeList 对 listArr 每个根节点都 push 完整 res 树,未按业务类型分流",
+    "repro": "打开报表管理对比三个根节点的 children",
+    "fix_hint": "按返回字段或接口分类型填充到对应根节点",
+    "id": "BUG-097",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "抽采泵站监测",
+    "file": "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:49-66",
+    "title": "setInterval 用 clearTimeout 清理",
+    "severity": "一般",
+    "type": "resource-leak",
+    "symptom": "离开页面后图表轮询可能继续,造成多余计算/内存占用",
+    "root_cause": "timer=setInterval(...),onUnmounted 调用 clearTimeout(timer)",
+    "repro": "打开含 monitorChart 的泵站页 → 离开路由 → 断点/日志可见 interval 仍触发",
+    "fix_hint": "改为 clearInterval(timer)",
+    "id": "BUG-098",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "文件共享中心",
+    "file": "src/views/vent/performance/fileDetail/index.vue:240-260,465-469",
+    "title": "setInterval 用 clearTimeout 清理",
+    "severity": "一般",
+    "type": "resource_leak",
+    "symptom": "关闭汇总弹窗或卸载后轮询未必停止,持续请求 queryVentMonReportJd",
+    "root_cause": "timer=setInterval 但 handleCancelHz/onUnmounted 使用 clearTimeout",
+    "repro": "打开汇总报表后关闭弹窗,观察是否仍持续请求 queryVentMonReportJd",
+    "fix_hint": "统一使用 clearInterval(timer)",
+    "id": "BUG-099",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "智能注浆系统",
+    "file": "src/views/vent/monitorManager/groutMonitor/index.vue:1-35",
+    "title": "2D 模型与 groutHome 同时渲染可能叠层",
+    "severity": "一般",
+    "type": "ui_logic",
+    "symptom": "is2DModel 为 true 时流程图与监控壳同时存在,交互/遮罩异常",
+    "root_cause": "v-if is2DModel 渲染 modelComponent,同时 activeKey==monitor 仍挂载 groutHome",
+    "repro": "开启全局 is2DModel 进入注浆监控页",
+    "fix_hint": "2D 时由单一容器负责模型,或让 groutHome 在 2D 模式跳过三维初始化",
+    "id": "BUG-100",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "机电硐室管控",
+    "file": "src/views/vent/home/configurable/configurable.data.ts:6164,6217",
+    "title": "electro-champer / electro-chamber pageType 拼写分裂",
+    "severity": "一般",
+    "type": "config_typo",
+    "symptom": "部分配置按错误 pageType 入库后,fetchConfigs('electro-champer') 只能拿到半套模块",
+    "root_cause": "同一业务存在 champer/chamber 两种 pageType 字面量",
+    "repro": "在配置表按两种 pageType 各查一次 records 数量",
+    "fix_hint": "统一为一种拼写并做数据迁移",
+    "id": "BUG-101",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "束管日报分析",
+    "file": "src/views/vent/bundle/bundleMonitorTable/bundle-table.data.ts:412-435",
+    "title": "保德 N₂ 子列重复两个平均值缺少最小值",
+    "severity": "一般",
+    "type": "wrong_column_dataIndex",
+    "symptom": "N₂ 两列相同平均值;最小值无法展示",
+    "root_cause": "第二、三列均为 title:平均值 + n2_ave",
+    "repro": "保德束管日报看氮气表头",
+    "fix_hint": "中间列改为最小值/n2_min",
+    "id": "BUG-102",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "瓦斯人工巡检地点管理(NFC)",
+    "file": "src/views/vent/gas/gasInspect/index.vue:331-342",
+    "title": "筛「两次」误把 pagination.current 写成 2",
+    "severity": "一般",
+    "type": "copy_paste_bug",
+    "symptom": "筛选两次后分页状态错乱",
+    "root_cause": "case '2': pagination.current=2",
+    "repro": "地点管理→巡检次数筛选→两次",
+    "fix_hint": "两次也 current=1",
+    "id": "BUG-103",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "用户日志管理",
+    "file": "src/views/monitor/log/index.vue:34,61-66",
+    "title": "初始 fieldMapToTime 格式与切换后不一致",
+    "severity": "一般",
+    "type": "config_mismatch",
+    "symptom": "首次进入登录日志时时间范围映射可能无效,切 Tab 后才正常",
+    "root_cause": "paramTime 初始为扁平数组,tabChange 才设为 [[field,[begin,end],fmt]] 结构",
+    "repro": "首次进入不切 Tab,使用时间筛选对比切 Tab 后行为",
+    "fix_hint": "初始化即使用与 case '1' 相同的 fieldMapToTime 结构",
+    "id": "BUG-104",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "色谱仪报表分析",
+    "file": "src/views/vent/bundleSpy/bundleSpyTable/index.vue; src/views/vent/monitorManager/comment/bundleSpyMonitorTable.vue:bundleSpyTable 175-195; bundleSpyMonitorTable 93-95",
+    "title": "发火阶段筛选项文案不一致",
+    "severity": "一般",
+    "type": "logic",
+    "symptom": "阶段统计为 0 或与报警字典不一致;同数据在不同组件统计结果不同",
+    "root_cause": "bundleSpyTable 过滤 '加速氧化升温阶段'(与 warnFire-brt 一致),comment/bundleSpyMonitorTable 过滤 '加速氧化阶段(自热期)';历史计算注释仍写 '加速氧化阶段'",
+    "repro": "同一份含阶段字段的报表分别在两处打开,对比进度条计数",
+    "fix_hint": "统一与后端/告警字典的阶段枚举(建议 '加速氧化升温阶段')",
+    "id": "BUG-105",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "防尘系统监测",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/atomizing.modal.vue:33-42",
+    "title": "主机位置字段错误附加 ℃ 单位",
+    "severity": "一般",
+    "type": "logic/display bug",
+    "symptom": "位置类字段后显示温度单位,信息误导",
+    "root_cause": "holderLocation 展示模板误加 ℃",
+    "repro": "打开喷雾监测详情查看“主机位置”",
+    "fix_hint": "去掉 ℃,位置字段无需单位",
+    "id": "BUG-106",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "防火门智能管控",
+    "file": "src/views/vent/home/configurable/firedoor/fireDoorMonitor.vue:76-99",
+    "title": "场景列表为空仍继续后续逻辑且配置增强未启用",
+    "severity": "一般",
+    "type": "incomplete_init",
+    "symptom": "无防火门场景时下拉为空、模块无有效数据;服务端配置未走 updateEnhancedConfigs",
+    "root_cause": "records 为空时仍调用 loadFireGateData;updateEnhancedConfigs 被注释",
+    "repro": "manageFireList 返回空→页面无场景可选且面板无数据",
+    "fix_hint": "无 records 时提示并 return;恢复 updateEnhancedConfigs(configs)",
+    "id": "BUG-107",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "防灭火系统监测",
+    "file": "src/views/vent/monitorManager/deviceMonitor/components/device/modal/firemon.modal.vue:63-65",
+    "title": "智慧球温度值单位误标为 %",
+    "severity": "一般",
+    "type": "logic/display bug",
+    "symptom": "温度值旁显示 % 而非 ℃,监控读数语义错误",
+    "root_cause": "模板单位复制错误",
+    "repro": "打开 firemon 详情查看温度项单位",
+    "fix_hint": "将单位改为 ℃",
+    "id": "BUG-108",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "预警联动控制",
+    "file": "src/views/vent/deviceManager/workingFace/CustomNormalTable.vue:250-251",
+    "title": "批量删除未传 handleSuccess 回调",
+    "severity": "一般",
+    "type": "undefined_api_ref",
+    "symptom": "确认后 handleSuccess is not a function,列表不刷新",
+    "root_cause": "batchDeleteById(params, handleSuccess) 被调用为 batchDelete({ids})",
+    "repro": "预警联动批删点确认看控制台",
+    "fix_hint": "传入 reload 作为第二参",
+    "id": "BUG-109",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  },
+  {
+    "module": "预警联动控制",
+    "file": "src/views/vent/deviceManager/workingFace/index.vue:1-92",
+    "title": "预警联动控制落到通用智能管控 CRUD,无联动逻辑",
+    "severity": "一般",
+    "type": "incomplete",
+    "symptom": "范围名为预警联动控制,实际仅为 managesys 列表增删改,无预警联动控制流程",
+    "root_cause": "页面复用 CustomNormalTable + managesys_list;onMounted 空实现,无联动策略/告警动作 UI",
+    "repro": "按菜单进入预警联动控制 → 仅见设备/系统管理表",
+    "fix_hint": "补齐联动规则配置与执行界面,或修正菜单路由到正确页面",
+    "id": "BUG-110",
+    "status": "新建",
+    "date": "2026-11-02",
+    "method": "静态审查"
+  }
+]

+ 482 - 0
docs/_heuristic_hits.json

@@ -0,0 +1,482 @@
+{
+  "file_count": 902,
+  "summary": {
+    "debugger": 41,
+    "setInterval": 43,
+    "setTimeout": 264,
+    "clearInterval": 56,
+    "clearTimeout": 160,
+    "onUnmounted": 190,
+    "inverted-return-perm": 6,
+    "res-length": 32,
+    "mock-comment-api": 45,
+    "hardcode-excel": 46
+  },
+  "interval_no_clear": [
+    "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:50:timer = setInterval(() => {",
+    "src/views/vent/monitorManager/alarmMonitor/alarm.data.ts:753:setInterval(function () {",
+    "src/views/vent/performance/fileDetail/index.vue:243:timer = setInterval(async () => {"
+  ],
+  "timeout_no_unmount": [
+    "src/views/vent/monitorManager/mainFanMonitor/mainWind.threejs.ts:223:setTimeout(() => {",
+    "src/views/vent/home/configurable/belt/threejs/belt.threejs.ts:91:// setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.tl.ts:376:// setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.hsw.ts:423:// setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:283:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:290:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:351:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:360:setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.ts:422:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.wlml.vue:191:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.wlml.vue:202:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.bd.vue:162:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.bd.vue:173:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/mainWind.lj.threejs.ts:193:setTimeout(() => {",
+    "src/views/vent/monitorManager/windrectMonitor/duishe.threejs.ts:277:setTimeout(() => {",
+    "src/views/vent/monitorManager/windrectMonitor/duishe.threejs.ts:289:// setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.xc.ts:428:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.hlg.vue:152:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.hlg.vue:163:setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.two.yj.ts:435:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/wisdomball.modal.vue:292:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/wisdomball.modal.vue:303:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistance.vue:474:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistance.vue:484:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistance.vue:492:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:197:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.vue:208:setTimeout(() => {",
+    "src/layouts/default/header/components/MessageBroadcast.vue:122:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:195:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:247:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:251:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:256:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:259:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/window.threejs.ts:408:setTimeout(async () => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.yj.ts:426:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/ballvalve.modal.vue:281:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/ballvalve.modal.vue:292:setTimeout(() => {",
+    "src/layouts/default/header/components/notify/index.vue:137:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.cct.vue:132:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.cct.vue:143:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.yjl.vue:123:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.yjl.vue:134:setTimeout(() => {",
+    "src/layouts/default/tabs/components/TabRedo.vue:25:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/dischargeGas/index.vue:183:setTimeout(() => handleStart(), 500);",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.xr.ts:400:// setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:140:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:508:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:522:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:529:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:544:timer = setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:699:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:709:setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:719:setTimeout(() => {",
+    "src/views/vent/performance/fileDetail/commen/treeList.vue:242:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/dust.modal.vue:247:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/dust.modal.vue:258:setTimeout(() => {",
+    "src/views/vent/monitorManager/airDoor/components/door-content-r.vue:169:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:196:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal-Gx.vue:174:setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.two.ss.ts:427:// setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/supplyAir.vue:126:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.zdrk.vue:186:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.zdrk.vue:197:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/firemon.modal.vue:164:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/firemon.modal.vue:175:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistanceCY.vue:474:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistanceCY.vue:484:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/components/conditionAssistanceCY.vue:492:setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.noStation.ts:337:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/gaspatrol.modal.vue:168:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/gaspatrol.modal.vue:179:setTimeout(() => {",
+    "src/views/vent/monitorManager/windowMonitor/shuangdaoFcYjl.threejs.ts:351://     // setTimeout(() => {",
+    "src/views/vent/monitorManager/fanLocalMonitor/components/dischargeGas.vue:127:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/atomizing.modal.vue:312:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/atomizing.modal.vue:323:setTimeout(() => {",
+    "src/views/vent/monitorManager/mainFanMonitor/mainWind.li3.threejs.ts:213:setTimeout(() => {",
+    "src/views/vent/monitorManager/gateMonitor/gate.threejs.yy.ts:372:// setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.sw.vue:122:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.sw.vue:133:setTimeout(() => {",
+    "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.sjh.vue:186:setTimeout(() => {"
+  ],
+  "hits": {
+    "debugger": [
+      "src/views/vent/monitorManager/workFaceMonitor/workFace.threejs.base.ts:266:// debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1549:debugger;",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.lj.threejs.ts:548:// debugger;",
+      "src/views/vent/home/configurable/belt/threejs/MonitorPanel.vue:152:debugger;",
+      "src/views/vent/monitorManager/windrectMonitor/duishe.threejs.ts:29:// debugger;",
+      "src/views/vent/safetyList/common/HistoryTable.vue:233:// debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.xc.ts:403://     debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.two.ssl.ts:190:debugger;",
+      "src/views/vent/monitorManager/windowMonitor/dandaoFcBd3.threejs.ts:170:debugger;",
+      "src/layouts/default/header/components/VoiceBroadcast.vue:67:// debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.single.ts:81:// debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.yj.ts:401://     debugger;",
+      "src/views/vent/monitorManager/deviceMonitor/components/device/index.vue:1343:// debugger;",
+      "src/views/vent/monitorManager/deviceMonitor/components/device/index.vue:1345:// debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.Two.ts:40:debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.Two.ts:42:debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.Two.ts:213:// debugger;",
+      "src/views/vent/monitorManager/windrectMonitor/index.vue:702:// debugger;",
+      "src/views/vent/monitorManager/windrectMonitor/windrect.threejs.ts:366:debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.xr.ts:375://     debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistance.vue:207:debugger;",
+      "src/views/vent/monitorManager/balancePressMonitor/index1.vue:161:debugger;",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:578:// debugger;",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:768:debugger;",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:795:debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.two.ss.ts:402://     debugger;",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_dtyj.vue:326:debugger;",
+      "src/views/vent/monitorManager/windrectMonitor/longmen.threejs.ts:319:// debugger;",
+      "src/views/vent/monitorManager/windrectMonitor/zhedie.threejs.ts:286://   debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.noStation.ts:312://     debugger;",
+      "src/views/vent/monitorManager/compressor/nitrogen.data.ts:235:// debugger;",
+      "src/views/vent/monitorManager/windowMonitor/shuangdaoFcYjl.threejs.ts:326://       //     debugger;",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.base.ts:209:// debugger;",
+      "src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.ts:60:debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.one.sp.ts:190:debugger;",
+      "src/views/vent/gas/gasPipeNet/index.vue:120:// debugger;",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.yy.ts:347://     debugger;",
+      "src/views/vent/monitorManager/nitrogen/nitrogen.threejs.ts:127:// debugger;",
+      "src/views/vent/monitorManager/groutMonitor/components/groutHomelt.vue:157:// debugger;",
+      "src/views/vent/gas/gasAssessment/threejs/gasAssessmen.threejs.ts:69:debugger;"
+    ],
+    "setInterval": [
+      "src/views/vent/home/configurable/green/fire-green.vue:113:interval = window.setInterval(() => {",
+      "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:50:timer = setInterval(() => {",
+      "src/views/vent/home/configurable/ventWLML.vue:118:interval = setInterval(() => {",
+      "src/views/vent/gas/gasPumpSetting/components/unitTable.vue:44:timer = setInterval(() => {",
+      "src/views/vent/home/configurable/dustControl.vue:59:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/index.vue:91:interval = window.setInterval(() => {",
+      "src/views/vent/home/configurable/fireWZ.vue:88:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/vent.vue:94:interval = setInterval(() => {",
+      "src/views/vent/gas/gasZk/index.vue:65:timer = setInterval(async () => {",
+      "src/views/vent/monitorManager/dedustMonitor/components/DedustHome.vue:169:timer = setInterval(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/hooks/useGasDischargeSimulation.ts:342:tickTimer = setInterval(simulationTick, Math.max(50, 1000 / speed.value));",
+      "src/views/vent/monitorManager/mainFanMonitor/hooks/useFanSwitchoverSimulation.ts:93:tickTimer = setInterval(() => {",
+      "src/views/vent/home/configurable/blue/homeBlue.vue:57:interval = setInterval(fetchData, 60000);",
+      "src/views/vent/home/configurable/fireBD.vue:124:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/blue/dustNew.vue:78:interval = setInterval(fetchData, 2000);",
+      "src/views/vent/home/configurable/green/vent-green.vue:74:interval = window.setInterval(() => {",
+      "src/views/vent/home/configurable/belt/belt.vue:113:timer = setInterval(() => {",
+      "src/views/vent/home/configurable/dust.vue:95:// setInterval(() => {",
+      "src/views/vent/home/configurable/ventSY.vue:108:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/tester.vue:95:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/vent182.vue:130:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/ventDHZ.vue:107:interval = setInterval(() => {",
+      "src/views/vent/monitorManager/dedustMonitor/components/DedustHomeBet.vue:184:timer = setInterval(() => {",
+      "src/views/vent/home/configurable/dustBD.vue:98:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/ventV6.vue:144:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/fire.vue:95:// setInterval(() => {",
+      "src/views/vent/monitorManager/groutMonitor/components/zhijiangSVG.vue:57:mixerTimer = setInterval(() => {",
+      "src/views/vent/home/configurable/blue/ventNew copy.vue:49:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/fireTS.vue:142:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/fireMine.vue:91:interval = setInterval(() => {",
+      "src/views/vent/home/configurable/ventV5.vue:121:interval = setInterval(() => {",
+      "src/views/vent/monitorManager/mainFanMonitor/hooks/useAreaSetSimulation.ts:85:setInterval(() => {",
+      "src/views/vent/monitorManager/alarmMonitor/alarm.data.ts:753:setInterval(function () {",
+      "src/views/vent/home/configurable/electroChamber.vue:97:// setInterval(() => {",
+      "src/views/vent/performance/fileDetail/index.vue:243:timer = setInterval(async () => {",
+      "src/views/vent/home/configurable/ventSDG.vue:170:interval = setInterval(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/dischargeGas/GasTrendChart.vue:234:const checkInit = setInterval(() => {",
+      "src/views/vent/home/configurable/blue/ventNew.vue:57:interval = setInterval(fetchData, 60000);",
+      "src/views/vent/home/configurable/green/dust-green.vue:83:interval = window.setInterval(() => {",
+      "src/views/vent/home/configurable/firedoor/fireDoorMonitor.vue:124:const interval = setInterval(() => {"
+    ],
+    "setTimeout": [
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHomeSP.vue:133:timer = setTimeout(",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.threejs.ts:223:setTimeout(() => {",
+      "src/views/vent/home/configurable/belt/threejs/belt.threejs.ts:91:// setTimeout(() => {",
+      "src/views/vent/monitorManager/deviceMonitor/index.vue:47:setTimeout(",
+      "src/views/vent/monitorManager/deviceMonitor/index.vue:61:setTimeout(() => {",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceVentHome.vue:245:timer = setTimeout(",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.tl.ts:376:// setTimeout(() => {",
+      "src/views/vent/monitorManager/tunFaceMonitor/index.vue:106:setTimeout(() =>{",
+      "src/views/vent/monitorManager/compressor/nitrogen.threejs.ts:112:setTimeout(async () => {",
+      "src/views/vent/monitorManager/compressor/nitrogen.threejs.ts:131:setTimeout(async () => {",
+      "src/views/vent/monitorManager/compressor/nitrogen.threejs.ts:155:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.hsw.ts:423:// setTimeout(() => {",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_lt.vue:152:timer = await setTimeout(",
+      "src/views/vent/safetyList/index.vue:188://   timer = setTimeout(",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:351:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:383:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:412:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:441:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:470:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:495:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:520:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:559:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:593:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:626:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:659:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:692:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:725:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:758:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:786:setTimeout(async () => {",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.ts:815:setTimeout(async () => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:283:setTimeout(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:290:setTimeout(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:351:setTimeout(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:360:setTimeout(() => {",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_dltj.vue:297:timer = await setTimeout(",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.ts:422:// setTimeout(() => {",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceDustHome.vue:159:timer = setTimeout(",
+      "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBD.vue:93:timer = setTimeout(",
+      "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.wlml.vue:191:setTimeout(() => {",
+      "src/views/vent/monitorManager/deviceMonitor/components/device/modal/fiber.modal.wlml.vue:202:setTimeout(() => {"
+    ],
+    "clearInterval": [
+      "src/views/vent/home/configurable/green/fire-green.vue:106:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventWLML.vue:117:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventWLML.vue:139:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventWLML.vue:154:clearInterval(interval);",
+      "src/views/vent/gas/gasPumpSetting/components/unitTable.vue:51:timer = clearInterval(timer);",
+      "src/views/vent/home/configurable/dustControl.vue:76:clearInterval(interval);",
+      "src/views/vent/home/configurable/index.vue:97:clearInterval(interval);",
+      "src/views/vent/home/configurable/fireWZ.vue:96:clearInterval(interval);",
+      "src/views/vent/home/configurable/vent.vue:100:clearInterval(interval);",
+      "src/views/vent/gas/gasZk/index.vue:85:clearInterval(timer);",
+      "src/views/vent/monitorManager/dedustMonitor/components/DedustHome.vue:174:clearInterval(timer);",
+      "src/views/vent/monitorManager/betKy/index.vue:260:clearInterval(timer);",
+      "src/views/vent/monitorManager/fanLocalMonitor/hooks/useGasDischargeSimulation.ts:346:clearInterval(tickTimer);",
+      "src/views/vent/monitorManager/mainFanMonitor/hooks/useFanSwitchoverSimulation.ts:103:clearInterval(tickTimer);",
+      "src/views/vent/home/configurable/blue/homeBlue.vue:61:clearInterval(interval);",
+      "src/views/vent/home/configurable/fireBD.vue:132:clearInterval(interval);",
+      "src/views/vent/home/configurable/blue/dustNew.vue:82:clearInterval(interval);",
+      "src/views/vent/home/configurable/green/vent-green.vue:67:clearInterval(interval);",
+      "src/views/vent/home/configurable/belt/belt.vue:112:if (timer) clearInterval(timer);",
+      "src/views/vent/home/configurable/belt/belt.vue:124:clearInterval(timer);",
+      "src/views/vent/home/configurable/dust.vue:101:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventSY.vue:107:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventSY.vue:129:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventSY.vue:144:clearInterval(interval);",
+      "src/views/vent/home/configurable/tester.vue:102:clearInterval(interval);",
+      "src/views/vent/home/configurable/vent182.vue:129:clearInterval(interval);",
+      "src/views/vent/home/configurable/vent182.vue:164:clearInterval(interval);",
+      "src/views/vent/home/configurable/vent182.vue:179:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventDHZ.vue:113:clearInterval(interval);",
+      "src/views/vent/monitorManager/dedustMonitor/components/DedustHomeBet.vue:189:clearInterval(timer);",
+      "src/views/vent/home/configurable/dustBD.vue:106:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventV6.vue:143:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventV6.vue:170:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventV6.vue:185:clearInterval(interval);",
+      "src/views/vent/home/configurable/fire.vue:101:clearInterval(interval);",
+      "src/views/vent/monitorManager/groutMonitor/components/zhijiangSVG.vue:65:clearInterval(mixerTimer);",
+      "src/views/vent/home/configurable/blue/ventNew copy.vue:55:clearInterval(interval);",
+      "src/views/vent/home/configurable/fireTS.vue:397:clearInterval(interval);",
+      "src/views/vent/home/configurable/fireMine.vue:99:clearInterval(interval);",
+      "src/views/vent/home/configurable/ventV5.vue:120:clearInterval(interval);"
+    ],
+    "clearTimeout": [
+      "src/views/vent/monitorManager/compressor/nitrogen.dixia.threejs.ts:107:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHomeSP.vue:460:clearTimeout(timer);",
+      "src/views/vent/monitorManager/windowMonitor/dandaoFcYjl.threejs.ts:203:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceVentHome.vue:335:clearTimeout(timer);",
+      "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:65:clearTimeout(timer);",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.tl.ts:218:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.hsw.ts:211:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_lt.vue:219:clearTimeout(timer);",
+      "src/views/vent/safetyList/index.vue:415:clearTimeout(timer);",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/conditionAssistanceCY.vue:328:clearTimeout(timer);",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_dltj.vue:744:clearTimeout(timer);",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.three.ts:211:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceDustHome.vue:238:clearTimeout(timer);",
+      "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBD.vue:196:clearTimeout(timer);",
+      "src/views/vent/monitorManager/windowMonitor/dandaoFcHjt.threejs.ts:215:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/gateMonitor/dandaoFcBd3.threejs.ts:295:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/windowMonitor/shuangdaoFc.threejs.ts:206:clearTimeout(this.animationTimer);",
+      "src/views/vent/home/configurable/green/fusion-warn-green.vue:49:clearTimeout(timer);",
+      "src/views/vent/home/configurable/green/fusion-warn-green.vue:97:clearTimeout(timer);",
+      "src/views/vent/safetyList/common/detail-235.vue:531:clearTimeout(timer);",
+      "src/views/vent/safetyList/common/detail-235.vue:532:clearTimeout(timer3)",
+      "src/views/vent/safetyList/common/detail-235.vue:790:clearTimeout(timer3)",
+      "src/views/vent/safetyList/common/detail-235.vue:791:clearTimeout(timer)",
+      "src/views/vent/safetyList/common/detail-235.vue:869:clearTimeout(timer)",
+      "src/views/vent/safetyList/common/detail-235.vue:870:clearTimeout(timer3)",
+      "src/views/vent/safetyList/common/detail-235.vue:1035:[timer, timer3].forEach((t) => t && clearTimeout(t));",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceGasHome.vue:246:clearTimeout(timer);",
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1767:clearTimeout(timer);",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.window.ts:202:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:125:clearTimeout(timer);",
+      "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:132:clearTimeout(timer1);",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/faultEchartLine.vue:287:clearTimeout(timer);",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceHome.vue:294:clearTimeout(timer);",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceVentHome.vue:314:clearTimeout(timer);",
+      "src/views/vent/safetyList/common/detail-cl.vue:461:clearTimeout(timer);",
+      "src/views/vent/safetyList/common/detail-cl.vue:465:clearTimeout(timer1);",
+      "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeCopy.vue:243:clearTimeout(timer);",
+      "src/views/vent/monitorManager/windowMonitor/dandaoFcBd2.threejs.ts:219:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/windowMonitor/dandaoFcLt.threejs.ts:203:clearTimeout(this.animationTimer);",
+      "src/views/vent/monitorManager/gateMonitor/gate.threejs.qd.ts:209:clearTimeout(this.animationTimer);"
+    ],
+    "onUnmounted": [
+      "src/views/vent/home/configurable/components/belt/CameraList.vue:75:onBeforeUnmount(() => {",
+      "src/views/vent/home/configurable/green/fire-green.vue:149:onUnmounted(() => {",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHomeSP.vue:449:onUnmounted(() => {",
+      "src/components/vent/micro/needAir.vue:53:onBeforeUnmount(async () => {",
+      "src/views/vent/monitorManager/balancePressMonitor/index3.vue:173:onUnmounted(() => {});",
+      "src/views/vent/monitorManager/deviceMonitor/index.vue:97:onBeforeUnmount(() => {});",
+      "src/views/vent/monitorManager/deviceMonitor/index.vue:98:onUnmounted(() => {",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceVentHome.vue:333:onUnmounted(() => {",
+      "src/views/vent/gas/gasPumpMonitor/components/monitorChart.vue:64:onUnmounted(() => {",
+      "src/views/vent/monitorManager/compressor/index.vue:135:onUnmounted(() => {});",
+      "src/views/vent/home/configurable/ventWLML.vue:153:onUnmounted(() => {",
+      "src/views/vent/monitorManager/tunFaceMonitor/index.vue:198:onUnmounted(() => {",
+      "src/layouts/default/header/components/VoiceBroadcastGsd.vue:149:onUnmounted(() => {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/waterLevel.vue:69:onUnmounted(() => {});",
+      "src/views/vent/monitorManager/mainFanMonitor/components/setValueSetting.vue:65:onUnmounted(() => {});",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_lt.vue:213:onBeforeUnmount(() => {",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_lt.vue:216:onUnmounted(() => {",
+      "src/views/vent/gas/gasPumpSetting/components/unitTable.vue:50:onUnmounted(() => {",
+      "src/views/vent/safetyList/index.vue:413:onUnmounted(() => {",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_dltj.vue:738:onBeforeUnmount(() => {",
+      "src/views/vent/monitorManager/compressor/components/nitrogenHome_dltj.vue:741:onUnmounted(() => {",
+      "src/views/vent/monitorManager/workFaceMonitor/components/workFaceDustHome.vue:236:onUnmounted(() => {",
+      "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBD.vue:189:// onBeforeUnmount(() => {",
+      "src/views/vent/monitorManager/gasPumpMonitor/components/gasPumpHomeBD.vue:193:onUnmounted(() => {",
+      "src/views/vent/home/configurable/dustControl.vue:74:onUnmounted(() => {",
+      "src/views/vent/home/configurable/index.vue:96:onUnmounted(() => {",
+      "src/views/vent/home/configurable/fireWZ.vue:95:onUnmounted(() => {",
+      "src/views/vent/home/configurable/vent.vue:99:onUnmounted(() => {",
+      "src/views/vent/home/configurable/green/fusion-warn-green.vue:94:onUnmounted(() => {",
+      "src/views/vent/safetyList/common/detail-235.vue:1034:onUnmounted(() => {",
+      "src/views/vent/gas/gasZk/index.vue:174:onUnmounted(() => {",
+      "src/views/vent/monitorManager/dedustMonitor/components/DedustHome.vue:173:onUnmounted(() => {",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceGasHome.vue:244:onUnmounted(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1761:onBeforeUnmount(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1764:onUnmounted(() => {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:384:onUnmounted(() => {",
+      "src/views/vent/monitorManager/fanLocalMonitor/components/faultEchartLine.vue:285:onUnmounted(() => {",
+      "src/views/vent/monitorManager/gasPumpMonitor/index-copy.vue:189:onUnmounted(() => {",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceHome.vue:292:onUnmounted(() => {",
+      "src/views/vent/monitorManager/tunFaceMonitor/components/tunFaceVentHome.vue:312:onUnmounted(() => {"
+    ],
+    "inverted-return-perm": [
+      "src/views/vent/monitorManager/alarmMonitor/warn/waterLevel.vue:5:v-if=\"!hasPermission('waterLevel:return')\"",
+      "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:5:v-if=\"!hasPermission('gasWarn:return')\"",
+      "src/views/vent/monitorManager/alarmMonitor/warn/deviceWarn.vue:5:v-if=\"!hasPermission('deviceWarn:return')\"",
+      "src/views/vent/monitorManager/alarmMonitor/warn/fireWarn.vue:4:<a-button v-if=\"!hasPermission('fireWarn:return')\" preIcon=\"ant-design:rollback-outlined\" type=\"text\" size=\"small\"",
+      "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:10:v-if=\"!hasPermission('ventilateWarn:return')\"",
+      "src/views/vent/monitorManager/alarmMonitor/warn/dustWarn.vue:6:v-if=\"!hasPermission('dustWarn:return')\""
+    ],
+    "res-length": [
+      "src/views/vent/safetyList/index.vue:203:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-235.vue:601:// if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-235.vue:779:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-235.vue:817:if (res && res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-235.vue:1025:if (res && res.length != 0) {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/gasWarn.vue:216:if (!res || res.length === 0) return;",
+      "src/views/vent/safetyList/common/detail-cl.vue:326:if (res.length != 0) {",
+      "src/views/vent/gas/gasInspectNonfc/components/inspectEdit.vue:56:if (res.length != 0) {",
+      "src/views/vent/gas/gasReport/index.vue:313:if (res.length != 0) {",
+      "src/views/vent/monitorManager/mainFanMonitor/index.vue:1080:if (res.length > 0 && data.length > 0) {",
+      "src/views/vent/gas/gasReport/index1.vue:180:if (res.length != 0) {",
+      "src/views/vent/gas/gasInspectNonfc/components/inspectEdit2.vue:59:if (res.length != 0) {",
+      "src/views/vent/gas/gasInspect/components/inspectEdit.vue:62:if (res.length != 0) {",
+      "src/views/vent/gas/gasInspect/components/inspectEdit.vue:75:if (res.length != 0) {",
+      "src/views/vent/monitorManager/airDoor/index.vue:56:if (res.length) {",
+      "src/views/vent/gas/gasInspectNonfc/components/inspectTask.vue:78:if (res.length != 0) {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/fireWarn.vue:91:if (!res || res.length === 0) return;",
+      "src/views/vent/monitorManager/camera/index.vue:66:if (res.length != 0) {",
+      "src/views/vent/reportManager/index.vue:91:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-130.vue:642:// if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-130.vue:820:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-130.vue:858:if (res && res.length != 0) {",
+      "src/views/vent/safetyList/common/detail-130.vue:1066:if (res && res.length != 0) {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue:202:if (!res || res.length === 0) return;",
+      "src/views/vent/safetyList/common/operateRecord.vue:76:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/operateRecord.vue:89:if (res && res.length != 0) {",
+      "src/views/vent/safetyList/common/detail.vue:735:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail.vue:930:if (res.length != 0) {",
+      "src/views/vent/safetyList/common/detail.vue:979:if (res && res.length != 0) {",
+      "src/views/vent/safetyList/common/detail.vue:1193:if (res && res.length != 0) {",
+      "src/views/vent/monitorManager/alarmMonitor/warn/dustWarn.vue:199:if (!res || res.length === 0) return;",
+      "src/views/vent/gas/gasInspect/components/inspectTask.vue:78:if (res.length != 0) {"
+    ],
+    "mock-comment-api": [
+      "src/views/vent/safetyList/index.vue:190://       // await getSubStationList()",
+      "src/views/vent/safetyList/index.vue:191://       await getStationList()",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:223://   await mainWindObj.setSmokeDirection('front', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:226://   await mainWindObj.setSmokeDirection('front', 'tubInversePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:423:// await mainObj.setSmokeDirection('back', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:425://   await mainObj.setSmokeDirection('back', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:427://   await mainObj.setSmokeDirection('back', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:439:// await mainObj.setSmokeDirection('back', 'tubInversePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:441://   await mainObj.setSmokeDirection('back', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:443://   await mainObj.setSmokeDirection('back', 'tubInversePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:454:// await mainObj.setSmokeDirection('back', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:456://   await mainObj.setSmokeDirection('back', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:458://   await mainObj.setSmokeDirection('back', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:487://   await mainObj.setSmokeDirection('front', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:489://   await mainObj.setSmokeDirection('front', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:502://   await mainObj.setSmokeDirection('front', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:504://   await mainObj.setSmokeDirection('front', 'tubInversePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:517://   await mainObj.setSmokeDirection('front', 'windowPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:519://   await mainObj.setSmokeDirection('front', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:547:// await mainObj.setSmokeDirection('back', 'tubPositivePath');",
+      "src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts:562:// await mainObj.setSmokeDirection('back', 'tubInversePath');",
+      "src/views/vent/safetyList/common/detail-235.vue:534:// await getSubStationList();",
+      "src/views/vent/safetyList/common/detail-235.vue:535:// await getStationList1();",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.lj.threejs.ts:211:// await this.openOrCloseValve(deviceType, 'open', duration);",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.lj.threejs.ts:228:// await this.openOrCloseValve(deviceType, 'close');",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.lj.threejs.ts:233:// await this.openOrCloseValve(deviceType, 'close', 0);",
+      "src/views/vent/gas/gasPumpMonitor/index.vue:87:// await getDeviceList();",
+      "src/views/vent/monitorManager/mainFanMonitor/index.vue:1969:// await setModelType('mainWindRect');",
+      "src/views/vent/monitorManager/fanLocalMonitor/fanLocal.threejs.Two.ts:609:// await animateCamera(",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:569://   await setModelType('balancePressTun'); //balancePressBase",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:572://   await getMonitor(true);",
+      "src/views/vent/safetyList/common/detail-130.vue:507://       await getShowReadList();",
+      "src/views/vent/safetyList/common/detail-130.vue:565:// await getSubStationList();",
+      "src/views/vent/safetyList/common/detail-130.vue:566:// await getStationList1();",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:214:// await this.openOrCloseValve(deviceType, 'open', duration);",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:231:// await this.openOrCloseValve(deviceType, 'close');",
+      "src/views/vent/monitorManager/mainFanMonitor/mainWind.xj.threejs.ts:236:// await this.openOrCloseValve(deviceType, 'close', 0);",
+      "src/views/vent/monitorManager/groutMonitor/components/groutHomehlg.vue:112:// await getDataSource(props.deviceId);",
+      "src/views/vent/monitorManager/groutMonitor/components/groutHomehlg.vue:162:// await setModelType('groutBase');",
+      "src/views/vent/monitorManager/alarmMonitor/index.vue:550:// await getDataSource();"
+    ],
+    "hardcode-excel": [
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1554:m3: 525.87, //5.0测试数据",
+      "src/views/vent/monitorManager/fanLocalMonitor/index.vue:1566:m3: 525.87, //5.0测试数据",
+      "src/views/vent/monitorManager/mainFanMonitor/components/AnalysisTable.vue:3:<a-table :dataSource=\"mockData\" :columns=\"Warncolumns\" :scroll=\"{ y: 300 }\"> </a-table>",
+      "src/views/vent/monitorManager/mainFanMonitor/components/AnalysisTable.vue:63:const mockData = [",
+      "src/views/vent/reportManager/comment/DeviceModal.vue:200:fileType: props.fileType == 'doc' ? 'docx' : props.fileType == 'xls' ? 'xlsx' : props.fileType == 'ppt' ? 'pptx' : props.fileType, //当文件类型为d",
+      "src/views/vent/gas/gasInspect/index.vue:276:let filename = `${new Date().getTime()}.xlsx`;",
+      "src/views/vent/gas/gasInspect/index.vue:296:const blob = new Blob([content], { type: 'application/xlsx;charset=UTF-8' }); // 构造一个blob对象来处理数据",
+      "src/views/vent/gas/gasAssessment/gasAssessment.data.ts:577:export const mockData = {",
+      "src/views/vent/gas/gasReport/index.vue:328:let filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/gas/gasReport/index.vue:340://     let filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/gas/gasReport/index.vue:457:const blob = new Blob([content], { type: 'application/xlsx;charset=UTF-8' }); // 构造一个blob对象来处理数据",
+      "src/views/vent/gas/gasReport/index.vue:479:let filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/gas/gasReport/index.vue:547:const filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/monitorManager/mainFanMonitor/index.vue:1924:const fileName = `${record['strname'] || '风机实时监测数据'}_${new Date().getTime()}.xlsx`;",
+      "src/views/vent/gas/gasInspectNonfc/index2.vue:235:let filename = `${new Date().getTime()}.xlsx`;",
+      "src/views/vent/gas/gasInspectNonfc/index2.vue:253:const blob = new Blob([content], { type: 'application/xlsx;charset=UTF-8' }); // 构造一个blob对象来处理数据",
+      "src/views/vent/gas/gasAssessment/components/gasVideo.vue:39:import { gasUnitOption, headerBadges, mockGasUnitData, gasUnitBarOption, mockData, gasUnitPieOption, mockPieData } from '../gasAssessment.da",
+      "src/views/vent/home/configurable/components/content.vue:358:const mockData = clone(props.chartData) || [];",
+      "src/views/vent/home/configurable/components/content.vue:510:const data = cfg?.type == 'scatter' ? getData(mockData, cfg.readFrom, cfg.parser) : getData(refData, cfg.readFrom, cfg.parser);",
+      "src/views/vent/gas/gasReport/index1.vue:204:const filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/gas/gasReport/index1.vue:308:const blob = new Blob([content], { type: 'application/xlsx;charset=UTF-8' }); // 构造一个blob对象来处理数据",
+      "src/views/vent/gas/gasReport/index1.vue:330:let filename = searchData.reportTime + '.xlsx';",
+      "src/views/vent/gas/gasAssessment/components/gasEcharts.vue:59:import { gasUnitOption, headerBadges, mockGasUnitData, gasUnitBarOption, mockData, gasUnitPieOption, mockPieData } from '../gasAssessment.da",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue:73:<template #container> <CustomChart :chart-config=\"PressO2Option\" :chart-data=\"mockData\" height=\"220px\" /> </template>",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue:145:import { PressO2Option, mockData1 } from '../balancePressO2.data';",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue:211:const mockData = ref<{ chartData: { dateTime: string; o2Val: string; pressureVal: string }[] }>({",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue:258:mockData.value = { chartData };",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:12::chartData=\"mockData\"",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:26:import { PressO2Option, mockData1 } from '../balancePressO2.data';",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:42:const mockData = ref<{ chartData: { dateTime: string; o2Val: string; pressureVal: string }[] }>({",
+      "src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome2.vue:559:mockData.value = { chartData };",
+      "src/views/vent/home/configurable/firedoor/components/fireDoorBoard.vue:121:const useMockData = ref(false);",
+      "src/views/vent/home/configurable/firedoor/components/fireDoorBoard.vue:123:const mockData = ref([",
+      "src/views/vent/home/configurable/firedoor/components/fireDoorBoard.vue:147:return useMockData.value ? mockData.value : props.data;",
+      "src/views/vent/home/configurable/firedoor/components/fireDoorBoard.vue:235:if (useMockData.value) {",
+      "src/views/vent/bundleSpy/bundleSpyTable/index.vue:139:fileName: '10月2日色谱分析报表.xlsx',",
+      "src/views/vent/gas/gasAnalysis/index.vue:225:let filename = `${new Date().getTime()}.xlsx`;",
+      "src/views/vent/gas/gasAnalysis/index.vue:232:const blob = new Blob([content], { type: 'application/xlsx;charset=UTF-8' }); // 构造一个blob对象来处理数据",
+      "src/views/vent/gas/gasAssessment/components/workFace.vue:68:import { gasMonitor, gasPumpValve, gasUnitBarOption, mockData, gasUnitPieOption, mockPieData } from '../gasAssessment.data';",
+      "src/views/vent/gas/gasAssessment/components/gasControl.vue:71:import { gasUnitOption, headerBadges, monitorValveData, monitorPosData, mockData, gasUnitPieOption, mockPieData } from '../gasAssessment.dat"
+    ]
+  }
+}

+ 984 - 0
docs/_scope_map.json

@@ -0,0 +1,984 @@
+[
+  {
+    "idx": 1,
+    "name": "主风机管控",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue",
+      "vent/monitorManager/mainFanMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+      "src\\views\\vent\\monitorManager\\mainFanMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 2,
+    "name": "局部风机管控",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue",
+      "vent/monitorManager/fanLocalMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+      "src\\views\\vent\\monitorManager\\fanLocalMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 3,
+    "name": "测风装置管控",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue",
+      "vent/monitorManager/windrectMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+      "src\\views\\vent\\monitorManager\\windrectMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 4,
+    "name": "风门管控",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue",
+      "vent/monitorManager/gateMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+      "src\\views\\vent\\monitorManager\\gateMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 5,
+    "name": "风窗管控",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue",
+      "vent/monitorManager/windowMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue",
+      "src\\views\\vent\\monitorManager\\windowMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 6,
+    "name": "气压温湿度监测",
+    "declared": [
+      "vent/monitorManager/sensorMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\sensorMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 7,
+    "name": "风门集中同控 d",
+    "declared": [
+      "vent/monitorManager/airDoor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\airDoor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 8,
+    "name": "需风量分析系统",
+    "declared": [
+      "vent/micro/createSubApp.vue"
+    ],
+    "resolved": [
+      "src\\components\\vent\\micro\\createSubApp.vue"
+    ],
+    "status": "micro",
+    "notes": ""
+  },
+  {
+    "idx": 9,
+    "name": "通风参数一张表",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/staticSheets/ventilateSheet.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\ventilateSheet.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 10,
+    "name": "通风能力核定",
+    "declared": [
+      "vent/micro/createSubApp.vue"
+    ],
+    "resolved": [
+      "src\\components\\vent\\micro\\createSubApp.vue"
+    ],
+    "status": "micro",
+    "notes": ""
+  },
+  {
+    "idx": 11,
+    "name": "130分站监测",
+    "declared": [
+      "vent/safetyList/common/detail-130.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\safetyList\\common\\detail-130.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 12,
+    "name": "158分站监测",
+    "declared": [
+      "vent/safetyList/common/detail.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\safetyList\\common\\detail.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 13,
+    "name": "235分站监测",
+    "declared": [
+      "vent/safetyList/common/detail-235.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\safetyList\\common\\detail-235.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 14,
+    "name": "通风系统监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 15,
+    "name": "通风网络解算",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 16,
+    "name": "关键通风路线",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 17,
+    "name": "实时网络解算",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 18,
+    "name": "控风方案决策",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 19,
+    "name": "多灾融合预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 20,
+    "name": "通风监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/ventilateWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\ventilateWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 21,
+    "name": "火灾监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/fireWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\fireWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 22,
+    "name": "粉尘监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/dustWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\dustWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 23,
+    "name": "瓦斯监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/gasWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\gasWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 24,
+    "name": "灾变应急控制",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 25,
+    "name": "设备监测预警",
+    "declared": [
+      "vent/monitorManager/deviceMonitorWarn/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitorWarn\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 26,
+    "name": "工作面来压预警",
+    "declared": [
+      "vent/monitorManager/betKy/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\betKy\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 27,
+    "name": "预警联动控制",
+    "declared": [
+      "vent/deviceManager/workingFace/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\deviceManager\\workingFace\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 28,
+    "name": "光纤测温监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 29,
+    "name": "束管监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 30,
+    "name": "防火门监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 31,
+    "name": "密闭监测系统",
+    "declared": [
+      "vent/monitorManager/obfurageMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\obfurageMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 32,
+    "name": "喷淋监控系统",
+    "declared": [
+      "vent/monitorManager/sprayMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\sprayMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 33,
+    "name": "智能注氮系统",
+    "declared": [
+      "vent/monitorManager/compressor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\compressor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 34,
+    "name": "智能注浆系统",
+    "declared": [
+      "vent/monitorManager/groutMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\groutMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 35,
+    "name": "火灾监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/fireWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\fireWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 36,
+    "name": "防灭火系统监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 37,
+    "name": "色谱仪报表分析",
+    "declared": [
+      "vent/bundleSpy/bundleSpyTable/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\bundleSpy\\bundleSpyTable\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 38,
+    "name": "束管日报分析",
+    "declared": [
+      "vent/bundle/bundleMonitorTable/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\bundle\\bundleMonitorTable\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 39,
+    "name": "瓦斯监测",
+    "declared": [
+      "layouts/default/index.vue"
+    ],
+    "resolved": [
+      "src\\layouts\\default\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 40,
+    "name": "瓦斯监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/gasWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\gasWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 41,
+    "name": "抽采泵站管控",
+    "declared": [
+      "vent/monitorManager/gasPumpMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\gasPumpMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 42,
+    "name": "抽采达标评判",
+    "declared": [
+      "vent/gas/gasAssessment/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasAssessment\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 43,
+    "name": "抽采综合管控",
+    "declared": [
+      "vent/gas/gasHome/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasHome\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 44,
+    "name": "瓦斯抽采单元",
+    "declared": [
+      "vent/gas/gasAssessment/gasUnit.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasAssessment\\components\\gasUnit.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 45,
+    "name": "瓦斯管网管控",
+    "declared": [
+      "vent/gas/gasPipeNet/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasPipeNet\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 46,
+    "name": "抽采泵站监测",
+    "declared": [
+      "vent/gas/gasPumpMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasPumpMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 47,
+    "name": "瓦斯日报历史详情",
+    "declared": [
+      "vent/gas/gasReportInspect/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasReportInspect\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 48,
+    "name": "瓦斯钻孔监测",
+    "declared": [
+      "vent/gas/gasZk/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasZk\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 49,
+    "name": "瓦斯巡检设备",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 50,
+    "name": "瓦斯人工巡检报表管理",
+    "declared": [
+      "vent/gas/gasReport/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasReport\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 51,
+    "name": "瓦斯人工巡检地点管理(NFC)",
+    "declared": [
+      "vent/gas/gasInspect/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasInspect\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 52,
+    "name": "瓦斯人工巡检业务分析",
+    "declared": [
+      "vent/gas/gasAnalysis/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasAnalysis\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 53,
+    "name": "瓦斯人工巡检地点管理",
+    "declared": [
+      "vent/gas/gasInspectNonfc/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasInspectNonfc\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 54,
+    "name": "一张表",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/staticSheets/gasSheet.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\gasSheet.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 55,
+    "name": "评判参数设置",
+    "declared": [
+      "vent/gas/gasPumpSetting/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasPumpSetting\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 56,
+    "name": "瓦斯日报分析",
+    "declared": [
+      "vent/gas/gasReportInspect/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\gas\\gasReportInspect\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 57,
+    "name": "喷雾降尘监控",
+    "declared": [
+      "layouts/RouteView.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\home\\configurable\\dust.vue"
+    ],
+    "status": "weak",
+    "notes": ""
+  },
+  {
+    "idx": 58,
+    "name": "除尘风机",
+    "declared": [
+      "vent/monitorManager/dedustMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\dedustMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 59,
+    "name": "粉尘监测预警",
+    "declared": [
+      "vent/monitorManager/alarmMonitor/warn/dustWarn.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\alarmMonitor\\warn\\dustWarn.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 60,
+    "name": "粉尘参数一张表",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/staticSheets/dustSheet.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\staticSheets\\dustSheet.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 61,
+    "name": "防尘系统监测",
+    "declared": [
+      "vent/monitorManager/deviceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\deviceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 62,
+    "name": "粉尘报表分析",
+    "declared": [
+      "vent/dust/dustMonitorTable/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\dust\\dustMonitorTable\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 63,
+    "name": "综采面智能管控",
+    "declared": [
+      "vent/monitorManager/workFaceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\workFaceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 64,
+    "name": "掘进面智能管控",
+    "declared": [
+      "vent/monitorManager/tunFaceMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\tunFaceMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 65,
+    "name": "防火门智能管控",
+    "declared": [
+      "vent/home/configurable/firedoor/fireDoorMonitor.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\home\\configurable\\firedoor\\fireDoorMonitor.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 66,
+    "name": "皮带巷管控系统",
+    "declared": [
+      "vent/monitorManager/beltTunMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\beltTunMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 67,
+    "name": "机电硐室管控",
+    "declared": [
+      "vent/monitorManager/chamberMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\chamberMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 68,
+    "name": "均压与低氧管控",
+    "declared": [
+      "vent/monitorManager/balancePressMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\balancePressMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 69,
+    "name": "机电硐室管控",
+    "declared": [
+      "vent/home/configurable/electroChamber.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\home\\configurable\\electroChamber.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 70,
+    "name": "压风管控系统",
+    "declared": [
+      "vent/monitorManager/nitrogen/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\nitrogen\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 71,
+    "name": "温度压差监测",
+    "declared": [
+      "vent/monitorManager/sensorMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\sensorMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 72,
+    "name": "安全监控系统",
+    "declared": [
+      "vent/monitorManager/safetyMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\safetyMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 73,
+    "name": "设备预警历史",
+    "declared": [
+      "vent/monitorManager/warningMonitor/index-mine.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\warningMonitor\\index-mine.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 74,
+    "name": "设备操作历史",
+    "declared": [
+      "vent/monitorManager/handlerMonitor/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\handlerMonitor\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 75,
+    "name": "视频墙",
+    "declared": [
+      "vent/monitorManager/camera/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\monitorManager\\camera\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 76,
+    "name": "文件共享中心",
+    "declared": [
+      "vent/performance/fileDetail/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\performance\\fileDetail\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 77,
+    "name": "报表管理",
+    "declared": [
+      "vent/reportManager/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\reportManager\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 78,
+    "name": "安全监控分站管理",
+    "declared": [
+      "vent/safetyList/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\safetyList\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 79,
+    "name": "安全监控分站管理详情",
+    "declared": [
+      "vent/safetyList/common/detail.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\safetyList\\common\\detail.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 80,
+    "name": "用户日志管理",
+    "declared": [
+      "monitor/log/index.vue"
+    ],
+    "resolved": [
+      "src\\views\\monitor\\log\\index.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  },
+  {
+    "idx": 81,
+    "name": "报表数据映射",
+    "declared": [
+      "vent/reportManager/comment/reportMap.vue"
+    ],
+    "resolved": [
+      "src\\views\\vent\\reportManager\\comment\\reportMap.vue"
+    ],
+    "status": "mapped",
+    "notes": ""
+  }
+]

+ 0 - 219
docs/ai-changes/20260929-audit-r4.md

@@ -1,219 +0,0 @@
-# 第四轮审计整改 · mky-vent-base(M1/M2/M3 重放 + R4-2/R4-4/R4-5)
-
-## ① 头部
-
-- **对照网址**:`http://39.97.59.228:8013/hrx/mky-vent-base/compare/master...fix/audit-r4-20260929`
-- **依据文档**:
-  - `tools/verify/代码审核-第四轮-mky-vent-base-20260929.md`(§1 R4-1/R4-2/R4-4/R4-5,§2 M1/M2/M3 重放落点)
-  - `tools/verify/第四轮-施工任务书-20260929.md` 第二章(工作令)
-  - `AGENTS.md` §七(§7.2 基座口径)/§九(改动说明随分支提交)
-- **分支**:`fix/audit-r4-20260929`(worktree `/root/VentAnaly60/.wt/mky-r4`)
-- **基线**:`upstream/master` = `46df977e`(团队 AI 助手文件层面重构后的新结构)
-- **日期**:2026-09-29(Asia/Shanghai)
-- **交付版本**:以分支 `git log` 为准(**不写死自指 hash**)
-- **状态**:已交付,已推送,**已 merge 更新后的 master 并通过全量构建**(2026-09-30,见 §⑨);未部署,未浏览器实测。
-
-## ② 提交清单
-
-一项一提交,提交信息均带编号(以 `git log 46df977e..HEAD` 为准):
-
-| # | 提交 | 内容 |
-|---|---|---|
-| 1 | `[Fix R4-M1] …` | 点选解读 SSE 补 `X-Access-Token`(重放 fix/base-agent-token M1,保留令牌可选语义) |
-| 2 | `[Fix R4-M2] …` | `throwStreamHttpError` 加 export;点选链路复用它替换裸 `throw new Error`;`formatClickError`(重放 M2) |
-| 3 | `[Fix R4-M3] …` | `/ventAI/api/me` + `getMe()` + 按 `is_admin` 隐藏技能/子智能体/思考级别入口(重放 M3;**该路径 2026-09-30 实测校正为 `/ventAI/api/model/me`,见 §⑩**) |
-| 4 | `[Fix R4-R4-4] …` | 删除 `Modal/src/index.less` 与 `antCss.less` 双份定义的关闭按钮宽度规则 |
-| 5 | `[Fix R4-R4-2] …` | `extractMarkdownLinks` 加 `MD_LINK_CACHE_MAX=200` LRU |
-| 6 | `[Fix R4-R4-5] …` | `ConversationNav` 滚动跟随缓存 wrappers 列表 |
-| 7 | `[Fix R4-R4-7/8] …` | `markdownSafe` 注释旧路径更正;`useChatScroll` 卸载时 `cancelAnimationFrame` |
-| 8 | `[Docs] …` | 本说明 + `docs/ai-changes/README.md` |
-| 9 | `[Fix R4-R4-5] …(复核 FR-1 收口)` | 缓存失效源补 `props.messages.length`(删 AI 消息场景)+ 注释/文档同步 |
-| 10 | `[Merge] …` | 合并上游 `origin/master`(5 个新提交,见 §⑨):3 处冲突解决 + 复验 |
-
-## ③ 改动面
-
-| 文件 | 改了什么 |
-|---|---|
-| `src/views/ventAI/dataPicker/api.ts` | M1:import `getToken`;`ssePost` headers 增 `'X-Access-Token': getToken()`。M2:import `throwStreamHttpError`;`!response.ok` 分支改 `await throwStreamHttpError(response)` |
-| `src/views/ventAI/dataPicker/useDataPicker.ts` | M2:import `StreamError`;新增 `formatClickError(e)`(429 带 retryAfter→分钟、413/404 兜底文案);catch 分支改 `error.value = formatClickError(e)` |
-| `src/views/ventAI/manageAssistent/api/client.ts` | M2:`throwStreamHttpError` 加 `export`(唯一硬阻塞点,函数体零改动)。M3:Api 枚举加 `me = '/ventAI/api/me'`;新增 `MeInfo` 接口与 `getMe()`(`errorMessageMode: 'none'`) |
-| `src/views/ventAI/manageAssistent/components/AiAssistantModal.vue` | M3:import `getMe`;新增 `isAdmin` ref(默认 false);新增 `fetchMe()`(失败置 false 不缓存);visible watch 的 fetch 组加 `fetchMe()`;`TaskListPanel`/`ChatInputArea` 各透传 `:isAdmin="isAdmin"` |
-| `src/views/ventAI/manageAssistent/components/panels/TaskListPanel.vue` | M3:props 加 `isAdmin?: boolean`;`optionItems` 由普通数组转 computed,按 `!isAdmin` 过滤 `skill`/`sub-agents` |
-| `src/views/ventAI/manageAssistent/components/chat/ChatInputArea.vue` | M3:props 加 `isAdmin?: boolean`(默认 false);`ThinkLevelPopup` **连同前面的 `.action-divider`** 包 `v-if="isAdmin"`。未改 `ThinkLevelPopup` 组件内部 |
-| `src/components/Modal/src/index.less` | R4-4:删除与 `antCss.less` 重复的 `.zxm-modal-close-x` 96px 规则块;保留本块独有的 `font-weight/outline` |
-| `src/views/ventAI/manageAssistent/lib/markdown.ts` | R4-2:`extractMarkdownLinks` 加 `MD_LINK_CACHE_MAX=200` FIFO LRU(与 `renderMarkdownCached` 同型) |
-| `src/views/ventAI/manageAssistent/components/chat/ConversationNav.vue` | R4-5:新增 `getWrappers()` 缓存(失效源=`qaPairs.length` + `props.messages.length` + O(1) `container.contains` 存活校验),`updateActivePairByScroll`/`scrollToPair` 改用它,rAF 合并不变 |
-| `src/utils/markdownSafe.ts` | R4-7(顺手):头部注释的旧路径 `chatModal/utils.ts` 更正为 `lib/markdown.ts`(纯注释) |
-| `src/views/ventAI/manageAssistent/hooks/useChatScroll.ts` | R4-8(顺手):`onBeforeUnmount` 时 `cancelAnimationFrame(scrollRafId)` |
-
-**冻结面零触碰**:`permissionGuard.ts` / `useAutoLogin.ts` / mock-login 相关、`.env`、`public/js/config.js` 均未改(`git diff 46df977e..HEAD --name-only` 已核,无命中)。
-
-## ④ 逐项说明
-
-### M1 点选解读 SSE 补 `X-Access-Token`(重放自我方 fix/base-agent-token M1)
-
-- **原来的行为**:`dataPicker/api.ts` 的 `ssePost` 只带 `Content-Type`,是基座唯一一条匿名调 TfAgents 的路径;消耗记到兜底账号 click-anonymous,无法按登录人记账。
-- **现在的行为**:headers 增 `'X-Access-Token': getToken()`,与对话链路(`client.ts:217/266/317`)同名同源。
-- **为什么这么改**:恢复按登录人记账归因(TfAgents 决策 D5 / B1-20)。
-- **与原来的差别**:仅多一个请求头。**令牌是「可选」语义:空令牌照发请求**(TfAgents 有 click-anonymous 兜底),**未加任何「未登录拦截/跳登录」判断**——这是用户已定的 D5 决策,若改成强制登录会把未登录场景直接变成不可用。
-- 注意:新 master 已把 SSE 读流收敛为 `consumeSse`(`api/sse.ts`),本项只补头,**没有**把旧分支的手写 SSE 循环带回来。
-
-### M2 复用 `throwStreamHttpError`/`StreamError`,429 变可读文案(重放 M2)
-
-- **原来的行为**:`!response.ok` 时裸 `throw new Error('HTTP错误: 429')`;`useDataPicker.ts` 一行 `e?.message || '请求失败'`,用户看不懂 429/413/404。
-- **现在的行为**:
-  1. `client.ts:70` 的 `throwStreamHttpError` 加 `export`(新结构导致的**唯一硬阻塞点**,函数体零改动;`StreamError` 本就导出);
-  2. `dataPicker/api.ts` 改 `await throwStreamHttpError(response)`——解析响应体 `detail`(字符串或 `{code,message,retry_after,limit_tokens,spent_tokens}`),抛出带 `status/retryAfter` 的 `StreamError`;
-  3. `useDataPicker.ts` 新增 `formatClickError(e)`:429 带 `retryAfter` 换算分钟(不足 1 分钟显示「不到 1 分钟」);413 服务端无文案时兜底「附件体积超过上限…」;404 兜底「会话不存在或无权访问」;普通 Error 一律走原 fallback,行为不回归。
-- **为什么这么改**:TfAgents 已返回结构化错误体(D6/B1-15/B1-19/B1-08),且与对话链路共用一套解析器,避免两份实现各自漂移。
-- **与原来的差别**:错误展示从 `HTTP错误: xxx` 变为可读文案;其余链路(consumeSse 流处理、成功路径)不变。
-
-### M3 `/ventAI/api/model/me` + `getMe()` + 按 `is_admin` 隐藏全局变更入口(重放 M3;路径经 2026-09-30 实测校正,见 §⑩)
-
-- **原来的行为**:所有角色都能看到并点击「技能」「子智能体」管理入口与「思考级别」切换;非管理员点了才被后端 403。
-- **现在的行为**:
-  1. `client.ts`:Api 枚举加 `me`;新增 `MeInfo` + `getMe()`(走 defHttp,axios 拦截器自动带令牌;`errorMessageMode:'none'` 静默失败,防接口未上线时每次开弹框都弹红错)。
-  2. `AiAssistantModal.vue`:新增 `isAdmin` ref(默认 false)与 `fetchMe()`;visible watch(`immediate: true`)的 fetch 组每次打开都调 `fetchMe()`;向 `TaskListPanel`、`ChatInputArea` 透传 `:isAdmin`。
-  3. `TaskListPanel.vue`:`optionItems` 转 computed,`!isAdmin` 时过滤 `skill`/`sub-agents`;「新建任务/定时任务」保持开放(属个人功能)。
-  4. `ChatInputArea.vue`:`ThinkLevelPopup` **连同前面的 `.action-divider`** 一起包 `v-if="isAdmin"`(不连分隔线会残留竖线);思考级别的**读取**(getModelMsg)不受影响,对所有人可用。
-- **为什么这么改**:TfAgents 已把这三类全局变更端点收归管理员(用户定案方案 B:后端返回 is_admin,前端隐藏入口)。
-- **与原来的差别**:仅入口可见性收敛;**`fetchMe` 失败置 `isAdmin=false` 且不缓存**(每次打开重新拉取,管理员名单可能在服务端变更)——这是历史浏览器验收踩过的坑(失败停留 false 导致管理员看不到入口),已原样保留。**未改 `ThinkLevelPopup` 组件内部**(可能被别处复用)。旧分支的 `adminConfigured` ref 在模板中从未消费(死状态),本次未搬运。
-
-### R4-4 关闭按钮规则去重
-
-- **原来的行为**:`Modal/src/index.less:77-87` 与 `design/vent/antCss.less:201-209` 双份定义同一条 `.zxm-modal-close-x { 96px }` 规则(f4a47a3c 为修生产错位写了两遍),加载顺序不同会互相覆盖。
-- **现在的行为**:删组件层重复块,保留 `antCss.less` 一份(其注释说明了用后代选择器提升优先级的意图);`index.less` 该块独有的 `font-weight: normal; outline: none;` 保留。
-- **为什么这么改**:单一事实源,避免将来改一处漏一处。
-- **与原来的差别**:编译产物 CSS 少一份同规则;选择器与值不变,渲染行为等价(less 编译实测见 §⑥)。
-
-### R4-2 `extractMarkdownLinks` 加 LRU
-
-- **原来的行为**:每次调用都 `marked.lexer` 全量解析;流式期间胶囊 computed 每个 token 全量重扫所有 AI 消息,CPU 随会话长度线性放大。
-- **现在的行为**:加 `MD_LINK_CACHE_MAX=200` 的 FIFO Map(与 `renderMarkdownCached` 同型),以原文为 key;唯一消费方 `lib/capsule.ts:61` 只读遍历,返回数组被缓存共享安全。
-- **为什么这么改 / 差别**:流式期每 token 的链接提取从 O(全部 AI 消息全文) 降为 O(1)(未变化消息全部命中);缓存有上限,内存代价 ≤ 几十 KB。
-
-### R4-5 滚动跟随 wrappers 缓存
-
-- **原来的行为**:`updateActivePairByScroll` 在滚动 rAF 回调里每帧 `querySelectorAll('.message-wrapper')` 全量查询(>100 条时每帧 O(n))。
-- **现在的行为**:查询结果缓存为数组,失效源=**「消息对数量 + 消息条数」**(`watch([qaPairs.length, props.messages.length])`);另加 O(1) 存活校验(`container.contains` 首个 wrapper),防 DOM 整批替换(如切换任务同问答对数)后用到游离节点。`scrollToPair` 的点击路径也复用。rAF 合并不变。
-- **与原来的差别**:滚动期每帧省一次 O(n) DOM 查询;判定逻辑与选中行为不变。
-- **复核后修正(FR-1)**:初版只 watch `qaPairs.length`,而它只随 **user** 消息数变化——删除 AI 消息(`ChatMessages.vue` 的 delete 按钮)不会改它,缓存会陈旧(外观级、可自愈)。已把 `props.messages.length` 并入失效源并同步注释。
-
-### R4-7 / R4-8(顺手项)
-
-- R4-7:`utils/markdownSafe.ts` 头部注释引用的 `chatModal/utils.ts` 已不存在(重构迁至 `lib/markdown.ts`),纯注释更正,无行为变化。
-- R4-8:`useChatScroll` 的 `scrollRafId` 原仅在重入时 cancel 自身,卸载后不 cancel(残留回调全 optional chaining,无崩溃);现 `onBeforeUnmount` 对称 cancel。该 composable 仅在 `AiAssistantModal` setup 内调用,钩子等价。
-
-## ⑤ 验收证据
-
-- **静态解析/ Lint**:全部通过,见 §⑥。
-- **less 编译行为等价实测**:对改动后的 `Modal/src/index.less` 用仓库 `less@4.7.0` 编译(缺失的全局变量按 `generateModifyVars` 语义打桩),输出 CSS 中 `.zxm-modal-close-x` 规则已消失、`font-weight: normal` 保留 → 删除的是与 antCss.less 完全相同的选择器+值,渲染等价。
-- **引用完整性自查**:`getToken`(`/@/utils/auth`)、`throwStreamHttpError`/`StreamError`/`getMe`(`/@/views/ventAI/manageAssistent/api/client`)均为真实导出;`AiAssistantModal → TaskListPanel/ChatInputArea` 的 `:isAdmin` 透传与两侧 props 声明一一对应;`formatClickError` 在 `handleClick` 之前定义(函数声明提升亦成立)。
-- **未验证项(如实)**:
-  - **未跑 `vite build`**(NAS 16G 悬崖边,硬性禁止;由 Lead 统一走远程构建)。
-  - **未浏览器实测**:M1 令牌头实际到达 TfAgents、M2 的 429/413/404 真实文案、M3 管理员/非管理员入口显隐、R4-5 滚动跟随手感——均为静态推演 + 旧分支既有验收结论外推(旧分支 M1/M2/M3 曾浏览器验收通过)。
-  - `extractMarkdownLinks` 缓存命中收益未跑 profiler 量化(结构推导可靠)。
-
-## ⑥ 静态检查
-
-在 `.wt/mky-r4` 执行(node_modules 为指向主检出的只读软链):
-
-```bash
-# 1) .ts 解析(仓库自带 @babel/parser@7.29.7,经由 .pnpm 路径 createRequire)
-node /tmp/parse-ts.mjs <changed .ts files>
-# 结果:6 个 .ts 全部 OK(exit 0)
-
-# 2) .vue 解析(仓库自带 @vue/compiler-sfc@3.5.40 的 parse + compileScript)
-node /tmp/parse-vue.mjs AiAssistantModal.vue TaskListPanel.vue ChatInputArea.vue ConversationNav.vue
-# 结果:4 个 .vue 全部 OK(exit 0)
-
-# 3) ESLint(eslint@8.57.1,仓库 .eslintrc.js)
-node_modules/.bin/eslint --ext .ts,.vue <全部 10 个改动文件>
-# 结果:exit 0,0 error / 0 warning(-f json 复核:10 文件 messages=0)
-
-# 4) less 编译抽查(R4-4 行为等价)
-less.render(index.less, modifyVars 打桩)  # 输出无 modal-close-x、保留 font-weight → OK
-```
-
-- 既有问题说明:本次 eslint 目标文件零告警,**未发现需要标注的既有问题**;`--ext` 参数与直接文件列表混用时 eslint 仅处理匹配文件,已用 `-f json` 复核确认真处理了目标文件。
-- 未跑 `vite build`(任务书明令禁止,8092 构建属 Lead 收口步骤)。
-
-## ⑦ 已知取舍
-
-1. **M3 未搬运 `adminConfigured`**:旧分支该 ref 在模板中从未消费(死状态),按最小改动原则未重放。
-2. **R4-5 存活校验**:除 `qaPairs.length` 失效外,额外保留 O(1) 的 `container.contains` 校验,覆盖「切换任务后问答对数恰好相同」的边角——比审计建议略保守,无行为风险。
-3. **R4-2 只做了 `extractMarkdownLinks` LRU**:胶囊 computed 每 token 全量重扫 messages 的**外层循环**仍在(收益主要在免除最重的 lexer);按消息对象缓存 links 的更大改动未做(改动面与回归面变大,收益递减)。
-4. **未做项(仅记录,不属本批)**:R4-3(ThinkingCard 每卡 1s interval 空转)、R4-6(TaskListPanel `:key="index"`)——审计定级 🟢 且明确"非本轮施工/可延后"。
-5. **未推送/未部署**:按任务书,push / deliver / 部署由 Lead 复核后统一执行。
-
-## ⑧ 交付状态与上游同步
-
-- **分支**:`fix/audit-r4-20260929`(worktree `/root/VentAnaly60/.wt/mky-r4`),基线 `upstream/master = 46df977e`,无分叉冲突项。
-- **提交**:7 个功能提交 + 1 个 `[Docs]` 提交(清单见 §②,hash 以 `git log` 为准)。
-- **上游同步**:分支自 `upstream/master` 新起(`46df977e`);**2026-09-30 已 merge 更新后的 `origin/master`**(+5 提交,含 API 按域拆分重构、dxf 支持、文件预览修复、导航条缓存),冲突与复验见 §⑨。
-- **推送/部署**:未 push、未 deliver、未部署(任务书 §〇.2,由 Lead 收口)。
-- **对照页**:`http://39.97.59.228:8013/hrx/mky-vent-base/compare/master...fix/audit-r4-20260929`(推送后由 Lead 核验 HTTP 200)。
-
-## ⑨ 合并新 master(2026-09-30)与复验
-
-审计分支交付后,上游 `origin/master` 又前进 5 个提交(`83eb0a1e` 来源卡片默认折叠、`e7e89214` 导航条逻辑+警告修复、
-`6de78411` API 按域拆分重构、`5f41a3be` dxf 支持、`64cfbb1a` 文件预览修复)。本次将 `origin/master` 合入分支,
-逐项核对「审计修改在新结构上是否仍然成立」。
-
-**取值原则**:AI 助手相关代码冲突时**以审计分支为主**(M1/M2/M3/R4-* 的审计语义一律保留);
-上游若已删除/重构掉载体文件,则把审计逻辑**平移**到新结构(见下表 `api/client.ts` 一行),不改审计行为。
-核对方式:对每个审计改动文件比对 `git grep -c "审计-第四轮"` 在审计分支与合并结果上的计数,10 个文件全部一致。
-
-### 冲突解决(3 处)
-
-| 文件 | 冲突 | 解决 |
-|---|---|---|
-| `api/client.ts` | 上游删除(拆分成 `api/*.ts`)vs 本分支修改(M2 加 export + M3 `getMe`) | 接受删除。M2 的「加 export」在新结构中**天然满足**(`throwStreamHttpError`/`StreamError` 已是 `api/errors.ts` 的导出);M3 的 `MeInfo`/`getMe()` 迁到新建 `api/user.ts`(按 barrel 约定 `export * from './user'`) |
-| `components/AiAssistantModal.vue` | 双方改同一 import 行 | 取上游的 barrel 路径并补 `getMe`:`import { …, StreamError, getMe } from '.../api'` |
-| `hooks/useChatScroll.ts` | 双方各加了 `onBeforeUnmount` 取消 rAF(R4-8 与上游重构撞车) | 两边等价(上游为 destroyOnClose 语义,本分支为 R4-8),按**冲突以审计分支为主**取审计版本(`if (scrollRafId !== null)` + R4-8 注释) |
-
-### 其他适配(非冲突但必须改)
-
-- `dataPicker/api.ts`、`dataPicker/useDataPicker.ts`:`throwStreamHttpError`/`StreamError` 的 import 由已删除的
-  `api/client` 改为 `api/errors`;注释中的旧路径一并更正(与 R4-7 同类)。
-- 自动合并文件复核结论:`ConversationNav.vue`(R4-5 的 `getWrappers` 缓存与上游 `toPlainTextCached` 共存,
-  失效源仍为「qaPairs.length + props.messages.length」FR-1 收口版)、`ChatInputArea.vue`/`TaskListPanel.vue`
-  (M3 的 `isAdmin` 过滤/隐藏完整)、`lib/markdown.ts`(R4-2 LRU 完整)。
-
-### 复验证据
-
-- **ESLint**:11 个审计改动文件,关闭 `prettier/prettier` 后 **0 error / 0 warning**。
-  (prettier 报的 3422 处 `Delete ␍` 是 Windows 检出 CRLF 环境噪声——对照组:本次未触碰的 `api/chat.ts` 同样报 161 处。)
-- **TypeScript**:`.tmp-tsconfig.json`(scoped:`ventAI/**` + `dataPicker/**` + `utils/markdownSafe.ts`)编译,
-  **ventAI 相关 0 error**;其余 61 处均为既有问题(`store/`、`router/`、`utils/http/` 等,与本次无关)。
-- **`vite build`**:exit 0(全量生产构建)。
-- **产物核对**:`/ventAI/api/me`(M3)、`X-Access-Token`(M1,`useDataPicker` chunk)、
-  `formatClickError` 的 429/413/404 分支文案(M2)、`ConversationNav` chunk(R4-5)均出现在 dist;
-  R4-4 在编译后 CSS 中 `.zxm-modal-close-x{…width:96px…}` **仅剩 1 处**(`antCss.less` 一份,组件层重复已消失)。
-- **未做(如实)**:浏览器实测与连后端联调(无 TfAgents 环境);M1 令牌头到达后端、M2 真实 429/413/404
-  文案、M3 管理员/非管理员入口显隐仍待浏览器验收。
-
-## ⑩ M3 接口路径校正与浏览器实测(2026-09-30)
-
-在 dev(`:3100`)+ 部署后端上做了浏览器实测,发现 **M3 的 me 路径与部署不一致,已修正**:
-
-- **原**:`api/user.ts` 用 `/ventAI/api/me`(审计文档 §④ 当时写的契约是 "GET /api/me")。
-- **实测**:dev 代理会剥掉 `/ventAI` 前缀,实际请求 `/api/me` —— 部署后端返回 **404**;
-  该后端 OpenAPI 中实际提供的是 **`/api/model/me`**(描述与 `MeInfo` 契约一致:
-  `{"username": str, "is_admin": bool, "admin_configured": bool}`),带令牌请求 **200**。
-- **修正**:`me = '/ventAI/api/model/me'`,`getMe()` 注释同步更新(补 admin_configured 语义)。
-
-**实测结果(当前部署)**:
-
-- `/api/model/me` → `{"username":"admin","is_admin":false,"admin_configured":false}`(管理员账号也是 false);
-- 管理端点 `POST /api/subagents/{name}/toggle` → **403 `admin_not_configured`**:
-  "管理员未配置(TFAGENTS_ADMIN_USERNAMES 为空),全局变更端点对所有人拒绝;请运维在 .env 配置
-  TFAGENTS_ADMIN_USERNAMES 后重启"。
-
-即:**当前部署下前端隐藏入口与后端"对所有人拒绝"是一致的**,不是前端过严;要让管理员看到
-「技能 / 子智能体 / 思考级别」入口,需 TfAgents 侧配置 `TFAGENTS_ADMIN_USERNAMES` 并重启。
-
-**其余实测(隐藏分支)**:左侧仅「新建任务 / 定时任务」、输入区无思考级别控件、打开弹框无红色报错
-(`errorMessageMode:'none'` 生效);对话 SSE 流式、链接胶囊(R4-2)、导航条点击跳转与滚动跟随(R4-5)、
-关闭弹框(R4-4/R4-8)均已在浏览器中跑通。M1/M2 的点选解读因该环境主风机页无设备数据、无行可点,
-UI 触发未能实测(运行模块经 dev server 取源码确认已含 M1/M2 改动)。

+ 0 - 43
docs/ai-changes/README.md

@@ -1,43 +0,0 @@
-# AI 改动说明(ai-changes)
-
-本目录存放**由 AI 协助完成的改动**的说明文档,目的是让人工审核在 Gogs 的「改动对照」页面上
-就能直接看到「改了什么 / 为什么这么改 / 与原来的差别 / 怎么验收的 / 有什么已知取舍」,
-不必再去翻外部文档。
-
-## 为什么要放进分支里
-
-改动说明**必须随改动一起提交到分支**,这样它才会出现在改动对照(compare)页面里:
-
-```
-http://39.97.59.228:8013/hrx/<repo>/compare/master...<分支名>
-```
-
-放在仓库外面的说明文件(例如 `/root/TFAgents/docs/...`)不会出现在对照页,审核人看不到。
-
-## 命名约定
-
-```
-docs/ai-changes/<YYYYMMDD>-<简短主题>.md
-```
-
-- 日期用**改动/交付当天**的日期(本地时区 Asia/Shanghai),便于按文件名排序找到最新一批;
-- 主题用 ASCII 短横线连接的小写单词(例:`agent-token`、`sec-cleanup`、`perf-load-v5`);
-- 同一天同一分支多次追加说明时,直接**更新同一个文件**,不要新建(避免同一批改动出现多份说明)。
-
-## 每份说明应包含
-
-1. **头部**:对照网址、依据文档、分支、基线、日期、交付版本、状态(是否已验收/已交付/已部署);
-2. **提交清单**:本次分支上有哪些提交(功能提交 + merge 提交);
-3. **改动面**:涉及哪些文件、各改了什么;
-4. **逐项说明**:每项都写清「原来的行为 / 现在的行为 / 为什么这么改 / 与原来的差别」,
-   关键取舍(例如「令牌是可选语义,不能改成强制登录」)必须写明,便于人工判断有没有改错业务形态;
-5. **验收证据**:怎么验的、结果如何、失败项的实际现象;**验收中发现并修复的缺陷要单独标出**;
-6. **静态检查**:lint / 类型检查的命令与结果,以及**哪些是既有问题**(避免被误认为新引入);
-7. **已知取舍**:明确写清未做的部分与原因,不要让审核人以为漏了;
-8. **交付状态与上游同步**:fork / 主仓库 / 是否 merge 了最新 `upstream/master` / 是否部署。
-
-## 已有说明
-
-| 日期 | 文件 | 分支 | 主题 |
-|---|---|---|---|
-| 2026-09-29 | `20260929-audit-r4.md` | `fix/audit-r4-20260929` | 第四轮审计整改:M1/M2/M3 重放 + R4-2/R4-4/R4-5 + R4-7/R4-8 顺手项(2026-09-30 追记 §⑨:合并新 master 的冲突解决与复验) |

+ 0 - 203
docs/configurable/README.md

@@ -1,203 +0,0 @@
-### 可配置首页文档及开发指引
-
-可配置首页是一个能让用户在线上进行灵活变更的首页,它可以在配置正确的布局、模块后展示它们,提供了更为低成本的维护方式。
-
-## 配置详解
-
-具体的配置字段及注释请见 _/views/vent/deviceManager/configurationTable/types.ts_
-
-## 目录结构
-
-_/configurable_
-
---_xxx.vue_ 各个首页的具体文件,每个首页需要一个文件来承载它们的子模块,放置特殊的装饰以及实现特定的功能。例如 dustBD 即为保德煤矿专用的粉尘首页。
-
---_mock.ts_ 提供一些模拟数据
-
---_configurable.data.ts_ 该文件及类似命名的文件用来提供测试用的首页具体配置,测试通过后可以依据此配置上线。
-
---_configurable.api.ts_ 获取数据的 api 都在这里维护。
-
---_/hooks_ 包含了可供各个首页、子模块核心组件复用的 setup 内容,包括初始化配置、初始化选项等。
-
---_/components_
-
-----_/detail_ 包含了各个细分模块的具体组件,例如列表、表格、告示板、画廊、时间线等等组件,它们根据自己的 prop 实现自己的内容。
-
-----_/enhanced_ 包含了新版子模块的各样组件,例如底部特化、边缘特化等,子模块内由上述的细分模块组成。
-
-----_/original_ 包含了原版子模块的组件,例如底部特化、边缘特化等,子模块内由上述的细分模块组成。
-
-----_/preset_ 包含了预设类细分模块的具体组件,预设类指的是较为复杂,难以可配置化的组件,通常仅需提供数据,即首页配置内指向的数据。
-
-----_ModuleXXX.vue_ 各个子模块的具体组件,子模块通常负责边框、Header、Content的布局,样式在这里维护。特殊情况下更为底层的实现也可以在这里。
-
-----_content.vue_ 内容组件,核心组件之一,这个组件负责将首页配置转换为可以供细分模块使用的 prop,并且引用所有细分模块,负责它们的布局。
-
-----_header.vue_ 头部组件,核心组件之一,这个组件负责将首页配置的 Header 项实现为下拉框,并向外提供了获取所选内容的方法,供其他与 content 类同的组件使用。
-
-## 开发人员开发流程
-
-从开发一个新的首页开始,需要的步骤可能如下:
-
-1、新建 xxx.vue 作为该首页的具体文件,引入 hooks 里的初始化方法,并对配置进行初始化,初始化数据与页面类型编码即 pageType。
-
-2、根据页面类型编码向项目的数据字典里添加新项,code 在配置表处定义(目前为 configurable_homepage),字典内容为上述的 pageType。
-
-3、参照已有的首页文件,将需要支持的子模块类型加入其中,添加必要的装饰并提供子模块需要的 prop。
-
-4、新建 configurable.data.ts 或类同的文件,根据先前的文件配置,写出一份适用于本首页的配置来。
-
-5、测试完毕后提交代码、打包项目,部署后在线上的首页配置页面将写好的配置以JSON写入即可。
-
-如果需要开发新的细分模块,那么基本流程如下,更详细的内容见另一章节:
-
-1、在配置类型声明处添加子项,可参考 chart、table、list、board 项的结构。
-
-2、开发细分模块,将其放置在 _/components/detail_ 下。
-
-3、根据细分模块的 prop,在 content.vue 下参考已有实现将新的细分模块标识添加进处理结构中,添加能把配置转换为 prop 的逻辑,同时添加该细分模块至相关布局代码中。
-
-4、测试修改并提交。
-
-如果是子模块,那么参考 ModuleEnhanced.vue 即可。
-
-## 运维及字典相关配置
-
-1、配置可配置首页配置页面,组件名:_vent/deviceManager/configurationTable/index_,参考菜单:_/configurable/table_,参考页面位置:设置-首页管理。
-
-2、配置可配置首页依赖的字典,进入字典配置页面,添加 configurable_homepage 字典项,参考名称:可配置首页。
-
-3、在 2 中添加的字典里添加子项,添加的子项具体名称需要和相关同事确认,参考字典:vent(通风首页)、gas(瓦斯首页)、dust(粉尘首页)、vent_realtime(通风首页-实时数据版)等。
-
-4、配置可配置首页,组件名:_vent/home/configurable/xxx_(需要和开发同事确认),参考菜单:将需要替换的首页菜单配给可配置首页。
-
-5、进入可配置首页配置页面,点击导入,将开发同事给的配置导入即可,后续调整可以点击帮助按钮查看配置细则,更为复杂的配置建议交与开发同事。
-
-## 配置详解
-
-我们从一张最常用的通风可配置首页 vent182.vue 开始,这个页面的绝大多数配置都是很好的例子。同时,这份文档只针对与目录结构章节提到的标准内容,对于任何基于此分发的版本不做讨论。
-
-这是一个常用模块的样子![alt text](image.png),这个模块在页面中存在若干个组成整体页面,页面则类似![alt text](image-1.png);一个模块通常包括以下几部分内容:
-
-1、模块的外边框
-
-2、模块的标题
-
-3、模块的设备选择框
-
-4、模块的主体
-
-5、模块的背景
-
-让我们逐一介绍,比对配置和代码!
-
-### 模块的外边框
-
-模块外边框在配置中对应值为![alt text](image-2.png);在代码中的应用实例为![alt text](image-3.png)
-
-目前模块外边框通常是在页面中自己定义的,因为多数页面的外边框是既定的且不同页面有不同边框,所以配置中所提供的外边框配置项仅有少部分页面进行了实际应用,如果需要修改外边框样式,建议直接修改页面中导入的边框。
-
-一个外边框组件负责根据配置渲染模块边框(有短边框,长边框,异形框等),同时边框内设备选择器和主体部分可能需要额外的客制化样式,你可以在这里处理。你可以用 _/src/views/vent/home/configurable/components/ModuleCommon.vue_ 做参考,它们的结构类似:
-
-```vue
-<template>
-  <Transition>
-    <BorderComponent>
-      <Title>标题在此</Title>
-      <Header>设备选择器,可以使用已有的hooks编写逻辑,也可以用标准的Header组件与Content交互</Header>
-      <Content>主体,只建议使用标准的Header组件</Content>
-    </BorderComponent>
-  </Transition>
-</template>
-<script>
-  // extract config and data form props
-</script>
-```
-
-### 模块标题
-
-略
-
-### 模块设备选择框
-
-模块设备选择框是模块中非常重要的部分,它负责展示设备列表,并允许用户选择设备。负责将选择到的数据向外传递,页面传递过来的数据和配置里的模拟数据通常都在这里处理。你可以参考 _/src/views/vent/home/configurable/components/header.vue_ 文件,简要地来说它的工作流程如下:
-
-1、根据Props传入的页面数据进行初始化
-
-2、根据Props传入的配置将数据进行处理
-
-3、渲染内容并提交事件,将选中的设备提交
-
-其中,数据处理时,如果配置上提供了模拟数据(mock)那么模拟数据会优先使用,然后走数据处理逻辑,会根据配置是否需要显示设备选择器进行进一步处理,现假设传入数据为`{ a: 123, b: [1,2,3] }`:
-
-1、如果需要设备选择器,则会根据`Config.deviceType`、`Config.moduleData.header`筛选上述数据,然后将设备数组初始化并默认选择第一个设备,假设配置了`Config.deviceType = 'b'`,那么最终设备数据为`[1,2,3]`,首个设备数据为`1`。组件将把`1`提交出去交给主体。
-
-2、如果不要设备选择器,则会把上述数据转化为一个设备,那么最终设备数据为`[{ a: 123, b: [1,2,3] }]`,首个设备数据为`{ a: 123, b: [1,2,3] }`。组件将把前面的数据提交给主体。
-
-### 模块主体
-
-模块主体部分是模块中最重要的部分,它负责实现主体子模块布局,展示设备数据,展示背景。处理 ![alt text](###模块设备选择框) 传递过来的数据。你可以参考 _/src/views/vent/home/configurable/components/content.vue_ 文件,简要地来说它的工作流程如下:
-
-1、处理传入的主体配置即`Config.moduleData`和设备数据,将数据转化为主体子模块需要的格式
-
-2、渲染主体布局、背景以及子模块,这两张图片是很好的例子![alt text](image-4.png)、![alt text](image-5.png)
-
-3、根据`<template>`的判断,显示指定的子模型并传递数据
-
-### 模块的子模块
-
-模块的子模块是显示信息的最小组件,开发者需要在这个级别的组件里接收从![alt text](###模块主体)传递过来的数据,并根据数据渲染内容。你可以参考 _/src/views/vent/home/configurable/components/detail/MiniBoard.vue_ 文件,简要地来说它的工作流程如下:
-
-1、根据传入的数据渲染主体文本、图表等内容
-
-2、根据样式文件,针对不同的`Props.type`渲染不同的样式
-
-子模块的工作非常简单,也很容易理解。但是简单意味着支持的复杂度不高,它们分为几个大类,但都只能胜任简单的展示任务,如果需要复杂的展示任务,那么你需要看看`Preset`!预设类组件可以自定义实现并实现复用,你可以参考 _/src/views/vent/home/configurable/components/preset/QHCurve.vue_ 文件,这是一个根据数据渲染风量风压曲线图的组件。要使用这些`Preset`,首先要确认所用的![alt text](###模块主体)中是否注册了该组件,你需要导入并注册该组件。然后在配置中把配置项写入`Config.moduleData.preset`下并在`Config.moduleData.layout`下使用注册名称排版。图片说明参考![alt text](image-6.png)、![alt text](image-7.png)
-
-### 常见问题
-
-#### 为什么我配置写好了却没有数据展示在上面呢?
-
-A:阅读上面的文档后检查一下,是不是没有正确地配置。具体的检查步骤参考:
-
-- 检查`Config.deviceType`是否需要配置,仅在需要设备选择器的时候配置该项!
-- 检查`Config.moduleData.header`配置是否正确,在需要设备选择器时,确保`readForm`指向了可读数组!
-- 检查`Config.moduleData.mock`是否配置,即使是空对象也会被认为是存在模拟数据,请确保模拟数据的正确性!
-- 检查控制台是否存在可配置首页下的报错,如有报错应当立即处理,否则会影响后续模块读取数据!
-
-#### 为什么我配置好了,数据也有但是数据没有正确地展示出来呢?
-
-A:通常是因为配置项没有正确地配置,请仔细检查配置项,尤其是类似与`{ ..., readForm: 'outer', items: [{ ..., readForm: 'outer.inner' }] }`的错误配置,内层的配置重复读取了`outer`导致了错误,正确的配置应该让内外层的`readForm`拼接起来后指向所要的数据。
-
-#### 我不会配置模拟数据,总是达不到想要的效果怎么办?
-
-A:模拟数据即`Config.moduleData.mock`,它绝大多数情况下是一个对象,如果不需要设备选择器,那么可配置首页将直接把模拟数据传给子模块。但如果需要设备选择器那么需要配合`Config.deviceType`来使用并确保其指向数组,例如写成`{ ..., mock: { [Config.deviceType]: [ ... ] } }`
-
-#### 如果项目部署后访问首页(可配置首页)没有出现任何内容怎么办?
-
-A:可能是由于以下的原因之一
-
-- 没有正确地配置菜单及其权限,请检查设置-菜单配置
-- 没有正确地配置子应用的模型导致出现了类似 _/micro-vent-3dModal/404_ 的链接,请检查设置-菜单配置-模型设置
-- 没有正确地添加配置项导致页面无内容,应在获取配置导入信息后于设置-首页配置导入
-
-#### 首页正常显示其内容,但是点击左下角呼出菜单后,点击Home图标却跳转到了其他页面怎么办?
-
-A:这是因为项目配置不正确导致的,参考设置-项目设置-编辑功能编辑首页为可配置首页路径并保存。
-
-#### 首页能够显示其内容,但是各个模块位置不齐、出现不想要的滚动条或者矿方想要更宽/更窄/更高等需求怎么办?
-
-A:根据需求自行调整模块`Config.showStyle`定义的宽高位置即可。需要注意定位(即`Config.showStyle.position`)里的`Top`和`Left`是按照总标题下至最底部,最左侧至最右侧为框计算的绝对值,不会计算模块的相互关系。
-
-#### 首页能够显示内容且位置、样式正确,但是某项指标的数据不对、不需要某项指标、需要添加某项指标怎么办?
-
-A:修改某项指标大致可以按照如下流程处理,图片资料参考![alt text](image-8.png)、![alt text](image-9.png)
-
-- 在首页使用控制台(F12)查看数据来源,通常是与 `/homedata` 相似的接口
-- 进入首页配置页面找到需要修改的模块,点击配置
-- 在控制台确认某项指标需要显示的数据的正确读取路径并更新至配置里
-
-#### 需要开发一个全新的页面,但是不知道如何下手怎么办?
-
-A:首先确认新页面的各个模块有没有可复用模块,通常在 _/assets/images/home-container/configurable_ 下可以通过图片的命名方式和样子来作初步确认,如果没有需要按需开发同时建议将图片资源按已有的命名规则加入。涉及复杂逻辑且没有可复用组件的建议直接使用![alt text](###模块子模块)中提到的`Preset`组件。

binární
docs/configurable/image-1.png


binární
docs/configurable/image-2.png


binární
docs/configurable/image-3.png


binární
docs/configurable/image-4.png


binární
docs/configurable/image-5.png


binární
docs/configurable/image-6.png


binární
docs/configurable/image-7.png


binární
docs/configurable/image-8.png


binární
docs/configurable/image-9.png


binární
docs/configurable/image.png


binární
docs/界面缺陷测试报告_全量重测.xlsx


+ 1 - 0
src/views/vent/monitorManager/alarmMonitor/common/external-mb.vue

@@ -133,6 +133,7 @@
           data-zoom-mode="index"
           :data-zoom-start="0"
           :data-zoom-end="10"
+          :alarm-symbol-mode="type === 'O₂' ? 'triangle' : 'auto'"
         />
       </div>
     </div>

+ 1 - 0
src/views/vent/monitorManager/alarmMonitor/common/internal-fire-bot.vue

@@ -117,6 +117,7 @@
         data-zoom-mode="index"
         :data-zoom-start="0"
         :data-zoom-end="10"
+        :alarm-symbol-mode="currentGas === 'O₂' ? 'triangle' : 'auto'"
       />
     </div>
   </div>

+ 14 - 0
src/views/vent/performance/fileDetail/fileDetail.api.ts

@@ -16,6 +16,8 @@ enum Api {
   sumVentReport = '/company/reportData/sumVentReport',
   zipdownload = '/ventanaly-sharefile/fileServer/zipdownload',
   queryVentMonReportJd = '/company/reportData/queryVentMonReportJd',
+  createMonthlySummaryJob = '/ventAI/api/monthly-summary/jobs',
+  queryMonthlySummaryJob = '/ventAI/api/monthly-summary/jobs',
   updataFileParam = '/ventanaly-sharefile/fileServer/updataFileParam',
 }
 
@@ -44,6 +46,18 @@ export const sumVentReport = () => defHttp.post({ url: Api.sumVentReport });
  */
 export const queryVentMonReportJd = () => defHttp.get({ url: Api.queryVentMonReportJd });
 
+/**
+ * 创建通风月报汇总任务
+ */
+export const createMonthlySummaryJob = (data: { year: number; month: number; force?: boolean }) =>
+  defHttp.post({ url: Api.createMonthlySummaryJob, data }, { isTransformResponse: false });
+
+/**
+ * 轮询通风月报汇总任务进度
+ */
+export const queryMonthlySummaryJob = (jobId: string) =>
+  defHttp.get({ url: `${Api.queryMonthlySummaryJob}/${jobId}` }, { isTransformResponse: false });
+
 /**
  * 左侧树接口
  * @param params

+ 419 - 41
src/views/vent/performance/fileDetail/index.vue

@@ -52,12 +52,23 @@
           <span style="color: #fff">文件类型:</span>
           <a-select v-model:value="searchForm.fileType" placeholder="请选择..." style="width: 220px; margin-right: 20px"
             :disabled="activeKey != '1'">
-            <a-select-option v-for="item in filetypeList" :value="item.value">{{ item.label }}</a-select-option>
+            <a-select-option v-for="item in filetypeList" :key="item.value" :value="item.value">{{ item.label }}</a-select-option>
           </a-select>
+          <span style="color: #fff">报表月份:</span>
+          <a-date-picker
+            v-model:value="reportMonth"
+            picker="month"
+            format="YYYY-MM"
+            valueFormat="YYYY-MM"
+            placeholder="请选择年月"
+            style="width: 220px; margin-right: 20px"
+            :allowClear="false"
+          />
           <a-button type="primary" preIcon="ant-design:search-outlined" @click="onSearch"
             :disabled="activeKey != '1'">查询</a-button>
-          <a-button type="primary" style="float: right" @click="reportSum"
-            v-if="sysOrgCode == 'sdmtjtgsd'">汇总报表</a-button>
+          <!-- <a-button type="primary" style="float: right" @click="reportSum"
+            v-if="sysOrgCode == 'sdmtjtgsd'">汇总报表</a-button> -->
+          <a-button type="primary" style="float: right" :loading="reportSumLoading" @click="reportSum">汇总报表</a-button>
           <a-button type="primary" style="float: right; margin-right: 20px" @click="openModal(true)">文件上传</a-button>
         </div>
         <div class="list">
@@ -106,22 +117,58 @@
 
     </a-modal>
     <!-- 汇总报表弹窗 -->
-    <a-modal v-model:visible="visiblehHz" centered :width="600" title="报表汇总" :footer="null" @cancel="handleCancelHz">
-      <div
-        style="height: 240px; overflow-y: auto; display: flex; flex-direction: column; align-items: center; padding: 10px; box-sizing: border-box">
-        <vue3-seamless-scroll hover-stop="true" :list="reportHzList" :hover="true" :step="0.06" class="seamless-warp1">
-          <div v-for="(item, index) in reportHzList" :key="index"
-            style="width: 100%; height: 40px; display: flex; justify-content: space-between; align-items: center">
-            <span>{{ item.time }}</span>
-            <span>{{ item.msg }}</span>
+    <a-modal
+      v-model:visible="visiblehHz"
+      centered
+      :width="860"
+      title="报表汇总"
+      :footer="null"
+      wrap-class-name="report-hz-modal-wrap"
+      @cancel="handleCancelHz"
+    >
+      <div class="report-hz-modal">
+        <section class="report-hz-section report-hz-section-progress">
+          <div class="report-hz-section-title">
+            <span class="report-hz-section-mark"></span>
+            <span>任务执行进度</span>
           </div>
-        </vue3-seamless-scroll>
+          <div class="report-hz-progress">
+            <div class="report-hz-progress-header">
+              <span class="report-hz-progress-label">当前进度</span>
+              <span class="report-hz-progress-text">{{ progressDone }} / {{ progressTotal }}({{ progressPercent }}%)</span>
+            </div>
+            <a-progress
+              :percent="progressPercent"
+              :status="progressStatus"
+              :stroke-color="progressStrokeColor"
+              :stroke-width="14"
+              :show-info="false"
+            />
+          </div>
+        </section>
+        <section class="report-hz-section report-hz-section-list">
+          <div class="report-hz-section-title">
+            <span class="report-hz-section-mark"></span>
+            <span>矿井处理明细</span>
+            <span class="report-hz-section-count" v-if="reportHzList.length">共 {{ reportHzList.length }} 项</span>
+          </div>
+          <div class="report-hz-list">
+            <div v-if="!reportHzList.length" class="report-hz-empty">暂无矿井汇总数据</div>
+            <div v-for="(item, index) in reportHzList" :key="`${item.mine}-${index}`" class="report-hz-item">
+              <div class="report-hz-item-index">{{ index + 1 }}</div>
+              <div class="report-hz-item-main">
+                <span class="report-hz-mine">{{ item.mine || '-' }}</span>
+                <span class="report-hz-file" :title="item.file">{{ item.file || '-' }}</span>
+              </div>
+              <span class="report-hz-status" :class="item.ok ? 'is-ok' : 'is-fail'">{{ item.ok ? '成功' : '失败' }}</span>
+            </div>
+          </div>
+        </section>
       </div>
     </a-modal>
   </div>
 </template>
 <script lang="ts" setup name="system-user">
-import { Vue3SeamlessScroll } from 'vue3-seamless-scroll';
 import customHeader from '/@/components/vent/customHeader.vue';
 import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
 import fileSystem from './commen/fileSystem.vue';
@@ -132,7 +179,8 @@ import endEd from '../endEd/index.vue';
 import { useRouter } from 'vue-router';
 import { useMessage } from '/@/hooks/web/useMessage';
 import { SvgIcon } from '/@/components/Icon';
-import { ref, onMounted, reactive, nextTick, watch, onUnmounted } from 'vue';
+import { ref, computed, onMounted, reactive, watch, onUnmounted } from 'vue';
+import dayjs from 'dayjs';
 import { columns } from './fileDetail.data';
 import {
   getTree,
@@ -144,17 +192,41 @@ import {
   deleteById,
   listData,
   getNowUserAgencyData,
-  sumVentReport,
-  queryVentMonReportJd,
+  createMonthlySummaryJob,
+  queryMonthlySummaryJob,
   zipdownload,
 } from './fileDetail.api';
 import { useGlobSetting } from '/@/hooks/setting';
 
+interface MineSummaryItem {
+  mine?: string;
+  file?: string;
+  json_rel_path?: string;
+  attempts?: number;
+  ok?: boolean;
+}
+
 let spinning = ref(false)
 const { sysOrgCode } = useGlobSetting();
 let visiblehHz = ref(false);
-let reportHzList = ref<any[]>([]);
-let timer: null | NodeJS.Timeout = null;
+let reportHzList = ref<MineSummaryItem[]>([]);
+let reportSumLoading = ref(false);
+let reportMonth = ref(dayjs().format('YYYY-MM'));
+let progressTotal = ref(0);
+let progressDone = ref(0);
+let jobStatus = ref('');
+let currentJobId = ref('');
+let timer: null | ReturnType<typeof setInterval> = null;
+const progressStrokeColor = { '0%': '#31bccc', '100%': '#0863c3' };
+const progressPercent = computed(() => {
+  if (!progressTotal.value) return 0;
+  return Math.min(100, Math.round((progressDone.value / progressTotal.value) * 100));
+});
+const progressStatus = computed(() => {
+  if (jobStatus.value === 'failed') return 'exception';
+  if (jobStatus.value === 'succeeded' || (progressTotal.value > 0 && progressDone.value >= progressTotal.value)) return 'success';
+  return 'active';
+});
 let activeKey = ref('1');
 let selfParam = reactive({
   //各矿参数
@@ -236,28 +308,125 @@ function downFilePublic(content, fileName) {
     navigator.msSaveBlob(blob, fileName);
   }
 }
+function clearReportTimer() {
+  if (timer) {
+    clearInterval(timer);
+    timer = null;
+  }
+}
+
+function resetReportHzState() {
+  reportHzList.value = [];
+  progressTotal.value = 0;
+  progressDone.value = 0;
+  jobStatus.value = '';
+  currentJobId.value = '';
+}
+
+function updateReportProgress(res: any) {
+  const job = res?.job || res || {};
+  const progress = job.progress || {};
+  progressTotal.value = Number(progress.total || 0);
+  progressDone.value = Number(progress.done || 0);
+  jobStatus.value = job.status || '';
+  const mines = progress.mines || job.mines || res?.mines || [];
+  reportHzList.value = Array.isArray(mines) ? mines : [];
+  return job;
+}
+
+function isJobFinished(status?: string) {
+  return status === 'succeeded' || status === 'failed';
+}
+
+function isProgressFull() {
+  return progressTotal.value > 0 && progressDone.value >= progressTotal.value;
+}
+
+function shouldStopPolling(status?: string) {
+  return isJobFinished(status) || isProgressFull();
+}
+
+function stopReportSumLoading() {
+  reportSumLoading.value = false;
+}
+
+async function pollMonthlySummaryJob(jobId: string) {
+  try {
+    const res = await queryMonthlySummaryJob(jobId);
+    const job = updateReportProgress(res);
+    if (shouldStopPolling(job.status)) {
+      clearReportTimer();
+      stopReportSumLoading();
+      if (job.status === 'failed') {
+        const errMsg = job.error?.message || '报表汇总失败';
+        createMessage.error(errMsg);
+      } else {
+        createMessage.success('报表汇总完成');
+        alive.value = new Date().getTime();
+      }
+    }
+    return job;
+  } catch (error) {
+    clearReportTimer();
+    stopReportSumLoading();
+    return null;
+  }
+}
+
 //汇总报表
-function reportSum() {
-  visiblehHz.value = true;
-  sumVentReport();
-  timer = setInterval(async () => {
-    let res = await queryVentMonReportJd();
-    reportHzList.value = res.jdList;
-    if (res.flag) {
-      visiblehHz.value = false;
-      clearTimeout(timer);
-      reportHzList.value.length = 0;
-      alive.value = new Date().getTime();
-    } else {
-      visiblehHz.value = true;
+async function reportSum() {
+  if (!reportMonth.value) {
+    createMessage.warning('请选择报表月份');
+    return;
+  }
+  const [yearStr, monthStr] = reportMonth.value.split('-');
+  const year = Number(yearStr);
+  const month = Number(monthStr);
+  if (!year || !month) {
+    createMessage.warning('报表月份格式不正确');
+    return;
+  }
+
+  reportSumLoading.value = true;
+  clearReportTimer();
+  resetReportHzState();
+
+  try {
+    const res = await createMonthlySummaryJob({ year, month, force: true });
+    if (!res?.success) {
+      const missing = Array.isArray(res?.missing_mines) ? res.missing_mines.join('、') : '';
+      createMessage.error(missing ? `汇总失败,缺矿:${missing}` : res?.message || '创建汇总任务失败');
+      stopReportSumLoading();
+      return;
+    }
+
+    const jobId = res.job_id;
+    if (!jobId) {
+      createMessage.error('未获取到任务编号');
+      stopReportSumLoading();
+      return;
     }
-  }, 3000);
+
+    currentJobId.value = jobId;
+    visiblehHz.value = true;
+    const firstJob = await pollMonthlySummaryJob(jobId);
+    if (!shouldStopPolling(firstJob?.status)) {
+      timer = setInterval(() => {
+        pollMonthlySummaryJob(jobId);
+      }, 1500);
+    }
+  } catch (error: any) {
+    createMessage.error(error?.message || '创建汇总任务失败');
+    stopReportSumLoading();
+  }
 }
+
 //关闭汇总弹窗
 function handleCancelHz() {
-  reportHzList.value.length = 0;
+  clearReportTimer();
+  stopReportSumLoading();
+  resetReportHzState();
   visiblehHz.value = false;
-  clearTimeout(timer);
   alive.value = new Date().getTime();
 }
 //上传文件
@@ -463,10 +632,8 @@ onMounted(() => {
   getTypeTableList();
 });
 onUnmounted(() => {
-  if (timer) {
-    clearTimeout(timer);
-    timer = undefined;
-  }
+  clearReportTimer();
+  stopReportSumLoading();
 });
 </script>
 
@@ -557,10 +724,166 @@ onUnmounted(() => {
   }
 }
 
-.seamless-warp1 {
-  width: 100%;
-  height: 100%;
+.report-hz-modal {
+  padding: 8px 12px 12px;
+}
+
+.report-hz-section {
+  margin-bottom: 20px;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+.report-hz-section-title {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 12px;
+  color: #eaf8ff;
+  font-size: 15px;
+  font-weight: 600;
+  letter-spacing: 0.5px;
+}
+
+.report-hz-section-mark {
+  width: 3px;
+  height: 14px;
+  border-radius: 2px;
+  background: linear-gradient(180deg, #5ce1ff, #1a7fd4);
+  box-shadow: 0 0 8px rgba(92, 225, 255, 0.45);
+}
+
+.report-hz-section-count {
+  margin-left: auto;
+  color: #7fbdd4;
+  font-size: 12px;
+  font-weight: 400;
+}
+
+.report-hz-progress {
+  padding: 18px 20px 16px;
+  border-radius: 10px;
+  background: linear-gradient(120deg, rgba(18, 78, 118, 0.55), rgba(10, 42, 72, 0.72));
+  border: 1px solid rgba(92, 225, 255, 0.35);
+  box-shadow: inset 0 0 24px rgba(49, 188, 204, 0.08);
+}
+
+.report-hz-progress-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 14px;
+}
+
+.report-hz-progress-label {
+  color: #b7e6f7;
+  font-size: 13px;
+}
+
+.report-hz-progress-text {
+  color: #5ce1ff;
+  font-size: 14px;
+  font-weight: 600;
+  font-variant-numeric: tabular-nums;
+}
+
+.report-hz-list {
+  max-height: 380px;
+  overflow-y: auto;
+  padding: 10px 12px;
+  border-radius: 10px;
+  background: rgba(8, 28, 46, 0.45);
+  border: 1px dashed rgba(153, 232, 255, 0.22);
+}
+
+.report-hz-empty {
+  text-align: center;
+  color: #9ec9db;
+  padding: 48px 0;
+}
+
+.report-hz-item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 14px;
+  padding: 12px 14px;
+  margin-bottom: 8px;
+  border-radius: 8px;
+  background: rgba(255, 255, 255, 0.03);
+  border: 1px solid transparent;
+  border-left: 3px solid rgba(92, 225, 255, 0.55);
+  transition: background 0.2s ease, border-color 0.2s ease;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+
+  &:hover {
+    background: rgba(49, 188, 204, 0.08);
+    border-color: rgba(153, 232, 255, 0.12);
+    border-left-color: #5ce1ff;
+  }
+}
+
+.report-hz-item-index {
+  flex-shrink: 0;
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #8ecde2;
+  font-size: 12px;
+  background: rgba(49, 188, 204, 0.12);
+  border: 1px solid rgba(153, 232, 255, 0.2);
+}
+
+.report-hz-item-main {
+  flex: 1;
+  min-width: 0;
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+
+.report-hz-mine {
+  color: #ffffff;
+  font-size: 14px;
+  font-weight: 500;
+}
+
+.report-hz-file {
+  color: #8eb9cc;
+  font-size: 12px;
   overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.report-hz-status {
+  flex-shrink: 0;
+  min-width: 56px;
+  text-align: center;
+  padding: 2px 12px;
+  border-radius: 999px;
+  font-size: 12px;
+  line-height: 20px;
+}
+
+.report-hz-status.is-ok {
+  color: #73d13d;
+  background: rgba(82, 196, 26, 0.12);
+  border: 1px solid rgba(82, 196, 26, 0.32);
+}
+
+.report-hz-status.is-fail {
+  color: #ff7875;
+  background: rgba(255, 77, 79, 0.12);
+  border: 1px solid rgba(255, 77, 79, 0.32);
 }
 
 ::v-deep .jeecg-svg-icon {
@@ -604,6 +927,26 @@ onUnmounted(() => {
   color: #fff !important;
 }
 
+::v-deep .zxm-picker {
+  width: 220px;
+  height: 30px;
+  background: transparent !important;
+  border: 1px solid var(--input-border) !important;
+  border-radius: 5px !important;
+  color: #fff !important;
+  margin-right: 20px;
+}
+
+::v-deep .zxm-picker-input > input {
+  color: #fff !important;
+  height: 28px;
+}
+
+::v-deep .zxm-picker-suffix,
+::v-deep .zxm-picker-clear {
+  color: #fff !important;
+}
+
 ::v-deep .zxm-btn-group {
   margin-right: 25px;
 }
@@ -640,4 +983,39 @@ onUnmounted(() => {
 ::v-deep .zxm-form-item-control-input {
   width: 90%;
 }
+
+::v-deep .report-hz-progress .zxm-progress-inner {
+  background: rgba(8, 28, 46, 0.7) !important;
+  border-radius: 999px !important;
+}
+
+::v-deep .report-hz-progress .zxm-progress-bg {
+  border-radius: 999px !important;
+}
+</style>
+
+<style lang="less">
+.report-hz-modal-wrap {
+  .zxm-modal {
+    top: auto;
+  }
+
+  .zxm-modal-content {
+    padding-bottom: 4px;
+  }
+
+  .zxm-modal-header {
+    padding: 16px 28px 12px;
+  }
+
+  .zxm-modal-body {
+    padding: 8px 28px 24px;
+  }
+
+  .zxm-modal-close-x {
+    width: 48px;
+    height: 48px;
+    line-height: 48px;
+  }
+}
 </style>

+ 15 - 1
src/views/vent/testChart/FiberTempChart.vue

@@ -83,6 +83,11 @@ const props = defineProps({
     type: String,
     default: 'percent',
   },
+  // auto: 超上限火焰 / 低于下限三角;triangle: 超限统一用三角(束管 O₂)
+  alarmSymbolMode: {
+    type: String,
+    default: 'auto',
+  },
 });
 
 const emit = defineEmits(['chart-click']);
@@ -111,9 +116,17 @@ function getDataKey() {
     yn: props.yAxisName,
     vl: props.valueLabel,
     vu: props.valueUnit,
+    asm: props.alarmSymbolMode,
   });
 }
 
+function resolveAlarmSymbol(val, minValue) {
+  if (props.alarmSymbolMode === 'triangle') {
+    return `image://${warningSVG}`;
+  }
+  return `image://${val < minValue ? warningSVG : firePng}`;
+}
+
 function disposeChart() {
   if (chartInstance) {
     chartInstance.off('click');
@@ -253,7 +266,7 @@ function getMarkPointData() {
       const offsetY = Math.max(8, size * 0.35);
       markPoints.push({
         coord: [idx, val],
-        symbol: `image://${val < minValue ? warningSVG : firePng}`,
+        symbol: resolveAlarmSymbol(val, minValue),
         symbolSize: [size, size],
         symbolOffset: [0, -offsetY],
         tooltip: {
@@ -580,6 +593,7 @@ watch(
     props.yAxisName,
     props.valueLabel,
     props.valueUnit,
+    props.alarmSymbolMode,
   ],
   () => {
     nextTick(() => {