diff --git a/shortcuts/base/base_dryrun_ops_test.go b/shortcuts/base/base_dryrun_ops_test.go index 5b9b7a36f..64d53bdfd 100644 --- a/shortcuts/base/base_dryrun_ops_test.go +++ b/shortcuts/base/base_dryrun_ops_test.go @@ -104,6 +104,8 @@ func TestDryRunRecordOps(t *testing.T) { nil, nil, ) assertDryRunContains(t, dryRunRecordUpsert(ctx, upsertCreateRT), "POST /open-apis/base/v3/bases/app_x/tables/tbl_1/records") + assertDryRunContains(t, dryRunRecordBatchCreate(ctx, upsertCreateRT), "POST /open-apis/base/v3/bases/app_x/tables/tbl_1/records/batch_create") + assertDryRunContains(t, dryRunRecordBatchUpdate(ctx, upsertCreateRT), "POST /open-apis/base/v3/bases/app_x/tables/tbl_1/records/batch_update") rt := newBaseTestRuntime( map[string]string{"base-token": "app_x", "table-id": "tbl_1", "record-id": "rec_1", "json": `{"Name":"B"}`}, diff --git a/shortcuts/base/base_execute_test.go b/shortcuts/base/base_execute_test.go index 374afb034..3698d3994 100644 --- a/shortcuts/base/base_execute_test.go +++ b/shortcuts/base/base_execute_test.go @@ -664,6 +664,75 @@ func TestBaseRecordExecuteReadCreateDelete(t *testing.T) { } }) + t.Run("batch create", func(t *testing.T) { + factory, stdout, reg := newExecuteFactory(t) + reg.Register(&httpmock.Stub{ + Method: "POST", + URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/records/batch_create", + Body: map[string]interface{}{ + "code": 0, + "data": map[string]interface{}{ + "fields": []interface{}{"Name"}, + "record_id_list": []interface{}{"rec_1", "rec_2"}, + "data": []interface{}{[]interface{}{"Alice"}, []interface{}{"Bob"}}, + }, + }, + }) + if err := runShortcut(t, BaseRecordBatchCreate, []string{"+record-batch-create", "--base-token", "app_x", "--table-id", "tbl_x", "--json", `{"fields":["Name"],"rows":[["Alice"],["Bob"]]}`}, factory, stdout); err != nil { + t.Fatalf("err=%v", err) + } + if got := stdout.String(); !strings.Contains(got, `"record_id_list"`) || !strings.Contains(got, `"rec_1"`) || !strings.Contains(got, `"Alice"`) { + t.Fatalf("stdout=%s", got) + } + }) + + t.Run("batch update", func(t *testing.T) { + factory, stdout, reg := newExecuteFactory(t) + reg.Register(&httpmock.Stub{ + Method: "POST", + URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/records/batch_update", + Body: map[string]interface{}{ + "code": 0, + "data": map[string]interface{}{ + "has_more": false, + "record_id_list": []interface{}{"rec_1"}, + "update": map[string]interface{}{"Status": "Done"}, + }, + }, + }) + if err := runShortcut(t, BaseRecordBatchUpdate, []string{"+record-batch-update", "--base-token", "app_x", "--table-id", "tbl_x", "--json", `{"record_id_list":["rec_1"],"patch":{"Status":"Done"}}`}, factory, stdout); err != nil { + t.Fatalf("err=%v", err) + } + if got := stdout.String(); !strings.Contains(got, `"record_id_list"`) || !strings.Contains(got, `"update"`) || !strings.Contains(got, `"Done"`) { + t.Fatalf("stdout=%s", got) + } + }) + + t.Run("batch update passthrough", func(t *testing.T) { + factory, stdout, reg := newExecuteFactory(t) + updateStub := &httpmock.Stub{ + Method: "POST", + URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/records/batch_update", + Body: map[string]interface{}{ + "code": 0, + "data": map[string]interface{}{ + "record_id_list": []interface{}{"rec_1"}, + }, + }, + } + reg.Register(updateStub) + if err := runShortcut(t, BaseRecordBatchUpdate, []string{"+record-batch-update", "--base-token", "app_x", "--table-id", "tbl_x", "--json", `{"record_id_list":["rec_1"],"patch":{"Name":"Alice","Status":"Done"}}`}, factory, stdout); err != nil { + t.Fatalf("err=%v", err) + } + if got := stdout.String(); !strings.Contains(got, `"record_id_list"`) || !strings.Contains(got, `"rec_1"`) { + t.Fatalf("stdout=%s", got) + } + body := string(updateStub.CapturedBody) + if !strings.Contains(body, `"record_id_list":["rec_1"]`) || !strings.Contains(body, `"patch":{"Name":"Alice","Status":"Done"}`) { + t.Fatalf("request body=%s", body) + } + }) + t.Run("delete", func(t *testing.T) { factory, stdout, reg := newExecuteFactory(t) reg.Register(&httpmock.Stub{ diff --git a/shortcuts/base/base_shortcuts_test.go b/shortcuts/base/base_shortcuts_test.go index 8271f3cff..e3289e851 100644 --- a/shortcuts/base/base_shortcuts_test.go +++ b/shortcuts/base/base_shortcuts_test.go @@ -132,7 +132,7 @@ func TestShortcutsCatalog(t *testing.T) { "+table-list", "+table-get", "+table-create", "+table-update", "+table-delete", "+field-list", "+field-get", "+field-create", "+field-update", "+field-delete", "+field-search-options", "+view-list", "+view-get", "+view-create", "+view-delete", "+view-get-filter", "+view-set-filter", "+view-get-visible-fields", "+view-set-visible-fields", "+view-get-group", "+view-set-group", "+view-get-sort", "+view-set-sort", "+view-get-timebar", "+view-set-timebar", "+view-get-card", "+view-set-card", "+view-rename", - "+record-list", "+record-search", "+record-get", "+record-upsert", "+record-upload-attachment", "+record-delete", + "+record-list", "+record-search", "+record-get", "+record-upsert", "+record-batch-create", "+record-batch-update", "+record-upload-attachment", "+record-delete", "+record-history-list", "+base-get", "+base-copy", "+base-create", "+role-create", "+role-delete", "+role-update", "+role-list", "+role-get", "+advperm-enable", "+advperm-disable", @@ -265,7 +265,6 @@ func TestBaseRecordValidate(t *testing.T) { t.Fatalf("record upsert validate should be nil for API passthrough") } } - func TestBaseViewValidate(t *testing.T) { ctx := context.Background() if err := BaseViewCreate.Validate(ctx, newBaseTestRuntime(map[string]string{"base-token": "b", "table-id": "tbl_1", "json": `{"name":"Main"}`}, nil, nil)); err != nil { diff --git a/shortcuts/base/record_batch_create.go b/shortcuts/base/record_batch_create.go new file mode 100644 index 000000000..623a2caaf --- /dev/null +++ b/shortcuts/base/record_batch_create.go @@ -0,0 +1,32 @@ +// Copyright (c) 2026 Lark Technologies Pte. Ltd. +// SPDX-License-Identifier: MIT + +package base + +import ( + "context" + + "github.com/larksuite/cli/shortcuts/common" +) + +var BaseRecordBatchCreate = common.Shortcut{ + Service: "base", + Command: "+record-batch-create", + Description: "Batch create records", + Risk: "write", + Scopes: []string{"base:record:create"}, + AuthTypes: authTypes(), + Flags: []common.Flag{ + baseTokenFlag(true), + tableRefFlag(true), + {Name: "json", Desc: "batch create JSON object", Required: true}, + }, + Tips: []string{ + `Example: --json '{"fields":["Title","Status"],"rows":[["Task A","Open"],["Task B","Done"]]}'`, + "Agent hint: use the lark-base skill's record-batch-create guide for usage and limits.", + }, + DryRun: dryRunRecordBatchCreate, + Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { + return executeRecordBatchCreate(runtime) + }, +} diff --git a/shortcuts/base/record_batch_update.go b/shortcuts/base/record_batch_update.go new file mode 100644 index 000000000..a06fb177e --- /dev/null +++ b/shortcuts/base/record_batch_update.go @@ -0,0 +1,32 @@ +// Copyright (c) 2026 Lark Technologies Pte. Ltd. +// SPDX-License-Identifier: MIT + +package base + +import ( + "context" + + "github.com/larksuite/cli/shortcuts/common" +) + +var BaseRecordBatchUpdate = common.Shortcut{ + Service: "base", + Command: "+record-batch-update", + Description: "Batch update records", + Risk: "write", + Scopes: []string{"base:record:update"}, + AuthTypes: authTypes(), + Flags: []common.Flag{ + baseTokenFlag(true), + tableRefFlag(true), + {Name: "json", Desc: "batch update JSON object", Required: true}, + }, + Tips: []string{ + `Example: --json '{"record_id_list":["recXXX"],"patch":{"Status":"Done"}}'`, + "Agent hint: use the lark-base skill's record-batch-update guide for usage and limits.", + }, + DryRun: dryRunRecordBatchUpdate, + Execute: func(ctx context.Context, runtime *common.RuntimeContext) error { + return executeRecordBatchUpdate(runtime) + }, +} diff --git a/shortcuts/base/record_ops.go b/shortcuts/base/record_ops.go index 294751af5..f91ca5799 100644 --- a/shortcuts/base/record_ops.go +++ b/shortcuts/base/record_ops.go @@ -69,6 +69,26 @@ func dryRunRecordUpsert(_ context.Context, runtime *common.RuntimeContext) *comm Set("table_id", baseTableID(runtime)) } +func dryRunRecordBatchCreate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") + return common.NewDryRunAPI(). + POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_create"). + Body(body). + Set("base_token", runtime.Str("base-token")). + Set("table_id", baseTableID(runtime)) +} + +func dryRunRecordBatchUpdate(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { + pc := newParseCtx(runtime) + body, _ := parseJSONObject(pc, runtime.Str("json"), "json") + return common.NewDryRunAPI(). + POST("/open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_update"). + Body(body). + Set("base_token", runtime.Str("base-token")). + Set("table_id", baseTableID(runtime)) +} + func dryRunRecordDelete(_ context.Context, runtime *common.RuntimeContext) *common.DryRunAPI { return common.NewDryRunAPI(). DELETE("/open-apis/base/v3/bases/:base_token/tables/:table_id/records/:record_id"). @@ -99,6 +119,7 @@ func validateRecordJSON(runtime *common.RuntimeContext) error { func recordListFields(runtime *common.RuntimeContext) []string { return runtime.StrArray("field-id") } + func executeRecordList(runtime *common.RuntimeContext) error { offset := runtime.Int("offset") if offset < 0 { @@ -168,6 +189,36 @@ func executeRecordUpsert(runtime *common.RuntimeContext) error { return nil } +func executeRecordBatchCreate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) + body, err := parseJSONObject(pc, runtime.Str("json"), "json") + if err != nil { + return err + } + result, err := baseV3Raw(runtime, "POST", baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "records", "batch_create"), nil, body) + data, err := handleBaseAPIResult(result, err, "batch create records") + if err != nil { + return err + } + runtime.Out(data, nil) + return nil +} + +func executeRecordBatchUpdate(runtime *common.RuntimeContext) error { + pc := newParseCtx(runtime) + body, err := parseJSONObject(pc, runtime.Str("json"), "json") + if err != nil { + return err + } + result, err := baseV3Raw(runtime, "POST", baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "records", "batch_update"), nil, body) + data, err := handleBaseAPIResult(result, err, "batch update records") + if err != nil { + return err + } + runtime.Out(data, nil) + return nil +} + func executeRecordDelete(runtime *common.RuntimeContext) error { _, err := baseV3Call(runtime, "DELETE", baseV3Path("bases", runtime.Str("base-token"), "tables", baseTableID(runtime), "records", runtime.Str("record-id")), nil, nil) if err != nil { diff --git a/shortcuts/base/shortcuts.go b/shortcuts/base/shortcuts.go index fec6df727..2068e280a 100644 --- a/shortcuts/base/shortcuts.go +++ b/shortcuts/base/shortcuts.go @@ -40,6 +40,8 @@ func Shortcuts() []common.Shortcut { BaseRecordSearch, BaseRecordGet, BaseRecordUpsert, + BaseRecordBatchCreate, + BaseRecordBatchUpdate, BaseRecordUploadAttachment, BaseRecordDelete, BaseRecordHistoryList, diff --git a/skills/lark-base/SKILL.md b/skills/lark-base/SKILL.md index e4e76060b..0ed66538c 100644 --- a/skills/lark-base/SKILL.md +++ b/skills/lark-base/SKILL.md @@ -38,7 +38,7 @@ metadata: - 不要把 `+record-list / +record-search` 当聚合分析引擎 - 不要没读 guide 就直接创建 formula / lookup 字段 - 不要凭自然语言猜表名、字段名、公式表达式里的字段引用 -- 不要把系统字段、formula 字段、lookup 字段当成 `+record-upsert` 的写入目标 +- 不要把系统字段、formula 字段、lookup 字段当成 `+record-upsert / +record-batch-create / +record-batch-update` 的写入目标 - 不要把“本地 Excel / CSV 导入成 Base”误判成 `+base-create`、`+table-create` 或 `+record-upsert`;这一步必须先走 `lark-cli drive +import --type bitable` - 不要在 Base 场景改走 `lark-cli api GET /open-apis/bitable/v1/...` - 不要因为 wiki 解析结果里的 `obj_type=bitable` 就去找 `bitable.*`;在本 CLI 里应继续使用 `lark-cli base +...` @@ -46,10 +46,10 @@ metadata: ## Base 基本心智模型 1. **Base 字段分三类** - - **存储字段**:真实存用户输入的数据,通常适合 `+record-upsert` 写入,例如文本、数字、日期、单选、多选、人员、关联。**附件字段例外**:对 agent 而言,文件上传必须走 `+record-upload-attachment`。 + - **存储字段**:真实存用户输入的数据,通常适合 `+record-upsert / +record-batch-create / +record-batch-update` 写入,例如文本、数字、日期、单选、多选、人员、关联。**附件字段例外**:对 agent 而言,文件上传必须走 `+record-upload-attachment`。 - **系统字段**:平台自动维护,只读,典型包括创建时间、最后更新时间、创建人、修改人、自动编号。 - **计算字段**:通过表达式或跨表规则推导,只读,典型包括 **公式字段(formula)** 和 **查找引用字段(lookup)**。 -2. **写记录前先判断字段类别** — 只有存储字段可直接写;公式 / lookup / 创建时间 / 更新时间 / 创建人 / 修改人 / 自动编号都应视为只读输出字段,不能拿来做 `+record-upsert` 入参。 +2. **写记录前先判断字段类别** — 只有存储字段可直接写;公式 / lookup / 创建时间 / 更新时间 / 创建人 / 修改人 / 自动编号都应视为只读输出字段,不能拿来做 `+record-upsert / +record-batch-create / +record-batch-update` 入参。 3. **Base 不只是存表数据,也能内建计算** — 用户提出“统计、比较、排名、文本拼接、日期差、跨表汇总、状态判断”等需求时,不能默认导出数据后手算;要先判断是否应通过 `+data-query` 或公式字段在 Base 内完成。 ## 分析路径决策 @@ -109,7 +109,7 @@ metadata: ## 核心规则 -1. **只使用原子命令** — 使用 `+table-list / +table-get / +field-create / +record-upsert / +view-set-filter / +record-history-list / +base-get` 这类一命令一动作的写法,不使用旧聚合式 `+table / +field / +record / +view / +history / +workspace` +1. **只使用原子命令** — 使用 `+table-list / +table-get / +field-create / +record-upsert / +record-batch-create / +record-batch-update / +view-set-filter / +record-history-list / +base-get` 这类一命令一动作的写法,不使用旧聚合式 `+table / +field / +record / +view / +history / +workspace` 2. **写记录前先读字段结构** — 先调用 `+field-list` 获取字段结构,再读 [lark-base-shortcut-record-value.md](references/lark-base-shortcut-record-value.md) 确认各字段类型的写入值格式 3. **写字段前先看字段属性规范** — 先读 [lark-base-shortcut-field-properties.md](references/lark-base-shortcut-field-properties.md) 确认 `+field-create/+field-update` 的 JSON 结构 4. **筛选查询按场景执行** — 先读 [lark-base-view-set-filter.md](references/lark-base-view-set-filter.md)、[lark-base-record-list.md](references/lark-base-record-list.md)、[lark-base-record-search.md](references/lark-base-record-search.md);默认优先 `+record-list`,仅当用户提供明确搜索关键词时使用 `+record-search`;视图筛选读取用 `+view-set-filter` + `+record-list` @@ -143,6 +143,8 @@ metadata: | 关键词搜索记录 | `lark-cli base +record-search` | 透传搜索参数;用于关键词检索,不用于聚合分析 | | 列表 / 获取记录 | `lark-cli base +record-list` / `+record-get` | 原子命令,如果需要`聚合计算`,`分组统计` 推荐走 `+data-query` | | 创建 / 更新记录 | `lark-cli base +record-upsert` | `--table-id [--record-id] --json` | +| 批量创建记录 | `lark-cli base +record-batch-create` | 适合大量创建写入(如 CSV/Excel 导入);先按 record-value 规范整理为 `json.fields + json.rows` | +| 批量更新指定记录 | `lark-cli base +record-batch-update` | `--table-id --json`(`json.record_id_list + json.patch`) | | 聚合分析 / 比较排序 / 求最值 / 筛选统计 | `lark-cli base +data-query` | 不要用 `+record-list / +record-search` 拉全量数据再手动计算,需使用 `+data-query` 走服务端计算 | | 配置 / 查询视图 | `lark-cli base +view-*` | `list/get/create/delete/get-*/set-*/rename` | | 查看记录历史 | `lark-cli base +record-history-list` | 按表和记录查询变更历史 | @@ -169,6 +171,7 @@ metadata: - **记录读取字段筛选**:`+record-list` 支持重复传参 `--field-id` 做字段筛选 - **`+record-list / +record-search` 选择规则**:优先使用 `+record-list`;仅当用户给出明确搜索关键词时,才使用 `+record-search` - **`+record-search` 使用规则**:仅通过 `--json` 传搜索请求体;`keyword/search_fields/offset/limit` 等字段合法性由 API 侧按 schema 校验 +- **`+record-batch-create` 适用边界**:优先用于大量创建写入(如 CSV/Excel 导入)。当输入是长表格或长文本时,先按 [lark-base-shortcut-record-value.md](references/lark-base-shortcut-record-value.md) 做字段映射和类型规范化,再组装 `fields + rows` 调用命令写入 - **字段可写性先判断**:存储字段才可写;公式 / lookup / 系统字段默认只读,写记录时应跳过 - **公式能力要主动想到**:用户说“算一下”“生成标签”“判断是否异常”“跨表汇总”“按日期差预警”时,要先判断是否应该建公式字段,而不是只返回手工分析方案 - **lookup 不是默认首选**:lookup 只在用户明确要求或确实更适合固定查找模型时使用;常规计算、跨表聚合和条件判断优先 formula @@ -277,9 +280,11 @@ https://{domain}/base/{base-token}?table={table-id}&view={view-id} ## 参考文档 -- [lark-base-shortcut-field-properties.md](references/lark-base-shortcut-field-properties.md) — `+field-create/+field-update` JSON 规范(推荐) +- [lark-base-shortcut-field-properties.md](references/lark-base-shortcut-field-properties.md) — `+field-create/+field-update` 调用前必看,各类型 field JSON 规范 - [role-config.md](references/role-config.md) — 角色权限配置详解 -- [lark-base-shortcut-record-value.md](references/lark-base-shortcut-record-value.md) — `+record-upsert` 值格式规范(推荐) +- [lark-base-shortcut-record-value.md](references/lark-base-shortcut-record-value.md) — record 写入(`+record-upsert / +record-batch-create / +record-batch-update`)调用前必看,各类型 record JSON 规范 +- [lark-base-record-batch-create.md](references/lark-base-record-batch-create.md) — `+record-batch-create` 用法与 `--json` 结构 +- [lark-base-record-batch-update.md](references/lark-base-record-batch-update.md) — `+record-batch-update` 用法与 `--json` 结构 - [formula-field-guide.md](references/formula-field-guide.md) — formula 字段写法、函数约束、CurrentValue 规则、跨表计算模式(强烈推荐) - [lookup-field-guide.md](references/lookup-field-guide.md) — lookup 字段配置规则、where/aggregate 约束、与 formula 的取舍 - [lark-base-view-set-filter.md](references/lark-base-view-set-filter.md) — 视图筛选配置 @@ -307,7 +312,7 @@ https://{domain}/base/{base-token}?table={table-id}&view={view-id} |----------|------| | [`table commands`](references/lark-base-table.md) | `+table-list / +table-get / +table-create / +table-update / +table-delete` | | [`field commands`](references/lark-base-field.md) | `+field-list / +field-get / +field-create / +field-update / +field-delete / +field-search-options` | -| [`record commands`](references/lark-base-record.md) | `+record-search / +record-list / +record-get / +record-upsert / +record-upload-attachment / +record-delete` | +| [`record commands`](references/lark-base-record.md) | `+record-search / +record-list / +record-get / +record-upsert / +record-batch-create / +record-batch-update / +record-upload-attachment / +record-delete` | | [`view commands`](references/lark-base-view.md) | `+view-list / +view-get / +view-create / +view-delete / +view-get-* / +view-set-* / +view-rename` | | [`data-query commands`](references/lark-base-data-query.md) | `+data-query` | | [`history commands`](references/lark-base-history.md) | `+record-history-list` | diff --git a/skills/lark-base/references/lark-base-record-batch-create.md b/skills/lark-base/references/lark-base-record-batch-create.md new file mode 100644 index 000000000..803883c25 --- /dev/null +++ b/skills/lark-base/references/lark-base-record-batch-create.md @@ -0,0 +1,76 @@ +# base +record-batch-create + +> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。 + +批量创建记录。 + +## 适用场景(重点) + +- 适合大量创建写入场景,例如导入 CSV / Excel、外部系统一次性写入新数据。 +- 当输入是长表格或长文本数据时,先按 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) 做字段映射和类型规范化,再组装 `fields + rows` 调用本命令写入。 + +## 推荐命令 + +```bash +lark-cli base +record-batch-create \ + --base-token XXXXXX \ + --table-id tblXXX \ + --json '{"fields":["标题","状态"],"rows":[["任务 A","Open"],["任务 B","Done"]]}' +``` + +```bash +lark-cli base +record-batch-create \ + --base-token XXXXXX \ + --table-id tblXXX \ + --json @batch-create.json +``` + +## 参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `--base-token ` | 是 | Base Token | +| `--table-id ` | 是 | 表 ID 或表名 | +| `--json ` | 是 | 批量创建请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@` 从文件读取 | + +## API 入参详情 + +**HTTP 方法和路径:** + +```http +POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_create +``` + +## `--json` 结构 + +对象形态:`{"fields":[...],"rows":[...]}`。 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `fields` | `string[]` | 是 | 字段 ID 或字段名数组 | +| `rows` | `any[][]` | 是 | 二维数组,每一行按 `fields` 同序给值;单次最多 200 行 | + +## 返回重点 + +`data` 为多行二维数组,与 `+record-list` 返回的多行数据结构一致(按 `fields` 列顺序对齐)。 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `fields` | `string[]` | 返回的字段名数组 | +| `field_id_list` | `string[]` | 返回的字段 ID 数组 | +| `record_id_list` | `string[]` | 新创建记录 ID 列表 | +| `data` | `any[][]` | 与 `fields` 对齐的多行数据 | +| `ignored_fields` | `array` | 可选,表示被忽略的字段信息 | + +## 坑点 + +- ⚠️ `--json` 必须是对象。 +- ⚠️ 写 `rows` 前必须先阅读 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md),按字段类型填值,禁止按自然语言猜测 value 结构。 +- ⚠️ `fields` 与 `rows` 列顺序必须一一对应。 +- ⚠️ 空单元格可以显式用 `null` 填充。 +- ⚠️ 单次最多 200 行,超出需分批写入。 + +## 参考 + +- [lark-base-record.md](lark-base-record.md) — record 索引页 +- [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) — 记录值格式规范 diff --git a/skills/lark-base/references/lark-base-record-batch-update.md b/skills/lark-base/references/lark-base-record-batch-update.md new file mode 100644 index 000000000..7014e2dfa --- /dev/null +++ b/skills/lark-base/references/lark-base-record-batch-update.md @@ -0,0 +1,71 @@ +# base +record-batch-update (batch update) + +> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。 + +批量更新记录(将同一份 `patch` 批量应用到一批 `record_id_list`)。 + +## 推荐命令 + +```bash +lark-cli base +record-batch-update \ + --base-token XXXXXX \ + --table-id tblXXX \ + --json '{"record_id_list":["recXXX"],"patch":{"field_id_or_name":"value"}}' +``` + +```bash +lark-cli base +record-batch-update \ + --base-token XXXXXX \ + --table-id tblXXX \ + --json @batch-update.json +``` + +## 参数 + +| 参数 | 必填 | 说明 | +|------|------|------| +| `--base-token ` | 是 | Base Token | +| `--table-id ` | 是 | 表 ID 或表名 | +| `--json ` | 是 | 批量更新请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@` 从文件读取 | + +## 生成 `patch` 前必看 + +- 先阅读 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md),按字段类型构造 `patch` 的 value,避免类型不匹配。 + +## API 入参详情 + +**HTTP 方法和路径:** + +```http +POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_update +``` + +## `--json` 结构 + +对象形态:`{"record_id_list":[...],"patch":{...}}`。 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `record_id_list` | `string[]` | 是 | 要更新的记录 ID 列表(单次最多 200 条) | +| `patch` | `object` | 是 | 同一份字段更新对象,会应用到 `record_id_list` 内所有记录 | + +## 返回重点 + +返回结构如下(其中 `update` 可与 `+record-list` 的单行字段对象结构对齐): + +| 字段 | 类型 | 说明 | +|------|------|------| +| `record_id_list` | `string[]` | 本次更新到的记录 ID 列表 | +| `update` | `object` | 本次应用的字段更新结果;可能为空对象 | +| `ignored_fields` | `{id,name,reason}[]` | 可选,被忽略字段信息 | + +## 坑点 + +- ⚠️ `--json` 必须是对象。 +- ⚠️ 该接口是“同值批量更新”:同一请求内所有 `record_id_list` 都会应用同一份 `patch`。 +- ⚠️ `record_id_list` 最大 200 条,超过会被接口校验拒绝。 +- ⚠️ 命令不会自动做字段/行映射转换,传什么就发什么。 + +## 参考 + +- [lark-base-record.md](lark-base-record.md) — record 索引页 diff --git a/skills/lark-base/references/lark-base-record.md b/skills/lark-base/references/lark-base-record.md index 0546ac7a4..3d82352b6 100644 --- a/skills/lark-base/references/lark-base-record.md +++ b/skills/lark-base/references/lark-base-record.md @@ -12,6 +12,8 @@ record 相关命令索引。 | [lark-base-record-list.md](lark-base-record-list.md) | `+record-list` | 分页列记录 | | [lark-base-record-get.md](lark-base-record-get.md) | `+record-get` | 获取单条记录 | | [lark-base-record-upsert.md](lark-base-record-upsert.md) | `+record-upsert` | 创建或更新记录 | +| [lark-base-record-batch-create.md](lark-base-record-batch-create.md) | `+record-batch-create` | 按 `fields/rows` 批量创建记录 | +| [lark-base-record-batch-update.md](lark-base-record-batch-update.md) | `+record-batch-update` | 批量更新记录 | | [lark-base-record-upload-attachment.md](lark-base-record-upload-attachment.md) | `+record-upload-attachment` | 上传本地文件到附件字段并更新记录 | | [lark-base-record-delete.md](lark-base-record-delete.md) | `+record-delete` | 删除记录 |