36 lines
1.5 KiB
Python
36 lines
1.5 KiB
Python
"""精确更新组件名称,或 props / style 下的一个字段"""
|
|
|
|
from typing import Annotated, Literal, Self
|
|
|
|
from pydantic import Field, JsonValue, model_validator
|
|
|
|
from app.schemas.base import NonBlankString
|
|
|
|
from .base import BaseAction
|
|
|
|
PathSegment = NonBlankString | Annotated[int, Field(ge=0)]
|
|
|
|
|
|
class UpdateAction(BaseAction):
|
|
"""替换组件的一个字段,不做深度合并;组件中还没有的中间对象由后端补齐。位置和尺寸用 move / resize,不用 update"""
|
|
|
|
type: Literal["update"] = "update"
|
|
section: Literal["name", "props", "style"] = Field(
|
|
description="字段路径的第一段:name 为组件名称,props / style 为组件属性区域"
|
|
)
|
|
path: list[PathSegment] = Field(
|
|
description='字段路径第一段之后的各段,字符串为对象键,整数为数组下标;name 没有后续路径,传空列表。例如字段 props.option.title.text 写成 section=props、path=["option", "title", "text"]'
|
|
)
|
|
value: JsonValue = Field(description="替换该字段的值,必须符合字段定义的类型和取值")
|
|
|
|
@model_validator(mode="after")
|
|
def path_matches_section(self) -> Self:
|
|
if (self.section == "name") != (not self.path):
|
|
raise ValueError("section 为 name 时 path 为空,props / style 至少一段路径")
|
|
return self
|
|
|
|
@property
|
|
def field_path(self) -> str:
|
|
"""与物料字段定义一致的点路径,例如 props.option.title.text"""
|
|
return ".".join([self.section, *map(str, self.path)])
|