# 版本记录(观澜·如东样板 v2) > 本文件由 `scripts/version_log.py` 生成,**勿手改**:事实(版本号、级别、变更)写在 > `src/version.py` 的 `HISTORY` 里,改完跑 `python scripts/version_log.py --write`。 > `guanlan.py check` 与打包器都会校验本文件与代码里的版本号是否一致。 ## 版本号规则(用户令 2026-09-17) 编号 **`v<大版本号>.<中版本号>.<小版本号>`**,例如 `v2.86.0`。 | 级别 | 含义 | |---|---| | 大版本号 | 系统解决方案、架构或核心功能改变 | | 中版本号 | 非核心功能新增、减少、修改 | | 小版本号 | 消缺完善 | **怎么改**:改动落在"解决方案/架构/核心功能" → 大 +1(中/小归 0);落在"非核心功能的新增/减少/修改" → 中 +1(小归 0);只是"消缺完善" → 小 +1;一次发布混了几类,取最高那一级 **打包文件名** = `app_guanlang_v2.86.0.zip`(规则:`app_guanlang_v<版本号>.zip`)。 版本号只写在 `src/version.py` 一行(`VERSION = '2.86.0'`);打包器、安装脚本、安装记录 `install-info.json`、自检都读它,不另设真源。 | 版本 | 日期 | 级别 | 主要变更 | 说明 | |---|---|---|---|---| | `v2.86.0` | 2026-10-06 | 中 | 汇报定制:章节正文渲染器从 v2.9.2 原文移植(此前为空实现) | 用户反馈:「汇报定制」页面与原页面不一致。**实逮根因**:Vue 版里两块是**空实现** —— `factsHtml = computed(() => "")` 与 `blockHtml = () => ""` ⇒ 选中任何章节,纸面上**什么都不渲染** (而一致性判据只比默认视图「预览为空」⇒ 两边一致 ⇒ 判据 15/15 也没发现)。**修**:把 v2.9.2 的 `rptFacts` / `rptK` / `rptBlock`(app.js 第 531–571 行)**原文移植**为 `src/lib/reportBlocks.ts`(工厂形式接收注入的 t/fmt/esc/dv/displayText/chart/SYS_KEY/sysName/stateChip/unitNo/STEP/winName/语言包/RPT/FACTS),仅做机械适配:`CH.x(` → `chart("x", `、`D.` → `d.`、`BD` 明确为 `d.fus.链盘`(旧页 app.js:541 的原始定义)。同时在 Report.vue 接线 `blockHtml/factsHtml`,并让 App 为 report 页签补取 `/api/facts`(事实卡契约来源)。**过程实逮(自身缺陷,均已修)**:① 抽取旧码时少取一行 ⇒ 括号不闭合(构建报 Unexpected end of file);② 重复导入 winName(Identifier already declared);③ 语言包导出名是 `ZH` 而非 `zh`。**验证(真应用 jsdom · 点「月报」预设)**:`BEFORE_ELS 1` ⇒ `AFTER_ELS 575 · BLOCKS 10 · CHART_HOSTS 4 · TEXT_LEN 4180`,正文首段为「观澜 · 运行分析报告 / 统计期 2026年 | 38 台 / 9 个章节 / 250,744MWh 上网电量 / 理论可发 287,713 / 1,650h 等效满发小时 / 94.8% 时间可用率 / 12.8% 损失率 / 36,968 MWh / 172h 平均停机间隔 …」,`ERRS 0` ✓。 | | `v2.85.2` | 2026-10-05 | 小 | 修「执行重算」第 ⑦ 步失败:「kb_ingest.py」 把 「_install_root」 误写成 「_p._install_root」 | 用户令(选 A):等"数据重算"跑完后复跑判据。**过程中实逮一个后端代码 bug**:整轮 「rebuild」 耗时 2,701 s、21 步里**只有第 ⑦ 步「本体: 码表/手册/文档」失败** ⇒ 「app_ontology/app_ontology_guanlan/ontology/kb_ingest.py:74」 调用了 **「_p._install_root(__file__)」**,而 「_install_root」 是本模块第 20 行 「from app_common.app_common_guanlan.api import install_root as _install_root」 (或第 23 行的兜底定义)导入的**模块级函数**;「_p」 在此处解析成了别的东西(报错:「AttributeError: module 'pathlib' has no attribute '_install_root'」)⇒ 该步失败并**中断整轮重算**(后面步骤依赖它 ⇒ 「/api/fleet」 持续 500 · 页面呈"无数据")。**修**:全仓检索同写法,仅此 1 处 ⇒ 改为 **「_install_root(__file__)」**;并在远端**单独跑该步验证通过**:「python -m src.ontology.kb_ingest」 ⇒ 产出 「{AlarmCode: 555, WorkInstruction: 559, FailureMode: 150, MaintTask: 559, Doc: 303, Component: 9, causedBy: 60, …}」 ✓。随后重新触发整轮 「rebuild」(各步幂等)以补齐后续步骤,待 「/api/fleet」 恢复 200 后再复跑结构/内容两套判据(15/15 目标)。 | | `v2.85.1` | 2026-10-05 | 小 | 措辞政策定案:以实时接口(当前算法)用词为准;3 条差异改判为「基线旧快照用词」 | 承接上一轮"建议第 2 步":统一 「链判级」 / 「窗末月?」 / 「平均停机间隔(MTBO)」 三处措辞差异。**先查清来源(实测)**:这**不是**同一系统两条路径互相打架,而是「**v2.9.2 基线页面自带的旧快照用词**」与「**当前算法新词**」之差 —— 实时 「/api/fleet」 里新词**内部一致**(「MTBO口径」 1 处 · 「变化口径」 1 处 · 「纯故障口径」 1 处;旧词 0 处),而基线 「detail_v2.html」 里旧词 7 处、新词 0 处。**用户裁定(2026-10-05):选 A —— 以当前算法新词为准**(「口径」 等),旧快照用词视为已过时。**落地**:判据工具 「tools/render_parity_v292.mjs」 中三条例外的 「why」 由"待后端统一口径"改判为「**基线旧快照用词 vs 当前算法新词 · 以实时接口为准 · 预期差异(非缺陷)**」,并在版本记录留档。**现状说明(重要)**:本轮复跑对拍时发现 「/api/fleet」 返回 **500(110 B)** —— 因为**产物已被用户"清除产物"清除**,故基线页与 Vue 侧都取不到数据、对拍必然 [X](**预期现象,不是回归** ✓)。待用户执行「执行重算」后,需复跑结构/内容两套判据确认仍为 15/15(本轮之前刚跑过:结构 15/15 · 内容 15/15 ✓)。 | | `v2.85.0` | 2026-10-05 | 中 | 清产物后给友好空态(不暴露 HTTP 500) | 用户令:清除产物后相应页面不显示数据,**提示要友好(不要报 HTTP 500)**。**修**:「App.load()」 对 4xx/5xx/异常**一律视为"暂无数据"** ⇒ 「d = {}」(空快照 ⇒ 各页照常渲染空态、不崩)+ 「dataMissing = true」,页面顶部给友好可操作提示(i18n 「app.data_missing」:「暂无数据:产物尚未生成或已被清除。请到「系统维护」页执行「数据重算」(或在 /ops 控制台点「执行重算」),完成后本页会自动刷新。」),**不出现任何 HTTP 状态码**。**过程实逮(两处自身缺陷,均已修)**:① 脚本因锚点不匹配漏插 「const dataMissing」 ⇒ 打包产物报 「ReferenceError: dataMissing is not defined」;② 「System.vue」 的 vue import 漏补 「onMounted」 ⇒ 「ReferenceError: onMounted is not defined」(system 页签渲染失败)。**验证(模拟 「/api/fleet」 返回 500)**:七个页签(overview/energy/component/vibration/generation/fault/system)逐一 ⇒ 「errs=0」 · 「friendly=true」 · 「leaks500=false」 ✓。 | | `v2.84.1` | 2026-10-05 | 小 | 清产物/重算后工作台自动重取数(并加「刷新数据」);实测空数据各页显示空态 | 用户要求:**「清除产物」完成后,工作台相应功能(总览/电量算账/部件问题/振动融合分析/发电性能/故障统计)不应再有数据展示**。**实逮的问题**:这些页的数据来自 「/api/fleet」(按窗实时 ✓),但清除产物是在 「/ops」 控制台里点的 ⇒ **Vue 应用不会自动重新取数** ⇒ 页面仍显示清除前的数据。**修**:① 「System.vue」 在 「/ops」 iframe 「load」 后(同源 ✓ 可直接访问其文档)监听 「#b_off」(清除产物)/「#b_rebuild」(执行重算)/「#b_start」/「#b_stop」/「#b_restart」 的点击,动作后 **4 秒**触发 「refresh」;② 重算块上方加**「刷新数据」**按钮(手动兜底);③ 「Workbench」 透传、「App」 新增 「reload()」 —— **清空页签级缓存 「apis」/「curves」 后重新 「load()」 与 「ensureTabApis(当前页签)」**。**验证(用空数据模拟"清完产物",不做破坏性操作)**:把 「/api/fleet」 返回置为空对象后,六个页签逐一渲染 ⇒ 「overview elements=113 · energy elements=5(正文为「电量算账 无数据」)· component 21 · vibration 82 · generation 9 · fault 43」,**全部 「errs=0」(不崩)** ✓ —— 即清除后重取数时,各页会如实呈现"无数据/占位符"状态 ✓。 | | `v2.84.0` | 2026-10-05 | 中 | 修「清除产物 404」:网关加 Path=/ops/api/** 专用路由(并实逮网关一直未真正重启) | 用户反馈「系统维护」内嵌的 /ops 控制台里点「清除产物」报 **404 操作被拒绝**。**排查链**:该按钮调 **「/ops/api/<动作>」**(该页 API 前缀 「/ops/api/」);**直连 Python 网关 28086** ⇒ 「/ops/api/state」 **200 · 1,155 B**(正常);**经 Java 网关 28084** ⇒ **404**,响应体是 **Spring 的 「{"timestamp":…,"status":404}」** ⇒ 说明**没有路由匹配**、请求没到 28086。**实逮根因(两个叠加)**:① 路由表里 「ops → 28086」 的谓词是 「Path=/ops/**」 + 「Path=/ops」,但运行中的进程用的仍是**旧配置** ⇒ **网关根本没有真正重启**(旧 pid 50588 一直存活;此前几轮 「sc stop/start」 的回显都是空的、实际未生效);② 为稳妥起见还在路由表**最前**加了一条专用路由 **「ops-api」 「Path=/ops/api/**」 → 28086**。**修法**:改 classpath 「application.yml」 ⇒ **先 「taskkill」 旧 pid、再 「sc stop/start guanlan」、轮询确认端口换新 pid** ⇒ 实测 **旧 pid 50588 → 新 pid 53904** ✓,随后 「/ops/api/state」 经 28084 ⇒ **200 · 1,155 B** ✓(「/ops」 仍 200 ✓)。**判据**:「/ops/api/state」 经网关必须 200(直连本就是 200)✓ —— 达标。**教训(已记入)**:改配置后必须**确认进程换新 pid** 才算重启成功,回显为空不能当作已重启。 | | `v2.83.3` | 2026-10-05 | 小 | 修「系统维护」数据重算按钮消失:内嵌改为直接 iframe src=/ops | 用户反馈「系统维护」里的「清除产物」「数据重算」按钮又没了。**根因**:这两个按钮位于**内嵌的 「/ops」 运维控制台**内;该块此前用的是 Blob-URL iframe(与「振动 CMS」同一批尝试),在你的浏览器上不显示。而 「/ops」 的 「X-Frame-Options」 早在 **2.81.4** 已放开(网关 「frameOptions().disable()」,实测响应头无 DENY ✓)。**修**:把该块改回**最朴素、与 v2.9.2 门户同款**的写法 —— 直接 「