25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

94 satır
20 KiB

  1. import fs from 'node:fs'
  2. import path from 'node:path'
  3. const root = path.resolve('reports/guide-closure-20260910')
  4. const phases = ['create','edit','reader','missing','content','revision','templates','layout','api','offline','final-document','export','resources']
  5. const runs = phases.map(phase => ({ phase, ...JSON.parse(fs.readFileSync(path.join(root, `${phase}.json`), 'utf8')) }))
  6. const checks = runs.flatMap(run => run.checks.map(check => ({ phase:run.phase, ...check })))
  7. const artifacts = JSON.parse(fs.readFileSync(path.join(root, 'artifact-validation.json'), 'utf8'))
  8. const fixes = [
  9. ['不存在的工程地址自动新建', 'runtime.ts', '不存在 ID 明确报错,返回列表选择,避免查看操作创建脏数据。', 'missing'],
  10. ['列表默认排序及重置', 'GuideProjectList.vue / content-lists.js', '统一按创建时间倒序;更新旧工程不应改变默认顺序。', 'templates / layout'],
  11. ['只读用户无法选择导出和阅读控件', 'ofd-v4.js', '放行导出格式、页码、缩放、搜索等阅读控件;OFD 导出不再尝试保存草稿。', 'reader'],
  12. ['狐狸三维视口被环境雾完全遮住', 'ofd-viewport.js', '单模型加载清除车间雾;加载场景仍使用场景自身环境配置。', 'revision / offline'],
  13. ['默认模型相机距离不适配真实模型尺寸', 'ofd-document.js', '缺省相机走自动取景,保留用户明确保存的相机位置。已有显式相机不批量覆盖。', 'final-document / regression'],
  14. ['新建继承演示工程版本、反馈和装备参数', 'ofd-v4.js', '新工程清空演示业务记录、零件、技术参数与来源文件;模板章节按原模板生成。', 'templates'],
  15. ['开发环境导出的离线三维包加载失败', 'ofd-offline-runtime-assets.js', '打包 Three.js 和解码器原始源码,消除 Vite 改写后的开发路径。', 'offline / artifact-validation'],
  16. ['长标题、公式间距与动画秒数版式', 'ofd-layout.js', '缺省长标题自适应,公式后增加必要间距,动画时间保留两位小数。', 'PDF 四页目视 / regression'],
  17. ['反馈示例固定引用不存在的步骤', 'ofd-v4.js', '默认反馈示例使用当前工程的实际步骤,避免新建工程执行示例直接 404。', 'api:submit-feedback 201'],
  18. ]
  19. // 通过只表示这里写明的观察范围,不代表正式业务链路验收。
  20. const coverage = [
  21. ['列表','列表加载、编号搜索、重置、创建时间排序','本地通过','templates / layout','编辑旧记录后的多记录排序组合未单独量化。'],
  22. ['列表','项目详情、状态、版本入口','部分覆盖','代码审查 + publish 截图','统计是本地数据,不能作为教学统计。'],
  23. ['列表','删除及所有批量/权限组合','待补验证','代码审查','未删除用户工程;未对每一种授权组合做全矩阵测试。'],
  24. ['创建','空白向导、基本信息、建档','本地通过','create','正式后台不存在该新工程。'],
  25. ['创建','四类模板静态/动态预览','本地通过','templates','实际逐个打开并切换目录。'],
  26. ['创建','模板 PDF、OFD 下载和选模板创建','本地通过','templates','下载实测第一类;新建实测第四类(4 章 9 步)。'],
  27. ['创建','模板来源与平台模板管理联动','待确认改造','静态 OFD_CONTENT_TEMPLATES','当前不是后台模板库。'],
  28. ['创建','演示历史、反馈、参数隔离','修复通过','templates','仅修复新建,不清理用户既有文档。'],
  29. ['分析规划','资料来源、需求规格、构建计划导出','部分覆盖','02-planning / export','Markdown 下载已测;专业内容自动分析质量未验收。'],
  30. ['分析规划','多装备、多层级、关键步骤覆盖','待业务验收','原始 DOCX 对照','狐狸、卡车为功能夹具,不能证明真实维修覆盖率。'],
  31. ['编辑','步骤属性、保存、刷新重开','本地通过','edit','仅在同一测试浏览器项目空间持久化。'],
  32. ['编辑','新步骤、续页、复制、撤销重做','本地通过','edit','章节及步骤所有拖动组合未穷举。'],
  33. ['编辑','表格单元格、合并拆分、边框','本地通过','layout','填写后重开检查;未对所有样式排列组合做测试。'],
  34. ['编辑','自由文本块、矩形标注','本地通过','layout','自由排版允许用户自行移动重叠;未自动约束所有自由布局。'],
  35. ['编辑','公式输入、说明、关联区排版','修复通过','content / regression / PDF','两个公式回归与实际 PDF 检查。'],
  36. ['编辑','字体、纸张、页眉页脚、所有标注形状','部分覆盖','属性面板巡检与源码','不是每个属性都做了写入、重开、导出三重验证。'],
  37. ['资源','本地 GLB 导入、绑定步骤','本地通过','edit / revision','09-Fox.glb、08-CesiumMilkTruck.glb。'],
  38. ['资源','后台模型制作/场景制作资源选择','待确认改造','本地 platformModels / 场景目录','不能声称使用了之前在服务端创建的两个场景。'],
  39. ['资源','单模型显示、取景、截图、动画','修复通过','revision / final-document','实际图像和帧差验证,截图保存后重开保留。'],
  40. ['资源','本地视频导入、播放、截帧保存','本地通过','resources','使用 2 秒测试视频;不代表真实维修内容验证。'],
  41. ['资源','音频、资料包、损坏模型、存储配额','待补验证','导入代码审查','未对全部格式和存储异常做实际测试。'],
  42. ['资源','模型热点、部件聚焦、三维与步骤语义关联','部分覆盖','属性面板 + 离线观察操作','专业热点与真实装备语义尚需专项验证。'],
  43. ['预览','静态版式、动态步骤搜索与跳转','本地通过','layout / templates','在线预览位于本地编辑器。'],
  44. ['预览','播放、暂停/重播、观察控制','本地通过','revision / offline','两模型动画帧改变;离线观察按钮逐个执行。'],
  45. ['权限','管理员只读、导出不修改文档','修复通过','reader(实际 admin 会话)','编辑使用 root;未把三角色全接口授权矩阵当作已验证。'],
  46. ['权限','账号间工程隔离、数据范围','待确认改造','共享本地存储命名空间','正式数据应以现有后台权限和用户范围为准。'],
  47. ['发布','预检清单、草稿预览、发布面板','本地通过','08-preflight / 09-publish-panel','预检通过不等于后端发布成功。'],
  48. ['发布','发布、修订、旧快照、新版本、撤回','本地通过','content / revision','现状均为本地生命周期;没有实际发送后台发布请求。'],
  49. ['发布','后台版本、OFD/离线交付物原子发布','待确认改造','ContentProjectService','后台已要求 GUIDE 的 OFD + OFFLINE_HTML ZIP;现有页面未串联。'],
  50. ['发布','审核策略','代码确认','ContentProjectService GUIDE 分支','审核按现有配置可选;不引入强制审核新规则。'],
  51. ['导入导出','工程 JSON、导入恢复、非法 JSON','本地通过','revision / resources','JSON 不是完整资产备份;模型字节仍在 IndexedDB。'],
  52. ['导入导出','实际 PDF 下载及四页版式','修复通过','final-pdf-page-1 至 4','中文、目录、模型图、公式目视检查;字体存在替代。'],
  53. ['导入导出','实际 OFD ZIP/XML','本地通过','artifact-validation','未用第三方原生 OFD 阅读器验证标准一致性或签章。'],
  54. ['导入导出','离线 ZIP、GLB 轻量化、运行时','修复通过','offline / artifact-validation','卡车导出按已有逻辑压缩;结构与动画保留,非原字节复制。'],
  55. ['离线','断开公网/业务服务后本地启动阅读','本地通过','offline','Windows + Node.js 本地静态服务;没有依赖外站的请求。'],
  56. ['离线','手机尺寸、麒麟、真实移动设备','部分覆盖','23-offline-mobile','390×844 可显示,按钮换行与三维取景仍偏拥挤;未测实机、麒麟。'],
  57. ['教学','学员指导书列表、正式阅读内容','待确认改造','正式内容查询 + teaching 接口查询','不能从本地发布进入正式教学阅读。'],
  58. ['教学','收藏、个人笔记、检索、进度','待确认改造','原始需求与离线入口核对','离线缺个人笔记/收藏入口;需与在线用户身份及进度方案一并实现。'],
  59. ['教学','学习统计、报表、训练/考试联动','待确认改造','后端 teaching/guides 与原始需求','未因后台存在接口而判为全链路通过。'],
  60. ['接口','九个本地契约操作与反馈样例','修复通过','api / revision','八个本地请求逐个执行;生命周期通过发布 UI 单独实测。'],
  61. ['接口','第三方 HTTP 调用、鉴权、正式反馈','待确认改造','api:零真实业务 HTTP 请求','显示 /api/ofd 不代表服务端真实提供该接口。'],
  62. ['质量','构建、单元回归、浏览器异常','通过','build 及 20 项测试','选定最终 E2E 阶段无 pageerror;不包含早期定位脚本失败。'],
  63. ['质量','三主题、键盘、长文档、并发和性能指标','待补验证','本轮边界','未验证所有组合;不能宣称 <1s / ≥25fps / ≥99% / ≤10s 已达标。'],
  64. ]
  65. const proposals = [
  66. ['A:编辑与正式内容闭环(优先)','保留现有编辑器,将列表、工程保存、模板/模型/场景选择、权限和版本操作对接现有 content 接口。服务端为数据真值;明确迁移本地工程和 IndexedDB 文件,不能静默覆盖。发布时提交 OFD 和离线 ZIP,并遵循现有可选审核设置。','验收:新建→编辑→刷新/换浏览器→发布→旧版本不变→撤回;正式数据库与界面一致,其他账号按权限可见。'],
  67. ['B:教学阅读闭环','衔接现有教学指导书、阅读记录和反馈接口;补齐个人笔记、收藏、学习进度与统计。离线笔记是否回传及冲突处理需要与在线范围一起定。','验收:教员发布→学员阅读→记录/笔记/反馈保存→教员统计可查询;账号隔离生效。'],
  68. ['C:对外接口真实联调','将当前本地契约自检与真实 HTTP 接口对齐,文档标明真实路径、参数、错误及授权;沿用现有平台认证机制,不新增密钥文件或独立服务。','验收:从独立客户端调用,读取/修改/反馈真实工程,未授权请求被拒绝。'],
  69. ]
  70. const pictures = [
  71. ['19-list-created-order.png','新建模板工程与创建时间排序'],['01-create-wizard.png','空白创建向导'],['02-planning.png','资料与规划'],['17-template-preview.png','模板结构预览'],
  72. ['27-final-fox.png','狐狸真实模型显示与取景'],['28-final-truck.png','卡车真实模型显示与取景'],['29-video-poster.png','视频播放与当前帧海报'],['30-invalid-import.png','非法工程导入保留原文档'],
  73. ['24-table-edit.png','表格编辑测试(自由块为测试内容)'],['25-markup.png','矩形标注'],['26-interactive-search.png','动态阅读搜索'],['16-withdrawn.png','本地版本撤回'],
  74. ['20-api-local.png','接口自检:实际仍为本地调度'],['21-offline-reading.png','离线步骤阅读'],['22-offline-model-0.png','离线狐狸三维'],['22-offline-model-1.png','离线卡车三维'],['23-offline-mobile.png','手机尺寸观察:仍有拥挤'],
  75. ...[1,2,3,4].map(n=>[`final-pdf-page-${n}.png`,`最终 PDF 第 ${n} 页`]),
  76. ]
  77. const summary = {date:'2026-09-10',conclusion:'未完全闭环;本地编辑与导出路径完成修复验证,正式内容、教学和对外 HTTP 接入待确认',environment:{web:'http://127.0.0.1:6180',gateway:6100,browser:'Edge headless / Playwright',viewport:'1920×1080;390×844 观察',accounts:'root 编辑、admin 只读(不含凭据)'},pass:checks.filter(c=>c.status==='PASS').length,fail:checks.filter(c=>c.status==='FAIL').length,unitTests:20,artifactChecks:artifacts.checks,fixes,coverage,proposals,runs}
  78. fs.writeFileSync(path.join(root,'summary.json'),JSON.stringify(summary,null,2))
  79. const esc = s => String(s??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]))
  80. const table = (heads,rows) => `<div class="table"><table><thead><tr>${heads.map(x=>`<th>${esc(x)}</th>`).join('')}</tr></thead><tbody>${rows.map(row=>`<tr>${row.map(x=>`<td>${esc(x)}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`
  81. const html=`<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>作业指导闭环检查 · 20260910</title><style>
  82. body{margin:0;background:#eef4f3;color:#173d36;font:15px/1.7 system-ui,"Microsoft YaHei",sans-serif}main{max-width:1300px;margin:auto;padding:30px}header,section{background:white;border:1px solid #c9ded8;border-radius:12px;padding:26px;margin-bottom:20px}h1{margin:0 0 12px;font-size:28px}h2{margin:0 0 15px;font-size:22px}h3{font-size:18px}.notice{padding:18px;border-left:5px solid #cf8618;background:#fff5e5}.stats{display:flex;gap:15px;flex-wrap:wrap}.stats b{padding:12px 20px;border-radius:8px;background:#e9f5ef}.table{overflow:auto}table{border-collapse:collapse;width:100%;font-size:14px}td,th{border:1px solid #cfdfdb;padding:10px;vertical-align:top;text-align:left}th{background:#edf6f2}a{color:#087e62}.images{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}figure{margin:0;border:1px solid #d8e4e0;padding:10px;border-radius:8px}figure img{width:100%;height:290px;object-fit:contain;background:#f1f5f4}figcaption{font-size:14px}code{background:#edf4f2;padding:2px 5px}nav{display:flex;gap:20px;flex-wrap:wrap}small{color:#56726b}@media(max-width:700px){main{padding:12px}section,header{padding:16px}.images{grid-template-columns:1fr}}@media print{body{background:white}main{padding:0}section{break-inside:auto}.images{grid-template-columns:1fr 1fr}a{color:inherit}}</style>
  83. <main><header><h1>作业指导模块:闭环检查与修复报告</h1><p>2026-09-10 · 资料 → 原型 → 设计 → 开发 → 测试</p><div class="notice"><strong>结论:未完全闭环。</strong>本地编制、三维/视频预览与导出已完成本轮验证;实际页面仍保存到浏览器本地库,尚未连通正式内容发布、教学阅读及对外 HTTP 接口。不能以本地“已发布”认定全系统发布成功。</div><p class="stats"><b>${summary.pass} 项 E2E 断言通过</b><b>${summary.fail} 项需求断言未满足</b><b>20 项回归通过</b><b>6 项交付物检查通过</b><b>构建通过</b></p><p>未满足的 5 项中,4 项重复印证正式内容/教学链路缺失,1 项为离线个人笔记和收藏入口缺失。通过项含“确认现状”的断言,不能直接换算为产品完成率。</p><nav><a href="#source">资料与范围</a><a href="#fixes">已修复</a><a href="#coverage">功能覆盖</a><a href="#confirm">待确认方案</a><a href="#evidence">截图</a><a href="#tests">测试明细</a></nav></header>
  84. <section id="source"><h2>1. 资料、原型与设计核对</h2><p>原始依据:<code>文档/桥梁装备“数字车间”资源建设需求参数.docx</code>。覆盖内容分析规划、标准模板、排版与媒体关联、PDF/离线交付、版本更新、教学阅读、个人记录、反馈和统计。未将未阅读的其他 PDF 算作本轮依据。</p><p>正式路由经 <code>LegacyGuidePageView.vue → runtime.ts → ofd-v4.js</code> 托管原型。工程存储为带命名空间的本地 ContentListStore(seed:false),资源字节在 IndexedDB;模板和平台资源选择仍使用本地实现。后台已有 content projects、guide templates、teaching guides 接口,现状是前后两条实现未衔接。</p><p>测试创建了空白狐狸文档和模板卡车文档;狐狸文档中加入卡车作为第二个模型步骤,对两种模型验证导出与离线阅读。由于服务端场景资源没有接通,本轮直接导入本地 GLB,不能声称走通了之前正式创建的狐狸/卡车场景引用。</p><p>小修保持原交互和文档结构;不重建编辑器、不新增独立服务、不改 DDL。本轮不提交 Git。</p></section>
  85. <section id="fixes"><h2>2. 开发修复</h2>${table(['问题','文件','处理','验证'],fixes)}</section>
  86. <section id="coverage"><h2>3. 全模块功能覆盖与边界</h2><p>按功能入口建立 ${coverage.length} 项检查矩阵。“部分覆盖”和“待补验证”明确保留,不表示已跑过所有按钮与组合。</p>${table(['范围','功能点','结论','证据','边界'],coverage)}</section>
  87. <section id="confirm"><h2>4. 需要确认的较大调整</h2><p>建议按 A → B → C 实施,复用现有后端和编辑器。以下尚未实施,避免在本次 bugfix 中静默改变存储、权限和发布规则。</p>${table(['范围','具体实施','验收闭环'],proposals)}<p>另有后续验证项:移动窄屏按钮与取景拥挤、完整主题/键盘矩阵、原生 OFD 阅读器、麒麟、长文档与性能压力测试。真实装备内容覆盖率及专业维修正确性需业务资料与实际装备验收。</p></section>
  88. <section><h2>5. 交付文件与复核方法</h2><p><a href="export-pdf.pdf">下载实测 PDF</a> · <a href="export-ofd.ofd">下载 OFD</a> · <a href="export-offline.zip">下载离线 ZIP</a> · <a href="export-project.json">下载工程 JSON</a> · <a href="export-requirement.md">需求规格</a> · <a href="export-plan.md">构建计划</a> · <a href="summary.json">完整 JSON 报告</a></p><p>离线 ZIP 完整解压后用其 Windows 启动脚本运行,需要已有 Node.js,通过本机 HTTP 打开,不能直接 file://。运行时和两个 GLB 均在包内,无公网或业务 API 依赖。OFD 已检查 ZIP/XML,PDF 四页已渲染核对;未宣称第三方 OFD 认证,PDF 字体跨平台一致性未验证。</p><p>测试数据保留在隔离的自动化浏览器空间,不在用户日常浏览器或服务端列表中。工程 JSON 含资源引用,不含所有模型原字节,导入编辑时需重新选择本地素材;离线 ZIP 是可独立复核的阅读交付物。下载内容使用测试文字,不能用于实际维修操作。</p>${table(['交付物检查','结果','说明'],artifacts.checks.map(c=>[c.name,c.status,c.detail]))}</section>
  89. <section id="evidence"><h2>6. 实际截图</h2><p>点击查看原图。截图用于证明对应操作,含测试自由文本/标注的页面不作为最终排版模板。</p><div class="images">${pictures.map(([file,title])=>`<figure><a href="${esc(file)}"><img loading="lazy" src="${esc(file)}" alt="${esc(title)}"></a><figcaption>${esc(title)}</figcaption></figure>`).join('')}</div></section>
  90. <section id="tests"><h2>7. 测试明细</h2><p>环境:Windows、Edge headless、Playwright,1920×1080;前端 6180,经 Gateway 6100;root 编辑、admin 只读。离线包通过隔离的 18766 本地静态服务运行并阻断其他主机请求。未将浏览器登录凭据写入报告。</p><p>命令:<code>node tools/guide-closure-live.mjs &lt;phase&gt;</code>(多阶段顺序执行,不能并发共享浏览器状态);<code>python tools/guide-artifact-check.py</code>;<code>node --test scripts/guide-legacy-closure.test.mjs</code>;现有 5 个 guide 测试脚本(17 项);<code>pnpm run build</code>(含 vue-tsc 和构建后校验)。新旧单元测试共 20 项通过,构建完成,仅既有 chunk size 提示。</p><p>早期脚本定位失败、重复运行造成的选择器歧义、Playwright storageState 无法恢复 Blob 原型,都未作为产品缺陷统计;实际模型测试通过界面重新导入,再在同一上下文刷新验证持久化。原始中间记录保留用于追溯,最终统计只采用下面选定阶段。</p>${table(['阶段','断言','结果','说明'],checks.map(c=>[c.phase,c.name,c.status,c.detail]))}<p>最终选定阶段 pageerror 总数:${runs.reduce((n,r)=>n+r.errors.length,0)}。真实 HTTP 业务写请求为零是尚未接入的证据,而不是接口性能验证。</p></section></main></html>`
  91. fs.writeFileSync(path.join(root,'index.html'),html)
  92. console.log(JSON.stringify({pass:summary.pass,fail:summary.fail,coverage:coverage.length,screenshots:pictures.length}))