Skip to content

Pageable 协议设计规范

设计背景与目标

在TFRobotServer中,所有的RobotComponent均是通过配置生成,数据结构多变,分页列表的字段、操作、联动方式都可能变化。平台内核通过Action机制,结合JsonSchema、Jmespath、x-namespace/x-actions/x-ref,实现了列表(pageable)场景的协议规范。

基本约定

  • 所有列表相关Action需通过@tfs_action注册,category为"pageable"。
  • 每个Action需定义清晰的入参Schema和返回Schema,均基于Pydantic/JsonSchema表达。
  • 支持通过x-namespace/x-actions/x-ref机制实现接口间联动。

典型接口结构

1. 主列表查询Action(get_list)

  • get_list 的返回结构必须为“列表容器”,最小要求是包含 items 字段。
  • 分页信息根据分页模式不同可选:
  • Page 模式:items + page + pageSize
  • Cursor 模式:items + cursor + pageSize
  • 返回Schema可在 items 的每个元素结构中声明 x-namespace,为所有Action提供变量。x-namespace 直接以变量名为 key,value 为 Jmespath 路径或 Options 结构(labels/keys/values 三个 Jmespath 字段,见下方示例)。
  • 可在每个元素结构中声明 x-actions,表明当前行可用的操作。
  • x-namespace 的 key 为变量名,value 为 Jmespath 路径或 Options 结构。
{
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {"type": "string"},
          "name": {"type": "string"}
        },
        "required": ["id", "name"],
        "x-namespace": {
          "row_id": "id",
          "user_options": {
            "Options": {
              "labels": "values[*].display_name",
              "keys": "values[*].user_id",
              "values": "users"
            }
          }
        },
        "x-actions": ["update_row", "delete_row", "select_user"]
      }
    },
    "page": {"type": "integer"},
    "pageSize": {"type": "integer"}
  },
  "required": ["items", "page", "pageSize"]
}

Cursor 模式示例(返回结构):

{
  "type": "object",
  "properties": {
    "items": {"type": "array", "items": {"type": "object"}},
    "cursor": {"type": "string"},
    "pageSize": {"type": "integer"}
  },
  "required": ["items", "cursor", "pageSize"]
}

2. 行操作Action(如update/delete/select_user)

  • 入参Schema字段可通过 x-ref 声明依赖,直接引用 namespace 中的变量名。
  • 可通过 x-default 声明字段默认值,值为 Jmespath 路径(相对于当前 namespace)。
  • 可通过 x-fetch 声明“补全动作”,当 x-ref/x-default 无法从当前 namespace 解析出值时,前端可触发该动作补全 namespace,然后重试解析。
{
  "type": "object",
  "properties": {
    "row_id": {
      "type": "string",
      "x-ref": "row_id"
    },
    "user_id": {
      "type": "string",
      "x-default": "user_options.keys[0]",
      "x-fetch": "aget_user_options"
    },
    "new_value": {"type": "string"}
  },
  "required": ["row_id", "user_id", "new_value"]
}

x-fetch 前端实现要求(列表场景)

  • 触发条件:仅当 x-ref / x-default 均无法从当前 namespace 得到可用值时,才允许触发 x-fetch
  • 缓存/去重:前端必须按 (action_name + resolved_params) 维度对 x-fetch 做缓存/去重,避免重复触发相同补全动作。
  • 循环/风暴控制:同一次参数解析链路中,x-fetch 最大触发次数为 10;超过阈值应中止并提示。

x-namespace/x-actions/x-ref 与 List 的最佳实践

  • 推荐在 items 的每个元素 schema 层级声明 x-namespace 和 x-actions,x-namespace 以变量名为 key,所有 Action 共享同一 namespace,便于统一引用。
  • x-ref 直接引用变量名,前端自动匹配当前上下文。
  • x-default 支持字段默认值从 namespace 动态获取。
  • x-fetch 仅填写动作名称字符串,用于在 x-ref/x-default 解析失败时补全 namespace。
  • Jmespath 用于表达相对路径,如 "id"、"person.name"。

FAQ

  • Q:能否只在根节点声明所有 x-namespace?
  • A:不推荐。建议在 items 层级声明,便于每个数据项独立注入上下文。
  • Q:如何表达 list 中“对应 index”?
  • A:前端遍历时自动注入当前项的 namespace,x-ref 直接写变量名即可。
  • Q:x-namespace 的 Options 结构是如何使用的?
  • A:Options 结构用于注入选项型变量,labels/keys/values 三个 Jmespath 字段分别对应选项的标签、键和值。

示例

  • get_list返回:
{
  "items": [
    {"id": "1", "name": "A"},
    {"id": "2", "name": "B"}
  ],
  "page": 1,
  "pageSize": 10
}
  • update_row参数:
{
  "row_id": "1",
  "new_value": "A1"
}
  • select_user参数:
{
  "user_options": {
    "Options": {
      "labels": ["用户1", "用户2"],
      "keys": ["1", "2"],
      "values": ["用户1", "用户2"]
    }
  }
}

联动与上下文

  • 前端根据x-ref自动推导参数来源,实现Action间数据流转。
  • 后端在Action注册与Schema中声明所有依赖,便于前端理解与渲染。

扩展与约定

  • 支持x-ui、x-table-column等扩展字段,提升前端体验。
  • 支持多级联动、复杂表格等高级场景。