docs: data-management column lookup via options_json
This commit is contained in:
@@ -9,6 +9,11 @@
|
||||
- 小节正文写用户能看懂的变化(新能力、修复、注意事项),避免堆砌内部实现细节
|
||||
- 打 tag 前**必须**为即将发布的版本新增一节;找不到匹配小节时,本次发布不会更新 changelog 字段
|
||||
|
||||
## 1.0.63
|
||||
|
||||
- 数据管理支持字段级 lookup:`options_json` 可声明同库关联表(`ref_table` / `value_column` / `label_column`),宿主新建/编辑时渲染下拉
|
||||
- 更新 SCHEMA.md 与元数据校验,兼容静态枚举数组与 lookup 对象两种形态
|
||||
|
||||
## 1.0.62
|
||||
|
||||
- Skill Action 新增 `interaction` / `interactionByPlacement`:声明数据管理点击是直通、轻确认还是参数表单(与 `executionProfile` 正交)
|
||||
|
||||
2
SKILL.md
2
SKILL.md
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: 技能开发模板(通用业务版)
|
||||
description: "OpenClaw 通用业务技能开发模板,供复制后定制新业务 skill。定制步骤见 development/DEVELOPMENT.md。"
|
||||
version: 1.0.62
|
||||
version: 1.0.63
|
||||
author: 深圳匠厂科技有限公司
|
||||
metadata:
|
||||
openclaw:
|
||||
|
||||
@@ -354,7 +354,11 @@ CREATE TABLE demo_items (
|
||||
|
||||
## 枚举字段 options_json
|
||||
|
||||
`options_json` 为 JSON 数组,每项包含 `value` 与 `label`:
|
||||
`options_json` 支持两种形态:
|
||||
|
||||
### 1)静态枚举(数组)
|
||||
|
||||
每项包含 `value` 与 `label`:
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -366,6 +370,31 @@ CREATE TABLE demo_items (
|
||||
|
||||
宿主据此渲染选择框;技能侧负责保证 JSON 合法且与物理字段取值一致。
|
||||
|
||||
### 2)表关联 lookup(对象,推荐用于外键式字段)
|
||||
|
||||
当字段取值依赖同库另一张业务表时,`display_type` 设为 `lookup`,`options_json` 写对象(**不是**数组):
|
||||
|
||||
```json
|
||||
{
|
||||
"ref_table": "platforms",
|
||||
"value_column": "platform_key",
|
||||
"label_column": "display_name",
|
||||
"filter_column": "enabled",
|
||||
"filter_value": 1
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|---|---|---|
|
||||
| `ref_table` | 是 | 同库被引用表名(snake_case 标识符) |
|
||||
| `value_column` | 是 | 写入当前字段的值列 |
|
||||
| `label_column` | 是 | 下拉展示名列 |
|
||||
| `filter_column` / `filter_value` | 否 | 等值过滤(如只列出 `enabled=1`) |
|
||||
|
||||
宿主在加载表 schema 时查询 `ref_table`,把结果展开成 `{value,label}` 下拉选项;**物理列仍存标量**(如 `platform_key` 文本、`account_id` 整数),不做嵌套子表。
|
||||
|
||||
示例:账号表的平台字段 → 平台信息表;凭据表的账号编号 → 账号信息表。
|
||||
|
||||
## 幂等初始化标准
|
||||
|
||||
- `_jiangchang_tables` 和 `_jiangchang_columns` 必须通过 upsert 初始化
|
||||
|
||||
@@ -196,7 +196,7 @@ def _default_uses_unixepoch(default_value: object) -> bool:
|
||||
|
||||
|
||||
def validate_options_json(options_json: str | None) -> tuple[list[str], list[str]]:
|
||||
"""校验枚举 options_json 可被解析为 [{value, label}, ...] 结构。"""
|
||||
"""校验 options_json:静态枚举数组,或 lookup 对象。"""
|
||||
errors: list[str] = []
|
||||
warnings: list[str] = []
|
||||
if options_json is None or str(options_json).strip() == "":
|
||||
@@ -206,8 +206,24 @@ def validate_options_json(options_json: str | None) -> tuple[list[str], list[str
|
||||
except json.JSONDecodeError as exc:
|
||||
errors.append(f"options_json 不是合法 JSON:{exc}")
|
||||
return errors, warnings
|
||||
|
||||
if isinstance(parsed, dict):
|
||||
for key in ("ref_table", "value_column", "label_column"):
|
||||
if not str(parsed.get(key) or "").strip():
|
||||
errors.append(f"options_json lookup 必须包含非空 {key}")
|
||||
ident = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
|
||||
for key in ("ref_table", "value_column", "label_column", "filter_column"):
|
||||
raw = parsed.get(key)
|
||||
if raw is None or raw == "":
|
||||
continue
|
||||
if not ident.match(str(raw)):
|
||||
errors.append(f"options_json.{key} 必须是安全标识符,当前为 {raw!r}")
|
||||
if parsed.get("filter_column") not in (None, "") and "filter_value" not in parsed:
|
||||
warnings.append("options_json lookup 声明了 filter_column 但未提供 filter_value")
|
||||
return errors, warnings
|
||||
|
||||
if not isinstance(parsed, list):
|
||||
errors.append("options_json 必须是 JSON 数组")
|
||||
errors.append("options_json 必须是 JSON 数组(静态枚举)或对象(lookup)")
|
||||
return errors, warnings
|
||||
for index, item in enumerate(parsed):
|
||||
if not isinstance(item, dict):
|
||||
|
||||
Reference in New Issue
Block a user