51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
"""大屏公共结构;组件属性、事件与数据源配置保持开放"""
|
|
|
|
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):
|
|
"""组件在画布上的绝对坐标和尺寸,单位 px"""
|
|
|
|
x: Number = Field(description="左上角横坐标")
|
|
y: Number = Field(description="左上角纵坐标")
|
|
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
|