feat(clipping): implement hide/recover toggle for all section dialogs
Update all three section dialogs to support hide/show toggle: SectionAxisDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionBoxDialogManager: - onHideToggle now calls hideSection()/recoverSection() SectionPlanePanel: - Add isHidden state tracking - Change onHide to onHideToggle(isHidden) - Add setHiddenState/getHiddenState methods - Update button to toggle active state SectionPlaneDialogManager: - Switch to onHideToggle callback - Call hideSection()/recoverSection() based on toggle state Behavior: Click hide button to hide section, click again to recover.
This commit is contained in:
1232
.sisyphus/drafts/API_CALLCHAIN.md
Normal file
1232
.sisyphus/drafts/API_CALLCHAIN.md
Normal file
File diff suppressed because it is too large
Load Diff
230
.sisyphus/drafts/framework-audit-report.md
Normal file
230
.sisyphus/drafts/framework-audit-report.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# iflow-engine 框架架构审核(代码 + 文档)
|
||||
|
||||
日期:2026-01-29
|
||||
|
||||
## 范围
|
||||
|
||||
本审核仅评估 `iflow-engine` SDK 的**内部框架/架构设计**,依据:
|
||||
- `src/` 下的源代码
|
||||
- `docs/` 下的架构与模块文档
|
||||
|
||||
不在本次范围内:
|
||||
- 功能完整性
|
||||
- UI/交互体验优劣
|
||||
- 重构路线/落地方案/实现细节(按你的要求不输出)
|
||||
|
||||
已确认的前提(来自你的要求):
|
||||
- 保留 `ManagerRegistry` 作为核心设计(单例 + 服务定位器)。
|
||||
- SDK 需要支持同一页面多个 viewer 实例。
|
||||
- 主题/语言是全局共享。
|
||||
- 事件应当按 `BimEngine` 实例隔离。
|
||||
- Components 设计上应当严格纯 UI:不触达 registry、不发布全局事件。
|
||||
- Components 也不应直接订阅/读取全局主题/国际化服务(theme/locale 应由 manager 注入或推送更新)。
|
||||
|
||||
## 严重级别说明
|
||||
|
||||
- **Critical(致命)**:架构层面存在矛盾或极易引发跨实例破坏。
|
||||
- **High(高)**:高概率造成长期维护痛点/难追踪 bug。
|
||||
- **Medium(中)**:明显增加认知负担或存在非小风险的不一致。
|
||||
- **Low(低)**:质量/风格问题,非结构性,但建议修整。
|
||||
|
||||
## 发现的问题清单
|
||||
|
||||
### 1) Critical:多实例事件隔离诉求,与全局单例事件总线结构矛盾
|
||||
|
||||
框架把所有事件集中在 `ManagerRegistry` 内部的一个全局 `EventEmitter` 上。
|
||||
这从结构上决定了:多个 `BimEngine` 实例之间无法做到事件天然隔离。
|
||||
|
||||
证据:
|
||||
- `src/core/manager-registry.ts:31-38`(`private eventEmitter: EventEmitter = new EventEmitter()`)
|
||||
- `src/core/manager-registry.ts:95-127`(`emit/on/off` 都委托给这一个 emitter)
|
||||
- `src/core/base-manager.ts:19-34`(所有 Manager 的订阅都通过单例 registry 完成)
|
||||
|
||||
影响:
|
||||
- 多个 viewer 共存时,任一实例发出的事件都可能被所有订阅者收到。
|
||||
- 事件域是全局的,不是 per-engine 的;如果要隔离,必须在别处“人为做隔离”,但当前框架没有内建边界。
|
||||
|
||||
### 2) Critical:销毁任一实例会重置全局 registry,破坏其他实例
|
||||
|
||||
`BimEngine.destroy()` 会调用 `ManagerRegistry.reset()`:清空事件监听并把单例置空。
|
||||
当页面存在多个引擎实例时,销毁其中一个就可能让其他实例失效。
|
||||
|
||||
证据:
|
||||
- `src/bim-engine.ts:150-164`(调用 `ManagerRegistry.reset()`)
|
||||
- `src/core/manager-registry.ts:82-88`(`reset()` 会 `clear()` emitter 并 `instance = null`)
|
||||
|
||||
影响:
|
||||
- 跨实例“断电式”故障;而且故障源头非局部,排查成本高。
|
||||
|
||||
### 3) High:全局 registry 存放实例态(container/wrapper/各类 manager 实例)
|
||||
|
||||
`ManagerRegistry` 不只是 locator:它持有 `container/wrapper` DOM 节点和大量 manager 实例。
|
||||
这使它变成一个全局可变的“状态袋”。
|
||||
|
||||
证据:
|
||||
- `src/core/manager-registry.ts:35-70`(`container`/`wrapper` 与各 manager 字段)
|
||||
- `src/bim-engine.ts:101-136`(把容器与所有 manager 写入单例)
|
||||
|
||||
影响:
|
||||
- 多实例情况下,“最后初始化的实例”会覆盖 `registry.container/wrapper` 与 manager 引用。
|
||||
- 排查问题时必须追踪“最后是谁写入了全局状态”。
|
||||
|
||||
### 4) High:服务定位器边界未被约束(叶子层大量直接 getInstance)
|
||||
|
||||
框架想表达分层,但叶子层代码频繁直接调用 `ManagerRegistry.getInstance()`。
|
||||
这会扩大隐式依赖并增加跳转/追踪成本。
|
||||
|
||||
证据(示例,不完全):
|
||||
- `src/components/button-group/toolbar/buttons/home/index.ts:15-16`
|
||||
- `src/components/button-group/toolbar/buttons/measure/index.ts:14-18`
|
||||
- `src/components/button-group/toolbar/buttons/map/index.ts:8-28`
|
||||
- `src/components/button-group/index.ts:65-68`(组件通过单例 registry 发事件)
|
||||
- `src/components/engine/index.ts:131-144`(Engine 组件通过单例 registry 发事件)
|
||||
- `src/managers/engine-manager.ts:64-68`(即便继承 `BaseManager`,回调里仍 `getInstance()`)
|
||||
|
||||
影响:
|
||||
- 依赖关系在 API/构造函数层面不可见,只能靠全局搜索发现。
|
||||
- 实际改动往往需要跨层与跨全局状态跳转。
|
||||
|
||||
### 5) High:组件层通过 registry 直接参与框架通信,削弱了文档里的分层承诺
|
||||
|
||||
文档里写明“组件不直接依赖 Manager,由 Manager 创建和管理组件实例”。
|
||||
但代码中组件通过全局 registry 发布事件。
|
||||
|
||||
证据:
|
||||
- 文档承诺:`docs/MODULES/组件模块.md:595-602`
|
||||
- 反例:`src/components/engine/index.ts:131-144`(`ManagerRegistry.getInstance().emit(...)`)
|
||||
- 反例:`src/components/button-group/index.ts:65-68`(组件通过 registry 发事件)
|
||||
|
||||
影响:
|
||||
- 组件层通过全局 locator 变得“半业务化/半框架化”。
|
||||
- 耦合上升,测试与复用更困难。
|
||||
|
||||
### 6) High:RightKeyManager 出现重复创建/归属不清
|
||||
|
||||
右键管理器至少在两处被创建。
|
||||
这会导致职责重复,并引入“到底谁是权威实例”的歧义。
|
||||
|
||||
证据:
|
||||
- `src/bim-engine.ts:108`(`this.rightKey = new RightKeyManager(this.wrapper)`)
|
||||
- `src/managers/engine-manager.ts:50-51`(`this.rightKey = new RightKeyManager(this.container)`)
|
||||
|
||||
影响:
|
||||
- 更高概率出现重复监听、hide/show 不一致、销毁责任不清。
|
||||
|
||||
### 7) High:Engine 组件依赖仓库相对路径的底层引擎产物(工程耦合)
|
||||
|
||||
代码没有从外部依赖(`iflow-engine-base`)导入,而是通过深层相对路径引入本仓库的 dist 文件。
|
||||
这会把构建/运行绑定到特定仓库布局。
|
||||
|
||||
证据:
|
||||
- `src/components/engine/index.ts:8-11`(从 `../../../../bim_engine_base/dist/...` 导入 `createEngine`)
|
||||
|
||||
影响:
|
||||
- CI/发布构建对目录结构高度敏感。
|
||||
- 线上发布包与本地开发行为可能不一致。
|
||||
|
||||
### 8) Medium:BimEngine 订阅主题变化但未保存取消订阅句柄
|
||||
|
||||
`BimEngine.init()` 对 `themeManager` 订阅后没有保存返回的 `unsubscribe`。
|
||||
|
||||
证据:
|
||||
- `src/bim-engine.ts:139-142`(`themeManager.subscribe(...)` 返回值未保存)
|
||||
|
||||
影响:
|
||||
- 在 SPA 场景反复创建/销毁引擎时可能累积订阅,形成隐性泄漏。
|
||||
|
||||
### 9) Medium:对话框定位依赖全局 registry.container(非实例局部上下文)
|
||||
|
||||
`BaseDialogManager` 的默认位置计算基于 `this.registry.container`。
|
||||
多实例时这隐含了“全局只有一个有效 container”。
|
||||
|
||||
证据:
|
||||
- `src/core/base-dialog-manager.ts:60-73`(读取 `this.registry.container` 计算位置)
|
||||
|
||||
影响:
|
||||
- 多实例下对话框可能相对“最后写入 registry 的容器”定位,表现不一致。
|
||||
|
||||
### 10) Medium:分层调用链本身会导致“改动面扩大”(层级跳转多)
|
||||
|
||||
文档明确了 5 层调用链(Button → DialogManager → EngineManager → Engine 组件 → 底层引擎)。
|
||||
哪怕每层都写得干净,累计的间接层也会扩大改动时的触达面。
|
||||
|
||||
证据:
|
||||
- `docs/API调用链.md:714-748`(层级说明)
|
||||
- `docs/引擎API对接.md:18-66`(架构概览与层级表)
|
||||
|
||||
影响:
|
||||
- 一个功能的内部改动往往需要同步修改 3-5 个位置。
|
||||
- 这会被外部感知为“框架复杂”,即使逻辑上自洽。
|
||||
|
||||
### 11) Medium:构建配置禁用代码分割(可能削弱 ESM tree-shaking 效果)
|
||||
|
||||
库构建使用 `inlineDynamicImports: true`,强制输出单文件 bundle。
|
||||
|
||||
证据:
|
||||
- `vite.config.ts:26-38`
|
||||
|
||||
影响:
|
||||
- 使用方更难获得按需使用/裁剪的收益。
|
||||
- 打包策略会进一步强化“框架很重”的印象。
|
||||
|
||||
### 12) Low:Engine.setTheme 为空实现(抽象与实现不一致)
|
||||
|
||||
Engine 组件暴露了 `setTheme`,但实现为空。
|
||||
|
||||
证据:
|
||||
- `src/components/engine/index.ts:153-160`
|
||||
|
||||
影响:
|
||||
- 虽然不是典型“架构问题”,但会加重抽象与行为不一致,长期会影响信任度与维护效率。
|
||||
|
||||
## 文档一致性备注
|
||||
|
||||
整体上文档很完整、意图也清晰(门面 + registry + 分层)。主要不一致/落差集中在:
|
||||
- 一些分层边界(如“组件不依赖 Manager”)在代码里被全局 registry 使用削弱。
|
||||
- “多实例 + 事件隔离”的需求与当前“全局单例事件域”存在硬冲突。
|
||||
|
||||
## 维护成本视角的客观评价(你选的侧重点)
|
||||
|
||||
这里把“维护成本”拆成三类:可读性(读懂/定位)、可改动性(改一个点波及范围)、可测试性(写测试/隔离依赖的难度)。
|
||||
|
||||
### A. 可读性(读懂/定位)
|
||||
|
||||
结论:**中等偏高的认知负担**。架构意图清晰,但“全局可取用 registry”让依赖与调用链变得隐式。
|
||||
|
||||
主要原因(按影响排序):
|
||||
- **隐式依赖**:叶子层普遍 `ManagerRegistry.getInstance()`,使得“一个文件真正依赖哪些子系统”无法从构造函数/参数判断,只能靠全局搜索。
|
||||
- 证据:`src/components/button-group/toolbar/buttons/home/index.ts:15-16`、`src/components/button-group/toolbar/buttons/measure/index.ts:14-18`、`src/components/button-group/toolbar/buttons/map/index.ts:8-28`
|
||||
- **状态来源不集中**:registry 同时存放 DOM 容器(`container/wrapper`)与大量 manager 实例,读代码时需要先搞清楚“谁在什么时候写入了 registry”。
|
||||
- 证据:`src/core/manager-registry.ts:35-70`、`src/bim-engine.ts:95-136`
|
||||
- **层级跳转多且链路分散**:你在文档里明确分层(L1-L5),这使新同学能理解“应该去哪里找”,但也意味着定位一个行为经常要横跨 3-5 个文件。
|
||||
- 证据:`docs/引擎API对接.md:18-66`、`docs/API调用链.md:714-748`
|
||||
|
||||
### B. 可改动性(改一个点波及范围)
|
||||
|
||||
结论:**改动面容易扩大**,尤其是新增/调整一个功能时,按规范往往需要在多个层同时补齐。
|
||||
|
||||
主要原因:
|
||||
- **强制的多层落点**:文档对“新增功能对接步骤”规定了 Button→Toolbar→DialogManager→Registry→BimEngine init→EngineManager→Engine 组件的连锁改动;这对一致性有好处,但会让小需求也要跨层改多个位置。
|
||||
- 证据:`docs/引擎API对接.md:326-517`(Step 1-7)
|
||||
- **全局注册表字段扩散**:新增一个 manager 往往意味着在 registry 增字段、在 BimEngine 填充引用;随着功能增长,registry 越来越像“全局大对象”,改动与回归风险随之增加。
|
||||
- 证据:`docs/引擎API对接.md:416-446`、`src/core/manager-registry.ts:35-70`、`src/bim-engine.ts:120-136`
|
||||
- **重复实例/归属不清会放大改动成本**:同一能力被多处创建/持有,会导致改动时需要同时修改多个入口,且更容易漏。
|
||||
- 证据:`src/bim-engine.ts:108`、`src/managers/engine-manager.ts:50-51`
|
||||
|
||||
### C. 可测试性(隔离依赖/写单测的难度)
|
||||
|
||||
结论:**偏难**(不是因为 TypeScript/DOM,而是因为全局单例与隐式依赖)。
|
||||
|
||||
主要原因:
|
||||
- **全局单例 + 全局事件域**:测试用例之间需要非常谨慎地清理/隔离 registry 状态与事件订阅,否则容易互相污染。
|
||||
- 证据:`src/core/manager-registry.ts:31-38`、`src/core/manager-registry.ts:82-88`
|
||||
- **组件/manager 直接触达全局状态**:例如 Engine 组件在底层事件回调里直接拿单例 registry 发事件,使得组件测试必须考虑全局副作用。
|
||||
- 证据:`src/components/engine/index.ts:131-144`
|
||||
- **订阅/事件监听的释放不完全**:存在订阅未保存/未释放的迹象,会导致测试环境(或 SPA)出现隐性泄漏与用例间干扰。
|
||||
- 证据:`src/bim-engine.ts:139-142`、`src/components/button-group/index.ts:97-112`、`src/components/button-group/index.ts:804-817`
|
||||
|
||||
### 维护成本总结(一句话)
|
||||
|
||||
你的架构“按分层组织代码、让功能落点清晰”的方向是对的;维护成本主要来自 **registry 单例让依赖与状态隐式化**,再叠加 **多层落点规范** 与 **少量重复实例/资源释放不全**,使得定位、改动、测试都会更依赖经验与全局搜索。
|
||||
104
.sisyphus/drafts/framework-optimization.md
Normal file
104
.sisyphus/drafts/framework-optimization.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Draft: Framework/Architecture Optimization
|
||||
|
||||
## Requirements (confirmed)
|
||||
- User wants a project-wide review of the current framework/architecture.
|
||||
- Goal: identify framework-level optimizations to reduce complexity and the need to "jump around" to make changes.
|
||||
- Concern reported by others: the framework feels "too complex" (likely too many indirections/cross-calls).
|
||||
|
||||
## User Preferences (confirmed)
|
||||
- Focus areas: module layering + dependency injection/service locator complexity.
|
||||
- Preferred output: a problem list (issues + evidence paths + impact), not a full refactor roadmap (for now).
|
||||
|
||||
## Deliverable Format (confirmed)
|
||||
- Provide: issue list + severity + evidence (paths/call chains). No redesign/implementation proposals in this pass.
|
||||
|
||||
## Evaluation Focus (confirmed)
|
||||
- User wants objective evaluation focused on maintenance cost (readability/changeability/testability).
|
||||
|
||||
## Layering Constraint (confirmed)
|
||||
- Components should be strict UI only: do not touch registry and do not emit global events.
|
||||
- Components should also NOT directly subscribe/read global theme/locale services; managers should inject theme/locale or push updates.
|
||||
|
||||
## Evaluation Criteria (confirmed)
|
||||
- Evaluate complexity from: readability, changeability, testability, runtime performance, build efficiency.
|
||||
- Risk tolerance: user is open to large refactors if justified.
|
||||
|
||||
## Compatibility Preference (confirmed)
|
||||
- User is OK with a major-version upgrade and breaking API changes if it yields a simpler SDK facade.
|
||||
|
||||
## Multi-instance Requirement (confirmed)
|
||||
- Must support multiple `BimEngine` instances on the same page, isolated per container.
|
||||
|
||||
## Desired Public API UX (confirmed)
|
||||
- Prefer single-entry, mostly-automatic initialization; internal modules can be lazy/optional.
|
||||
|
||||
## Global vs Instance State (confirmed)
|
||||
- Theme/locale should be global across all viewers on the same page (change once applies to all).
|
||||
|
||||
## Event Model (confirmed)
|
||||
- Events should be isolated per `BimEngine` instance (no implicit cross-instance broadcast).
|
||||
|
||||
## Design Constraint (confirmed)
|
||||
- Keep `ManagerRegistry` as a core design; critique should focus on boundary rules and misuse patterns rather than removing it.
|
||||
|
||||
## Registry Model Decision (confirmed)
|
||||
- User wants to keep `ManagerRegistry` as a global singleton (not per-engine instance).
|
||||
|
||||
## Observations (from user)
|
||||
- "要调来调去" suggests high coupling, too many layers, or hard-to-trace control flow.
|
||||
|
||||
## Additional User Context (confirmed)
|
||||
- User believes current design is intentionally decoupled; wants an objective, fair assessment of where the framework/architecture has problems.
|
||||
- User is not sure which part is complex; expects reviewer to discover issues by reading the project.
|
||||
|
||||
## User Instruction (confirmed)
|
||||
- User requests reviewer-style assessment without asking many implementation-preference questions.
|
||||
|
||||
## Output Artifact
|
||||
- Audit report drafted at: `.sisyphus/drafts/framework-audit-report.md`.
|
||||
|
||||
## Build/Distribution Context (confirmed)
|
||||
- Built with npm.
|
||||
- Output is an SDK/library consumed by third-party callers.
|
||||
|
||||
## SDK Entry Point (evidence)
|
||||
- Demo uses UMD global `window.IflowEngine.BimEngine` and instantiates via `new Engine('app', { locale: 'zh-CN' })`.
|
||||
- Evidence: `demo/index.html:207-215`, `demo/viewer.html:151-160`.
|
||||
- Public surface in demo is manager-like properties: `engine.toolbar`, `engine.dialog`, `engine.propertyPanel`, and nested 3D engine access `engine.engine.initialize()` / `engine.engine.loadModel()`.
|
||||
- Evidence: `demo/index.html:228-307`, `demo/index.html:343-467`, `demo/index.html:469-478`.
|
||||
|
||||
## Primary Distribution Target (confirmed)
|
||||
- Primary consumption: ESM `import { BimEngine } from 'iflow-engine'`.
|
||||
|
||||
## Early Code Findings (evidence; subject to deeper review)
|
||||
- `BimEngine` currently *eagerly constructs* many managers inside its constructor flow (`this.init()`), rather than requiring external `initX()` calls.
|
||||
- Evidence: `src/bim-engine.ts:46-69`, `src/bim-engine.ts:95-142`.
|
||||
- There is a singleton-style registry/service-locator (`ManagerRegistry.getInstance()`), and `BimEngine` writes many manager references into it.
|
||||
- Evidence: `src/bim-engine.ts:57-58`, `src/bim-engine.ts:101-136`.
|
||||
- This creates a potential mismatch with docs that describe “user calls initEngine()/initToolbar()/...” as a step-by-step initialization.
|
||||
- Evidence: `README.md` “快速开始/初始化各个管理器” section vs `src/bim-engine.ts` eager init.
|
||||
- Build is Vite library mode, with `inlineDynamicImports: true` (single-file bundle), which can reduce ESM tree-shaking benefits and may increase load size.
|
||||
- Evidence: `vite.config.ts:26-38`, `package.json:5-13`.
|
||||
|
||||
## Doc Findings (evidence)
|
||||
- Architecture docs explicitly define `ManagerRegistry` as Singleton + Service Locator, and many call chains obtain it via `ManagerRegistry.getInstance()` even in leaf button configs.
|
||||
- Evidence: `docs/架构设计.md:100-115`, `docs/API调用链.md:69-93`.
|
||||
- Call-chain doc shows deep 5-layer pipeline (Button -> DialogManager -> EngineManager -> Engine component -> base engine). This is understandable but can feel "too many hops" when changes span layers.
|
||||
- Evidence: `docs/API调用链.md:714-748`.
|
||||
- Core docs show `ManagerRegistry` stores `container/wrapper` plus many manager instances, making it effectively a global mutable bag of state.
|
||||
- Evidence: `docs/MODULES/核心模块.md:114-137`.
|
||||
|
||||
## Technical Decisions
|
||||
- TBD
|
||||
|
||||
## Research Findings
|
||||
- Pending codebase exploration.
|
||||
|
||||
## Scope Boundaries
|
||||
- INCLUDE: architecture review, module boundaries, dependency direction, layering, wiring/DI, config/initialization flow, build/runtime structure.
|
||||
- EXCLUDE: feature work unless explicitly requested; large refactor without a plan.
|
||||
|
||||
## Open Questions
|
||||
- What does "framework" refer to here (backend framework / engine core architecture / plugin system / build system)?
|
||||
- What are the top pain points (debugging, onboarding, adding features, runtime performance, build speed)?
|
||||
- What constraints exist (API stability, deadlines, must-keep patterns, target platforms)?
|
||||
Reference in New Issue
Block a user