# -*- coding: utf-8 -*- """版本与安装信息的**唯一真源**(2026-09-17 用户令 1:安装时检查已装版本、提示差异、问是否重装)。 为什么单开一个模块:以前版本号散在三处(`scripts/pack_dist.py` 的 `VERSION`、README 抬头、说明书标题), 改一处忘一处就会出现"包说 0.4.0、安装记录说 0.2.0"这种对不上的事。现在: src/version.py ← 唯一真源(本文件) scripts/pack_dist.py ← 读它写进 dist-manifest.json 与默认包名 install.ps1 / install.sh ← 读它写进 <安装目录>/install-info.json,并与已装的比对 guanlan.py / 各文档 ← 读它(文档里的人工版本号以它为准) `install-info.json` 落在安装根本身(不在 run/ 里):它是**交付物级别的安装记录**, 卸载/重装/拷机都要跟着走,所以和 `configs/`、`dist-manifest.json` 同级。 """ from __future__ import annotations try: from ._root import install_root as _install_root except ImportError: # 直接当脚本跑(python <本文件>)时没有包上下文 from _root import install_root as _install_root import datetime as dt import json import pathlib NAME = '观澜·如东样板 v2' VERSION = '2.78.2' # ★ 版本只改这里 EDITION = 'offline-single-package' PACKAGE_STEM = 'app_guanlang' # 交付包文件名前缀(用户令 2026-09-17) INSTALL_INFO = 'install-info.json' # 相对安装根 SERVICE_NAME = 'guanlan' # Windows 服务名 / systemd 单元名(用户令 1) SERVICE_DISPLAY = '观澜·如东样板 v2 (Guanlan Wind Asset Intelligence)' # ── 版本号规则(用户令 2026-09-17)──────────────────────────────────────────────── # 编号: v<大版本号>.<中版本号>.<小版本号> 例: v2.5.0 # 定义: 大版本号 —— 系统解决方案、架构或核心功能改变 # 中版本号 —— 非核心功能新增、减少、修改 # 小版本号 —— 消缺完善 # 包名: 打包文件名 = app_guanlang_v<版本号>.zip 例: app_guanlang_v2.5.0.zip # 用法: 用户/发布者定"这次算哪一级"→ VERSION 改一行 → 打包器与安装脚本自动跟着变 # (级别判据见 BUMP_RULE;一次发布混了几类就取最高那一级) RULE = 'v<大版本号>.<中版本号>.<小版本号>' LEVEL_MEANING = { 'major': '大版本号 —— 系统解决方案、架构或核心功能改变', 'minor': '中版本号 —— 非核心功能新增、减少、修改', 'patch': '小版本号 —— 消缺完善', } BUMP_RULE = ('改动落在"解决方案/架构/核心功能" → 大 +1(中/小归 0);' '落在"非核心功能的新增/减少/修改" → 中 +1(小归 0);' '只是"消缺完善" → 小 +1;一次发布混了几类,取最高那一级') # 版本记录(人读的那份由 scripts/version_log.py 生成到 docs/版本记录.md;这里只有事实,不重复描述) # level: major/minor/patch 表示这一版**相对上一版**是哪一级变化;legacy 表示该版用的是 # 旧编号体系(0.x,未按本规则),仅作历史对账用。 HISTORY: tuple[dict, ...] = ( dict(version='2.78.2', date='2026-10-04', level='patch', title='修「登录后进不了工作台」:补 /detail/v2 路径判定 + 修 TDZ;门户三入口改 target=_top', note='用户反馈「登陆后没有进入工作台」。**两个真因**:① `App.vue` 只按 hash 判模式,**没有 `/detail/v2` 路径判定** ⇒ 门户里的「登录」(指向 `/detail/v2`)打开后仍是**门户模式** ⇒ 看起来"没进工作台"(且会回到门户,形成循环)。补 `const _isDetail = /\\/detail\\/v2\\/?$/.test(location.pathname)` 并纳入模式判定。② 补判定时又踩到 JS **暂时性死区(TDZ)**:`if (_tabInHash) tab.value = _tabInHash` 被我写在 `const tab = ref(...)` **之前** ⇒ 抛错导致**整页空白**(`#tab=…` 场景全白)。已把赋值移到声明之后。③ 门户里的入口改写:门户跑在 iframe 内,链接必须 `target="_top"` 才能打到顶层窗口(此前改成 `#workbench` ✗,外层 Vue 收不到 ⇒ "迁移看起来没生效")。现改为:振动·CMS → `/detail/v2#tab=vibration`、交付文档 → `/detail/v2#tab=documents`、数据重算 → `/detail/v2#tab=recalc`、登录 → `/detail/v2#workbench`(均 `target="_top"`)。**行为实测(jsdom 真跑、用远端真实 fleet 214 KB 作夹具)**:`/detail/v2` ⇒ `wrap=true tabs=14 active=总览`(进工作台 ✓);`/detail/v2#tab=vibration` ⇒ `wrap=true tabs=14 active=振动融合分析`,子选项卡 `["融合矩阵","端到端闭环","逐台情况","报警工单","振动分析"]` ✓ —— 即用户要求的三项迁移(振动 5 子视图随窗 · 交付文档 · 数据重算 与系统维护并列)在 `/detail/v2` 下均已可用。远端已部署(36 件)。'), dict(version='2.78.1', date='2026-10-04', level='patch', title='修门户正文出现原始标记文字:装配口径照 portal_build.py(模板包进