You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LightWork3D/docs/FreeCAD 端子显示连线保存回写开发文档.md

620 lines
23 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# FreeCAD 端子显示、手动连线、保存回写开发文档
## 1. 当前任务边界
本文档只面向当前由一个人负责的 FreeCAD 3D 工作台能力:
- 端子显示
- 端子手动连线
- FreeCAD 文档保存
- 最小 3D -> 2D 回写
当前不做:
- 自动布线
- `D:\code\zwl\sources\ThreeD` 旧 3D 引擎扩展
- 复杂 UI 改造
- FreeCAD 核心 C/C++ 源码改造
- 3D 位姿写入数据库
- 新增或依赖旧 3D 场景表
第一版 3D 真相源是 FreeCAD 文档,即 `scene.FCStd`。QET/zwl 只负责 2D 数据、交换 JSON、启动 FreeCAD、后续读取最小回写结果。
## 2. 已有代码与文档现状
### 2.1 LightWork3D / FreeCAD 侧
已有模块:
- `src/Mod/FreeCADExchange/ExchangeBootstrap.py`
- `src/Mod/FreeCADExchange/DeviceImport.py`
- `src/Mod/FreeCADExchange/InitGui.py`
当前已经做到:
- 从环境变量 `QET_2D_TO_3D_JSON` 读取 `2d_to_3d.json`
- 校验 `project_uuid / devices / terminals / device_models`
- 根据 `resolved_model_path` 导入 STEP / IGES / FCStd 等本地模型
- 将导入的设备放入 `QETExchangeDevices` 根组
当前还没有真正完成:
- 根据 `terminals` 创建设备端子对象
- 端子对象的 LCS / 标记属性
- 端子之间的手动连线
- `3d_to_2d.json` 回写
### 2.2 zwl / QET 侧
已有模块:
- `sources/FreeCAD/FreeCADExchangeExportService.cpp`
- `sources/FreeCAD/FreeCADLaunchService.cpp`
当前已经做到:
- 导出 `<ProjectRoot>/.qet_freecad/2d_to_3d.json`
- 返回 `<ProjectRoot>/.qet_freecad/scene.FCStd`
- 启动 FreeCAD并设置
- `QET_2D_TO_3D_JSON`
- `QET_FREECAD_SCENE_FILE`
第一版数据库约束:
- 只允许依赖 `project_2d3d_symbol_binding`
- 只允许依赖 `project_2d3d_terminal_binding`
- 设备绑定只依赖 `project_uuid / element_uuid / instance_id`
- 端子绑定只依赖 `project_uuid / terminal_uuid / instance_id`
- 第一版端子绑定唯一依据是 `terminal_uuid`
### 2.3 代码落地约束
当前第一版实现优先放在:
```text
D:\LightWork3D\src\Mod\FreeCADExchange
```
实现形式优先使用 Python 文件,例如:
```text
src/Mod/FreeCADExchange/DeviceImport.py
src/Mod/FreeCADExchange/TerminalImport.py
src/Mod/FreeCADExchange/ManualWiring.py
src/Mod/FreeCADExchange/ExchangeWriteBack.py
```
第一版尽量只改 FreeCAD 插件层:
- 可以新增 `FreeCADExchange` 下的 `.py` 文件。
- 可以修改 `FreeCADExchange\ExchangeBootstrap.py` 做流程调度。
- 可以修改 `FreeCADExchange\InitGui.py` 注册简单命令。
- 可以修改 `FreeCADExchange\CMakeLists.txt`,把新增 `.py` 加入安装/复制列表。
第一版尽量不改:
- FreeCAD 核心 C/C++ 源码。
- `D:\code\zwl\sources\ThreeD` 旧 3D 模块。
- 数据库旧 3D 场景表。
这样做的好处是:你的端子显示、手动连线、保存回写可以先作为 FreeCAD 工作台插件跑通;后续 csm 改 UI、qdj 做自动布线时,可以直接调用这些 Python 层能力,不需要他们理解或修改 FreeCAD 核心源码。
## 3. 本地设备模板是否可以使用
可以,而且第一版建议优先使用本地模板。
QET 导出的 `device_models[].resolved_model_path` 本来就是给 FreeCAD 使用的本地模型路径。FreeCADExchange 当前支持导入:
- `.step`
- `.stp`
- `.iges`
- `.igs`
- `.brep`
- `.brp`
- `.fcstd`
因此本地 STEP 文件可以直接作为第一批几何资源导入。
但从当前开发方向开始,正式可复用的设备模板建议统一保存为 `.FCStd`。也就是说:
```text
STEP / STP / STE 原始几何
-> 在 FreeCAD 里添加端子 LCS 和电气语义
-> 保存为 FCStd 设备模板
-> 后续不同工程、不同人员统一使用这个 FCStd
```
STEP / STP / STE 适合作为模板制作的输入,不建议作为长期带电气语义的最终交付文件。因为 STEP 可以稳定保存几何,但不能可靠保存 FreeCAD LCS、动态属性、端子角色、接线资格等二次开发语义。
但需要注意:
> 本地 STEP 只提供几何,不天然提供“哪个位置是端子”。
所以要实现端子显示和端子连线,本地模板还必须补一层端子语义。第一版采用下面的优先级:
1. 正式方式:使用 FCStd 模板,在模板里提前放好 LCS 端子对象。
2. 过渡方式STEP + sidecar JSON在同目录下保存端子槽位坐标。
3. 如果没有模板语义,则跳过端子生成并输出警告,不再用 bbox fallback 猜端子位置。
sidecar 只作为 FreeCAD 端模板辅助文件,不进入第一版数据库绑定主键。
sidecar 里除了端子坐标,还可以继续补端子朝向,例如 `rotation`,让模板端子不只是“有位置”,还可以“有方向”。
FCStd 模板里的 LCS 如果已经带了 Placement 朝向,导入时要把位置和朝向一并读取出来,这样生成的工程端子不只是有坐标,还能保留真实出线方向。
### 3.1 FCStd 设备模板制作约定
FCStd 设备模板用于解决“这个模型本身就带端子语义”的问题。模板端子是跨工程复用的槽位,不绑定某个具体工程里的 `terminal_uuid`
推荐模板结构:
```text
电流互感器.FCStd
ModelGeometry
Terminal_P1
Terminal_P2
```
模板端子使用 LCS 表示,至少保存:
- `Role = "Terminal"`
- `CanWire = true`
- `QetTemplateSlotName = "P1"` / `"P2"`
- `QetTerminalLabel = "P1"` / `"P2"`
- `QetTerminalType = "primary"` 等可选分类
模板端子不保存:
- `QetTerminalUuid`
- `QetInstanceId`
- `project_uuid`
- 任意工程内绑定字段
这些工程级字段由导入项目时的 `2d_to_3d.json` 和 FreeCADExchange 运行时补齐。这样同一个 FCStd 设备模板才能在多个工程、多台机器、多人之间复用。
### 3.1.1 FCStd 导入运行时约定
FCStd 模板中的端子 LCS 是“模板槽位定义”,不是最终留在工程场景里的端子对象。
导入到 `QETScene`FreeCADExchange 的处理顺序是:
1. 复制 FCStd 中的几何对象到设备组。
2. 读取模板 LCS 的 `QetTemplateSlotName / Label / Placement`
3. 将槽位位置和朝向序列化到设备组属性 `QetTemplateSlotsJson`
4. 删除复制出来的模板 LCS 及其 `OriginFeatures`,避免这些模板对象留在 `App::Part` 中参与变换或选择。
5. 后续由 `TerminalImport.py``terminal_uuid``QETTerminals_*` 下创建工程端子 LCS。
这样做不会改变第一版数据库约束:`QetTemplateSlotsJson` 只是 FreeCAD 文档内部的运行时缓存,不进入 `project_2d3d_symbol_binding``project_2d3d_terminal_binding`
如果同一个设备从 FCStd 切回 STEP / IGES / BREP 等非 FCStd 模型,导入时会清空旧的 `QetTemplateSlotsJson`,避免继续沿用上一次 FCStd 的端子槽位。
### 3.2 模板制作工具目标
后续在 `FreeCADExchange` 中新增模板制作能力,目标是让用户不需要手工给 LCS 添加属性:
1. 导入 STEP / STP / STE 几何模型。
2. 在模型真实接线位置添加端子,例如 `P1`、`P2`。
3. 自动创建 LCS并写入模板端子语义。
4. 保存为 `.FCStd` 设备模板。
5. 后续 LightWork3D 工程引用该 `.FCStd` 后,自动识别模板端子并生成工程端子对象。
### 3.2.1 方案 2设备模板端子制作面板
当前 Python 控制台方式只适合开发验证,不适合 CAD 工作人员。下一步开发目标改为在 FreeCAD 右侧任务区提供“设备模板端子制作”面板。
第一版面板能力:
- 显示当前文档中的模板端子列表。
- 输入端子名,例如 `P1`、`P2`。
- 用户选择模型上的孔、点或对象后,点击“添加端子”。
- 点击“校验端子”显示总数、有效数和警告。
- 点击“保存为 FCStd”选择路径并保存模板。
该面板只包装现有 Python 能力,不改 FreeCAD C/C++ 源码:
- `TemplateAuthoring.create_template_terminal`
- `TemplateAuthoring.validate_template_terminals`
- `TemplateAuthoring.save_template_as_fcstd`
目标是让 CAD 工作人员只通过鼠标选择和按钮点击完成模板制作,不再直接输入 Python 代码。
### 3.3 A 方案资产流转约定
A 方案下,`.FCStd` 是正式可复用设备资产STEP / STP / STE 只作为模板制作的原始几何输入。
完整流转固定为:
```text
STEP / STP / STE 原始几何
-> FreeCAD 中添加端子 LCS 和模板语义
-> 保存为 FCStd 设备模板
-> zwl/QET 选择该 FCStd 作为设备 3D 资产
-> 3D 视图导出 2d_to_3d.json
-> FreeCAD 导入 FCStd 并绑定工程端子
-> 手动连线并保存 scene.FCStd
-> 生成 3d_to_2d.json
```
zwl/QET 侧只需要支持 `.FCStd` 的选择、复制、保存和导出路径,不解析 `.FCStd` 内部的 LCS、端子属性或装配结构。`.FCStd` 的内部语义由 FreeCADExchange 读取。
详细设计见:
- `docs/superpowers/specs/2026-05-20-freecad-fcstd-asset-flow-design.md`
## 4. 为什么要先落地设备模板
这里的“设备模板”不是要求先把所有设备都建完,而是要先有一个稳定样板,证明端子显示和连线可以依附在真实设备上。
原因:
- 端子必须依附在设备实例上,不能只是空间中的孤立点。
- 端子连线需要稳定的起点、终点和出线方向。
- STEP 普通顶点不稳定,不适合作为端子主对象。
- 如果没有模板层,后续每种设备都要手工猜端子位置。
- 自动布线后续会依赖当前手动布线沉淀出的端子对象和路径对象。
因此第一版只需要选 1 到 2 个设备样板,例如断路器、端子排或继电器,把模板约定跑通。
## 5. 第一版对象模型
### 5.1 设备实例组
每个 2D 设备实例在 FreeCAD 中对应一个设备组。
建议对象:
```text
QETExchangeDevices
QETDevice_<element_uuid>
imported model objects
QETTerminals
QETWires
```
设备组至少保存属性:
- `QetProjectUuid`
- `QetElementUuid`
- `QetInstanceId`
- `QetResolvedModelPath`
`QetInstanceId` 如果输入为空,由 FreeCAD 生成,并在保存回写时写入 `3d_to_2d.json`
### 5.2 端子对象
端子使用 FreeCAD LCS 表示。推荐对象为:
```text
Datum CoordinateSystem + Role="Terminal"
```
端子对象至少保存属性:
- `QetProjectUuid`
- `QetElementUuid`
- `QetTerminalUuid`
- `QetInstanceId`
- `Role = "Terminal"`
- `CanWire = true`
端子判断规则:
1. 对象必须有 `Role`
2. `Role == "Terminal"`
3. 对象必须有 `QetTerminalUuid`
4. `CanWire == true`
第一版禁止把 `terminal_key``connection_point_key` 当作绑定主键。模板内部可以有槽位名,但最终业务识别只认 `terminal_uuid`
### 5.3 手动连线对象
手动连线可以先用 FreeCAD 中的折线对象表示,例如 Draft Wire 或 Part 曲线。
连线对象至少保存属性:
- `QetProjectUuid`
- `QetStartTerminalUuid`
- `QetEndTerminalUuid`
- `QetStartInstanceId`
- `QetEndInstanceId`
- `RouteType = "Manual"`
连线对象建议挂在对应设备实例下的 `QETWires_<element_uuid>` 组里,优先跟随起点端子所属设备。
第一版连线路径保存在 `scene.FCStd`。是否把路径几何回写给 QET后续单独扩协议不在当前最小数据库绑定范围内。
## 6. 推荐文件结构
`src/Mod/FreeCADExchange` 下逐步拆分模块:
```text
FreeCADExchange/
ExchangeBootstrap.py # 启动入口,读取 JSON调度导入流程
DeviceImport.py # 设备导入,已存在
TemplateSemantics.py # 新增:读取 FCStd LCS 或 STEP sidecar 端子槽位
TemplateAuthoring.py # 计划新增:把 STEP/STP/STE 制作为带端子语义的 FCStd 模板
TemplateAuthoringPanel.py # 新增CAD 人员使用的端子制作任务面板
TerminalImport.py # 新增:根据 terminals 创建/更新端子对象
TerminalObjects.py # 新增:端子对象属性、查找、校验工具
ManualWiring.py # 新增:端子选择、折线路径创建、连线对象属性
ExchangeWriteBack.py # 新增:生成 3d_to_2d.json
InitGui.py # 后续由 UI 改造统一接入命令
CMakeLists.txt # 新增 .py 后必须同步加入 FreeCADExchange_Scripts
```
如果暂时不做 UI可以先暴露 Python 函数和简单命令,保证功能链路可测。
推荐第一版调用链:
```text
ExchangeBootstrap.py
-> DeviceImport.import_devices_from_payload(...)
-> TerminalImport.import_terminals_from_payload(...)
-> ExchangeWriteBack.write_back_if_needed(...) 或由保存命令触发
ManualWiring.py
-> 只允许选择 TerminalObjects.is_terminal_object(...) 认可的端子对象
-> 创建 RouteType="Manual" 的连线对象
-> 保存到 scene.FCStd
```
每新增一个 Python 模块,都要加入 `FreeCADExchange\CMakeLists.txt``FreeCADExchange_Scripts`,否则 Visual Studio 构建/INSTALL 后运行目录里不会出现该脚本。
## 7. 开发步骤
### 阶段 A0FCStd 设备模板制作
目标:
- 用户可以导入 STEP / STP / STE 几何模型。
- 用户可以给模型添加带电气语义的端子 LCS。
- 模板保存为 `.FCStd` 后,可以脱离当前工程复用。
实现建议:
- 新增 `TemplateAuthoring.py`
- 提供最小命令:
- `QET_Template_AddTerminal`
- `QET_Template_SaveAsFCStd`
- 第一版端子位置可以通过用户选择对象/点位后的三维坐标生成。
- 第一版端子方向默认使用单位旋转,后续再补出线方向编辑。
模板端子属性:
- `Role = "Terminal"`
- `CanWire = true`
- `QetTemplateSlotName`
- `QetTerminalLabel`
- `QetTerminalType`
验收:
- 打开一个普通 STEP 模型。
- 添加 `P1`、`P2` 两个端子。
- 保存为 `电流互感器.FCStd`
- 重新打开该 FCStd 后,端子 LCS 仍存在,属性仍存在。
- 在项目导入流程中引用该 FCStd端子位置优先来自模板 LCS而不是 bbox fallback。
### 阶段 A本地模板导入基线
目标:
- 本地 STEP / FCStd 可以稳定导入。
- 正式设备资源优先使用带端子语义的 FCStd 模板。
- 设备组有 `QetElementUuid / QetInstanceId`
- 重新打开同一个项目时,不重复创建同一设备。
改动点:
- 保持 `DeviceImport.py` 现有逻辑。
- 补齐设备组上的 `QetProjectUuid`
- 如果 `instance_id` 为空,生成稳定的 FreeCAD 实例 ID。
验收:
- 使用本地 FCStd 模板导入设备。
- FreeCAD 树中可看到设备组。
- 关闭并重新打开,不产生重复设备组。
### 阶段 B端子显示
目标:
- 根据 `2d_to_3d.json``terminals` 为设备创建端子对象。
- 每个端子都能在 FreeCAD 场景中被看到、被选中。
实现建议:
- 新增 `TerminalImport.py`
-`element_uuid``instance_id` 找到设备组。
- 为每个 `terminal_uuid` 创建 LCS。
- LCS 放入设备组下的 `QETTerminals` 子组。
端子位置策略:
1. 如果 FCStd 模板已有 `Role="Terminal"` 的 LCS则优先读取模板 LCS 的槽位信息,再生成工程端子 LCS。
2. 如果有 sidecar JSON则按 sidecar 坐标创建。
3. 如果只有 STEP 且没有 sidecar则不生成端子并在导入报告中提示缺少模板槽位。
第一版不再按设备包围盒猜测临时端子,避免把错误端子位置保存进工程。
验收:
- 控制台输出端子创建数量。
- 每个端子对象带 `QetTerminalUuid`
- 选择端子时能确认它属于哪个设备实例。
### 阶段 C端子手动连线
目标:
- 只能从端子连到端子。
- 普通几何点、边、面不能直接作为布线端点。
实现建议:
- 新增 `ManualWiring.py`
- 提供函数:
- `is_terminal_object(obj)`
- `create_manual_wire(start_terminal, end_terminal, waypoints)`
- `list_manual_wires(doc)`
- 第一版路径点可以先使用:
- 起点 LCS 原点
- 用户手动点选的中间点
- 终点 LCS 原点
如果暂时没有完整 UI可先做最小命令
1. 用户选择两个端子对象。
2. 执行命令生成一条直线或折线。
3. 连线对象保存起止端子 UUID。
验收:
- 未选择端子时拒绝创建连线。
- 选择同一个端子作为起终点时拒绝创建。
- 创建成功后,连线对象带起点和终点 UUID。
### 阶段 D保存与回写
目标:
- FreeCAD 保存 `scene.FCStd`
- 生成 `.qet_freecad/3d_to_2d.json`
实现建议:
- 新增 `ExchangeWriteBack.py`
- 从文档中扫描:
- 设备组
- 端子对象
- 手动连线对象
- 第一版正式回写结构遵守现有协议最小集:
```json
{
"schema_version": "1.0",
"project_uuid": "string",
"generated_at": "2026-05-20T10:00:00+08:00",
"instances": [
{
"element_uuid": "string",
"instance_id": "string"
}
],
"terminals": [
{
"terminal_uuid": "string",
"instance_id": "string"
}
]
}
```
连线路径第一版保存在 `.FCStd`。如需 QET 读取线对象,建议后续扩展协议字段,不直接写入现有两张绑定表。
验收:
- 保存后存在 `3d_to_2d.json`
- JSON 中每个设备有 `element_uuid / instance_id`
- JSON 中每个端子有 `terminal_uuid / instance_id`
- 不写入 `project_3d_scene_instance`、`project_3d_space_object`、`project_2d3d_link`。
## 8. 是否能达到图二效果
可以达到同方向效果,但需要分层理解。
图二效果包含:
- 本地模型导入
- 柜体和导轨等场景模型
- 设备装配
- FreeCAD 视图展示
- 模型树层级
本文档当前只保证:
- 本地模板能进入 FreeCAD
- 端子能显示
- 端子能手动连线
- FreeCAD 能保存并回写最小绑定
如果本地模板里包含机柜、导轨和设备,并且导入逻辑按组组织,就可以逐步做出图二那类 FreeCAD 场景。复杂 UI、自动排布、自动布线不属于当前个人任务第一阶段。
## 9. 首批模板建议
第一批不要铺太多设备。建议只选:
1. 机柜或安装板:提供场景参考。
2. DIN 导轨:提供设备摆放参考。
3. 一个断路器或继电器:验证设备端子。
4. 一个端子排:验证多端子排列和连线。
每个模板至少准备:
- 原始几何文件:`.STEP` / `.STP` / `.STE`
- 正式模板文件:`.FCStd`
- 模板内 LCS 端子:`Role="Terminal"`,带槽位名和接线资格
- 可选 sidecar只作为过渡或校验不作为正式交付优先方案
- 模板说明:原点、朝向、尺寸单位、端子数量
常用设备建议优先补齐 `FCStd LCS`,把端子位置从临时的 `bbox fallback` 提升为真实可用坐标。
## 10. 单人开发优先级
建议按下面顺序推进:
1. 不改 UI先把 Python 功能函数跑通。
2. 不碰自动布线,先把端子对象和手动线对象持久化。
3. 不扩旧数据库表,只生成 `3d_to_2d.json`
4. 不追求所有设备,先做一个样板设备跑通闭环。
5. 不让 STEP 顶点直接参与布线,只认带属性的端子 LCS。
## 11. 最小验收场景
准备一个测试项目:
- 2 个设备
- 每个设备至少 2 个端子
- 每个设备绑定一个本地 STEP 或 FCStd 模型
验收步骤:
1. 在 QET 点击打开 FreeCAD。
2. QET 生成 `2d_to_3d.json`
3. FreeCAD 导入设备模型。
4. FreeCAD 为端子创建 LCS。
5. 用户选择两个端子创建手动连线。
6. 保存 FreeCAD 文档。
7. 生成 `3d_to_2d.json`
8. 关闭 FreeCAD 再打开,设备、端子、连线仍存在。
达到以上结果,就说明“端子显示 + 端子连线 + 保存回写”第一版闭环成立。
## 12. 开发结果记录要求
每次开发完成后,都要在本文档末尾追加一条开发记录,至少包含:
- 时间
- 本次实现了什么
- 验证结果
- 未完成或待跟进事项
建议格式:
```text
- 2026-05-20完成端子对象创建与显示逻辑支持 FCStd LCS / sidecar JSON / bbox fallback已验证 FreeCAD 可导入并生成端子对象。待补常用设备真实端子坐标。
- 2026-05-20补上 sidecar `rotation` 解析与端子 Placement 应用,端子模板现在可以同时带位置和方向;已用单元测试验证解析和放置逻辑。
- 2026-05-20补上 FCStd 模板 LCS 朝向保留,模板端子现在可以从源对象直接继承 Placement 方向;已用单元测试验证。
- 2026-05-20补上手动连线对象归属到设备 `QETWires_*` 组,连线树结构现在和设备模板一致;已用单元测试验证。
- 2026-05-20明确 A 方案STEP/STP/STE 只作为原始几何输入,正式可复用设备资源统一保存为带 LCS 电气端子的 FCStd 模板;后续设计 `TemplateAuthoring.py` 做模板制作工具。
- 2026-05-20新增 FCStd 设备模板制作基础能力,支持把模型上的点位创建为带 `Role="Terminal"`、`CanWire=true`、`QetTemplateSlotName` 的模板端子 LCS已用单元测试验证端子语义写入和模板校验逻辑。
- 2026-05-20补充 A 方案资产流转设计,明确 `.FCStd` 为正式设备资产zwl/QET 只负责选择、保存、导出 `.FCStd` 路径FreeCADExchange 负责读取 LCS 端子语义并生成工程端子。
- 2026-05-20补上 `QET_Template_SaveAsFCStd` 模板保存命令,保存前会校验至少存在一个有效模板端子,并自动补 `.FCStd` 后缀;已用单元测试验证保存路径和端子校验结果。
- 2026-05-20修复 `TemplateAuthoring.py` 在 `FreeCADCmd.exe` 命令行模式下导入时误注册 GUI 命令的问题;已在运行目录验证创建 `P1` 模板端子、保存 `.FCStd`、重新打开后端子语义仍可识别。
- 2026-05-20确定方案 2 开发目标:新增“设备模板端子制作”任务面板,让 CAD 工作人员通过输入端子名、选择模型位置、点击按钮完成添加端子、校验端子和保存 FCStd不再依赖 Python 控制台。
- 2026-05-20新增 `TemplateAuthoringPanel.py`,提供“设备模板端子制作”任务面板和 `QET_Template_OpenAuthoringPanel` 命令;面板支持输入端子名、添加端子、校验端子、保存 FCStd并已同步到运行目录验证模块可导入。
- 2026-05-25新增 `WiringImport.py`,把 `2d_to_3d.json` 中的 `wires` 导入为 `QETWiring_01_Tasks` 下的导线任务;`ExchangeBootstrap.py` 已接入启动导入流程。`ManualWiringPanel.py` 增加任务列表、选择导线任务和删除最后折点,按任务生成导线时会把 `wire_id / net_uuid / group_uuid / wire_mark` 写入正式导线对象,并把任务状态更新为 `Routed`。已通过 35 项 `freecad_exchange*_test.py` 单元测试,并安装到 `D:\fc\run-FreeCAD-1.1.1` 运行目录验证 `WiringImport / ManualWiring / ManualWiringPanel / WiringObjects` 可导入。
- 2026-05-25修复 FCStd 设备导入后模板 LCS 留在工程场景的问题;导入时会把模板槽位位置和朝向缓存到设备组 `QetTemplateSlotsJson`,随后删除模板 LCS 及其 `OriginFeatures`,工程端子仍按 `terminal_uuid` 生成到 `QETTerminals_*`。已补单元测试验证 FCStd 导入不保留模板 LCS、切回 STEP 会清空旧槽位缓存,并避免重复访问已删除对象的 `Group / InList / Name`。
```