diff --git a/shortcuts/base/workflow_create.go b/shortcuts/base/workflow_create.go index 0bba5bbeb..fbf8a886e 100644 --- a/shortcuts/base/workflow_create.go +++ b/shortcuts/base/workflow_create.go @@ -19,7 +19,7 @@ var BaseWorkflowCreate = common.Shortcut{ AuthTypes: []string{"user", "bot"}, Flags: []common.Flag{ {Name: "base-token", Desc: "base token", Required: true}, - {Name: "json", Desc: `workflow body JSON, e.g. {"title":"My Workflow","steps":[...]}; or @path/to/file.json for large definitions`, Required: true}, + {Name: "json", Desc: `workflow body JSON, e.g. {"title":"My Workflow","steps":[...]}`, Required: true}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if strings.TrimSpace(runtime.Str("base-token")) == "" { diff --git a/shortcuts/base/workflow_update.go b/shortcuts/base/workflow_update.go index 0b316e4fd..f0e6179bd 100644 --- a/shortcuts/base/workflow_update.go +++ b/shortcuts/base/workflow_update.go @@ -20,7 +20,7 @@ var BaseWorkflowUpdate = common.Shortcut{ Flags: []common.Flag{ {Name: "base-token", Desc: "base token", Required: true}, {Name: "workflow-id", Desc: "workflow ID (wkf... prefix)", Required: true}, - {Name: "json", Desc: `workflow body JSON, e.g. {"title":"New Title","steps":[...]}; or @path/to/file.json for large definitions`, Required: true}, + {Name: "json", Desc: `workflow body JSON, e.g. {"title":"New Title","steps":[...]}`, Required: true}, }, Validate: func(ctx context.Context, runtime *common.RuntimeContext) error { if strings.TrimSpace(runtime.Str("base-token")) == "" { diff --git a/skills/lark-base/SKILL.md b/skills/lark-base/SKILL.md index 80d81d3fc..88f276ba2 100644 --- a/skills/lark-base/SKILL.md +++ b/skills/lark-base/SKILL.md @@ -1,7 +1,7 @@ --- name: lark-base version: 1.2.0 -description: "当需要用 lark-cli 操作飞书多维表格(Base)时调用:适用于建表、字段管理、记录读写、视图配置、历史查询,以及角色/表单/仪表盘管理;也适用于把旧的 +table / +field / +record 写法改成当前命令写法。涉及字段设计、公式字段、查找引用、跨表计算、行级派生指标、数据分析需求时也必须使用本 skill。" +description: "当需要用 lark-cli 操作飞书多维表格(Base)时调用:适用于建表、字段管理、记录读写、视图配置、历史查询,以及角色/表单/仪表盘管理/工作流;也适用于把旧的 +table / +field / +record 写法改成当前命令写法。涉及字段设计、公式字段、查找引用、跨表计算、行级派生指标、数据分析需求时也必须使用本 skill。" metadata: requires: bins: ["lark-cli"] @@ -82,19 +82,24 @@ metadata: ## Workflow 专项规则 -1. **执行任何 workflow 命令前,必须先读两份文档:对应的命令文档 + [lark-base-workflow-schema.md](references/lark-base-workflow-schema.md)** - - `+workflow-create` → 先读 [lark-base-workflow-create.md](references/lark-base-workflow-create.md) + schema - - `+workflow-update` → 先读 [lark-base-workflow-update.md](references/lark-base-workflow-update.md) + schema - - `+workflow-list` → 先读 [lark-base-workflow-list.md](references/lark-base-workflow-list.md) + schema - - `+workflow-get` → 先读 [lark-base-workflow-get.md](references/lark-base-workflow-get.md) + schema - - `+workflow-enable` → 先读 [lark-base-workflow-enable.md](references/lark-base-workflow-enable.md) + schema - - `+workflow-disable` → 先读 [lark-base-workflow-disable.md](references/lark-base-workflow-disable.md) + schema - - schema 中定义了所有 StepType 枚举、步骤结构、Trigger/Action/Branch/Loop 的 data 格式、值引用语法等 - - 禁止凭自然语言猜测 `type` 值(如把"新增记录"猜成 `CreateTrigger`),必须从 schema 的 StepType 枚举中复制准确的类型名称 - -2. **创建前确认依赖信息** - - 先通过 `+table-list` / `+field-list` 获取真实的表名、字段名 +1. **执行任何 workflow 命令前,必须先读对应的命令文档** + - **创建**: 先读 [workflow-create.md](references/lark-base-workflow-create.md)(它会引导你读 schema) + - **修改**: 先读 [workflow-update.md](references/lark-base-workflow-update.md) + [workflow-get.md](references/lark-base-workflow-get.md) 获取现有配置 + - **查询/批量操作**: 先读 [workflow-list.md](references/lark-base-workflow-list.md)(注意场景适用性) + - **获取详情**: 先读 [workflow-get.md](references/lark-base-workflow-get.md),用于获取完整 workflow 定义(含 steps 结构) + - **启用**: 先读 [workflow-enable.md](references/lark-base-workflow-enable.md),启用处于 `disabled` 状态的工作流 + - **禁用**: 先读 [workflow-disable.md](references/lark-base-workflow-disable.md),禁用处于 `enabled` 状态的工作流 +2. **禁止凭自然语言猜测 `type` 值** + - 必须从 schema 的 StepType 枚举中复制准确的类型名称 + - 如 `AddRecordTrigger` 不是 `CreateTrigger` +3. **创建前确认依赖信息** + - 通过 `+table-list` / `+field-list` 获取真实的表名、字段名 - 禁止凭自然语言猜测表名/字段名填入 workflow 配置 +4. **workflow_id 与 table_id 区分** + - `workflow_id` 以 `wkf` 开头,从 `+workflow-list` 或 URL 的 `?table=wkf...` 参数获取 + - `table_id` 以 `tbl` 开头,两者在 URL 的 `?table=` 参数里都会出现,需根据前缀判断 +5. **启用/禁用为写入操作** + - `+workflow-enable` / `+workflow-disable` 执行前必须向用户确认 base-token 和 workflow-id ## Dashboard(仪表盘/数据看板)模块 **当用户提到 "仪表盘、dashboard、数据看板、图表、可视化、block、组件、添加组件、创建图表" 等仪表盘相关的关键词时,必须阅读** [lark-base-dashboard.md](references/lark-base-dashboard.md) 这个指引文档,了解仪表盘模块的命令和能力后再进行后续操作。 diff --git a/skills/lark-base/references/lark-base-workflow-create.md b/skills/lark-base/references/lark-base-workflow-create.md index 162b07e16..71229ba9e 100644 --- a/skills/lark-base/references/lark-base-workflow-create.md +++ b/skills/lark-base/references/lark-base-workflow-create.md @@ -4,18 +4,31 @@ 在 Base 中创建一个新的自动化工作流。新建后状态为 `disabled`,需调用 `+workflow-enable` 才能启用。 +## ⚠️ 执行前必读 + +创建工作流前请按顺序完成: + +1. **先读本文档**,了解 `--json` 参数格式和 `client_token` 的必填要求 +2. **阅读 [workflow-guide.md](lark-base-workflow-guide.md)**,获取 Loop、IfElseBranch、SwitchBranch 等**完整示例** +3. **参考 [workflow-schema.md](lark-base-workflow-schema.md)**,查询具体字段定义 +4. **不需要先调用 `+workflow-list`**,创建操作不依赖现有工作流列表 +5. **按需调用 `+table-list` 和 `+field-list`** 获取表名和字段名(只在需要时调用) +6. **若遇到单多选字段,可调用`+field-get`命令**来获取选项详情 +7. **调用命令时,请将 body 数据直接通过 --json 传入,禁止创建任何的临时文件,即禁止使用 --json @filename** + +**常见错误**: +- ❌ 缺少 `client_token` → 报错: `client token is empty` +- ❌ 猜测 StepType → 报错: `unknown step type 'CreateTrigger'`(应该是 `AddRecordTrigger`) +- ❌ 字段引用路径错误 → 报错: `prompt references an unknown reference` + +> 💡 **提示**: 复杂场景(循环、分支、多步骤组合)的完整示例请直接阅读 [workflow-guide.md](lark-base-workflow-guide.md),本文档只包含基础用法。 + ## 推荐命令 ```bash -# 内联 JSON(简单工作流) lark-cli base +workflow-create \ --base-token BascXxxxxx \ - --json '{"client_token":"1700000000","title":"新订单自动通知","steps":[{"id":"trigger_1","type":"AddRecordTrigger","title":"监控新订单","next":"action_1","data":{"table_name":"订单表","watched_field_name":"订单号"}},{"id":"action_1","type":"LarkMessageAction","title":"发送通知","next":null,"data":{"receiver":[{"value_type":"user","value":"ou_xxxx"}],"send_to_everyone":false,"title":[{"value_type":"text","value":"新订单提醒"}],"content":[{"value_type":"text","value":"收到新订单"}],"btn_list":[]}}]}' - -# 从文件读取(推荐用于复杂工作流) -lark-cli base +workflow-create \ - --base-token BascXxxxxx \ - --json @workflow.json + --json '{"client_token":"1704067200","title":"新订单自动通知","steps":[{"id":"trigger_1","type":"AddRecordTrigger","title":"监控新订单","next":"action_1","data":{"table_name":"订单表","watched_field_name":"订单号"}},{"id":"action_1","type":"LarkMessageAction","title":"发送通知","next":null,"data":{"receiver":[{"value_type":"user","value":{"id":"ou_xxxx"}}],"send_to_everyone":false,"title":[{"value_type":"text","value":"新订单提醒"}],"content":[{"value_type":"text","value":"收到新订单"}],"btn_list":[]}}]}' ``` ## 参数 @@ -23,7 +36,7 @@ lark-cli base +workflow-create \ | 参数 | 必填 | 说明 | |------|------|------| | `--base-token ` | 是 | 多维表格 Base Token(`Basc` 开头) | -| `--json ` | 是 | 工作流 body JSON,包含 `title` 和/或 `steps`;支持 `@path/to/file.json` 从文件读取 | +| `--json ` | 是 | 工作流 body JSON,包含 `title` 和 `steps` | ## 如何从链接中提取参数 @@ -82,12 +95,12 @@ POST /open-apis/base/v3/bases/:base_token/workflows "title": "发送通知", "next": null, "data": { - "receiver": [{ "value_type": "user", "value": "ou_xxxx" }], + "receiver": [{ "value_type": "user", "value": {"id": "ou_xxxx"} }], "send_to_everyone": false, "title": [{ "value_type": "text", "value": "新订单提醒" }], "content": [ { "value_type": "text", "value": "收到新订单,客户:" }, - { "value_type": "ref", "value": { "path": "$.trigger_1.客户名称" } } + { "value_type": "ref", "value": "$.trigger_1.fldCustomerName" } ], "btn_list": [] } @@ -117,7 +130,7 @@ POST /open-apis/base/v3/bases/:base_token/workflows { "ok": true, "data": { - "workflow_id": "wkfxxxxxx", + "workflow_id": "wkfosaYTS1V6rhjF", "title": "新订单自动通知", "status": "disabled", "steps": [...], @@ -135,16 +148,25 @@ POST /open-apis/base/v3/bases/:base_token/workflows > 这是**写入操作** — 执行前必须向用户确认。 1. 与用户确认 `--base-token` 和工作流定义(`--json` 内容) -2. 对于复杂工作流,建议先将 JSON 写入文件,再用 `@file.json` 传入 -3. 执行命令,报告返回的 `workflow_id`(`wkf` 开头) -4. 提示用户:新建工作流初始状态为 `disabled`,需调用 `+workflow-enable --workflow-id <返回的 workflow_id>` 才会生效 +2. 执行命令,报告返回的 `workflow_id`(`wkf` 开头) +3. 提示用户:新建工作流初始状态为 `disabled`,需调用 `+workflow-enable --workflow-id <返回的 workflow_id>` 才会生效 ## 坑点 -- ⚠️ **client_token 必传**:缺失会返回 `[code=800004006] client token is empty`,这不是权限问题,是 JSON body 缺字段。每次请求传唯一值即可(如 `"$(date +%s)"`) +> ⚠️ **【重要】client_token 必传**:缺失会返回 `[code=800004006] client token is empty`,这**不是权限问题**,是 **JSON body 缺字段**。每次请求传唯一值即可(如 `"$(date +%s)"` 或 `"1743078000"`) + - ⚠️ **新建后默认禁用**:`status` 固定返回 `disabled`,需要额外调用 `+workflow-enable` 才能让工作流生效;不要误报"创建成功即启用" - ⚠️ **steps 中 id 字段必须唯一**:每个步骤的 `id` 由调用方指定,且在工作流内必须唯一;`next` 和 `children.links[].to` 引用的 ID 必须在同一 steps 数组中存在,否则服务端返回 `[2200] Internal Error` -- ⚠️ **@file 路径限制**:`--json @workflow.json` 会读取文件内容,复杂 workflow 强烈建议用文件而不是命令行内联。CLI 强制要求相对路径(如 `@./workflow.json`),绝对路径(包括 `/tmp/xxx` 和 `/Users/.../xxx`)会被拒绝 +- ⚠️ **字段类型校验**:设置字段值时,`value_type` 必须与字段实际类型匹配: + - **select 类型字段**(单选/多选/流程):必须用 `option`,不能用 `text` + ```json + // ✅ 正确 + { "field_name": "大区", "value": [{"value_type": "option", "value": {"name": "华东"}}] } + // ❌ 错误 - 会报错 valueType 'text' not allowed for fieldType '3' + { "field_name": "大区", "value": [{"value_type": "text", "value": "华东"}] } + ``` + - **SetRecordTrigger 的 field_watch_info** 同样受此限制,select 类型字段的 value 必须用 `option` + 常见 action 输出:`FindRecordAction` → `$.step_id.recordNum`(记录数)、`$.step_id.fieldRecords`(查找到的记录列表);`AddRecordAction` → `$.step_id.recordId` - ⚠️ **权限不足**:如遇 `permission denied`,先确认当前身份(bot 或 user)是否对该 Base 有编辑权限,再检查 scope 是否已开通。参考 [lark-shared](../../lark-shared/SKILL.md) 中的权限不足处理流程 - ⚠️ **user_id_type**:涉及用户的 `value_type: "user"` 的 value 字段传 OpenID,服务端会根据 `user_id_type`(默认 `open_id`)解析;如需传 `user_id` 格式需在 body 里显式声明 `"user_id_type": "user_id"` diff --git a/skills/lark-base/references/lark-base-workflow-get.md b/skills/lark-base/references/lark-base-workflow-get.md index 1e7e1f058..181c065d2 100644 --- a/skills/lark-base/references/lark-base-workflow-get.md +++ b/skills/lark-base/references/lark-base-workflow-get.md @@ -1,7 +1,7 @@ # base +workflow-get > **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。 -> **必读参考:** 获取到的 `steps` 列表的具体节点结构和各触发器/动作组件的完整配置项,请参见 [`lark-base-workflow-schema.md`](lark-base-workflow-schema.md)。 +> 💡 **按需查阅:** 如需深入理解返回的 `steps` 节点结构,可参考 [workflow-schema.md](lark-base-workflow-schema.md)。简单统计(如节点数量)无需阅读 schema。 获取一个 workflow 的完整定义,包括标题、状态、所有步骤(steps)及其配置。 diff --git a/skills/lark-base/references/lark-base-workflow-guide.md b/skills/lark-base/references/lark-base-workflow-guide.md new file mode 100644 index 000000000..b67321b68 --- /dev/null +++ b/skills/lark-base/references/lark-base-workflow-guide.md @@ -0,0 +1,718 @@ +# Workflow 构造指南 + +本文档提供 Workflow 的完整构造示例、常见模式和错误避免指南。 + +> **配套文档**: +> - Workflow 的数据结构参考:[lark-base-workflow-schema.md](lark-base-workflow-schema.md) +> - 创建命令:[lark-base-workflow-create.md](lark-base-workflow-create.md) +> - 更新命令:[lark-base-workflow-update.md](lark-base-workflow-update.md) + +--- + +## 快速开始 + +### 最简单的 Workflow + +新增记录时发送消息通知: + +```json +{ + "client_token": "1704067200", + "title": "新订单自动通知", + "steps": [ + { + "id": "trigger_1", + "type": "AddRecordTrigger", + "title": "监控新订单", + "next": "action_1", + "data": { + "table_name": "订单表", + "watched_field_name": "订单号" + } + }, + { + "id": "action_1", + "type": "LarkMessageAction", + "title": "发送通知", + "next": null, + "data": { + "receiver": [{ "value_type": "user", "value": {"id": "ou_xxxx", "name": "张三"} }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "新订单提醒" }], + "content": [ + { "value_type": "text", "value": "收到新订单" } + ], + "btn_list": [] + } + } + ] +} +``` + +--- + +## 场景速查表 + +| 场景 | 步骤组合 | 示例 | +|------|---------|------| +| 新增触发+通知 | AddRecordTrigger → LarkMessageAction | [下方](#示例1-新增记录触发--发送消息) | +| 定时+循环 | TimerTrigger → FindRecordAction → Loop → LarkMessageAction | [下方](#示例2-定时触发--查找记录--循环遍历--发送消息) | +| 条件判断 | ... → IfElseBranch → 分支处理 | [下方](#示例3-条件分支-ifelsebranch) | +| 多路分类 | ... → SwitchBranch → 多分支处理 | [下方](#示例4-多路分支-switchbranch) | +| 复杂组合 | 定时+查找+循环+分支+消息 | [下方](#示例5-组合场景-定时查找循环分支消息) | + +--- + +## 完整示例 + +### 示例 1: 新增记录触发 + 发送消息 + +**场景**: 当订单表新增记录时,发送飞书消息通知负责人。 + +```json +{ + "client_token": "1704067201", + "title": "新订单自动通知", + "steps": [ + { + "id": "step_trigger", + "type": "AddRecordTrigger", + "title": "新增订单时触发", + "next": "step_notify", + "data": { + "table_name": "订单表", + "watched_field_name": "订单号", + "condition_list": null + } + }, + { + "id": "step_notify", + "type": "LarkMessageAction", + "title": "发送订单通知", + "next": null, + "data": { + "receiver": [{ "value_type": "ref", "value": "$.step_trigger.fldManager" }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "新订单提醒" }], + "content": [ + { "value_type": "text", "value": "客户 " }, + { "value_type": "ref", "value": "$.step_trigger.fldCustomer" }, + { "value_type": "text", "value": " 创建了新订单,金额:¥" }, + { "value_type": "ref", "value": "$.step_trigger.fldAmount" } + ], + "btn_list": [ + { + "text": "查看订单", + "btn_action": "openLink", + "link": [{ "value_type": "ref", "value": "$.step_trigger.recordLink" }] + } + ] + } + } + ] +} +``` + +**关键点**: +- `AddRecordTrigger` 监控 `table_name` 表的 `watched_field_name` 字段 +- 使用 `ref` 引用触发器输出的字段值(注意是 fieldId,不是字段名) +- `recordLink` 是触发器内置输出,表示记录链接 + +--- + +### 示例 2: 定时触发 + 查找记录 + 循环遍历 + 发送消息 + +**场景**: 每天早上 9 点,查找所有待处理订单,给每个客户发送提醒。 + +```json +{ + "client_token": "1704067202", + "title": "每日待处理订单提醒", + "steps": [ + { + "id": "step_timer", + "type": "TimerTrigger", + "title": "每天早上9点触发", + "next": "step_find_orders", + "data": { + "rule": "DAILY", + "start_time": "2025-01-01 09:00", + "is_never_end": true + } + }, + { + "id": "step_find_orders", + "type": "FindRecordAction", + "title": "查找所有待处理订单", + "next": "step_loop_customers", + "data": { + "table_name": "订单表", + "field_names": ["客户名称", "订单金额", "客户联系方式"], + "should_proceed_when_no_results": false, + "filter_info": { + "conjunction": "and", + "conditions": [ + { + "field_name": "状态", + "operator": "is", + "value": [{ "value_type": "option", "value": { "name": "待处理" } }] + } + ] + } + } + }, + { + "id": "step_loop_customers", + "type": "Loop", + "title": "遍历每个订单", + "children": { + "links": [ + { "kind": "loop_start", "to": "step_send_reminder" } + ] + }, + "next": null, + "data": { + "loop_mode": "continue", + "max_loop_times": 100, + "data": [{ + "value_type": "ref", + "value": "$.step_find_orders.fieldRecords" + }] + } + }, + { + "id": "step_send_reminder", + "type": "LarkMessageAction", + "title": "发送催办消息", + "next": null, + "data": { + "receiver": [{ + "value_type": "ref", + "value": "$.step_loop_customers.item.fldContact" + }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "订单处理提醒" }], + "content": [ + { "value_type": "text", "value": "您好,您的订单 " }, + { "value_type": "ref", "value": "$.step_loop_customers.item.fldName" }, + { "value_type": "text", "value": " 金额 ¥" }, + { "value_type": "ref", "value": "$.step_loop_customers.item.fldAmount" }, + { "value_type": "text", "value": " 正在处理中。" } + ], + "btn_list": [] + } + } + ] +} +``` + +**关键点**: +- `Loop.data` 必须传入 `ref` 类型的数据源(通常是 FindRecordAction 的 `fieldRecords`) +- `Loop.children.links` 必须包含 `kind: "loop_start"` 的链接指向循环体 +- 循环体内用 `$.{loopStepId}.item.{fieldId}` 引用当前遍历记录的字段 +- `$.{loopStepId}.index` 获取当前索引(从 0 开始) + +--- + +### 示例 3: 条件分支(IfElseBranch) + +**场景**: 根据订单金额判断,大额订单通知主管审批,小额订单自动通过。 + +```json +{ + "client_token": "1704067203", + "title": "订单金额自动判断", + "steps": [ + { + "id": "step_trigger", + "type": "AddRecordTrigger", + "title": "新增订单时触发", + "next": "step_check_amount", + "data": { + "table_name": "订单表", + "watched_field_name": "订单金额" + } + }, + { + "id": "step_check_amount", + "type": "IfElseBranch", + "title": "判断是否为大额订单", + "children": { + "links": [ + { "kind": "if_true", "to": "step_notify_manager", "label": "high", "desc": "金额>=10000" }, + { "kind": "if_false", "to": "step_auto_approve", "label": "normal", "desc": "金额<10000" } + ] + }, + "next": "step_log", + "data": { + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_trigger.fldAmount" }, + "operator": "isGreaterEqual", + "right_value": [{ "value_type": "number", "value": 10000 }] + } + ] + } + ] + } + } + }, + { + "id": "step_notify_manager", + "type": "LarkMessageAction", + "title": "通知主管审批大额订单", + "next": "step_log", + "data": { + "receiver": [{ "value_type": "user", "value": {"id": "ou_manager", "name": "主管"} }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "大额订单待审批" }], + "content": [ + { "value_type": "text", "value": "有大额订单 ¥" }, + { "value_type": "ref", "value": "$.step_trigger.fldAmount" }, + { "value_type": "text", "value": " 需要您审批" } + ], + "btn_list": [] + } + }, + { + "id": "step_auto_approve", + "type": "SetRecordAction", + "title": "自动标记小额订单为已审核", + "next": "step_log", + "data": { + "table_name": "订单表", + "ref_info": { "step_id": "step_trigger" }, + "field_values": [ + { + "field_name": "审批状态", + "value": [{ "value_type": "option", "value": { "name": "已自动审核" } }] + } + ] + } + }, + { + "id": "step_log", + "type": "GenerateAiTextAction", + "title": "生成订单处理日志", + "next": null, + "data": { + "prompt": [ + { "value_type": "text", "value": "请生成订单处理日志,金额:" }, + { "value_type": "ref", "value": "$.step_trigger.fldAmount" } + ] + } + } + ] +} +``` + +**关键点**: +- `IfElseBranch.children.links` 必须包含 `if_true` 和 `if_false` 两个分支 +- `next` 指向两个分支汇合后的步骤(可选,为 null 则分支结束) +- `condition` 使用 OrGroup 结构,支持 `(A and B) or (C and D)` 的复杂条件 +- 分支内可以用 `ref_info` 引用触发记录,用 `filter_info` 批量筛选记录 + +--- + +### 示例 4: 多路分支(SwitchBranch) + +**场景**: 根据订单优先级(P0/P1/P2)执行不同的处理流程。 + +```json +{ + "client_token": "1704067204", + "title": "按优先级分类处理订单", + "steps": [ + { + "id": "step_trigger", + "type": "AddRecordTrigger", + "title": "新增订单时触发", + "next": "step_classify", + "data": { + "table_name": "订单表", + "watched_field_name": "优先级" + } + }, + { + "id": "step_classify", + "type": "SwitchBranch", + "title": "按优先级分类", + "children": { + "links": [ + { "kind": "case", "to": "step_p0_handler", "label": "p0", "desc": "P0-紧急" }, + { "kind": "case", "to": "step_p1_handler", "label": "p1", "desc": "P1-高优先级" }, + { "kind": "case", "to": "step_p2_handler", "label": "p2", "desc": "P2-普通" }, + { "kind": "case", "to": "step_other_handler", "label": "other", "desc": "其他" } + ] + }, + "next": null, + "data": { + "mode": "exclusive", + "no_match_action": "classifyToOther", + "child_branch_list": [ + { + "name": "P0-紧急", + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_trigger.fldPriority" }, + "operator": "is", + "right_value": [{ "value_type": "option", "value": { "name": "P0" } }] + } + ] + } + ] + } + }, + { + "name": "P1-高优先级", + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_trigger.fldPriority" }, + "operator": "is", + "right_value": [{ "value_type": "option", "value": { "name": "P1" } }] + } + ] + } + ] + } + }, + { + "name": "P2-普通", + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_trigger.fldPriority" }, + "operator": "is", + "right_value": [{ "value_type": "option", "value": { "name": "P2" } }] + } + ] + } + ] + } + } + ] + } + }, + { + "id": "step_p0_handler", + "type": "LarkMessageAction", + "title": "P0紧急处理", + "next": null, + "data": { + "receiver": [{ "value_type": "user", "value": {"id": "ou_director", "name": "总监"} }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "🚨 P0 紧急订单" }], + "content": [{ "value_type": "text", "value": "有新的 P0 紧急订单需要立即处理" }], + "btn_list": [] + } + }, + { + "id": "step_p1_handler", + "type": "SetRecordAction", + "title": "标记高优先级", + "next": null, + "data": { + "table_name": "订单表", + "ref_info": { "step_id": "step_trigger" }, + "field_values": [ + { "field_name": "处理状态", "value": [{ "value_type": "text", "value": "高优先级待处理" }] } + ] + } + }, + { + "id": "step_p2_handler", + "type": "Delay", + "title": "普通订单延迟处理", + "next": null, + "data": { "duration": 60 } + }, + { + "id": "step_other_handler", + "type": "SetRecordAction", + "title": "标记其他订单", + "next": null, + "data": { + "table_name": "订单表", + "ref_info": { "step_id": "step_trigger" }, + "field_values": [ + { "field_name": "处理状态", "value": [{ "value_type": "text", "value": "待分类" }] } + ] + } + } + ] +} +``` + +**关键点**: +- `SwitchBranch` 适合 3 路及以上的分支场景(少于 3 路用 `IfElseBranch` 更简洁) +- `children.links` 中 `kind: "case"` 的 `label` 对应 `child_branch_list` 中的条件 +- `mode: "exclusive"` 表示排他执行(第一个匹配的分支执行后停止) +- `no_match_action: "classifyToOther"` 表示无匹配时走最后一个 `case`(兜底分支) + +--- + +### 示例 5: 组合场景(定时+查找+循环+分支+消息) + +**场景**: 每天早上 9 点,查找昨天的订单,按金额分级,给不同级别的销售发送不同的通知。 + +```json +{ + "client_token": "1704067205", + "title": "每日订单分级通知", + "steps": [ + { + "id": "step_timer", + "type": "TimerTrigger", + "title": "每天早上9点触发", + "next": "step_find_orders", + "data": { + "rule": "DAILY", + "start_time": "2025-01-01 09:00", + "is_never_end": true + } + }, + { + "id": "step_find_orders", + "type": "FindRecordAction", + "title": "查找昨天所有订单", + "next": "step_loop", + "data": { + "table_name": "订单表", + "field_names": ["订单号", "客户名称", "金额", "销售负责人"], + "should_proceed_when_no_results": false, + "filter_info": { + "conjunction": "and", + "conditions": [ + { "field_name": "创建时间", "operator": "isGreaterEqual", "value": [{ "value_type": "date", "value": "yesterday" }] } + ] + } + } + }, + { + "id": "step_loop", + "type": "Loop", + "title": "遍历每个订单", + "children": { + "links": [ + { "kind": "loop_start", "to": "step_classify" } + ] + }, + "next": "step_summary", + "data": { + "loop_mode": "continue", + "max_loop_times": 500, + "data": [{ "value_type": "ref", "value": "$.step_find_orders.fieldRecords" }] + } + }, + { + "id": "step_classify", + "type": "SwitchBranch", + "title": "按金额分类", + "children": { + "links": [ + { "kind": "case", "to": "step_vip_notify", "label": "vip", "desc": "VIP >= 10万" }, + { "kind": "case", "to": "step_normal_notify", "label": "normal", "desc": "普通 < 10万" } + ] + }, + "next": null, + "data": { + "mode": "exclusive", + "no_match_action": "fail", + "child_branch_list": [ + { + "name": "VIP订单", + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_loop.item.fldAmount" }, + "operator": "isGreaterEqual", + "right_value": [{ "value_type": "number", "value": 100000 }] + } + ] + } + ] + } + }, + { + "name": "普通订单", + "condition": { + "conjunction": "or", + "conditions": [ + { + "conjunction": "and", + "conditions": [ + { + "left_value": { "value_type": "ref", "value": "$.step_loop.item.fldAmount" }, + "operator": "isLess", + "right_value": [{ "value_type": "number", "value": 100000 }] + } + ] + } + ] + } + } + ] + } + }, + { + "id": "step_vip_notify", + "type": "LarkMessageAction", + "title": "VIP订单通知", + "next": null, + "data": { + "receiver": [{ "value_type": "ref", "value": "$.step_loop.item.fldSales" }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "🌟 VIP大额订单" }], + "content": [ + { "value_type": "text", "value": "恭喜!您有一笔 VIP 订单 ¥" }, + { "value_type": "ref", "value": "$.step_loop.item.fldAmount" }, + { "value_type": "text", "value": ",客户:" }, + { "value_type": "ref", "value": "$.step_loop.item.fldCustomer" } + ], + "btn_list": [] + } + }, + { + "id": "step_normal_notify", + "type": "LarkMessageAction", + "title": "普通订单通知", + "next": null, + "data": { + "receiver": [{ "value_type": "ref", "value": "$.step_loop.item.fldSales" }], + "send_to_everyone": false, + "title": [{ "value_type": "text", "value": "新订单通知" }], + "content": [ + { "value_type": "text", "value": "您有一笔新订单 ¥" }, + { "value_type": "ref", "value": "$.step_loop.item.fldAmount" } + ], + "btn_list": [] + } + }, + { + "id": "step_summary", + "type": "GenerateAiTextAction", + "title": "生成日报", + "next": null, + "data": { + "prompt": [ + { "value_type": "text", "value": "请生成昨日订单处理日报" } + ] + } + } + ] +} +``` + +--- + +## 构造技巧 + +### Loop 构造要点 + +1. **数据源**: `Loop.data` 必须传入 `ref` 类型,通常是 `FindRecordAction` 的 `fieldRecords` +2. **循环体**: `children.links` 必须包含 `kind: "loop_start"` 指向循环体入口 +3. **引用**: 循环体内用 `$.{loopStepId}.item.{fieldId}` 引用当前元素 +4. **索引**: 用 `$.{loopStepId}.index` 获取当前索引(从 0 开始) + +### 分支构造要点 + +1. **IfElseBranch**: + - 适合二元判断(是/否、大于/小于) + - `children.links` 必须包含 `if_true` 和 `if_false` + - 可以用 `next` 指向汇合点 + +2. **SwitchBranch**: + - 适合多路分类(3路及以上) + - `label` 对应 `child_branch_list` 中的条件顺序 + - 建议加一个兜底分支(其他) + +### 字段值构造 + +| 字段类型 | value_type | 示例 | +|---------|------------|------| +| 文本 | `text` | `{"value_type": "text", "value": "张三"}` | +| 数字 | `number` | `{"value_type": "number", "value": 100}` | +| 单选 | `option` | `{"value_type": "option", "value": {"name": "已完成"}}` | +| 人员 | `user` | `{"value_type": "user", "value": {"id": "ou_xxxx"}}` | +| 引用 | `ref` | `{"value_type": "ref", "value": "$.step_1.fldxxx"}` | + +--- + +## 常见错误避免 + +### Top 10 高频错误 + +| # | 错误信息 | 原因 | 解决方案 | +|---|---------|------|---------| +| 1 | `path "xxx" does not exist in the output path tree` | ref 引用路径错误或 stepId 不存在 | 检查 stepId 是否在 steps 数组中;使用 fieldId 而非字段名;确保路径以 `$.` 开头 | +| 2 | `recordInfo.conditions must be non-empty` | `condition_list` 为空数组 `[]` | 改用 `null` 或省略该字段 | +| 3 | `At least one of filter info and ref info is required` | SetRecordAction/FindRecordAction 缺少定位条件 | 必须提供 `filter_info` 或 `ref_info` 之一 | +| 4 | `client token is empty` | 缺少 `client_token` | 每次请求传入唯一值(时间戳或随机字符串) | +| 5 | `valueType 'text' not allowed for fieldType '3'` | select 类型字段值格式错误 | 改用 `option` 类型 | +| 6 | `Undefined Step Type` | 使用了不支持的 StepType | 使用 `AddRecordTrigger` 而非 `CreateRecordTrigger` | +| 7 | `prompt references an unknown reference from step` | 引用的 stepId 不存在 | 确保引用的 step 在同一 workflow 的 steps 数组中 | +| 8 | `[2200] Internal Error` | 1. steps[].id 重复 2. next/children.links 引用了不存在的 step | 确保所有 step id 唯一;检查引用关系 | +| 9 | 工作流结构不完整 | Branch/Loop 节点缺少 `children` | 仅 Branch(IfElseBranch/SwitchBranch)和 Loop 节点需要 `children`,Trigger/Action 节点无需设置 | +| 10 | 嵌套分支过于复杂 | 多层 IfElseBranch 嵌套 | 3+ 路分支用 SwitchBranch 替代嵌套 IfElseBranch | + +### 其他常见错误 + +**1. condition_list 为空数组** +```json +// ❌ 错误 +{ "condition_list": [] } + +// ✅ 正确 +{ "condition_list": null } +// 或省略该字段 +``` + +**2. filter_info 和 ref_info 同时提供** +```json +// ❌ 错误 +{ "filter_info": {...}, "ref_info": {...} } + +// ✅ 正确(二选一) +{ "filter_info": {...}, "ref_info": null } +{ "filter_info": null, "ref_info": {...} } +``` + +**3. 使用字段名而非 fieldId** +```json +// ❌ 错误 +{ "value": "$.step_1.客户名称" } + +// ✅ 正确 +{ "value": "$.step_1.fldXXXXXXXX" } +``` + +--- + +## 参考 + +- [lark-base-workflow-schema.md](lark-base-workflow-schema.md) — 字段定义参考 +- [lark-base-workflow-create.md](lark-base-workflow-create.md) — 创建命令 +- [lark-base-workflow-update.md](lark-base-workflow-update.md) — 更新命令 diff --git a/skills/lark-base/references/lark-base-workflow-list.md b/skills/lark-base/references/lark-base-workflow-list.md index e9029be72..84fe35179 100644 --- a/skills/lark-base/references/lark-base-workflow-list.md +++ b/skills/lark-base/references/lark-base-workflow-list.md @@ -98,6 +98,18 @@ POST /open-apis/base/v3/bases/:base_token/workflows/list } ``` +## ⚡ 性能提示 +### 场景适用性 +**✅ 需要先 list 的场景**: +- 批量操作:启用/停用多个工作流(先 list,再批量 enable/disable) +- 查询统计:统计定时触发的工作流数量(先 list,再筛选) +- 修改操作:修改指定名称的工作流(先 list ,从列表中找到对应名称工作流的 workflow_id,再 get/update) + **❌ 不需要先 list 的场景**: +- **创建工作流**:直接调用 `+workflow-create`,不需要先 list +- 查看指定工作流详情:如果已知 workflow_id,直接 `+workflow-get` +### 缓存策略 +同一会话中处理多个工作流时,只需调用一次 `+workflow-list` 获取全部结果,然后从中筛选所需的工作流,避免重复查询。 + ## 坑点 - ⚠️ **列表用 POST 不用 GET**:`/workflows/list` 是 POST 接口,`page_token` 放在 Request Body 里而不是 Query 参数,常见误区 diff --git a/skills/lark-base/references/lark-base-workflow-schema.md b/skills/lark-base/references/lark-base-workflow-schema.md index ac80870cd..3a0594020 100644 --- a/skills/lark-base/references/lark-base-workflow-schema.md +++ b/skills/lark-base/references/lark-base-workflow-schema.md @@ -1,6 +1,21 @@ # Workflow 数据结构参考 -本文档定义 `+workflow-create` / `+workflow-update` 命令 `--json` body 的完整数据结构(V2 协议)。 +本文档定义 Workflow 的完整数据结构,适用于: +- **查询场景**:理解 `+workflow-get` 返回的 `steps` 结构 +- **创建/修改场景**:构造 `+workflow-create` / `+workflow-update` 的 `--json` body +> 💡 **本文档是纯字段参考**。如需**创建/修改**工作流的完整示例,请阅读 [workflow-guide.md](lark-base-workflow-guide.md)。 +--- +## 📖 快速导航 + +根据你的需求跳转到对应章节: + +| 需求 | 章节 | +|------|------| +| 了解 Step 基础结构 | [WorkflowStep 基础结构](#workflowstep-基础结构) | +| 查询 Trigger 类型及 data 字段 | [Trigger data](#trigger-data-详细结构) | +| 查询 Action 类型及 data 字段 | [Action data](#action-data-详细结构) | +| 查询 Branch/Loop 结构 | [Branch data](#branch-data-详细结构) / [System data](#system-data-详细结构) | +| 查询 ValueInfo/Condition 等公共类型 | [公共类型](#公共类型) | --- @@ -128,6 +143,7 @@ ## Trigger data 详细结构 + ### AddRecordTrigger ```json @@ -178,13 +194,13 @@ ``` | 字段 | 必填 | 说明 | -|------|------|------| -| `table_name` | 是 | 监控的数据表名 | -| `record_watch_conjunction` | 否 | 记录筛选组合方式:`and` / `or`,默认 `and` | -| `record_watch_info` | 否 | 记录级过滤条件(修改前值匹配),为空则监听全部 | -| `field_watch_info` | 否 | 字段级监控条件列表,至少一个 | -| `trigger_control_list` | 否 | 触发控制,可选值:`pasteUpdate` / `automationBatchUpdate` / `syncUpdate` / `appendImport` | -| `condition_list` | 否 | 过滤条件数组,数组中每个元素为 AndCondition 结构,多个 AndCondition 之间为 OR 关系 | +|------|----|------| +| `table_name` | 是 | 监控的数据表名 | +| `record_watch_conjunction` | 否 | 记录筛选组合方式:`and` / `or`,默认 `and` | +| `record_watch_info` | 否 | 记录级过滤条件(修改前值匹配),为空则监听全部 | +| `field_watch_info` | 是 | 字段级监控条件列表,至少一个 | +| `trigger_control_list` | 否 | 触发控制,可选值:`pasteUpdate` / `automationBatchUpdate` / `syncUpdate` / `appendImport` | +| `condition_list` | 否 | 过滤条件数组,数组中每个元素为 AndCondition 结构,多个 AndCondition 之间为 OR 关系 | `FieldWatchItem`: @@ -245,7 +261,7 @@ ```json { "receive_scene": "group", - "receiver": [{ "value_type": "group", "value": "测试群" }], + "receiver": [{ "value_type": "group", "value": {"id": "oc_xxxx", "name": "测试群"} }], "scope": "all", "filter": { "conjunction": "and", @@ -349,12 +365,12 @@ ```json { - "receiver": [{ "value_type": "user", "value": "ou_xxxx" }], + "receiver": [{ "value_type": "user", "value": {"id": "ou_xxxx"} }], "send_to_everyone": false, "title": [{ "value_type": "text", "value": "新订单通知" }], "content": [ { "value_type": "text", "value": "客户 " }, - { "value_type": "ref", "value": "$.trigger_1.fieldIdxxx" }, + { "value_type": "ref", "value": "$.trigger_1.fldCustomerName" }, { "value_type": "text", "value": " 创建了新订单" } ], "btn_list": [ @@ -435,6 +451,8 @@ ```json { + "mode": "exclusive", + "no_match_action": "classifyToOther", "child_branch_list": [ { "name": "高优先级", @@ -460,6 +478,10 @@ | 字段 | 必填 | 说明 | |------|------|------| +| `mode` | 否 | 分支模式。`exclusive`:排他模式,仅执行一个满足条件的子分支;`parallel`:并行模式,执行所有满足条件的子分支。默认 `exclusive` | +| `no_match_action` | 否 | `mode=exclusive` 时使用,无匹配时的处理策略。`classifyToOther`:归类到其他分支;`fail`:报错终止。默认 `classifyToOther` | +| `fail_mode` | 否 | `mode=parallel` 时使用,部分分支出错时策略。`partialSuccess`:部分成功即继续;`fail`:任一失败即终止。默认 `partialSuccess` | +| `match_mode` | 否 | `mode=parallel` 时使用,所有分支不满足时策略。`noneMatchSkip`:跳过继续;`noneMatchFail`:报错终止。默认 `noneMatchSkip` | | `child_branch_list` | 是 | BranchItem[],1-10 个条件分支 | `BranchItem`: @@ -480,7 +502,7 @@ { "loop_mode": "continue", "max_loop_times": 100, - "data": [{ "value_type": "ref", "value": "$.find_record_stepIdxxx.records" }] + "data": [{ "value_type": "ref", "value": "$.find_record_stepIdxxx.fieldRecords" }] } ``` @@ -593,18 +615,18 @@ $.{stepId}.{pathId}.{childPathId}.{grandChildPathId} ##### FindRecordAction(查找记录) -| pathId | 说明 | 引用示例 | -|--------|------|----------| -| `fieldRecords` | 所有找到的记录的引用(可用于 Loop 遍历) | 不支持引用 | -| `firstfieldsRecord` | 第一条匹配记录 | `$.{stepId}.firstfieldsRecord` | -| `firstfieldsRecord.{fieldId}` | 首条记录的字段值,可下钻字段属性 | `$.{stepId}.firstfieldsRecord.{fieldId}` | -| `firstfieldsRecord.recordId` | 记录 ID 数组 | `$.{stepId}.firstfieldsRecord.recordId` | -| `fields` | 查找到的所有记录某列值 | 不支持引用 | -| `fields.{fieldId}` | 用户选择的字段 | `$.{stepId}.fields.{fieldId}` | -| `fields.{fieldId}.fieldId` | 用户选择的字段id数组 | `$.{stepId}.fields.{fieldId}.fieldId` | -| `fields.{fieldId}.fieldName` | 用户选择的字段名数组 | `$.{stepId}.fields.{fieldId}.fieldName` | -| `fields.recordId` | 记录 ID 数组 | `$.{stepId}.fields.recordId` | -| `recordNum` | 找到记录总数 | `$.{stepId}.recordNum` | +| pathId | 说明 | 引用示例| +|--------|------|-------| +| `fieldRecords` | 所有找到的记录的引用(可用于 Loop 遍历) | `$.{stepId}.fieldRecords`| +| `firstfieldsRecord` | 第一条匹配记录 | `$.{stepId}.firstfieldsRecord`| +| `firstfieldsRecord.{fieldId}` | 首条记录的字段值,可下钻字段属性 | `$.{stepId}.firstfieldsRecord.{fieldId}`| +| `firstfieldsRecord.recordId` | 记录 ID 数组 | `$.{stepId}.firstfieldsRecord.recordId`| +| `fields` | 查找到的所有记录某列值 | 不支持引用| +| `fields.{fieldId}` | 用户选择的字段 | `$.{stepId}.fields.{fieldId}`| +| `fields.{fieldId}.fieldId` | 用户选择的字段id数组 | `$.{stepId}.fields.{fieldId}.fieldId`| +| `fields.{fieldId}.fieldName` | 用户选择的字段名数组 | `$.{stepId}.fields.{fieldId}.fieldName`| +| `fields.recordId` | 记录 ID 数组 | `$.{stepId}.fields.recordId`| +| `recordNum` | 找到记录总数 | `$.{stepId}.recordNum`| ##### AddRecordAction(新增记录) diff --git a/skills/lark-base/references/lark-base-workflow-update.md b/skills/lark-base/references/lark-base-workflow-update.md index 45cb15ce2..28a9c97fd 100644 --- a/skills/lark-base/references/lark-base-workflow-update.md +++ b/skills/lark-base/references/lark-base-workflow-update.md @@ -4,22 +4,23 @@ 全量替换 Base 中一个已有工作流的定义(`title` 和/或 `steps`)。使用 PUT 语义,传入的内容会完整覆盖原有定义。 -> 如果只想修改标题,用 `+workflow-patch`(PATCH 接口,仅支持 `title` 字段)更合适。 +## ⚠️ 执行前必读 + +更新工作流前请按顺序完成: + +1. **先读本文档**,了解 `--json` 参数格式和 PUT 全量覆盖的语义 +2. **阅读 [workflow-guide.md](lark-base-workflow-guide.md)**,获取 Loop、IfElseBranch、SwitchBranch 等**完整示例**(与创建场景共用相同的步骤结构) +3. **参考 [workflow-schema.md](lark-base-workflow-schema.md)**,查询具体字段定义 +4. **按需调用 `+workflow-list`** 获取工作流 ID(`wkf` 开头) +5. **如需基于现有工作流修改**,先调用 `+workflow-get` 导出当前定义,在此基础上修改 ## 推荐命令 ```bash -# 从文件读取(推荐,工作流 JSON 通常较大) -lark-cli base +workflow-update \ - --base-token BascXxxxxx \ - --workflow-id wkfxxxxxx \ - --json @workflow.json - -# 内联 JSON(仅修改标题,steps 置空) lark-cli base +workflow-update \ --base-token BascXxxxxx \ - --workflow-id wkfxxxxxx \ - --json '{"title":"新标题"}' + --workflow-id wkfosaYTS1V6rhjF \ + --json '{"title":"新标题","steps":[{"id":"trigger_1","type":"AddRecordTrigger","title":"监控新订单","next":"action_1","data":{"table_name":"订单表","watched_field_name":"订单号"}},{"id":"action_1","type":"LarkMessageAction","title":"发送通知","next":null,"data":{"receiver":[{"value_type":"user","value":{"id":"ou_xxxx"}}],"send_to_everyone":false,"title":[{"value_type":"text","value":"新订单提醒"}],"content":[{"value_type":"text","value":"收到新订单"}],"btn_list":[]}}]}' ``` ## 参数 @@ -28,7 +29,7 @@ lark-cli base +workflow-update \ |------|------|------| | `--base-token ` | 是 | 多维表格 Base Token(`Basc` 开头) | | `--workflow-id ` | 是 | 工作流 ID(`wkf` 开头),可从 `+workflow-list` 获取 | -| `--json ` | 是 | 工作流 body JSON,包含 `title` 和/或 `steps`;支持 `@path/to/file.json` 从文件读取 | +| `--json ` | 是 | 工作流 body JSON,包含 `title` 和/或 `steps`| ## 如何从链接中提取参数 @@ -90,12 +91,12 @@ PUT /open-apis/base/v3/bases/:base_token/workflows/:workflow_id "title": "发送通知", "next": null, "data": { - "receiver": [{ "value_type": "user", "value": "ou_xxxx" }], + "receiver": [{ "value_type": "user", "value": {"id": "ou_xxxx"} }], "send_to_everyone": false, "title": [{ "value_type": "text", "value": "新订单提醒" }], "content": [ { "value_type": "text", "value": "收到新订单,客户:" }, - { "value_type": "ref", "value": { "path": "$.trigger_1.客户名称" } } + { "value_type": "ref", "value": "$.trigger_1.fldCustomerName" } ], "btn_list": [] } @@ -104,6 +105,8 @@ PUT /open-apis/base/v3/bases/:base_token/workflows/:workflow_id } ``` +> **注意**:Trigger 和 Action 节点不应设置 `children` 字段,只有 Branch(如 IfElseBranch、SwitchBranch)和 System(如 Loop)节点才需要 `children` 来描述分支或循环结构。 + ## API 出参详情 **Response `data` 字段:** @@ -125,7 +128,7 @@ PUT /open-apis/base/v3/bases/:base_token/workflows/:workflow_id { "ok": true, "data": { - "workflow_id": "wkfxxxxxx", + "workflow_id": "wkfosaYTS1V6rhjF", "title": "新订单自动通知(更新版)", "status": "disabled", "steps": [...], @@ -144,8 +147,7 @@ PUT /open-apis/base/v3/bases/:base_token/workflows/:workflow_id 1. 确认 `--base-token` 和 `--workflow-id`(建议先用 `+workflow-list` 查出 ID) 2. 确认 `--json` 的完整内容 — PUT 会全量覆盖,漏传 `steps` 会清空所有步骤 -3. 对于复杂工作流,建议先将 JSON 写入文件,用 `@file.json` 传入 -4. 执行命令,报告返回的 `workflow_id` 和 `update_time` +3. 执行命令,报告返回的 `workflow_id` 和 `update_time` ## 坑点 @@ -153,12 +155,11 @@ PUT /open-apis/base/v3/bases/:base_token/workflows/:workflow_id - ⚠️ **workflow_id 前缀**:以 `wkf` 开头,从 URL 的 `?table=wkf...` 提取;和 table_id(`tbl` 开头)混淆会导致 `[2200] Internal Error` - ⚠️ **steps 中 id 字段必须唯一**:每个步骤的 `id` 在同一工作流内必须唯一;`next` 和 `children.links[].to` 引用的 ID 必须在 steps 数组中存在 - ⚠️ **更新不影响 enabled 状态**:`+workflow-update` 不会改变工作流的 `enabled/disabled` 状态;需要另外调用 `+workflow-enable` / `+workflow-disable` -- ⚠️ **scope 待确认**:内部文档未列出权限名称,代码中使用 `base:workflow:write`,如遇 `[230013] permission denied` 需核对实际 scope -- ⚠️ **@file 支持**:`--json @workflow.json` 会读取文件内容,复杂 workflow 强烈建议用文件 ## 参考 -- [lark-base-workflow-schema.md](lark-base-workflow-schema.md) — 完整 Workflow 数据结构 +- [lark-base-workflow-schema.md](lark-base-workflow-schema.md) — Workflow 数据结构参考 +- [lark-base-workflow-guide.md](lark-base-workflow-guide.md) — **完整示例、构造技巧、常见错误** - [lark-base-workflow-create](lark-base-workflow-create.md) — 创建工作流 - [lark-base-workflow-enable](lark-base-workflow-enable.md) — 启用工作流 - [lark-base-workflow-list](lark-base-workflow-list.md) — 列出全部工作流