20261019-audit-r5-fix.md 18 KB

第五轮审计整改 · mky-vent-base(M-1 必修 + M-2/3/4/5 建议改 + M-7/8/9/12 低优收口)

① 头部

  • 对照网址:http://39.97.59.228:8013/hrx/mky-vent-base/compare/master...fix/audit-r5-20261019
  • 依据文档:
    • tools/verify/代码审核-第五轮-mky-vent-base-20261017.md(§1 分级台账 M-1~M-18、§2 三张清单)
    • AGENTS.md §7.2(基座口径)/§7.4(资源与全局最优)/§九(改动说明随分支提交)
  • 分支:fix/audit-r5-20261019(工作区直改,由 Lead 统一评审提交)
  • 基线:upstream/master = e3d4295c(2026-10-16「AI助手增加打开网页链接面板」)
  • 日期:2026-10-19(Asia/Shanghai)
  • 交付版本:本分支首个提交(代码 + 本说明同一提交;hash 以 git log 为准,不写死自指 hash)
  • 状态:已本地提交;推送 fork / 交付/浏览器验收由 Lead 统一执行;未部署

② 提交清单

# 类型 内容
1 功能提交 第五轮审计整改:M-1(🔴 恢复色谱仪报表真实接口、删除写死 mock)/M-2/M-3/M-4/M-5/M-7/M-8/M-9/M-11/M-12 + 本说明

基线即 upstream/master @ e3d4295c,本分支无 merge 提交;git log upstream/master..HEAD 可核。

③ 改动面

# 文件 对应项 改了什么
1 src/views/vent/bundleSpy/bundleSpyTable/index.vue M-1/M-11 删除写死的 10-02 mock 报表对象(含真实矿测点数据),恢复 getbundleSpyInfoList({ type: 'bundleSpy', ...params }) 真实调用;reportVersion 改由 setReportVersion(res) 解析(删除 reportVersion.value = res.reportVersion ?? null 写死分支与 else 分支);删除 setReportVersion 内本轮新增的两条调试 console.log(:96/:98);:207 既有 console.log(posMonitor.value) 保留不动
2 src/views/ventAI/manageAssistent/components/resource/WebPreviewPanel.vue M-2 iframe 加 sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-downloads";文件头注释由"不加 sandbox…要收紧的话…"更新为"已按此收紧"及未放行的越权项说明
3 src/views/ventAI/manageAssistent/api/streamPost.ts M-3 'X-Access-Token': getToken() 改为 ...(getToken() ? { 'X-Access-Token': getToken() } : {}),令牌为空不再发送 "null" 字符串头;注释保留"令牌可选、未登录不拦截"语义
4 src/assets/images/fire.png M-4 1080×1528 / 717,080 B → 85×120 / 4,278 B(保持 RGBA 透明,sharp 等比缩放 + pngquant 量化,视觉观感核对通过);唯一引用点 FiberTempChart.vue 经 @/assets/images/fire.png 引入,路径不变
5 src/views/vent/monitorManager/groutMonitor/components/zhijiangSVG.vue M-5 320ms 搅拌 interval 增加页面可见性暂停:visibilitychange 隐藏时记录运行态并 stopMixer(),回前台且此前在运行则 startMixer();onMounted 注册监听、onUnmounted 对称 removeEventListener + stopMixer();默认行为(挂载即转)不变
6 src/views/vent/monitorManager/gasPumpMonitor/index.vue M-7 2D 分支 <component v-if="globalConfig?.is2DModel" …> 增加 v-show="activeKey == 'monitor'",与 3D 容器一致在非监测页签隐藏;未改 v-if,避免重挂载闪动
7 src/views/vent/home/configurable/green/vent-green.vue M-8 轮询 list({ types }).then(updateData) 补 .catch(console.error 记日志,不弹全局错误)
8 src/views/vent/home/configurable/green/dust-green.vue M-8 轮询 getDisHome({ dataList }).then(updateData) 补 .catch(同上)
9 src/views/vent/home/configurable/green/fire-green.vue M-8 轮询 getDisHome({ dataList }).then(updateData) 补 .catch(同上)
10 src/views/vent/home/configurable/green/fusion-warn-green.vue M-9 setTimeout(async () => { try { await getCenterList(); } finally {...} }) 的 try 与 finally 之间补 catch(console.error 记日志),finally 重排逻辑不变
11 src/views/ventAI/manageAssistent/components/resource/DwgPreview.vue M-12 svgUrlCache 由组件实例级提升为模块级(新增独立 <script lang="ts"> 块),带上限 20 条 FIFO(超出丢最旧,重复键刷新位置),键仍为 file.id;写入收口到 cacheSvgUrl(),注释更新为实际行为(只缓存服务端静态地址、绝不缓存 blob 地址;releaseSvgBlob 只释放当前实例临时 blob,二者互不干扰)

明确未改(保持原样):M-6(M3 入口"可见但只读",产品决策)、M-10/M-13~M-18(仅记录级)、自动登录/免密冻结面、.env、public/js/config.js、/modelreq 相关——git status --porcelain 已核仅上述 11 个文件 + 本说明文档。

④ 逐项说明

M-1(🔴 必修)色谱仪报表首屏恢复真实接口、删除 mock 报表

  • 原来的行为:65743bff0 把 getTableList() 的真实接口注释,函数体返回写死的「10月2日色谱分析报表」对象(14 条布尔台采空区真实测点 CO/O₂/CH₄ 等数据,reportVersion 固定 '2.0')。首屏默认加载走该函数;getAllFile() 失败/为空/慢时页面长期显示这份假数据且无错误提示;真实矿测点数据随前端源码与 dist 分发。
  • 现在的行为:恢复 const res = await getbundleSpyInfoList({ type: 'bundleSpy', ...params });(与注释掉的调用及 bundleSpy-table.api.ts 签名一致),删除整个 mock 对象;reportVersion 由既有 setReportVersion(res) 解析(支持 reportVersion/report_version/version 三键,未返回时保留原值),不再写死 2.0、布尔台列定义与后端实际版本重新挂钩。
  • 为什么这么改:mock 是"修复"临时绕过被误提交,属功能退化 + 业务敏感数据入库;真实接口恢复后首屏数据即真实数据。
  • 与原来的差别:仅首屏数据来源变化(mock → 真实接口);getTableList 余下逻辑(content 解析、计数、百分比、图表)一字未动。setReportVersion 的两条调试 console.log(M-11)一并删除;:207 的既有 console.log(posMonitor.value) 按指示保留。

M-2(🟡)网页预览 iframe 加 sandbox

  • 原来的行为:<iframe> 无 sandbox,在基座可信 UI 内直接加载模型输出/外部检索的任意 http(s) 链接(点击劫持/界面伪装面);文件头注释自述"先不做限制、要收紧加 sandbox 即可"。
  • 现在的行为:按团队注释给定的收紧口加 sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-downloads"。保留 allow-same-origin 是因地址多为内网系统,iframe 地址栏读取(currentHref)、登录态、下载、弹窗依赖它;未放 allow-top-navigation 等越权项。X-Frame-Options/CSP 拒绝时的白屏兜底("新窗口打开")不受影响。
  • 为什么这么改:收紧第三方内容在基座内的能力面,成本一行、回归面仅限预览面板。
  • 与原来的差别:仅 iframe 多一个 sandbox 属性 + 头注释同步为实际行为。

M-3(🟡)空令牌不再发送 "null" 字符串头

  • 原来的行为:'X-Access-Token': getToken() 无条件写入;getToken() 无值返回 null,fetch 的 Headers 把 null 序列化成字符串 "null" 发出(不是缺省该头)。
  • 现在的行为:...(getToken() ? { 'X-Access-Token': getToken() } : {}),令牌为空时该头缺省;仍照常发请求(后端有兜底账号)。
  • 为什么这么改:避免后端把 "null" 当非法令牌判 401,导致"未登录走匿名兜底"场景(M1 设计语义)不可用。
  • 与原来的差别:仅空令牌时的请求头差异;保留"令牌可选、未登录不拦截"注释语义,未加任何登录拦截。

M-4(🟡)fire.png 717KB 大图压缩

  • 原来的行为:1080×1528 / 717,080 B 的 fire.png 仅作光纤测温图表 60×60 markPoint 图标(FiberTempChart.vue:87),无用大图进 dist(带宽 + 构建 imagemin 耗时)。
  • 现在的行为:sharp 等比缩至 85×120(≤120px 目标内,2× 适配高分屏)+ palette 量化,4,278 B,RGBA 透明保留、观感核对通过;引用路径不变,无需改代码。
  • 为什么这么改:消除 §7.4 资源专项里唯一"否"项,收益零成本。
  • 与原来的差别:仅二进制资产变化;本机无 ImageMagick/pngquant CLI,sharp 为临时目录 npm install --no-save(/tmp/pngtest),未污染仓库依赖。

M-5(🟡)注浆 2D SVG 搅拌 interval 可见性暂停

  • 原来的行为:320ms setInterval 常驻逐相切 DOM,页面切后台仍跑(CSS 流动动画后台自动节流的收益被抵消)。
  • 现在的行为:document.hidden 时记录"隐藏前是否在运行"并 stopMixer();回前台且此前在运行则 startMixer()。监听在 onMounted 注册、onUnmounted 对称 removeEventListener + stopMixer()。记录运行态是为了不顶掉外部 animate({ running: false }) 的主动暂停。
  • 为什么这么改:后台零收益的主线程开销直接清零,回归面仅限该组件动画。
  • 与原来的差别:仅页面隐藏期间搅拌头停在第 1 相(stopMixer 原有语义);默认"挂载即转"不变。

M-7(🟢)gasPumpMonitor 2D 分支非监测页签隐藏

  • 原来的行为:2D 分支无显隐控制,切到"历史/操作记录/故障记录"页签后 SVG 流动画仍在底层运行;3D 分支有 v-show="activeKey == 'monitor'"。
  • 现在的行为:2D 分支加 v-show="activeKey == 'monitor'",与 3D 对齐。
  • 为什么这么改:页签一致性 + 历史页签下不为不可见的动画耗主线程。
  • 与原来的差别:仅非监测页签下 2D SVG 不可见;用 v-show 而非改 v-if,无重挂载闪动。

M-8(🟢)green 系列轮询补 .catch

  • 原来的行为:vent-green(60s 轮询)、dust-green/fire-green(2s 轮询)的 .then(updateData) 无 catch,接口失败产生 unhandled rejection。
  • 现在的行为:补 .catch,内只 console.error 记日志,不弹全局错误(避免 dust/fire 2s 一轮的失败弹窗风暴);轮询间隔、清理(stopInterval/unmounted)逻辑不变。

M-9(🟢)fusion-warn-green 重试链补 catch

  • 原来的行为:setTimeout(async () => { try { await getCenterList(); } finally { getMonitor(false) } }) 失败时 unhandled rejection(重试链靠 finally 续排,本身不断)。
  • 现在的行为:try 与 finally 之间补 catch(console.error 记日志);finally 重排逻辑一字未动,失败仍按 20s 续下一轮。

M-12(🟢)DwgPreview svgUrlCache 提升为模块级带上限 Map

  • 原来的行为:svgUrlCache 在 setup 内为实例级,注释声称"关掉再打开复用"不成立(面板实例随标签切换重建,同图纸重开重新上传转换)。
  • 现在的行为:缓存提升为模块级(独立 <script lang="ts"> 块),上限 20 条 FIFO 丢最旧(重复键刷新插入序位置,防热点图纸被误淘汰),键仍为 file.id。blob 生命周期:缓存只存服务端静态地址(buildStaticFileUrl(result.svgFile)),绝不存 blob 地址——blob 由具体实例 URL.createObjectURL 创建、随 releaseSvgBlob(换文件/卸载)释放,二者互不干扰,既不产生悬空 URL 也不泄漏。
  • 为什么这么改:同图纸关开/切标签省掉"重新上传 + 重新转换"(转换接口超时已放宽到 120s,是真实昂贵开销);上限 20 条静态 URL 字符串的内存代价可忽略。
  • 与原来的差别:同一份 dwg 在会话内第二次打开命中缓存直接取回渲染;load(force=true) 重试仍绕开缓存。

⑤ 验收证据

  1. 代码层:git diff e3d4295c -- src/views/vent/bundleSpy/bundleSpyTable/index.vue 逐 hunk 核对——mock 对象(原 :136-147 共 12 行含 1 行超长 content)整段删除,恢复单行真实调用;grep -n "10月2日\|2109495072969183233" src/views/vent/bundleSpy/bundleSpyTable/index.vue 0 命中(mock 数据与真实矿测点数据清零)。
  2. 对称性核对:zhijiangSVG.vue 新增 visibilitychange 监听注册/移除一一对应(onMounted/onUnmounted);green 系列、fusion-warn 未新增任何定时器/监听。
  3. fire.png:identify(sharp metadata)核对 85×120 RGBA,read_image 目检观感正常;grep -rn "fire.png" src 仅 FiberTempChart.vue:23 一处引用,路径不变。
  4. 未浏览器实测:本仓为工作区整改,未构建未部署(8092 构建按约定在 88 机,由 Lead 安排);sandbox iframe 的实际加载行为(内网系统登录态)建议部署后抽一条 AI 网页链接目验。
  5. 验收中未发现需回修的自身缺陷。

⑥ 静态检查

检查 命令 结果
ESLint(ventAI 3 文件) pnpm exec eslint streamPost.ts DwgPreview.vue WebPreviewPanel.vue 0 问题,退出码 0
ESLint(zhijiangSVG.vue) pnpm exec eslint zhijiangSVG.vue 0 问题,退出码 0
ESLint(其余 5 个 vue) pnpm exec eslint bundleSpyTable/index.vue gasPumpMonitor/index.vue vent-green.vue dust-green.vue fire-green.vue fusion-warn-green.vue 大量 既有 报错(6 文件合计 709 条 prettier/prettier 缩进类 + vue/multi-word-component-names + gasPumpMonitor/index.vue:145 TSX 风格类型断言解析错误),基线(stash 后)同口径 721 条,报错类别与文件范围完全一致——团队代码整体不按该 eslint 配置缩进,属既有配置错配;改动行只涉及其中 prettier 换行类(vent-green :62-65、fusion-warn :52-64),为与文件内既有风格保持一致刻意未按 eslint 重排(改了反而扩大 diff、与邻行风格断裂)。无新增错误类别
vue-tsc pnpm exec vue-tsc --noEmit(590s 上限) 未能完成:改动态与基线态两次尝试均在约 10 分钟处被 SIGABRT(与项目记忆"本机 16G 跑不动全量 TS 检查/构建"一致,属环境内存限制,非本次改动引入);基线对照因 git index.lock 并发冲突未跑成。替代验证:改动文件全部通过 ESLint(含 TS 语法解析,gasPumpMonitor 的解析错误为基线既有);改动均为局部、类型收敛型(...(cond ? {...} : {})、Map 泛型显式、无新 any),未新增 TS 错误的风险极低

手工核对:改动文件无新增硬编码敏感信息(无口令/内网 IP/token);无新增未清理定时器/监听(visibilitychange 对称移除);无新增调试 console.log(仅 M-1 要求删除的两条已删,新增的都是 M-8/M-9 要求的 console.error 错误日志)。

⑦ 已知取舍

  • M-4 若被问"为何本轮能改":本机原无 ImageMagick/pngquant/optipng/sharp(CLI 探测全空),但 pnpm store 里有 pngquant-bin/optipng-bin 二进制,且 /tmp 临时 npm install sharp --no-save 可用,故按"有工具"路径执行了压缩;未动仓库依赖清单。
  • M-6 未改:M3 管理入口"可见但只读"是团队产品决策(写操作仍禁用、后端 403 兜底仍在),按指示保持原样,需用户知悉。
  • M-10/M-13~M-18 未改:均为仅记录级(未知预警等级显示 -、Enter 换行、技能详情停用、初始化交错、任务归并启发式、MutationObserver 单例、既有 echarts 不 dispose、camera hooks 近重复),按指示不提案不施工。
  • M-3 后端行为未实测:空令牌不发头对 TfAgents 是纯收敛(后端此前收到 "null" 字符串,语义更差),无论后端原行为如何都不会劣化;后端对无头请求的实际处理仍以 88 环境实测为准。
  • gasPumpMonitor 2D 隐藏方式:按指示用 v-show,历史页签下 2D SVG DOM 仍在但不可见(与 3D 容器同语义);如后续要彻底停止其内部动画,需 2D 组件侧支持(本轮不做)。
  • 未跑 pnpm build:按项目记忆(NAS 16G 悬崖边、8092 全量构建 OOM)明确禁止本机构建;构建验证在 88 机进行。

⑧ 交付状态与上游同步

  • 交付状态:已本地提交(代码 + 本说明同一提交);已推送 fork(lizuo/mky-vent-base)并交付团队仓同名分支(hrx/mky-vent-base),对照页 compare/master...fix/audit-r5-20261019 实测 HTTP 200;未推送/合并 master、未部署。
  • 上游同步:分支基线 = upstream/master @ e3d4295c,behind=0;本轮未改动任何与上游冲突的面。
  • 部署与浏览器验收(AI 网页链接 sandbox 实际加载、色谱仪报表首屏真实数据、green 首页失败静默)留待后续在 88 环境安排。

⑨ 合并 master 后的处理(2026-10-21,AI 助手部分复核)

本节记录按第五轮审计复核建议把 origin/master(7d3cddad)合入本分支时的冲突处理与收口,代码以合并结果为准。

  • DwgPreview.vue(M-12):master 已于 10-20(242753f1)重写该组件——历史附件按 fileId 直接取服务端转换结果,模块级缓存改存 svg 正文(svgTextCache),静态 URL 链路整体删除——与本分支 M-12 冲突。合并采用 master 版本,不保留 svgUrlCache 实现;仅把 M-12 的「上限 20 条 FIFO、重复键刷新插入序」移植到 svgTextCache,避免长会话无界增长(每份约 1MB 文本)。
  • WebPreviewPanel.vue(M-2):sandbox 在 master 的界面改版上自动合并;按内网系统实际用法补充 allow-modals(alert/confirm/prompt/window.print),其余放行项与未放行的 top-navigation 不变。
  • 空令牌头(M-3):streamPost 改为单次读取令牌后条件放行;同口径同步到 api/attachment.ts、components/chat/DownloadFiles.vue、lib/filePreview.ts,避免附件下载/预览在未登录时发出 "null" 令牌头。
  • 范围:仅上述 5 个文件按合并结果调整,其余审计改动随合并保留;本地 master 未改动、未推送远端,未部署。