refactor: sync managers and section box actions

Wire section box scale/reverse/reset to clipping APIs and sync demo artifacts.
This commit is contained in:
yuding
2026-02-04 18:20:30 +08:00
parent b12940f49c
commit 191c571f40
64 changed files with 10569 additions and 7065 deletions

View File

@@ -1,9 +1,8 @@
{
"active_plan": null,
"completed_at": "2026-02-02T09:45:00.000Z",
"last_plan": "clipping-api-migration",
"active_plan": "/Users/yuding/WORK/LYZ/project/bimEngine/engine/.sisyphus/plans/refactor-model-operations.md",
"started_at": "2026-02-04T07:23:30.594Z",
"session_ids": [
"ses_3e2bc84f9ffeHmiDS2pkiLtX2n"
"ses_3dec861d2ffekLv6QMzLySFf7p"
],
"status": "completed"
}
"plan_name": "refactor-model-operations"
}

View File

@@ -0,0 +1,5 @@
# Decisions - Path Roaming Implementation
This notepad tracks architectural and design decisions made during implementation.
---

View File

@@ -0,0 +1,5 @@
# Issues - Path Roaming Implementation
This notepad tracks problems, gotchas, and issues encountered during implementation.
---

View File

@@ -0,0 +1,199 @@
# Learnings - Path Roaming Implementation
This notepad tracks conventions, patterns, and accumulated wisdom from the path-roaming feature implementation.
---
## [2026-02-03T07:48:40] Codebase Exploration - Locale and Component Patterns
### Locale Files Structure
- **Location**: `src/locales/{types.ts, zh-CN.ts, en-US.ts}`
- **Pattern**: Nested objects matching TypeScript interface
- **Existing `walkControl.path` field**: Already contains `dialogTitle` property
- **Line ranges**:
- types.ts: lines 158-176
- zh-CN.ts: lines 151-168
- en-US.ts: lines 151-168
### Engine/EngineManager Method Patterns
- **Engine class** (`src/components/engine/index.ts`):
- Use guard clauses: `if (!this._isInitialized || !this.engine?.xxx)`
- Console warnings for uninitialized state: `console.warn('[Engine] ...')`
- Return `null` explicitly (not `undefined`)
- JSDoc comments required
- Type assertions where needed
- **EngineManager class** (`src/managers/engine-manager.ts`):
- Proxy pattern: `this.engineInstance?.methodName() ?? null`
- Optional chaining with nullish coalescing
- Consistent return types with Engine class
- **getEngineInfo() locations**:
- Engine: line 691-697
- EngineManager: line 426-428
### Component Implementation Patterns
- **WalkPathPanel status**: Exists as stub (55 lines), missing CSS and types files
- **Reference implementations**: MeasurePanel (888 lines), WalkControlPanel (468 lines)
- **Core interface**: `IBimComponent` with init(), destroy(), setTheme(), setLocales()
- **Subscriptions**: localeManager and themeManager subscriptions in init()
- **CSS variables**: Prefix with `--bim-*` for theming
- **Class naming**: `bim-[panel-name]-[element]` convention
- **Import pattern**: CSS at top, services/types imports follow
## [2026-02-03T07:50:15] Task 1 Complete - I18n Text Added
### Changes Made
- **types.ts**: Expanded `walkControl.path` from 1 field to 9 fields (dialogTitle + 8 new fields)
- **zh-CN.ts**: Added Chinese translations for all 9 fields
- **en-US.ts**: Added English translations for all 9 fields
### Fields Added
1. duration - 漫游时间 / Duration
2. durationUnit - 秒 / s
3. loop - 循环播放 / Loop
4. addPoint - 添加漫游点 / Add Point
5. deleteAll - 删除全部 / Delete All
6. point - 漫游点 / Point
7. play - 播放漫游 / Play
8. noPoints - 暂无漫游点,请添加 / No points yet
### Verification
- ✅ Build succeeded: `npm run build` passed with no errors
- ✅ All three files modified with exact code from plan
- ✅ Type safety maintained (TypeScript interface matches implementation)
### Notes
- Chinese JSDoc comments in types.ts are intentional per plan specification
- Subagent failed with JSON parse error, completed directly as trivial edit
## [2026-02-03T07:51:30] Task 2 Complete - Types.ts Created
### File Created
- **Location**: `src/components/walk-path-panel/types.ts`
- **Size**: 24 lines
### Interfaces Defined
1. **RoamingPoint**: Represents a single roaming point with `index: number`
2. **PlayOptions**: Configuration for playback with 4 optional fields:
- duration?: number (milliseconds)
- loop?: boolean
- onComplete?: () => void
- onPointComplete?: (pointIndex: number) => void
### Documentation
- All interfaces have Chinese JSDoc comments (per plan requirement)
- All fields have inline comments explaining purpose
- Public API documentation complete
### Verification
- ✅ Build succeeded: `npm run build` passed
- ✅ File created with exact code from plan
- ✅ Type definitions ready for component implementation
## [2026-02-03T07:52:30] Task 3 Complete - Engine pathRoaming Methods Added
### Changes Made
- **File**: `src/components/engine/index.ts`
- **Location**: After `getEngineInfo()` method (line 697)
- **Lines added**: ~90 lines of code
### Methods Added
1. **pathRoamingAddPoint()** - void - Add current camera position as roaming point
2. **pathRoamingRemovePoint(index)** - void - Remove point by index
3. **pathRoamingClearPoints()** - void - Clear all points
4. **pathRoamingGetPoints()** - any[] - Get all points array
5. **pathRoamingJumpToPoint(index)** - void - Jump to specific point
6. **pathRoamingPlay(options)** - void - Play roaming with callbacks
### Pattern Compliance
- ✅ Guard clauses: `if (!this._isInitialized || !this.engine?.pathRoaming)`
- ✅ Console warnings: `console.warn('[Engine] pathRoaming not available')`
- ✅ JSDoc comments for all public methods
- ✅ Internal comments explaining logic flow
- ✅ Section markers for code organization
- ✅ Consistent with existing Engine class patterns
### Verification
- ✅ Build succeeded: `npm run build` passed
- ✅ All 6 methods added with exact signatures from plan
- ✅ Ready for EngineManager proxy methods
## [2026-02-03T07:53:15] Task 4 Complete - EngineManager Proxy Methods Added
### Changes Made
- **File**: `src/managers/engine-manager.ts`
- **Location**: After `getEngineInfo()` method (line 428)
- **Lines added**: ~60 lines of code
### Proxy Methods Added
All 6 methods delegate to `this.engineInstance`:
1. **pathRoamingAddPoint()** - Proxies to engineInstance
2. **pathRoamingRemovePoint(index)** - Proxies with parameter
3. **pathRoamingClearPoints()** - Proxies to engineInstance
4. **pathRoamingGetPoints()** - Returns array with nullish coalescing
5. **pathRoamingJumpToPoint(index)** - Proxies with parameter
6. **pathRoamingPlay(options)** - Proxies with options object
### Pattern Compliance
- ✅ Proxy pattern: `this.engineInstance?.methodName()`
- ✅ Optional chaining for safety
- ✅ Nullish coalescing for getPoints: `?? []`
- ✅ JSDoc comments matching Engine class
- ✅ Section markers for code organization
- ✅ Consistent with existing EngineManager patterns
### Verification
- ✅ Build succeeded: `npm run build` passed
- ✅ All 6 proxy methods match Engine class signatures
- ✅ Ready for WalkPathPanel component implementation
## [2026-02-03T07:55:00] Tasks 5-7 Complete - WalkPathPanel & CSS Implemented
### Task 5: WalkPathPanel Component
- **File**: `src/components/walk-path-panel/index.ts`
- **Lines**: 377 lines of TypeScript
- **Complexity**: Complex UI component with state management
#### Features Implemented
1. **Initialization**: Load existing points from engine on panel open
2. **Settings**: Duration input (seconds → milliseconds) and loop checkbox
3. **Point Management**: Add, delete, delete all operations
4. **Point List**: Dynamic rendering with empty state
5. **Playback**: Play with callbacks, highlight current point during playback
6. **Lifecycle**: init(), setLocales(), setTheme(), destroy()
#### Key Patterns
- Render-based updates: Full re-render on state changes
- Callback integration: onPointComplete for highlighting, onComplete for cleanup
- Theme application: CSS variables via setProperty
- I18n integration: Subscribe to localeManager, use t() function
### Task 6: CSS Styling
- **File**: `src/components/walk-path-panel/index.css`
- **Lines**: 233 lines of CSS
- **Sections**: Buttons, Forms, Points Section, Point Items
#### Style Features
1. **Theming**: All colors use CSS variables with fallbacks
2. **Highlight Effect**: `.walk-path-point-item-active` for playing point
3. **Hover Effects**: Button hover states, action button visibility on hover
4. **Responsive**: Flexbox layouts, overflow handling
5. **Transitions**: Smooth hover and state changes
### Task 7: Build Verification
-`npm run build` succeeded
- ✅ Bundle size: 2,078 KB (ES), 1,370 KB (UMD)
- ✅ No TypeScript errors
- ✅ All 7 tasks complete
### Total Implementation
- **Files created**: 2 (types.ts, index.css)
- **Files modified**: 5 (types.ts, zh-CN.ts, en-US.ts, Engine.ts, EngineManager.ts)
- **Files replaced**: 1 (walk-path-panel/index.ts)
- **Total lines added**: ~1,200 lines
- **Build status**: ✅ SUCCESSFUL

View File

@@ -0,0 +1,29 @@
# Problems - Path Roaming Implementation
This notepad tracks unresolved blockers and critical problems requiring attention.
---
## [2026-02-03T07:52:00] Delegation System Failure
### Issue
Subagent delegation consistently failing with JSON parse error:
```
SyntaxError: JSON Parse error: Unexpected EOF
```
### Impact
- Cannot use delegate_task() for any category
- All 3 delegation attempts failed (Tasks 1, 2, 3)
- Forced to complete tasks directly as orchestrator
### Workaround
Completing tasks directly while maintaining:
- Plan specification compliance
- Build verification
- Notepad documentation
### Action Required
- Investigate delegation system JSON serialization
- May need to report to framework maintainers

View File

@@ -0,0 +1,109 @@
## [2026-02-03T09:55] Task 1: I18n Files Update
### Pattern Observed
- All menu i18n keys use JSDoc comments with Chinese descriptions in types.ts
- Format: `/** 中文描述 */\n{key}: string;`
- This is a codebase convention for bilingual documentation
### Implementation
- Added 4 fields to menu object: quickSelect, selectSameType, selectSameLevel, selectSameLevelType
- Maintained alphabetical ordering after existing fields
- Chinese: 快速选择, 选择同类模型, 选择同层模型, 选择同层同类模型
- English: Quick Select, Select Same Type, Select Same Level, Select Same Level & Type
### Verification
- tsc --noEmit passed with no errors
- All three files updated consistently
## [2026-02-03T09:58] Task 2: Engine Layer Methods
### Implementation
- Added 8 public methods to Engine class between lines 792-903
- Pattern: check initialization → get highlightModels → call engine.modelToolModule API
- Section markers: `// ==================== 构件操作 ====================`
- Each method has JSDoc with Chinese description (SDK convention)
### API Mapping
```
hideSelectedModels() → modelToolModule.hideModel(models)
translucentSelectedModels() → modelToolModule.translucentModel(models)
isolateSelectedModels() → modelToolModule.isolateModel(models)
translucentOtherModels() → modelToolModule.translucentOtherModel(models)
showAllModels() → modelToolModule.showAllModels()
batchSelectSameTypeModel() → modelToolModule.batchSelectSameTypeModel(models)
batchSelectSameLevelModel() → modelToolModule.batchSelectSameLevelModel(models)
batchSelectSameLevelTypeModel() → modelToolModule.batchSelectSameLevelTypeModel(models)
```
### Verification
- TypeScript compilation: PASSED
- Methods follow existing patterns (fitSectionBoxToModel as reference)
- Positioned correctly before destroy() method
## [2026-02-03T10:00] Task 3: EngineManager Proxy Methods
### Implementation
- Added 8 proxy methods to EngineManager class (lines 494-555)
- Pattern: Simple delegation to engineInstance methods using optional chaining
- Format: `this.engineInstance?.{methodName}();`
- Each method has JSDoc with Chinese description
### Verification
- TypeScript compilation: PASSED
- All 8 methods correctly delegate to Engine layer
- Positioned between path roaming and destroy() method
## [2026-02-03T10:03] Task 4: Right-Click Menu Handler Updates
### Implementation
- Replaced all console.log placeholders with actual method calls
- Added "快速选择" submenu with 3 options (order: 5)
- Updated menu item ordering:
- isolateSelected: order 4 (unchanged)
- quickSelect: order 5 (NEW)
- fitSectionBox: order 5 → 6
- showAll: order 6 → 7
### Menu Structure
```
1. 构件详情 (componentDetail)
2. 隐藏选中构件 (hideSelected) → hideSelectedModels()
3. 半透明选中构件 (transparentSelected) → translucentSelectedModels()
4. 隔离选中构件 (isolateSelected) → SUBMENU
- 其他构件隐藏 (hideOthers) → isolateSelectedModels()
- 其他构件半透明 (transparentOthers) → translucentOtherModels()
5. 快速选择 (quickSelect) → SUBMENU [NEW]
- 选择同类模型 (selectSameType) → batchSelectSameTypeModel()
- 选择同层模型 (selectSameLevel) → batchSelectSameLevelModel()
- 选择同层同类模型 (selectSameLevelType) → batchSelectSameLevelTypeModel()
6. 剖切盒适应 (fitSectionBox) → fitSectionBoxToModel()
7. 显示全部 (showAll) → showAllModels() [always visible]
```
### Verification
- TypeScript compilation: PASSED
- All console.log placeholders replaced
- All i18n keys properly linked to translations
## [2026-02-03T10:05] Task 5: Build & Commit
### Build Verification
- Command: `npm run build`
- Result: SUCCESS
- Output size: 2,084.68 kB (ES), 1,374.53 kB (UMD)
- Build time: 4.06s
### Commit
- Hash: 89783d0
- Message: "feat(menu): implement right-click menu functions for model operations"
- Files staged: 5 (types.ts, zh-CN.ts, en-US.ts, engine/index.ts, engine-manager.ts)
- Stats: 551 insertions(+), 118 deletions(-)
### Summary
All 5 tasks completed successfully:
1. ✅ I18n files updated (4 new fields)
2. ✅ Engine layer: 8 methods added
3. ✅ EngineManager: 8 proxy methods added
4. ✅ Right-click menu handler: All functions connected + quick select submenu
5. ✅ Build verification: PASSED

View File

@@ -1,420 +0,0 @@
# 构件详情弹窗 Bug 修复
## TL;DR
> **Quick Summary**: 修复构件详情弹窗的 5 个问题:删除重复的 PropertyPanelManager统一使用 ComponentDetailManager修复 CSS 样式(背景色、左边距);修复选中切换时内容不更新的问题。
>
> **Deliverables**:
> - 删除 PropertyPanelManager 及所有引用
> - 工具栏按钮改用 ComponentDetailManager
> - 折叠面板样式修复
> - 选中切换功能正常工作
>
> **Estimated Effort**: Medium (2-3 小时)
> **Parallel Execution**: YES - 2 waves
> **Critical Path**: Task 1 → Task 2 → Task 4 → Task 5
---
## Context
### Original Request
用户在测试时发现 5 个问题:
1. 双弹窗 - 底部面板和右键菜单各打开一个弹窗
2. 无背景色 - 折叠面板头部没有背景色
3. 左边距不足 - 头部需要增加左侧 padding
4. Mock 数据 - 工具栏按钮打开的是 mock 数据
5. 选中切换无效 - 点击不同构件内容不更新
### Interview Summary
**Key Discussions**:
- 确认完全删除 PropertyPanelManager不是废弃
- 手动测试策略(非 TDD
- 统一使用 ComponentDetailManager 作为唯一实现
**Research Findings**:
- 发现两套独立实现ComponentDetailManager 和 PropertyPanelManager
- PropertyPanelManager 硬编码了 mock 数据
- Toolbar 按钮调用的是错误的 Manager
- CSS 问题ghost 模式下背景色被设为 transparent
### Root Cause Analysis
| 问题 | 根因 |
|------|------|
| 双弹窗 | 两个 Manager 创建两个不同的 DialogID 不同) |
| 无背景色 | `collapse/index.css` 第 19 行:`.is-ghost .bim-collapse-header { background-color: transparent }` |
| Mock 数据 | `property/index.ts` 调用 `propertyPanel?.show()` 而非 `componentDetail?.show()` |
| 选中切换 | 事件流正确,但需要验证 init() 是否被正确调用 |
---
## Work Objectives
### Core Objective
统一构件详情功能为单一实现ComponentDetailManager修复所有样式和功能问题。
### Concrete Deliverables
- 删除文件:`src/managers/property-panel-manager.ts``.recycle/`
- 修改文件:共 5 个文件需要修改
### Definition of Done
- [ ] `bun run build` 成功,无编译错误
- [ ] 底部工具栏"构件详情"按钮调用 ComponentDetailManager
- [ ] 只能打开一个构件详情弹窗
- [ ] 折叠面板头部有背景色(亮色/暗色模式)
- [ ] 头部有适当的左边距
- [ ] 选中不同构件时弹窗内容自动更新
### Must Have
- 单一弹窗实例
- 背景色在所有主题下可见
- 真实数据加载(非 mock
### Must NOT Have (Guardrails)
- 不得保留 PropertyPanelManager 的任何代码
- 不得在 ComponentDetailManager 中使用 mock 数据
- 不得破坏现有的右键菜单功能
- 不得影响其他 Manager 的功能
---
## Verification Strategy (MANDATORY)
### Test Decision
- **Infrastructure exists**: NO (无自动化测试)
- **User wants tests**: Manual-only
- **Framework**: none
### Manual QA Procedures
**For each TODO, verification is done via playground:**
1. **启动环境**: `bun run dev:demo`
2. **测试工具**: 浏览器开发者工具 + 手动操作
3. **证据收集**: 截图 + 控制台日志
---
## Execution Strategy
### Parallel Execution Waves
```
Wave 1 (Start Immediately):
├── Task 1: 删除 PropertyPanelManager
├── Task 2: 修改 Toolbar 按钮
└── Task 3: 修复 CSS 样式
Wave 2 (After Wave 1):
├── Task 4: 清理 BimEngine 和 Registry 引用
└── Task 5: 验证选中切换功能
Wave 3 (Final):
└── Task 6: 完整回归测试
```
### Dependency Matrix
| Task | Depends On | Blocks | Can Parallelize With |
|------|------------|--------|---------------------|
| 1 | None | 4 | 2, 3 |
| 2 | None | 5 | 1, 3 |
| 3 | None | 5 | 1, 2 |
| 4 | 1 | 5 | None |
| 5 | 2, 3, 4 | 6 | None |
| 6 | 5 | None | None (final) |
---
## TODOs
### Wave 1: Core Changes (可并行)
- [ ] 1. 删除 PropertyPanelManager
**What to do**:
-`src/managers/property-panel-manager.ts` 移动到 `.recycle/YYYY-MM-DD/` 目录
- 记录删除原因
**Must NOT do**:
- 不得直接 `rm` 删除文件
- 不得保留任何代码片段
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`git-master`]
- `git-master`: 文件移动和版本控制
**Parallelization**:
- **Can Run In Parallel**: YES
- **Parallel Group**: Wave 1 (with Tasks 2, 3)
- **Blocks**: Task 4
- **Blocked By**: None
**References**:
- `src/managers/property-panel-manager.ts` - 要删除的文件223 行)
- `.recycle/` - 目标回收目录(按 AI_COLLABORATION.md 规范)
**Acceptance Criteria**:
- [ ] 文件已移动到 `.recycle/YYYY-MM-DD/src/managers/property-panel-manager.ts`
- [ ] 创建 `.recycle/YYYY-MM-DD/README.md` 记录删除原因
- [ ] 原位置文件不存在
**Commit**: NO (groups with Task 4)
---
- [ ] 2. 修改 Toolbar 按钮指向 ComponentDetailManager
**What to do**:
- 修改 `src/components/button-group/toolbar/buttons/property/index.ts`
-`registry.propertyPanel?.show()` 改为 `registry.componentDetail?.show()`
**Must NOT do**:
- 不得改变按钮的其他属性id, label, icon
- 不得添加额外逻辑
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
- `coding-standards`: 确保代码风格一致
**Parallelization**:
- **Can Run In Parallel**: YES
- **Parallel Group**: Wave 1 (with Tasks 1, 3)
- **Blocks**: Task 5
- **Blocked By**: None
**References**:
- `src/components/button-group/toolbar/buttons/property/index.ts:13-17` - 当前实现(调用 propertyPanel
- `src/managers/component-detail-manager.ts:35-50` - ComponentDetailManager.show() 方法
**Acceptance Criteria**:
- [ ] 第 16 行改为 `registry.componentDetail?.show()`
- [ ] 保留 console.log 用于调试
- [ ] 无 TypeScript 错误
**Commit**: NO (groups with Task 4)
---
- [ ] 3. 修复折叠面板 CSS 样式
**What to do**:
- 修改 `src/components/collapse/index.css`
-`.is-ghost .bim-collapse-header` 添加背景色
- 增加左侧 padding
- 移除 ComponentDetailManager 中的内联样式 hack可选
**Must NOT do**:
- 不得破坏非 ghost 模式的样式
- 不得使用 `!important`(除非绝对必要)
**Recommended Agent Profile**:
- **Category**: `visual-engineering`
- **Skills**: [`frontend-ui-ux`]
- `frontend-ui-ux`: CSS 样式专家
**Parallelization**:
- **Can Run In Parallel**: YES
- **Parallel Group**: Wave 1 (with Tasks 1, 2)
- **Blocks**: Task 5
- **Blocked By**: None
**References**:
- `src/components/collapse/index.css:18-22` - 当前 ghost 模式样式background: transparent
- `src/components/collapse/index.css:42-54` - 标准 header 样式(有 background-color
- `src/managers/component-detail-manager.ts:159-167` - 当前的样式 hack可移除
- `src/themes/presets.ts` - 主题变量定义
**Acceptance Criteria**:
- [ ] `.is-ghost .bim-collapse-header``background-color: var(--bim-component-bg)`
- [ ] `.is-ghost .bim-collapse-header``padding-left: 12px` 或类似值
- [ ] 暗色模式下背景可见
- [ ] 亮色模式下背景可见
- [ ] hover 状态仍有不同背景色
**Commit**: NO (groups with Task 4)
---
### Wave 2: Cleanup & Verification
- [ ] 4. 清理 BimEngine 和 ManagerRegistry 中的 PropertyPanelManager 引用
**What to do**:
- 修改 `src/bim-engine.ts`
- 删除 import 语句(第 8 行)
- 删除属性声明(第 37 行)
- 删除实例化代码(第 110 行)
- 删除 registry 注册(第 126 行)
- 删除 destroy 调用(第 156 行)
- 修改 `src/core/manager-registry.ts`
- 删除 import 语句(第 14 行)
- 删除属性声明(第 52-53 行)
**Must NOT do**:
- 不得删除 ComponentDetailManager 相关代码
- 不得改变初始化顺序
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
- `coding-standards`: TypeScript 代码清理
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential
- **Blocks**: Task 5
- **Blocked By**: Task 1
**References**:
- `src/bim-engine.ts:8` - import PropertyPanelManager
- `src/bim-engine.ts:37` - propertyPanel 属性声明
- `src/bim-engine.ts:110` - new PropertyPanelManager()
- `src/bim-engine.ts:126` - registry.propertyPanel = ...
- `src/bim-engine.ts:156` - propertyPanel?.destroy()
- `src/core/manager-registry.ts:14` - import type
- `src/core/manager-registry.ts:52-53` - propertyPanel 属性
**Acceptance Criteria**:
- [ ] `bun run build` 成功
- [ ] 无 PropertyPanelManager 相关代码
- [ ] 无未使用的 import 警告
**Commit**: YES
- Message: `refactor(component-detail): 移除 PropertyPanelManager统一使用 ComponentDetailManager`
- Files:
- `.recycle/YYYY-MM-DD/src/managers/property-panel-manager.ts`
- `src/components/button-group/toolbar/buttons/property/index.ts`
- `src/components/collapse/index.css`
- `src/bim-engine.ts`
- `src/core/manager-registry.ts`
- Pre-commit: `bun run build`
---
- [ ] 5. 验证并修复选中切换功能
**What to do**:
- 在 playground 中测试选中切换
- 如果不工作,检查以下几点:
1. `component:selected` 事件是否正确发射Engine 组件)
2. `ComponentDetailManager.init()` 是否被调用
3. `isOpen()` 返回值是否正确
- 根据发现的问题进行修复
**Must NOT do**:
- 不得添加不必要的 console.log调试后删除
- 不得改变事件名称或 payload 结构
**Recommended Agent Profile**:
- **Category**: `unspecified-low`
- **Skills**: [`coding-standards`]
- `coding-standards`: 调试和代码修复
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential (after Wave 1)
- **Blocks**: Task 6
- **Blocked By**: Tasks 2, 3, 4
**References**:
- `src/components/engine/index.ts:131-145` - 事件发射代码
- `src/managers/component-detail-manager.ts:19-33` - 事件监听代码
- `src/managers/component-detail-manager.ts:68-81` - loadAndRenderContent 方法
**Acceptance Criteria**:
**Manual Execution Verification:**
- [ ] 启动 `bun run dev:demo`
- [ ] 选中构件 A右键打开构件详情
- [ ] 验证:弹窗显示构件 A 的属性
- [ ] 选中构件 B不关闭弹窗
- [ ] 验证:弹窗自动更新为构件 B 的属性
- [ ] 控制台打印 `[Engine] 构件选中:` 日志
**Commit**: YES (if changes made)
- Message: `fix(component-detail): 修复选中切换时内容不更新的问题`
- Files: depends on what needs fixing
- Pre-commit: `bun run build`
---
### Wave 3: Final Verification
- [ ] 6. 完整回归测试
**What to do**:
- 运行 `bun run build` 确保编译通过
- 在 playground 中完整测试所有功能
**Must NOT do**:
- 无代码修改(仅测试)
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`playwright`]
- `playwright`: 浏览器自动化测试(可选)
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Final
- **Blocks**: None (final task)
- **Blocked By**: Task 5
**References**:
- 无(纯测试任务)
**Acceptance Criteria**:
**Manual Execution Verification (COMPLETE REGRESSION):**
**构建验证:**
- [ ] `bun run build` → 成功,无错误
- [ ] `bun run dev:demo` → 启动成功
**问题 1 - 单一弹窗验证:**
- [ ] 点击底部工具栏"构件详情" → 打开弹窗
- [ ] 右键点击"构件详情" → 同一个弹窗(不是新弹窗)
- [ ] 弹窗 ID 在 DevTools 中为 `component-detail-dialog`
**问题 2 - 背景色验证:**
- [ ] 暗色模式:折叠面板头部有可见背景色
- [ ] 切换到亮色模式(如果支持):头部背景仍可见
- [ ] hover 时背景色有变化
**问题 3 - 左边距验证:**
- [ ] 折叠面板标题有适当的左侧间距(不贴边)
**问题 4 - 真实数据验证:**
- [ ] 选中构件后打开弹窗 → 显示真实属性数据
- [ ] 不显示 mock 数据(如 "1f8d-4a2e-9c", "Generic - 200mm"
**问题 5 - 选中切换验证:**
- [ ] 弹窗打开状态下,选中不同构件 → 内容自动刷新
- [ ] 取消选中 → 显示"请先选中构件"
**Commit**: NO (无代码修改)
---
## Commit Strategy
| After Task | Message | Files | Verification |
|------------|---------|-------|--------------|
| 4 | `refactor(component-detail): 移除 PropertyPanelManager统一使用 ComponentDetailManager` | 6 files | `bun run build` |
| 5 | `fix(component-detail): 修复选中切换时内容不更新的问题` (if needed) | TBD | `bun run build` |
---
## Success Criteria
### Verification Commands
```bash
bun run build # Expected: Build success, no errors
```
### Final Checklist
- [ ] 所有 "Must Have" 功能正常
- [ ] 所有 "Must NOT Have" 未出现
- [ ] 构建通过
- [ ] 5 个原始问题全部解决

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,547 @@
# 右键菜单功能对接
## TL;DR
> **Quick Summary**: 对接右键菜单的构件操作功能,包括隐藏、半透明、隔离、显示全部,以及新增"快速选择"子菜单。
>
> **Deliverables**:
> - 国际化文件更新types.ts, zh-CN.ts, en-US.ts
> - Engine 层新增 8 个方法
> - EngineManager 层新增 8 个代理方法
> - 右键菜单 handler 实现功能调用
>
> **Estimated Effort**: Short (约 30 分钟)
> **Parallel Execution**: NO - sequential
> **Critical Path**: Task 1 → Task 2 → Task 3 → Task 4
---
## Context
### Original Request
对接右键菜单的以下功能:
1. 隐藏选中构件:`engine.modelToolModule.hideModel(engine.engineStatus.highlightModels)`
2. 半透明选中构件:`engine.modelToolModule.translucentModel(engine.engineStatus.highlightModels)`
3. 隔离/隐藏其他构件:`engine.modelToolModule.isolateModel(engine.engineStatus.highlightModels)`
4. 隔离/半透明其他构件:`engine.modelToolModule.translucentOtherModel(engine.engineStatus.highlightModels)`
5. 显示所有模型:`engine.modelToolModule.showAllModels()`
新增快速选择子菜单:
6. 选择同类模型:`engine.modelToolModule.batchSelectSameTypeModel(engine.engineStatus.highlightModels)`
7. 选择同层模型:`engine.modelToolModule.batchSelectSameLevelModel(engine.engineStatus.highlightModels)`
8. 选择同层同类模型:`engine.modelToolModule.batchSelectSameLevelTypeModel(engine.engineStatus.highlightModels)`
### 底层 API 模式
```typescript
// 获取选中构件
const models = engine.engineStatus.highlightModels;
// 调用 modelToolModule 方法
engine.modelToolModule.hideModel(models);
engine.modelToolModule.translucentModel(models);
engine.modelToolModule.isolateModel(models);
engine.modelToolModule.translucentOtherModel(models);
engine.modelToolModule.showAllModels();
engine.modelToolModule.batchSelectSameTypeModel(models);
engine.modelToolModule.batchSelectSameLevelModel(models);
engine.modelToolModule.batchSelectSameLevelTypeModel(models);
```
---
## Work Objectives
### Core Objective
将底层引擎的构件操作 API 对接到右键菜单,实现完整的构件隐藏、半透明、隔离和快速选择功能。
### Concrete Deliverables
- `src/locales/types.ts` - 添加 4 个新字段
- `src/locales/zh-CN.ts` - 添加中文翻译
- `src/locales/en-US.ts` - 添加英文翻译
- `src/components/engine/index.ts` - 添加 8 个方法
- `src/managers/engine-manager.ts` - 添加 8 个代理方法 + 更新右键菜单 handler
### Definition of Done
- [x] 右键选中构件时,所有菜单功能可正常调用
- [x] 快速选择子菜单正确显示三个选项
- [x] 构建成功:`npm run build`
### Must Have
- 所有 8 个底层 API 都要对接
- 国际化支持中英文
- 保持现有代码风格
### Must NOT Have (Guardrails)
- 不要修改底层引擎 API
- 不要添加额外的 UI 组件
- 不要修改菜单的显示逻辑
---
## Verification Strategy
### Test Decision
- **Infrastructure exists**: NO
- **User wants tests**: Manual-only
- **QA approach**: Manual verification
---
## TODOs
- [x] 1. 更新国际化文件
**What to do**:
1.`src/locales/types.ts``menu` 对象中添加:
```typescript
quickSelect: string;
selectSameType: string;
selectSameLevel: string;
selectSameLevelType: string;
```
2. 在 `src/locales/zh-CN.ts` 的 `menu` 对象中添加:
```typescript
quickSelect: '快速选择',
selectSameType: '选择同类模型',
selectSameLevel: '选择同层模型',
selectSameLevelType: '选择同层同类模型'
```
3. 在 `src/locales/en-US.ts` 的 `menu` 对象中添加:
```typescript
quickSelect: 'Quick Select',
selectSameType: 'Select Same Type',
selectSameLevel: 'Select Same Level',
selectSameLevelType: 'Select Same Level & Type'
```
**Must NOT do**:
- 不要修改其他现有字段
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential
- **Blocks**: Task 2, 3, 4
- **Blocked By**: None
**References**:
- `src/locales/types.ts:53-64` - 现有 menu 类型定义
- `src/locales/zh-CN.ts:34-45` - 现有中文翻译
- `src/locales/en-US.ts:34-45` - 现有英文翻译
**Acceptance Criteria**:
- [ ] TypeScript 无类型错误
- [ ] 三个文件都已更新
**Commit**: NO (与 Task 2-4 一起提交)
---
- [x] 2. Engine 层添加构件操作方法
**What to do**:
在 `src/components/engine/index.ts` 中添加以下 8 个公共方法在路径漫游区域之后、destroy 之前):
```typescript
// ==================== 构件操作 ====================
/**
* 隐藏选中构件
*/
public hideSelectedModels(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot hide models: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.hideModel(models);
}
}
/**
* 半透明选中构件
*/
public translucentSelectedModels(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot translucent models: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.translucentModel(models);
}
}
/**
* 隔离选中构件(隐藏其他)
*/
public isolateSelectedModels(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot isolate models: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.isolateModel(models);
}
}
/**
* 半透明其他构件
*/
public translucentOtherModels(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot translucent other models: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.translucentOtherModel(models);
}
}
/**
* 显示所有模型
*/
public showAllModels(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot show all models: engine not initialized.');
return;
}
this.engine.modelToolModule.showAllModels();
}
/**
* 批量选择同类模型
*/
public batchSelectSameTypeModel(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot batch select: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.batchSelectSameTypeModel(models);
}
}
/**
* 批量选择同层模型
*/
public batchSelectSameLevelModel(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot batch select: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.batchSelectSameLevelModel(models);
}
}
/**
* 批量选择同层同类模型
*/
public batchSelectSameLevelTypeModel(): void {
if (!this._isInitialized || !this.engine?.modelToolModule) {
console.warn('[Engine] Cannot batch select: engine not initialized.');
return;
}
const models = this.engine.engineStatus?.highlightModels;
if (models) {
this.engine.modelToolModule.batchSelectSameLevelTypeModel(models);
}
}
// ==================== 结束:构件操作 ====================
```
**Must NOT do**:
- 不要修改现有方法
- 不要修改 `fitSectionBoxToModel` 方法
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential
- **Blocks**: Task 3
- **Blocked By**: Task 1
**References**:
- `src/components/engine/index.ts:496-506` - `fitSectionBoxToModel` 参考模式(使用 highlightModels
- `src/components/engine/index.ts:431-491` - 路径漫游方法区域(在此之后添加)
**Acceptance Criteria**:
- [ ] 8 个方法都已添加
- [ ] 方法有 JSDoc 注释
- [ ] 使用项目规范的区域注释标记
**Commit**: NO (与其他 Task 一起提交)
---
- [x] 3. EngineManager 添加代理方法
**What to do**:
在 `src/managers/engine-manager.ts` 中添加 8 个代理方法在路径漫游区域之后、destroy 之前):
```typescript
// ==================== 构件操作 ====================
/**
* 隐藏选中构件
*/
public hideSelectedModels(): void {
this.engineInstance?.hideSelectedModels();
}
/**
* 半透明选中构件
*/
public translucentSelectedModels(): void {
this.engineInstance?.translucentSelectedModels();
}
/**
* 隔离选中构件(隐藏其他)
*/
public isolateSelectedModels(): void {
this.engineInstance?.isolateSelectedModels();
}
/**
* 半透明其他构件
*/
public translucentOtherModels(): void {
this.engineInstance?.translucentOtherModels();
}
/**
* 显示所有模型
*/
public showAllModels(): void {
this.engineInstance?.showAllModels();
}
/**
* 批量选择同类模型
*/
public batchSelectSameTypeModel(): void {
this.engineInstance?.batchSelectSameTypeModel();
}
/**
* 批量选择同层模型
*/
public batchSelectSameLevelModel(): void {
this.engineInstance?.batchSelectSameLevelModel();
}
/**
* 批量选择同层同类模型
*/
public batchSelectSameLevelTypeModel(): void {
this.engineInstance?.batchSelectSameLevelTypeModel();
}
// ==================== 结束:构件操作 ====================
```
**Must NOT do**:
- 不要修改现有方法
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential
- **Blocks**: Task 4
- **Blocked By**: Task 2
**References**:
- `src/managers/engine-manager.ts:431-492` - 路径漫游代理方法区域
**Acceptance Criteria**:
- [ ] 8 个代理方法都已添加
- [ ] 方法有 JSDoc 注释
**Commit**: NO (与其他 Task 一起提交)
---
- [x] 4. 更新右键菜单 Handler
**What to do**:
在 `src/managers/engine-manager.ts` 的 `registerHandler` 回调中:
1. **替换隐藏选中构件的 onClick**(约第 78-81 行):
```typescript
onClick: () => {
this.hideSelectedModels();
this.rightKey?.hide();
}
```
2. **替换半透明选中构件的 onClick**(约第 90-93 行):
```typescript
onClick: () => {
this.translucentSelectedModels();
this.rightKey?.hide();
}
```
3. **替换隔离-隐藏其他的 onClick**(约第 107-110 行):
```typescript
onClick: () => {
this.isolateSelectedModels();
this.rightKey?.hide();
}
```
4. **替换隔离-半透明其他的 onClick**(约第 114-117 行):
```typescript
onClick: () => {
this.translucentOtherModels();
this.rightKey?.hide();
}
```
5. **替换显示全部的 onClick**(约第 142-144 行):
```typescript
onClick: () => {
this.showAllModels();
this.rightKey?.hide();
}
```
6. **在隔离选中构件菜单项之后order: 4 之后),添加快速选择子菜单**order: 5将剖切盒适应改为 order: 6显示全部改为 order: 7
```typescript
// 5. 快速选择(带子菜单)
items.push({
id: 'quickSelect',
label: 'menu.quickSelect',
group: 'component',
order: 5,
children: [
{
id: 'selectSameType',
label: 'menu.selectSameType',
onClick: () => {
this.batchSelectSameTypeModel();
this.rightKey?.hide();
}
},
{
id: 'selectSameLevel',
label: 'menu.selectSameLevel',
onClick: () => {
this.batchSelectSameLevelModel();
this.rightKey?.hide();
}
},
{
id: 'selectSameLevelType',
label: 'menu.selectSameLevelType',
onClick: () => {
this.batchSelectSameLevelTypeModel();
this.rightKey?.hide();
}
}
]
});
```
7. **更新剖切盒适应的 order 为 6**
8. **更新显示全部的 order 为 7**
**Must NOT do**:
- 不要修改菜单项的 id 和 label除了新增的
- 不要修改 group 分组逻辑
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: [`coding-standards`]
**Parallelization**:
- **Can Run In Parallel**: NO
- **Parallel Group**: Sequential (final task)
- **Blocks**: None
- **Blocked By**: Task 3
**References**:
- `src/managers/engine-manager.ts:53-149` - 现有右键菜单 handler
- `src/managers/engine-manager.ts:96-121` - 隔离子菜单结构参考
**Acceptance Criteria**:
- [ ] 所有 console.log 占位符已替换为实际方法调用
- [ ] 快速选择子菜单正确添加
- [ ] 菜单项 order 正确排序
**Commit**: YES
- Message: `feat(menu): implement right-click menu functions for model operations`
- Files:
- `src/locales/types.ts`
- `src/locales/zh-CN.ts`
- `src/locales/en-US.ts`
- `src/components/engine/index.ts`
- `src/managers/engine-manager.ts`
- Pre-commit: `npm run build`
---
- [x] 5. 构建验证
**What to do**:
- 运行 `npm run build` 确保构建成功
**Recommended Agent Profile**:
- **Category**: `quick`
- **Skills**: []
**Parallelization**:
- **Can Run In Parallel**: NO
- **Blocks**: None
- **Blocked By**: Task 4
**Acceptance Criteria**:
```bash
npm run build
# 预期: 构建成功,无错误
```
**Commit**: NO
---
## Commit Strategy
| After Task | Message | Files | Verification |
|------------|---------|-------|--------------|
| 4 | `feat(menu): implement right-click menu functions for model operations` | types.ts, zh-CN.ts, en-US.ts, engine/index.ts, engine-manager.ts | npm run build |
---
## Success Criteria
### Verification Commands
```bash
npm run build # Expected: Build successful
```
### Final Checklist
- [x] 国际化文件已更新3 个文件)
- [x] Engine 层添加 8 个方法
- [x] EngineManager 层添加 8 个代理方法
- [x] 右键菜单 handler 已更新
- [x] 快速选择子菜单已添加
- [x] 构建成功