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.json、e9/mysql.json、e9/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_lock、SYS-04→ov_log_keep、SYS-05→ov_doc_backup、SYS-06→ov_doc_zip、SYS-08→ov_lic_remind、SYS-09→ov_sensitive、LIC-01→ov_lic_expire、LIC-05→ov_nonstd_func、DOC-06→ov_attach_dir、VER-04→ov_upgrade_freq、VER-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.js与gen_customer_report.py均已接入ov——DOM_NAME/DOM_COLOR/problems增ov、两处DESC_MAP增 11 条、totalScore由 scoreFromTriggered 触发式改为**「用户给定阈值」线性引擎**(v11,与gen_customer_report.py的score_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.py、e9-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.json:CDP 保存请求实战抓包模板(取数驱动必读,不可或缺)。- ~~
oa-diag-datas/2018TX-011-泛微客户应用数据情况诊断20190527.xlsx~~ 【已移除 2026-08-31】:官方模板(覆盖 Excel 复用),已删除。 references/four_domain_items.md:四域子项 ↔ SQL key 映射与覆盖说明。
二、前置条件
- 复用已登录会话(默认):Chrome 已登录 OA,开启远程调试端口 9222(
--remote-debugging-port=9222),并停在「集成中心→数据展现集成」(engine.html#/integration/datashow) 页面。 - AI 启动独立浏览器(设
E9_LAUNCH=1):无需手动开端口。驱动用 playwright 拉起一个带调试端口的独立浏览器(优先系统 Chrome,持久化 profile 保留登录态),你在弹出窗口登录,驱动自动检测登录态后继续。需设E9_OA_URL=http://你的OA地址:端口。 - Node + playwright-core:
node_cdp_driver.js内部require('playwright-core'),回退本机C:/Users/Administrator/.workbuddy/binaries/node/workspace/node_modules/playwright-core。 - 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)
- 复用会话模式:在目标 OA 登录、开 9222、停 datashow 页;或直接用 launch 模式。
- launch 模式(推荐,最简单):
E9_LAUNCH=1 E9_OA_URL=<新OA地址>启动浏览器 → 你登录 →--enumerate拿到当前 OA 所有数据展现集成配置列表 → 你选一个数字 ID,设E9_CFGID=<ID>取数。无需手写任何配置 ID / subcompanyid——枚举自动列出全部配置,取数按你选的数字 ID 执行(已实测:subcompanyid 不影响取数,仅后台归类字段)。 - 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 实战钉死,全程序化、零点击):
POST /api/integration/datashow/getDataShowOperation(operator=save,type=BTN_SAVE) 把 SQL + 字段定义(keyfield / dtinfo_MergedFieldData)写回配置 11003;POST /api/integration/common/searchpagetablekey(body=各字段名空值 + showtypeid=11003) 返回一次性dataKey=searchpagetablekey-pageid-11003_<令牌>;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 单页布局。
- 主体问题总览 = issuegrid 卡片流(参照 oatrain 参考报告的
.issue/.it/.id):严重(crit)与警告/关注(warn/info)分两组;标题带[系统人员/系统流程/知识管理/周期性诊断]域前缀,副标题带「实测值 / 阈值」;点击卡片直达对应域。- 严重/警告分离 + 折叠:总览中严重组默认展开、警告/关注组默认折叠(
#ov-warn带folded);每域面板内严重卡片默认展开、警告/关注卡片默认折叠(#pwarn-<dom>带folded)。严重度图例:红=严重 / 橙=警告 / 蓝=关注。- 诊断域 = 标签页(
.tabs+.panel):v11 起共 6 个标签 = 4 个评分域(人力资源 / 流程管理 / 知识管理 / 全局设置情况;系统运行 v13 起并入 HR「登录与密码安全」,仅 E10 保留独立域)+ 周期性诊断(内容章,不计入评分);E10 无 ov → 4 评分域(人力资源/流程管理/知识管理/系统运行)+ 周期内容章。标签带问题数;ov 标签显示「全局设置情况(11)」。激活态显示域色+白字。域内结构:.dhead标题 → 4 张.kpis指标 →.dsummary导读 → 严重卡片(展开)/ 警告卡片(折叠)/.charts-grid图表;ov 域额外渲染ovTableHtml()11 项可点击下钻明细表。- 图表懒渲染:
renderCharts(domain)仅在标签被点击时绘制(rendered[domain]守卫),避免 21 张图首屏开销。- 穿透明细 = 右侧 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。- 诊断说明(
.diag-note)四项(⚠ 取消「数据来源」第一项):仅保留 ①采集范围 ②判定口径 ③安全规范 ④报告日期。不得再加回「数据来源」。- 图表含异常染色:异常图表挂
.anom-badge(crit/warn 级别由problems[].drillKey关联),徽章数 = 触发问题的图数。
双产物架构(2026-08-22 固化):每个系统出 互动版 + 客户版 两份报告,版式均为 v6 最终版式、命名统一:
- 互动版(HTML):
report/gen_report_v6.js(JS,issuegrid 总览 + 五域标签 + 右侧 sticky 穿透面板),产物报告/诊断报告-{SYS}-互动版.html(E9_REPORT_HTML环境变量可覆盖输出路径)。--pdf标记已停用(客户版改由 Python 生成)。 - 互动版 ov 域(v9,2026-08-27 14:48 当前版本):
ovPanelHtml()渲染 5 个段组(.ov-group),结构 = 段标题独立元素(.ov-section<h3>+ CSS::before4×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-card(ovCard(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.py由HAS_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 章节,新增kpiHtml的sys分支(暴力破解/密码风险/离职未回收 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生成时把" "转" "(普通空格在打印时折叠会丢缩进)。② PDF 页眉页脚丢失 = 规则缺陷(非偶发):页眉页脚是写进每个.pagediv 内的.page-hdr-new/.page-foot-newHTML 元素(Chrome 打印未用displayHeaderFooter),靠position:absolute; bottom:8mm定位;当单.page内容 > A4 297mm 时 absolute footer 落可视区外 → 该页页脚丢失/错位。实测 page 5(ov 全局设置)五段同页溢出。③ 最终修复:保留 v11 absolute footer(短页贴底正确),仅把 page 5 ov 拆为 5a/5b 两个.pagediv(ov_panel_html()改返回(top_html, bot_html),在「文档与备份」后插<!--OV_SPLIT_MARKER-->用partition拆分;top=授权+安全基线+文档与备份+建议、bot=附件目录+非标功能)。page_footer11 处条件化为(n if HAS_OV else n-2),PAGE_TOTAL=17(E9 增 1 页;E10 仍 16)。④ 失败尝试已回退:.page{display:flex;flex-direction:column}+footermargin-top:auto引入 2 个空白页(实测 p6/p18),已弃用。⑤ 实测:客户版 HTML 534458 B/17 页、PDF 约 811 KB;pypdf 验证 17 页零空白页、p2-p17「第 X 页 共 17 页」连续、每页页眉+内容+页脚完整;TOC 二级 缩进生效。⑥ 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_DOMSE9 分支去'sys'(['ov','hr','wf','km']);客户版_scoredE9 去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 地址主机名" → fallbackOA_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后):取数完成后,从results找key==='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→ 生成器 fallbackoaUrlhost = v14 字节级行为。⑧ 防回归:ov_lic_expireSQL 端点必须保留且首列名保留为「授权公司」或「公司名」;如端点重命名或列名变更,须同步改node_cdp_driver.js的customerName提取逻辑,避免再次回退到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; },renderDetailline 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_backup走metric-grid分支(rowCount=1, cols=3),最长文本oa/weaver/ecology/filesystembackup在word-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-cell改display:flex;align-items:baseline;gap:10px;min-width:0(值弹性伸缩 + 列名固定 80px 右对齐)。2) 空值友好:JS 渲染循环里判断valStr.trim()===''→ 加emptyclass,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_basic8 列 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.js抛Cannot 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-23 列 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×1080getBoundingClientRect()实测验证几何(detail-panelx=1150,w=380右栏 / panelx=390,w=742左列)。④ 处置(最小手术,单文件):gen_report_v6.js第 326 行</div></div></div>→</div></div>(删多余闭合);回退诊断期误加的 3 处grid-columnCSS(实测无效——节点已被移出网格容器,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-item的data-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×1080getBoundingClientRect+ DOM 实测):逐域打开/切换,右栏默认内容 = ov「授权完整信息」/ hr「人员账号总体概况」/ wf「流程路径总体概况」/ km「知识管理总体概况」/ period「月度流程新建请求」,#dp-body均含.dtable或.metric-grid,detail-panelx=1150,w=380(右栏),无 pageerror。⑤ 防回归:1)renderDefaultDetail与renderDefaultIndex须在同一 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(...)",须同步给someFn加window.someFn = someFn;;否则按钮/卡片/行/单元格的点击全部静默失效,无任何错误提示——只能用 Edge 模拟点击才能发现(仅看代码 grepwindow.难发现,因为 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)允许列窄于内容;.kpi加min-width:0; overflow:hidden,.kn/.kl加white-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)
.probcardsCSS 硬编码grid-template-columns: 1fr 1fr——2 列网格下 1 个卡片只占一列,自然只半宽。2).pc-sug有padding: 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 时 inlinestyle="--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.js原page.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) L49await page.goto('file://' + htmlFile, ...)→await page.goto(pathToFileURL(path.resolve(htmlFile)).href, ...);3) L77await 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.py经HAS_OV=(SYS=='E9')(L82)早已分支排除 ov(目录/概览/章节均无 ov)——客户版本就正确,无需改动;问题仅在互动版引擎gen_report_v6.jsL149-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 永远拿不到.activeclass(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首域 + initswitchTab(首域)运行时激活」两者一致,缺一不可——只改其一必导致某系统初打开空白。
⚠️ 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.jstotalScore计算后插入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.pyargparse 增--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.jscustArgs数组追加--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
- 源 PNG
- 客户版页眉/页脚版式(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.py的page_header()/page_footer(n)两个函数 + 对应 CSS(.page-hdr-new/.page-foot-new系列)。22222 模板源报告/_gen_22222_report.py已同步同一实现(保留 oatrain 样例数据),禁止在任一文件里回退为旧版「{:02d} customer report/泛微客户应用诊断 · oatrain 测试环境」页脚。 - 禁止事项:页脚不得只塞一张图片糊弄;页码必须真实动态;logo 后必须带「数字化办公」;目录暗底页不得出现白底 header 条。
- 页眉(每页,封面除外):左 = 泛微 logo(
生成链路(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.js → gen_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.js:E10 全量取数入口(复用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.json(results[]结构)整形为 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-core(NODE_PATH指向其 node_modules);② Edge 浏览器(__render_v6.js/__verify_v6.js内executablePath,路径不同需改);③ Chrome 9222 调试端口 + 已登录 OA 会话(取数前置)。run_all.js内NODE_PATH/Python 候选路径同理为机器相关。 - 覆盖 Excel 功能已移除(模板 xlsx 与生成器已删除),不再输出
四域诊断_2018TX011_全量覆盖.xlsx。
六、Oracle 三大根因(踩坑必看,否则指标全 0)
- 空串即 NULL:
loginid <> ''在 Oracle 恒为假 → 只用IS NOT NULL判已分配账号。 workflow_currentoperator.usertype实际只有 0(人员)/2,无 1 → 改用usertype=0。- 签退日志
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.js→gen_report_v6.js --html;客户版直接换--data跑gen_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 删除。
Scan to join WeChat group