chore: checkpoint web Blender feature-gap work, docs and tests
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

- update native web_engine sources and rebuilt wasm artifacts
- add task cards, status notes and tooling scripts
- add web e2e specs, tutorial UI sources and tutorial assets
- sync golden task manifests and audit records

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
mes123456
2026-11-11 10:46:55 +08:00
parent f3e21c6b98
commit d1e6b63d54
665 changed files with 59149 additions and 39194 deletions

View File

@@ -0,0 +1,81 @@
# 二级减速器互动教学(REDUCER_TUTORIAL)
## 用户入口
- `/?tutorial=reducer`:React 图文落地页(结构、零件卡、课堂实录、课程树、开始/继续/重置)。
- `/?tutorial=reducer&start=1`:真实 Web Blender(本地 WASM Main)+ 引导侧栏。
- 帮助 → 二级减速器教学:在新标签页打开落地页。
## 已实现
- 35 步课程(引导 + 33 个必需步骤 + 完成总结),覆盖:
- 箱体/箱盖:立方体、应用缩放、删面 + Solidify、Mirror + Boolean UNION 箱脚、
圆柱孔刀 + Join + Boolean DIFFERENCE 轴承孔、Inset/挤出止口、Mirror 螺栓孔、Bevel。
- 传动件:三根轴(圆柱 + 轴颈 + Join + 键槽布尔)、四个齿轮
(圆柱轮坯 + 齿槽刀 + Empty 对象偏移 Array + Boolean 切齿 + 轴孔/键槽布尔 + Bevel)、
Torus 套圈 + 滚球轴承。
- 标准件与附件:端盖、平键、六角法兰螺栓、通气帽、油标、放油塞、文字转网格铭牌(Subsurf 底板)。
- 装配与交付:集合层级、轴组件 Empty + 父子、根 Empty 总装、四种材质与槽位、Linked Duplicate、
保存 `.blend`(OPFS + 下载)与 GLB 导出。
- **课程工程身份**:reducer 首次进入时通过 `ensureCourseProject("tutorial-reducer", "二级减速器.blend")`
把默认场景写入 OPFS 课程工程(复用 `persistProject`,不触发下载),
检查点写 `projects/tutorial-reducer/snapshots`,与 parts 课程的快照链隔离。
- **React TreeView**:新增 `tutorial/TutorialTreeView.tsx`(role=tree/treeitem、方向键/Home/End、
展开/折叠、状态标记),用于:
- 落地页课程结构(章节 → 步骤);
- 装配章节的“实时装配树”(按 SceneIR 的集合/父子关系生成)。
- **课程化改造**:新增 `tutorial/course.ts`,把课程 id、步骤、进度文件名、资源目录、
保存/总结步骤、文案与零件卡参数化;parts 组件改为薄包装,parts 行为不变。
- **进度与恢复**:OPFS `tutorial/reducer-progress.json` 为权威记录,localStorage 镜像;
恢复前先读 OPFS 进度,恢复失败显示提示;首次推进前串行完成“恢复或确保课程工程”。
## 本批修复的真实缺口
1. 课程工程身份与就绪竞态:引导页的“下一步”可能在 `ensureCourseProject` 启动前被点击,
从而把错误的默认工程 id 写进进度并排队检查点。现在侧栏把 `projectState`(idle/preparing/ready/failed)
纳入 `ready` 门控,串行完成“恢复或确保课程工程”后才允许演示与推进;失败时显示提示并允许继续练习,但不写错误 id。
2. 箱体轴承孔校验:箱体在箱脚步骤已有一个 Boolean(Union),按类型取第一个 Boolean 会命中箱脚而不是轴承孔。
校验现在按操作数“箱体孔刀”匹配 Boolean 修改器。
3. 轴与轴承的局部坐标:输入轴与轴承的旋转未应用时,SceneIR 网格包围盒沿局部 Z 轴,
长度/外径校验误判。演示现在在 Join 前应用旋转(与桌面建模习惯一致)。
4. 编号对象计数:`findNodes` 的名称后缀规则只接受 `.001` 形式,无法匹配“轴承1…6/端盖1…6/键1…4/法兰螺栓1…9”。
计数校验改为按 `^轴承\d+$` 等编号名称匹配。
5. 齿轮齿槽阵列与布尔:Boolean 操作数上的**活动 Array 修改器**在 Web Main 的实时视口中只切出一条齿槽
(17 份阵列未被布尔求值)。已做对照:即使齿槽刀保持可见,活动 Array 仍只切一条,可见性不是原因;
在布尔前 `bpy.context.view_layer.update()` 后应用齿槽阵列则得到正确齿形。
课程因此改为“阵列 → 应用 → Boolean”;齿轮1 的 `-view` 截图显示 17 条齿槽,齿轮2 显示 34 齿结果。
这仍是引擎的实时操作数求值缺口(已记录在“已知限制”),应用阵列是桌面同样可用的工作流。
6. 重场景的保存竞争:减速器场景较大,通用 autosave 与教程检查点同时序列化会长时间占用项目锁,
导致“下一步”在完成检查后仍被禁用。现在课程激活时停用通用 autosave,教程检查点串行化(只允许一个在跑),
重课程每 3 次推进写一次检查点(零件课程保持每步);“下一步”不再等待后台保存。
代价是最多可能丢失 2 步的场景快照,进度步骤仍每步写入。
7. 材质创建校验:未分配到任何对象的材质不会出现在 SceneIR,四种新材质的颜色校验全部失败。
课程在创建步先给箱体/输入轴/轴承1/箱盖各分配一个代表材质,下一步再分配其余零件。
8. 实时装配树可读性:SceneIR 中的隐藏辅助对象(Mirror/Array 控制 Empty、隐藏切刀)会淹没装配层级。
React 树现在过滤 `visible=false` 的对象与空集合,仅显示可见装配层级。
## 验证状态
- 有头 Chromium 全流程(2026-11-11,`capture-parts-tutorial-screenshots.mjs --course reducer --dev --port 5218`):
35 步全部通过,`status: PASS`,`errors: []`;保存与 GLB 导出检查均为绿色
(GLB 2,674,332 字节,31 条相机/灯光等警告);齿轮1 视口参考图确认 17 条齿槽。
截图:`web/app/public/tutorial/reducer/landing.jpg`、`steps/<id>.jpg`、`steps/<id>-view.jpg`、`00-assembly.jpg`
(35 步共 70 张步骤图 + 总览;落地页已在全部步骤截图生成后重新截取)。
- `npm run typecheck`:exit 0;`npm run build`:exit 0(含 `PartsTutorialLanding-*.js` 课程 chunk)。
- 生产构建上的 4 个 spec 全部通过(2026-11-11,`playwright.deployment-local.config.ts`,workers=1,48.1s):
- `wbv2-reducer-tutorial-production.spec.ts`(19.9s):落地页/课程树 → 开始 → `tutorial-reducer` OPFS 工程 →
箱体演示 → 齿轮毛坯/阵列/布尔 → 刷新继续 → OPFS 恢复(Active 齿轮1)→ 保存 `.blend` + GLB 下载与 magic →
`projects/<savedProjectId>/scene.blend`。
- `reducer-tutorial-accessibility.spec.ts`(4.5s):落地页与课程树 axe、装配步骤的实时 React 树 axe。
- `wbv2-parts-tutorial-production.spec.ts`(18.6s)与 `parts-tutorial-accessibility.spec.ts`(4.4s):零件课程回归。
- 无障碍修复:课程目录序号颜色 #7d8287→#a6abb0(对比度 4.45→通过 4.5),装配树元信息同样改为 #a6abb0。
## 已知限制
- Boolean 的**活动** Array 操作数在 Web Main 实时视口中只求值一份;课程在布尔前应用阵列。
待补:按桌面源码检查 Boolean 操作数的求值依赖(`MOD_boolean.cc` 的 `DEG_OB_COMP_GEOMETRY`
与 Array 的 `offset_ob` 关系),并加回归用例。
- 齿轮为教学简化齿形(直齿、无渐开线修形),用于讲解阵列+布尔流程,不用于强度/噪声分析。
- 轴承为简化模型(内外套圈 + 8 个滚球),未建模保持架与游隙。
- 端盖为简化圆盘+凸台,未做密封槽与标准螺栓孔阵列。
- 油标/放油塞/通气帽为示意模型;法兰螺栓数量与位置为教学布置。