返回 Skill 列表
extension
分类: 数据与分析无需 API Key

泛微-OA系统数据分析

自动获取E9系统中全局设置、人事、内容、流程和周期性分析五域数据,并分析数据健康度,整理检测报告,支持oracle、sqlserver、mysqy和达梦数据库; 自动获取E10系统中人事、内容、流程和周期性分析四域数据,并分析数据健康度,整理检测报告,支持oracle、sqlserver、mysqy和达梦数据库;

person作者: user_c2018d06hubcommunity

E9 应用诊断 · 端到端报告生成

把「复用浏览器已登录 OA 会话 → 四域全量只读取数 → 生成正式客户报告 HTML + 2018TX-011 覆盖 Excel」整套流程做成可一键复用的 skill。方法论(四域切分、评分模型、红线铁律、环境预检)详见 e9-diagnosis-plan skill,本 skill 负责实际执行与产出

⚠ 本 skill 运行路线(2026-08-14 校正) 端到端闭环:取数完成后自动生成报告与覆盖 Excel。唯一路线 = CDP 复用已登录 OA 会话(密码零接触,符合认证红线): oa-diag-datas/node_cdp_driver.js(取数 → 报告/oa_diag_result.json)→ oa-diag-datas/report/gen_report_v6.js(v6 互动版 HTML + 客户版打印 HTML)→ oa-diag-datas/report/__render_v6.js --pdf-only(客户版 PDF)→ oa-diag-datas/report/gen_full_coverage.py(2018TX-011 覆盖 Excel),一条命令 node run_all.js 全出。取数按 system(e9/e10) 调驱动、按 db(oracle/sqlserver/mysql/dameng) 选语句 SQL 集。所有生成物统一落 oa-diag-datas/报告/(见「五-4」)。 旧路线(Chrome 扩展 oa-diag-ext 数据源+建模虚拟表、scripts 直连 Oracle 主库 + diag_config.json 密码配置)已于 2026-08-14 删除,请勿再引用。

一、产物(端到端:取数 → 报告 → 覆盖 Excel 一体)

  • oa-diag-datas/node_cdp_driver.js取数入口(薄调度层)。解析取数目标(system/db/oaUrl/cfgId)→ 校验能力(失败快退)→ 回显确认 → 调对应驱动。复用浏览器已登录 OA 会话(CDP,9222 端口)取数,落盘 报告/oa_diag_result.json(items[] 结构)。密码零接触
  • oa-diag-datas/drivers/:取值方式层。e9_datashow.js(E9 数据展现通道,已实现,4 库通用);e10_api.js(E10 新接口,P2 占位);index.js(system→驱动 注册表)。
  • oa-diag-datas/dialects/:SQL 语句层。e9/oracle.json(✅ 已实测 87 条,含第 5 域「全局设置情况」11 项)、e9/sqlserver.jsone9/mysql.jsone9/dameng.json(⚠ 机器初翻、未实测,须逐库核对)。index.js(db→SQL集 注册表)。

第 5 分析域「全局设置情况」(2026-08-27 落地 E9 oracle;v10 改名,原称「系统整体情况」)

  • 分类名称:全局设置情况(跨 系统设置 SYS / 授权 LIC / 版本升级 VER / 文档 DOC 四子组,精选 11 项)。
  • key 约定:ov_ 语义前缀(如 ov_pwd_lock/ov_lic_expire/ov_upgrade_stall),方言 item 额外携带 src(SYS-/LIC-/VER-/DOC- 源码编号)、name(中文标题)、desc(检测目的)、sev(crit/warn/info) 四个字段,作为名称/说明/判定的单一事实源,供后续报告第 5 域与跨方言推广直接复用。
  • 11 项映射:SYS-02→ov_pwd_lockSYS-04→ov_log_keepSYS-05→ov_doc_backupSYS-06→ov_doc_zipSYS-08→ov_lic_remindSYS-09→ov_sensitiveLIC-01→ov_lic_expireLIC-05→ov_nonstd_funcDOC-06→ov_attach_dirVER-04→ov_upgrade_freqVER-03→ov_upgrade_stall。(⚠ ov_sysver 已于 2026-08-26 删除,不在 oracle.json / 生成器内;其替代项为 ov_attach_dir。)
  • 三处 SQL 落地(事实源):dialects/e9/oracle.json(87 条,含 name/desc/sev/src)、项目根 diag_sqls.json(87 条)。⚠ oracle_diag_full.py 已于 2026-08-27 退役并隔离至 _quarantine/(原为直连脚本、含硬编码凭据,违反红线),不再作为同步目标或验证手段;验证一律走 CDP 数据展现通道。
  • ⚠️ 验证方法纠正(2026-08-27):上一轮误用项目根 oracle_diag_full.py(直连 192.168.2.37:1521/ecology,含硬编码 user/password/ip)做 SQL 可执行性检查——此属 skill 已于 2026-08-14 删除的旧路线,违反「不直连库 / 密码不进文件 / 数据库 IP 不进文件」红线。该直连检查仅确认了 SQL 语法与返回结构正确,不构成 skill 要求的验证。本域 11 项的规范验证必须经 CDP 复用已登录 OA 会话 → 数据展现集成通道(drivers/e9_datashow.js)执行,详见「九、红线」与「四、取数机制」。
  • 待推广(规范验证已完成 ✅):① ✅ 经 CDP 数据展现通道规范重验 11/11 全 OK、0 失败(2026-08-27,OATRAIN E9+Oracle,配置 11003「获取数据测死」,零点击、密码零接触;结果见 oa-diag-datas/报告/oa_diag_result.json);② e9 其余方言(mysql/sqlserver/dameng) 改写并实测;③ e10 全方言;④ ✅ 报告第 5 域已落地(2026-08-27,基于 oa_diag_result.json 前台生成三产物):gen_report_v6.jsgen_customer_report.py 均已接入 ov——DOM_NAME/DOM_COLOR/problemsov、两处 DESC_MAP 增 11 条、totalScore 由 scoreFromTriggered 触发式改为**「用户给定阈值」线性引擎**(v11,与 gen_customer_report.pyscore_hr/wf/km/sys/ov 完全一致:域集合 E9={hr,wf,km,sys,ov}/E10={hr,wf,km,sys},period 仅作内容章不计入评分)、overall 改按 SCORED_DOMS 均值(E9/5、E10/4)、score_ov() 直接评分(ov 为描述性指标,不靠 problem_rules 触发判定);互动版增「系统整体情况(11)」标签页 + 9 个 ov 图表 + 可下钻明细表,客户版增「二、全局设置情况」章节(首个域章节)。三产物:报告/诊断报告-E9-互动版.html(2.4MB)/诊断报告-E9-客户版.html(514KB)/诊断报告-E9-客户版.pdf(720KB)。
  • 遗留处置 ✅oracle_diag_full.py 已于 2026-08-27 退役并隔离至 E:/workbuddy/系统信息分析/_quarantine/(已移除硬编码 user/password/ip,消除直连红线),不再作为同步目标或验证手段;验证一律走 CDP 数据展现通道。项目内另有历史 192.168.2.37 引用(ds_sql_server.pye9-drive/bak/oa_diag_result_*.json)待专项清理。
  • oa-diag-datas/targets/:每环境目标配置(你提供参数的落点),如 oatrain.json
  • oa-diag-datas/report/gen_report_v2.js正式 HTML 报告生成器(旧版单页布局)。读 JSON → 渲染增强版客户报告。输出 oa_diag_report_oatrain.html。⚠️ 此为 2026-08-22 之前的旧版式,已被 v6 取代,仅作回退保留。
  • oa-diag-datas/report/__frag_buildhtml.js + __assemble_v6.js + gen_report_v4.js(基类/内嵌数据) + gen_report_v5.js(PDF 正文):v6 最终版式生成链路(详见「五-2」)。gen_report_v6.js 为已组装好的 v6 生成器(oatrain 定稿样例,已支持 5 域含 ov 域)。报告产物现统一输出到 oa-diag-datas/report/(互动版/客户版 HTML+PDF,命名带 -v6 后缀以标识 v6 版式产物);oa-diag-datas/报告/ 仅留取数 JSON(oa_diag_result.json 等)与历史基线留档(gold 客户版 .html/.pdf),不再作为主产物输出目录。
  • ~~oa-diag-datas/report/gen_full_coverage.py~~ 【已移除 2026-08-31】:原 2018TX-011 覆盖 Excel 生成器(模板与脚本已删除)。
  • oa-diag-datas/run_all.js一键端到端编排。顺序执行 取数 → v6 报告(互动版 HTML + 客户版 HTML + 客户版 PDF)→ 覆盖 Excel,产物全部落 报告/
  • oa-diag-datas/captured_save_full.jsonCDP 保存请求实战抓包模板(取数驱动必读,不可或缺)。
  • ~~oa-diag-datas/2018TX-011-泛微客户应用数据情况诊断20190527.xlsx~~ 【已移除 2026-08-31】:官方模板(覆盖 Excel 复用),已删除。
  • references/four_domain_items.md:四域子项 ↔ SQL key 映射与覆盖说明。

二、前置条件

  1. 复用已登录会话(默认):Chrome 已登录 OA,开启远程调试端口 9222(--remote-debugging-port=9222),并停在「集成中心→数据展现集成」(engine.html#/integration/datashow) 页面。
  2. AI 启动独立浏览器(设 E9_LAUNCH=1:无需手动开端口。驱动用 playwright 拉起一个带调试端口的独立浏览器(优先系统 Chrome,持久化 profile 保留登录态),你在弹出窗口登录,驱动自动检测登录态后继续。需设 E9_OA_URL=http://你的OA地址:端口
  3. Node + playwright-corenode_cdp_driver.js 内部 require('playwright-core'),回退本机 C:/Users/Administrator/.workbuddy/binaries/node/workspace/node_modules/playwright-core
  4. Python + openpyxl(仅覆盖 Excel 需要):受管 venv 已建 C:/Users/Administrator/.workbuddy/binaries/python/envs/default 并装 openpyxl。运行 Excel 时用该 venv 解释器(或设 E9_PYTHON 指向它)。

三、运行(端到端:取数 + 报告 + 覆盖 Excel)

方式 A:复用已登录会话(默认,向后兼容)

cd <skill>/oa-diag-datas
NODE="C:/Users/Administrator/.workbuddy/binaries/node/versions/22.12.0/node.exe"
$NODE node_cdp_driver.js                  # 未指定 E9_CFGID 时先枚举数据展现配置并让你选(不再静默默认 11003)
E9_CFGID=10504 $NODE node_cdp_driver.js   # 指定其他数据展现配置
$NODE node_cdp_driver.js --enumerate      # 仅枚举当前 OA 的数据展现集成配置(写 datashow_configs.json 并打印)

方式 B:AI 启动独立浏览器(你只需登录 + 选配置)

# 1) 启动浏览器 → 你登录 → AI 枚举配置列表(写 datashow_configs.json)
E9_LAUNCH=1 E9_OA_URL=http://oa.x.com:port $NODE node_cdp_driver.js --enumerate
# 2) 你从列表选一个配置 ID 告诉 AI;AI 用该 ID 取数:
E9_LAUNCH=1 E9_OA_URL=http://oa.x.com:port E9_CFGID=<你选的数字ID> $NODE node_cdp_driver.js
# 一键端到端(取数→报告→Excel):
E9_LAUNCH=1 E9_OA_URL=http://oa.x.com:port E9_CFGID=<ID> $NODE run_all.js

终端为交互环境(TTY)时,node_cdp_driver.js(不设 E9_CFGID)会自动枚举并让你输入编号/ID/名称 选择,无需手动指定。选择清单(printList)自适应 E9(id/标识/名称/所属机构)与 E10(id/名称/创建人/创建时间)两种格式,一律 ID+名称一起显示。

环境变量 / 参数

| 变量 | 说明 | 默认 | |---|---|---| | E9_SYS_TYPE | 系统版本:e9 / e10(e10 选了会提示「P2 未实现」) | e9 | | E9_DB_TYPE | 数据库语句:oracle / sqlserver / mysql / dameng | oracle | | E9_LAUNCH=1 | AI 启动独立浏览器(否则复用已登录会话) | 关 | | E9_OA_URL | OA 基础地址,launch 模式必填 | 空 | | E9_CFGID | 指定数据展现配置 ID(未指定则先枚举并让你选,不再静默默认)。回显确认与执行日志均带配置名称(从 datashow_configs.json 反查,如 11003(名称=获取数据测死)) | 无(必须选) | | E9_CONN_NAME | E10 指定数据连接器名称(按名称匹配);不设则自动解析(默认连接器→匹配 dbType→首个)。run_e10_full.js 取数前会先打印连接器清单(ID+名称+库名+是否默认)并标出将使用哪一个 | 空(自动) | | E9_CDP_PORT | launch 浏览器暴露的调试端口 | 9222 | | E9_CDP_URL | connect 模式连接地址 | http://127.0.0.1:9222 | | E9_LOGIN_TIMEOUT | 等待登录超时(秒) | 180 | | E9_HEADLESS=1 | launch 用无头模式(服务器/CI 测试用) | 关 | | E9_CHROME_EXE | 指定 Chrome 路径(默认自动探测系统 Chrome) | 自动 | | E9_PROFILE | launch 浏览器持久化 profile 目录 | ./.cdp-profile | | E9_PYTHON | 覆盖 Excel 生成用的 python 解释器 | 系统 python | | --target <name> | 读取 targets/<name>.json 作为取数目标(优先级高于环境变量) | - | | --enumerate | 仅枚举当前 OA 数据展现配置列表并退出 | - |

  • 取数驱动打印每项 [OK]/[ERR] 与 ok/fail 计数;报告脚本打印大小与严重/警告/关注数;覆盖脚本打印输出路径。
  • 产物均在 oa-diag-datas/ 同目录。
  • 报告图表为服务端内联 SVG,直接用 Chrome 打开 HTML 即可看到全部图(无需浏览器端 JS)。

多系统切换(换 OA)

  1. 复用会话模式:在目标 OA 登录、开 9222、停 datashow 页;或直接用 launch 模式。
  2. launch 模式(推荐,最简单)E9_LAUNCH=1 E9_OA_URL=<新OA地址> 启动浏览器 → 你登录 → --enumerate 拿到当前 OA 所有数据展现集成配置列表 → 你选一个数字 ID,设 E9_CFGID=<ID> 取数。无需手写任何配置 ID / subcompanyid——枚举自动列出全部配置,取数按你选的数字 ID 执行(已实测:subcompanyid 不影响取数,仅后台归类字段)。
  3. SQL 按 db 选对应语句文件(dialects/e9/<db>.json),逻辑 key 不变,报告/覆盖 Excel 零改动复用。Oracle 已实测;非 Oracle 语句为机器初翻、未实测,须逐库核对后再用于真实取数。重出报告:report/gen_report_v2.js / report/gen_full_coverage.py 可反复跑(读 JSON 重渲染),不依赖再次连库。

四、取数机制详解(CDP 复用已登录 OA 会话)

核心链路(oatrain.cn:9999 实战钉死,全程序化、零点击)

  1. POST /api/integration/datashow/getDataShowOperation(operator=save,type=BTN_SAVE) 把 SQL + 字段定义(keyfield / dtinfo_MergedFieldData)写回配置 11003;
  2. POST /api/integration/common/searchpagetablekey(body=各字段名空值 + showtypeid=11003) 返回一次性 dataKey=searchpagetablekey-pageid-11003_<令牌>
  3. POST /api/ec/dev/table/datas(带该 dataKey) 返回真实数据行 {datas:[...]}

脚本自动:从 SQL 列别名解析字段定义(深度感知括号/引号的 splitTopLevel/selectColumns/extractAlias)、清洗 E9 列表渲染注入的 <span> 包裹、每 5 条落盘一次防丢失。最终 JSON 结构 {generatedAt, configId, fetchMode, redline, count, ok, fail, items:[{key,cap,sql,columns,rows,rowCount,error}]}

模板注意:保存请求体固定字段来自实战抓包 captured_save_full.json(取数驱动必读)。旧手工模板 save_template_11003.json 已删除,请勿使用。

五、报告与覆盖生成

  • gen_report_v2.js:读 报告/oa_diag_result.json(环境变量 E9_DIAG_JSON 可覆盖),渲染增强版报告(环境变量 E9_REPORT_HTML 可改输出路径)。健壮性靠 R0(key) 安全取首行——某项取数失败/空数据返回 {} 也不硬崩,空数据降级出占位报告;DESCRIPTIONS 把 key 映射成中文标题实现中文化;`singleMetrics()`` 把单值指标外露成卡片。(旧版单页布局,2026-08-22 起由 v6 取代)
  • ~~gen_full_coverage.py~~ 【已移除】:原 2018TX-011 覆盖 Excel 生成器,已删除。

五-2、v6 最终版式报告(2026-08-22 锁定,后续客户报告统一用此版式)

版式规范(强制):本版为可交付客户的最终锁定版式,换系统/换客户重出报告时必须沿用,不得回退到 v2 单页布局。

  1. 主体问题总览 = issuegrid 卡片流(参照 oatrain 参考报告的 .issue/.it/.id):严重(crit)与警告/关注(warn/info)分两组;标题带 [系统人员/系统流程/知识管理/周期性诊断] 域前缀,副标题带「实测值 / 阈值」;点击卡片直达对应域。
  2. 严重/警告分离 + 折叠:总览中严重组默认展开、警告/关注组默认折叠(#ov-warnfolded);每域面板内严重卡片默认展开、警告/关注卡片默认折叠(#pwarn-<dom>folded)。严重度图例:红=严重 / 橙=警告 / 蓝=关注。
  3. 诊断域 = 标签页.tabs + .panel):v11 起共 6 个标签 = 4 个评分域(人力资源 / 流程管理 / 知识管理 / 全局设置情况;系统运行 v13 起并入 HR「登录与密码安全」,仅 E10 保留独立域)+ 周期性诊断(内容章,不计入评分);E10 无 ov → 4 评分域(人力资源/流程管理/知识管理/系统运行)+ 周期内容章。标签带问题数;ov 标签显示「全局设置情况(11)」。激活态显示域色+白字。域内结构:.dhead 标题 → 4 张 .kpis 指标 → .dsummary 导读 → 严重卡片(展开)/ 警告卡片(折叠)/ .charts-grid 图表;ov 域额外渲染 ovTableHtml() 11 项可点击下钻明细表。
  4. 图表懒渲染renderCharts(domain) 仅在标签被点击时绘制(rendered[domain] 守卫),避免 21 张图首屏开销。
  5. 穿透明细 = 右侧 sticky 面板:四域标签页下为 1fr 380px 双栏(.dom-layout + .dom-content + 右侧 .detail-panel{position:sticky;top:14px})。点击图表元素联动填充右侧明细(表 + 搜索/排序/分页 + 整改洞察)。≤1100px 回落单列、面板 static;@media print 隐藏 .detail-panel.panel 强制 display:block、卡片 page-break-inside:avoid
  6. 诊断说明(.diag-note)四项(⚠ 取消「数据来源」第一项):仅保留 ①采集范围 ②判定口径 ③安全规范 ④报告日期。不得再加回「数据来源」
  7. 图表含异常染色:异常图表挂 .anom-badge(crit/warn 级别由 problems[].drillKey 关联),徽章数 = 触发问题的图数。

双产物架构(2026-08-22 固化):每个系统出 互动版 + 客户版 两份报告,版式均为 v6 最终版式、命名统一:

  • 互动版(HTML)report/gen_report_v6.js(JS,issuegrid 总览 + 五域标签 + 右侧 sticky 穿透面板),产物 报告/诊断报告-{SYS}-互动版.htmlE9_REPORT_HTML 环境变量可覆盖输出路径)。--pdf 标记已停用(客户版改由 Python 生成)。
  • 互动版 ov 域(v9,2026-08-27 14:48 当前版本)ovPanelHtml() 渲染 5 个段组(.ov-group),结构 = 段标题独立元素.ov-section <h3> + CSS ::before 4×15px 主题色竖条 + 黑字粗体 15px + 右侧 .sub 段摘要)+ 内容区。5 段主题色:授权与版本 #1e40af(蓝)/ 安全基线 #d97706(橙)/ 文档与备份 #16a34a(绿)/ 附件目录 #7c3aed(紫)/ 特殊清单 #7c3aed(紫)。每段形式(v8 起固化):授权与版本 3 卡(授权完整信息 / 升级情况 / 授权提醒配置)/ 安全基线 3 卡(密码策略 / 敏感词策略 / 日志保留)/ 文档与备份 2 卡(不等宽:文档备份占 2 列宽 .ov-card.span-2 + 文档压缩·加密占 1 列宽,第 3 个位置空置) / 附件目录 普通明细表 .ov-table(不做卡片)/ 特殊清单 · 非标功能启用 汇总卡 .ov-sum(>5 行时仅显示汇总,明细穿透右侧面板)。v8 起取消「其他情况检测明细」整段:不再展示 11 项项目编号/数据上限/采集行数。ovTableHtml() 函数保留为 no-op 返回 ''(保证 PDF 链路的 ctxRows 调用不报错);CSS 也已清理。卡片样式 .ov-cardovCard(title, lines, drillKey, cardColor, cardClass)):与四域 .pcard 同款——白底 + border-radius:10px + box-shadow:0 2px 8px rgba(15,23,42,.06) + border-top:3px solid 顶部色带(v9 替代 v7/v8 的左竖条 4px 粗线条)+ 标题 + 右侧「明细 ›」+ 内嵌字段键值对(.lbl 灰标签 / .val 黑值);lines 支持 [label, value, state] 三元组按 state 着色(.val.bad/.val.warn/.val.ok);hover 阴影加深 + 上浮。第 5 个参数 cardClass 接受 'span-2' 让该卡片 grid-column: span 2卡片与卡片并列 grid .ov-cards {grid-template-columns:repeat(3,1fr); gap:12px}必须出现阴影效果否则"看着就是一片看不出来是单独的卡片"——这是用户原话。附件目录不用卡片:统一用 .ov-table(白底圆角 10px + thead sticky #f8fafc + tbody hover #f0f7ff),每行 cursor:pointer 穿透右侧明细。ov 严重问题通过 problem_rules.json(9 条规则:ov_lic_days <30 crit/<90 warn / ov_stall_mon >18 crit/>12 warn / ov_pwd_lock_off=0 crit / ov_sens_off=0 warn / ov_log_short <30 warn / ov_zip_unenc=0 warn / ov_backup_missing=0 crit)触发,与四域同款 .pcard.crit/.warn 流(圆角渐变阴影基线)→ ov 严重问题卡片样式与四域完全一致不要回退到 v4 单行副行扁平形态、v3 实色横条反白文字、v2/v5 不用 rules 触发的形态、v6 旧版卡片化附件目录(.ov-card-item)/卡片化其他情况检测明细(.ov-meta-item),也不要把「其他情况检测明细」段加回来——v8 起永久取消。
  • ov 域(全局设置情况)展示 v9(当前:v9 顶部色带 + v8 取消其他情况检测明细 + v8 文档备份 span-2)ovPanelHtml() 取代旧 9 个单值柱状图;ov 严重问题由 problem_rules.json 触发进入 .pcard 流,与四域同款。metrics.js 加 13 个 ov 派生指标(ov_lic_days / ov_stall_mon / ov_upgrade_freq_12m / ov_pwd_lock_on / ov_pwd_lock_err / ov_sens_on / ov_sens_90d / ov_log_days / ov_zip_compress / ov_zip_encrypt / ov_backup_period_min / ov_backup_dir_set / ov_remind_on)。ov_sysver 已取消(不在生成器内,也不在 oracle.json 内);ov_attach_dir 为其替代项。互动版 1529 KB / 21 图表 / 健康度 54(v11 起两版统一为「用户给定阈值」线性评分引擎,oatrain 实测:ov 触发 1 严重 + 2 警告 = 升级停滞 20 月 / 授权剩余 64 天 / 日志 5 天;与客户版 54 严格一致)。

⚠️ v10 固化(2026-08-27):ov 域「系统整体情况」→「全局设置情况」,并前移为 E9 客户版首个域章节(二、全局设置情况,位于一、诊断概览之后)。PDF 红线:客户版 PDF 仅由 gen_customer_report.py(22222 模板 HTML)经 __render_v6.js --pdf-only 生成,与互动版 HTML 完全无关——绝不在互动版链路里加 PDF 步骤。② 客户版 OV 页内容ov_panel_html()(Python,与互动版 ovPanelHtml() 同款五段:授权与版本 / 安全基线 / 文档与备份 / 附件目录 / 特殊清单·非标功能启用)已写入 gen_customer_report.py,五段内容随 PDF 一并交付。③ E10 不动gen_customer_report.pyHAS_OV = (SYS=='E9') 控制——仅 E9(有 ov_ 数据)走新结构(OV 首章 + 章节重排 + 五段面板);E10 暂未移植 ov_,保持原结构(HR=二、OV 末章六、章节不重排)字节级不变。 ⚠️ v11 固化(2026-08-27):两版评分引擎统一,分数严格一致。根因:此前互动版用 scoreFromTriggered(触发式、地板 35)+ problem_rules.json,客户版用「用户给定阈值」线性函数,且两版评分域集合错开一个(互动有 period 无 sys、客户有 sys 无 period)→ 同一数据出现 互动版 47 / 客户版 54 的不一致。② 统一方案:互动版 gen_report_v6.js 的评分整段替换为与客户版 gen_customer_report.py 完全相同的线性阈值引擎scoreHr/Wf/Km/Sys/Ov 移植为 JS,逐字段对齐 items.get(key).rows[0][col] + int(x or d) 语义),域集合统一为 E9={hr,wf,km,sys,ov}(5 域)/ E10={hr,wf,km,sys}(4 域)period(周期性诊断)降为纯内容章节(保留标签页/图表/问题清单),不计入评分。③ 补齐结构:互动版原无 sys 章节,新增 kpiHtmlsys 分支(暴力破解/密码风险/离职未回收 KPI)并将 sys 纳入标签页/面板,使其与客户版(6 章:5 评分域 + 周期内容章)结构对齐。④ 实测对账(oatrain E9):两版逐域分完全一致 = 全局设置 55 / 人力资源 30 / 流程管理 46 / 知识管理 66 / 系统运行 75,综合健康度均 54。⑤ E10 不动HAS_OV=(SYS=='E9') 门控——E10 评分域 = 4(hr/wf/km/sys)、概览表 4 行、不纳入 ov;客户版 overall 分母随 HAS_OV 条件化为 /5 或 /4。⑥ PDF 红线不变:客户版 PDF 仍仅由 gen_customer_report.py__render_v6.js --pdf-only 生成,与互动版无关。⑦ 目录二级对齐:客户版 toc_rows 二级条目去掉 4 空格前导,「1.」与一级「一、」左对齐(正常排版)。 ⚠️ v12 固化(2026-08-27):客户版 TOC 二级缩进恢复 + PDF 页眉页脚丢失根因修复。TOC 二级缩进(纠 v11 误判):v11 把「二级缩进」误读为「左对齐」而去掉 4 空格前导;实际用户要缩进表达层级。toc_rows 二级条目恢复 4 空格前导,toc_html 生成时把 " ""&nbsp;&nbsp;&nbsp;&nbsp;"(普通空格在打印时折叠会丢缩进)。② PDF 页眉页脚丢失 = 规则缺陷(非偶发):页眉页脚是写进每个 .page div 内的 .page-hdr-new/.page-foot-new HTML 元素(Chrome 打印未用 displayHeaderFooter),靠 position:absolute; bottom:8mm 定位;当单 .page 内容 > A4 297mm 时 absolute footer 落可视区外 → 该页页脚丢失/错位。实测 page 5(ov 全局设置)五段同页溢出。③ 最终修复:保留 v11 absolute footer(短页贴底正确),仅把 page 5 ov 拆为 5a/5b 两个 .page divov_panel_html() 改返回 (top_html, bot_html),在「文档与备份」后插 <!--OV_SPLIT_MARKER-->partition 拆分;top=授权+安全基线+文档与备份+建议、bot=附件目录+非标功能)。page_footer 11 处条件化为 (n if HAS_OV else n-2),PAGE_TOTAL=17(E9 增 1 页;E10 仍 16)。④ 失败尝试已回退.page{display:flex;flex-direction:column}+footer margin-top:auto 引入 2 个空白页(实测 p6/p18),已弃用。⑤ 实测:客户版 HTML 534458 B/17 页、PDF 约 811 KB;pypdf 验证 17 页零空白页、p2-p17「第 X 页 共 17 页」连续、每页页眉+内容+页脚完整;TOC 二级 &nbsp; 缩进生效。⑥ E10 不动HAS_OV=(SYS=='E9') 门控保持页码/总页数条件化。 ⚠️ v13 固化(2026-08-28):E9 取消「系统运行(sys)」域(冗余+重复计分澄清)。用户质疑:互动版 E9 出现「系统运行」分页,其 KPI「离职未回收账号」与 HR 域 KPI 同一指标重复出现(展示层 2 次);问是否重复计分。② 澄清:评分重复——每版 sys 仅在 SCORED_DOMS/_scored 计入一次;"2 次"是展示冗余(离职未回收同时挂在 HR KPI 与 sys KPI)。③ 处置(仅 E9,E10 字节级不变)sys 域从 E9 两版整体移除——互动版 SCORED_DOMS E9 分支去 'sys'['ov','hr','wf','km']);客户版 _scored E9 去 s_sys[s_hr,s_wf,s_km]+([s_ov] if HAS_OV else []))、删「六、系统运行情况」章、概览表去 sys 行、toc 去该项并重排(周期/问题/总结→六/七/八)、sec-h2 章节号条件化、PAGE_TOTAL=16、页脚连续 2-16。sys 指标(离职未回收/暴力破解/密码风险)并入 HR「登录与密码安全」(客户版该章已含暴力破解/密码风险,数据不丢失)。④ 实测对账(oatrain E9):两版逐域分一致 = 全局设置 55 / 人力资源 30 / 流程管理 46 / 知识管理 66,综合健康度均 49(4 域均值,原 5 域 54)。互动版 p-sys 面板消失、客户版无 sys 章;客户版 PDF pypdf 验证 16 页零空白页、页脚 2-16 连续。⑤ E10 不动:E10 仍 4 域(hr/wf/km/sys)含 sys 章(末章五),HAS_OV=(SYS=='E9') 门控保持。⑥ 防回归:勿把 sys 重新加回 E9 两版(会再次造成离职未回收重复展示);若未来要恢复系统运行独立域,须先把「离职未回收账号」从 HR KPI 中移出避免重复。 ⚠️ v15 固化(2026-08-28):E9 客户名称从授权端点「授权公司」自动获取(而非 OA 地址主机名)。截图反馈:客户版封面"客户名称"显示 oatrain.cn(访问域名),用户要求改为"获取到的客户名称"。② 根因:driver 未采集客户名,gen_customer_report.py:21 注释"默认取 OA 地址主机名" → fallback OA_URL.split('//')[-1].split(':')[0] = oatrain.cn,与"客户名称"语义不符。③ 方案选择:经用户确认,E9 从授权端点 ov_lic_expire.rows[0]["授权公司"] 抓取(oatrain 实测值=e9test,即客户全称/单位名);E10 保持现状不更改(driver 不写入 customer 字段 → 生成器 fallback 到 oaUrl 主机名,行为与 v14 完全一致)。④ driver 改动node_cdp_driver.js:135 后):取数完成后,从 resultskey==='ov_lic_expire',取 rows[0]['授权公司']rows[0]['公司名'] → trim → 仅当 target.system==='e9' 且非空时,条件展开 {...(customerName ? { customer: customerName } : {})} 写入 oa_diag_result.json 顶层。⑤ 生成器改动gen_customer_report.py:21,86):优先级改为 args.customer > DATA.get('customer','') > oaUrl host;注释「默认取 OA 地址主机名」改为「优先级: --customer > JSON.customer > OA 地址主机名」;E10 因 JSON 无 customer 字段,无缝回退 v14 行为。⑥ 验证:oatrain E9 重跑取数 87/87、JSON 顶层 customer='e9test';客户版 HTML 515516 B / PDF 791046 B / 16 页零空白;pypdf 抽 p2 封面文字:以下数据为 e9test(E9 / Oracle)提供 + 报告制作人: 泛微客服部已无 oatrain.cn。⑦ E10 不动:E10 driver 不写 customer → 生成器 fallback oaUrl host = v14 字节级行为。⑧ 防回归ov_lic_expire SQL 端点必须保留且首列名保留为「授权公司」或「公司名」;如端点重命名或列名变更,须同步改 node_cdp_driver.jscustomerName 提取逻辑,避免再次回退到 oaUrl 主机名。 ⚠️ v16 固化(2026-08-28):E9 互动版右侧穿透明细——1) 内容少时不再出滚动条;2) 非标功能清单不显示「实现类」列。两个截图反馈:ov_doc_backup panel 只有 1 行 3 列 K-V 内容(备份目录路径较长),底部仍出现横向滚动条;ov_nonstd_func 表格显示「非标编号 / 功能名称 / 实现类 / 状态」4 列,其中 实现类 全是 com.weaver.upgrade.domain.UpgradeXXX 类路径,对客户与一般阅读无意义,要求不显示。② 根因:① .metric-cell .mv{font-size:19px;...} 缺换行控制,长字符串(如 oa/weaver/ecology/filesystembackup)撑出 metric-cell → 撑出 sticky panel 380px → 触发 .dp-body{overflow:auto} 横向滚动条。② renderDetail() line 985 直读 it.columns 透传给 dtable,无任何过滤;it.columns=4 时 4 列全显示。③ 处置gen_report_v6.js 顶层 line 32-33 + clientJS IIFE 内 line 896 同步镜像):1) 新增 HIDE_COLS 映射 + filterCols 函数(IIFE 内部也要 mirror 一次,因 clientJS 是模板字符串独立注入,不引用顶层 scope):var HIDE_COLS = { ov_nonstd_func: ['实现类'] }; function filterCols(key, cols){ var h = HIDE_COLS[key]; return h ? cols.filter(c => !h.includes(c)) : cols; }renderDetail line 985 改为 var cols = filterCols(key, it.columns||[])。2) CSS .metric-cell .mv 加换行控制.mv{font-size:19px;...;word-break:break-all;overflow-wrap:anywhere;line-height:1.25}。④ 端到端验证:模拟数据 ov_nonstd_func={columns:['非标编号','功能名称','实现类','状态'], rows:103 行}filterCols('ov_nonstd_func', columns)["非标编号","功能名称","状态"] 3 列(实现类已移除);ov_doc_backupmetric-grid 分支(rowCount=1, cols=3),最长文本 oa/weaver/ecology/filesystembackupword-break:break-all 下自动换行不撑出 panel,横向滚动条消失。互动版 HTML 重生成 2427 KB/约 21 图表 / 健康度 49 严重 6 警告 21。⑤ ⚠ 必须同步两处的根因:顶层 line 32-33 与 clientJS IIFE line 896 都要加 HIDE_COLS/filterCols,且结构保持完全一致,否则互动版浏览器会抛 ReferenceError(clientJS 自带闭包,不读取顶层)。⑥ 防回归:1) 后续若增加更多要隐藏的列,往 HIDE_COLS 顶/IIFE 两处同步添 key:[col1, col2];2) .metric-cell .mv 的换行控制不得删除(否则长字符串场景横滚会回来);3) 其它表格列若出现长字符串溢出,可复刻同样模式(word-break:break-all;overflow-wrap:anywhere;line-height:1.25)到对应 CSS 类。 ⚠️ v17 固化(2026-08-28):E9 互动版 metric-grid 单行明细面板由 2 列改 1 列(每项独占一行),长内容自动换行 + 空值友好提示。截图反馈:ov_doc_backup 面板里"文档主目录"为空(系统默认)、"备份目录"是有内容的长路径(oa/weaver/ecology/filesystem/backup)、"备份周期_分钟"=1440——当前 2 列布局把"文档主目录"和"备份目录"挤在同一行,"备份目录"的长路径在窄格里被压成 3 行碎片,每项之间没有视觉分隔、阅读吃力;用户问"是不是应该是两行,之后当内容长的时候内容自动换行会不会好些"。② 根因:① .metric-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px} 固定 2 列,3 个 K-V 时 2+1 分布导致路径类 cell 被挤窄。② .metric-cell .mv 只设了粗体大字号,缺 word-break:break-all;overflow-wrap:anywhere,路径 / 处不强制断行。③ 处置4 处源文件全部同步——gen_report_v4.js(CSS line 380-383 + buildHTML line 720-721)、__frag_buildhtml.js(clientJS CSS line 167-170 + 渲染 line 453-454)、__assemble_v6.js 组装出的 gen_report_v6.js、以及 skill 副本 oa-diag-datas/report/ 下 3 份):1) CSS 改 1 列布局grid-template-columns:1fr;gap:6px.metric-celldisplay:flex;align-items:baseline;gap:10px;min-width:0(值弹性伸缩 + 列名固定 80px 右对齐)。2) 空值友好:JS 渲染循环里判断 valStr.trim()==='' → 加 empty class,CSS .metric-cell .mv.empty{color:#cbd5e1;font-weight:500} + 文本替换为 (系统默认,未配置),与 v16 0 值场景统一。3) 字阶降一档(19px→15px、mv 列加粗 800→700),使 1 列布局下 8 行 hr_basic 等多列数值面板仍紧凑可读。④ 端到端验证(playwright 注入 mock):ov_doc_backup 渲染效果——「(系统默认,未配置)」 浅灰斜体(文档主目录)→ 路径按 / 断行成 2 行(备份目录)→ 1440 粗体蓝(备份周期_分钟),3 cell 各占一行无横滚;hr_basic 8 列 1 列布局下 8 行紧凑排列,无视觉冗长。⑤ 副作用(已确认可接受):所有走 metric-grid 路径的 1 行明细(HR 域 hr_basic/hr_no_cert/hr_probation/hr_pwd_risk、WF 域 wf_basic/wf_agent、KM 域 km_basic/km_zero_read/hr_leave_report 等 15 个)面板高度从 4 行→8 行,但每项独占一行更清晰,路径/地址类长内容不再被挤。⑥ 防回归:1) metric-grid 任何改回 2 列的提交都需重走 ov_doc_backup 长路径视觉验证(核心验收:oa/weaver/ecology/filesystem/backup 在窄格里 3 行碎片 = 必拒);2) gen_report_v4.js(buildHTML 源)+ __frag_buildhtml.js(clientJS 源)+ gen_report_v6.js(组装产物)三处 metric-grid CSS 同步改、缺一会被 assemble 重置覆盖;3) skill 副本 oa-diag-datas/report/{v4,v6,__frag_buildhtml}.js 与 workspace 报告样式方案/ 同步更新,下次导出 skill 时直接采用即可。⑦ 额外修复gen_report_v6.js:80 初始化 problems={hr,wf,km,period}ov:[],导致含 ov 域规则的 JSON 跑 gen_report_v6.jsCannot read properties of undefined (reading 'push')——补 ov:[](v15 移除 sys 域时漏改)。 # 【已移除 2026-08-31】整目录已删除

⚠️ v18 撤销(2026-08-28 15:27):用户撤回 v18 CSS 补丁,恢复 14:08 截图前 13:59 5 域原版。用户决策:v18 改动(label/value 分两行 + word-break + span-2 改 3 列)虽然视觉上"修复"了 14:08 截图投诉的"文档备份挤一行"问题,但用户认为v18 破坏了之前的内容,要求回退到 14:08 截图之前的状态(即 13:59 5 域完整版、未含任何 v17/v18 改动)。② 执行cp .bak20260828_v17rerun → 诊断报告-E9-互动版.html,15:27 字节级恢复 2427236 B(与 13:59 完全一致)。③ 备份结构oa-diag-datas/报告/):

  • 诊断报告-E9-互动版.html现行 5 域原版(无 v18)
  • 诊断报告-E9-互动版.html.bak20260828_v17rerun — 15:10 备份(5 域原版) ④ 教训:修复"用户已确认正常的报告"前须先确认改动是否会破坏既有结构,宁可不改也不要破坏;用户决策优先于 AI 视觉判断。后续如需再次修复文档备份面板排版,先以最小侵入方案(如只加 word-break 不动 layout)+ 用户确认后再落地。

⚠️ v18 固化(2026-08-28 15:21,作废):ov-card 卡片 label/value 改两行布局 + 长内容自动换行(v17 错位的更正)。背景纠正:v17 改的 .metric-grid 是 4 域 v6 生成器用的组件;用户日常在用的 5 域版(oa-diag-datas/报告/诊断报告-E9-互动版.html,13:59,5 域 + 11 项 ov 面板,DATA.RAW 格式)用的是 .ov-card 卡片 + .ov-card-lines 子容器,v17 改动对它完全无效。我之前一直盯着 E:\workbuddy\系统信息分析\报告样式方案\ 副本(v6.js 跑出的 4 域版)乱改一通,把 skill 报告目录的 5 域完整版覆盖成了 4 域错版——这才是用户说"这次修改后覆盖了之前的修改任务"的根因。② 用户真实诉求(ov-card 上下文):"文档备份面板,主目录空(系统默认),备份目录路径有内容,现在 label/value 放到了一行,是不是应该是两行;之后长内容自动换行好些"。③ 根因.ov-card-lines div 默认 display:block,3 个 div(主目录/备份目录/备份周期)已经各占一行,但每个 div 内部 label("主目录:")和 value("—")横排挤在一行——用户要的是 label 一行、value 下一行的"两行布局",且长路径在窄卡片里要自动换行(ov-card.span-2 3 列 grid 占 2 列宽 → 路径类可能溢出截断)。④ 处置(直接 CSS 补丁,锚点=.ov-card-lines div{line-height:1.85;color:#475569;font-size:12.5px} 后追加;字节增量 +384;5 域 HTML 报告 15:21 重生成 2427620 字节):1) .ov-card-lines > div{display:flex;flex-direction:column;align-items:flex-start;gap:1px;padding:2px 0} — 每行 div 内部上下排(label 上、value 下);2) .ov-card-lines .lbl{display:block;font-size:11px;color:#94a3b8;line-height:1.3;margin-right:0} — label 浅灰小字单独一行;3) .ov-card-lines .val{display:block;font-size:13px;color:#1e293b;font-weight:600;line-height:1.4;word-break:break-all;overflow-wrap:anywhere;max-width:100%} — value 单独一行 + 长内容自动换行 + 不溢出;4) .ov-card.span-2{grid-column:span 3} — "文档备份"等 span-2 宽卡片改占满 3 列,路径有充足空间不截断。⑤ 端到端验证(playwright 1440×900 截图实测):文档备份卡片——主目录/—、备份目录/oa/weaver/ecology/filesystembackup、备份周期/1440 分钟各自两行布局;所有 ov-card(授权/密码策略/日志/敏感词/文档压缩)统一受益同步改两行;路径完整显示不截断,长内容自动换行。⑥ 作用范围:仅 .ov-card-lines 子元素布局,其他卡片(ov-lic-row/ov-table/附件目录表)不受影响。客户版(22222 模板)无 .ov-card 组件,v18 对客户版无效也不需要。⑦ 已知遗留(v18 没动):a) 13:59 5 域报告的生成器不在 skill 目录(grep 全盘 0 命中"全局设置情况分析"/"ov-card-title"),下次取数后若要更新互动版,须手动同步 v18 CSS 补丁(不可直接 gen_report_v6.js 重生成,因它产 4 域无 ov-card)。b) v16 的 HIDE_COLS(隐藏"实现类"列)在 skill 生成器里仍缺失(v16 同步时漏了),用户当前没提,暂不补。c) 工作目录 E:\workbuddy\系统信息分析\报告样式方案\ 副本已与 skill 报告目录脱节,下次改任何报告样式须先确认改的是哪份(真版在 skill 报告目录,副本只是临时调试用)。 # 【已移除 2026-08-31】整目录已删除

⚠️ v19 固化(2026-08-28 21:23):互动版「明细掉到页面下方 + 后几个域错位」根因=ov-sum 嵌套 div 不平衡触发 HTML5 寄养,已修复并在源头固化。两个截图反馈:a) 各域穿透明细面板应固定在右侧栏,却掉到页面下方满宽;b) 后几个域(hr/wf/km/period)正文位置错乱(不在左列)。② 根因(实证,非假设)ovGroupsHtml() 的非标功能汇总块 ov-sum 结尾多写一个 </div>(3 个闭合,实际只需 2 个:.ov-sum-pills + .ov-sum),导致 HTML5 解析器「foster parenting(寄养)」提前隐式闭合 <section id="p-ov">,随后把 p-hr/wf/km/period 四个面板寄养出 .dom-content、把 .detail-panel 寄养出 .dom-layout → 整页 2 列 grid(742px + 380px)塌缩、detail-panel 落页面下方满宽。这是五域版特有(gold 四域无 ov-sum 块),故对比四域「看不出差异」——差异藏在 ov 域内容里。③ 定位手段(可复现):用 parse5(完整 HTML5 解析算法,含 foster parenting)解析生成 HTML,确认 p-ov 在 dom-content 内、p-hr/wf/km/period 寄养到 dom-layout、detail-panel 寄养到 .main;再用标签平衡扫描定位多余 </div> 位置;Edge 1920×1080 getBoundingClientRect() 实测验证几何(detail-panel x=1150,w=380 右栏 / panel x=390,w=742 左列)。④ 处置(最小手术,单文件)gen_report_v6.js 第 326 行 </div></div></div></div></div>(删多余闭合);回退诊断期误加的 3 处 grid-column CSS(实测无效——节点已被移出网格容器,CSS 放哪都没用)。源码保持干净。⑤ 验证:parse5 结构校验 5 个 panel 全在 dom-content、detail-panel 在 dom-layout 右栏;Edge 实测逐 tab 点击 ov/hr/wf/km/period,各 panel 恒左列、detail 恒右列。两举报全部消除。(注:打开/切换域的默认右栏内容在 v20 改为自动下钻本域第一个明细;『重置』按钮仍可回退到本域明细导航列表,11/18/12/9/5 项)防回归(关键,下次改 ovGroupsHtml/任何嵌套 div 必查):1) ovGroupsHtml() 内任一组(尤其 ov-sum)的 <div> 开闭必须严格平衡——单标签不平衡即塌整页、且不报任何错误,只看图才能发现;2) 改后必跑结构校验:运行时 .dom-layout 子节点必须恰为 [dom-content, detail-panel],且 5 个 section.panel 全在 dom-content 内(可用 __verify_v6.js 或 parse5 自检,检测 panel/detail-panel 是否被寄养出预期容器);3) 本次修复后 gen_report_v6.js正确支持 5 域(含 ov 域 ov-card + ov-sum)可直接重生成互动版——v18 固化⑦「已知遗留 a/b(生成器不在 skill/不可直接重生成/HIDE_COLS 缺失)」已随本次修复不再成立,勿再据此限制。⑦ 客户版不受影响gen_customer_report.py 走 22222 模板、不含 ov-sum 块,本次 bug 仅影响互动版,客户版无需改动。 ⚠️ v20 固化(2026-08-28 21:57):互动版右侧明细面板默认行为变更——打开/切换域自动下钻本域第一个明细(取代原默认显示明细导航列表)。用户要求:① 域右侧穿透明细面板,打开该域时默认展示本域第一个明细内容(而非明细导航列表);② 切换域后默认显示该域第一个明细。② 根因(与 v19 一致性的偏差):v19 固化⑤将默认行为写成「#dp-default 显示本域明细导航列表」(即 renderDefaultIndex(d) 输出的 .di-list),与用户当前要求不一致——属文档与生成对不齐。③ 处置(最小手术,单文件 gen_report_v6.js 的 clientJS IIFE):1) 新增 renderDefaultDetail(d) 函数(紧接 renderDefaultIndex 之后、同一闭包内):取 .domain-index[data-dom=d] 中首个存在 D.RAW[key].di-itemdata-key,直接 showDetail(key,{row:-1,label:null}) 下钻;若本域无任何可用明细(模块未启用)则回退 renderDefaultIndex(d)。2) switchTab(d) 末行由 renderDefaultIndex(d) 改为 renderDefaultDetail(d);初始加载末行 renderDefaultIndex('ov') 改为 renderDefaultDetail('ov')。3) 『重置』按钮保持 renderDefaultIndex(d) 不动——保留「回退到本域明细导航列表、可浏览全量明细条目」的能力,默认展开首个明细后仍能查看列表,不丢功能。④ 验证(Edge 1920×1080 getBoundingClientRect + DOM 实测):逐域打开/切换,右栏默认内容 = ov「授权完整信息」/ hr「人员账号总体概况」/ wf「流程路径总体概况」/ km「知识管理总体概况」/ period「月度流程新建请求」,#dp-body 均含 .dtable.metric-grid,detail-panel x=1150,w=380(右栏),无 pageerror。⑤ 防回归:1) renderDefaultDetailrenderDefaultIndex 须在同一 clientJS 闭包内(clientJS 是模板字符串独立注入,不读顶层 scope);2) 取首个明细时必须校验 D.RAW[key] 存在——DI_DESC_MAP 首项 key 可能对应未启用模块(无 RAW 数据),须跳过取下一个有数据的,否则 showDetail 会 early-return 留下陈旧内容;3) 若将来调整 DI_DESC_MAP 各域明细项顺序/增减,打开域默认下钻的「第一个明细」会随之变化,属预期行为;4) 切勿把 switchTab/init 改回 renderDefaultIndex(会退回旧默认=导航列表),除非用户明确要求。 ⚠️ v21 固化(2026-08-28 22:14):互动版 IIFE 闭包函数未挂 window 导致内联 onclick 全部静默失效(ov-card / ov-sum / 附件目录表行 / di-item 全部中招),已修复并在源头固化。用户反馈:ov 域「全局设置情况」里所有卡片(授权完整信息/升级情况/授权提醒配置/密码策略/敏感词策略/日志保留/文档备份/文档压缩·加密)和底部「非标功能汇总」点击后,右侧穿透明细面板没有变成对应的明细内容(图表点击却正常——因为图表用 canvas.onclick = fnRef 走闭包)。② 根因(铁证):clientJS 整段包在 IIFE (function(){...})() 内,showDetail / renderDetail / renderInsight / resetDetail / renderDefaultIndex / renderDefaultDetail 都在闭包里,没有 window.xxx 暴露。但 .ov-card(line 281)、.ov-sum(line 326)、ov 附件目录表 <tr>(line 321)、.di-item(line 341)都用内联 onclick="showDetail('key',{row:-1,label:null})"——内联 onclick 走 window 全局查找,找不到 IIFE 内的 showDetail(浏览器对未定义标识符仅抛 ReferenceError,无任何 UI 反馈,表现为"点了没反应")。③ 审计范围(grep 所有 onclick=\"...\"):共 13 处内联 onclick,修复前只有 toggleFold / gotoDomain / __sort / __pg / __pgTo 已挂 window(5 处可用),其余 8 处涉及 showDetail 的全部失效;pc-link 用纯 DOM API(getElementById+scrollIntoView)自包含,不依赖闭包。④ 处置(最小手术,clientJS IIFE 内 line 888 后追加 4 行)window.showDetail = showDetail; window.resetDetail = resetDetail; window.renderDefaultIndex = renderDefaultIndex; window.renderDefaultDetail = renderDefaultDetail;——把 4 个被内联 onclick 依赖的闭包函数一次性挂 window,零行为变更(这些函数本身不变,只是补全局可访问性)。⑤ 验证(Edge 1920×1080 + pageerror 监听):① 初始 ov 默认 = 授权完整信息(#dp-body.dtable,v20 行为无回归)✓;② 点击 ov-card「密码策略」→ 右侧 dp-name=「密码策略」、含表 ✓;③ 点击 ov-sum「非标功能汇总」→ 右侧 dp-name=「非标功能汇总」、含表 ✓;④ console / pageerror 零错误 ✓。⑥ 防回归铁律(极其重要)在 clientJS IIFE 内定义、又被 HTML 内联 onclick="..." 引用的任何函数,都必须在 IIFE 末尾挂一次 window.xxx = xxx;——这是 IIFE + 内联 onclick 混合模式的硬约束。后续如新增内联 onclick="someFn(...)",须同步给 someFnwindow.someFn = someFn;否则按钮/卡片/行/单元格的点击全部静默失效,无任何错误提示——只能用 Edge 模拟点击才能发现(仅看代码 grep window. 难发现,因为 IIFE 内函数本身合法)。⑦ 新发现但未修的预存 bug(v21 修复范围外,供下次治理):「重置」按钮调 renderDefaultIndex(d)getElementById('dp-default') 拿容器,但 renderDetail 早已用 body.innerHTML = h#dp-body 整块替换,#dp-default 容器在首次 showDetail 后就被销毁renderDefaultIndex 因此 if(!box) return; 提前退出——所以「重置回退到本域明细导航列表」这条路径实际是静默坏掉的(不是 v21 引入,是 showDetail 早就在替换 #dp-body)。要修须让 renderDefaultIndex 改写 #dp-body.innerHTML = '<div id="dp-default" class="di-list">' + idx.innerHTML + '</div>'(重建容器)。等用户拍板再做,不擅自动 v20 设计的「重置→列表」回退语义。

⚠️ v22 固化(2026-08-28 22:25):互动版每域 KPI 网格 .kpis 改为按数量自适应列数规则,整体宽度不变,按 5–6 / 7+ 自动调整。用户要求:每域 KPI 网格(页内 dhead 下方第一个白底卡片组):默认显示 4 个(4 列);当 KPI 数量 5–6 时,自动调整每一个卡片的宽度,放到一行显示;当 KPI 数量 ≥7 时,自动拆成 2 行显示;整体宽度(.kpis 容器)始终不变——绝不因 KPI 多而撑爆左栏布局。② 根因(前次实现语义不足):旧 CSS 硬编码 grid-template-columns: repeat(4, 1fr),ov 域 6 个 KPI 时自动 4+2 换行(后两卡占半宽),与用户期望的「6 全部挤一行、每卡更窄」不符;其他域都是 4 KPI 走默认。③ 处置(最小手术、单文件 gen_report_v6.js:1) CSS(L442–445).kpis{grid-template-columns: repeat(var(--cols,4), minmax(0,1fr)); ...} ——硬编码 4 列改 var(--cols,4) 变量化列数,并加 minmax(0,1fr) 允许列窄于内容;.kpimin-width:0; overflow:hidden.kn / .klwhite-space:nowrap; text-overflow:ellipsis 防溢出。2) HTML 生成器(buildHTML 渲染 .kpis 处):先 kpiHtml(d) 取内部 HTML,match(/<div class="kpi">/g) 计 KPI 个数 N;N∈[5,6] 时 --cols=N,否则维持默认 4 列——style="--cols:6" inline 注入到 .kpis 容器上。最终映射:N=1–4 → 4 列、单卡 178px、单行;N=5 → 5 列、单卡 140px、单行;N=6 → 6 列、单卡 115px、单行;N≥7 → 4 列、自动换行 2+ 行(N=7–8 拆 2 行,N=9–12 拆 3 行)。.kpis 容器宽度始终 ≈742px(左栏 .dom-content 宽度),不受数量影响。④ 验证(Edge 1920×1080 + 合成覆盖):1) 真实报告 5 域实测:ov n=6 → --cols=6、单卡 115px、唯一 y=1234(单行)、.kpis 宽 742px ✓;hr/wf/km/period n=4 → --cols=4、单卡 178px、单行、.kpis 宽 742px ✓;无 pageerror ✓。2) 合成 HTML 覆盖 n=1/2/3/4/5/6/7/8/9/12 十档:列数与行数完全符合上表映射,每档 .kpis 容器宽恒 742px ✓。⑤ 防回归铁律:1) --cols 必须 inline 设在 .kpis 上而非父容器——CSS 变量沿 DOM 树继承,父级设 --cols:6 会污染下方所有 .kpis;2) minmax(0,1fr) 不可缺——否则窄卡会被 1fr 的 min-content 撑爆,5–6 行情景下卡片宽度不会自适应;3) 取 KPI 个数用 match<div class="kpi"> 出现次数即可——不要去改 kpiHtml(d) 的返回值结构(多返回值会牵动后续所有调用点);4) 列数规则 N∈[5,6]→N、其余→4 是用户当面规定,不可凭"看着更整齐"随意扩到 7+(7+ 用户明确要拆行);5) 任何后续若 kpiHtml(d) 各域返回的 KPI 数量变化,ov 域(6→5 或 6→7)会自动重列,其他域若扩到 5–6 同样适配,无需再改 CSS

⚠️ v23 固化(2026-08-28 22:46):严重问题/警告折叠卡网格改为「N=1 占满整行 / N≥2 两列」自适应;建议与影响文本起点对齐。用户反馈:ov 域严重问题仅 1 张卡时,单卡只占左半(约 360px),右侧大量空白——与"每行 2 卡、单卡占 2 卡位"的预期不符;卡片内部"建议:"行比"影响:"行向右缩进,视觉不对齐。② 根因(双 bug):1) .probcards CSS 硬编码 grid-template-columns: 1fr 1fr——2 列网格下 1 个卡片只占一列,自然只半宽。2) .pc-sugpadding: 7px 10px(左右各内缩 10px),而 .pc-impact 无 padding——两者起始 x 不同,导致建议视觉上向里缩进。③ 处置(最小手术、单文件 gen_report_v6.js:1) CSS(L452).probcards{grid-template-columns: repeat(var(--pc-cols,2), 1fr); ...}——硬编码改 var(--pc-cols,2) 变量化(默认 2)。2) CSS(L462).pc-sug{ ...padding: 8px 0}——去掉左右 padding,保留上下 padding 让框仍可视;文字起点与 .pc-impact 完全对齐。3) 生成器 L691~708:严重/警告两处生成 .probcards 时计算 N===1 ? 1 : 2;N===1 时 inline style="--pc-cols:1",网格退化为单列、单卡自然撑满整行 → 742px(左栏宽);N≥2 不写 style,走 CSS 默认 --pc-cols:2 → 2 列 365×2 + gap,总容器宽度恒 742px 不变.pcard 高度由 content 撑开(无 min-height),单卡变宽后内容自动换行、高度自适应,无需另动。④ 验证(Edge 1920×1080 + pageerror 监听):ov 严重 N=1 → 单列 742px、单卡 742px ✓;ov 警告 N=3 → 双列 365×2 ✓;hr 严重 N=2 / 警告 N=8 → 双列 ✓;wf 严重 N=2 / 警告 N=8 → 双列 ✓;km 严重 N=1 → 单列 742px ✓、警告 N=2 → 双列 ✓;period 域 0 问题、无块打印、pageerror / console.error 零错误 ✓。所有块 diffImpVsSugContent = 0(影响起始 x=410、建议起始 x=410,逐卡逐块完全对齐)。⑤ 防回归铁律:1) --pc-cols 必须 inline 设在该域的 .probcards 上、不能提到父级,否则下面 5 域会全被覆盖成 1 列——CSS 变量沿 DOM 继承,子域级别必须各设各的;2) N=1 → 单列 是用户当面规定——不可凭"看着更整齐"扩到"全部单列"(多卡时 1 卡一行会撑爆左栏高度),也不可凭"看着紧凑"改回"全部双列"(会再现单卡只占半宽);3) .pc-sug 必须水平 padding=0 才能与 .pc-impact 对齐——后续如要给建议加图标/计数,应放进 padding-left/right 之外、绝不回到水平 padding;4) .pcard 禁止加 min-height——单卡变宽后自然换行,高度由 content 决定。

⚠️ v24 固化(2026-08-28 23:37):客户版 PDF 转换在中文 报告/ 目录下 ERR_FILE_NOT_FOUND(file URL punycode 编码),已修复并在源头固化。用户反馈/触发:A 收口(23:26,统一落中文 报告/)后补生成 E9 客户版 PDF 时,__render_v6.js --pdf-only 报告/诊断报告-E9-客户版.html 报告/诊断报告-E9-客户版.pdf 报错 page.goto: net::ERR_FILE_NOT_FOUND at file://xn--4rrx74a/...xn--4rrx74a 是「报告」的 punycode)——中文目录被当 URL 主机名编码,文件找不到。② 根因(铁证)__render_v6.jspage.goto('file://' + pdfHtml)(L76)/ page.goto('file://' + htmlFile)(L48)把相对路径直接拼 file://,中文 报告/ 目录段被 URL 解析为 authority 并 punycode 编码 → 路径错乱。E9 互动版(23:26)重生成只跑 gen_report_v6.js --html 不触发此 goto,故此前未暴露;E10 客户版(23:27)当时由 gen_e10_report.js 传绝对/可解析路径侥幸成功,掩盖了 bug。③ 处置(最小手术、单文件 report/__render_v6.js:1) 顶部加 const { pathToFileURL } = require('url');(L17);2) L49 await page.goto('file://' + htmlFile, ...)await page.goto(pathToFileURL(path.resolve(htmlFile)).href, ...);3) L77 await pdfPage.goto('file://' + pdfHtml, ...)await pdfPage.goto(pathToFileURL(path.resolve(pdfHtml)).href, ...)path.resolve 基于 cwd 把相对路径转绝对,pathToFileURL 生成正确 file:/// + 盘符 + UTF-8 编码中文路径,彻底规避 punycode。④ 验证:重跑 E9 客户版 PDF → 报告/诊断报告-E9-客户版.pdf(23:37, 791048B)成功;E10 客户版 PDF 同机制保持可用。⑤ 防回归铁律__render_v6.js 任何 page.goto 一律用 pathToFileURL(path.resolve(x)).href,绝不手写 'file://' + 变量——中文目录(本 skill 产物默认落 报告/)下手写拼 file:// 必 punycode 失败;即使当前 root 是英文目录,此写法对相对/中文路径都健壮,勿回退。

⚠️ v25 固化(2026-08-31):v6 引擎域集合改为「按数据实际存在域过滤」,E10 自动剔除未移植的 ov(全局设置情况)域、E9 输出不变。用户指令:E10 尚未移植 ov_(全局设置情况)11 条方言语句,要求删除 E10 报告中该部分的页面显示与评分规则(互动版+客户版),不动 E9。② 核查结论:E10 数据 oa_diag_result_e10.json 实有 0 条 ov_ 条目(76 条全为 hr/wf/km/period);客户版 gen_customer_report.pyHAS_OV=(SYS=='E9')(L82)早已分支排除 ov(目录/概览/章节均无 ov)——客户版本就正确,无需改动;问题仅在互动版引擎 gen_report_v6.js L149-151 把 TAB_DOMS/SCORE_DOMS/DOM_ORDER 硬编码含 ov,导致 E10 互动版渲染空 ov tab、且把空白 ov 计 100 分拉高健康度。③ 处置(最小手术、单文件 gen_report_v6.js:L149-151 改为 const PRESENT_DOMS = Array.from(new Set((r.items||[]).map(it=>String(it.key||'').split('_')[0]).filter(Boolean))); + TAB_DOMS=['ov','hr','wf','km','period'].filter(d=>PRESENT_DOMS.includes(d)); + SCORE_DOMS=['ov','hr','wf','km'].filter(d=>PRESENT_DOMS.includes(d));——数据驱动:E9 数据含 ov_ → PRESENT_DOMS 含 ov → 与硬编码原值完全一致(E9 输出字节级不变);E10 无 ov_ → ov 自动剔除(tab/面板/评分全移除)。ovGroupsHtml() 函数定义仍保留(仅 d==='ov' 分支在 TAB_DOMS 不含 ov 时不触发,无调用)。④ 验证:E10 互动版重生成 → 无 charts-ov/switchTab('ov')/data-dom="ov"/>全局设置情况< 渲染标记,健康度 73→80(ov 不再计入均值);E9 互动版用新引擎重生成 → 49/6/21 与改动前一致(无回归);E10 客户版重生成无报错、无 ov 章节。⑤ 防回归铁律TAB_DOMS/SCORE_DOMS/DOM_ORDER 必须保持「按 PRESENT_DOMS 过滤」的数据驱动写法,禁止改回硬编码数组——否则 E10 会重现空 ov tab、且 E9 若有域缺数据也会被错误渲染;新增域时只在候选列表 ['ov','hr','wf','km','period'] 里加 key,引擎自动按数据有无决定显隐。

⚠️ v25b 固化(2026-08-31):互动版初打开默认 tab 跟随 TAB_DOMS[0](E10 默认 hr,E9 默认 ov),不再硬编码 'ov'用户反馈:v25 修复剔除了 E10 ov tab 后,初打开互动版,右侧默认面板仍显示「全局设置情况 / 本域暂无明细条目」(残留的 ov 占位),与"打开显示第一个域"的预期不符。② 根因:v25 只改了 L149-151 的域集合(即标签页生成),未改 L930-931 的初始化调用 + L910 的 reset fallback —— 三处都仍硬编码 'ov' 作为默认打开域。③ 处置(最小手术、单文件 gen_report_v6.js,3 处):1) L910(reset 按钮 fallback):var d = active ? active.id.replace('p-','') : 'ov';var d = active ? active.id.replace('p-','') : (TAB_DOMS[0] || 'ov');。2) L930-931(脚本初始化):renderCharts('ov'); renderDefaultDetail('ov');renderCharts(TAB_DOMS[0] || 'ov'); renderDefaultDetail(TAB_DOMS[0] || 'ov');(前置一行注释 v25b 注明)。④ 验证:E10 互动版嵌入脚本里 init calls = renderCharts(TAB_DOMS[0] || 'ov') + renderDefaultDetail(TAB_DOMS[0] || 'ov')(实测)→ E10 默认 tab 渲染第一个域 hr,右侧默认下钻其首个明细;E9 互动版不变(TAB_DOMS[0] 仍为 ov,行为完全等同 v25)。⑤ 防回归铁律renderCharts/renderDefaultDetail/renderDefaultIndex 三函数的默认参数 + reset fallback 一律用 TAB_DOMS[0] || 'ov'禁止回到硬编码 'ov'——否则 E10 将永久残留「全局设置情况」占位内容,且脚本其他数据驱动域过滤无效。⑥ 补充(2026-08-31 收口):init 漏 switchTab 导致 E10 初打开主区空白,已补全。 v25b 原固化只把 renderCharts/renderDefaultDetail 默认参数改 TAB_DOMS[0]||'ov',但漏了 switchTab(TAB_DOMS[0]||'ov')——clientJS 末尾 init 若不调 switchTab,首域 panel 永远拿不到 .active class(CSS .panel{display:none}.panel.active{display:block}),E10(无 ov)初打开主区全空白;E9 因 tabs/panels 写死 d==='ov' active 而侥幸可见,但本质仍缺运行时激活。已于 src 收口:① tabs/panels 默认高亮由写死 d==='ov' 改为数据驱动 d===TAB_DOMS[0](L684/685/695);② init 调 switchTab(TAB_DOMS[0]||'ov')(switchTab 内部已 renderCharts,故原独立 renderCharts 行省略)。防回归铁律(新增):改任何「默认显隐/首域」逻辑,必须同时保证「HTML 静态 .active 首域 + init switchTab(首域) 运行时激活」两者一致,缺一不可——只改其一必导致某系统初打开空白。

⚠️ v26 固化(2026-08-31):客户版新增 --use-interactive-score 标志,与互动版调用同一 gen_report_v6.js --score-only 取同源分数,保证两版得分严格一致。用户反馈:v25 剔除了 E10 ov 域评分(互动版健康度 73→80),但客户版仍按业务指标 100-减项算法算出 73——两版得分不一致(80 vs 73)。② 根因:互动版用 scoreDomain(d) = 100 - Σ(problems数 × DOM_SCORE_WEIGHT[sev])(告警问题数加权扣分);客户版用 score_hr/wf/km/sys = 100 - Σ(业务指标减项)(离职率/卡单密度/空目录率等),两套算法从根本不同源。③ 处置(最小手术,3 文件 3 改):1) 互动版 gen_report_v6.js totalScore 计算后插入 if (process.argv.includes('--score-only')) 模式:stdout 输出 {overall, by_domain, score_doms, dom_triggered, crit, warn, info} JSON 后 process.exit(0)——纯 stdout,无 HTML 生成。2) 客户版 gen_customer_report.py argparse 增 --use-interactive-score 标志,启用时 subprocess.run([NODE, ENGINE, '--score-only'], env={E9_DIAG_JSON, E9_RULES}) 拿 JSON,覆盖 overall + s_hr/wf/km/ov/sys 各域分;失败回退业务指标。3) 适配器 gen_e10_report.js custArgs 数组追加 --use-interactive-score——E10 报告流水线一并对齐。④ 验证:E10 互动版=80、客户版=80(一致✓);各域分 hr=85 wf=67 km=88 ov=65 sys=90(互动版 scoreDomain 输出)回填到客户版模板;E9 默认不传此标志(保持业务指标旧路径 49),与互动版 scoreDomain 巧合相等。⑤ 防回归铁律:E10 适配器必须始终--use-interactive-score(客户版 = 互动版 = 同源),E9 跳过此标志(业务指标路径);若以后增加同源对齐需求,扩展 gen_report_v6.js --score-only 的 JSON 字段即可,已预留 by_domain/dom_triggered/严重度计数。

  • 客户版(HTML + PDF)report/gen_customer_report.py(Python,22222 模板版式:封面<建筑图内联> + 报告说明 + 目录 + 九章诊断 + 关键问题清单 + 总结建议),系统(E9/E10)/客户名/日期/制作人均参数化(见 --customer/--author/--cover/--data)。⚠ 报告说明页的「软件分析版本」与「数据获取通道」随数据 system/dbLabel 自动切换,绝不写死 E9/E10 专属值:E9 → e-cology 9.0 / Oracle 11g / 数据展现集成通道;E10 → e-cology 10.0 / MySQL / 数据加工·SQL 视图通道(与 drivers/e10_api.js 头部口径一致)。产物 报告/诊断报告-{SYS}-客户版.html.pdf
  • 标准命名规范(强制,不加 -v6 后缀;同一 v6 引擎产物,目录已区分;去除随机日期前缀)诊断报告-E9-互动版.html / 诊断报告-E9-客户版.html / 诊断报告-E9-客户版.pdf 诊断报告-E10-互动版.html / 诊断报告-E10-客户版.html / 诊断报告-E10-客户版.pdf
  • 封面图资产:report/cover_building.svg(纯文本 SVG、内部 base64 内联原图;为零二进制以通过 SkillHub 等三方平台,单文件可显示,不依赖相对路径/中文目录)。
  • 资源 PNG 全部 SVG 化(v31 2026-08-31,SkillHub 二进制黑名单规避)
    • 源 PNG 报告/图片1.png / yemei.png / 2a5b1f1d...png → 同名 .svg 包装(png base64 内嵌)
    • HTML 内 <img src="data:image/svg+xml;base64,..."/> 视觉与原 PNG 一致
    • gen_customer_report.py / _gen_22222_report.py 两处 img_b64() 均改为按扩展名推断 mime
  • 客户版页眉/页脚版式(2026-08-26 固化,E9/E10 完全一致,对齐客户提供的参考图 报告/2a5b1f1d869e9878150e9d89e7183d9a_4.png
    • 页眉(每页,封面除外):左 = 泛微 logo(报告/图片1.png,base64 内联)+ 「数字化办公」标签;右 = 「泛微客户应用情况诊断书」;下方一条 黑→绿→灰 渐变分割线(3px)。目录暗底页(.toc-page)页眉文字/logo 全部白色(logo 用 filter:brightness(0) invert(1) 反色),不放白底条
    • 页脚(每页,封面除外):两行版式,中间一条 1px 黑色细线分隔 —— 第 1 行左「泛微网络科技股份有限公司」+「www.weaver.com.cn」(带下划线),右「第 N 页 共 {总页数} 页」(N 随实际页数动态变化);第 2 行「地址:上海市闵行区三鲁公路3419号泛微软件大厦 电话:021-52262600 邮编:201112」。目录暗底页页脚文字全部白色、细线半透明白。
    • 唯一实现源report/gen_customer_report.pypage_header() / page_footer(n) 两个函数 + 对应 CSS(.page-hdr-new / .page-foot-new 系列)。22222 模板源 报告/_gen_22222_report.py 已同步同一实现(保留 oatrain 样例数据),禁止在任一文件里回退为旧版「{:02d} customer report / 泛微客户应用诊断 · oatrain 测试环境」页脚。
    • 禁止事项:页脚不得只塞一张图片糊弄;页码必须真实动态;logo 后必须带「数字化办公」;目录暗底页不得出现白底 header 条。

生成链路(skill oa-diag-datas/report 为唯一运行链路;workspace 报告样式方案 仅为 v6 设计存档,不再同步维护):产物统一输出到 oa-diag-datas/报告/: # 【已移除 2026-08-31】整目录已删除

# 0) Python 运行器(任意含 base64 的 Python 即可,客户版生成器只用标准库)
PY="C:/Users/Administrator/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
# 1) 组装 v6 生成器(把 v6 版式 + 内嵌数据注入 gen_report_v6.js)
NODE="C:/Users/Administrator/.workbuddy/binaries/node/versions/22.22.2/node.exe"
$NODE __assemble_v6.js
# 2) 互动版 HTML(标准命名 报告/诊断报告-{SYS}-互动版.html)
$E9_DIAG_JSON=报告/oa_diag_result.json $NODE gen_report_v6.js --html
# 3) 客户版 HTML(22222 模板,Python;标准命名 诊断报告-{SYS}-客户版.html)
$PY gen_customer_report.py --data 报告/oa_diag_result.json --out 报告/诊断报告-E9-客户版.html
# 4) 客户版 PDF(由 -客户版.html 经 playwright+Edge 打印;--pdf-only 跳过截图)
NODE_PATH="C:/Users/Administrator/.workbuddy/binaries/node/workspace/node_modules" $NODE __render_v6.js --pdf-only 报告/诊断报告-E9-客户版.html 报告/诊断报告-E9-客户版.pdf
# ⚠ 仅开发调试用,正式使用不跑(用户定稿要求:不输出截图和其他内容):
#   $NODE __render_v6.js        # 全量模式:互动版域截图 + PDF(调试版式用)
#   $NODE __verify_v6.js        # 结构校验(0 JS 错误 / 21 图全画,改版式后回归用)

换客户数据接入(重要防误用)gen_report_v4.js 与已生成的 gen_report_v6.js 内嵌的是 oatrain 测试数据(DIAG/CHARTJS 在 /* 嵌入数据 */ 段)。切勿直接拿 gen_report_v6.js 交付非 oatrain 环境。正确做法:把新客户的诊断结果按相同 items[] 结构替换 gen_report_v4.js/* 嵌入数据 */ 段(及 CHARTJS),重跑 __assemble_v6.jsgen_report_v6.js --html;客户版直接 gen_customer_report.py --data <新JSON>(无需重汇编)。版式(上述 1~7)零改动复用。

五-3、E10 v6 报告生成(2026-08-22 起与 E9 同版式)

  • oa-diag-datas/run_e10_full.jsE10 全量取数入口(复用 drivers/e10_api.js,CDP 9223 + .cdp-profile-e10 独立会话)。数据库语句用 E9_DB_TYPE(2026-08-22 起):默认 mysql(✅ 已验证基线);oracle/sqlserver/dameng 为 MySQL 基线转写版(verified:false,选非 mysql 时脚本打印警示),失败项看 e10_fail_report.json 语句级诊断。取数对象(SQL 视图 ID)经 targets/e10_*.json 提供。连接器清单展示(2026-08-24 起):取数前先打印当前环境全部数据连接器(ID+名称+库名+是否默认)并标出自动将使用哪一个,换连接器设 E9_CONN_NAME=<名称>;完成行输出 连接器 id=X(名称=Y)
  • oa-diag-datas/gen_e10_report.js:E10 报告适配器(薄层),把 drivers/e10_api.js 产出的 报告/oa_diag_result_e10.jsonresults[] 结构)整形为 v6 引擎期望的 { items[], system:'e10', dbLabel:'MySQL', ok, fail, ... },再调 report/gen_report_v6.js 出互动版 HTML,客户版改由 report/gen_customer_report.py(22222 模板)生成。
  • v6 引擎已支持 E9_REPORT_HTML 环境变量覆盖输出路径gen_e10_report.js 用此机制把互动版写到 报告/诊断报告-E10-互动版.html,客户版写到 报告/诊断报告-E10-客户版.html
  • 封面客户名由 CUSTOMER 环境变量控制(gen_e10_report.js 互动版已设为 泛微 E10 协同管理平台;客户版由 gen_customer_report.py --customer 同值传入);系统版本/标题由 r.system(大写 → E10)动态生成,无需后处理改标题。
  • 真 PDF 自动生成(无需手工跑 render)gen_e10_report.js 内部自动 spawnSync 调用 report/__render_v6.js --pdf-only <客户版HTML> <输出PDF>(Playwright + Edge 打印引擎,NODE_PATH 指向 workspace/node_modules),直接产出 报告/诊断报告-E10-客户版.pdf。⚠ 客户版由 gen_customer_report.py 生成 22222 模板 HTML、再经 __render_v6.js 转 PDF;gen_report_v6.js 现仅出互动版(不再有 --pdf 客户版输出)。
  • 正式交付只出 3 件产物:互动版 HTML + 客户版 HTML(打印源)+ 客户版 PDF;不出截图、不出其他校验内容(与 E9 定稿要求一致)。
  • 生成命令
NODE="C:/Users/Administrator/.workbuddy/binaries/node/versions/22.22.2/node.exe"
cd C:/Users/Administrator/.workbuddy/skills/OA系统四域数据分析/oa-diag-datas
$NODE gen_e10_report.js   # 一键出 3 件:互动版 HTML + 客户版 HTML + 客户版 PDF(PDF 内部自动转换)

五-4、产物目录统一与导出清理规则(2026-08-22 定)

E9 与 E10 所有生成物统一落 oa-diag-datas/报告/report/ 只放纯代码,oa-diag-datas 根目录只放模板/配置。所有脚本输出/输入默认路径均已改为 ../报告/(相对 report/),且写入前自动 mkdirSync recursive,整包拷走后链路照跑(无硬编码绝对路径)。

| 目录 | 放什么 | 导出前处理 | |---|---|---| | report/ | 纯代码(生成器/渲染器/校验器/chart.js/advice 模板) | 保留 | | oa-diag-datas 根 | 模板与配置(captured_save_full.json、datashow_configs.json、problem_rules.json、dialects/、targets/、drivers/) | 保留 | | 报告/ | 全部生成物:E9 结果 JSON、E9 互动版/客户版 HTML+PDF、E10 结果 JSON+报告三件套、覆盖 Excel | 清空(可再生的运行产物,含 oatrain 测试数据,勿打包给他人) |

  • 换机/导出给他人的外部依赖(比目录更要紧,需对方自备):① node + playwright-coreNODE_PATH 指向其 node_modules);② Edge 浏览器(__render_v6.js/__verify_v6.jsexecutablePath,路径不同需改);③ Chrome 9222 调试端口 + 已登录 OA 会话(取数前置)。run_all.jsNODE_PATH/Python 候选路径同理为机器相关。
  • 覆盖 Excel 功能已移除(模板 xlsx 与生成器已删除),不再输出 四域诊断_2018TX011_全量覆盖.xlsx

六、Oracle 三大根因(踩坑必看,否则指标全 0)

  1. 空串即 NULLloginid <> '' 在 Oracle 恒为假 → 只用 IS NOT NULL 判已分配账号。
  2. workflow_currentoperator.usertype 实际只有 0(人员)/2,无 1 → 改用 usertype=0
  3. 签退日志 operatetype='304'operateuserid=0(未关联具体人员)→ 按地点维度(clientaddress)呈现并标注「签退日志未关联人员」。

七、其他关键口径

  • 封存部门:hrdepartment.canceled 为 CHAR → 比较用 COALESCE(dp.canceled,'0')='1'(字符,勿与数字比,否则 ORA-00932)。
  • 单行聚合 + COUNT(*) 不可混用(ORA-00937),已拆 wf_basic/wf_type_cnt/wf_request_total
  • 密码加盐哈希,不可查弱口令 → 用「从未改密/超期未换」作等价替代(见报告 1.2.20/21 说明)。
  • 登录日志表 hrmsysmaintenancelog:6=登录成功、302=登录失败、304=签退、303=其他;clienttype 1=PC、2=移动。
  • 日期多为 CHAR(10) YYYY-MM-DD,比较加格式护栏 LENGTH(x)=10 AND x>'1900-01-01'

八、四域覆盖与未覆盖项

  • 完整覆盖:HR 1.1 + 1.2.1~1.2.33(34 节)、WF 2.1 + 2.2.1~2.2.22(23 节)、KM 3.1 + 3.2.1~3.2.7(8 节)、周期性诊断 5 节。详见 references/four_domain_items.md
  • 诚实标注未覆盖:1.2.9(离职频次流水)、1.2.27/1.2.28(考勤模块未启用)、1.2.29(高管手机隐藏字段无标识)在当前环境无数据;2.2.19(公共短语 SQL 集漏带)。报告中已明确标注「数据不足/模块未启用」,不编造。

九、红线(绝对不可为)

  • 全程 SELECT无 INSERT/UPDATE/DELETE/CREATE/ALTER/DROP。复用浏览器已登录 OA 会话,不直连库、不碰密码、AI 不代登。
  • 脚本不接触密码、不自动登录、不试密码(防锁管理员)。业务高峰勿跑全表大查询。
  • 测试数据(大量「测试/培训专用」类目)须在报告「数据口径说明」中诚实标注,正式交付前建议剔除后复核。

十、复用提示

  • 换系统:仅改运行环境(在目标 OA 登录、对应实例开 9222),并设 E9_SYS_TYPE/E9_DB_TYPE 选对驱动与语句;逻辑 key 不变,报告/覆盖 Excel 零改动复用。E10 与 E9 均统一用 v6 最终版式:E9 走 run_all.js(互动版 gen_report_v6.js --html + 客户版 gen_customer_report.py + PDF __render_v6.js --pdf-only),E10 走 run_e10_full.js 取数 + gen_e10_report.js 一键出互动版 HTML + 客户版 HTML/PDF(命名均为 诊断报告-{SYS}-*)。
  • 重出报告(v6 最终版式):换客户时按「五-2」替换 gen_report_v4.js 内嵌数据后重跑 __assemble_v6.jsgen_report_v6.js --html;客户版直接换 --datagen_customer_report.py(无需重汇编)。版式锁定不变。禁止回退到 gen_report_v2.js 旧布局。覆盖 Excel 功能已移除(模板与生成器已删除)。
  • 评分:报告中各域健康分/总结为当前环境测算值,换库后建议按 e9-diagnosis-plan 的阈值模型重算。
  • 模板比对源:已移除(官方 xlsx 与生成器已于 2026-08-31 删除,规范已固化进 problem_rules.json)。

历史说明:旧路线(Chrome 扩展 oa-diag-ext 数据源+建模虚拟表、scripts 直连 Oracle 主库 + diag_config.json 密码配置)因违反「密码不进对话/不直连库」红线、且已被 CDP 复用会话路线完全取代,已于 2026-08-14 从本 skill 删除。