Lark Base スキル
- インストール数 87.7万
これはlarksuiteのlark-baseのコピーです。インストール数と順位は元のリスティングに集計されます。
Lark Base は Claude のスキルで、lark-cli の base コマンドを通して、Feishu の Base(bitable)のテーブル、フィールド、レコード、ビュー、数式、ダッシュボード、ワークフロー、ロールを操作します。
インストールしたくない場合は、Skillselion MCP 経由で先に試せます。インストール不要、ディスクにも何も残りません。
1. Claude Code - リモートコネクタを追加:
claude mcp add --transport http skillselion https://mcp.skillselion.com/mcpClaude.ai・ChatGPT・Cursor の場合は、この URL をカスタムコネクタとして追加します。
https://mcp.skillselion.com/mcp2. エージェントに頼む:
Use Skillselion load_skill to load skill:open.feishu.cn#lark-base (Lark Base) and follow it.インストールが向いている場合
Feishu の Base(bitable)で、構造化データを構築し、クエリする場合に向いています。
見送ったほうがよい場合
Excel / CSV / .base の Base へのインポート(lark-drive を使います)や、認証とスコープの扱い(lark-shared を使います)には向きません。
lark-baseの主な内容
- lark-cli の base ショートカットによる Base の CRUD 全般:テーブル、フィールド、レコード、ビュー、フォーム、ダッシュボード、ワークフロー、ロール
- +data-query によるクラウド側のフィルタ・ソート・集計、ガード付きの JSON による数式とルックアップのフィールド
- 一括書き込みは 1 回の呼び出しにつき 200 レコードまでで、書き込む前に実際のフィールド構造を読み取ることを徹底します
数字で見るlark-base
| 累計インストール数 | 876,559 (87.7万) | skills.shレジストリ |
|---|---|---|
| リポジトリ | ||
2026年11月9日時点のデータ(Skillselionカタログ同期)
lark-baseはClaude Codeで何ができますか?
Feishu/Larkアカウントと、lark-cliによるユーザー認証が必要です。
- 機能
- テーブル管理 · レコードのCRUD · 集計クエリ · 数式・参照フィールド
- ユースケース
- database · data analysis
- 料金
- 無料
lark-baseのドキュメントが説明する機能
飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、workflow、角色权限;
Base 曾用名 Bitable
- 一括書き込みは1回の呼び出しにつき200レコードが上限
- テーブル、フィールド、レコード、ビュー、フォーム、ダッシュボード、ワークフロー、ロールに対するselect/list/getコマンド
lark-baseにはどんなファイルが含まれますか?
Base
普通 Base 是数据容器,由一棵 Base Block 资源树和 Base 级配置组成。folder、table、docx、dashboard、workflow 都是 Block 类型;Advanced Permission / Role 是 Base 级配置,不属于 Block。Table 是其中承载业务数据的核心 Block。Workspace 是组织 Base 与 BaseApp 的外层容器;BaseApp(AppMode)通过 Page 和组件组织 Base 数据,不是 Base 的别名。
身份选择(优先)
操作 Base 优先使用 --as user;用户明确要求应用身份时使用 --as bot。权限失败按 lark-shared 以原身份修复 scope 或资源 ACL;只有用户明确同意更换操作者时才切换身份。
进入前必做:解析目标实体
开始操作前先确定 base_token 和目标实体类型;上下文已提供 <bitable> / <base_refer> 标签及资源 ID 时直接使用。其余情况从两个入口解析:
- URL 或分享链接:
lark-cli base +url-resolve --url '<url>' --as user。Base URL 根据返回的resource_type/block_type及table_id、view_id、record_id、dashboard_id、workflow_id、docx_token、share_token等坐标进入对应模块;BaseApp/app/URL 返回app_token,并在链接携带时返回workspace_token和page_id。实体类型以解析结果为准。 - Base 标题或关键词:
lark-cli base +title-resolve --title '<keyword>' --as user。单一结果直接取得base_token;多个候选结合标题、所有者和更新时间消歧,仍无法唯一确定时请用户选择。随后按下方 Base Block 资源模型定位目标实体。 - BaseApp: 优先使用真实
/app/URL;已有workspace_token时可用+workspace-entity-list --type baseapp定位。两者都没有时请用户补充应用链接或 Workspace,不按名称全局猜测app_token。
读取 Base: Base 信息用 +base-get,资源目录按下方 Base Block 资源模型读取。
写入 Base: 创建新 Base 使用一次 +base-create --name <base-name> --table-name <table-name> --fields '<field-array>' 同时创建 Base、首表和 fields;+base-copy 复制整个 Base;Base 内资源统一按下方 Block 生命周期管理。
Base Block 资源模型
Base
├── Base Block 资源树
│ ├── Table Block
│ │ ├── Field schema
│ │ ├── Records / CellValue
│ │ ├── Views
│ │ └── Forms / Questions
│ ├── Dashboard Block(布局容器)
│ │ └── Dashboard 内部 Blocks(图表、指标卡、文本)
│ ├── Workflow Block
│ │ └── Workflow definition(title、status、steps 执行图)
│ ├── Docx Block → docx_token / lark-doc
│ └── Folder Block → 子 Block
└── Base 级配置
└── Advanced Permission / Roles每个 Base Block 都有 id、type、可修改的 name、所在 Folder 的 parent_id,并在同级目录中具有顺序。+base-block-list 是统一发现入口;+base-block-create 创建 Block,+base-block-rename 修改名称,+base-block-move 通过 --parent-id 调整目录并通过 --before-id / --after-id 调整顺序,+base-block-delete 删除 Block。类型专属内容再由对应模块命令处理。
创建时已经明确类型专属初始内容,可直接使用对应构造命令一次完成:Table 用 +table-create --fields,Dashboard 用 +dashboard-create 设置主题,Workflow 用 +workflow-create --json 提交完整定义;Folder 和 Docx 使用 +base-block-create。
Block 的 id 按类型直接作为对应模块坐标:
| Block type | 模块坐标与内部内容 |
|---|---|
table | id 即 table_id;内部包含 Field、Record、View 和 Form |
dashboard | id 即 dashboard_id;内部包含图表、指标卡和文本等 Dashboard 组件 |
workflow | id 即 workflow_id;内部包含 title、status 和 steps 执行图 |
docx | Block 另带 docx_token;正文由 lark-doc 处理 |
folder | id 是目录 Block ID,也可作为 --parent-id;只组织子 Block |
Table Block(The Core)
Table 本身是 Base Block,也是 Base 的核心数据存储层;Field、Record、View 和 Form 是 Table 内部对象,不是 Base Block。业务数据查询、写入、关联、统计和分析都从 Table 开始;标准资源读取链路是 +table-list → +field-list → +record-list / +record-search,多表的 +field-list 可以并发执行;记录相关任务读取 Record 查询与分析 SOP。
读取 Table: +table-list 定位表,+table-get 读取详情。Table 专属复制使用 +table-copy,异步状态用 +table-copy-status;schema 和 records 由下方内部对象操作。
Table 下的大多数更新通过异步链路生效,接口成功返回后立即读取可能暂时看不到最新状态。优先以写入成功响应作为操作结果;任务必须确认最终状态时,先完成本轮相关变更,再统一读取验收,避免逐项写后立即读回。
Field
Field 定义列 schema。field_id 是稳定列标识,name 是可修改的展示名称;Formula、Lookup、Link、Select 等属于 Field 类型或能力。
读取 Field: +field-list / +field-get / +field-search-options。写入 Field: 已有 Table 中创建多个字段时,优先向一次 +field-create --json 传字段对象数组;单字段更新和删除用 +field-update / +field-delete。创建和更新分别读取 field-create / field-update,由命令文档继续路由 Field JSON、Formula 和 Lookup 协议。
Record
Record 是 Table 中的一行数据,包含该记录在各个 Field 下的 CellValue。系统 record_id 是表内稳定、非空且唯一的主键,Table 的主字段只是展示字段。
读取 Record: 记录预览、筛选、匹配、统计、聚合、TopN、多表或语义分析,以及写前定位记录和写后验收,都必须先完整读取 Record 查询与分析 SOP,并由该 SOP 选择具体命令。写入 Record: 优先使用 batch create / batch update 创建或更新一条或多条记录,按其文档中的 CellValue 协议提交字段值。
Record 生命周期: +record-delete 删除记录;+record-share-link-create 创建记录分享链接;+record-history-list 查询单条记录的变更事件,读取 历史记录协议。附件使用 +record-upload-attachment / +record-download-attachment / +record-remove-attachment 操作。
Record 中的 Select、人员、群组、Link、附件的 CellValue 通常是多值;Link 的目标 table_id 来自 Field schema,CellValue 中的 id 对应目标表 record_id。
View
View 是同一 Table records 上的持久化筛选、排序、分组和展示配置,共享底层 records,不产生数据副本。一次性查询直接使用 Record 读取;需要在 Base UI 中长期保存、共享或复用访问方式时使用 View。
读取 View: 使用 +view-list / +view-get,并通过 +view-get-filter / +view-get-sort / +view-get-group / +view-get-visible-fields / +view-get-timebar / +view-get-card 读取持久化配置。写入 View: 使用 +view-create / +view-rename / +view-delete 管理 View,并通过对应的 +view-set-* 更新筛选、排序、分组、可见字段、时间轴和卡片配置;筛选结构读 View filter,由该文档继续路由公共 condition 协议。
Form
Form 依附于 Table,以 Field 作为题目,每次有效提交会创建一条 Record,适合信息收集、外部填写、条件题目和附件提交。
- 读取 Table 中的表单配置: 使用
+form-list/+form-get读取表单,使用+form-questions-list读取题目配置;这些命令使用表单所属的base_token + table_id。 - 创建或修改 Table 中的表单配置: 使用
+form-create/+form-update/+form-delete管理表单;题目由 Table Field 承载,question ID 对应field_id,创建和更新分别读取 questions create / questions update,删除使用+form-questions-delete。 - 填写分享表单并提交: 对表单分享链接使用
+url-resolve取得share_token,按 Form detail 执行+form-detail读取真实题目、必填项和显示条件,再按 Form submit 构造字段与附件并执行+form-submit。
Dashboard Block
Dashboard Block 是 Base Block 树中的仪表盘容器,负责承载页面主题、布局和内部组件集合,本身不表示某一项图表数据。使用 +dashboard-list 定位容器,+dashboard-get 读取容器信息,+dashboard-update 修改主题,+dashboard-arrange 统一编排内部组件布局。
容器内部的图表、指标卡和文本等组件在 Dashboard API 中也称为 Block,但不属于 Base Block 树。内部 Block 分为三条操作路径:
- 读取配置:
+dashboard-block-list/+dashboard-block-get读取组件类型、布局和data_config;文本组件的正文也属于配置。 - 写入配置:
+dashboard-block-create/+dashboard-block-update/+dashboard-block-delete管理组件,data_config定义数据源、维度、指标、聚合或文本内容。 - 读取内容:
+dashboard-block-get-data读取图表、指标卡等数据组件的计算结果。
操作内部 Block 前先读 Dashboard,由该入口继续路由组件配置和结果协议。
应用模式与 Workspace 心智模型
Workspace 是组织 Base 和 BaseApp 的空间容器;BaseApp 创建时必须归属一个 Workspace。BaseApp 用 Page 组织界面,每个 Page 包含图表、列表或富文本组件;组件通过 data_config 引用 Base 数据,但不会改变 Base、Table、Field 和 Record 的归属关系。Workspace 负责资源归属,App 负责页面和组件,Base 负责数据。
- Workspace: 使用
+workspace-create、+workspace-entity-list和+workspace-move-in创建目录、列出其中的 Base/BaseApp 或移入资源。 - 应用: 使用
+app-create/+app-get;应用查询和创建依赖真实app_token/workspace_token。 - 页面: 使用
+app-page-list/get/create/rename/delete管理 Page。 - 组件: 使用
+app-block-list/get/create/update读写组件配置,使用+app-block-get-data读取组件计算结果。
BaseApp、Workspace、Page 或组件任务开始前完整读取 应用模式与 Workspace;构造组件 data_config 时继续读取 应用组件配置。BaseApp 不走 lark-apps。当前不支持 BaseApp 复制、Page 完整复制、页面图标以及从 Workspace 移出资源;遇到这些目标按 reference 的能力边界处理,不以新建空对象或 Drive 移动冒充。
- BaseApp(应用模式)中的 Page 和组件使用
app_token/page_id/block_id,表、字段和记录仍使用组件所引用 Base 的base_token;不要混用 token 或把 BaseApp 当作 Base 的别名。 - 复用现有 BaseApp block 的
data_config只能作为结构模板,首次 Create/Update 前仍要逐项对齐用户显式要求;用户要求排序时必须显式写group_by[].sort.order或顶层sort.order,不能用旧配置省略的方向或当前get-data结果顺序代替。 - 应用页面的 block 与仪表盘 block 是同一套底层实体,但 ID 体系不通用;按当前模块 reference 选择命令和配置协议。
Workflow Block
Workflow 本身是 Base Block,其内部是一张由 next / children 连接的 steps 执行图;触发器、动作、条件分支和循环都是 step 类型。它适合定时执行、Record 新增或变更联动、消息通知、记录读写和跨系统调用。Workflow 分为三条操作路径:
- 读取配置:
+workflow-list定位流程,+workflow-get读取title、status和完整steps执行图。 - 写入配置:
+workflow-create创建完整定义,+workflow-update更新完整定义;构造或修改配置前读取 Workflow,由该入口继续路由 step 类型和 schema。 - 运行状态控制:
+workflow-enable/+workflow-disable启用或停用已有 Workflow,不修改 steps 执行图。
Advanced Permission(AdvPerm)
AdvPerm 为 Base 开启细粒度权限模式;Role 在此基础上配置 Base、Table、View、Field、Record、Dashboard 和 Docx 等资源的访问能力,适合按团队或职责限制可见范围、编辑能力、复制下载和数据访问规则。
读取 AdvPerm: +base-get 查看 is_advanced,+role-list / +role-get 查看角色。写入 AdvPerm: +advperm-enable / +advperm-disable 启停高级权限,+role-create / +role-update / +role-delete 管理角色。先读 权限与角色,由该入口继续路由权限 JSON 协议。
Docx Block
Docx Block 是组织在 Base 目录中的飞书文档资源,适合把说明、方案和报告与数据表、仪表盘及流程放在同一 Base 中;正文仍使用标准 Docx 数据模型。
从 Base Block 资源目录按 --type docx 定位文档并取得 docx_token;正文读取、创建与编辑使用 lark-doc。
Folder Block
Folder Block 只承担 Base 目录分组和层级组织。用 +base-block-list --parent-id <folder_block_id> 读取直接子项。
通用执行契约
- Update 先确认命令是完整替换还是 delta:完整替换使用可信当前配置做 read-modify-write,delta 只提交目标变更。
- 优先用写入返回确认结果;返回不足以确认或任务明确要求核验时再读回目标。
- 命令具有 confirmation gate 时,确认目标和影响后使用
--yes。
不在本 Skill 范围
- 认证、初始化、scope、身份切换和授权恢复 →
lark-shared - Excel、CSV、
.base等本地文件与 Base 之间的导入/导出 →lark-drive - Base 内嵌 Docx 的正文编辑 →
lark-doc;电子表格内容操作 →lark-sheets
Base Advanced Permission 与 Role
This is the module entry point for Base advanced permissions and roles. Use it to choose commands and understand safety boundaries. For the permission JSON itself, use Role Permission Schema.
Command selection
| Goal | Command | Notes |
|---|---|---|
| Check advanced permission status | +base-get | Read data.base.is_advanced. There is no +advperm-get command. |
| Enable advanced permissions | +advperm-enable | Required before creating or updating roles. Caller must be a Base admin. |
| Disable advanced permissions | +advperm-disable | High-risk write. Disabling invalidates existing custom roles. |
| Locate roles | +role-list | Returns role summaries. Use +role-get for full config. |
| Inspect one role | +role-get | Use before updating a role or deciding whether a role can be deleted. |
| Create a custom role | +role-create | Supports custom_role only. Read Role Permission Schema before constructing --json. |
| Update a role | +role-update | Delta merge. Read current config first, then send only intended changes. |
| Delete a role | +role-delete | Custom roles only. System roles cannot be deleted. |
Required order
At the start of a role workflow, before the first +role-list, +role-get, +role-create, +role-update, or +role-delete call:
- Run
lark-cli base +base-get --base-token <base_token>and inspectdata.base.is_advanced. - If
is_advancedisfalse, run+advperm-enablebefore the role command. If the user did not authorize enabling advanced permissions, stop and explain the required precondition. - Run the requested role commands only after
is_advancedistrueor+advperm-enablesucceeds. Reuse that confirmed status for later role calls in the same workflow.
Do not probe with +advperm-get: that command is not supported. Do not use an empty +role-list response to infer the advanced permission status; a disabled Base can also return an empty list.
Safety boundaries
- Role operations require advanced permissions to be enabled and the caller to be a Base admin.
+role-createcreates custom roles only.+role-deleteis only for custom roles. System roles such as editor/reader can be configured within supported limits, but cannot be deleted.+role-updateuses delta merge: omitted fields remain unchanged, but identity fields such asrole_nameandrole_typeshould match the current target role.+advperm-disableinvalidates existing custom roles; confirm the target Base and user intent before passing--yes.
Common Fewshots
Use these fewshots for simple role changes. For table, field, record, dashboard, docx, or filter permission details, switch to Role Permission Schema.
Create a custom role that keeps copy/download disabled:
lark-cli base +role-create \
--base-token <base_token> \
--json '{"role_name":"Reviewer","role_type":"custom_role","base_rule_map":{"copy":false,"download":false}}'Rename a role while preserving its type:
lark-cli base +role-update \
--base-token <base_token> \
--role-id <role_id> \
--json '{"role_name":"Finance Reviewer","role_type":"custom_role"}' \
--yesGrant read-only access to one table:
lark-cli base +role-update \
--base-token <base_token> \
--role-id <role_id> \
--json '{"role_name":"Finance Reviewer","role_type":"custom_role","table_rule_map":{"Orders":{"perm":"read_only"}}}' \
--yesJSON SSOT
Use Role Permission Schema for:
AdvPermBaseRoleConfigtop-level structure.base_rule_map,table_rule_map,dashboard_rule_map, anddocx_rule_map.- Table, view, field, record, dashboard, and docx permission values.
- Filter permission JSON.
- Default permission strategy and risk rules.
BaseApp Block data_config
本文件说明 BaseApp 组件 data_config 的 CLI 映射与操作约束,不复制完整字段 Schema。App 图表的每个 data_sources[] 元素复用 Dashboard Block 配置 的字段取值、筛选、分组、排序及规范化规则;区别是 Dashboard 使用扁平单数据源结构,而 App 图表在顶层使用共享的 base_token 和多数据源 data_sources[]。列表组件是 App 独有协议,不复用 Dashboard 图表结构。本文所称“组件协议”是指 CLI 随版本发布的 API 元数据、本文明确列出的约束及实际服务端校验结果。
类型映射
- 图表:
--type column|bar|line|pie|ring|area|combo|scatter|funnel|wordCloud|radar|statistics - 富文本:
--type text(与 Dashboard 文本组件同名同义) - 列表:
--type list --sub-type standard|grouped|collapsible|card|detail - 列表省略
--sub-type时默认standard type/sub_type创建后不可修改
外层请求字段
- Create 只发送
name、type、按需发送的sub_type和data_config。name、type必填;图表和列表的data_config必填,富文本可省略。 - 标准列表未显式指定
--sub-type时,不发送sub_type,由服务端使用standard默认值;其他列表类型必须发送对应sub_type。 - 图表和富文本不得发送
sub_type。 - Update 只发送
name、data_config,且至少提供一个;未传字段保持不变,不允许修改type、sub_type。 - 布局、位置、尺寸、
show_title等展示配置不属于本期公开 Create/Update 请求字段,CLI 不提供或提升这些字段。
列表配置
列表公共数据源字段为单值 base_token 和 table_name。每个列表最多关联一个 Base,且该 Base 必须位于 App 所在的同一 Workspace。
按组件协议,各 subtype 使用以下字段组:
- 公共:
base_token、table_name、filter、sort_by standard/grouped/collapsible:columns、group_bycard:fields、card_configdetail:fields、detail_configcolumns和fields都是可选字段。未指定时 CLI 不发送,由服务端使用产品默认字段。- 只有用户显式指定
columns/fields时才发送;显式传[]表示明确发送空数组,不能作为默认值自动补入。 filter、sort_by、group_by、card_config、detail_config也都是可选字段;未指定时不发送。- 列表 Create 的
data_config必填,其中只有base_token和table_name是顶层必填字段。 - 可选对象一旦传入,其内部必填项仍须满足协议,例如
filter必须包含conjunction和 1~50 项conditions。
不要添加协议未定义的语义校验,尤其不要假设:
- detail/card 必须有 title;
- grouped/collapsible 必须或只能有一个 group_by;
- fields 存在 role 或 visible 属性。
未知顶层字段会被本地校验拒绝;只有确认 CLI 校验与最新协议不一致时才使用 --no-validate。
创建示例
lark-cli base +app-block-create \
--app-token <app_token> --page-id <page_id> \
--name "订单列表" \
--type list --sub-type standard \
--data-config '{"base_token":"<base_token>","table_name":"订单"}'字段的具体对象结构与必填性以 CLI 当前版本的 API 元数据和服务端校验结果为准,不在这里猜测未公开属性。
更新语义
下面是只更新顶层 filter 的示例,适用于协议将 filter 定义在 data_config 顶层的组件(所有列表 subtype 均可使用)。组件类型在创建后不可修改,所以 update 命令不再传 --type。App 图表的 filter 定义在对应的 data_sources[] 元素中;更新图表筛选时必须按图表结构传入完整 data_sources,不能把 filter 提到顶层。
lark-cli base +app-block-update \
--app-token <app_token> --page-id <page_id> --block-id <block_id> \
--data-config '{"filter":{"conjunction":"and","conditions":[{"field_name":"状态","operator":"is","value":"已完成"}]}}'- CLI 只发送用户显式传入的字段。
- 未传字段由服务端保持不变。
- 不为 update 注入 create 默认值,不先读取后拼成全量配置。
- 数组/对象字段的替换粒度以组件协议和服务端校验结果为准。
图表与富文本
App 图表是多数据源结构(ChartDataConfig),与 Dashboard 的扁平单源结构不同。 顶层用一个 base_token(所有数据源共用),table_name / series / count_all / group_by / filter 下沉到每个 data_sources[] 元素里;顶层另有可选的 data_source_mode 和 sort。每个数据源内部各字段的取值逻辑与 Dashboard Block 配置 完全一致(series[].rollup 大写、group_by[].sort 小写等),CLI 对每个 data_sources[] 元素复用同一套规范化与校验。富文本使用 --type text,配置为 {"text":"..."},无数据源;Create 时可省略 data_config,等价于空文本。
text 内容怎么取:text 组件没有
/data接口,走+app-block-get-data会被服务端兜底成通用 500。改用+app-block-get --block-id <widget_id>直接读data_config.text(Markdown 原文)。图表仍走+app-block-get-data --block-id <chart_token>。
顶层参数:
| 参数 | 必填 | 取值 | 说明 |
|---|---|---|---|
base_token | 是 | string | 数据所在 Base 的 token;所有数据源共用同一个值。App 命令不带 --base-token,只能写在 data_config 内 |
data_sources | 是 | ChartDataSourceConfig[] | 有序数组,至少一项 |
data_source_mode | 否 | aggregate / compare | aggregate(默认)在横轴聚合数据源;compare 按数据源拆分系列 |
sort | 否 | `{type: group\ | value\ |
每个 data_sources[] 元素:table_name(必填)、series 与 count_all=true 二选一、group_by(最多 2 项,statistics 不允许)、filter。
{
"base_token": "A2f5boKjfazMzesI9zKbmugTc4T",
"data_sources": [
{
"table_name": "数据表",
"count_all": true,
"group_by": [
{ "field_name": "文本", "mode": "integrated", "sort": { "type": "value", "order": "desc" } }
]
}
]
}对应命令(单数据源计数柱状图):
lark-cli base +app-block-create \
--app-token <app_token> --page-id <page_id> \
--name "文本分布" --type column \
--data-config '{"base_token":"A2f5boKjfazMzesI9zKbmugTc4T","data_sources":[{"table_name":"数据表","count_all":true,"group_by":[{"field_name":"文本","mode":"integrated","sort":{"type":"value","order":"desc"}}]}]}'多数据源示例(两张表各出一条系列,按数据源拆分):
lark-cli base +app-block-create \
--app-token <app_token> --page-id <page_id> \
--name "销售与成本" --type combo \
--data-config '{"base_token":"bas_xxx","data_source_mode":"compare","data_sources":[{"table_name":"销售表","group_by":[{"field_name":"月份","sort":{"type":"group","order":"asc"}}],"series":[{"field_name":"销售额","rollup":"SUM"}]},{"table_name":"成本表","group_by":[{"field_name":"月份","sort":{"type":"group","order":"asc"}}],"series":[{"field_name":"成本","rollup":"SUM"}]}],"sort":{"type":"group","order":"asc"}}'Update 语义:传入 data_sources 即全量替换整个有序数组;修改 base_token 时必须同时传入完整 data_sources。请求不得包含 sub_type(平滑/堆积/百分比等展示变体走产品默认值)。布局、位置、尺寸和展示配置不属于本期公开 Create/Update 协议。其他请求字段以 CLI 当前版本的 API 元数据和服务端校验结果为准。
BaseApp(应用模式)操作指引
先读 `../lark-shared/SKILL.md`。接口和组件字段以 CLI 当前版本的 API 元数据、组件配置 reference 和服务端校验结果为准;不要从组件名称推断额外约束。
不支持能力:先判断并停止
复制 BaseApp
本期没有 BaseApp 复制命令。用户要复制或克隆既有 BaseApp 时,直接说明当前 CLI 无法完成并停止;不要继续探索浏览器、OpenAPI 或创建类命令等替代通道,也不要发起任何写请求。
+base-copy只支持 Base,不支持 BaseApp;不得向它传入app_token,也不得把复制出的 Base 描述为应用副本。+app-create只创建全新空 BaseApp,不复制既有页面和组件。- 不要使用 Drive copy 或其他 Base shortcut 拼装、模拟或冒充 BaseApp 复制。
创建或归属 PageGroup
当前第一阶段的页面层级能力只支持顶级 Page 节点。PageGroup 的创建、归属设置,以及把现有 Page 移入页面组均不支持。
最终答复必须同时说明上述正向支持范围和负向限制,不能只说 PageGroup 不支持。用户命中这些诉求时,直接说明当前 CLI 无法完成并停止;不要继续探索浏览器、OpenAPI 或普通 Page 命令等替代通道,也不要读取页面后声称能完成分组或发起任何写请求。
从 Workspace 移出或移除资源
当前 CLI 只支持用 +workspace-move-in 把 Base 或 BaseApp 移入 Workspace,不支持从 Workspace 移出或移除资源,也没有 workspace move-out / workspace remove 命令。这类请求必须先完成只读定位,再说明限制并停止,顺序不可调换:
- Workspace URL 含
/base/workspace/<workspace_token>时,提取其中的真实workspace_token,不要把完整 URL 当作命令参数。 - 在同一轮立即执行
lark-cli base +workspace-entity-list --workspace-token <workspace_token> --page-size 100 --as user;若has_more=true,继续分页直到完整。该查询是必要的只读定位步骤,不要把它留成等待用户再次选择的可选项,也不要用--help代替真实查询。 - 用服务端返回的
entities[].name、entity_type、token和url忠实判断目标。名称完全匹配时报告真实对象;没有完全匹配时明确说明不存在精确同名实体,并原样列出可能相关的候选。不得自动去掉或补齐前后缀,也不得仅凭名称相似就声称已经定位目标。用户直接给出 token 时仍要忠实报告该 token 对应的实际名称。 - 定位结果报告完后,明确说明当前 CLI 无法执行 Workspace 移出/移除,并停止,不要发起任何写请求。用户在任一步骤中取消时立即停止,取消后不再调用工具。
lark-cli drive +move 只改变 Base 或 BaseApp 在云盘中的目录位置,不改变其 Workspace 归属,不能作为移出 Workspace 的替代方案。不要继续探索 Drive move/delete、另一个 Workspace 的 +workspace-move-in、浏览器、OpenAPI 或源码来拼装或冒充该操作;只有用户后续明确提出另一项受支持的操作时,才执行新的写入。
Token 与命令
| 对象 | 标识 | 命令 |
|---|---|---|
| Workspace | workspace_token | +workspace-create / +workspace-entity-list / +workspace-move-in |
| BaseApp | app_token | +app-create/get;重命名和删除见下方 |
| Base | base_token | +base-create 返回;表、字段、记录命令使用它 |
| Page | page_id | +app-page-list/get/create/update/delete |
| Block | block_id | +app-block-list/get/create/update |
页面和组件命令使用 app_token;Base 数据命令使用 base_token。+app-block-get-data 使用 app_token + base_token + chart_token:CLI 参数名仍为 --block-id,但必须传组件返回的 chart_token,不能传普通 block_id。请求路径与仪表盘图表数据接口相同。
BaseApp / AppMode 是 Base 域能力。用户提供 /app/ 链接时,先用 +url-resolve;它会返回 app_token,并忠实提取链接实际携带的 workspace_token 与 page_id。直接使用本指引和 lark-cli base +...,不要先尝试 lark-cli apps。
查询应用
lark-cli base +app-get --app-token <app_token>- 没有
lark-cli base +app-list。需要列出某个 Workspace 内的 BaseApp 时,唯一列表入口是:
lark-cli base +workspace-entity-list \
--workspace-token <workspace_token> \
--type baseapp \
--page-size 100- 响应中的
pages是页面摘要。 ref的结构是Base token -> 当前组件引用的 Table 名称数组。需要操作被引用 Base 时,使用ref的 key 作为base_token。ref只描述当前组件已经引用的数据源;没有被组件引用的 Base 不会出现在其中。
查询页面与组件
lark-cli base +app-page-list --app-token <app_token> --page-size 100
lark-cli base +app-block-list \
--app-token <app_token> \
--page-id <page_id> \
--page-size 100+app-get已返回足够的页面摘要时,可直接取得目标page_id;需要完整页面目录或分页确认时再用+app-page-list。+app-page-list返回的某个 Page 若name为空字符串,表示当前用户对该 Page 无权限,不表示 Page 没有标题。报告该权限状态,不要将其page_id用于后续页面或组件读写。- 只需列表摘要时不要逐个调用
+app-block-get复核;仅在用户需要单个组件详情时使用 get。 +app-block-list返回type=unsupported的组件时,只能通过列表摘要识别它的存在。当前 CLI 不支持读取详情、读取计算数据或修改此类组件;不要调用+app-block-get、+app-block-get-data或+app-block-update,这些请求会报错。
创建 Workspace
lark-cli base +workspace-create \
--name "AppMode-空白评测空间" \
--as user创建应用
lark-cli base +app-create \
--name "销售应用" \
--workspace-token <workspace_token> \
--as user+app-create没有--base-token。--workspace-token必填;+app-create只调用 App 创建接口,不创建 Workspace、Base,也不移动资源。--theme-style可选,支持default|cloudBlue|fresh|softLight|future|technology。- 记录输出中的
app_token和workspace_token。
创建应用的自然语言编排
先根据用户是否指定 Workspace 和现有 Base 选择流程,再调用原子 shortcut:
| 用户提供的信息 | 执行流程 |
|---|---|
| Workspace + 现有 Base | 确认 Base 位于该 Workspace → +app-create;不创建备用 Base |
| Workspace,未指定 Base | +app-create → +base-create 创建空 Base → +workspace-move-in |
| 未指定 Workspace,指定现有 Base | 先确认该 Base 所属 Workspace;能确定时在该 Workspace 执行 +app-create,不能确定时请用户提供 Workspace;不创建备用 Base |
| Workspace 和 Base 都未指定 | +workspace-create → +app-create → +base-create 创建空 Base → +workspace-move-in |
应用模式的列表组件只能引用同一 Workspace 内的一个 Base。用户指定现有 Base 时,不要因为 +app-create 没有接收 base_token 就额外创建 Base;后续在组件 data_config.base_token 中引用该 Base。
多步编排中,每个成功的 shortcut 都会立即产生资源且不自动回滚。后续步骤失败时,明确报告已经成功创建的 Workspace、App 或 Base 及其 token;用户要求继续时,只重试失败步骤,不要重复创建已经成功的资源。
读取图表计算结果
lark-cli base +app-block-get-data \
--app-token <app_token> \
--base-token <base_token> \
--block-id <chart_token>--block-id的值必须取图表组件摘要中的chart_token,不能使用组件的普通block_id。base_token使用当前图表组件data_config.base_token;一个 App 引用多个 Base 时,不要从+app-get ref中任意选择一个 key。page_id不参与请求。- 返回协议与
+dashboard-block-get-data完全一致。
重命名应用
lark-cli drive files patch \
--file-token <app_token> \
--type bitable \
--data '{"new_title":"新名称"}'BaseApp 与 Base 在 Drive 文件接口中都使用 type=bitable。new_title 只更新应用标题,不会重命名它引用的 Base,也不会修改 Page 或 Block。
删除应用
lark-cli drive +delete --file-token <app_token> --type bitable --yes- 删除 BaseApp 应用本体需要切到
lark-drive。 - BaseApp 与 Base 在 Drive 删除接口中都使用
--type bitable;删除 BaseApp 时--file-token传app_token。 - 这是高风险写操作;执行前先确认
app_token来自+app-get或+workspace-entity-list。
Page
本期不支持的 Page 能力
Page 复制和页面图标均不在本期范围。用户提出复制 Page、复制页面、克隆页面、沿用页面图标、设置或修改页面图标等需求时:
- 明确说明当前 CLI 不支持该能力,并确认本次没有执行任何写入。
- 不得调用
+app-page-create冒充完整复制;空 Page 不包含原 Page 的内容、组件或图标。 - 不得尝试使用其他 shortcut 拼装、模拟或声称完成 Page 复制或图标设置。
- 在最终答复中将以下替代能力单独成段说明,但不要自动执行:
可用替代能力(本次未执行):当前 CLI 可以新建一个空 Page,但不会复制原 Page 的内容、组件或图标。如需新建空 Page,请明确告诉我。
只有用户后续明确要求新建空 Page,才可以调用 +app-page-create。
lark-cli base +app-page-list --app-token <app_token>
lark-cli base +app-page-create --app-token <app_token> --name "总览"
lark-cli base +app-page-update --app-token <app_token> --page-id <page_id> --name "经营总览"
lark-cli base +app-page-delete --app-token <app_token> --page-id <page_id> --yes- 同一 App 内 Page 名称必须唯一。创建或更新名称前,CLI 会读取页面列表;更新时排除当前 Page。
- 同一 Page 内组件名称必须唯一。
+app-block-create会分页读取该 Page 的全部组件并在创建前检查重名。 - 本期没有 Page arrange,也没有 Block delete;Block 的
type/sub_type创建后不可修改。详见本期不支持的能力。
本期不支持的能力
下列能力本期不存在。用户提出时,直接说明不支持并给出可选的替代方向,不要用 Dashboard 或其他域的同名能力顶替。
| 用户诉求 | 本期状态 | 正确动作 |
|---|---|---|
| 自动排版 / 重新布局 / 美化页面组件 | 没有 App page arrange | 直接告知不支持;不要调用 +dashboard-arrange |
| 删除页面组件 | 没有 App block delete | 直接告知不支持,只能在 UI 处理;不要调用 +dashboard-block-delete |
| 修改组件位置 / 大小 / 置顶 | 布局、位置、尺寸不属于公开 Create/Update 协议 | 直接告知不支持;不要用 +app-block-update 做空更新伪装成移动 |
修改已有组件的 type/sub_type | type/sub_type 创建后不可修改 | 先读取当前 Block;无论是否已为目标类型,最终答复都要说明此约束。已匹配时说明无需写入;不匹配时说明只能在 UI 处理;不得调用或承诺用 +app-block-update 修改类型 |
| 修改已存在 App 的主题 | --theme-style 只在 +app-create 时生效 | 直接告知不支持;如确有必要,说明只能新建 App 时指定主题 |
读取或修改 type=unsupported 的组件 | 列表仅用于识别该组件存在,详情读取、计算数据读取和修改均不支持 | 直接告知不支持;不要调用 +app-block-get、+app-block-get-data 或 +app-block-update,这些请求会报错 |
+dashboard-* 命令只作用于 Base 内的仪表盘,dashboard_id 是 blk 开头、组件 ID 是 cht 开头;AppMode 的 pge 页面和 wgt 组件不属于它们的作用域。缺少能力时不要用这些命令试探,包括 --help 和 --dry-run:一次调用就是一次错误的能力归属判断。
列表组件
创建列表时使用 --type list 与 --sub-type standard|grouped|collapsible|card|detail。省略 --sub-type 时默认 standard。
lark-cli base +app-block-create \
--app-token <app_token> \
--page-id <page_id> \
--name "待处理订单" \
--type list \
--sub-type standard \
--data-config '{"base_token":"<base_token>","table_name":"订单"}'data_config.base_token是单值:每个列表最多选择一个 Base。- Base 必须在当前 App 的同一个 Workspace;CLI 写入前校验。
- 完整字段协议读 lark-base-app-block-data-config.md。
更新组件
+app-block-update 只发送显式传入的 data_config 字段。未传字段保持不变;数组或对象字段是否整体替换,以组件配置 reference和服务端校验结果为准。不要为了“补全”先读取并提交全量配置。
常见恢复
| 现象 | 动作 |
|---|---|
status=partial | 告知已完成/失败步骤;用户要求继续时执行 retry.command |
| Page 重名 | 先 +app-page-list,选择唯一名称后重试 |
| 组件重名 | 先 +app-block-list,为该 Page 内的新组件选择唯一名称后重试 |
| 列表 Base 不在同一 Workspace | 用 +workspace-entity-list 核对;选择同 Workspace Base |
| 列表协议校验失败 | 读取组件协议文档;不要推断 title、group_by 数量或 field role |
| Block 类型选错 | 本期无法删除且类型不可改,只能在 UI 处理后重新创建 |
| 用户要 arrange / 删组件 / 调位置 / 改主题 | 按本期不支持的能力直接告知不支持;不要改用 +dashboard-* 命令 |
base CellValue 规范(lark-base-cell-value)
适用命令:
lark-cli base +record-batch-create、lark-cli base +record-batch-update
本文件定义 shortcut 写记录 时 CellValue 的推荐格式,目标是让 AI 一次写对。不同命令的外层 JSON 形状不同,但每个 cell 都以本文为 source of truth。
1. 顶层规则(必须遵守)
--json必须是 JSON 对象。+record-batch-create --json使用{"create_records":[{"字段名或字段ID": CellValue}, ...]},数组中的每个对象代表一条新 Record。+record-batch-update --json使用{"update_records":{"rec_xxx":{"字段名或字段ID": CellValue}, ...}},以record_id定位每条待更新 Record。- 一次 payload 里同一字段只用一种 key(字段名或字段 ID),不要重复。
- 写入前先
+field-list获取字段type/style/multiple,再构造值。 - 需要清空字段时优先传
null(字段允许清空时)。
2. 各类型 CellValue
2.1 text
text 字段的 style.type 影响单元格检查逻辑: type=plain 传 Markdown 格式的字符串。 type=url 传一个带 title 的 Markdown 格式链接,或单独传一个链接。 type=phone 传合法电话号码。 type=email 传合法邮箱字符串。
{
"标题": "Hello, [lark-cli](https://github.com/larksuite/cli)",
"官网": "[官网](https://example.com)",
"联系电话": "1380000000000",
"邮箱": "owner@example.com"
}2.2 number
用 JSON number,不要用带单位或千分位的字符串。货币、百分比、进度、评分等数字类字段也按数字写入,展示格式由字段配置决定。
{
"工时": 12.5,
"预算": 3000,
"完成度": 0.65,
"评分": 4
}2.3 select(单选/多选)
select 字段统一传选项名称数组。multiple=false 时数组只能包含一个元素,multiple=true 时可以包含多个元素。只支持写入字段中已有的选项;构造 CellValue 前先用 +field-list 或 +field-search-options 确认目标选项存在。
{
"单选": ["Todo"],
"多选": ["后端", "高优"]
}读取单元格时与写入的数据结构一致。
2.4 datetime
写入可省略时区偏移量,系统会按 Base 时区解析输入字符串;优先使用 YYYY-MM-DD HH:mm。Base 默认按分钟展示,但底层以毫秒级精度存储时间
{
"截止时间": "2026-03-24 10:00"
}读取单元格时,日期时间输出为标准 RFC3339 字符串并固定保留三位毫秒,例如 "2026-03-24T10:00:00.000+08:00"。
2.5 checkbox
用 JSON boolean:true 或 false,不要用 "true"、"是"、1。
{
"已完成": true
}2.6 user / group_chat
user 和 group_chat 字段统一传对象数组。multiple=false 时数组只能包含一个元素,multiple=true 时可以包含多个元素。每个元素至少包含 id;人员字段传用户 ID(如 ou_xxx),群字段传群 ID(如 oc_xxx)。
人员字段:不要猜 ID。 不知道
open_id时,先用lark-contact查 id:lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user。
群组字段:不要猜 ID。 不知道
chat_id时,先用lark-im搜群:lark-cli im +chat-search --query "<群名关键词>" --as user;取结果里的oc_xxx。
{
"负责人": [
{ "id": "ou_xxx" },
{ "id": "ou_xxx2" }
],
"协作群": [
{ "id": "oc_xxx" }
]
}读取单元格时仍为对象数组,每个元素为 {id, name},例如 [{"id":"ou_xxx","name":"张三"}]。
2.7 link
用对象数组,元素包含 id,值为目标记录的 record_id。不要传记录标题;先用 +record-list / +record-search 找到目标记录 ID。
{
"关联任务": [
{ "id": "<record_id>" }
]
}读取单元格时与写入的数据结构一致。
2.8 location
- 读取:
{lng, lat, full_address},三个成员均非空。 - 写入:
{lng, lat},经纬度均为数字;full_address由平台根据坐标解析,不允许手动指定。 - 筛选行为:按照
full_address做字符串筛选,将 Location 当作文本列使用文本 operator。
{
"坐标": {
"lng": 116.397428,
"lat": 39.90923
}
}2.9 attachment(不作为普通 CellValue 写入)
读取单元格时,附件为数组,每个元素为 {file_token, size, name},例如 [{"file_token":"box_xxx","size":1024,"name":"report.pdf"}]。
- 追加附件:使用
lark-cli base +record-upload-attachment --record-id <record_id> --field-id <field_id> --file <path>;可重复--file一次追加多个附件,不能用普通记录操作接口写附件值。 - 删除附件:使用
lark-cli base +record-remove-attachment --record-id <record_id> --field-id <field_id> --file-token <file_token> --yes;可重复--file-token一次删除同一单元格里的多个附件。 - 下载附件:使用
lark-cli base +record-download-attachment --record-id <record_id> --file-token <file_token> --output <dir>;不传--file-token时下载整行所有附件,也可重复--file-token只下载指定附件。Base 附件必须用这个命令下载,用其他下载入口可能失败。
3. 只读字段(不要写)
写记录时,auto_number、lookup、formula、created_at/updated_at、created_by/updated_by 均为只读字段。
写入只读字段通常不会更新数据;返回里可能出现 ignored_fields,reason 会说明 READONLY。看到这种返回时,不要重试同一 payload,应移除只读字段,只写存储字段。
读取单元格时,auto_number、formula、lookup 为 string | null;created_at、updated_at 为 RFC3339 字符串或 null;created_by、updated_by 为 array<{id, name}>。
4. 完整示例
{
"标题": "Created from shortcut",
"状态": ["Todo"],
"标签": ["高优", "外部依赖"],
"工时": 8,
"截止时间": "2026-03-24 10:00",
"已完成": false,
"负责人": [{ "id": "ou_123" }],
"关联任务": [{ "id": "rec_456" }],
"坐标": { "lng": 116.397428, "lat": 39.90923 }
}Base Dashboard Block 配置
Block 的 data_config 字段因 type 不同而变化。本文档是 Dashboard block 扁平单数据源 data_config 的单一事实来源(SSOT),包含组件类型、字段结构、筛选格式、约束和可复制模板。BaseApp 图表的外层结构不同,但每个 data_sources[] 元素复用本文的字段取值、筛选、分组、排序及规范化规则;创建或更新 App 组件时,还必须读取 BaseApp Block data_config 了解共享 base_token、多数据源封装,以及 App 独有的列表组件协议。
支持的组件类型(type 枚举)
| type 值 | 说明 |
|---|---|
column | 柱状图 |
bar | 条形图 |
line | 折线图 |
pie | 饼图 |
ring | 环形图 |
area | 面积图 |
combo | 组合图 |
scatter | 散点图 |
funnel | 漏斗图 |
wordCloud | 词云 |
radar | 雷达图 |
statistics | 指标卡 |
text | 文本(支持 Markdown) |
字段类型与操作符速查(AI 决策用)
先用
+field-list/+field-get确认字段type;本节使用当前字段接口里的 canonical 类型名:number、text、select、datetime、checkbox、user。
text: is, isNot, contains, doesNotContain, isEmpty, isNotEmpty
number: is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty
select(multiple=false): is, isNot, isEmpty, isNotEmpty
select(multiple=true): is, isNot, contains, doesNotContain, isEmpty, isNotEmpty
datetime: is, isGreater, isLess, isEmpty, isNotEmpty
checkbox: is (value: true/false)
user / created_by / updated_by: is, isNot, isEmpty, isNotEmptyisGreaterEqual / isLessEqual 不是全局不支持:它们可用于 number,但不能用于 datetime / created_at / updated_at。日期范围必须用 isGreater / isLess 配合 ExactDate;不要把数字字段的操作符集合套到日期字段上。
data_config 通用结构
| 字段 | 类型 | 说明 |
|---|---|---|
table_name | string | 关联数据表名称 |
series | [{ "field_name": "xxx", "rollup": "SUM" }] | 指标/Y 轴(与 count_all 二选一)。rollup 支持 SUM / MAX / MIN / AVERAGE |
count_all | boolean | COUNTA 聚合,统计所有记录数(与 series 二选一) |
group_by | [{ "field_name": "xxx", "mode": "integrated", "sort": {...} }] | X 轴分组维度。mode 必填,sort 可选,见下方说明 |
filter | object | 筛选条件 |
filter.conjunction | "and" / "or" | 筛选逻辑 |
filter.conditions | [{ "field_name", "operator", "value" }] | 筛选条件数组,value 类型因字段类型而异(见下方 filter 格式规则) |
text 类型特殊结构
text 类型组件用于展示富文本内容,不需要数据源配置(无 table_name、series、group_by、filter)。
| 字段 | 类型 | 说明 |
|---|---|---|
text | string | 必填。支持 Markdown 语法,详见下方说明 |
支持的 Markdown 语法:
| 语法 | 示例 | 效果 |
|---|---|---|
| 一级标题 | # 标题 | 大标题 |
| 二级标题 | ## 标题 | 中标题 |
| 三级标题 | ### 标题 | 小标题 |
| 加粗 | **文字** | 文字 |
| 斜体 | *文字* | 文字 |
| 删除线 | ~~文字~~ | ~~文字~~ |
| 有序列表 | 1. 项目 | 1. 项目 |
| 无序列表 | - 项目 | - 项目 |
注意:以上未提及的 Markdown 语法(如链接、图片、代码块、表格等)均不支持。
group_by 详细说明
mode 枚举
| mode | 含义 | 适用场景 |
|---|---|---|
integrated | 聚合分组(默认) | 绝大部分场景,按字段值分组统计 |
enumerated | 多值拆分统计 | 多选、人员等多值字段,将每个选项/人员拆开独立统计 |
多选、人员等多值字段默认用
enumerated;其他字段默认用integrated。
sort 排序
| sort.type | 含义 | 典型场景 |
|---|---|---|
group | 按横轴值排序 | 按月份升序、按品类名字母序 |
value | 按纵轴值排序 | 按销售额从大到小 |
view | 按数据源记录顺序 | 保持原表行序(不常用) |
sort.order:asc(升序)/ desc(降序)
只要写 sort 对象,就需要明确排序方向。CLI 会把 sort.type 为 group 或 view 且缺少 order 的情况规范化为 order:"asc";sort.type:"value" 必须显式写 order:"asc" 或 order:"desc",因为指标值排序方向会改变业务含义。
如果表中行序就是业务顺序,首次创建 block 时就一次性设置 sort:{"type":"view","order":"asc"} 保留行序,避免创建后再二次更新排序条件。
示例 — 柱状图按销售额降序:
{
"table_name": "订单表",
"series": [{ "field_name": "金额", "rollup": "SUM" }],
"group_by": [{ "field_name": "类别", "mode": "integrated", "sort": {"type": "value", "order": "desc"} }]
}filter 格式规则
基本结构:
{
"filter": {
"conjunction": "and",
"conditions": [
{ "field_name": "字段名", "operator": "操作符", "value": "值" }
]
}
}多条件示例(and/or):
{
"filter": {
"conjunction": "and",
"conditions": [
{ "field_name": "状态", "operator": "is", "value": "已完成" },
{ "field_name": "金额", "operator": "isGreater", "value": 1000 }
]
}
}操作符:
| 操作符 | 含义 | 是否需要 value |
|---|---|---|
is | 等于 | 是 |
isNot | 不等于 | 是 |
contains | 包含 | 是 |
doesNotContain | 不包含 | 是 |
isEmpty | 为空 | 否 |
isNotEmpty | 不为空 | 否 |
isGreater | 大于 | 是 |
isGreaterEqual | 大于等于 | 是 |
isLess | 小于 | 是 |
isLessEqual | 小于等于 | 是 |
各字段类型的 value 格式:
| 字段类型 | value 类型 | 适用操作符 | 示例 |
|---|---|---|---|
text | string | is, isNot, contains, doesNotContain, isEmpty, isNotEmpty | {"field_name":"姓名","operator":"contains","value":"张"} |
number | number | is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty | {"field_name":"金额","operator":"isGreater","value":0} |
select (multiple=false) | string(选项名) | is, isNot, isEmpty, isNotEmpty | {"field_name":"状态","operator":"is","value":"已完成"} |
select (multiple=true) | string[](选多个)/ string(选单个) | is, isNot, contains, doesNotContain, isEmpty, isNotEmpty | 多选传数组如 ["标签1","标签2"];单选传单个字符串 |
datetime / created_at / updated_at | ["ExactDate", Unix 毫秒时间戳] | is, isGreater, isLess, isEmpty, isNotEmpty | {"field_name":"创建日期","operator":"isGreater","value":["ExactDate",1704038400000]} |
checkbox | boolean | is | {"field_name":"已审核","operator":"is","value":true} |
user / created_by / updated_by | string 或 string[](用户 ID,格式 ou_xxx)。不知道 open_id 时先用 lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user 查 id。 | is, isNot, isEmpty, isNotEmpty | {"field_name":"负责人","operator":"is","value":"ou_xxxxxxxxxxxxxxxx"} |
| 所有类型(为空/不为空) | 不需要 value | isEmpty, isNotEmpty | {"field_name":"备注","operator":"isEmpty"} |
value类型因字段而异,可为string | number | boolean | string[] | ["ExactDate", number],需按上表构造。
日期筛选
图表 data_config.filter 筛选 datetime / created_at / updated_at 字段时:
- 有值条件只能使用
is、isGreater或isLess,不得使用isGreaterEqual或isLessEqual。 value必须写成["ExactDate", <Unix 毫秒时间戳>],不得直接传裸时间戳。isEmpty/isNotEmpty不传value。
日期区间示例:
{
"filter": {
"conjunction": "and",
"conditions": [
{
"field_name": "派单日期",
"operator": "isGreater",
"value": ["ExactDate", 1785686400000]
},
{
"field_name": "派单日期",
"operator": "isLess",
"value": ["ExactDate", 1786032000000]
}
]
}
}约束与本地校验
- 必填与互斥
- 图表类型必填:
table_name - text 类型必填:
text - 互斥:
series与count_all二选一,且至少提供其一(仅图表类型) - text 类型不支持:
series、count_all、group_by、filter - 长度/结构
group_by最多 2 个;每项field_name必填group_by[].sort.type取值group|value|view;order取值asc|desc- 规范化(CLI 自动处理;
--no-validate时不生效,data_config原样透传给后端) series[].rollup自动转成大写(如sum→SUM)group_by[].sort.type/order自动转成小写group_by[].sort.type为group或view且缺少order时,自动补order:"asc";value排序不会自动补方向- 本地校验(可通过
--no-validate跳过) +dashboard-block-create默认对data_config做轻量校验;失败会聚合错误并给出修复建议+dashboard-block-update不做强类型校验,由后端验证具体字段- 仅需传入合法 JSON;CLI 不会擅自改写你的业务含义
可复制模板
按意图选择模板:
- 比较不同类别数值 → 柱状图 / 条形图
- 看趋势变化 → 折线图 / 面积图
- 看占比分布 → 饼图 / 环形图 / 词云
- 多指标对比 → 组合图
- 看两变量关系 → 散点图
- 看流程转化 → 漏斗图
- 看多维度评分 → 雷达图
- 显示单个指标 → 指标卡(统计数字或记录数)
最小柱状图:
{
"table_name": "表名",
"series": [{ "field_name": "数值字段", "rollup": "SUM" }],
"group_by": [{ "field_name": "分组字段", "mode": "integrated" }]
}最小饼图/环形图(按分类字段统计行数占比):
{
"table_name": "表名",
"count_all": true,
"group_by": [{ "field_name": "分类字段", "mode": "integrated" }]
}折线图(按月趋势):
{
"table_name": "表名",
"series": [{ "field_name": "金额", "rollup": "SUM" }],
"group_by": [{ "field_name": "月份", "mode": "integrated", "sort": {"type":"group","order":"asc"} }]
}条形图(横向柱状图):
{
"table_name": "表名",
"series": [{ "field_name": "数值字段", "rollup": "SUM" }],
"group_by": [{ "field_name": "分组字段", "mode": "integrated" }]
}面积图(趋势填充):
{
"table_name": "表名",
"series": [{ "field_name": "数值字段", "rollup": "SUM" }],
"group_by": [{ "field_name": "时间字段", "mode": "integrated", "sort": {"type":"group","order":"asc"} }]
}组合图(柱+线等多指标对比):
{
"table_name": "表名",
"series": [
{ "field_name": "指标1", "rollup": "SUM" },
{ "field_name": "指标2", "rollup": "SUM" }
],
"group_by": [{ "field_name": "分类字段", "mode": "integrated" }]
}散点图(两变量相关性):
{
"table_name": "表名",
"series": [{ "field_name": "Y轴字段(数值/指标)", "rollup": "SUM" }],
"group_by": [{ "field_name": "X轴字段(分类/维度)", "mode": "integrated" }]
}漏斗图(流程转化):
先判断用户要看的数值语义:
- 当前数量:统计每个当前状态/阶段下有多少记录,例如“各环节当前数量”“当前阶段分布”。源表有状态/阶段字段时,直接用
count_all:true+group_by。 - 累计数量:统计到达该阶段及其后续阶段(后缀和)的累计数量,例如“流程转化”“从 A 到 B 各环节转化”。此口径假设流程单向、无跳阶/回退、记录不删除;不满足时须用状态变更历史,不能对当前快照累加。如果表中已有累计数量字段或阶段汇总表,直接用该字段画漏斗图;否则先计算累计数量,创建并写入 helper 汇总表后再画图。
当前数量:
{
"table_name": "表名",
"count_all": true,
"group_by": [{ "field_name": "状态字段", "mode": "integrated" }]
}累计数量:
{
"table_name": "流程汇总表名",
"series": [{ "field_name": "累计数量", "rollup": "SUM" }],
"group_by": [{ "field_name": "阶段字段", "mode": "integrated", "sort": {"type":"view","order":"asc"} }]
}如果只有当前状态数据但用户要看流程转化,需要先按业务阶段顺序计算每个阶段的累计数量,再创建 helper 汇总表(如:阶段、累计数量),用 +record-batch-create 一次写入后,按“累计数量”模板创建漏斗图。helper 表行序就是业务顺序时,首次创建 block 时一次性设置好 group_by.sort。
⚠️ 注意:helper 汇总表仅用于源表无法直接聚合出目标形态的场景(如上面的累计数量漏斗图)。只要能在源表上直接用
group_by+rollup(含AVERAGE)算出,就不需要新建 helper 表。
词云(文本频率):
{
"table_name": "表名",
"count_all": true,
"group_by": [{ "field_name": "文本字段", "mode": "integrated" }]
}雷达图(多维度评分):
{
"table_name": "表名",
"series": [
{ "field_name": "维度1", "rollup": "SUM" },
{ "field_name": "维度2", "rollup": "SUM" },
{ "field_name": "维度3", "rollup": "SUM" }
],
"group_by": [{ "field_name": "分类字段", "mode": "integrated" }]
}指标卡(统计数字):
{
"table_name": "数据表",
"series": [{ "field_name": "数字", "rollup": "SUM" }]
}指标卡(统计记录数):
{
"table_name": "数据表",
"count_all": true
}文本组件(Markdown 富文本):
{
"text": "# 🚀 一级标题\n这是一个 **加粗** *斜体* ~~删除线~~ 的示例。\n\n## 📌 二级标题\n1. 有序列表项 1\n2. 有序列表项 2\n\n### 📌 三级标题\n- 无序列表项 1\n- 无序列表项 2"
}注意:text 类型组件不需要
table_name、series、group_by、filter等数据源相关字段。
常见错误与修复
- 同时存在
series与count_all - 现象:后端/本地校验报互斥错误
- 修复:见「关键约束」章节的二选一规则
- 缺少
table_name - 现象:本地校验缺少必填字段
- 修复:指定数据源表名(使用表名,非表 ID)
series[].rollup大小写/取值不合法- 现象:本地校验提示枚举不支持
- 修复:改为
SUM|MAX|MIN|AVERAGE中之一(不区分大小写,CLI 会统一为大写;计数请使用count_all:true) group_by超出 2 个或字段名为空- 修复:保留前 2 个,或补齐
field_name - 排序枚举不合法
- 修复:
group_by.sort.type仅能为group|value|view;order为asc|desc - filter 写法不规范
- 修复:
conjunction取and|or;conditions[].operator必须在本页表格列举的范围内;除isEmpty/isNotEmpty外需提供value
坑点
count_all与series二选一 — 两者不能同时使用- filter
value类型因字段而异 — 文本/单选为 string,数字为 number,日期为毫秒时间戳,多选/人员可为 string[],复选框为 boolean;isEmpty/isNotEmpty不需要 value data_config结构随type变化 — 不同组件类型的字段不同,创建前务必确认类型对应的字段- 表名用 name,不是 ID —
table_name对应的是表名称(如「订单表」),不是table_id
base +dashboard-block-get-data
前置条件: 先阅读 lark-base-dashboard.md 了解 dashboard 整体工作流。
获取仪表盘图表组件(block)的最终计算结果,返回一份适合 AI 直接消费的图表协议 JSON。
这个命令适合以下场景:
- 读取柱状图 / 条形图 / 折线图 / 饼图 / 环形图 / 面积图 / 组合图 / 散点图 / 漏斗图 / 雷达图 / 词云 / 指标卡的实际计算结果;
- 把图表结果交给 AI 做后续总结、趋势解释、同比/环比说明、异常点提取;
- 在不读取原始记录的前提下,直接消费图表层已经聚合好的结果;
- 验证某个图表当前展示的数据是否符合预期。
[!IMPORTANT] - 本命令返回的是图表结果协议,不是 block 元数据; - 如果你需要
name、type、layout、data_config等配置,请先用+dashboard-block-get; - 文本组件(text)不涉及计算,不适用本命令;
一句话理解
+dashboard-block-get-data = 拿图表“算出来的结果”,而不是拿图表“怎么配置的”。
支持的图表类型
当前支持以下图表类型的数据计算与返回:
二维图表(10 种)
- 柱状图
- 条形图
- 折线图
- 饼图
- 环形图
- 面积图
- 组合图
- 散点图
- 漏斗图
- 雷达图
特殊类型(2 种)
- 词云
- 指标卡(statistics)
[!CAUTION] 文本组件虽然也属于 dashboard block,但它不产生可计算数据,因此不会返回本协议。
推荐命令
lark-cli base +dashboard-block-get-data \
--base-token bascn***************CtadY \
--block-id chtxxxxxxxx如果你还不知道目标 block 的 ID,典型顺序是:
# 先看仪表盘里有哪些组件
lark-cli base +dashboard-block-list \
--base-token bascn***************CtadY \
--dashboard-id blkxxxxxxxx \
--page-size 100
# 再读取某个组件的最终计算结果
lark-cli base +dashboard-block-get-data \
--base-token bascn***************CtadY \
--block-id chtxxxxxxxx如果用户要读取多个组件,先通过 +dashboard-block-list --page-size 100 取得真实 ID;若返回 has_more=true,继续把本页返回的 page_token 传给 --page-token,直到 has_more=false。收齐目标组件并跳过没有计算结果的文本组件后,再在一个 shell 工具调用内串行执行。每条命令会依次输出一个完整 JSON envelope;不要把每个 block 拆成独立模型轮次。
set -euo pipefail
block_ids=(cht_block_1 cht_block_2)
for block_id in "${block_ids[@]}"; do
lark-cli base +dashboard-block-get-data \
--base-token bascn***************CtadY \
--block-id "$block_id"
done数组中的 ID 必须逐字来自 +dashboard-block-list 返回,不要把名称或未经验证的用户文本作为 shell 代码执行。循环仍然是串行 API 调用,只减少模型往返,不裁剪任何组件结果。
如果你需要先确认组件类型、名称或 data_config,请先执行:
lark-cli base +dashboard-block-get \
--base-token bascn***************CtadY \
--dashboard-id blkxxxxxxxx \
--block-id chtxxxxxxxx参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token,标识目标多维表格 |
--block-id <id> | 是 | 图表 Block ID,即目标组件的唯一标识 |
--format <fmt> | 否 | 输出格式,遵循 CLI 全局输出格式规则 |
--dry-run | 否 | 只预览 API 调用,不真正执行 |
[!TIP] 这个命令不需要
--dashboard-id。只要base_token + block_id即可定位并读取图表结果。
返回结构总览
CLI 成功输出使用标准 {ok, identity, data} 信封:
{
"ok": true,
"identity": "user",
"data": {
"dimensions": [],
"measures": [],
"main_data": []
}
}其中 identity 是本次调用实际使用的身份,data 是 CLI 图表协议本体。不同图表类型的 data 结构略有不同:
| 图表类型 | 一定有 | 可能有 |
|---|---|---|
| 二维图表 | dimensions / measures / main_data | 无 |
| 词云 | dimensions / measures / main_data | 无 |
| 指标卡 | dimensions / measures / main_data | comparison_data / trend_data |
协议字段说明
1) dimensions
维度定义数组,告诉你主结果里每个 dim_* key 代表什么字段。
[
{
"field_name": "文本",
"alias": "dim_5bKp"
}
]字段含义:
| 字段 | 说明 |
|---|---|
field_name | 维度字段显示名称 |
alias | 维度别名,在 main_data / trend_data 中作为 key 使用 |
2) measures
指标定义数组,告诉你每个 me_* key 代表什么聚合指标。
[
{
"field_name": "Count",
"aggregation": "count_all",
"alias": "me_Y291bnRfYWxsX0NvdW50"
}
]字段含义:
| 字段 | 说明 |
|---|---|
field_name | 统计该指标时所使用的字段名称;当 aggregation = count_all 时固定为 Count,表示统计记录总数 |
aggregation | 聚合方式,常见值:count_all / count / sum / avg / min / max |
alias | 指标别名,在 main_data / comparison_data / trend_data 中作为 key 使用 |
例如:
- 如果统计“销售额”的求和,则
field_name = 销售额、aggregation = sum - 如果统计记录总数,则
field_name = Count、aggregation = count_all
3) main_data
主结果集。每一行都是一个对象,key 不是字段名本身,而是 dimensions / measures 中声明过的 alias。
[
{
"dim_5bKp": {"value": "A"},
"me_Y291bnRfYWxsX0NvdW50": {"value": 3}
}
]4) comparison_data
仅指标卡可能返回。表示同/环比的两个值,顺序固定为:
- 当前周期值
- 对比周期值
[!NOTE] 原始协议里通常不直接展示周期名称,只提供对应的值。因此解释“同比”还是“环比”、以及比较窗口具体是什么,通常要结合组件配置或 UI 上下文理解。
5) trend_data
仅指标卡可能返回。表示时间序列趋势,每一行通常包含一个时间维度和一个指标值。
alias 规则与读取方式
你不应该把 alias 当成人类可读字段名,而应把它视为结果表里的列 ID。
常见生成规则:
- 维度 alias:
dim_+base64(field_name) - 指标 alias:
me_+base64(aggregation + "_" + field_name)
[!NOTE] 为了便于阅读,本文档中的部分示例会使用简化后的 alias(例如
dim_xxx、me_xxx或较短的示例值),不保证和真实返回值逐字符一致。 在实际读取结果时,应始终以dimensions/measures中声明的 alias 为准,而不要假设所有示例都严格展开成完整编码值。
例如:
{
"dimensions": [
{"field_name": "文本", "alias": "dim_5bKp"}
],
"measures": [
{"field_name": "Count", "aggregation": "count_all", "alias": "me_xxx"}
],
"main_data": [
{
"dim_5bKp": {"value": "A"},
"me_xxx": {"value": 3}
}
]
}应解读为:
dim_5bKp对应字段“文本”,取值是Ame_xxx对应指标count_all(Count),取值是3
[!TIP] 读取结果时,先看
dimensions/measures,再解main_data。不要仅凭 alias 名字猜含义。
各图表类型的协议细节
一、二维图表
适用于:柱状图、条形图、折线图、饼图、环形图、面积图、组合图、散点图、漏斗图、雷达图。
结构特征
dimensions:通常有1~2个维度- 不分组聚合时:通常 1 个维度
- 开启分组聚合时:通常 2 个维度
measures:指标定义数组main_data:按“维度组合”展开后的行数据
这类数据代表什么
二维图表返回的本质上是一张聚合结果表:
- 每一行代表一个维度值,或一组维度组合;
- 每一个 measure 值代表该维度下算出来的指标结果;
- 如果图表开启了分组聚合,那么每一行表示“主维度 + 分组维度”的一个组合结果;
- 如果图表是折线图、面积图这类带时间轴的图,通常可以把第一维理解为横轴、把 measure 理解为纵轴数值;
- 如果图表是饼图、环形图这类占比图,通常可以把每一行理解为一个扇区对应的分类及其数值。
换句话说,AI 在读取这类结果时,可以把它当作“按某些维度聚合后的统计明细表”,适合进一步做排序、Top N、占比解释、分组对比和趋势总结。
示例 1:普通二维图表(无分组聚合)
{
"dimensions": [
{
"field_name": "文本",
"alias": "dim_5bKp"
}
],
"measures": [
{
"aggregation": "count_all",
"field_name": "Count",
"alias": "me_Y291bnRfYWxsX0NvdW50"
}
],
"main_data": [
{
"dim_5bKp": {"value": "A"},
"me_Y291bnRfYWxsX0NvdW50": {"value": 3}
},
{
"dim_5bKp": {"value": "B"},
"me_Y291bnRfYWxsX0NvdW50": {"value": 2}
},
{
"dim_5bKp": {"value": "C"},
"me_Y291bnRfYWxsX0NvdW50": {"value": 2}
}
]
}可解读为:
- 维度字段是“文本”
- 指标是“按记录总数统计”
- 当“文本”字段为
A时,对应的Count指标值是3 - 当“文本”字段为
B时,对应的Count指标值是2 - 当“文本”字段为
C时,对应的Count指标值是2
示例 2:二维图表(开启分组聚合)
{
"dimensions": [
{
"field_name": "文本",
"alias": "dim_5bKp"
},
{
"field_name": "单选",
"alias": "dim_5aSl"
}
],
"measures": [
{
"aggregation": "count_all",
"field_name": "Count",
"alias": "me_YW91bnR"
}
],
"main_data": [
{
"dim_5bKp": {"value": "A"},
"dim_5aSl": {"value": "a-1"},
"me_YW91bnR": {"value": 2}
},
{
"dim_5bKp": {"value": "A"},
"dim_5aSl": {"value": "a-2"},
"me_YW91bnR": {"value": 1}
},
{
"dim_5bKp": {"value": "B"},
"dim_5aSl": {"value": "b-1"},
"me_YW91bnR": {"value": 1}
},
{
"dim_5bKp": {"value": "C"},
"dim_5aSl": {"value": "c-1"},
"me_YW91bnR": {"value": 2}
}
]
}可解读为:
- 第一维是“文本”,第二维是“单选”,指标是“按记录总数统计”
- 当“文本”字段为
A、且“单选”字段为a-1时,对应的指标值是2 - 当“文本”字段为
A、且“单选”字段为a-2时,对应的指标值是1 - 当“文本”字段为
B、且“单选”字段为b-1时,对应的指标值是1 - 当“文本”字段为
C、且“单选”字段为c-1时,对应的指标值是2 - 如果按“文本”字段汇总,那么“文本”字段为
A时总指标值是3;为B时总指标值是1;为C时总指标值是2
二、词云
结构特征
词云协议仍然沿用 dimensions + measures + main_data 的结构,但语义稍有不同:
dimensions对应被分词的字段;main_data每一行代表一个词;measure的 value 表示按该词分组后计算出来的统计值。
这类数据代表什么
词云返回的不是“原文列表”,而是按词分组后的聚合统计结果:
dimensions定义的是被分词的来源字段;measure对应的是该词在当前图表统计范围内对应的统计值,具体含义取决于聚合方式和指标字段;main_data的每一行都可以理解成“某个词 + 该词对应的统计结果”,其中该维度的具体 value 就是拆分出来的词;- 返回结果通常已经结合图表当前过滤条件、时间范围、数据权限等上下文计算完成。
因此,AI 读取词云数据时,更适合做“关键词排序”“热点词解释”“按词聚合结果分析”“主题归纳”,而不是把它当成逐条文本记录去理解。
示例
{
"dimensions": [
{
"field_name": "文本",
"alias": "dim_5bKp"
}
],
"measures": [
{
"aggregation": "count_all",
"field_name": "Count",
"alias": "me_YW91bnR"
}
],
"main_data": [
{
"dim_5bKp": {"value": "A"},
"me_YW91bnR": {"value": 3}
},
{
"dim_5bKp": {"value": "B"},
"me_YW91bnR": {"value": 2}
},
{
"dim_5bKp": {"value": "C"},
"me_YW91bnR": {"value": 2}
}
]
}可解读为:
- 被统计的分词字段是“文本”
- 当前示例里的 measure 是
count_all(Count),所以这里的统计值可以理解为“按词分组后的记录总数” - 当分词结果为
A时,对应的统计值是3 - 当分词结果为
B时,对应的统计值是2 - 当分词结果为
C时,对应的统计值是2 - 按统计值排序,分词结果
A对应的值最高 - 分词结果
B和C的统计值相同,说明它们处于同一梯队
三、指标卡(statistics)
指标卡除了主值外,还可能包含同/环比与趋势结果,是本命令里结构最特殊的一类。
结构特征
measures:有且仅有一个指标main_data:通常只有一行,表示总指标值comparison_data:可选,表示当前周期值与对比周期值trend_data:可选,表示趋势序列dimensions:可能包含同/环比日期字段、趋势日期字段
这类数据代表什么
指标卡返回的核心是一个主指标摘要,外加可选的比较信息和趋势信息:
main_data表示当前卡片最核心、最醒目的那个主值;它通常是某个表的记录总数,或某个字段的聚合值,本身不带时间周期概念;comparison_data表示用于同/环比展示的两个数值,通常是“当前周期值”和“对比周期值”;它们表示某个时间周期下的记录总数,或某个字段的聚合值;trend_data表示这个指标在一段时间内的变化轨迹,用来支持走势判断;dimensions在指标卡里通常不是拿来做主分组展示,而是给trend_data或同/环比相关日期字段提供语义说明。
例如:
main_data = 7可以理解为当前卡片展示的主数据,比如某张表当前总记录数是7;comparison_data[0] = 6则表示某个比较周期下的当前值,比如“本月记录总数 = 6”;- 因此,
main_data与comparison_data[0]不一定相等,因为两者表达的口径并不完全相同。
因此,AI 在解读指标卡时,应该优先回答这几个问题:
- 当前主值是多少;
- 和对比周期相比是上升、下降还是持平;
- 趋势整体是增长、波动还是下滑;
- 是否存在明显的异常峰值或低谷。
[!NOTE] 当指标卡同时指定同/环比和趋势时,
dimensions中日期维度的顺序是固定的: 1. 第一个元素是趋势对应的日期维度; 2. 第二个元素是同/环比对应的日期维度。另外要注意:
comparison_data自身通常不直接携带日期字段,它只给出“当前周期值 / 对比周期值”。dimensions中的第一个日期维度会直接出现在trend_data中,作为趋势序列的时间列; 第二个日期维度则主要用于补充“该卡片配置了哪类比较相关日期字段”的语义。
示例
{
"dimensions": [
{
"field_name": "日期",
"alias": "dim_ZGF0ZQ"
},
{
"field_name": "日期2",
"alias": "dim_ZGF0ZTI"
}
],
"measures": [
{
"aggregation": "count_all",
"field_name": "Count",
"alias": "me_YW91b"
}
],
"main_data": [
{
"me_YW91b": {"value": 7}
}
],
"comparison_data": [
{
"me_YW91b": {"value": 6}
},
{
"me_YW91b": {"value": 0}
}
],
"trend_data": [
{
"dim_ZGF0ZQ": {"value": "2026-01-15"},
"me_YW91b": {"value": 1}
},
{
"dim_ZGF0ZQ": {"value": "2026-01-17"},
"me_YW91b": {"value": 1}
},
{
"dim_ZGF0ZQ": {"value": "2026-03-22"},
"me_YW91b": {"value": 1}
},
{
"dim_ZGF0ZQ": {"value": "2026-04-24"},
"me_YW91b": {"value": 2}
},
{
"dim_ZGF0ZQ": {"value": "2026-05-01"},
"me_YW91b": {"value": 1}
}
]
}可解读为:
- 当前主指标值 =
7 - 当前主指标值不带时间周期概念,可理解为当前卡片主数据
- comparison_data[0] = 当前周期值
6,例如某个时间周期(如本月)下的统计值 - comparison_data[1] = 对比周期值
0 dimensions[0]对应趋势日期维度,因此实际出现在trend_data里dimensions[1]对应同/环比相关的日期维度,用来补充比较语义- trend_data 展示该指标随时间的变化序列
- 从 comparison_data 看,当前周期相较对比周期是上升的,并且对比周期值为 0
- 从 trend_data 看,这个指标并不是每天都有值,而是在若干离散日期出现
- 趋势序列里的最高点出现在
2026-04-24,值为2 - 其余出现的日期大多为
1,说明整体上有波动,但暂时没有持续快速增长的趋势
[!NOTE]
comparison_data只告诉你“当前值 / 对比值”,不额外标出日期区间文本。如果用户需要完整说明“和上周比”还是“和上月比”,通常要结合组件配置或界面上下文进一步判断。
如何正确解读返回值
建议按下面顺序阅读:
- 先看
dimensions:确认每个dim_*alias 对应哪个字段; - 再看
measures:确认每个me_*alias 是什么聚合方式; - 最后读
main_data/comparison_data/trend_data:把 alias 还原成“字段名 + 指标名”再做解释。
推荐解释模板
如果要把结果转成自然语言,建议不要只“复述数值”,而应尽量覆盖下面几个层次:
- 先解释指标含义:说明 measure 代表“记录总数”“某字段求和”“平均值”等;
- 再给出核心结果:明确当前主值、主要分类、主要组合或主要词项;
- 做排序或 Top N 提炼:指出最高、最低、前几名、同一梯队;
- 补充分组/对比关系:如果有第二维或 comparison_data,就说明比较对象和差异;
- 分析趋势或异常点:如果有时间序列,指出上升、下降、波动、峰值、低谷;
- 最后给一句结论:总结最值得关注的信息。
可参考下面模板:
- 二维图表:
- 基础模板:
按 <维度字段> 统计,当前指标 <指标含义>;其中 <维度值1>=<指标值1>,<维度值2>=<指标值2> ... - 增强模板:
按 <维度字段> 统计,当前指标表示 <指标含义>。从结果看,<Top1维度值> 的值最高,为 <Top1值>;<Top2维度值> 和 <Top3维度值> 紧随其后。若按 Top N 看,前 <N> 项合计贡献了 ...;若看低值项,<低值维度值> 最低,为 <低值>。整体上,<一句总结>
- 分组聚合图表:
- 基础模板:
按 <维度1> 统计,并以 <维度2> 分组,得到 <组合1>=<值1>,<组合2>=<值2> ... - 增强模板:
当前指标表示 <指标含义>。按 <维度1> 拆分后,不同 <维度2> 组之间存在明显差异:例如 <组合1> = <值1>,<组合2> = <值2>。如果按 <维度1> 汇总,<Top1维度1值> 总值最高,为 <汇总值>;如果看组内对比,<某组> 在 <某维度1值> 下表现最强 / 最弱。整体说明 <一句总结>
- 词云:
- 基础模板:
按分词结果统计,当前指标表示 <指标含义>;其中 <词1>=<统计值1>,<词2>=<统计值2> ... - 增强模板:
当前词云反映的是“按词分组后的 <指标含义>”。从结果看,<Top1词> 的值最高,为 <值1>,说明它是当前最突出的关键词;<Top2词>、<Top3词> 处于第二梯队。如果按 Top N 看,主要关注词集中在 <主题A>、<主题B>;如果有多个词数值接近,可归为同一热点层级。整体上,这组词更适合用来总结 <主题/热点/关注点>
- 指标卡:
- 基础模板:
当前主指标值为 <main_data>;当前周期值为 <comparison_data[0]>;对比周期值为 <comparison_data[1]>;趋势上 ... - 增强模板:
当前主指标表示 <指标含义>,主值为 <main_data>。若看周期比较,当前周期值为 <comparison_data[0]>,对比周期值为 <comparison_data[1]>,因此整体表现为 <上升/下降/持平>。若看趋势序列,最高点出现在 <日期>,值为 <峰值>;最低点出现在 <日期>,值为 <低值>;整体走势表现为 <持续增长/阶段波动/明显回落>。如果需要给出结论,可总结为:<一句总结>
[!TIP] 当用户明确要求“帮我分析”“帮我总结”“帮我找异常 / Top N / 趋势”时,优先采用增强模板,而不是只逐条复述原始数值。
常见工作流
场景 1:用户要“拿这个图表当前展示的数据”
# 如果已知 block_id,直接读结果
lark-cli base +dashboard-block-get-data \
--base-token xxx \
--block-id chtxxxxxxxx场景 2:用户说“帮我分析这个图表”,但你还不知道它是什么组件
# 先看组件配置,确认它是不是支持计算的图表类型
lark-cli base +dashboard-block-get \
--base-token xxx \
--dashboard-id blk_xxx \
--block-id chtxxxxxxxx
# 再读最终计算结果
lark-cli base +dashboard-block-get-data \
--base-token xxx \
--block-id chtxxxxxxxx场景 3:用户要找“仪表盘里哪个图的结果异常”
# 先列组件
lark-cli base +dashboard-block-list \
--base-token xxx \
--dashboard-id blk_xxx
# 再针对可疑 block 逐个取结果
lark-cli base +dashboard-block-get-data \
--base-token xxx \
--block-id chtxxxxxxxx何时优先用这个命令
- 用户说“帮我拿这个图表算出来的数据 / 结果 / 指标”
- 用户已经知道
block_id,目标是读取结果而不是看配置 - 用户后续还要让 AI 对图表结果做解释、归纳、比较、总结
- 你只关心图表层的聚合产出,不需要回到底表逐条读记录
何时不要误用
- 想看 block 的
data_config、名称、类型、布局 → 用+dashboard-block-get - 想列出仪表盘里有哪些组件 → 用
+dashboard-block-list - 想修改或新建组件 → 用
+dashboard-block-update/+dashboard-block-create - 想看原始记录明细,而不是图表聚合结果 → 回到
record-* - 目标是文本组件 → 本命令不适用
常见误区
误区 1:把这个命令当成“获取 block 详情”
不是。这个命令不返回:
- block 名称
- block 类型
- layout
data_config- 所属 dashboard 信息
这些都应该通过 +dashboard-block-get 获取。
误区 2:以为它返回的是原始记录
不是。它返回的是图表聚合后的最终结果。如果图表本身做了过滤、分组、聚合、时间窗口限制,返回值反映的是图表视角,不是原始表全量明细。
误区 3:直接把 alias 当真实字段名读
不应该。alias 只是协议里的键,必须结合 dimensions / measures 还原语义。
误区 4:看到指标卡的 comparison_data 就以为已经知道“同比/环比周期文本”
不一定。它只给出比较值,不一定给出周期标签。若要精确解释比较窗口,通常还需要组件配置或 UI 上下文。
dry-run 用途
可用来确认最终会调用的接口路径:
lark-cli base +dashboard-block-get-data \
--base-token bascn_example_token \
--block-id chtxxxxxxxx \
--dry-run \
--format pretty你应能看到类似:
GET /open-apis/base/v3/bases/bascn_example_token/dashboards/blocks/chtxxxxxxxx/data适合在以下场景使用:
- 校验
base_token/block_id是否传对; - 调试 agent 生成的命令;
- 编写自动化测试时确认请求结构。
参考
- lark-base-dashboard.md — dashboard 模块总指引
+dashboard-block-get— 获取 block 元数据- Dashboard Block 配置 — data_config 结构和组件类型说明
Dashboard(仪表盘/数据看板)模块指引
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
Dashboard 是 Base 中的数据可视化看板,可以把表格数据变成组件(图表、指标卡等)进行展示。
核心概念
- Dashboard(仪表盘):容器,包含多个组件
- Block(组件):仪表盘中的单个可视化元素(柱状图、折线图、饼图、指标卡等)
- data_config:组件的数据源配置(表名、字段、分组等)
能力速览
| 你想做什么 | 用这些命令 | 关键文档 |
|---|---|---|
| 创建/删除/改名称 | +dashboard-create/delete/update | 本页下方「仪表盘管理」 |
| 在仪表盘里添加组件 | +dashboard-block-create | 先定位 dashboard、表和字段,再读 Dashboard Block 配置 构造 data_config |
| 修改组件 | +dashboard-block-update | 先读 block 现状,再读 Dashboard Block 配置 决定替换哪些顶层 key |
| 查看仪表盘有哪些组件 | +dashboard-get 或 +dashboard-block-list | 本页下方「查看仪表盘」 |
| 读取图表计算结果 | +dashboard-block-get-data | 返回图表最终数据协议;需要 block 元数据先用 +dashboard-block-get |
| 智能重排组件布局 | +dashboard-arrange | 用户明确要求重排,或本次会话新建仪表盘的收尾整理;无法指定 x/y/w/h、精确位置或尺寸 |
典型场景工作流
场景 1:从 0 到 1 创建仪表盘
从 0 到 1 创建仪表盘时,按用户需求规划组件的类型和数量,并注意以下要点:
- 聚合方式:创建指标卡或分布图时优先把聚合写进
data_config,只有 Top N、字段取值探索、复杂筛选校验或 helper 汇总表场景才先用+data-query。 - Dry-run 边界:已按模板构造的简单指标卡、分布图、趋势图不需要逐个
--dry-run后再真实创建;只有在调试 JSON、检查请求体、复杂自造data_config或处理 API validation 错误时才 dry-run。 - 验证方式:创建接口成功返回即表示写入成功。只有结果不确定时才用一次
+dashboard-get或+dashboard-block-list确认仪表盘和组件存在;不要仅为确认创建而逐组件调用+dashboard-block-get-data。 - 布局方式:
+dashboard-arrange仅两种情况使用:① 用户明确要求美化/重排;② 本次会话中从零新建的仪表盘,建完组件后做一次性布局整理。不是创建成功的必要步骤。
示例:搭建一个销售数据分析仪表盘
# 第 1 步:创建空白仪表盘
lark-cli base +dashboard-create --base-token xxx --name "销售数据分析"
# 记录返回的 dashboard_id
# 第 2 步:获取数据源信息
lark-cli base +table-list --base-token xxx
lark-cli base +field-list --base-token xxx --table-id <table_id>
# 第 3 步:规划应该创建哪些组件(根据用户需求确定组件类型和数量)
# 例如:总销售额(指标卡)、月度趋势(折线图)、品类占比(饼图)
# 第 4 步:顺序创建每个组件(必须串行执行,不能并发)
# 重要:创建组件前,先确定 dashboard_id、组件 name/type 和真实表字段
# 再阅读 lark-base-dashboard-block-config.md 了解 data_config 结构、组件类型和 filter 规则
# 第 1 个组件
lark-cli base +dashboard-block-create \
--base-token xxx \
--dashboard-id blk_xxx \
--name "总销售额" \
--type statistics \
--data-config '{"table_name":"订单表","series":[{"field_name":"金额","rollup":"SUM"}]}'
# 第 2 个组件(等上一个完成后再执行)
lark-cli base +dashboard-block-create \
--base-token xxx \
--dashboard-id blk_xxx \
--name "月度趋势" \
--type line \
--data-config '{"table_name":"订单表","series":[{"field_name":"金额","rollup":"SUM"}],"group_by":[{"field_name":"月份","mode":"integrated"}]}'
# 继续创建其他组件...
# 第 5 步:组件创建完成后,使用 arrange 命令智能重排布局(可选但推荐)
# 默认布局可能不够美观,arrange 会根据组件数量和类型自动优化布局
# 若用户没有要求美化/重排,可先跳过此步骤;这不影响仪表盘和组件是否已创建成功
lark-cli base +dashboard-arrange \
--base-token xxx \
--dashboard-id blk_xxx场景 2:在已有仪表盘上添加新组件
# 第 1 步:列出仪表盘,定位到当前仪表盘
lark-cli base +dashboard-list --base-token xxx
# 获取目标 dashboard_id
# 第 2 步:根据用户诉求规划组件类型和数据源
# 建议先查看当前仪表盘已有组件,避免重复创建,或作为参考
lark-cli base +dashboard-get --base-token xxx --dashboard-id blk_xxx
# 第 3 步:获取数据源信息
lark-cli base +table-list --base-token xxx
lark-cli base +field-list --base-token xxx --table-id <table_id>
# 第 4 步:顺序创建每个新组件(必须串行执行,不能并发)
# 重要:先确定 dashboard_id、组件 name/type 和真实表字段
# 再阅读 lark-base-dashboard-block-config.md 了解 data_config 结构
lark-cli base +dashboard-block-create \
--base-token xxx \
--dashboard-id blk_xxx \
--name "新组件名" \
--type column \
--data-config '{...}'场景 3:编辑已有组件
[!IMPORTANT]
+dashboard-block-update不能修改组件的type(图表类型),只能更新name和data_config。 如需更换组件类型,必须先删除再重新创建。
# 第 1 步:列出仪表盘,定位到当前仪表盘
lark-cli base +dashboard-list --base-token xxx
# 第 2 步:列出组件,获取到目标组件
lark-cli base +dashboard-block-list --base-token xxx --dashboard-id blk_xxx
# 获取目标 block_id
# 提示:查看已有组件可作为参考,或检查是否重复创建相似组件
# 第 3 步:获取组件当前详情
lark-cli base +dashboard-block-get --base-token xxx --dashboard-id blk_xxx --block-id chtxxxxxxxx
# 第 4 步:根据用户编辑诉求准备更新
# 如果编辑诉求涉及数据源变更,需要先获取数据源信息
lark-cli base +table-list --base-token xxx
lark-cli base +field-list --base-token xxx --table-id <table_id>
# 第 5 步:执行更新
# 重要:先读取当前 block 的 name/type/data_config
# 再阅读 lark-base-dashboard-block-config.md 了解 data_config 更新规则
lark-cli base +dashboard-block-update \
--base-token xxx \
--dashboard-id blk_xxx \
--block-id chtxxxxxxxx \
--data-config '{...}'
场景 4:重排仪表盘布局
当用户明确要求对已有仪表盘进行布局重排或美化时使用(对本次会话从零新建的仪表盘,可在建完组件后直接做一次性整理,见场景 1)。
[!CAUTION] - 排列结果是服务端智能推荐,不一定完全符合用户预期 - Dashboard shortcut 无法指定
x/y/w/h、精确位置或尺寸(如"第一排放 A""图表撑满整行"),排列逻辑是自适应的 - 不建议在已有仪表盘上自动调用,除非用户明确要求 - 用户只要求一般性重排/美化时,可执行一次+dashboard-arrange;用户要求精确结果时,先说明限制并询问是否接受自适应布局,接受后才执行,不能静默替代或声称精确满足 - 执行一次+dashboard-arrange后即停止;不要继续探测 rawlark-cli api、源码或未公开布局参数
# 第 1 步:列出仪表盘,定位到目标仪表盘
lark-cli base +dashboard-list --base-token xxx
# 第 2 步:执行智能重排
lark-cli base +dashboard-arrange \
--base-token xxx \
--dashboard-id blk_xxx场景 5:读取仪表盘或组件现状
选择查询方式:
- 想看仪表盘整体结构(含主题、所有组件名称和类型)→ 用 方式 A
- 只想快速查看有哪些组件 → 用 方式 B
- 想看某个组件的详细 data_config 配置 → 用 方式 C
- 想看某个图表/指标卡实际算出来的数据 → 用 方式 D
用户要求读取“全部图表”或“完整仪表盘”时,先用方式 B 分页枚举所有 block:使用 --page-size 100;若返回 has_more=true,继续把本页返回的 page_token 传给 --page-token,直到 has_more=false。收齐后再对每个 block 收口,不能只返回 get-data 成功的子集:
- 图表或指标卡:使用方式 D 读取计算结果。
text:使用方式 C,正文位于data_config.text;text 没有计算结果,但属于完整仪表盘内容。- get-data 返回不支持的图表类型:先用方式 C 读取真实
data_config,确认table_name、维度、指标、聚合与筛选,再按 Record 查询与分析 SOP 使用+data-query重建同口径结果。字段必须来自真实配置和表结构,不得猜测;无法等价重建时明确报告限制,不能静默省略该 block。
# 第 1 步:列出仪表盘,定位到当前仪表盘
lark-cli base +dashboard-list --base-token xxx
# 第 2 步:根据用户诉求查看详情
# 方式 A:查看仪表盘整体情况(包含所有组件列表)
lark-cli base +dashboard-get --base-token xxx --dashboard-id blk_xxx
# 方式 B:列出所有组件
lark-cli base +dashboard-block-list \
--base-token xxx \
--dashboard-id blk_xxx \
--page-size 100
# 方式 C:查看某个组件的详细配置
lark-cli base +dashboard-block-get --base-token xxx --dashboard-id blk_xxx --block-id chtxxxxxxxx
# 方式 D:查看某个图表组件的计算结果(AI 友好的 chart protocol)
lark-cli base +dashboard-block-get-data --base-token xxx --block-id chtxxxxxxxx
# 最后:把获取到的现状信息整理好告诉用户需要读取多个组件的计算结果时,先用方式 B 获取真实 block_id(使用 --page-size 100;若 has_more=true,继续把返回的 page_token 传给 --page-token,直到 has_more=false),再按 lark-base-dashboard-block-get-data.md 的多组件范式,在一个 shell 工具调用内串行读取;不要把每个 block 拆成独立模型轮次。文本组件没有计算结果,应跳过。
组件类型选择
组件 type 决定展示形式:
| 用户想看什么 | 选什么 type | 说明 |
|---|---|---|
| 数据趋势(时间变化) | line | 折线图组件 |
| 类别比较(谁高谁低) | column | 柱状图组件 |
| 占比分布(各部分比例) | pie | 饼图组件 |
| 单个关键指标 | statistics | 指标卡组件 |
| 富文本说明/标题/注释 | text | 文本组件(支持 Markdown) |
详细组件类型和 data_config 完整规则:Dashboard Block 配置
常见问题
Q: 创建组件的命令和 data_config 怎么写? A:
- 先确定
dashboard_id、组件name、组件type和真实表字段 - 再读 Dashboard Block 配置 了解:
- 全部组件类型的可复制模板
- filter 筛选条件格式
- 字段类型与操作符对应表
Q: 为什么组件创建失败了? A: 常见原因:
table_name用了 table_id 而不是表名(必须用表名称,如「订单表」)series和count_all同时存在(必须二选一,互斥)- 字段名拼写错误(必须用
+field-list获取的真实字段名,禁止猜测) - 组件创建并发执行(必须串行,等上一个完成再执行下一个)
Q: 可以一次创建多个组件吗? A: 不可以,必须串行执行。等上一个 +dashboard-block-create 完成后再执行下一个。
Q: 组件的 type 创建后能改吗? A: 不能。+dashboard-block-update 只能修改 name 和 data_config,不能修改 type。
Q: 更新组件的命令和 data_config 怎么写? A:
- 先读取当前 block,确认
block_id、当前type和已有data_config - 再读 Dashboard Block 配置 了解 data_config 结构
data_config 更新策略(顶层 key merge):
- 只传入需要修改的顶层字段(如
series、filter) - 未传的顶层字段(如
group_by)自动保留原值 - 但每个传入的字段内部是全量替换(如传新
filter会完整覆盖旧filter)
Q: 查看已有组件有什么用? A: 在「添加新组件」或「编辑组件」前查看已有组件可以:
- 了解当前仪表盘已有哪些可视化
- 避免重复创建相似的组件
- 参考已有组件的 data_config 结构作为模板
Q: 我想直接拿图表算好的结果给 AI 分析,应该用什么? A: 用 +dashboard-block-get-data。它返回图表协议 JSON(常见字段包括 dimensions、measures、main_data,指标卡可能还有 comparison_data、trend_data),不返回 block 名称、类型、布局或 data_config;需要这些元数据时先用 +dashboard-block-get。
写入前检查
- 创建 block 前必须知道
base_token、dashboard_id、组件name/type和data_config。 - 更新 block 前必须知道
base_token、dashboard_id、block_id,并读过当前 block。 data_config中使用表名和字段名,不使用 table_id / field_id;名称必须来自+table-list/+field-list的真实返回。
Base NDJSON:pandas 示例
仅在统一数据分析 SOP 已选择 pandas 后读取。本页不重复 Base 的粒度与关系规则,只展示对应实现。
示例假设 records.ndjson 包含 record_id、日期、状态、金额、负责人、标签、关联客户;customers.ndjson 包含 record_id、客户名称。多值列使用统一数据分析 SOP 定义的数组结构。
加载与日期解析
import pandas as pd
records = pd.read_json("records.ndjson", lines=True)
raw_dates = records["日期"].astype("string")
records["日期_local"] = pd.to_datetime(
raw_dates.str.slice(0, 10), format="%Y-%m-%d", errors="coerce"
)
records["日期_instant"] = pd.to_datetime(
raw_dates, format="ISO8601", utc=True, errors="coerce"
)按来源 Base 的日、周、月分组使用 日期_local;计算真实时长、排序或跨时区比较使用 日期_instant。实际任务只需构造所需的一列。
集合谓词:保持 record 粒度
筛选“状态”包含“进行中”的记录,并在 record 粒度汇总:
active = records[records["状态"].map(lambda values: "进行中" in values)]
summary = {
"records_count": len(active),
"amount_sum": active["金额"].sum(min_count=1),
}单数组展开:切换到人员粒度
owners = records[["record_id", "负责人"]].explode("负责人", ignore_index=True)
owners = owners[owners["负责人"].notna()].assign(
user_id=lambda df: df["负责人"].map(lambda user: user["id"]),
user_name=lambda df: df["负责人"].map(lambda user: user["name"]),
)
by_owner = (
owners.groupby(["user_id", "user_name"], as_index=False)
.agg(records_count=("record_id", "nunique"))
.sort_values("records_count", ascending=False)
)Link JOIN:先建立边表
edges = (
records[["record_id", "关联客户"]]
.rename(columns={"record_id": "source_record_id"})
.explode("关联客户", ignore_index=True)
)
edges = edges[edges["关联客户"].notna()].assign(
target_record_id=lambda df: df["关联客户"].map(lambda link: link["id"])
)[["source_record_id", "target_record_id"]]
customers = pd.read_json("customers.ndjson", lines=True).rename(
columns={"record_id": "target_record_id"}
)
joined = edges.merge(
customers[["target_record_id", "客户名称"]],
on="target_record_id",
how="left",
)多数组共现:显式生成行内笛卡尔积
连续两次 explode 表示同一 source record 内的 负责人 × 标签:
pairs = (
records[["record_id", "负责人", "标签"]]
.explode("负责人", ignore_index=True)
.explode("标签", ignore_index=True)
.dropna(subset=["负责人", "标签"])
.assign(
user_id=lambda df: df["负责人"].map(lambda user: user["id"]),
user_name=lambda df: df["负责人"].map(lambda user: user["name"]),
)
)
cooccurrence = (
pairs.groupby(["user_id", "user_name", "标签"], as_index=False)
.agg(records_count=("record_id", "nunique"))
.sort_values("records_count", ascending=False)
)Base NDJSON:Python 标准库示例
仅在统一数据分析 SOP 已选择 Python 标准库后读取。本页不重复 Base 的粒度与关系规则,只展示对应实现。
示例假设 records.ndjson 包含 record_id、日期、状态、金额、负责人、标签、关联客户;customers.ndjson 包含 record_id、客户名称。多值列使用统一数据分析 SOP 定义的数组结构。
加载与日期解析
NDJSON 每行是一条独立 JSON record;按行读取即可,不要先把文件整体载入字符串。
import json
from datetime import date, datetime
def read_ndjson(path):
with open(path, encoding="utf-8") as stream:
for line in stream:
if line.strip():
yield json.loads(line)
records = list(read_ndjson("records.ndjson"))
for record in records:
raw_date = record["日期"]
record["日期_local"] = date.fromisoformat(raw_date[:10]) if raw_date else None
record["日期_instant"] = datetime.fromisoformat(raw_date) if raw_date else None按来源 Base 的日、周、月分组使用 日期_local;计算真实时长、排序或跨时区比较使用 日期_instant。实际任务只需构造所需的一项。
集合谓词:保持 record 粒度
筛选“状态”包含“进行中”的记录,并在 record 粒度汇总:
active = [record for record in records if "进行中" in record["状态"]]
amounts = [record["金额"] for record in active if record["金额"] is not None]
summary = {
"records_count": len(active),
"amount_sum": sum(amounts) if amounts else None,
}单数组展开:切换到人员粒度
用嵌套循环表达 lateral expansion;按人员 id 聚合,name 只用于展示。
from collections import defaultdict
record_ids_by_owner = defaultdict(set)
owner_names = {}
for record in records:
for owner in record["负责人"]:
record_ids_by_owner[owner["id"]].add(record["record_id"])
owner_names[owner["id"]] = owner["name"]
by_owner = sorted(
(
{
"user_id": user_id,
"user_name": owner_names[user_id],
"records_count": len(record_ids),
}
for user_id, record_ids in record_ids_by_owner.items()
),
key=lambda row: (-row["records_count"], row["user_id"]),
)Link JOIN:先建立目标表索引
目标表的 record_id 是唯一主键,可直接建立哈希索引;Link 的 id 用于索引查找。
customers = {
customer["record_id"]: customer
for customer in read_ndjson("customers.ndjson")
}
joined = []
for record in records:
for link in record["关联客户"]:
customer = customers.get(link["id"])
joined.append(
{
"source_record_id": record["record_id"],
"target_record_id": link["id"],
"客户名称": customer["客户名称"] if customer else None,
}
)多数组共现:显式生成行内笛卡尔积
两层嵌套循环表示同一 source record 内的 负责人 × 标签:
record_ids_by_pair = defaultdict(set)
owner_names = {}
for record in records:
for owner in record["负责人"]:
owner_names[owner["id"]] = owner["name"]
for tag in record["标签"]:
record_ids_by_pair[(owner["id"], tag)].add(record["record_id"])
cooccurrence = sorted(
(
{
"user_id": user_id,
"user_name": owner_names[user_id],
"标签": tag,
"records_count": len(record_ids),
}
for (user_id, tag), record_ids in record_ids_by_pair.items()
),
key=lambda row: (-row["records_count"], row["user_id"], row["标签"]),
)Base data-query DSL reference
前置路由: Record 查询与分析 SOP | 认证或授权问题: `../lark-shared/SKILL.md`
本文档合并常用 fewshot 与完整 DSL 协议。只有 Record 查询与分析 SOP 的 Cloud 路径选定 +data-query 后才读取,并优先定位与当前查询有关的示例、字段或错误协议。
限制
- 权限要求(按文档类型分流):
- 普通多维表格:调用者拥有文档的阅读权限即可
- 高级权限多维表格:调用者必须是文档管理员,拥有 FA(Full Access / 完全访问权限)
权限不足时返回权限错误。
推荐命令
# 按字段分组计数
lark-cli base +data-query \
--base-token MAGObxxxxx \
--dsl '{
"datasource": {"type": "table", "table": {"tableId": "tblxxxxxxxx"}},
"dimensions": [{"field_name": "城市", "alias": "dim_city"}],
"measures": [{"field_name": "城市", "aggregation": "count", "alias": "count"}],
"shaper": {"format": "flat"}
}'
# 带过滤条件 + 排序 + 限制条数
lark-cli base +data-query \
--base-token MAGObxxxxx \
--dsl '{
"datasource": {"type": "table", "table": {"tableId": "tblxxxxxxxx"}},
"dimensions": [{"field_name": "城市", "alias": "dim_city"}],
"measures": [{"field_name": "金额", "aggregation": "sum", "alias": "total_amount"}],
"filters": {
"type": 1,
"conjunction": "and",
"conditions": [{"field_name": "城市", "operator": "isNot", "value": [""]}]
},
"sort": [{"field_name": "total_amount", "order": "desc"}],
"pagination": {"limit": 100},
"shaper": {"format": "flat"}
}'
# 使用 tableName(表名)代替 tableId
lark-cli base +data-query \
--base-token MAGObxxxxx \
--dsl '{
"datasource": {"type": "table", "table": {"tableName": "销售数据"}},
"measures": [{"field_name": "金额", "aggregation": "sum", "alias": "total"}],
"shaper": {"format": "flat"}
}'
# 聚合或维度查询后如需读取逐条记录,先让 data-query 返回可回查的业务 key
lark-cli base +data-query \
--base-token MAGObxxxxx \
--dsl '{
"datasource": {"type": "table", "table": {"tableId": "tblxxxxxxxx"}},
"dimensions": [{"field_name": "业务编号", "alias": "biz_key"}],
"measures": [{"field_name": "指标值", "aggregation": "max", "alias": "max_value"}],
"filters": {
"type": 1,
"conjunction": "and",
"conditions": [{"field_name": "状态", "operator": "is", "value": ["有效"]}]
},
"sort": [{"field_name": "max_value", "order": "desc"}],
"pagination": {"limit": 10},
"shaper": {"format": "flat"}
}'参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token(base_token) |
--dsl <json> | 是 | LiteQuery Protocol JSON DSL 查询语句 |
如何从链接中解析参数
用户通常会提供如下 URL:
https://example.feishu.cn/base/<base_token>?table=<block_id>不要直接把 URL 中的 table= 当成数据表 ID。它表示当前选中的 Base 顶层块,可能是数据表、仪表盘、工作流、文件夹或文档。先解析链接:
lark-cli base +url-resolve --url "<url>" --as user--base-token:使用返回的base_token- 仅当返回的
block_type为table时,DSL 中的tableId才使用返回的table_id - 如果返回的是其他块类型,按
hint.next_step继续处理;如果只返回中性的block_id,先用+base-block-list确认块类型,再选择实际要查询的数据表
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/data/queryPath 参数:
| 参数 | 必填 | 说明 |
|---|---|---|
base_token | 是 | Base Token |
Request Body — DSL 结构:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
datasource | object | 是 | 数据源,包含 type(固定 "table")和 table 对象 |
datasource.table.tableId | string | 二选一 | 目标数据表 ID |
datasource.table.tableName | string | 二选一 | 目标数据表名称 |
dimensions | Dimension[] | 否* | 分组维度字段(GROUP BY) |
measures | Measure[] | 否* | 聚合度量字段 |
filters | FilterGroup | 否 | 过滤条件(WHERE) |
sort | Sort[] | 否 | 排序规则 |
pagination | object | 否 | 限制返回行数,{limit: N},最大 5000 |
shaper | object | 否 | 结果格式,固定 {format: "flat"} |
\*
dimensions和measures至少填写一个。
Dimension 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
field_name | string | 是 | 字段名称 |
alias | string | 否 | 输出列别名,需全局唯一 |
Measure 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
field_name | string | 是 | 字段名称 |
aggregation | string | 是 | 聚合函数:sum、avg、min、max、count、count_all、distinct_count |
alias | string | 否 | 输出列别名,需全局唯一 |
聚合函数适用字段类型:
| 聚合函数 | 适用字段类型 |
|---|---|
sum / avg | number |
min / max | number、datetime |
count | 全字段适用,计数非空值 |
count_all | 全字段适用,计数所有行 |
distinct_count | 全字段适用 |
number包含style.type为progress/currency/rating等所有子类型。
FilterGroup:
{
"filters": {
"type": 1,
"conjunction": "and",
"conditions": [
{"field_name": "城市", "operator": "is", "value": ["北京"]}
]
}
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | int | 是 | 固定填 1 |
conjunction | string | 否 | 条件组合逻辑:"and" 或 "or",默认 "and" |
conditions | Condition[] | 否 | 条件列表 |
Condition:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
field_name | string | 是 | 字段名称(必须与表中字段名精确匹配) |
operator | string | 是 | 运算符(见下方运算符表) |
value | string[] | 是 | 条件值数组;isEmpty/isNotEmpty 时必须传空数组 [] |
运算符:
| 运算符 | 说明 |
|---|---|
is | 等于 |
isNot | 不等于 |
contains | 包含 |
doesNotContain | 不包含 |
isEmpty | 为空 |
isNotEmpty | 不为空 |
isGreater | 大于 |
isGreaterEqual | 大于等于 |
isLess | 小于 |
isLessEqual | 小于等于 |
各运算符的适用字段类型见下方「按各字段类型筛选时 value 格式详解」。
按各字段类型筛选时 value 格式详解:
text
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot / contains / doesNotContain | ["文本内容"] | 仅 1 个 | ["Hello"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:文本无自然顺序,比较运算无意义。text也覆盖电话、超链接、邮箱、条码字段;通过style.type区分(plain(默认)/phone/url/barcode),运算符集合一致。 当style.type=url时,value 筛选的是链接显示名称,而不是 URL 本身。
number
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot / isGreater / isGreaterEqual / isLess / isLessEqual | ["数字字符串"] | 仅 1 个 | ["23.4"]、["-100"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
value 必须为合法数字的字符串形式。
number也覆盖货币、进度、评分字段;通过style.type区分(plain(默认)/currency/progress/rating),运算符集合一致,仅 value 解释不同: - 当style.type=progress时,34% 对应 0.34 而不是 34。 - 当style.type=rating时,必须输入整数,代表评分。
auto_number
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot / contains / doesNotContain | ["编号字符串"] | 仅 1 个 | ["00001"] |
isGreater / isGreaterEqual / isLess / isLessEqual | ["编号字符串"] | 仅 1 个 | ["00010"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
select
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot | ["选项名"] | 仅 1 个 | ["选项A"] |
contains / doesNotContain | ["选项A", "选项B"] | 可多个 | ["选项A", "选项B"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:选项为枚举值,无自然顺序。 通过multiple区分单选(multiple=false,默认)/ 多选(multiple=true)。
user / created_by / updated_by
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot | ["用户ID1", "用户ID2"] | 可多个 | ["ou_aaa", "ou_bbb"] |
contains / doesNotContain | ["用户ID1", "用户ID2"] | 可多个 | ["ou_aaa", "ou_bbb"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:人员无法比大小。 用户 ID 使用open_id(ou_前缀),接口层会自动做 ID 转换。
group_chat
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot | ["群组ID1", "群组ID2"] | 可多个 | ["oc_aaa", "oc_bbb"] |
contains / doesNotContain | ["群组ID1", "群组ID2"] | 可多个 | ["oc_aaa", "oc_bbb"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:群组无法比大小。
link
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot | ["recId1", "recId2"] | 可多个 | ["recAAA", "recBBB"] |
contains / doesNotContain | ["recId1", "recId2"] | 可多个 | ["recAAA", "recBBB"] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:关联记录无法比大小。 value 传关联表记录的record_id。 双向关联(创建时设bidirectional=true)也属于link类型,运算符与单向关联一致。
location
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is / isNot / contains / doesNotContain | ["地址文本"] | 仅 1 个 | ["北京市朝阳区..."] |
isEmpty / isNotEmpty | [] | 0 个 | [] |
不支持
isGreater/isGreaterEqual/isLess/isLessEqual:地理位置无自然顺序。 location 按full_address字符串筛选,不支持经纬度空间筛选;查城市/片区时优先用contains,避免用is匹配短地址词。
checkbox
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
is | ["true"] 或 ["false"] | 仅 1 个 | ["true"] |
仅支持
is运算符,不支持其他运算符。
datetime / created_at / updated_at
日期字段仅支持 is、isEmpty、isNotEmpty、isGreater、isLess 五种运算符。
value 使用预定义关键字机制,第一个元素为字符串常量名称:
| 关键字 | 说明 | value 格式 | 支持的运算符 |
|---|---|---|---|
ExactDate | 精确日期 | ["ExactDate", "1773187200000"](毫秒时间戳) | is、isGreater、isLess |
Today | 今天 | ["Today"] | is、isGreater、isLess |
Tomorrow | 明天 | ["Tomorrow"] | is、isGreater、isLess |
Yesterday | 昨天 | ["Yesterday"] | is、isGreater、isLess |
CurrentWeek | 本周 | ["CurrentWeek"] | 仅 is |
LastWeek | 上周 | ["LastWeek"] | 仅 is |
CurrentMonth | 本月 | ["CurrentMonth"] | 仅 is |
LastMonth | 上月 | ["LastMonth"] | 仅 is |
TheLastWeek | 过去七天 | ["TheLastWeek"] | 仅 is |
TheNextWeek | 未来七天 | ["TheNextWeek"] | 仅 is |
TheLastMonth | 过去三十天 | ["TheLastMonth"] | 仅 is |
TheNextMonth | 未来三十天 | ["TheNextMonth"] | 仅 is |
- ExactDate 时区行为:毫秒时间戳在实际筛选时会被转为文档时区当天零点,跨时区场景需注意日期可能偏移一天。
- 范围型关键字(
CurrentWeek、LastWeek、CurrentMonth、LastMonth、TheLastWeek、TheNextWeek、TheLastMonth、TheNextMonth)仅支持is运算符。- 关键字大小写敏感:
ExactDate、Today、CurrentWeek等首字母大写,写错大小写会导致校验失败。
attachment
| 运算符 | value 格式 | 元素个数 | 示例 |
|---|---|---|---|
isEmpty / isNotEmpty | [] | 0 个 | [] |
附件字段仅支持
isEmpty和isNotEmpty,不支持其他运算符。
formula / lookup
公式和查找引用字段的运算符和 value 格式 取决于其结果数据类型,按结果类型参照上方对应字段类型的规则。例如:
- 公式结果为数字 → 按
number规则 - 公式结果为日期 → 按
datetime规则 - 公式结果为单选 → 按
select规则
Sort 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
field_name | string | 是 | 字段名称或 alias |
order | string | 否 | "asc"(默认)或 "desc" |
Pagination 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
limit | int | 否 | 返回记录数上限,必须为正整数,最大 5000;不填时使用系统默认值。不支持 offset |
Shaper 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
format | string | 是 | 固定为 "flat",表示返回扁平化的对象数组 |
CLI 出参详情
CLI 输出标准信封 {ok, identity, data}(失败时为 {ok:false, identity, error})。
成功时:
{"ok": true, "identity": "user", "data": {"main_data": [{"dim_city": {"value": "北京"}, "total_amount": {"value": 12345.00}}, ...]}}失败时:
{"ok": false, "identity": "user", "error": {"type": "api", "subtype": "unknown", "code": 800004006, "message": "...does not exist in table schema", "hint": "...", "log_id": "..."}}Response 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
ok | bool | 是否成功 |
identity | string | 执行身份:user / bot |
data.main_data | []object | 查询结果数组,每个元素为一行数据(成功时) |
error | object | 失败时的 typed 错误,含 type / subtype / code / message / hint / log_id |
每行数据的字段值封装在 CellValue 中:
{
"dim_city": {
"value": "北京"
},
"total_amount": {
"value": 12345.00
}
}value:展示值(人员名称、选项名称、格式化日期等)
返回值
命令成功后输出 data 字段的内容:
{
"main_data": [
{
"dim_city": {"value": "直营"},
"measure_count": {"value": 1}
},
{
"dim_city": {"value": "加盟"},
"measure_count": {"value": 2}
}
]
}工作流
- 确认 base-token 和 table-id
- 先查表结构:执行
lark-cli base +field-list --base-token <base_token> --table-id <table_id> - 从返回的字段列表中获取 field_name(DSL 中使用的字段名称)
- 根据字段信息构造 DSL JSON
- 执行 +data-query
- 解读返回结果:
- 结果在
data.main_data数组中,每个元素代表一行 - 每行对象的 key 为 DSL 中指定的
alias;未指定 alias 时,key 为自动生成的列名 - 每个 value 是 CellValue 对象,实际值在
value字段中,如{"value": "北京"}或{"value": 12345.00} - 失败时结果在
data.error中,包含具体错误码和信息
与记录读取组合
+data-query 可返回聚合结果,也可在只传 dimensions 时返回维度字段行;这些维度行按字段组合去重,不包含 record_id,不能等同于逐条原始记录。需要输出聚合结果对应的原始记录字段、展示值、记录定位信息或关联表字段时,按以下方式组合:
- 用
+data-query在 Base 云端查询服务中完成全局筛选、分组、聚合、排序和 TopN,得到业务 key、分组值或候选字段组合。 - 如果已经拿到候选记录的
record_id,用+record-get读取逐条记录字段。 - 如果拿到的是结构化业务 key(例如编号、状态、日期、金额等),用
+record-list --filter-json做精确过滤后读取;+record-search用于文本展示值关键词。 - 只有候选条件本身是文本展示值关键词时,才使用
+record-search,并用search_fields限定范围、select_fields做投影。 - 若候选记录包含 link 字段,提取关联
record_id后到关联表用+record-get批量读取展示字段。 - 最终回答展示真实业务字段;内部
record_id用于连接或定位。
不要把 data-query pagination.limit 理解为分页扫描;它只限制 Base 云端查询服务返回的聚合结果行数,不支持 offset。需要逐条原始记录时按 Cloud SOP 的 +record-list / +record-search 回查规则处理。
坑点
- ⚠️ 必须先查表结构:DSL 的
field_name必须与表中字段名称精确匹配(区分大小写),不能凭猜测构造。先用lark-cli base +field-list --base-token <base_token> --table-id <table_id>获取真实字段名 - ⚠️ 权限要求按文档类型分流:普通多维表格只需文档阅读权限;高级权限多维表格必须是文档管理员(FA / Full Access),否则返回权限错误
- ⚠️ alias 不支持中文:dimensions 和 measures 的 alias 必须使用英文(如
dim_city、total_amount),中文 alias 会导致错误 - ⚠️ API 路径是
base/v3:本接口路径为/open-apis/base/v3/bases/:base_token/data/query,不是bitable/v1。两者完全不同,用错版本号会返回[2200] Internal Error - ⚠️
dimensions和measures至少填一个:两个都不填会返回 DSL 校验错误 - ⚠️
shaper必须为{"format": "flat"}:不填或填其他值会导致结果格式不可预期,建议始终显式指定 - ⚠️ 数据表标识
tableIdvstableName:datasource 中可以用tableId(如tblXXX)或tableName(数据表的用户自定义显示名称),二选一,不要混用 - ⚠️
pagination.limit最大 5000:超过会报错,且不支持 offset,只支持 limit - ⚠️ 所有 alias 必须全局唯一:dimensions 和 measures 之间的 alias 也不能重名
参考
- lark-base — 多维表格全部命令
- lark-shared — 认证和全局参数
- Cloud SOP — Cloud 路径的查询范围、下推、分页、
+record-list/+record-search回查和关系查询 - lark-base-cell-value.md — CellValue 格式规范
- Field Schema — 字段类型与 JSON 结构
base +field-create
前置条件: 先阅读 `../lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
创建一个或多个字段;同一表的多个字段优先使用一次 JSON 数组输入。
formula / lookup 创建前读取对应 guide;涉及跨表引用时同时读取目标表结构。
推荐命令
lark-cli base +field-create \
--base-token <base_token> \
--table-id <table_id> \
--json '{"name":"预算","type":"number","style":{"type":"plain","precision":2}}'
lark-cli base +field-create \
--base-token <base_token> \
--table-id <table_id> \
--json '{"name":"状态","type":"select","multiple":false,"default_value":["Todo"],"options":[{"name":"Todo","hue":"Blue","lightness":"Lighter"},{"name":"Done","hue":"Green","lightness":"Light"}]}'
# 多个字段复用相同字段 JSON 形状,一次传非空数组
lark-cli base +field-create \
--base-token <base_token> \
--table-id <table_id> \
--json '[{"name":"备注","type":"text"},{"name":"优先级","type":"select","multiple":false,"options":[{"name":"高"},{"name":"低"}]}]'参数
| 参数 | 必填 | 说明 |
|---|---|---|
--base-token <token> | 是 | Base Token |
--table-id <id_or_name> | 是 | 表 ID 或表名 |
--json <body> | 是 | 单个字段 JSON 对象,或多个字段对象组成的非空数组 |
API 入参详情
HTTP 方法和路径:
POST /open-apis/base/v3/bases/:base_token/tables/:table_id/fieldsJSON 值规范
--json接受单个字段 JSON 对象,也接受多个字段对象组成的非空数组;不要再套fields等外层对象。- 数组按顺序创建字段,遇到首个失败即停止且不自动回滚;部分失败时保留
items中的created项,按hint修正后只提交failed和not_attempted项,并保持依赖顺序。 - 每个字段对象最少包含:
name、type。 - 所有字段类型都支持可选
description;支持纯文本,也支持 Markdown 链接,如协作约定可参考[团队字段约定](https://example.com/field-spec)。 - 需要字段默认值时传
default_value,直接使用字段对应 CellValue;datetime/user的动态填充用$slot。完整规则见 Field Schema。 type不同,必填子字段不同:select:multiple控制是否多选,options定义静态选项,dynamic_options_source定义动态选项来源。静态与动态选项配置二选一,不能同时传。link:必须有link_table,可选bidirectional、bidirectional_link_field_name。formula:必须有expression;先读 formula guide,再创建。lookup:必须有from、select、where;先读 lookup guide,再创建。
正确(base +field-create)
{
"name": "状态",
"type": "select",
"multiple": false,
"default_value": ["Todo"],
"options": [
{ "name": "Todo", "hue": "Blue", "lightness": "Lighter" },
{ "name": "Done", "hue": "Green", "lightness": "Light" }
]
}参考
- Field Schema — 字段 JSON 规范(推荐)
- Formula Field — 创建公式必读
- Lookup Field — 创建查找引用必读
Base Field Schema
适用命令:
lark-cli base +field-create、lark-cli base +field-update
本文档定义 +field-create / +field-update 写字段时 --json 的推荐格式,是字段类型与字段 JSON 结构的 source of truth。目标不是复刻完整 schema,而是让 agent 稳定产出正确 payload。
1. 顶层规则(必须遵守)
- 单个字段定义始终是 JSON 对象,每个字段对象统一使用:
type+name+ 类型特有字段。 +field-create --json接受一个字段对象或非空字段对象数组。+field-update --json只接受一个字段对象。- 所有字段类型都支持可选
description;支持纯文本,也支持 Markdown 链接。 - 字段默认值使用
default_value,直接传对应 CellValue;支持范围只有text、number、静态select、datetime、user。清空默认值传null;创建时省略表示不设置。 - 不要使用旧结构:
field_name、property、ui_type、数字枚举type。 +field-update是 override 式的完整覆盖PUT,不是 partial update;先用+field-get读取当前定义,在其基础上修改目标属性,并把整个字段需要保留的可写配置完整写回,同时带--yes。type=formula或type=lookup创建/更新前,必须先读对应 guide。
推荐示例:
{
"type": "text",
"name": "需求背景",
"description": "记录需求背景与已知约束"
}2. 字段速查
| 类型 | 最小必填字段 | 常见补充字段 |
|---|---|---|
text | type name | style.type default_value |
number | type name | style default_value |
select | type name | multiple + options + 静态 default_value,或 multiple + dynamic_options_source |
datetime | type name | style.format default_value |
created_at / updated_at | type name | style.format |
user / group_chat | type name | multiple;仅 user 支持 default_value |
created_by / updated_by | type name | 无 |
link | type name link_table | bidirectional bidirectional_link_field_name |
formula | type name expression | 无 |
lookup | type name from select where | aggregate |
auto_number | type name | style.rules |
attachment / location / checkbox | type name | 无 |
所有类型都可额外传 description;上表的“常见补充字段”只列类型特有配置。
3. 各类型写法
3.1 text
文本字段;电话、超链接、邮箱、条码也都属于 text,通过 style.type 区分。 支持 default_value:静态 Markdown 文本字符串;phone style 必须是合法电话号码;url style 传一个 Markdown 链接或裸 URL;email style 必须是合法邮箱字符串,不要传 Markdown 链接或 mailto:。
最小写法(默认 style.type 为 plain):
{
"type": "text",
"name": "标题",
"default_value": "默认标题"
}常用写法:
默认值可以是 Markdown 文本
{
"type": "text",
"name": "标题",
"description": "主标题字段",
"default_value": "未命名"
}style.type=phone 时默认值是合法电话号码字符串。
{
"type": "text",
"name": "联系电话",
"style": { "type": "phone" },
"default_value": "+8613800000000"
}{
"type": "text",
"name": "官网",
"style": { "type": "url" },
"default_value": "[官网](https://example.com)"
}{
"type": "text",
"name": "邮箱",
"style": { "type": "email" },
"default_value": "owner@example.com"
}常用 style.type:plain(默认)、phone、url、email、barcode。
3.2 number
数字字段;货币、进度、评分都属于 number,通过 style.type 区分。 支持 default_value:静态 JSON number;所有 number style 都按这个规则写。
最小写法(默认 style.type 为 plain):
{
"type": "number",
"name": "工时",
"default_value": 8
}style 是按 type 区分的对象;不同 style.type 的内部字段不一样,不要混传。
plain
支持字段:precision、percentage、thousands_separator
默认值 / 约束:
precision取值0..4,默认2percentage默认falsethousands_separator默认false
{
"type": "number",
"name": "工时",
"style": {
"type": "plain",
"precision": 2,
"percentage": false,
"thousands_separator": true
},
"default_value": 8
}currency
支持字段:precision、currency_code
默认值 / 约束:
precision取值0..4,默认2currency_code必填,如CNY、USD、EUR
{
"type": "number",
"name": "预算",
"style": { "type": "currency", "precision": 2, "currency_code": "CNY" }
}progress
支持字段:percentage、color
默认值 / 约束:
percentage默认truecolor必填color可用:Blue、Purple、DarkGreen、Green、Cyan、Orange、Red、Gray、WhiteToBlueGradient、WhiteToPurpleGradient、WhiteToOrangeGradient、GreenToRedGradient、RedToGreenGradient、BlueToPinkGradient、PinkToBlueGradient、SpectralGradient
{
"type": "number",
"name": "完成度",
"style": { "type": "progress", "percentage": true, "color": "Blue" },
"default_value": 0.65
}rating
支持字段:icon、min、max
默认值 / 已知平台范围:
icon默认staricon可用:star、heart、thumbsup、fire、smile、lightning、flower、numbermin取值0..1,默认1max取值1..10,默认5
{
"type": "number",
"name": "评分",
"style": { "type": "rating", "icon": "star", "min": 1, "max": 5 }
}3.3 select
单选和多选都使用 select;用 multiple 区分。multiple 默认 false。静态选项用 options,动态选项用 dynamic_options_source;两者不要同时传。
静态选项
支持字段:multiple、options 支持 default_value:静态选项名数组;即使 multiple=false 也写数组,如 ["Todo"]。
默认值 / 约束:
multiple默认falseoptions最多10000项options[]结构是{name, hue?, lightness?}options[].name必填options[].hue可用:Red、Orange、Yellow、Lime、Green、Turquoise、Wathet、Blue、Carmine、Purple、Gray缺省值为Blueoptions[].lightness可用:Lighter、Light、Standard、Dark、Darker缺省值为Lighter- 选项里没有
id,只有name。 - 支持
default_value配置:填选项名数组。
{
"type": "select",
"name": "状态",
"multiple": false,
"default_value": ["Todo"],
"options": [
{ "name": "Todo", "hue": "Blue", "lightness": "Lighter" },
{ "name": "Done", "hue": "Green", "lightness": "Light" }
]
}动态选项
当新字段要引用或复用另一选项字段的选项列表时,优先使用 dynamic_options_source,避免重复定义和维护 options。
支持字段:multiple、dynamic_options_source 动态选项不支持 default_value。
默认值 / 约束:
multiple默认falsedynamic_options_source结构是{table_id, field_id}dynamic_options_source.table_id填来源表 id 或表名dynamic_options_source.field_id填来源字段 id 或字段名dynamic_options_source仅创建支持;更新已有字段时不要传- 引用选项条件 / 级联筛选条件:这个功能在 Base 前端支持,属于 UI-only 属性,OpenAPI 里不支持,CLI 不能读取、创建或更新;不要根据接口返回缺失判断未配置
- 动态选项不支持配置
default_value。
{
"type": "select",
"name": "动态状态",
"multiple": false,
"dynamic_options_source": {
"table_id": "选项表",
"field_id": "候选状态"
}
}3.4 datetime
手动填写的日期/时间字段。系统时间用 created_at / updated_at。 支持 default_value:静态时间字符串,或 { "$slot": "record_created_time" }。datetime + record_created_time 是自动填充可编辑单元格;created_at 是只读创建时间元信息。
最小写法:
{
"type": "datetime",
"name": "截止时间",
"default_value": "2026-03-24 10:00"
}支持字段:style.format
默认值 / 约束:
style.format默认yyyy/MM/dd可用格式:yyyy/MM/dd、yyyy/MM/dd HH:mm、yyyy/MM/dd HH:mm Z、yyyy-MM-dd、yyyy-MM-dd HH:mm、yyyy-MM-dd HH:mm Z、MM-dd、MM/dd/yyyy、dd/MM/yyyystyle.format只控制 Base 前端展示,不影响 CLI 读取的 CellValue;前端当前最多配置到分钟级展示,底层时间值以毫秒级精度存储。
常用写法:
{
"type": "datetime",
"name": "截止时间",
"style": { "format": "yyyy-MM-dd HH:mm" },
"default_value": { "$slot": "record_created_time" }
}3.5 created_at / updated_at
系统创建时间 / 系统更新时间字段;可配显示格式,但记录写入时应视为只读。
支持字段:style.format
默认值 / 约束:
style.format默认yyyy/MM/dd- 可用格式:
yyyy/MM/dd、yyyy/MM/dd HH:mm、yyyy/MM/dd HH:mm Z、yyyy-MM-dd、yyyy-MM-dd HH:mm、yyyy-MM-dd HH:mm Z、MM-dd、MM/dd/yyyy、dd/MM/yyyy
{ "type": "created_at", "name": "创建时间" }{ "type": "updated_at", "name": "更新时间", "style": { "format": "yyyy/MM/dd HH:mm" } }3.6 user / group_chat
两者都支持 multiple(默认 true);仅 user 支持人员数组 default_value,元素使用 { "id": "ou_xxx" } 或 { "$slot": "current_user" },用户 ID 必须来自真实查询。
{
"type": "user",
"name": "负责人",
"multiple": true,
"default_value": [{ "$slot": "current_user" }, { "id": "ou_xxx" }]
}{ "type": "group_chat", "name": "负责群", "multiple": true }3.7 created_by / updated_by
系统创建人和修改人字段,记录写入时只读:{ "type": "created_by", "name": "创建人" }、{ "type": "updated_by", "name": "更新人" }。
3.8 link
关联字段;link_table 必填。
支持字段:link_table、bidirectional、bidirectional_link_field_name
默认值 / 约束:
link_table必填link字段的单元格表示“当前记录关联到的对侧表记录集合”bidirectional默认falsebidirectional=true时,会在被关联表自动创建一个反向关联字段。任一侧记录的关联关系发生变更时,另一侧对应记录会自动同步更新bidirectional_link_field_name仅在bidirectional=true时使用- 关联字段筛选:这个功能在 Base 前端支持,属于 UI-only 属性,OpenAPI 里不支持,CLI 不能读取、创建或更新;不要根据接口返回缺失判断未配置
{
"type": "link",
"name": "关联任务",
"link_table": "任务表"
}双向关联:
{
"type": "link",
"name": "关联任务",
"link_table": "任务表",
"bidirectional": true,
"bidirectional_link_field_name": "反向关联"
}更新时注意:
link不允许转换为其他类型,其他类型也不能转换为link。- 现有
link字段的bidirectional不能改。
3.9 formula
公式字段;expression 必填。创建/更新前先读 Formula Field 学习公式语法。
{
"type": "formula",
"name": "合计",
"expression": "1+1"
}3.10 lookup
查找引用字段使用 from、select、where 和可选 aggregate;结构、条件和聚合值必须按 Lookup Field 构造。
3.11 auto_number
自动编号字段;创建时不写 style.rules 会使用默认规则:NO.001。更新已有自动编号字段时应显式提交目标 style.rules,因为 +field-update 会把新的编号规则重新应用到已有编号。
最小写法:
{
"type": "auto_number",
"name": "编号"
}style.rules 包含 1–9 条规则:固定文本用 { "type":"text", "text":"TASK-" };递增序号用 { "type":"incremental_number", "length":4 }(长度 1–9);创建时间用 { "type":"created_time", "date_format":"yyyyMMdd" },格式支持 yyyyMMdd、yyyyMM、yyMM、MMdd、yyyy、MM、dd。
自定义规则:
{
"type": "auto_number",
"name": "编号",
"style": {
"rules": [
{ "type": "text", "text": "TASK-" },
{ "type": "created_time", "date_format": "yyyyMMdd" },
{ "type": "incremental_number", "length": 4 }
]
}
}3.12 attachment / location / checkbox
{ "type": "attachment", "name": "附件" }{ "type": "location", "name": "位置" }Location 读取为 {lng,lat,full_address};写入只使用数字 {lng,lat},full_address 由平台根据坐标解析,不允许手动指定;筛选行为按照 full_address 做字符串筛选,将 Location 当作文本列使用文本 operator。location -> text 时只保留 full_address。
{ "type": "checkbox", "name": "完成" }4. 创建与更新
+field-create:按目标字段配置直接构造--json。+field-update:使用同样的 JSON 结构,但执行完整覆盖更新,不是局部 patch。先用+field-get读取当前定义,在其基础上修改目标属性;需要保留的名称、类型、样式、选项、默认值、描述及类型专属配置都应完整写回,并带--yes。
5. 暂不支持字段
Object(对象字段)、Button(按钮字段)、Stage(流程字段)暂时都没有被 CLI 支持。这些字段会展示为 not_support 字段并被保护:不允许修改,不允许读取内容。
6. 易错点
select只有一个类型;不要写single_select/multi_select,用multiple控制是否多选。number的精度、货币、进度、评分配置都放在style下,不要写顶层precision。datetime是手动日期字段;系统时间请改用created_at/updated_at。formula/lookup没读 guide 前不要直接写。- 只有
text、number、静态select、datetime、user支持default_value;清空统一传"default_value": null。其他字段类型不要配置默认值。
lark-baseに関連するスキルは?
Lark Base スキルのフォークは?
カタログにはLark Baseのコピーが1件あり、インストール数は合計48.7万です。これらはすべて、この元のリスティングに正規化されます。
- larksuite - インストール数48.7万
Lark Base スキルのよくある質問
Lark Base スキルはどんな人に向いていますか?
Feishu の Base(bitable)で、構造化データを構築し、クエリする場合に向いています。 次に当てはまる場合は見送ってください:Excel / CSV / .base の Base へのインポート(lark-drive を使います)や、認証とスコープの扱い(lark-shared を使います)には向きません。
lark-baseはどんなときに使いますか?
Feishu の Base、bitable、多次元テーブル、または /base/ のリンクを扱うときに使います。
lark-baseのバッジを追加する
このスキルは現在、SkillselionのTop 25で#25です。アワードバッジは最新の順位を表示し、自動で更新されます。
埋め込みコードを取得
このスキルがSkillselionに掲載されていることを開発者に示せます。READMEに貼り付けてください。