mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 17:45:15 +08:00
docs(base): refine record cell value guidance (#636)
* refactor(base): enforce field-map record upsert input 1. Reject top-level fields wrappers in base +record-upsert input and keep request bodies as field maps. 2. Replace record-upsert tests with Map<FieldNameOrID, CellValue> input and assert the outgoing body has no fields wrapper. 3. Consolidate Base record value documentation around lark-base-cell-value and update record command references. * refactor(base): use common record JSON parsing for upsert 1. Remove the dedicated record-upsert parser and restore the shared record JSON object validation path. 2. Keep record-upsert dry-run and execution as raw JSON object passthrough. 3. Drop the test assertion that rejected a top-level fields key for record-upsert. * docs(base): refine record cell value guidance 1. Align record CellValue examples with live behavior for date, URL, user, link, select, numeric styles, and readonly fields. 2. Remove misleading user_id_type and execution identity prompts from record-writing guidance. 3. Keep record JSON file input guidance generic and avoid documenting environment-specific stdin or path limits.
This commit is contained in:
@@ -584,17 +584,25 @@ func TestBaseTableExecuteUpdate(t *testing.T) {
|
||||
|
||||
func TestBaseRecordExecuteUpsertUpdate(t *testing.T) {
|
||||
factory, stdout, reg := newExecuteFactory(t)
|
||||
reg.Register(&httpmock.Stub{
|
||||
updateStub := &httpmock.Stub{
|
||||
Method: "PATCH",
|
||||
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/records/rec_x",
|
||||
Body: map[string]interface{}{
|
||||
"code": 0,
|
||||
"data": map[string]interface{}{"record_id": "rec_x", "fields": map[string]interface{}{"Name": "Alice"}},
|
||||
},
|
||||
})
|
||||
if err := runShortcut(t, BaseRecordUpsert, []string{"+record-upsert", "--base-token", "app_x", "--table-id", "tbl_x", "--record-id", "rec_x", "--json", `{"fields":{"Name":"Alice"}}`}, factory, stdout); err != nil {
|
||||
}
|
||||
reg.Register(updateStub)
|
||||
if err := runShortcut(t, BaseRecordUpsert, []string{"+record-upsert", "--base-token", "app_x", "--table-id", "tbl_x", "--record-id", "rec_x", "--json", `{"Name":"Alice"}`}, factory, stdout); err != nil {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
body := decodeCapturedJSONBody(t, updateStub)
|
||||
if body["Name"] != "Alice" {
|
||||
t.Fatalf("request body=%v", body)
|
||||
}
|
||||
if _, ok := body["fields"]; ok {
|
||||
t.Fatalf("request body must not contain fields wrapper: %v", body)
|
||||
}
|
||||
if got := stdout.String(); !strings.Contains(got, `"updated": true`) || !strings.Contains(got, `"rec_x"`) {
|
||||
t.Fatalf("stdout=%s", got)
|
||||
}
|
||||
@@ -1018,17 +1026,25 @@ func TestBaseRecordExecuteReadCreateDelete(t *testing.T) {
|
||||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
factory, stdout, reg := newExecuteFactory(t)
|
||||
reg.Register(&httpmock.Stub{
|
||||
createStub := &httpmock.Stub{
|
||||
Method: "POST",
|
||||
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/records",
|
||||
Body: map[string]interface{}{
|
||||
"code": 0,
|
||||
"data": map[string]interface{}{"record_id": "rec_new", "fields": map[string]interface{}{"Name": "Alice"}},
|
||||
},
|
||||
})
|
||||
if err := runShortcut(t, BaseRecordUpsert, []string{"+record-upsert", "--base-token", "app_x", "--table-id", "tbl_x", "--json", `{"fields":{"Name":"Alice"}}`}, factory, stdout); err != nil {
|
||||
}
|
||||
reg.Register(createStub)
|
||||
if err := runShortcut(t, BaseRecordUpsert, []string{"+record-upsert", "--base-token", "app_x", "--table-id", "tbl_x", "--json", `{"Name":"Alice"}`}, factory, stdout); err != nil {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
body := decodeCapturedJSONBody(t, createStub)
|
||||
if body["Name"] != "Alice" {
|
||||
t.Fatalf("request body=%v", body)
|
||||
}
|
||||
if _, ok := body["fields"]; ok {
|
||||
t.Fatalf("request body must not contain fields wrapper: %v", body)
|
||||
}
|
||||
if got := stdout.String(); !strings.Contains(got, `"created": true`) || !strings.Contains(got, `"rec_new"`) {
|
||||
t.Fatalf("stdout=%s", got)
|
||||
}
|
||||
|
||||
@@ -252,6 +252,7 @@ func TestBaseTableValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBaseRecordValidate(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
if BaseRecordList.Validate != nil {
|
||||
t.Fatalf("record list validate should be nil for repeatable --field-id")
|
||||
}
|
||||
@@ -264,6 +265,9 @@ func TestBaseRecordValidate(t *testing.T) {
|
||||
if BaseRecordUpsert.Validate == nil {
|
||||
t.Fatalf("record upsert validate should reject invalid JSON before dry-run")
|
||||
}
|
||||
if err := BaseRecordUpsert.Validate(ctx, newBaseTestRuntime(map[string]string{"base-token": "b", "table-id": "tbl_1", "json": `{"Name":"Alice"}`}, nil, nil)); err != nil {
|
||||
t.Fatalf("record upsert map validate err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBaseViewValidate(t *testing.T) {
|
||||
|
||||
@@ -572,30 +572,6 @@ func resolveViewRef(views []map[string]interface{}, ref string) (map[string]inte
|
||||
return nil, fmt.Errorf("view %q not found", ref)
|
||||
}
|
||||
|
||||
func normalizeRecordInputs(raw string) ([]map[string]interface{}, error) {
|
||||
var records []interface{}
|
||||
if err := common.ParseJSON([]byte(raw), &records); err != nil {
|
||||
return nil, fmt.Errorf("--records invalid JSON, must be a record array")
|
||||
}
|
||||
result := make([]map[string]interface{}, 0, len(records))
|
||||
for idx, item := range records {
|
||||
record, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("record %d must be an object", idx+1)
|
||||
}
|
||||
if fields, ok := record["fields"].(map[string]interface{}); ok {
|
||||
normalized := map[string]interface{}{"fields": fields}
|
||||
if recordID, ok := record["record_id"].(string); ok && recordID != "" {
|
||||
normalized["record_id"] = recordID
|
||||
}
|
||||
result = append(result, normalized)
|
||||
continue
|
||||
}
|
||||
result = append(result, map[string]interface{}{"fields": record})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func chunkRecords(records []map[string]interface{}, size int) [][]map[string]interface{} {
|
||||
if size <= 0 {
|
||||
size = 1
|
||||
|
||||
@@ -189,13 +189,7 @@ func TestBaseV3Helpers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRecordAndChunkHelpers(t *testing.T) {
|
||||
records, err := normalizeRecordInputs(`[{"record_id":"rec_1","fields":{"Name":"Alice"}},{"Name":"Bob"}]`)
|
||||
if err != nil || len(records) != 2 {
|
||||
t.Fatalf("records=%v err=%v", records, err)
|
||||
}
|
||||
if _, err := normalizeRecordInputs(`[1]`); err == nil || !strings.Contains(err.Error(), "must be an object") {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
records := []map[string]interface{}{{"record_id": "rec_1"}, {"record_id": "rec_2"}}
|
||||
if len(chunkRecords(records, 1)) != 2 || len(chunkStringIDs([]string{"a", "b", "c"}, 2)) != 2 {
|
||||
t.Fatalf("chunk helpers mismatch")
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ var BaseRecordBatchCreate = common.Shortcut{
|
||||
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.",
|
||||
"Agent hint: use lark-base-cell-value.md as the source of truth for each CellValue.",
|
||||
},
|
||||
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
||||
return validateRecordJSON(runtime)
|
||||
|
||||
@@ -24,6 +24,7 @@ var BaseRecordBatchUpdate = common.Shortcut{
|
||||
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.",
|
||||
"Agent hint: use lark-base-cell-value.md as the source of truth for each patch CellValue.",
|
||||
},
|
||||
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
|
||||
return validateRecordJSON(runtime)
|
||||
|
||||
@@ -20,7 +20,7 @@ var BaseRecordUpsert = common.Shortcut{
|
||||
baseTokenFlag(true),
|
||||
tableRefFlag(true),
|
||||
recordRefFlag(false),
|
||||
{Name: "json", Desc: "record JSON object", Required: true},
|
||||
{Name: "json", Desc: "record JSON object: Map<FieldNameOrID, CellValue>", Required: true},
|
||||
},
|
||||
Tips: []string{
|
||||
`Example: --json '{"Name":"Alice"}'`,
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
- `lark-cli base table.records create` ✅
|
||||
- `lark-cli base records create` ❌
|
||||
2. **优先使用 Shortcut** — 有 Shortcut 的操作不要手拼原生 API
|
||||
3. **写记录前** — 先调用 `table.fields list` 获取字段 `type/ui_type`,再读 [lark-base-shortcut-record-value.md](../../skills/lark-base/references/lark-base-shortcut-record-value.md) 确认每个字段类型的值格式
|
||||
3. **写记录前** — 先调用 `table.fields list` 获取字段 `type/ui_type`,再读 [lark-base-cell-value.md](../../skills/lark-base/references/lark-base-cell-value.md);该文档是 CellValue 的 source of truth
|
||||
4. **写字段前** — 先读 [lark-base-shortcut-field-properties.md](../../skills/lark-base/references/lark-base-shortcut-field-properties.md) 确认字段类型的 `property` 结构
|
||||
5. **筛选查询前** — 先读 [lark-base-view-set-filter.md](../../skills/lark-base/references/lark-base-view-set-filter.md),当前 `base/v3` 通过 `view.filter update + table.records list` 组合完成筛选读取
|
||||
6. **批量上限 500 条/次** — 同一表建议串行写入,并在批次间延迟 0.5–1 秒
|
||||
6. **批量上限 200 条/次** — 同一表建议串行写入,并在批次间延迟 0.5–1 秒
|
||||
7. **改名和删除按明确意图执行** — 视图重命名这类低风险改名操作,目标和新名称明确时可直接执行;删除记录 / 字段 / 表时,只要用户已经明确要求删除且目标明确,也可直接执行,不需要再补一次确认
|
||||
8. **不要走旧 bitable 路径** — Base 场景不要调用 `lark-cli api GET /open-apis/bitable/v1/...`;即使 wiki 解析结果是 `obj_type=bitable`,后续也应继续使用 `lark-cli base ...`
|
||||
9. **不要把本地文件导入误判成 Base 表内操作** — 如果目标是“把 Excel / CSV / `.base` 快照导入成 Base / 多维表格”,必须先走 `lark-cli drive +import --type bitable`;只有导入完成后,才回到 `lark-cli base ...`
|
||||
@@ -34,13 +34,11 @@
|
||||
|
||||
- **Base token 口径统一**:无论 Shortcut 还是原生 API,都统一使用 `base_token`
|
||||
- **附件字段**:上传本地文件时只能走 `lark-cli base +record-upload-attachment`
|
||||
- **人员字段 / 用户字段**:调试时注意 `user_id_type` 与执行身份(user / bot)差异
|
||||
- **能力边界**:当前 `base/v3` 原生 spec 以单表 / 单记录 / 视图筛选配置为主,批量写入和旧 `search` 场景优先走 unified Shortcut 组合能力
|
||||
- **视图重命名确认规则**:用户已经明确“把哪个视图改成什么名字”时,执行 `table.views patch` / 对应 shortcut 直接改名即可,不需要再补一句确认
|
||||
- **删除确认规则(记录 / 字段 / 表)**:执行 `table.records delete / table.fields delete / tables delete` 或对应 shortcut 时,如果用户已经明确要求删除且目标明确,可以直接执行;只有目标不明确时才先追问
|
||||
- **创建 / 复制 Base 的友好性规则**:创建或复制 Base 时,`folder_token`、`time_zone`、复制时的新名称都属于可选项;用户没特别要求时不要为这些参数额外打断
|
||||
- **创建 / 复制 Base 的结果返回规范**:成功后必须主动返回新 Base 的 token;如果返回结果里带可访问链接(如 `base.url`),也要一并返回
|
||||
- **附件字段本地文件上传**:只能使用 `lark-cli base +record-upload-attachment`
|
||||
|
||||
## Wiki 链接特殊处理(特别关键!)
|
||||
|
||||
@@ -103,18 +101,18 @@ lark-cli wiki spaces.get_node --params '{"token":"Pgrrwvr***********UnRb"}'
|
||||
|
||||
| 错误码 | 含义 | 解决方案 |
|
||||
|--------|------|---------|
|
||||
| 1254064 | 日期格式错误 | 用毫秒时间戳,非字符串 / 秒级 |
|
||||
| 1254068 | 超链接格式错误 | 用 `{text, link}` 对象 |
|
||||
| 1254066 | 人员字段错误 | 用 `[{id:"ou_xxx"}]`,并确认 `user_id_type` |
|
||||
| 1254064 | 日期格式错误 | 传 `YYYY-MM-DD HH:mm:ss` 字符串,不要写相对时间 |
|
||||
| 1254068 | 超链接格式错误 | `"https://example.com"` 或 `"[文本](https://example.com)"` |
|
||||
| 1254066 | 人员字段错误 | `[{ "id": "ou_xxx" }]` |
|
||||
| 1254045 | 字段名不存在 | 检查字段名(含空格、大小写) |
|
||||
| 1254015 | 字段值类型不匹配 | 先 list 字段,再按类型构造 |
|
||||
| `param baseToken is invalid` / `base_token invalid` | 把 wiki token、workspace token 或其他 token 当成了 `base_token` | 如果输入来自 `/wiki/...`,先查 `wiki.spaces.get_node`;当 `obj_type=bitable` 时,用 `node.obj_token` 作为 `base_token` 重试,不要改走 `bitable/v1` |
|
||||
| 1254104 | 批量超 500 条 | 分批调用 |
|
||||
| 1254104 | 批量超 200 条 | 分批调用 |
|
||||
| 1254291 | 并发写冲突 | 串行写入 + 批次间延迟 |
|
||||
|
||||
## 参考文档
|
||||
|
||||
- [lark-base-shortcut-field-properties.md](../../skills/lark-base/references/lark-base-shortcut-field-properties.md) — 字段类型 property 配置
|
||||
- [lark-base-shortcut-record-value.md](../../skills/lark-base/references/lark-base-shortcut-record-value.md) — 记录值格式详解
|
||||
- [lark-base-shortcut-field-properties.md](../../skills/lark-base/references/lark-base-shortcut-field-properties.md) — 字段类型 JSON 配置
|
||||
- [lark-base-cell-value.md](../../skills/lark-base/references/lark-base-cell-value.md) — CellValue source of truth
|
||||
- [lark-base-view-set-filter.md](../../skills/lark-base/references/lark-base-view-set-filter.md) — 查询筛选指南(filter / operator / sort / 分页)
|
||||
- [examples.md](../../skills/lark-base/references/examples.md) — 完整操作示例(建表、筛选、更新)
|
||||
|
||||
@@ -103,7 +103,7 @@ metadata:
|
||||
| 命令 | 用途 / 何时使用 | 必读 reference | 路由提醒 |
|
||||
|------|------------------|----------------|----------|
|
||||
| `+record-search / +record-list / +record-get` | 按关键词检索记录、读取记录明细 / 分页导出,或获取单条记录详情 | [`lark-base-record-search.md`](references/lark-base-record-search.md)、[`lark-base-record-list.md`](references/lark-base-record-list.md)、[`lark-base-record-get.md`](references/lark-base-record-get.md) | 默认优先 `+record-list`;仅当用户提供明确搜索关键词时使用 `+record-search`;取数不用来做聚合分析;`--limit` 最大 `200`;仅在用户明确需要时继续翻页;`+record-list` 只能串行执行 |
|
||||
| `+record-upsert / +record-batch-create / +record-batch-update` | 创建、更新或批量写入记录 | [`lark-base-record-upsert.md`](references/lark-base-record-upsert.md)、[`lark-base-record-batch-create.md`](references/lark-base-record-batch-create.md)、[`lark-base-record-batch-update.md`](references/lark-base-record-batch-update.md)、[`lark-base-shortcut-record-value.md`](references/lark-base-shortcut-record-value.md) | 写前先 `+field-list`;只写存储字段;`+record-batch-update` 为同值更新(同一 patch 应用到多条记录);批量单次不超过 `200` 条;附件不要走这里 |
|
||||
| `+record-upsert / +record-batch-create / +record-batch-update` | 创建、更新或批量写入记录 | [`lark-base-record-upsert.md`](references/lark-base-record-upsert.md)、[`lark-base-record-batch-create.md`](references/lark-base-record-batch-create.md)、[`lark-base-record-batch-update.md`](references/lark-base-record-batch-update.md)、[`lark-base-cell-value.md`](references/lark-base-cell-value.md) | 写前先 `+field-list`;只写存储字段;`+record-batch-update` 为同值更新(同一 patch 应用到多条记录);批量单次不超过 `200` 条;附件不要走这里 |
|
||||
| `+record-upload-attachment` | 给已有记录上传附件 | [`lark-base-record-upload-attachment.md`](references/lark-base-record-upload-attachment.md) | 附件上传专用链路,不要用 `+record-upsert` / `+record-batch-*` 伪造附件值 |
|
||||
| `lark-cli docs +media-download` | 下载 Base 附件文件到本地 | [`../lark-doc/references/lark-doc-media-download.md`](../lark-doc/references/lark-doc-media-download.md) | Base 附件的 `file_token` 从 `+record-get` 返回的附件字段数组里取;**不要用 `lark-cli drive +download`**(对 Base 附件返回 403) |
|
||||
| `+record-delete / +record-history-list` | 删除记录,或查询某条记录的变更历史 | [`lark-base-record-delete.md`](references/lark-base-record-delete.md)、[`lark-base-record-history-list.md`](references/lark-base-record-history-list.md) | 删除时用户已明确目标可直接执行并带 `--yes`;历史查询按 `table-id + record-id`,不支持整表扫描;`+record-history-list` 只能串行执行 |
|
||||
@@ -273,10 +273,6 @@ lark-cli auth login --domain base
|
||||
4. 若 bot 身份仍然返回权限错误,**立即停止重试**,根据错误响应按 `lark-shared` 流程引导用户解决(引导去开发者后台开通 scope 或确认资源访问权限)。
|
||||
5. 只有在用户明确要求"用应用身份 / bot 身份操作",才跳过 user 直接使用 `--as bot`。
|
||||
|
||||
**补充说明**:
|
||||
|
||||
- 人员字段 / 用户字段:注意 `user_id_type` 与执行身份(user / bot)差异。
|
||||
|
||||
## 4. 执行规则
|
||||
|
||||
### 4.1 标准执行顺序
|
||||
@@ -293,7 +289,7 @@ lark-cli auth login --domain base
|
||||
1. 先拿结构,再写命令;至少先拿当前表结构,跨表时还要拿目标表结构。
|
||||
2. 不要猜表名、字段名、表达式引用,一律以真实返回为准。
|
||||
3. 只使用原子命令;不要回退到旧的聚合式 `+table / +field / +record / +view / +history / +workspace`。
|
||||
4. 写记录前先读字段结构;先 `+field-list`,再按字段类型构造写入值。
|
||||
4. 写记录前先读字段结构;先 `+field-list`,再按 [`lark-base-cell-value.md`](references/lark-base-cell-value.md) 构造 CellValue。
|
||||
5. 写字段前先看字段属性规范;先读 `lark-base-shortcut-field-properties.md`,再构造 `+field-create / +field-update` 的 JSON。
|
||||
6. 只写可写字段;系统字段、附件字段、`formula`、`lookup` 默认不作为普通记录写入目标。
|
||||
7. 聚合分析与取数分流;统计走 `+data-query`,关键词检索走 `+record-search`,明细走 `+record-list / +record-get`。
|
||||
@@ -323,15 +319,15 @@ lark-cli auth login --domain base
|
||||
|
||||
| 错误 / 现象 | 含义 | 恢复动作 |
|
||||
|-------------|------|----------|
|
||||
| `1254064` | 日期格式错误 | 用毫秒时间戳,非字符串 / 秒级 |
|
||||
| `1254068` | 超链接格式错误 | 用 `{text, link}` 对象 |
|
||||
| `1254066` | 人员字段错误 | 用 `[{id:"ou_xxx"}]`,并确认 `user_id_type` |
|
||||
| `1254064` | 日期格式错误 | 传 `YYYY-MM-DD HH:mm:ss` 字符串,不要写相对时间 |
|
||||
| `1254068` | 超链接格式错误 | `"https://example.com"` 或 `"[文本](https://example.com)"` |
|
||||
| `1254066` | 人员字段错误 | `[{ "id": "ou_xxx" }]` |
|
||||
| `1254045` | 字段名不存在 | 检查字段名(含空格、大小写) |
|
||||
| `1254015` | 字段值类型不匹配 | 先 `+field-list`,再按类型构造 |
|
||||
| `param baseToken is invalid` / `base_token invalid` | 把 wiki token、workspace token 或其他 token 当成了 `base_token` | 如果输入来自 `/wiki/...`,先用 `lark-cli wiki spaces get_node` 取真实 `obj_token`;当 `obj_type=bitable` 时,用 `node.obj_token` 作为 `--base-token` 重试,不要改走 `bitable/v1` |
|
||||
| `not found` 且用户给的是 wiki 链接 | 常见于把 wiki token 当成 base token | 优先回退检查 wiki 解析,而不是改走 `bitable/v1` |
|
||||
| formula / lookup 创建失败 | 指南未读或结构不合法 | 先读 `formula-field-guide.md` / `lookup-field-guide.md`,再按 guide 重建请求 |
|
||||
| 系统字段 / 公式字段写入失败 | 只读字段被当成可写字段 | 改为写存储字段,计算结果交给 formula / lookup / 系统字段自动产出 |
|
||||
| `ignored_fields` / `READONLY` | 只读字段被当成可写字段,常见于系统字段、formula、lookup | 移除只读字段,只写存储字段;计算结果交给 formula / lookup / 系统字段自动产出 |
|
||||
| `1254104` | 批量超 200 条 | 分批调用 |
|
||||
| `1254291` | 并发写冲突 | 串行写入 + 批次间延迟 |
|
||||
| `91403` | 无权限访问该 Base | **不要重试**。按 `lark-shared` 权限不足处理流程引导用户解决权限问题 |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
本文档提供基于 `lark-cli base ...` 的完整示例,覆盖 unified Shortcut 与当前 `base/v3` 原生 API 的常见组合方式。
|
||||
|
||||
> **返回**: [SKILL.md](../SKILL.md) | **参考**: [shortcut 字段 JSON 规范](lark-base-shortcut-field-properties.md) · [shortcut 记录值规范](lark-base-shortcut-record-value.md)
|
||||
> **返回**: [SKILL.md](../SKILL.md) | **参考**: [shortcut 字段 JSON 规范](lark-base-shortcut-field-properties.md) · [CellValue 规范](lark-base-cell-value.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
144
skills/lark-base/references/lark-base-cell-value.md
Normal file
144
skills/lark-base/references/lark-base-cell-value.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# base CellValue 规范(lark-base-cell-value)
|
||||
|
||||
> 适用命令:`lark-cli base +record-upsert`、`lark-cli base +record-batch-create`、`lark-cli base +record-batch-update`
|
||||
|
||||
本文件定义 **shortcut 写记录** 时 `CellValue` 的推荐格式,目标是让 AI 一次写对。不同命令的外层 JSON 形状不同,但每个 cell 都以本文为 source of truth。
|
||||
|
||||
## 1. 顶层规则(必须遵守)
|
||||
|
||||
- `--json` 必须是 JSON 对象。
|
||||
- `+record-upsert`:顶层直接传字段映射:`{"字段名或字段ID": CellValue}`。
|
||||
- `+record-batch-create`:`rows` 是 `CellValue[][]`,列顺序由 `fields` 决定。
|
||||
- `+record-batch-update`:`patch` 是 `Map<FieldNameOrID, CellValue>`,同一份 `patch` 会应用到所有 `record_id_list`。
|
||||
- 一次 payload 里同一字段只用一种 key(字段名或字段 ID),不要重复。
|
||||
- 写入前先 `+field-list` 获取字段 `type/style/multiple`,再构造值。
|
||||
- 需要清空字段时优先传 `null`(字段允许清空时)。
|
||||
|
||||
## 2. 各类型 CellValue
|
||||
|
||||
### 2.1 text / phone / url
|
||||
|
||||
用字符串。URL 字段也传 URL 字符串;普通文本里可以保留 Markdown 风格链接文本,平台会按字段类型处理。
|
||||
|
||||
```json
|
||||
{
|
||||
"标题": "Hello",
|
||||
"联系电话": "1380000000000",
|
||||
"官网": "https://example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 number
|
||||
|
||||
用 JSON number,不要用带单位或千分位的字符串。货币、百分比、进度、评分等数字类字段也按数字写入,展示格式由字段配置决定。
|
||||
|
||||
```json
|
||||
{
|
||||
"工时": 12.5,
|
||||
"预算": 3000,
|
||||
"完成度": 0.65,
|
||||
"评分": 4
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 select(单选/多选)
|
||||
|
||||
单选用选项名字符串;多选用选项名数组。选项名建议与字段配置一致;写入未知选项时平台可能自动新增选项,因此不要把自然语言近义词当成已有选项传入。
|
||||
|
||||
```json
|
||||
{
|
||||
"单选": "Todo",
|
||||
"多选": ["后端", "高优"]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 datetime
|
||||
|
||||
优先用 `YYYY-MM-DD HH:mm:ss` 字符串,这是最稳妥的写法,也和常见 API 输出更容易对齐。不要写相对时间(如“明天上午”)。
|
||||
|
||||
```json
|
||||
{
|
||||
"截止时间": "2026-03-24 10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.5 checkbox
|
||||
|
||||
用 JSON boolean:`true` 或 `false`,不要用 `"true"`、`"是"`、`1`。
|
||||
|
||||
```json
|
||||
{
|
||||
"已完成": true
|
||||
}
|
||||
```
|
||||
|
||||
### 2.6 user
|
||||
|
||||
用对象数组,元素至少包含 `id`。单选/多选人员字段都使用数组;`id` 必须是可被当前 Base 识别的用户 ID,写入前确认字段是否允许多选人员。
|
||||
|
||||
```json
|
||||
{
|
||||
"负责人": [
|
||||
{ "id": "ou_xxx" },
|
||||
{ "id": "ou_xxx2" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.7 link
|
||||
|
||||
用对象数组,元素包含 `id`,值为目标记录的 `record_id`。不要传记录标题;先用 `+record-list` / `+record-search` 找到目标记录 ID。
|
||||
|
||||
```json
|
||||
{
|
||||
"关联任务": [
|
||||
{ "id": "<record_id>" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.8 location
|
||||
|
||||
用对象 `{lng, lat}`,两者都是数字;`lng` 是经度,`lat` 是纬度。
|
||||
|
||||
```json
|
||||
{
|
||||
"坐标": {
|
||||
"lng": 116.397428,
|
||||
"lat": 39.90923
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.9 attachment(不作为普通 CellValue 写入)
|
||||
|
||||
用户要把本地文件加到记录里时,必须使用 `lark-cli base +record-upload-attachment --file <path>` 上传到已有记录。不能用普通记录操作接口来上传附件。
|
||||
|
||||
`+record-get` 返回的附件字段单元格包含 `file_token` 和文件名,可以把 `file_token` 交给 `lark-cli docs +media-download` 进行附件下载。
|
||||
|
||||
## 3. 只读字段(不要写)
|
||||
|
||||
以下字段在写记录时应视为只读:
|
||||
- `auto_number`
|
||||
- `lookup`
|
||||
- `formula`
|
||||
- `created_at` / `updated_at`
|
||||
- `created_by` / `updated_by`
|
||||
|
||||
写入只读字段通常不会更新数据;返回里可能出现 `ignored_fields`,reason 会说明 `READONLY`。看到这种返回时,不要重试同一 payload,应移除只读字段,只写存储字段。
|
||||
|
||||
## 4. 完整示例
|
||||
|
||||
```json
|
||||
{
|
||||
"标题": "Created from shortcut",
|
||||
"状态": "Todo",
|
||||
"标签": ["高优", "外部依赖"],
|
||||
"工时": 8,
|
||||
"截止时间": "2026-03-24 10:00:00",
|
||||
"已完成": false,
|
||||
"负责人": [{ "id": "ou_123" }],
|
||||
"关联任务": [{ "id": "rec_456" }],
|
||||
"坐标": { "lng": 116.397428, "lat": 39.90923 }
|
||||
}
|
||||
```
|
||||
@@ -371,5 +371,5 @@ value 使用预定义关键字机制,第一个元素为字符串常量名称
|
||||
|
||||
- [lark-base](../SKILL.md) — 多维表格全部命令
|
||||
- [lark-shared](../../lark-shared/SKILL.md) — 认证和全局参数
|
||||
- [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) — shortcut 字段值格式规范
|
||||
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|
||||
- [lark-base-shortcut-field-properties.md](lark-base-shortcut-field-properties.md) — shortcut 字段类型与 JSON 结构
|
||||
|
||||
@@ -6,23 +6,16 @@
|
||||
|
||||
## 适用场景(重点)
|
||||
|
||||
- 适合大量创建写入场景,例如导入 CSV / Excel、外部系统一次性写入新数据。
|
||||
- 当输入是长表格或长文本数据时,先按 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) 做字段映射和类型规范化,再组装 `fields + rows` 调用本命令写入。
|
||||
- 适合导入 CSV / Excel、外部系统一次性写入新数据。
|
||||
- 先把输入数据映射到合适的字段类型,再组装 `fields + rows`。
|
||||
|
||||
## 推荐命令
|
||||
|
||||
```bash
|
||||
lark-cli base +record-batch-create \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
lark-cli base +record-batch-create --base-token <base_token> --table-id <table_id> \
|
||||
--json '{"fields":["标题","状态"],"rows":[["任务 A","Open"],["任务 B","Done"]]}'
|
||||
```
|
||||
|
||||
```bash
|
||||
lark-cli base +record-batch-create \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--json @batch-create.json
|
||||
lark-cli base +record-batch-create --base-token <base_token> --table-id <table_id> --json @batch-create.json
|
||||
```
|
||||
|
||||
## 参数
|
||||
@@ -33,44 +26,33 @@ lark-cli base +record-batch-create \
|
||||
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
||||
| `--json <body>` | 是 | 批量创建请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@<file_path>` 从文件读取 |
|
||||
|
||||
## API 入参详情
|
||||
## API
|
||||
|
||||
**HTTP 方法和路径:**
|
||||
|
||||
```http
|
||||
POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_create
|
||||
```
|
||||
`POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_create`
|
||||
|
||||
## `--json` 结构
|
||||
|
||||
本节只说明 `+record-batch-create` 的外层 JSON 形状;CellValue 统一看 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
||||
|
||||
对象形态:`{"fields":[...],"rows":[...]}`。
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `fields` | `string[]` | 是 | 字段 ID 或字段名数组 |
|
||||
| `rows` | `any[][]` | 是 | 二维数组,每一行按 `fields` 同序给值;单次最多 200 行 |
|
||||
| `rows` | `CellValue[][]` | 是 | 二维数组,每一行按 `fields` 同序给 cell;单次最多 200 行 |
|
||||
|
||||
## 返回重点
|
||||
|
||||
`data` 为多行二维数组,与 `+record-list` 返回的多行数据结构一致(按 `fields` 列顺序对齐)。
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `fields` | `string[]` | 返回的字段名数组 |
|
||||
| `field_id_list` | `string[]` | 返回的字段 ID 数组 |
|
||||
| `record_id_list` | `string[]` | 新创建记录 ID 列表 |
|
||||
| `data` | `any[][]` | 与 `fields` 对齐的多行数据 |
|
||||
| `ignored_fields` | `array` | 可选,表示被忽略的字段信息 |
|
||||
返回 `fields`、`field_id_list`、`record_id_list`、`data`,其中 `data` 与 `fields` 列顺序对齐。
|
||||
|
||||
## 坑点
|
||||
|
||||
- ⚠️ `--json` 必须是对象。
|
||||
- ⚠️ 写 `rows` 前必须先阅读 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md),按字段类型填值,禁止按自然语言猜测 value 结构。
|
||||
- ⚠️ `fields` 与 `rows` 列顺序必须一一对应。
|
||||
- ⚠️ 空单元格可以显式用 `null` 填充。
|
||||
- ⚠️ 单次最多 200 行,超出需分批写入。
|
||||
- `fields` 与每行 `rows` 的列顺序必须一一对应。
|
||||
- 空单元格必须显式用 `null` 填充。
|
||||
- 单次最多 200 行,超出需分批写入。
|
||||
- select 写入未知选项时平台可能自动新增选项;如果不是要新增选项,先确认真实选项名。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-base-record.md](lark-base-record.md) — record 索引页
|
||||
- [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) — 记录值格式规范
|
||||
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|
||||
|
||||
@@ -7,17 +7,10 @@
|
||||
## 推荐命令
|
||||
|
||||
```bash
|
||||
lark-cli base +record-batch-update \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--json '{"record_id_list":["recXXX"],"patch":{"field_id_or_name":"value"}}'
|
||||
```
|
||||
lark-cli base +record-batch-update --base-token <base_token> --table-id <table_id> \
|
||||
--json '{"record_id_list":["<record_id>"],"patch":{"状态":"完成"}}'
|
||||
|
||||
```bash
|
||||
lark-cli base +record-batch-update \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--json @batch-update.json
|
||||
lark-cli base +record-batch-update --base-token <base_token> --table-id <table_id> --json @batch-update.json
|
||||
```
|
||||
|
||||
## 参数
|
||||
@@ -28,44 +21,33 @@ lark-cli base +record-batch-update \
|
||||
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
||||
| `--json <body>` | 是 | 批量更新请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@<file_path>` 从文件读取 |
|
||||
|
||||
## 生成 `patch` 前必看
|
||||
## API
|
||||
|
||||
- 先阅读 [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
|
||||
```
|
||||
`POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_update`
|
||||
|
||||
## `--json` 结构
|
||||
|
||||
本节只说明 `+record-batch-update` 的外层 JSON 形状;CellValue 统一看 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
||||
|
||||
对象形态:`{"record_id_list":[...],"patch":{...}}`。
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `record_id_list` | `string[]` | 是 | 要更新的记录 ID 列表(单次最多 200 条) |
|
||||
| `patch` | `object` | 是 | 同一份字段更新对象,会应用到 `record_id_list` 内所有记录 |
|
||||
| `patch` | `Map<FieldNameOrID, CellValue>` | 是 | 字段更新对象;key 是字段名或字段 ID,value 是 `CellValue`;同一份 `patch` 会应用到 `record_id_list` 内所有记录 |
|
||||
|
||||
## 返回重点
|
||||
|
||||
返回结构如下(其中 `update` 可与 `+record-list` 的单行字段对象结构对齐):
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `record_id_list` | `string[]` | 本次更新到的记录 ID 列表 |
|
||||
| `update` | `object` | 本次应用的字段更新结果;可能为空对象 |
|
||||
| `ignored_fields` | `{id,name,reason}[]` | 可选,被忽略字段信息 |
|
||||
返回 `record_id_list`、`update`,可选返回 `ignored_fields`;`update` 可能为空对象。
|
||||
|
||||
## 坑点
|
||||
|
||||
- ⚠️ `--json` 必须是对象。
|
||||
- ⚠️ 该接口是“同值批量更新”:同一请求内所有 `record_id_list` 都会应用同一份 `patch`。
|
||||
- ⚠️ `record_id_list` 最大 200 条,超过会被接口校验拒绝。
|
||||
- ⚠️ 命令不会自动做字段/行映射转换,传什么就发什么。
|
||||
- 这是“同值批量更新”:所有 `record_id_list` 都应用同一份 `patch`。
|
||||
- `record_id_list` 最大 200 条,超过会被接口校验拒绝。
|
||||
- 命令不会自动做字段/行映射转换,传什么就发什么。
|
||||
- 如果 `patch` 包含只读字段,返回里可能出现 `ignored_fields`;这些字段不会被更新。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-base-record.md](lark-base-record.md) — record 索引页
|
||||
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
```bash
|
||||
lark-cli base +record-delete \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id> \
|
||||
--yes
|
||||
```
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
```bash
|
||||
lark-cli base +record-get \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id>
|
||||
```
|
||||
|
||||
## 参数
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
```bash
|
||||
# 查询最新一页历史
|
||||
lark-cli base +record-history-list \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id>
|
||||
|
||||
# 指定分页大小,带游标翻页
|
||||
lark-cli base +record-history-list \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id> \
|
||||
--page-size 30 \
|
||||
--max-version 123456
|
||||
```
|
||||
|
||||
@@ -32,15 +32,15 @@
|
||||
|
||||
```bash
|
||||
lark-cli base +record-list \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--offset 0 \
|
||||
--limit 100
|
||||
|
||||
lark-cli base +record-list \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--view-id vewXXX \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--view-id <view_id> \
|
||||
--field-id fldStatus \
|
||||
--field-id 项目名称 \
|
||||
--offset 0 \
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
```bash
|
||||
lark-cli base +record-search \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--json '{"keyword":"Created","search_fields":["Title","fld_owner"],"offset":0,"limit":100}'
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--json '{"keyword":"Created","search_fields":["Title","<field_id>"],"offset":0,"limit":100}'
|
||||
|
||||
lark-cli base +record-search \
|
||||
--base-token XXXXXX \
|
||||
--table-id tblXXX \
|
||||
--json '{"view_id":"vewXXX","keyword":"Alice","search_fields":["Title","Owner"],"select_fields":["Title","Owner","Status"],"offset":0,"limit":50}'
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--json '{"view_id":"<view_id>","keyword":"Alice","search_fields":["Title","Owner"],"select_fields":["Title","Owner","Status"],"offset":0,"limit":50}'
|
||||
```
|
||||
|
||||
## 参数
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
```bash
|
||||
# 单条记录
|
||||
lark-cli base +record-share-link-create \
|
||||
--base-token xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-ids rec_xxx
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-ids <record_id>
|
||||
|
||||
# 多条记录(使用 "," 分隔)
|
||||
lark-cli base +record-share-link-create \
|
||||
--base-token xxx \
|
||||
--table-id tbl_xxx \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-ids rec001,rec002,rec003
|
||||
```
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
```bash
|
||||
lark-cli base +record-upload-attachment \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx \
|
||||
--field-id fld_attach \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id> \
|
||||
--field-id <field_id> \
|
||||
--file ./report.pdf
|
||||
|
||||
lark-cli base +record-upload-attachment \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx \
|
||||
--base-token <base_token> \
|
||||
--table-id <table_id> \
|
||||
--record-id <record_id> \
|
||||
--field-id "附件" \
|
||||
--file ./report.pdf \
|
||||
--name "Q1-final.pdf"
|
||||
@@ -48,4 +48,3 @@ lark-cli base +record-upload-attachment \
|
||||
## 参考
|
||||
|
||||
- [lark-base-record.md](lark-base-record.md) — record 索引页
|
||||
- [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) — 记录值格式详解
|
||||
|
||||
@@ -7,16 +7,13 @@
|
||||
## 推荐命令
|
||||
|
||||
```bash
|
||||
lark-cli base +record-upsert \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--json '{"项目名称":"Apollo","状态":"进行中"}'
|
||||
# 创建记录
|
||||
lark-cli base +record-upsert --base-token <base_token> --table-id <table_id> \
|
||||
--json '{"项目名称":"Apollo","状态":"进行中"}'
|
||||
|
||||
lark-cli base +record-upsert \
|
||||
--base-token app_xxx \
|
||||
--table-id tbl_xxx \
|
||||
--record-id rec_xxx \
|
||||
--json '{"项目名称":"Apollo","状态":"进行中","标签":["高优","外部依赖"],"截止日期":"2026-03-24 10:00:00"}'
|
||||
# 更新记录
|
||||
lark-cli base +record-upsert --base-token <base_token> --table-id <table_id> --record-id <record_id> \
|
||||
--json '{"项目名称":"Apollo","状态":"完成","完成时间":"2026-03-24 10:00:00"}'
|
||||
```
|
||||
|
||||
## 参数
|
||||
@@ -26,44 +23,26 @@ lark-cli base +record-upsert \
|
||||
| `--base-token <token>` | 是 | Base Token |
|
||||
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
||||
| `--record-id <id>` | 否 | 传入时走更新,不传时走创建 |
|
||||
| `--json <body>` | 是 | 记录 JSON 对象 |
|
||||
| `--json <body>` | 是 | 字段写入对象,类型 `Map<FieldNameOrID, CellValue>` |
|
||||
|
||||
## API 入参详情
|
||||
## API
|
||||
|
||||
**HTTP 方法和路径:**
|
||||
- 创建:`POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records`
|
||||
- 更新:带 `--record-id` 时改走 `PATCH /records/:record_id`
|
||||
|
||||
```
|
||||
POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records
|
||||
```
|
||||
## `--json` 结构
|
||||
|
||||
- 带 `--record-id` 时内部改走 `PATCH /records/:record_id`。
|
||||
|
||||
## JSON 值规范
|
||||
|
||||
- `--json` 必须是 **JSON 对象**。
|
||||
- key 可用字段名或字段 ID,但一次请求里同一字段只用一种标识,避免重复写入冲突。
|
||||
- value 必须匹配字段类型;先 `+field-list` 再构造值。
|
||||
- 推荐值形状(常用):
|
||||
- 文本:`"标题"`
|
||||
- 数字:`12.5`
|
||||
- 单选:`"Todo"`
|
||||
- 多选:`["A","B"]`
|
||||
- 复选框:`true`
|
||||
- 人员:`[{"id":"ou_xxx"}]`
|
||||
- 关联记录:`[{"id":"rec_xxx"}]`
|
||||
- 日期:`"YYYY-MM-DD HH:mm:ss"`(如 `"2026-03-24 10:00:00"`)
|
||||
- 需要清空字段时优先传 `null`(字段允许清空时)。
|
||||
- 公式、查找引用、创建/更新时间、创建/修改人等只读字段不要写入。
|
||||
|
||||
**正确(base +record-upsert)**
|
||||
- `--json` 必须是 **JSON object map**,形状是 `Map<FieldNameOrID, CellValue>`。
|
||||
- key 是字段名或字段 ID;value 是该字段的 `CellValue`。
|
||||
- 一次请求里同一字段只用一种标识,避免重复写入冲突。
|
||||
- 写入前先 `+field-list` 确认字段类型和字段名/ID。
|
||||
- CellValue 统一看 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
||||
|
||||
```json
|
||||
{
|
||||
"项目名称": "Apollo",
|
||||
"状态": "进行中",
|
||||
"标签": ["高优", "外部依赖"],
|
||||
"负责人": [{ "id": "ou_xxx" }],
|
||||
"截止日期": "2026-03-24 10:00:00"
|
||||
"完成时间": "2026-03-24 10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -71,19 +50,15 @@ POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records
|
||||
|
||||
- 创建时返回 `record` 和 `created: true`。
|
||||
- 更新时返回 `record` 和 `updated: true`。
|
||||
|
||||
## 工作流
|
||||
|
||||
|
||||
1. 先确定是新增还是修改。
|
||||
- 如果写入了 `formula / lookup / created_at / updated_at / created_by / updated_by` 等只读字段,返回里可能出现 `ignored_fields`,这些字段不会被更新。
|
||||
|
||||
## 坑点
|
||||
|
||||
- ⚠️ `--json` 必须是对象,不支持数组。
|
||||
- ⚠️ 有 `--record-id` 就一定走更新;不传就一定走创建,不会自动查重。
|
||||
- ⚠️ 这是写入操作,执行前必须确认。
|
||||
- 有 `--record-id` 就一定更新;不传就一定创建,不会自动查重或按业务键 upsert。
|
||||
- select 写入未知选项时平台可能自动新增选项;如果不是要新增选项,先用 `+field-list` / `+field-search-options` 确认真实选项名。
|
||||
- 这是写入操作,执行前必须确认目标表和字段。
|
||||
|
||||
## 参考
|
||||
|
||||
- [lark-base-record.md](lark-base-record.md) — record 索引页
|
||||
- [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md) — shortcut 记录值格式规范(推荐)
|
||||
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|
||||
|
||||
@@ -24,6 +24,6 @@ record 相关命令索引。
|
||||
- 聚合页只保留目录职责;每个命令的详细说明请进入对应单命令文档。
|
||||
- 所有 `+xxx-list` 调用都必须串行执行;若要批量跑多个 list 请求,只能串行执行。
|
||||
- `+record-list` 支持重复传参 `--field-id` 做字段筛选。
|
||||
- 写记录 JSON 前优先阅读 [lark-base-shortcut-record-value.md](lark-base-shortcut-record-value.md)。
|
||||
- 写记录 JSON 前优先阅读 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
||||
- 本地文件写入附件字段时,必须使用 `+record-upload-attachment`。
|
||||
- 从附件字段下载文件时,用 `lark-cli docs +media-download --token <file_token> --output <path>`,用法见 [`../../lark-doc/references/lark-doc-media-download.md`](../../lark-doc/references/lark-doc-media-download.md)。
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
# base shortcut record JSON 规范(lark-base-shortcut-record-value)
|
||||
|
||||
> 适用命令:`lark-cli base +record-upsert`
|
||||
|
||||
本文件定义 **shortcut 写记录** 时 `--json` 的推荐格式,目标是让 AI 一次写对。
|
||||
|
||||
## 1. 顶层规则(必须遵守)
|
||||
|
||||
- `--json` 必须是 JSON 对象。
|
||||
- 顶层直接传字段映射:`{"字段名或字段ID": 值}`。
|
||||
- 一次 payload 里同一字段只用一种 key(字段名或字段 ID),不要重复。
|
||||
- 写入前先 `+field-list` 获取字段 `type/style/multiple`,再构造值。
|
||||
|
||||
## 2. 各类型值格式与示例
|
||||
|
||||
### 2.1 text / phone / url
|
||||
|
||||
**推荐值**:字符串。
|
||||
|
||||
```json
|
||||
{
|
||||
"标题": "Hello",
|
||||
"联系电话": "1380000000000",
|
||||
"官网": "https://example.com"
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "string", "description": "text field cell, example: \"one string and [one url](https://foo.bar)\"" }
|
||||
```
|
||||
|
||||
### 2.2 number
|
||||
|
||||
**推荐值**:数字。
|
||||
|
||||
```json
|
||||
{
|
||||
"工时": 12.5,
|
||||
"预算": 3000
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "number", "description": "number field cell, can be any float64 value" }
|
||||
```
|
||||
|
||||
### 2.3 select(单选/多选/阶段)
|
||||
|
||||
**推荐值**:
|
||||
- 单选:字符串
|
||||
- 多选:字符串数组
|
||||
|
||||
```json
|
||||
{
|
||||
"状态": "Todo",
|
||||
"标签": ["后端", "高优"]
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "array", "items": { "type": "string", "description": "option name" }, "description": "select field cell, example: [\"option_1\", \"option_2\"]" }
|
||||
```
|
||||
|
||||
### 2.4 datetime
|
||||
|
||||
**推荐值**:`YYYY-MM-DD HH:mm:ss` 字符串(稳妥写法)。
|
||||
|
||||
```json
|
||||
{
|
||||
"截止时间": "2026-03-24 10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "string", "description": "datetime field cell. accepts common datetime strings and timestamp-like values. Prefer \"YYYY-MM-DD HH:mm:ss\" in requests because it is the most stable format and matches the API output. Example: \"2026-01-01 19:30:00\"" }
|
||||
```
|
||||
|
||||
### 2.5 checkbox
|
||||
|
||||
**推荐值**:布尔值。
|
||||
|
||||
```json
|
||||
{
|
||||
"已完成": true
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "boolean", "description": "checkbox field cell" }
|
||||
```
|
||||
|
||||
### 2.6 user
|
||||
|
||||
**推荐值**:对象数组,元素至少有 `id`。
|
||||
|
||||
```json
|
||||
{
|
||||
"负责人": [
|
||||
{ "id": "ou_xxx" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "user id" } }, "required": ["id"], "additionalProperties": false }, "description": "user field cell, example: [{\"id\": \"ou_123\"}]" }
|
||||
```
|
||||
|
||||
### 2.7 link
|
||||
|
||||
**推荐值**:对象数组,元素至少有 `id`。
|
||||
|
||||
```json
|
||||
{
|
||||
"关联任务": [
|
||||
{ "id": "rec_xxx" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{ "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "record id" } }, "required": ["id"], "additionalProperties": false }, "description": "link field cell, example: [{\"id\": \"rec_123\"}]" }
|
||||
```
|
||||
|
||||
### 2.8 location
|
||||
|
||||
**推荐值**:对象 `{lng, lat}`。
|
||||
|
||||
```json
|
||||
{
|
||||
"坐标": {
|
||||
"lng": 116.397428,
|
||||
"lat": 39.90923
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Schema**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": { "lng": { "type": "number", "description": "Longitude" }, "lat": { "type": "number", "description": "Latitude" } },
|
||||
"required": ["lng", "lat"],
|
||||
"additionalProperties": false,
|
||||
"description": "location field cell, example: {\"lng\": 113.94765, \"lat\": 22.528533}"
|
||||
}
|
||||
```
|
||||
|
||||
### 2.9 attachment
|
||||
|
||||
对 agent 而言,附件上传是**特殊链路**:如果用户要把本地文件加到记录里,必须使用 `lark-cli base +record-upload-attachment` 上传到已有记录。
|
||||
|
||||
**Schema - attachment**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "array",
|
||||
"items": { "type": "object", "properties": { "file_token": { "type": "string", "minLength": 0, "maxLength": 50 }, "name": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": ["file_token", "name"], "additionalProperties": false },
|
||||
"description": "attachment field cell. For agent, do not synthesize this payload via +record-upsert; must use +record-upload-attachment to upload files."
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 只读字段(不要写)
|
||||
|
||||
以下字段在写记录时应视为只读:
|
||||
- `auto_number`
|
||||
- `lookup`
|
||||
- `formula`
|
||||
- `created_time` / `modified_time`
|
||||
- `created_by` / `modified_by`
|
||||
|
||||
## 4. 快速可用完整示例
|
||||
|
||||
```json
|
||||
{
|
||||
"标题": "Created from shortcut",
|
||||
"状态": "Todo",
|
||||
"标签": ["高优", "外部依赖"],
|
||||
"工时": 8,
|
||||
"截止时间": "2026-03-24 10:00:00",
|
||||
"已完成": false,
|
||||
"负责人": [{ "id": "ou_123" }],
|
||||
"关联任务": [{ "id": "rec_456" }],
|
||||
"坐标": { "lng": 116.397428, "lat": 39.90923 }
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user