改动说明-perf-base-v1.md 10 KB

改动说明:perf-base-v1(基座稳定性与性能优化轮)

日期:2026-09-11 | 分支:perf-base-v1 | 范围:仅 mky-vent-base(基座门户) 基线:origin/fix-subapp-loading(含 fix-subapp-loading 三项修复)+ origin/master 497477be(测风拓扑/ventAI 弹框等新功能)合并,起点 cb285f47 依据:docs/19《基座深度审查与稳定性提速方案》(三代理分域深审:30+ 稳定性缺陷/速度新根因/8 张改进设计卡) 原则:小步修改、不改业务逻辑与子应用通信协议、逐项独立 commit 可单独 revert、修改处带 [perf-base-v1] 注释标记 提交总量:31 个(15 批次1 + 10 批次2 + D1/D2 修复 + 文档 + 合并),未推送前已经 QA 全量验证,QA 后补交 D1/D2 修复与本文档


背景一句话

docs/19 深审确认基座存在成体系的"挂而不摘"缺陷(20 处定时器泄漏、WS 三断点、3D 越切越卡根因、首屏新根因等),本分支按审定批次 1+2 落地修复,目标是:首屏 <5s、页面切换 <1s、内存平稳


改动明细

第一组:批次 1 稳定性速赢(15 提交)

编号 commit 文件 改动 为什么
base-S-T1/L1 266d8bfc configurable/ 下 20 个分版页面 setInterval 返回值补赋值到 interval/timer 原代码裸调用 + clearInterval(undefined) 无效——每进一次页面永久新增一条 60s 轮询器("门户挂一天后请求风暴"的主因,20 处同款复制粘贴 bug)
base-S-T2 09baba85 monitorManager/nitrogenMonitor/index.vue 同上补赋值 + onUnmounted 清理 裸 60s 轮询永久泄漏
base-S-T3 2d402cd2 vent/home/colliery/index.vue 1s 时钟补 clockTimer + 卸载清理 每秒 dayjs 格式化永久运行
base-S-T6 1b4ea726 vent/dataCenter/deviceCenter/index.vue 设备列表 3s 与行展开 1s 两个轮询拆分为 listTimer/expandTimer 原共用一个变量:展开行清掉列表轮询且不恢复,设备列表静默停止刷新
base-L2 16180b1b index.html liveplayer-lib.min.js(844KB)加 defer 同步阻塞脚本拖慢首屏
base-L4 cd695880 .env.production VITE_USE_MOCK=true→false 生产构建注入 mock 服务器有正确性风险
base-L5 fcf6636f src/qiankun/apps.ts prefetchApps 只保留 3D 子应用 4 个子应用全量预取 ≈10-30MB 后台下载,挤占首屏窗口
base-L8 c94267e5 package.json 删除 plyr(全仓 0 引用) 依赖卫生
base-L9 0d8116b9 src/api/sys/vent.ts 删除 return 之后 3.88 万行不可达内联 mock 构建/解析负担与误导性代码
base-L10 e4914c17 components/Container/src/Adaptive.vue resize 监听改为单次注册 原每次 resize 新增一条永久 window 监听
base-L11 d2601c76 App.vue、design/default.less @font-face 加 font-display:swap 5MB 字体下载期间文字不可见(FOIT)
base-L14 abfa00d3 index.html、public/vent/ 启动屏背景图落 public 并修正 url ./src/... 引用生产 404,启动屏背景缺失
base-S-L1 d2ce667f utils/threejs/useThree.ts、hooks/vent/useThree.ts(删除) resize 注册/移除统一用 _boundResize 同一引用 .bind() 注册 vs 原引用移除静默失败,20+ 处 3D 页每进一次泄漏一条监听;死文件 hooks/vent/useThree.ts(0 引用)一并删除
base-S-3D2 a3244d5c utils/threejs/useThree.ts destroy() 不再调用全局 $renderer.dispose() 全仓 3D 页共享该渲染器,页面销毁时清空 GPU 缓存会导致下一个 3D 页全量重编译 shader——"3D 页越切越卡"的直接根因
base-S-D1 dad68da1 store/modules/errorLog.ts 错误日志 .slice(0, 100) 只进不出,长会话线性增长

第二组:批次 2 安全与性能主线(8 提交)

编号 commit 文件 改动 为什么
base-卡3 6292f7aa vite.config.ts build.modulePreload.resolveDependencies:html 入口剔除 office-preview/markdown-vendor/tinymce-vendor/html2canvas/codemirror/cron-parser 预载 这些重型 chunk 对多数页面是纯预载浪费;保留 echarts-vendor(首页图表在用)不误杀
base-卡2a 1e683e3c rightPositionBar.vue、content-New.vue、blue/content.vue、blue/content-New.vue、blue/content-FireNew.vue、green/content-green.vue MiniChat 静态 import 改 defineAsyncComponent 布局头部静态链把 4.46MB office-preview + markdown/echarts vendor 拖进登录后首帧
base-卡2b 308b8226 components/AIChat/MiniChat.vue vue-office 三组件改 defineAsyncComponent(isShowDoc 时才加载);echarts 改 initChart 内 await import 文件预览/图表非必现路径,按需加载
base-卡2c 0d2113bf ventAI/.../FilePreviewPanel.vue VueOfficeDocx 与 XLSX 改按需 import 同上
base-卡6a 934b59b3 新增 src/utils/markdownSafe.ts;ventAI chatModal/utils.ts 改转调 公共消毒管线(marked+DOMPurify,白名单 ADD_TAGS:['img'])收敛为单一实现 原两处实现漂移:ventAI 版有消毒、MiniChat 版裸渲染
base-卡6b 8cc07e7c MiniChat.vue、AIChat/index.vue、DataPickerModal.vue、MarkdownViewer.vue 4 处高危 v-html 数据源接入 DOMPurify 消毒 LLM 输出 + 用户输入双通道裸渲染 = 同源 XSS(可窃 token);顺带删除 0 引用死文件 Aichat copy.vue
base-卡1 0e54a39e index.html、public/js/config.js、新增 utils/onlyOffice.ts、3 个 DocEditor 弹窗 移除首屏 9050 注入;onlyOfficeUrl 配置化;loadDocsApi 单例按需加载,弹窗 await + 失败提示 原每次进门户无条件请求 http://<host>:9050(死链必现错误;HTTPS 下被混合内容拦截)
base-卡7 94bd9674 public/js/config.js、新增 utils/aiChatApi.ts、AIChat.ts(6 处)、MiniChat.vue(9 处)、.env.development、types/global.d.ts AI 接口地址配置化(aiChatUrl/difyUrl),删除全部硬编码 IP;difyApiKey 改 config 可配 HTTPS 部署下明文 IP fetch 全量失效;换网段部署需改码重构建
base-S-W d0120534 hooks/web/useWebSocket.ts、useVentWebSocket.ts、balancePress 两页 WS 三断点修复:①不再覆写 vueuse open/close(原致连接无法关闭/断线永久死亡);②connectWebSocket 按 url 幂等(原每次调用新建连接覆盖全局变量,同一条告警被 N 个连接重复分发);③balancePress 匿名回调改命名 + 卸载 offWebSocket + warnModal destroy(原离开页面后告警弹窗照样弹且成倍增加);useVentWebSocket 真 close + autoReconnect + watchEffect 防叠加 告警通道可靠性
base-L14b fdf7839d index.html 删除 deepblue 主题指向不存在图片的 background-image 行 与 L14 同款 404 隐患

第三组:QA 缺陷修复(1 提交)

编号 commit 文件 改动 为什么
base-D1 7617a39e(并入) pnpm-lock.yaml 重新生成本地 lockfile(plyr 清零) 删 plyr 后 lockfile 未同步,CI frozen-lockfile 场景会失败(QA 实测发现并提供再生 diff)
base-D2 7617a39e(并入) configurable/index.vue:90 60s 轮询补 interval = 赋值 S-T1 同款模式的最后一处遗漏(QA A3 复核发现)

验证记录

结果
QA 静态核验矩阵 9/9 PASS(24 个治理点逐一到位,证据 docs/audit/验证-基座perf-base-v1-20260911.md)
语法校验 14 个 .ts + 42 个 .vue 全量校验 0 真实错误
pnpm build 生产构建 成功(dist 343MB;office-preview/tinymce 等为独立异步 chunk)
dist 产物 modulepreload 收敛为 5 个 vendor;6005/8000 硬编码 IP 不再进入运行时代码;:9050 仅剩代理表字符串;应用自有 console 清除
消毒链路 4 处高危 v-html 全部经 DOMPurify 白名单管线
WS 消费方兼容 7 个 useWebSocket 消费方 API 兼容(导出签名未变)

E2E GUI 冒烟(本地 nginx:新基座 dist + 修复版子应用 dist + 生产后端反代)

场景 结果
登录 → 首页三维场景 渲染完整(Cesium 地形/巷道/设备/实时数据),console 0 错误、9050 请求 0 次
首页 → 设备监测页(tunMonitor&windrect&tabtype=monitor,生产上永久加载的变体) 遮罩 19s 正常收起,页面完整渲染(36 条实时数据),零报错——生产上该页 15 分钟永不完成
内存 加载期峰值 ~1.2GB(含在途 GLB),稳定后正常

风险与回退

  1. 构建未在本机全量复跑:本机 node_modules 曾被 pnpm 12 失败重装破坏(cross-env 丢失)。QA 在损坏前已完成 pnpm build 验证(构建成功 + 产物核验),其后仅 D2 一行改动未随 dist 验证——合并后请重跑 pnpm build(先 pnpm install 修复 node_modules)。
  2. 行为变化点(审核关注):① connectWebSocket 异 url 互斥(当前部署各 url 殊途同归 :9999 同频道,风险低→观察项 O1);② useVentWebSocket 开启 autoReconnect(原一次心跳超时即永久断流);③ 生产 mock 关闭(若某接口依赖 mock 需核实);④ 工作区路由 glob 内的 blue/ventNew copy.vue 未删除(有路由风险,仅修了其中的定时器赋值)。
  3. 回退:每组改动独立 commit,git revert <commit> 单项回退;整组回退 git revert <A> <B>(第一组/第二组各自连续)。

遗留清单(本轮不做,已登记 docs/19)

  • MiniChat.vue:388 第二枚硬编码 dify key(深度思考开关覆写 APIKEY)→ 建议增加 difyApiKeyR1 配置项;
  • ventNew copy.vue 死文件删除(落在路由 glob 内,需先确认 DB 菜单无引用);
  • 全仓 echarts dispose 补齐(46 处 init 仅 3 处 dispose)、巨型内联 SVG 静态化、3D 子应用保活、批次 3/4(9050 反代落地、mp4 懒加载、three 按需化)——按 docs/19 §8 排期。

与其他分支/文档的关系

  • perf-base-v1 已包含 fix-subapp-loading 全部修复(挂载遮罩 60s 兜底 + 卸载竞态修复);
  • 子应用侧配套分支:msx/VentModelWeb perf-load-v5(切页 keep-alive 复用 + 生命周期治理,QA Go)——建议两分支配套合并部署
  • 审查依据与完整缺陷清单:docs/19;仓库更新后新增代码审计:docs/18。