feat:架构重构
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"""动作类型统一入口,新增操作时在这里显式加入联合类型"""
|
||||
|
||||
from typing import Annotated, Self
|
||||
from typing import Annotated
|
||||
|
||||
from pydantic import Field, TypeAdapter, model_validator
|
||||
from pydantic import Field
|
||||
|
||||
from .add import AddAction
|
||||
from .base import ActionModel, BaseAction
|
||||
@@ -14,29 +14,18 @@ from .update_canvas import UpdateCanvasAction
|
||||
|
||||
# 按 type 选择对应模型,不维护重复的操作名称映射
|
||||
Action = Annotated[
|
||||
AddAction | DeleteAction | MoveAction | ResizeAction | UpdateAction | UpdateCanvasAction,
|
||||
AddAction
|
||||
| DeleteAction
|
||||
| MoveAction
|
||||
| ResizeAction
|
||||
| UpdateAction
|
||||
| UpdateCanvasAction,
|
||||
Field(discriminator="type"),
|
||||
]
|
||||
action_adapter = TypeAdapter(Action)
|
||||
|
||||
|
||||
class ActionBatch(ActionModel):
|
||||
actions: list[Action] = Field(description="按数组顺序执行的动作列表,允许为空")
|
||||
unsupported_reason: str | None = Field(
|
||||
default=None,
|
||||
description="需求中有任何部分无法用现有动作或查到的字段完成时,说明缺少什么能力,此时 actions 为空;能完成时为 null",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def unsupported_has_no_actions(self) -> Self:
|
||||
if self.unsupported_reason and self.actions:
|
||||
raise ValueError("填写 unsupported_reason 时 actions 必须为空,不能只执行需求的一部分")
|
||||
return self
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Action",
|
||||
"ActionBatch",
|
||||
"ActionModel",
|
||||
"AddAction",
|
||||
"BaseAction",
|
||||
"DeleteAction",
|
||||
@@ -44,5 +33,4 @@ __all__ = [
|
||||
"ResizeAction",
|
||||
"UpdateAction",
|
||||
"UpdateCanvasAction",
|
||||
"action_adapter",
|
||||
]
|
||||
|
||||
@@ -10,16 +10,18 @@ from app.schemas.screen import ScreenNode
|
||||
|
||||
|
||||
class AddAction(ActionModel):
|
||||
"""按物料新增组件"""
|
||||
|
||||
type: Literal["add"] = "add"
|
||||
component_key: NonBlankString = Field(
|
||||
description="物料目录编号,即 list_components 返回的 key"
|
||||
)
|
||||
node: ScreenNode = Field(
|
||||
description="待新增的完整组件,包含新 ID、类型、布局和配置"
|
||||
)
|
||||
plan_id: NonBlankString | None = Field(
|
||||
default=None, description="对应的规划组件编号,独立模拟时可省略"
|
||||
)
|
||||
component_key: NonBlankString | None = Field(
|
||||
default=None, description="使用的物料目录编号,规划生成时必填"
|
||||
description="新组件。id、type、layout 必填,其余只写需要覆盖物料默认配置的字段;"
|
||||
"后端按物料默认配置补全:对象逐层覆盖,数组整体替换,null 明确覆盖。"
|
||||
"id 不能与现有组件重复,同一批里先 delete 的 ID 可以再用;type 必须与物料一致"
|
||||
)
|
||||
sample_data: bool = Field(
|
||||
default=False, description="物料含示例数据,不代表已获取真实业务数据"
|
||||
default=False,
|
||||
description="由后端按物料设置,不用填写;true 表示组件使用物料示例数据,不是真实业务数据",
|
||||
)
|
||||
|
||||
@@ -6,4 +6,6 @@ from .base import BaseAction
|
||||
|
||||
|
||||
class DeleteAction(BaseAction):
|
||||
"""删除已有组件"""
|
||||
|
||||
type: Literal["delete"] = "delete"
|
||||
|
||||
@@ -10,6 +10,8 @@ from .base import BaseAction
|
||||
|
||||
|
||||
class MoveAction(BaseAction):
|
||||
"""按相对位移移动组件。目标是绝对位置时,用目标坐标减去当前坐标,例如当前 x=100、目标 x=150 时 delta_x=50"""
|
||||
|
||||
type: Literal["move"] = "move"
|
||||
delta_x: Number = Field(
|
||||
default=0, description="水平位移,单位 px,正数向右,负数向左"
|
||||
|
||||
@@ -10,6 +10,8 @@ from .base import BaseAction
|
||||
|
||||
|
||||
class ResizeAction(BaseAction):
|
||||
"""设置组件的绝对宽高,不改变位置"""
|
||||
|
||||
type: Literal["resize"] = "resize"
|
||||
width: PositiveNumber | None = Field(
|
||||
default=None, description="目标宽度,单位 px,省略或 null 表示保持原值"
|
||||
|
||||
@@ -12,12 +12,14 @@ 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 没有后续路径,传空列表"
|
||||
description='字段路径第一段之后的各段,字符串为对象键,整数为数组下标;name 没有后续路径,传空列表。例如字段 props.option.title.text 写成 section=props、path=["option", "title", "text"]'
|
||||
)
|
||||
value: JsonValue = Field(description="替换该字段的值,必须符合字段定义的类型和取值")
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ from .base import ActionModel
|
||||
|
||||
|
||||
class UpdateCanvasAction(ActionModel):
|
||||
"""修改画布属性"""
|
||||
|
||||
type: Literal["update_canvas"] = "update_canvas"
|
||||
properties: dict[NonBlankString, JsonValue] = Field(
|
||||
min_length=1,
|
||||
description="要替换的 canvas 顶层字段,如 width、height、backgroundColor;未提供的字段保持不变",
|
||||
description="要替换的 canvas 顶层字段及最终值,如 width、height、backgroundColor;未提供的字段保持不变。改变画布尺寸不会自动缩放或移动组件",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user