」**;新增 「portalCmsDoc(d, cms, portalCss)」 生成整页文档。**过程实逮**:p71 的替换脚本把 「const F = computed(() => props.d?.fus)」 整行换掉 ⇒ 「bodyHtml」 里 「F.value」 报错、整个振动页渲染失败(iframe 也不出现);已补回 「const F」。**核验(真应用渲染)**:「FRAME Y · srcdoc 36,137 字符」 · 「HAS_PORTAL_CSS true」 · 「HAS_HERO_TITLE true」(振动与 SCADA 联合分析)· 「CHIPS_ROW true」(「.chips」 行就位)· chip 共 12 个(含按窗实时值:当前时间窗/需关注/未见异常/窗口内报警工单/CMS 采集窗/CMS 裁决/行动项)。远端已部署 36 件。'),
dict(version='2.81.5', date='2026-10-05', level='patch',
title='修「系统维护」等页签内容未加载:App 改为按页签按需取数',
note='用户反馈:工作台「系统维护」里除「数据重算」外的其他内容未加载。**实逮根因**:App 的 「load()」 **只取 「/api/fleet」**,而各视图要的数据走 「props.apis[...]」:「System.vue」 要 「/api/maint_survey」、「Decision/Report」 要 「/api/ask_models」、「Generation」 要 「/api/curves」 ⇒ 这些接口在真实页面上**从未被请求过** ⇒ 页签内容为空(旧页是**按页签按需取**的)。**为何判据曾是绿的**:一致性/对拍脚本会把接口数据**喂**给 Vue 侧,掩盖了"应用自己不取数"这一层。**处置**:「App.vue」 增 「TAB_APIS」 映射与 「ensureTabApis(id)」(取过即缓存,失败也记 error 不阻塞),「watch(tab)」 在进入工作台时按需取数,并把 「apis」 / 「curves」 传给 「Workbench」(此前未传)。**验证**:真应用选中「系统维护」时实际请求 「["/api/maint_survey","/api/fleet"]」 ✓(「MAINT_CALLED true」);用**远端真实** 「/api/maint_survey」 夹具渲染,巡检表与文字(覆盖/末次更新/责任…)出现 ✓。'),
dict(version='2.81.4', date='2026-10-05', level='patch',
title='修「数据重算」看不到清除产物/重算按钮:网关去掉 X-Frame-Options 默认 DENY',
note='用户反馈:并入「系统维护」的「数据重算」里**没有"清除产物""重算按钮"**。**根因(实逮)**:那两个按钮位于内嵌的 **「/ops」 运维控制台**里(该页按钮:「b_start」/「b_stop」/「b_restart」/「b_off」=清除产物(直接删除,不留备份)✓,「/ops」 本身 200·9,889 B 完全可用),但 「/ops」 的响应头带 **「X-Frame-Options: DENY」** ⇒ **浏览器拒绝把它放进 iframe** ⇒ 页面上只剩 hero 与 chip、看不到控制台内容。该头来自**网关侧 Spring Security 的默认 frameOptions=DENY**(「GatewaySecurityConfig」 未覆写)。**处置**:在网关安全链里 「http.headers().frameOptions().disable();」(内网单机工具,去掉该头以支持**同源**嵌入;WebFlux 的 「FrameOptionsSpec」 没有 Servlet 的 「sameOrigin()」,故用 disable)。本地离线编译通过(class 4,310 B)→ 上传 「target/classes/.../GatewaySecurityConfig.class」 → 重启服务。**复验(远端响应头)**:「/ops」 ⇒ 200 · 9,889 B · **响应头 {}(已无 DENY)** ✓;「/」 200·413 B ✓;「/detail/v2」 200·413 B ✓;「/algorithm/healthz」 200 ✓。(「/api/fleet」 仍带 DENY —— 那是它自己另设的头,与 iframe 嵌入无关。)注:「backend-gateway/build_offline.py」 在"组装依赖"一步因离线取不到 maven 插件而返回非 0(「target/lib」 已存在,不影响编译产物),故本次按"编译是否产出新 class"判定后单独上传。'),
dict(version='2.81.3', date='2026-10-04', level='patch',
title='「系统维护」内的「数据重算」改为同源 iframe + 门户 CSS(渲染与 v2.9.2 一致)',
note='用户反馈「数据重算嵌入系统维护后与 v2.9.2 的系统维护 + 数据重算有差异」。**实逮差异点**:该节的 hero/chip 是**门户 CSS** 渲染的(深色 hero、圆角 chip),而我只是把 HTML 用 「v-html」 塞进工作台,门户 CSS 并未作用于该块 ⇒ 计算样式实测 「hero bg=透明/padding=0」、「chip 无背景」(门户里不是这样)。**处置**:照门户四节的既有手法,把这一节装进**同源 iframe(srcdoc = 门户 CSS + 「#recalc」 节原文)**,「width:100% · height:1420px · border:0」,「
」 保证链接打到顶层;该 iframe 仍标 「data-added="recalc"」,继续被一致性判据排除(「system」 页签仍 220 元素一致 ✓)。另外核实用户第 1 项:「振动 CMS」的按窗实时值**代码已在远端产物中**(「窗口内报警工单」/「CMS 采集窗」/「CMS 裁决」/「当前时间窗」 均在 bundle 内 ✓)⇒ 若界面未见,属浏览器缓存,需 Ctrl+F5。'),
dict(version='2.81.2', date='2026-10-04', level='patch',
title='「系统维护」内的「数据重算」改为 v2.9.2 原样(hero + 3 chip + /ops 控制台 iframe)',
note='用户反馈:并入「系统维护」的「数据重算」与 v2.9.2 有差别。**实逮**:我在该处放的是**自写的**状态面板(「Recalc.vue」:运行状态 + 开始重算按钮 + 日志 pre),而 v2.9.2 门户的「数据重算」节是「运维 · 数据重算与产物」hero + 3 个 chip(● 重算期间按钮全灰 / ● 后端拒绝 = 真生效(HTTP 409)/ ● 重算产物即时进页面)+ **内嵌 「/ops」 控制台 iframe**(宽 100%、高 1150px、「loading=lazy」)+ 「直接打开:/ops 控制台」回退链接。已按原文替换:抽出 「lib/portalRecalc.ts」(864 字符,取自门户 shell 的 「#recalc」),「System.vue」 用 「v-html」 渲染该块;iframe 在门户里由 JS 赋 「src」,此处直接写 **「/ops」**(同源相对路径,原 「
」 也改为 「/ops」)。该块是**用户指定并入**的新增内容,已在判据工具中按 「data-added」 子树排除(「struct_diff.mjs」),故 「system」 页签仍为 **220 个元素一致** ✓。核验:块存在 ✓ · kicker「运维 · 数据重算与产物」✓ · iframe 「src=/ops」 + 「title=数据重算与产物」 ✓ · 回退链接 「/ops」 ✓。'),
dict(version='2.81.1', date='2026-10-04', level='patch',
title='「振动 CMS」页数值全部按窗/CMS 实时(并修 portal_cms 未触发取数)',
note='用户令:「振动 CMS」页要**按窗实时值**。① 窗口侧实时:当前时间窗(「d.win」)、需关注/未见异常(「d.fus.kpi」 候选观察/全场,随 「/api/fleet?win=」 变)、**窗口内报警工单条数**(「d.fus.事件.主轴.工单.总条数」);② CMS 侧实时(「/api/vibcms」):采集窗 + 时间范围(「窗」/「时间范围」)、裁决分布(「grades」 统计优秀/良好/报警)、行动项条数(「action」)、数据时点(「date」);③ 移除门户里**写死的**「TCM 六采集窗 · 320 万记录 · 160 万谱」——该记录/谱计数**接口并不提供**,故改为用接口可得的实时项替代(不编造)。④ **实逮并修**:按需取数只对 「cms」 触发,「portal_cms」 未触发 ⇒ CMS 侧 chip 全为 0;已改为两者都触发。双窗验证:窗口「2026年」 ⇒「当前时间窗 · 2026年」「需关注 35 台」「窗口内报警工单 · 11 条」「CMS 采集窗 w0316 · 2026-03-16 → 2026-04-21」「CMS 裁决 · 优秀 32 / 良好 3 / 报警 3」「行动项 … 条 · 数据时点 2026-09-29」;切到「全程」 ⇒ 时间窗与需关注/未见异常随之变化 ✓。'),
dict(version='2.81.0', date='2026-10-04', level='minor',
title='门户「振动·CMS」迁入「振动融合分析」为并列子选项卡「振动 CMS」(受时间窗影响)',
note='用户令:把门户的「振动·CMS」迁到「振动融合分析」里,成为与"融合矩阵/端到端闭环/逐台情况/报警工单/振动分析"**并列的第 6 个子选项卡「振动 CMS」**,且**受时间窗影响**。实现:① 从 v2.9.2 门户 shell 抽出 「#cms」 节(1.6 KB:hero + 状态 chip + 入口)为 「src/lib/portalCms.ts」;② 「lib/vib.ts」 的 「FUS_SUBS」 增 「portal_cms」(6 项),新增 「portalCmsHtml(d)」:把门户里的**静态数字**替换为**按当前时间窗实时算**的值 —— 「需关注 N 台」「未见异常 M 台」取自 「d.fus.kpi」(候选观察/全场,二者随 「/api/fleet?win=」 变化)、「证据窗末」取 「d.fus.证据窗末」,并**追加一个「当前时间窗 · 」chip**(直接体现窗口);③ i18n 增 「fus.sub.portal_cms」(zh:振动 CMS / en:Vibration CMS);④ 「Vibration.vue」 接 「portal_cms」 分支。**实测(真应用 jsdom 点击 + 两个窗口对比)**:子选项卡为 ["融合矩阵","端到端闭环","逐台情况","报警工单","振动分析","振动 CMS"](6 个);点「振动 CMS」出门户内容(HAS_HERO true:振动与 SCADA 联合分析 / 六层模型…);**随窗变化**:窗口「2026年」 ⇒ chips ["当前时间窗 · 2026年","需关注 35 台","未见异常 3 台",…];窗口「全程」 ⇒ ["当前时间窗 · 全程","需关注 9 台","未见异常 29 台",…] ✓。远端已部署 36 件。'),
dict(version='2.80.2', date='2026-10-04', level='patch',
title='修「振动融合分析」点击子选项卡页面不变(弃用 v-unwrap)',
note='用户反馈:「振动融合分析」里点「端到端闭环 / 逐台情况 / 报警工单」页面没有变化。**根因(实逮)**:这些子视图的 HTML 挂在 「v-html」 + **「v-unwrap」** 上,而 「v-unwrap」 只在 「mounted」 **解包一次**(把宿主替换为子节点后把宿主移出文档)⇒ 之后 Vue 每次 「v-html」 更新都写进**已脱离文档的宿主** ⇒ 页面上永远是最初那一屏(表现为"点了没反应")。中途我曾把指令改成"注释锚点 + updated 同步",但在**数据异步到达 / 重复渲染**下锚点与节点归属会错位(实测元素数出现堆积与错位:matrix 10、units 4150 等),机制本身过于脆弱。**最终处置**:**弃用 「v-unwrap」**(「Assistant.vue」 / 「Decision.vue」 / 「Vibration.vue」 三处),改为保留宿主 「div.unwrap-host」 —— 先核实**没有任何 CSS 依赖 「#root」 的直接子结构**(扫描 0 条命中),故该层 div 无样式副作用;对拍工具本就把它按"透明"处理,**10/10 页签结构一致性不受影响**。**修复后真应用点击实测**(点 5 个子选项卡各一次,数 「#root」 元素数):matrix **1126**(基线 1126)· loop **13**(基线 13)· units 4151(基线 3398)· events **626**(基线 626)· cms 558(基线 543)—— 前三+events 与基线**逐字相同**,units/cms 因"真应用按真实数据/真实交互路径渲染"与SSR 对拍口径不同而略有出入(非堆积,多次点击不再增长)。'),
dict(version='2.80.1', date='2026-10-04', level='patch',
title='振动融合分析(含 5 个子页面)与 v2.9.2 差异核定;修 cms 子页面未取 /api/vibcms',
note='用户令:核定「振动融合分析」中所有页面(含子页面)与 v2.9.2 的差异并修改。① **判据补强**:「tools/struct_diff.mjs」 增加**子视图支持**(「tab:sub」:基线点 「#root [data-fsub=]」 停稳后比骨架,Vue 侧把 「sub」 传给 「renderTab」),于是 5 个子页面都进了结构对拍。② **结构**:vibration 「matrix/loop/units/events/cms」 = **5/5 一致**(1126 / 13 / 3398 / 626 / 543 个元素)。③ **内容**:同 5 项文本/表格/图数字 = **5/5 一致**(561 / 9 / 1126 / 492 / 158 项文本;表 1/0/2/9/2 张;含 1 条已登记例外:后端"页面按窗缓存 vs 实时 /api/fleet"的措辞差异,非前端)。④ **实逮到一处真实差异(工具此前掩盖)**:旧页在选中 cms 子视图时会**按需异步取 「/api/vibcms」**(「app.js:980」),而 Vue 应用**从不取该接口**(只在契约里声明路径、靠父组件传 「cms」 而无人传)⇒ **真实打开「振动分析」时无数据**;我的对拍脚本会替它喂数据,所以此前判据是"绿的"却与实际不符。已修:「Vibration.vue」 选中 cms 时按需 「fetch(\'/api/vibcms\')」(prop 优先,保持对拍同源口径 + 「cmsErr」 兜底)。**真行为验证**(真应用 + 远端真实 「/api/vibcms」 6,297 B 夹具):点击「振动分析」⇒ 实际发出 「["/api/fleet","/api/vibcms"]」、「VIB_CMS_CALLED true」、渲染出表格 **39 行** ✓。'),
dict(version='2.80.0', date='2026-10-04', level='minor',
title='页签精简(去「架构与资料/门户」、数据重算并入系统维护)+ 删除页头模式按钮(修布局乱)',
note='用户两项:① **页签精简** —— 工作台页签由 14 减为 **11**:去掉「架构与资料」(其首个子选项卡即"系统架构")与「门户」;「数据重算」不再单列页签,改为并入 **系统维护** 页签内的一个区块(「System.vue」 内渲染 「」)。现页签为:总览 · 电量算账 · 部件问题 · 振动融合分析 · 发电性能 · 故障统计 · 检修决策 · 检修助手 · 汇报定制 · 系统维护 · 交付文档。② **修布局乱** —— **实逮**根因:页头里还残留一组"模式按钮"(工作台 / 契约自检 / 关于本前端),它们用的容器也是 「