"""大屏公共结构;组件属性、事件与数据源配置保持开放""" from typing import Annotated, Self from pydantic import Field, model_validator from .base import ExtensibleModel, JsonObject, NonBlankString Number = int | float PositiveNumber = Annotated[Number, Field(gt=0)] class Canvas(ExtensibleModel): width: PositiveNumber height: PositiveNumber class Layout(ExtensibleModel): x: Number y: Number width: PositiveNumber height: PositiveNumber class ScreenNode(ExtensibleModel): id: NonBlankString type: NonBlankString layout: Layout name: str | None = None props: JsonObject = Field(default_factory=dict) style: JsonObject | None = None events: list[JsonObject] | None = None class Screen(ExtensibleModel): canvas: Canvas nodes: list[ScreenNode] # 保持前端字段名;数据源的具体类型与绑定校验后续再引入 dataSource: list[JsonObject] = Field(default_factory=list) @model_validator(mode="after") def unique_node_ids(self) -> Self: seen: set[str] = set() for node in self.nodes: if node.id in seen: raise ValueError(f"重复的节点 ID: {node.id}") seen.add(node.id) return self