feat:新增物料
This commit is contained in:
@@ -16,7 +16,7 @@ class AddAction(ActionModel):
|
||||
description="新组件。id、type、layout 必填,其余只写需要覆盖物料默认配置的字段;"
|
||||
"后端按 type 找到物料,用默认配置补全:对象逐层覆盖,数组整体替换,null 明确覆盖。"
|
||||
"id 不能与当前大屏上的组件重复(包括之前提交里新增的),先 delete 的 ID 可以再用;type 用 list_components 返回的 type。"
|
||||
'任何字段值都可以写成 {"$query": "SELECT ..."},后端替换成上传数据的查询结果(对象数组,键是结果的列名)'
|
||||
'任何字段值都可以写成 {"$query": "SELECT ..."},后端替换成上传数据的查询结果:写入单个值的字段时结果要一行一列,取那个值;写入数字、文字数组的字段时结果要只有一列;其余是对象数组,键是结果的列名'
|
||||
)
|
||||
sample_data: bool = Field(
|
||||
default=False,
|
||||
|
||||
@@ -23,7 +23,7 @@ class UpdateAction(BaseAction):
|
||||
)
|
||||
value: JsonValue = Field(
|
||||
description="替换该字段的值,必须符合字段定义的类型和取值;"
|
||||
'可以写成 {"$query": "SELECT ..."},后端替换成上传数据的查询结果(对象数组,键是结果的列名)'
|
||||
'可以写成 {"$query": "SELECT ..."},后端替换成上传数据的查询结果:写入单个值的字段时结果要一行一列,取那个值;写入数字、文字数组的字段时结果要只有一列;其余是对象数组,键是结果的列名'
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
|
||||
@@ -15,5 +15,6 @@ 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、theme(light 亮色 / dark 深色)、backgroundColor;未提供的字段保持不变。"
|
||||
"改 theme 会让组件里跟随主题的颜色一起变;backgroundColor 写 null 表示用主题的背景色。改变画布尺寸不会自动缩放或移动组件",
|
||||
)
|
||||
|
||||
@@ -74,11 +74,14 @@ class ComponentDefinition(ExtensibleModel):
|
||||
|
||||
|
||||
def _default_problem(field, template: JsonObject) -> str | None:
|
||||
"""默认值只有一个来源:默认配置有该路径时取它,没有时字段必须声明 default"""
|
||||
"""默认值只有一个来源:默认配置有该路径时取它,没有时字段必须声明 default;
|
||||
跟随主题的颜色由前端按画布主题取,默认配置里不能写死"""
|
||||
try:
|
||||
current = lookup(template, field.segments)
|
||||
except ValueError:
|
||||
return "的路径与默认配置结构冲突"
|
||||
if field.themed:
|
||||
return None if current is MISSING else "跟随主题,默认配置里不能写死颜色"
|
||||
if current is MISSING:
|
||||
if field.default is None:
|
||||
return "在默认配置中不存在,需要声明 default"
|
||||
|
||||
@@ -20,10 +20,11 @@ ValueType = Literal[
|
||||
ItemType = Literal["string", "number", "integer", "boolean", "color", "object"]
|
||||
|
||||
# 值类型对应的前端属性控件;array / object 没有通用控件,只能不在面板显示
|
||||
# number 可以输入小数,integer 只能输入整数
|
||||
PANEL_CONTROLS: dict[str, str] = {
|
||||
"string": "input",
|
||||
"number": "number",
|
||||
"integer": "number",
|
||||
"integer": "integer",
|
||||
"boolean": "checkbox",
|
||||
"color": "color",
|
||||
"enum": "select",
|
||||
@@ -101,6 +102,10 @@ class MaterialField(ExtensibleModel):
|
||||
aliases: list[NonBlankString] = Field(
|
||||
default_factory=list, description="用户可能的叫法,供字段搜索使用"
|
||||
)
|
||||
themed: bool = Field(
|
||||
default=False,
|
||||
description="颜色跟随画布主题:默认配置里不写值,由前端按画布主题(亮 / 暗)取色;写入 null 恢复跟随",
|
||||
)
|
||||
editable: bool = Field(default=True, description="是否允许修改")
|
||||
panel: bool = Field(default=True, description="是否显示在前端属性面板")
|
||||
span: int | None = Field(default=None, description="属性面板栅格宽度,24 为整行")
|
||||
@@ -115,10 +120,15 @@ class MaterialField(ExtensibleModel):
|
||||
raise ValueError(f"只有 array 字段提供 item_type,且 array 必须提供: {self.path}")
|
||||
if self.panel and self.value_type not in PANEL_CONTROLS:
|
||||
raise ValueError(f"{self.value_type} 字段没有属性面板控件,panel 必须为 false: {self.path}")
|
||||
if self.themed and (self.value_type != "color" or self.default is not None):
|
||||
raise ValueError(f"只有 color 字段可以跟随主题,且不能声明 default: {self.path}")
|
||||
return self
|
||||
|
||||
def value_error(self, value: JsonValue) -> str | None:
|
||||
"""检查值是否符合字段类型和取值约束,符合返回 None"""
|
||||
# 跟随主题的颜色写 null 表示去掉单独设置的颜色、恢复跟随
|
||||
if self.themed and value is None:
|
||||
return None
|
||||
if self.value_type == "enum":
|
||||
allowed = [option.value for option in self.options]
|
||||
return None if value in allowed else f"取值必须是 {allowed} 之一"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""大屏公共结构;组件属性、事件与数据源配置保持开放"""
|
||||
|
||||
from typing import Annotated, Self
|
||||
from typing import Annotated, Literal, Self
|
||||
|
||||
from pydantic import Field, model_validator
|
||||
|
||||
@@ -13,6 +13,13 @@ PositiveNumber = Annotated[Number, Field(gt=0)]
|
||||
class Canvas(ExtensibleModel):
|
||||
width: PositiveNumber
|
||||
height: PositiveNumber
|
||||
theme: Literal["light", "dark"] | None = Field(
|
||||
default=None,
|
||||
description="画布主题:组件里没单独设置的文字、坐标轴、分隔线、卡片底等颜色按主题取;旧大屏没有时前端按背景色推断",
|
||||
)
|
||||
backgroundColor: str | None = Field(
|
||||
default=None, description="画布背景色;为 null 时用主题的背景色"
|
||||
)
|
||||
|
||||
|
||||
class Layout(ExtensibleModel):
|
||||
|
||||
Reference in New Issue
Block a user