Merge remote-tracking branch 'origin/dev' into dev

dev
Zhaowenlong 4 weeks ago
commit affafbf5f6

1
.gitignore vendored

@ -51,6 +51,7 @@ install_manifest.txt
/bulid/ /bulid/
/build-*/ /build-*/
/cmake-build*/ /cmake-build*/
/run/
/src/Tools/offlinedoc/localwiki/ /src/Tools/offlinedoc/localwiki/
/src/Tools/offlinedoc/*.txt /src/Tools/offlinedoc/*.txt
/conda/environment.yml /conda/environment.yml

@ -110,7 +110,6 @@
}, },
"cabinet": {}, "cabinet": {},
"devices": [], "devices": [],
"terminals": [],
"device_models": [], "device_models": [],
"wires": [] "wires": []
} }
@ -123,8 +122,7 @@
- `generated_at`:导出时间 - `generated_at`:导出时间
- `source`:导出来源信息 - `source`:导出来源信息
- `cabinet`:当前图纸属性中绑定的机柜信息 - `cabinet`:当前图纸属性中绑定的机柜信息
- `devices`:设备实例绑定 - `devices`:设备实例绑定,以及每个设备名下的接线处
- `terminals`:端子实例绑定
- `device_models`:设备 3D 模型解析结果 - `device_models`:设备 3D 模型解析结果
- `wires`:导线起点/终点与标注快照 - `wires`:导线起点/终点与标注快照
@ -193,7 +191,8 @@
{ {
"element_uuid": "string", "element_uuid": "string",
"instance_id": "string", "instance_id": "string",
"display_tag": "string" "display_tag": "string",
"terminals": []
} }
``` ```
@ -204,20 +203,22 @@
| `element_uuid` | 2D设备实例UUID | 是 | QET 图纸中的设备实例主键 | | `element_uuid` | 2D设备实例UUID | 是 | QET 图纸中的设备实例主键 |
| `instance_id` | 3D实例ID | 是 | FreeCAD 侧设备实例主键 | | `instance_id` | 3D实例ID | 是 | FreeCAD 侧设备实例主键 |
| `display_tag` | 2D设备实例标注 | 否 | JSON 显示辅助字段,优先使用 2D 中设备标注作为 FreeCAD 树标签;为空时再退回 `instance_id` / `element_uuid` | | `display_tag` | 2D设备实例标注 | 否 | JSON 显示辅助字段,优先使用 2D 中设备标注作为 FreeCAD 树标签;为空时再退回 `instance_id` / `element_uuid` |
| `terminals` | 设备接线处列表 | 否 | 当前设备名下的 2D 接线处集合FreeCAD 会先按设备再导入接线处 |
### 6.4 说明 ### 6.4 说明
- 如果第一次进入 3D 时还没有 `instance_id`,允许先导出空字符串或缺省值 - 如果第一次进入 3D 时还没有 `instance_id`,允许先导出空字符串或缺省值
- FreeCAD 创建 3D 实例后,再在回写阶段补齐 - FreeCAD 创建 3D 实例后,再在回写阶段补齐
- `display_tag` 不进入第一版数据库最小字段集,它只存在于交换 JSON 中,用来让 3D 树视图与 2D 标注更容易对上 - `display_tag` 不进入第一版数据库最小字段集,它只存在于交换 JSON 中,用来让 3D 树视图与 2D 标注更容易对上
- `terminals` 是设备级子结构,不再单独放在顶层
--- ---
## 7. `terminals` 结构 ## 7. `devices[].terminals` 结构
### 7.1 作用 ### 7.1 作用
`terminals` 负责表达: `devices[].terminals` 负责表达:
> 一个 2D 端子实例,属于哪个 3D 设备实例。 > 一个 2D 端子实例,属于哪个 3D 设备实例。
@ -227,7 +228,8 @@
{ {
"terminal_uuid": "string", "terminal_uuid": "string",
"instance_id": "string", "instance_id": "string",
"element_uuid": "string" "element_uuid": "string",
"terminal_display": "string"
} }
``` ```
@ -238,6 +240,7 @@
| `terminal_uuid` | 2D端子UUID | 是 | QET 端子实例主键 | | `terminal_uuid` | 2D端子UUID | 是 | QET 端子实例主键 |
| `instance_id` | 3D实例ID | 是 | 该端子所属的 3D 设备实例 | | `instance_id` | 3D实例ID | 是 | 该端子所属的 3D 设备实例 |
| `element_uuid` | 2D设备实例UUID | 否 | JSON 导入辅助字段,帮助 FreeCAD 在首次没有 `instance_id` 时仍能知道端子属于哪个设备 | | `element_uuid` | 2D设备实例UUID | 否 | JSON 导入辅助字段,帮助 FreeCAD 在首次没有 `instance_id` 时仍能知道端子属于哪个设备 |
| `terminal_display` | 接线处标注 | 否 | 2D 端子在图纸上的显示标注,供 FreeCAD 端子对象显示和槽位匹配使用 |
### 7.4 为什么这里允许带 `element_uuid` ### 7.4 为什么这里允许带 `element_uuid`

@ -337,46 +337,58 @@ def _normalize_devices(payload):
index index
) )
) )
normalized.append( device_terminals = item.get("terminals", [])
{ if device_terminals is None:
"element_uuid": element_uuid, device_terminals = []
"instance_id": _normalize_instance_id(item), if not isinstance(device_terminals, list):
"display_tag": display_tag.strip() if isinstance(display_tag, str) else "", raise ExchangeValidationError(
} "Field 'terminals' in device entry #{0} must be a list.".format(index)
) )
return normalized
def _normalize_terminals(payload): normalized_terminals = []
terminals = payload.get("terminals", []) for terminal_index, terminal_item in enumerate(device_terminals):
if not isinstance(terminals, list): terminal_entry_label = "device entry #{0} terminal entry #{1}".format(
raise ExchangeValidationError("Field 'terminals' must be a list.") index, terminal_index
normalized = []
for index, item in enumerate(terminals):
if not isinstance(item, dict):
raise ExchangeValidationError(
"Terminal entry #{0} must be an object.".format(index)
) )
terminal_uuid = _require_string(item, "terminal_uuid") if not isinstance(terminal_item, dict):
element_uuid = item.get("element_uuid", "")
if element_uuid and not isinstance(element_uuid, str):
raise ExchangeValidationError( raise ExchangeValidationError(
"Field 'element_uuid' in terminal entry #{0} must be a string.".format( "{0} must be an object.".format(terminal_entry_label.capitalize())
index
) )
terminal_uuid = _require_string(terminal_item, "terminal_uuid")
terminal_element_uuid = _optional_string(
terminal_item, "element_uuid", terminal_entry_label
) or element_uuid
normalized_terminals.append(
{
"terminal_uuid": terminal_uuid,
"instance_id": _normalize_instance_id(terminal_item)
or _normalize_instance_id(item),
"element_uuid": terminal_element_uuid,
"terminal_display": _optional_string(
terminal_item, "terminal_display", terminal_entry_label
),
}
) )
normalized.append( normalized.append(
{ {
"terminal_uuid": terminal_uuid, "element_uuid": element_uuid,
"instance_id": _normalize_instance_id(item), "instance_id": _normalize_instance_id(item),
"element_uuid": element_uuid.strip() if isinstance(element_uuid, str) else "", "display_tag": display_tag.strip() if isinstance(display_tag, str) else "",
"terminal_display": _optional_string(item, "terminal_display", "terminal entry #{0}".format(index)), "terminals": normalized_terminals,
} }
) )
return normalized return normalized
def _normalize_terminals(devices):
normalized = []
for device in devices:
for terminal in device.get("terminals", []) or []:
normalized.append(dict(terminal))
return normalized
def _optional_string(item, field_name, entry_label): def _optional_string(item, field_name, entry_label):
value = item.get(field_name, "") value = item.get(field_name, "")
if value is None: if value is None:
@ -562,14 +574,16 @@ def load_exchange_payload(json_path):
if not isinstance(schema_version, str) or not schema_version.strip(): if not isinstance(schema_version, str) or not schema_version.strip():
raise ExchangeValidationError("Field 'schema_version' must be a string.") raise ExchangeValidationError("Field 'schema_version' must be a string.")
normalized_devices = _normalize_devices(payload)
normalized = { normalized = {
"schema_version": schema_version.strip(), "schema_version": schema_version.strip(),
"project_uuid": project_uuid, "project_uuid": project_uuid,
"generated_at": payload.get("generated_at", ""), "generated_at": payload.get("generated_at", ""),
"source": payload.get("source", {}), "source": payload.get("source", {}),
"cabinet": _normalize_cabinet(payload), "cabinet": _normalize_cabinet(payload),
"devices": _normalize_devices(payload), "devices": normalized_devices,
"terminals": _normalize_terminals(payload), "terminals": _normalize_terminals(normalized_devices),
"device_models": _normalize_device_models(payload), "device_models": _normalize_device_models(payload),
"wires": _normalize_wires(payload), "wires": _normalize_wires(payload),
} }

Loading…
Cancel
Save