first commit
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
# advperm — 高级权限管理
|
||||
|
||||
控制 Base 的高级权限总开关,并管理自定义角色(增删改查 + 子角色权限规则)。
|
||||
适用场景:"如何控制谁能看/改 Base 数据"、"开启/关闭高级权限"、"新建/修改/删除角色"、"按字段或行配置权限"。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `advperm enable` | 开启 Base 高级权限总开关 |
|
||||
| `advperm disable` | 关闭 Base 高级权限总开关(高危) |
|
||||
| `advperm role-list` | 列出 Base 下全部角色 |
|
||||
| `advperm role-get` | 获取单角色完整配置 |
|
||||
| `advperm role-create` | 创建自定义角色 |
|
||||
| `advperm role-update` | 增量更新自定义角色(PATCH 语义) |
|
||||
| `advperm role-delete` | 删除自定义角色(不可逆) |
|
||||
|
||||
> 所有子命令的 `--base-id` 必填,可用隐藏别名 `--base`。
|
||||
|
||||
## 命令详情
|
||||
|
||||
### advperm enable — 开启高级权限
|
||||
|
||||
```bash
|
||||
dws aitable advperm enable --base-id BASE_ID --format json
|
||||
```
|
||||
|
||||
返回 `{baseId, enabled: true}`。
|
||||
|
||||
只有开启后角色配置才会真正限制成员的可访问范围;关闭状态下角色配置仍可读但不生效。
|
||||
|
||||
### advperm disable — 关闭高级权限(高危)
|
||||
|
||||
```bash
|
||||
dws aitable advperm disable --base-id BASE_ID --yes --format json
|
||||
```
|
||||
|
||||
返回 `{baseId, enabled: false}`。关闭后所有角色配置即刻失效,全员回退到默认权限。涉及多人协作或敏感数据务必和用户二次确认,建议先 `role-list` 留底。
|
||||
|
||||
### advperm role-list — 列出全部角色
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-list --base-id BASE_ID --format json
|
||||
```
|
||||
|
||||
返回结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"enabled": true,
|
||||
"defaultRole": { "mode": 0 },
|
||||
"roles": [
|
||||
{
|
||||
"roleId": "10685308981",
|
||||
"name": "可查看角色",
|
||||
"roleType": "custom",
|
||||
"system": false,
|
||||
"subRoles": [
|
||||
{
|
||||
"authLevel": "read",
|
||||
"targetId": "HMEaRQ4",
|
||||
"targetType": "sheet",
|
||||
"config": { "actions": 268435455 },
|
||||
"display": {
|
||||
"authLevelLabel": "仅查看",
|
||||
"targetTypeLabel": "数据表",
|
||||
"permissionScopeNote": "...",
|
||||
"actionsLabels": ["新增视图", "删除视图", "修改视图"],
|
||||
"actionsNote": "..."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
关键字段:
|
||||
|
||||
- `roleType`:`custom`(自定义) / `system_editor` / `system_reader` / `5000`(owner) / `4000`(manager)。
|
||||
- `system`:boolean,true 表示系统角色(不可删)。
|
||||
- `subRoles[].display.*`:服务端返回的人类可读标签,可直接拼接给用户阅读,无需自行映射枚举。
|
||||
- 不返回角色成员列表;如需"成员-角色"映射请去 AI 表格 Web 端。
|
||||
- 新建 Base 默认 `enabled=false`,开启后只有 `owner` / `manager` 两个 meta 角色;`system_editor` / `system_reader` 需要在 Web UI 给成员授权"可编辑/可查看"后才会被服务端自动生成。
|
||||
|
||||
`role-list` / `role-get` 不需要管理员权限,普通成员也可读。
|
||||
|
||||
### advperm role-get — 获取单角色配置
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-get --base-id BASE_ID --role-id ROLE_ID --format json
|
||||
```
|
||||
|
||||
返回结构同 `role-list` 中单个 role 对象(含完整 `subRoles[].config` 字段/行级规则与 `display.*` 标签)。
|
||||
|
||||
### advperm role-create — 创建自定义角色
|
||||
|
||||
```bash
|
||||
# 仅指定 name,子角色由服务端按默认(none)填充
|
||||
dws aitable advperm role-create --base-id BASE_ID --name "市场可读" --format json
|
||||
|
||||
# 创建时即指定 sub-roles(推荐——避免再走一次 role-update)
|
||||
dws aitable advperm role-create --base-id BASE_ID --name "市场可读" \
|
||||
--sub-roles '[{"targetId":"<sheetId>","targetType":"sheet","authLevel":"read"}]' --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|:---:|------|
|
||||
| `--name` | ✅ | 角色名称 |
|
||||
| `--role-type` | | 角色类型字符串(留空由服务端决定默认值,如 `custom`) |
|
||||
| `--flow-type` | | 流程类型字符串(按业务需要) |
|
||||
| `--sub-roles` | | JSON 数组:`[{targetId, targetType, authLevel, appId?, config?}]`,详见下方"sub-roles 子字段"段 |
|
||||
|
||||
返回新建角色的完整配置(同 `role-get` 出参格式,含自动生成的 default subRoles)。
|
||||
系统角色无法通过本命令创建。
|
||||
|
||||
### advperm role-update — 增量更新自定义角色(PATCH 语义)
|
||||
|
||||
```bash
|
||||
# 只改名
|
||||
dws aitable advperm role-update --base-id BASE_ID --role-id ROLE_ID --name "新名字"
|
||||
|
||||
# 只改 sheet 子角色 authLevel,name 不传保持不变
|
||||
dws aitable advperm role-update --base-id BASE_ID --role-id ROLE_ID \
|
||||
--sub-roles '[{"targetId":"<sheetId>","targetType":"sheet","authLevel":"edit-own"}]'
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|:---:|------|
|
||||
| `--role-id` | ✅ | 目标自定义角色 ID(数字 long 字符串) |
|
||||
| `--name` | | 新角色名称;不传不修改 |
|
||||
| `--role-type` / `--flow-type` | | 可选 |
|
||||
| `--sub-roles` | | JSON 数组,**PATCH 合并语义**:按 `(targetId, targetType)` 合并到现有 subRoles,入参中的 sub 整体替换该 sub,**入参未提及的 sub 保留不变**(无需先调 `role-get` 自行 merge) |
|
||||
|
||||
**系统角色禁止更新**(包括 owner / manager / system_editor / system_reader)。
|
||||
|
||||
### sub-roles 子字段
|
||||
|
||||
每个 sub-role 描述「角色对某个权限目标的访问粒度」:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `targetId` | string | 目标资源 ID(数据表 → `tableId`;仪表盘 → `dashboardId`;应用 → `appId`) |
|
||||
| `targetType` | string | `sheet` / `dashboard` / `app` |
|
||||
| `authLevel` | string | `manage` / `edit-own` / `edit-custom-field` / `edit-field-range` / `read` / `none` |
|
||||
| `appId` | string(可选) | 仅 `targetType=app` 时使用 |
|
||||
| `config` | object(可选) | 字段/行级细化规则;含 `actions`(位图)/ `rows` / `cells`。结构与 `role-get` 出参 `subRoles[].config` 对齐 |
|
||||
|
||||
### advperm role-delete — 删除自定义角色(不可逆)
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-delete --base-id BASE_ID --role-id ROLE_ID --yes --format json
|
||||
```
|
||||
|
||||
要求同时满足:
|
||||
|
||||
1. 该 Base 已开启高级权限(`role-list` 返回 `enabled=true`)。
|
||||
2. 当前 dws 登录用户是该 Base 的管理员/Owner。
|
||||
3. `--role-id` 是 `role-list` 返回的数字 long 字符串(如 `"10685308981"`),且对应角色 `system=false`。
|
||||
|
||||
不可逆,删前先 `role-get` 留底。
|
||||
|
||||
## 能力边界
|
||||
|
||||
| 能力 | 状态 |
|
||||
|------|------|
|
||||
| 开/关高级权限 | ✅ 需管理员 |
|
||||
| 列出 / 读取角色 | ✅ 普通成员也可读 |
|
||||
| 创建自定义角色 | ✅ 需管理员 |
|
||||
| 增量修改角色(PATCH 语义,不清空未传字段) | ✅ 需管理员 |
|
||||
| 删除自定义角色 | ✅ 需管理员 |
|
||||
| 修改/删除系统角色 | ❌ 服务端禁止;只能在 AI 表格 Web 端操作 |
|
||||
| 角色 ↔ 成员绑定 | ❌ CLI 暂不支持,需在 AI 表格 Web 端 → Base 设置 → 高级权限 → 角色管理面板手动完成 |
|
||||
|
||||
## 错误码速查
|
||||
|
||||
| 场景 | code | type | message |
|
||||
|------|------|------|---------|
|
||||
| advperm 关闭时调用写接口(如 `role-delete` / `role-create` / `role-update`) | `ADVANCED_PERMISSION_DISABLED` | `USER_ERROR` | `Advanced permission is disabled for base <BASE>, please enable it via setAdvancedPermission before managing roles` |
|
||||
| 非管理员调用 `enable` / `disable` / `role-create` / `role-update` / `role-delete` | `401` | `AUTH_ERROR` | `the current user must be a manager (administrator) of this base to manage roles or advanced permission` |
|
||||
| 删除/更新系统角色(`system=true`) | `600` | `USER_ERROR` | `Illegal argument` |
|
||||
| 操作不存在的数字 roleId(get/update/delete) | `600` | `USER_ERROR` | `Illegal argument` |
|
||||
| 传非数字 roleId(如 `owner` / `manager`) | `INVALID_PARAMS` | `INPUT_ERROR` | `roleId is required` |
|
||||
| `role-create` 缺 `--name` | `INVALID_PARAMS` | `INPUT_ERROR` | `name is required` |
|
||||
| `--sub-roles` JSON 不是数组 / 解析失败 | (CLI 层拦截) | — | `--sub-roles 解析失败 ...` / `--sub-roles 必须是 JSON 数组` |
|
||||
| `--base-id` 无法解析 | `INVALID_BASE_ID` | `INPUT_ERROR` | `baseId cannot be resolved to docId` |
|
||||
|
||||
> `600 / Illegal argument` 同时覆盖"操作系统角色"和"操作不存在 roleId"两种情况。拿到 `600` 时先 `role-list` 自查目标 roleId 是否存在、是否 `system=true`,再据此引导用户。
|
||||
|
||||
## 典型工作流
|
||||
|
||||
### 排查"成员看不到某些字段/记录"
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-list --base-id BASE_ID --format json
|
||||
# 若 enabled=false:高级权限未开,所有规则不生效,与用户确认是否需要 enable
|
||||
|
||||
dws aitable advperm enable --base-id BASE_ID --format json
|
||||
dws aitable advperm role-list --base-id BASE_ID --format json
|
||||
# 看 roles[] 里有哪些自定义角色
|
||||
|
||||
dws aitable advperm role-get --base-id BASE_ID --role-id ROLE_ID --format json
|
||||
# 检查 subRoles[].config 中的字段/行级权限规则
|
||||
```
|
||||
|
||||
### 新建一个"市场可读"角色
|
||||
|
||||
```bash
|
||||
# 1. 确保高级权限已开
|
||||
dws aitable advperm enable --base-id BASE_ID --format json
|
||||
|
||||
# 2. 拿目标 sheet 的 tableId
|
||||
dws aitable table get --base-id BASE_ID --format json
|
||||
|
||||
# 3. 创建角色 + 指定 sheet 子角色 authLevel=read
|
||||
dws aitable advperm role-create --base-id BASE_ID --name "市场可读" \
|
||||
--sub-roles '[{"targetId":"<tableId>","targetType":"sheet","authLevel":"read"}]' \
|
||||
--format json
|
||||
# → 返回新角色完整配置,含 roleId,记下后续 patch / delete 使用
|
||||
```
|
||||
|
||||
### 升级角色权限(read → edit-own),保留其他配置
|
||||
|
||||
```bash
|
||||
# 只传 sub-roles,name 等其他字段保持不变(PATCH 语义)
|
||||
dws aitable advperm role-update --base-id BASE_ID --role-id ROLE_ID \
|
||||
--sub-roles '[{"targetId":"<tableId>","targetType":"sheet","authLevel":"edit-own"}]' \
|
||||
--format json
|
||||
```
|
||||
|
||||
### 改角色名(不影响权限规则)
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-update --base-id BASE_ID --role-id ROLE_ID --name "新名字"
|
||||
```
|
||||
|
||||
### 清理废弃角色
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-list --base-id BASE_ID --format json
|
||||
dws aitable advperm role-delete --base-id BASE_ID --role-id ROLE_ID --yes --format json
|
||||
```
|
||||
|
||||
### 关闭高级权限(恢复全员可见)
|
||||
|
||||
```bash
|
||||
dws aitable advperm role-list --base-id BASE_ID --format json > /tmp/roles-backup.json
|
||||
dws aitable advperm disable --base-id BASE_ID --yes --format json
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# attachment — 附件上传
|
||||
|
||||
> **STOP — 不要使用钉盘 (drive) 上传!** 钉盘 fileId 无法写入 attachment 字段。必须使用以下流程。
|
||||
>
|
||||
> **STOP — 严禁在 record create/update 的 cells 里直接传图片 URL!** 直传 `{"url":"https://..."}` 会导致服务端同步下载图片,批量写入时触发 TIMEOUT_ERROR。正确做法:先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。
|
||||
|
||||
## 准备附件上传
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable attachment upload [flags]
|
||||
Example:
|
||||
dws aitable attachment upload --base-id <BASE_ID> --file-name report.xlsx --size 204800
|
||||
dws aitable attachment upload --base-id <BASE_ID> --file-name photo.png --size 1024 --mime-type image/png
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--file-name string 文件名,必须含扩展名 (必填)
|
||||
--size int 文件大小(字节),>0 (必填)
|
||||
--mime-type string MIME type(不传时根据扩展名推断)
|
||||
```
|
||||
|
||||
## 附件上传完整流程(推荐:使用脚本,2 步完成)
|
||||
|
||||
```bash
|
||||
# 步骤 1: 使用脚本一键上传(内部自动完成 prepare + PUT)
|
||||
python3 scripts/upload_attachment.py <BASE_ID> /path/to/report.pdf
|
||||
# 输出: { "fileToken": "ft_xxx", "fileName": "report.pdf", "size": 204800 }
|
||||
|
||||
# 步骤 2: 在 record create/update 中使用 fileToken 写入
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldAttachId":[{"fileToken":"ft_xxx"}]}}]' --format json
|
||||
```
|
||||
|
||||
> `uploadUrl` 有时效性(`expiresAt`),脚本会自动在获取后立即上传。
|
||||
|
||||
## 手动流程(不使用脚本)
|
||||
|
||||
```bash
|
||||
# 1. 获取上传凭证
|
||||
dws aitable attachment upload --base-id <BASE_ID> --file-name report.pdf --size 204800 --format json
|
||||
# → 返回 uploadUrl、fileToken
|
||||
|
||||
# 2. PUT 上传(Content-Type 必须是文件的具体 MIME type)
|
||||
curl -X PUT "<uploadUrl>" -H "Content-Type: application/pdf" --data-binary @report.pdf
|
||||
|
||||
# 3. 写入记录
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"fldAttachId":[{"fileToken":"ft_xxx"}]}}]' --format json
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
# AI 表格最佳实践
|
||||
|
||||
## 1. 字段可写性分类
|
||||
|
||||
| 字段类型 | 可写 | 正确方式 |
|
||||
|----------|------|----------|
|
||||
| 文本/数字/日期/单选/多选/复选框/URL | ✅ | record create/update |
|
||||
| 附件 | ⚠️ | 必须先走 [attachment upload 流程](./aitable-attachment.md) |
|
||||
| 创建人/修改人/创建时间/修改时间 | ❌ | 系统字段,只读 |
|
||||
| 公式/查找引用 | ❌ | 只读,由系统计算 |
|
||||
| AI 字段 | ❌ | 只读,由 AI 自动计算 |
|
||||
|
||||
## 2. 查询执行契约
|
||||
|
||||
1. **不要拉全量后在 context 里手动统计** — 标量聚合用 `record stats`,分组/去重用 `record group-stats`
|
||||
2. **has_more=true 时不能做全局结论** — 数据可能不完整
|
||||
3. **优先用 `--filters` 在服务端过滤** — 不要拉全量后在本地 jq/grep
|
||||
4. **fieldId 必须来自 `field get` 真实返回** — 不要猜测 fieldId
|
||||
5. **减少响应体积** — 用 `--field-ids` 仅返回需要的字段
|
||||
|
||||
## 3. 任务选路
|
||||
|
||||
| 用户诉求 | 优先方案 | 不要误走 |
|
||||
|---------|----------|----------|
|
||||
| 查看几条数据 | `record query` | 不要用 `--all` |
|
||||
| 全量拉取明细 | `record query --all` | 不要手动循环 cursor |
|
||||
| 标量统计 | `record stats` | 不要先拉全量再本地计算 |
|
||||
| 分组/去重统计 | `record group-stats` | 不要先拉全量再本地 groupby |
|
||||
| 全量导出为文件 | `export data` | 不要 `--all` 拉全量再写文件 |
|
||||
| 批量写入 | `record create`(分批 100 条) | 不要一次传超过 100 条 |
|
||||
| 附件/图片上传 | `attachment upload` 获取 fileToken → `record create/update` 用 fileToken 写入 | **严禁直接传图片 URL 到附件字段**(服务端同步下载会超时) |
|
||||
| 文件级导入 | `import upload` + `import data` | 不要手动解析 xlsx 再逐条写入 |
|
||||
|
||||
## 4. 创建/修改后回读确认
|
||||
|
||||
执行写操作后,建议立即回读确认结果:
|
||||
|
||||
| 写操作 | 建议回读命令 | 确认内容 |
|
||||
|--------|-------------|----------|
|
||||
| `table create` | `table get --table-ids <新tableId>` | 表名、字段列表是否符合预期 |
|
||||
| `field create` | `field get --table-id <tableId>` | 新字段是否出现在字段列表中 |
|
||||
| `record create/update` | `record query --record-ids <新recordId>` | 写入值是否正确 |
|
||||
|
||||
## 5. AI 字段注意事项
|
||||
|
||||
- AI 字段的 prompt **必须至少包含一个 `fieldRef` 引用**,纯文本 prompt 会被后端拒绝
|
||||
- 先创建/确认被引用字段的 fieldId,再在 prompt 中引用
|
||||
- `outputType` 必须与字段类型一致(如 `outputType=text` 配 `--type text`)
|
||||
@@ -0,0 +1,346 @@
|
||||
# cells 写入/读取格式规范(cellValue 数据结构)
|
||||
|
||||
> 适用命令:`dws aitable record create --records`、`dws aitable record update --records`、`dws aitable record query` 返回
|
||||
>
|
||||
> 本文件是 DWS AI 表格 cellValue 的 **source of truth**。写入记录时,必须严格按此格式构造 cells 对象。
|
||||
|
||||
## 顶层规则
|
||||
|
||||
- cells 的 key **必须是 fieldId**(如 `fldXXX`),不是字段名称
|
||||
- fieldId 必须从 `field get` 返回中获取
|
||||
- 不同字段类型的 value 格式不同,混用会报错
|
||||
- 系统只读字段(creator/lastModifier/createdTime/lastModifiedTime/formula)不可写入
|
||||
|
||||
## 各字段类型详解
|
||||
|
||||
### text(文本)
|
||||
|
||||
**写入**:字符串
|
||||
```json
|
||||
{"fldTextId": "这是一段文本"}
|
||||
```
|
||||
|
||||
**读取**:字符串
|
||||
```json
|
||||
{"fldTextId": "这是一段文本"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### number(数字)
|
||||
|
||||
**写入**:数字或数字字符串
|
||||
```json
|
||||
{"fldNumId": 123.45}
|
||||
{"fldNumId": "123.45"}
|
||||
```
|
||||
|
||||
**读取**:字符串形式的数字
|
||||
```json
|
||||
{"fldNumId": "123.45"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### singleSelect(单选)
|
||||
|
||||
**写入**:选项名称字符串(推荐),或对象形式 `{id, name}`
|
||||
```json
|
||||
{"fldSelectId": "进行中"}
|
||||
{"fldSelectId": {"id": "opt_xxx", "name": "进行中"}}
|
||||
```
|
||||
|
||||
> 写入不存在的选项名称时,系统会自动创建该选项。
|
||||
> 对象写入时 id 为准,服务端会校验 id 是否存在。
|
||||
|
||||
**读取**:对象 `{id, name}`
|
||||
```json
|
||||
{"fldSelectId": {"id": "opt_abc123", "name": "进行中"}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### multipleSelect(多选)
|
||||
|
||||
**写入**:选项名称数组(推荐),或对象数组
|
||||
```json
|
||||
{"fldMultiId": ["标签A", "标签B"]}
|
||||
{"fldMultiId": [{"id": "opt_a", "name": "标签A"}, {"id": "opt_b", "name": "标签B"}]}
|
||||
```
|
||||
|
||||
> 写入时每项需带 id(对象模式)或直接传 name 字符串。不存在的 name 会自动补入选项配置。
|
||||
|
||||
**读取**:对象数组
|
||||
```json
|
||||
{"fldMultiId": [{"id": "opt_a", "name": "标签A"}, {"id": "opt_b", "name": "标签B"}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### date(日期)
|
||||
|
||||
**写入**:日期字符串、RFC3339 字符串、或毫秒时间戳
|
||||
```json
|
||||
{"fldDateId": "2026-03-15"}
|
||||
{"fldDateId": "2026-03-15 09:00"}
|
||||
{"fldDateId": "2026-03-15T09:00+08:00"}
|
||||
```
|
||||
|
||||
**读取**:RFC3339 字符串(带时区)
|
||||
```json
|
||||
{"fldDateId": "2026-03-15T09:00:00+08:00"}
|
||||
```
|
||||
|
||||
**过滤**(`record query --filters`):日期字段**只能用日期专用操作符** `date_eq` / `before` / `after` / `not_before` / `not_after` / `exist` / `un_exist`,比较值用日期字符串(如 `"2026-03-15"`)。
|
||||
- ❌ 通用 `eq` / `ne` / `gt` / `gte` / `lt` / `lte` / `contain` 对日期字段无效,会静默返回 0 条;
|
||||
- ❌ 不支持区间 `date_between` 与相对 `from_now`(CLI 会直接拒绝),范围查询用 `not_before` + `not_after` 组合。
|
||||
- 详见 [aitable-filter-sort.md](./aitable-filter-sort.md) §日期字段过滤。
|
||||
|
||||
---
|
||||
|
||||
### currency(货币)
|
||||
|
||||
**写入**:数字(与 number 相同)
|
||||
```json
|
||||
{"fldCurrencyId": 99.5}
|
||||
```
|
||||
|
||||
**读取**:字符串形式的数字(小数位数取决于 formatter 配置)
|
||||
```json
|
||||
{"fldCurrencyId": "99.5"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### progress(进度)
|
||||
|
||||
**写入**:0~1 之间的浮点数(0 表示 0%,1 表示 100%)
|
||||
```json
|
||||
{"fldProgressId": 0.75}
|
||||
```
|
||||
|
||||
> ⚠️ **常见错误**:写入 75 不会报错,但会被存储为 7500%(因为系统将其理解为 75 倍)。
|
||||
> 正确做法:75% 应写入 0.75。API 不会拒绝超出 [0,1] 的值,但显示会异常。
|
||||
> 如果字段配置了 `customizeRange`,则按自定义范围传值。
|
||||
|
||||
**读取**:字符串形式的数字
|
||||
```json
|
||||
{"fldProgressId": "0.75"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### rating(评分)
|
||||
|
||||
**写入**:整数,必须在字段配置的 min~max 范围内
|
||||
```json
|
||||
{"fldRatingId": 4}
|
||||
```
|
||||
|
||||
> ⚠️ 超出 max 范围的值(如 max=5 时写入 6)会被服务端拒绝并返回错误。
|
||||
|
||||
**读取**:数字(字符串形式)
|
||||
```json
|
||||
{"fldRatingId": "4"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### checkbox(勾选)
|
||||
|
||||
**写入**:布尔值
|
||||
```json
|
||||
{"fldCheckId": true}
|
||||
{"fldCheckId": false}
|
||||
```
|
||||
|
||||
**读取**:布尔值
|
||||
```json
|
||||
{"fldCheckId": true}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### user(人员)
|
||||
|
||||
**写入**:对象数组,每项必须含 `userId` 和 `corpId`
|
||||
```json
|
||||
{"fldUserId": [{"userId": "staff_001", "corpId": "dingxxxxxxxx"}]}
|
||||
```
|
||||
|
||||
> 单选字段(`multiple=false`)也必须传数组,只是数组长度为 1。
|
||||
> 如果目标用户不在当前请求组织内,回退为 `[{"userRef": "ur_0AaZ19"}]`。
|
||||
|
||||
**读取**:对象数组
|
||||
```json
|
||||
{"fldUserId": [{"userId": "staff_001", "corpId": "dingxxxxxxxx"}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### department(部门)
|
||||
|
||||
**写入**:对象数组,每项含 `deptId`
|
||||
```json
|
||||
{"fldDeptId": [{"deptId": "52528700"}]}
|
||||
```
|
||||
|
||||
**读取**:对象数组
|
||||
```json
|
||||
{"fldDeptId": [{"deptId": "52528700"}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### group(群组)
|
||||
|
||||
**写入**:对象数组,每项含 `cid`
|
||||
```json
|
||||
{"fldGroupId": [{"cid": "74577067501"}]}
|
||||
```
|
||||
|
||||
> ⚠️ key 是 **`cid`**,不是 `openConversationId`
|
||||
|
||||
**读取**:对象数组
|
||||
```json
|
||||
{"fldGroupId": [{"cid": "74577067501"}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### url(链接)
|
||||
|
||||
**写入**:对象 `{text, link}` 或纯 URL 字符串
|
||||
```json
|
||||
{"fldUrlId": {"text": "钉钉官网", "link": "https://dingtalk.com"}}
|
||||
{"fldUrlId": "https://dingtalk.com"}
|
||||
```
|
||||
|
||||
> 纯字符串写入时,服务端自动补齐为 `{"text":"原字符串","link":"原字符串"}`
|
||||
|
||||
**读取**:对象 `{text, link}`
|
||||
```json
|
||||
{"fldUrlId": {"text": "钉钉官网", "link": "https://dingtalk.com"}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### richText(富文本)
|
||||
|
||||
**写入**:对象 `{markdown: "..."}`
|
||||
```json
|
||||
{"fldRichId": {"markdown": "**加粗**\n普通文字\n"}}
|
||||
```
|
||||
|
||||
**读取**:对象 `{markdown: "..."}`(有损,颜色/@人等信息可能丢失)
|
||||
```json
|
||||
{"fldRichId": {"markdown": "**加粗**\n普通文字\n"}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### attachment(附件)
|
||||
|
||||
**写入**:对象数组,**必须使用 `fileToken`**
|
||||
|
||||
```json
|
||||
{"fldAttachId": [{"fileToken": "ft_xxx"}]}
|
||||
```
|
||||
|
||||
> ⚠️ **必须先通过 [attachment upload 流程](./aitable-attachment.md) 上传文件获取 `fileToken`,再将 `fileToken` 写入 cells。**
|
||||
> ❌ **严禁直接传 `{"url": "https://..."}` 形式写入附件/图片字段** — 服务端会同步下载图片,10 条记录即触发 TIMEOUT_ERROR 超时。
|
||||
> 写入会**整体覆盖**原附件列表,不是追加。
|
||||
|
||||
**读取**:对象数组(含下载链接、文件名、大小)
|
||||
```json
|
||||
{"fldAttachId": [{"url": "https://...", "filename": "report.pdf", "size": 204800}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### telephone / email / barcode / idCard(电话/邮箱/条码/身份证)
|
||||
|
||||
**写入**:字符串
|
||||
```json
|
||||
{"fldPhoneId": "13800138000"}
|
||||
{"fldEmailId": "test@example.com"}
|
||||
{"fldBarcodeId": "978-3-16-148410-0"}
|
||||
{"fldIdCardId": "520402196001067498"}
|
||||
```
|
||||
|
||||
> idCard 必须是后端认可的合法身份证号格式
|
||||
|
||||
**读取**:字符串
|
||||
```json
|
||||
{"fldPhoneId": "13800138000"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### geolocation(地理位置)
|
||||
|
||||
**写入**:对象,包含 `address`、`name`、`location`
|
||||
```json
|
||||
{
|
||||
"fldGeoId": {
|
||||
"address": "浙江省杭州市思凯路与爱橙街交叉口东南200米",
|
||||
"name": "阿里中心·未科D1幢",
|
||||
"location": ["120.007852", "30.271194"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> `location` 按 **[经度, 纬度]** 传**字符串数组**
|
||||
|
||||
**读取**:对象(含额外的 `fullAddress` 字段,由服务端自动拼接)
|
||||
```json
|
||||
{
|
||||
"fldGeoId": {
|
||||
"address": "浙江省杭州市",
|
||||
"fullAddress": "阿里中心-浙江省杭州市",
|
||||
"name": "阿里中心",
|
||||
"location": ["120.007852", "30.271194"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### unidirectionalLink / bidirectionalLink(关联字段)
|
||||
|
||||
**写入**:对象 `{linkedRecordIds: [...]}`
|
||||
```json
|
||||
{"fldLinkId": {"linkedRecordIds": ["recXXX", "recYYY"]}}
|
||||
```
|
||||
|
||||
**读取**:对象 `{linkedRecordIds: [...]}`
|
||||
```json
|
||||
{"fldLinkId": {"linkedRecordIds": ["recXXX", "recYYY"]}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 只读字段(禁止写入)
|
||||
|
||||
以下字段类型由系统自动填充,`record create/update` 时**禁止传入**:
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| `creator` | 创建人 |
|
||||
| `lastModifier` | 最后编辑人 |
|
||||
| `createdTime` | 创建时间 |
|
||||
| `lastModifiedTime` | 最后编辑时间 |
|
||||
| `formula` | 公式字段(系统计算) |
|
||||
| AI 字段 | 由 AI 自动计算 |
|
||||
|
||||
## 常见错误速查
|
||||
|
||||
| 错误 | 正确做法 |
|
||||
|------|----------|
|
||||
| cells key 用字段名称 `"课程名称"` | 用 fieldId `"fldXXX"` |
|
||||
| progress 写入 `75` | 写入 `0.75`(范围 0~1) |
|
||||
| attachment 直接传文件路径或图片 URL | 必须先 `attachment upload` 获取 fileToken,再用 fileToken 写入(直传 URL 会超时) |
|
||||
| user 字段传用户名字符串 | 传对象数组 `[{"userId":"...", "corpId":"..."}]` |
|
||||
| group 字段用 `openConversationId` | 用 `cid` |
|
||||
| singleSelect 传 option id 字符串 | 传 name 字符串或 `{"id":"...", "name":"..."}` 对象 |
|
||||
| 对只读字段写入值 | 不传该字段,由系统自动填充 |
|
||||
@@ -0,0 +1,55 @@
|
||||
# dashboard & chart — 仪表盘与图表
|
||||
|
||||
## 建议操作顺序
|
||||
|
||||
```bash
|
||||
# 1) 只在缺少配置结构时读取模板
|
||||
dws aitable dashboard config-example --format json
|
||||
dws aitable +chart-widgets-example --format json
|
||||
|
||||
# 2) 先拿 dashboard,再拿 chart 详情
|
||||
dws aitable dashboard get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --format json
|
||||
dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-id <CHART_ID> --format json
|
||||
```
|
||||
|
||||
只按名称创建、改名并确认时,不需要读取配置示例或 Help:
|
||||
|
||||
```bash
|
||||
dws aitable dashboard create --base-id <BASE_ID> --name <名称> --format json
|
||||
dws aitable +dashboard-update --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --name <新名称> --format json
|
||||
dws aitable +dashboard-get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --format json
|
||||
```
|
||||
|
||||
部分服务端更新回执可能仍回显更新前名称;只做一次 `+dashboard-get` 读回,以该后续权威读回为最终状态。读回已是目标名称时判定更新完成,不重放写操作,也不因旧回执继续探测 Help。
|
||||
|
||||
## 要点
|
||||
|
||||
- `dashboard get` 返回的 `charts[].chartId` 可直接给 `chart get` 使用
|
||||
- 删除 dashboard 会级联删除其全部 chart;确认前必须说明该影响
|
||||
- `dashboard share get` 可能返回 `404`(资源不存在或未开通),需按可重试错误处理,不要误判为参数拼错
|
||||
- `chart share get` 可正常返回 `enabled/shareUrl`,用于分享状态判断
|
||||
|
||||
## dashboard 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `dashboard get` | 获取仪表盘详情(含 charts 列表) | `--base-id` `--dashboard-id` | — |
|
||||
| `dashboard create` | 创建仪表盘 | `--base-id` + (`--config` 或 `--name`) | `--name` 简化版创建空看板;`--config` 传完整 JSON |
|
||||
| `dashboard update` | 更新仪表盘 | `--base-id` `--dashboard-id` + (`--config` 或 `--name`) | `--name` 仅改名;`--config` 更新完整配置 |
|
||||
| `dashboard delete` | 删除仪表盘 | `--base-id` `--dashboard-id` | 级联删除全部 chart,不可逆;由 Runtime 请求确认,Reference 不携带确认绕过参数 |
|
||||
| `dashboard config-example` | 查看仪表盘配置模板 | 无 | 创建前先调此命令了解 config 结构 |
|
||||
| `dashboard arrange` | 自动重排图表布局 | `--base-id` `--dashboard-id` | 把图表按行铺满网格,避免某行只占半幅、留下大片空白;返回 `{totalColumns, layout, alignedChartCount}` |
|
||||
|
||||
## chart 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `chart get` | 获取图表详情 | `--base-id` `--dashboard-id` `--chart-id` |
|
||||
| `chart create` | 创建图表 | `--base-id` `--dashboard-id` `--config` `--layout` |
|
||||
| `chart update` | 更新图表配置 | `--base-id` `--dashboard-id` `--chart-id` `--config` |
|
||||
| `chart delete` | 删除图表 | `--base-id` `--dashboard-id` `--chart-id` | 不可逆;由 Runtime 请求确认,Reference 不携带确认绕过参数 |
|
||||
| `+chart-widgets-example` | 查看所有图表类型的 widgets 模板 | 无 |
|
||||
|
||||
## 配置获取流程
|
||||
|
||||
已有符合当前 leaf Schema 的合法 config 时直接创建/更新,不读取模板。只有缺少结构时调用一次 `+chart-widgets-example`;该命令当前返回所有图表类型示例,随后只使用目标类型,并按真实 tableId/fieldId 填充后执行。
|
||||
@@ -0,0 +1,131 @@
|
||||
# AI 表格数据分析 SOP
|
||||
|
||||
> 当用户诉求涉及查询、筛选、排序、统计、Top/Bottom N、分组聚合、判断全局结论时,必须先读本文档再执行。
|
||||
|
||||
## 1. 查询决策树
|
||||
|
||||
```
|
||||
用户要做什么?
|
||||
│
|
||||
├─ 查看/导出原始记录明细
|
||||
│ → record query [--filters] [--sort] [--field-ids] [--limit]
|
||||
│
|
||||
├─ 按条件筛选记录(如"状态=进行中的记录")
|
||||
│ → record query --filters '{"operator":"and","operands":[...]}'
|
||||
│
|
||||
├─ 取 Top N / Bottom N(如"销售额最高的5条")
|
||||
│ → record query --sort '[{"fieldId":"xxx","direction":"desc"}]' --limit 5
|
||||
│
|
||||
├─ 全量统计(如"一共多少条"、"所有记录的总销售额")
|
||||
│ → record stats --stats '[{"fieldId":"...","statsType":"COUNT|SUM|AVG|..."}]'
|
||||
│
|
||||
├─ 分组统计(如"每个状态各有多少条")
|
||||
│ → record group-stats --group '[...]' --stats '[{"fieldId":"...","statsType":"count"}]'
|
||||
│
|
||||
├─ 条件唯一实体数(如"有索赔单的门店共有多少家")
|
||||
│ → record group-stats --filters '{...}' --stats '[{"fieldId":"<实体字段>","statsType":"distinct"}]'
|
||||
│
|
||||
└─ 判断全局结论(如"是否所有记录都满足条件")
|
||||
→ record stats 对反向过滤结果 COUNT;只有需要行级证据时再 record query
|
||||
```
|
||||
|
||||
## 2. 核心规则
|
||||
|
||||
### 2.1 禁止基于默认分页下全局结论
|
||||
|
||||
`record query` 默认返回 100 条。如果返回 JSON 中 `data.nextCursor` 非空,表示还有后续数据,当前结果**不是全量**。
|
||||
|
||||
```json
|
||||
{"data": {"nextCursor": "3hf5MtLbLZ", "records": [...]}}
|
||||
```
|
||||
|
||||
- ❌ 错误:只查了默认 100 条就说"共 100 条记录"
|
||||
- ✅ 正确:使用 `--all` 自动翻页拿全量,再统计
|
||||
|
||||
### 2.2 能在服务端过滤的,不要拉到本地再过滤
|
||||
|
||||
| 需求 | 正确做法 | 错误做法 |
|
||||
|------|---------|---------|
|
||||
| 筛选"状态=已完成" | `--filters '{"operator":"and","operands":[{"operator":"eq","operands":["fldXXX","已完成"]}]}'` | `--all` 拉全量再本地 filter |
|
||||
| 按日期降序取最新5条 | `--sort '[...]' --limit 5` | `--all` 拉全量再本地 sort + slice |
|
||||
| 模糊搜索标题含"Q1" | `--filters` 用 `contain` 操作符 | 全量拉取再本地 grep |
|
||||
|
||||
### 2.3 聚合必须优先在服务端完成
|
||||
|
||||
以下场景均有服务端聚合入口,不得先用 `record query --all` 下载全表计算:
|
||||
|
||||
- `record stats`:不分组的 COUNT / SUM / AVG / MAX / MIN / MEDIAN / DISTINCT / 完整率等
|
||||
- `record group-stats`:分组统计,以及不带 group 的条件 DISTINCT 唯一计数
|
||||
- 任意条件比率:分别聚合分子与分母,再对齐范围和 `dataVersion` 计算
|
||||
|
||||
只有用户要求记录明细、少量样本校验、精确分位数输入,或聚合接口明确返回不支持/错误时,才允许使用 `record query`。需要先逐行运算再聚合的指标(例如两个日期相减)必须使用表内已有且可聚合的公式字段;没有该字段时停止并请用户先在 AI 表格页面创建,不能下载全表本地二次计算。
|
||||
|
||||
### 2.4 --all 使用注意
|
||||
|
||||
```bash
|
||||
dws aitable record query \
|
||||
--base-id <baseId> \
|
||||
--table-id <tableId> \
|
||||
--all \
|
||||
--field-ids <只取需要的字段> \
|
||||
--format json
|
||||
```
|
||||
|
||||
- **必须配合 `--field-ids`** 限制返回字段,减少数据量
|
||||
- 对于大表(>1000条),先告知用户可能耗时
|
||||
- `--all` 会自动处理分页,无需手动翻页
|
||||
|
||||
## 3. filters 快速参考
|
||||
|
||||
详细语法见 [aitable-filter-sort.md](./aitable-filter-sort.md)。
|
||||
|
||||
### 常用操作符速查
|
||||
|
||||
| 操作符 | 适用类型 | 含义 | 示例 operands |
|
||||
|--------|---------|------|-------------|
|
||||
| `eq` | 通用 | 等于 | `["fldXXX", "值"]` |
|
||||
| `ne` | 通用 | 不等于 | `["fldXXX", "值"]` |
|
||||
| `gt` / `lt` | 数值/日期 | 大于/小于 | `["fldXXX", "25"]` |
|
||||
| `gte` / `lte` | 数值/日期 | 大于等于/小于等于 | `["fldXXX", "100"]` |
|
||||
| `contain` | 文本 | 包含 | `["fldXXX", "关键词"]` |
|
||||
| `exist` / `un_exist` | 通用 | 有值/为空 | `["fldXXX"]`(无第二参数) |
|
||||
| `any_of` | 多选 | 包含任一 | `["fldXXX", "选项A"]` |
|
||||
|
||||
### filters 结构模板
|
||||
|
||||
```json
|
||||
{
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{"operator": "eq", "operands": ["<fieldId>", "<值>"]},
|
||||
{"operator": "gt", "operands": ["<fieldId>", "<数值>"]}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 分析结果呈现规范
|
||||
|
||||
### 4.1 必须包含的信息
|
||||
|
||||
- **数据范围**:基于哪个表、哪些筛选条件、查询了多少条记录
|
||||
- **计算方法**:用了什么聚合方式(sum/count/avg 等)
|
||||
- **结果值**:精确到合理小数位
|
||||
|
||||
### 4.2 示例
|
||||
|
||||
> 基于「销售数据」表,筛选条件:日期 ≥ 2026-01-01,共查询到 342 条记录。
|
||||
> - 总销售额:¥1,234,567.89(SUM)
|
||||
> - 平均单价:¥3,610.46(AVG)
|
||||
> - 最大单笔:¥89,000.00(MAX)
|
||||
|
||||
## 5. 任务选路心智模型
|
||||
|
||||
| 用户诉求 | 优先方案 | 不要误走 |
|
||||
|---------|---------|---------|
|
||||
| 一次性标量统计 | `record stats` | 不要 `record query --all` 后本地聚合 |
|
||||
| 分组/去重统计 | `record group-stats` | 不要下载全表 groupby / 去重 |
|
||||
| 长期展示派生指标 | 创建 formula 字段(见 [formula-guide](./aitable-formula-guide.md)) | 不要每次手算再手动写入 |
|
||||
| 按条件筛选记录 | `record query --filters` | 不要 `--all` 拉全量再本地 filter |
|
||||
| 取最新/最大/前N | `--sort + --limit` | 不要 `--all` 再本地排序取前N |
|
||||
| 关键词检索 | `record query --filters` 用 `contain` | 不要把表格当搜索引擎全文检索 |
|
||||
| 验证"是否全部满足" | 反向 filters(筛不满足的),看是否有结果 | 不要 `--all` 逐条遍历 |
|
||||
@@ -0,0 +1,272 @@
|
||||
# datasource — 数据源同步管理
|
||||
|
||||
将外部数据源(当前仅支持 OA 审批)同步到 AI 表格。完整链路:list-sources → (OA) 选择模板 → get-fields → create → sync-status → sync / update / get-config。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 | 读/写 |
|
||||
|------|------|-------|
|
||||
| `+datasource-list-sources` | 列出可用数据源条目,获取 processCode/name/iconUrl/url | 读 |
|
||||
| `+datasource-get-fields` | 获取可同步字段列表,用于决定 field-ids | 读 |
|
||||
| `+datasource-create` | 创建数据源表并触发首次全量同步 | 写 |
|
||||
| `+datasource-update` | 更新已有数据源表的同步配置 | 写 |
|
||||
| `+datasource-sync` | 手动触发一次同步(最多 5 张表) | 写 |
|
||||
| `+datasource-sync-status` | 查询同步任务状态(RUNNING/FINISHED/FAILED) | 读 |
|
||||
| `+datasource-get-config` | 获取数据源表当前同步配置 | 读 |
|
||||
|
||||
## 典型工作流
|
||||
|
||||
```
|
||||
Step 0 列出可用来源 +datasource-list-sources --base-id <B> --datasource-type OA
|
||||
→ 返回 approvals 数组(通常含多个审批模板)
|
||||
|
||||
Step 0.5 (OA 审批) 选择模板 list-sources 返回的 approvals 数组通常含多个审批模板,需确定目标:
|
||||
- 用户已指定名称(如"采购申请")→ 按 name 精确/模糊匹配
|
||||
· 唯一命中 → 提取该条的 processCode/name/iconUrl/url,继续
|
||||
· 多候选 → 列出匹配项让用户消歧
|
||||
· 零命中 → 停止,提示用户确认名称或从完整列表选择
|
||||
- 用户未指定 → 列出候选模板清单(name + processCode),等用户选择
|
||||
- 禁止:未匹配直接选第一项、或凭记忆猜 processCode
|
||||
注:此步骤针对 OA 审批数据源(多模板场景);其他数据源类型的
|
||||
list-sources 返回结构可能不同,按实际 result 解析即可,
|
||||
不一定需要选择步骤。
|
||||
|
||||
Step 1 (可选) 获取可同步字段 +datasource-get-fields --base-id <B> --datasource-type OA --source-config '<JSON>'
|
||||
→ 决定需要同步哪些字段,得到 field-ids
|
||||
|
||||
Step 2 创建数据源 +datasource-create --base-id <B> --datasource-type OA --source-config '<JSON>'
|
||||
→ sourceConfig 中的 processCode/name/iconUrl/url 来自 Step 0.5 选中的模板
|
||||
→ 返回 tableId + taskId
|
||||
|
||||
Step 3 查询同步结果 +datasource-sync-status --base-id <B> --table-id <T> --task-ids <TASK_ID>
|
||||
→ FINISHED=完成,FAILED=看 errorCode 排查,RUNNING=轮询
|
||||
|
||||
Step 4 (后续) 手动触发同步 +datasource-sync --base-id <B> --table-ids <T1>,<T2>
|
||||
→ 返回新 taskId,再用 sync-status 查结果
|
||||
|
||||
Step 5 (后续) 更新配置 +datasource-update --base-id <B> --table-id <T> --source-config '<JSON>' --auto
|
||||
→ 更新后自动触发一次同步
|
||||
|
||||
查看当前配置 +datasource-get-config --base-id <B> --table-id <T>
|
||||
```
|
||||
|
||||
## sourceConfig 字段协议
|
||||
|
||||
以下字段协议仅适用于 OA 审批数据源(datasourceType=OA),其他数据源类型待后续开放。
|
||||
|
||||
### 须从 list-sources 原样透传(必填)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| processCode | String | OA 审批流程编码 |
|
||||
| name | String | 展示名称 |
|
||||
| iconUrl | String | 图标 URL |
|
||||
| url | String | 跳转链接 |
|
||||
|
||||
### 调用方自行设置
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| dataType | String | 是 | 数据范围类型:`time_range` / `start_time` / `recent_time` |
|
||||
| recentDays | String | 条件 | dataType=recent_time 时有效,取值 `7d`/`30d`/`1y`,默认 `30d` |
|
||||
| startDate | String | 条件 | dataType=time_range 或 start_time 时有效,`yyyy-MM-dd`,默认 30 天前 |
|
||||
| endDate | String | 条件 | dataType=time_range 时有效,`yyyy-MM-dd`,默认当天 |
|
||||
| keepRemovedFields | Boolean | 否 | 是否保留已删除字段,默认 false |
|
||||
| splitParentTableField | Boolean | 否 | 是否拆分父表字段 |
|
||||
|
||||
> list-sources 返回的 keepRemovedFields / splitParentTableField / enableDataSyncOaDetailList 不要透传,由调用方按需设置。
|
||||
|
||||
### 三种 dataType 最小示例
|
||||
|
||||
```json
|
||||
// recent_time — 最近一段时间
|
||||
{"processCode":"PROC-xxxx","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"...","url":"..."}
|
||||
|
||||
// time_range — 指定起止日期
|
||||
{"processCode":"PROC-xxxx","name":"采购申请","dataType":"time_range","startDate":"2025-01-01","endDate":"2025-12-31","iconUrl":"...","url":"..."}
|
||||
|
||||
// start_time — 从某日期至今
|
||||
{"processCode":"PROC-xxxx","name":"采购申请","dataType":"start_time","startDate":"2025-06-01","iconUrl":"...","url":"..."}
|
||||
```
|
||||
|
||||
## autoSyncSetting 频率配置
|
||||
|
||||
仅在 `--auto=true` 时生效。不传时使用下游默认自动同步策略。
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| syncType | 是 | `hourly`(按小时间隔)/ `scheduled`(定时触发) |
|
||||
| hourlyInterval | hourly 时 | 正整数,小时间隔 |
|
||||
| scheduleType | scheduled 时 | `daily` / `weekly` / `monthly` |
|
||||
| timeValue | scheduled 时 | `HH:mm` 触发时间 |
|
||||
| selectedMonthDays | monthly 时必填 | 每月几号触发,1-31 |
|
||||
| selectedWeekdays | weekly 时必填 | 每周哪几天触发,1=周一…7=周日 |
|
||||
| skipNonWorkingDay | 否 | 是否跳过非工作日,默认 false |
|
||||
|
||||
示例:`{"syncType":"scheduled","scheduleType":"daily","timeValue":"09:00"}`
|
||||
|
||||
## 命令详情
|
||||
|
||||
### +datasource-list-sources — 列出可用数据源条目
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-list-sources --base-id BASE_ID --datasource-type OA --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--datasource-type` | 是 | 数据源类型,当前仅支持 `OA` |
|
||||
|
||||
返回每条条目包含 `result`(下游原始 JSON 字符串)和 `sourceType`(OA 审批对应 2)。OA 审批场景下 result 为 approvals 数组:
|
||||
|
||||
```json
|
||||
{
|
||||
"approvals": [
|
||||
{
|
||||
"processCode": "PROC-xxxx",
|
||||
"name": "采购申请",
|
||||
"iconUrl": "https://...",
|
||||
"url": "https://...",
|
||||
"keepRemovedFields": false,
|
||||
"splitParentTableField": false,
|
||||
"enableDataSyncOaDetailList": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
调用方应自行解析 result,提取目标模板字段后构造 sourceConfig。
|
||||
|
||||
### +datasource-get-fields — 获取可同步字段列表
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-get-fields --base-id BASE_ID --datasource-type OA \
|
||||
--source-config '{"processCode":"PROC-xxxx","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"...","url":"..."}' \
|
||||
--format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--datasource-type` | 是 | 数据源类型,当前仅支持 `OA` |
|
||||
| `--source-config` | 是 | 源配置 JSON 字符串,结构同 create 的 --source-config |
|
||||
|
||||
返回字段列表(字段 ID、名称、类型等),用于在 create/update 中指定 `--field-ids`。
|
||||
|
||||
### +datasource-create — 创建数据源表
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-create --base-id BASE_ID --datasource-type OA \
|
||||
--source-config '{"processCode":"PROC-xxxx","name":"采购申请","dataType":"recent_time","recentDays":"30d","iconUrl":"...","url":"..."}' \
|
||||
--format json
|
||||
|
||||
# 开启自动同步 + 自定义频率
|
||||
dws aitable +datasource-create --base-id BASE_ID --datasource-type OA \
|
||||
--source-config '...' --auto \
|
||||
--auto-sync-setting '{"syncType":"scheduled","scheduleType":"daily","timeValue":"09:00"}' \
|
||||
--format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--datasource-type` | 是 | 数据源类型,当前仅支持 `OA` |
|
||||
| `--source-config` | 是 | 源配置 JSON 字符串(见上方字段协议) |
|
||||
| `--auto` | 否 | 是否开启自动同步,默认 false;无论是否传入,CLI 都会把该字段下发给下游 |
|
||||
| `--auto-sync-setting` | 否 | 自动同步频率配置 JSON 字符串,仅 --auto=true 时生效 |
|
||||
| `--field-ids` | 否 | 需要同步的字段 ID 列表,不传时同步全部字段 |
|
||||
|
||||
返回新建数据源表 tableId 和同步任务 taskId。创建后自动触发一次全量同步,需用 `+datasource-sync-status` 查最终结果。
|
||||
|
||||
### +datasource-update — 更新数据源配置
|
||||
|
||||
```bash
|
||||
# 仅开启自动同步
|
||||
dws aitable +datasource-update --base-id BASE_ID --table-id TABLE_ID --auto --format json
|
||||
|
||||
# 更新源配置
|
||||
dws aitable +datasource-update --base-id BASE_ID --table-id TABLE_ID \
|
||||
--source-config '{"processCode":"PROC-yyyy","name":"出差申请","dataType":"recent_time","recentDays":"30d","iconUrl":"...","url":"..."}' \
|
||||
--format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--table-id` | 是 | 已有数据源表 ID(sync=true) |
|
||||
| `--source-config` | 否 | 新的源配置 JSON 字符串,不传时保持原配置;传入时整体覆盖 |
|
||||
| `--auto` | 否 | 是否开启自动同步,不传时保持原设置 |
|
||||
| `--auto-sync-setting` | 否 | 自动同步频率配置 JSON 字符串,仅 --auto=true 时生效;不传时保持原频率配置 |
|
||||
| `--field-ids` | 否 | 需要同步的字段 ID 列表,不传时保持现有字段配置 |
|
||||
|
||||
更新后自动触发一次全量同步,返回新 taskId。
|
||||
|
||||
### +datasource-sync — 手动触发同步
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-sync --base-id BASE_ID --table-ids TBL1,TBL2 --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--table-ids` | 是 | 待同步的数据源表 ID 列表(sync=true),1-5 个 |
|
||||
|
||||
返回结果包含文档链接,可打开查看同步进度。每张表独立提交,部分失败不影响其他表。
|
||||
|
||||
### +datasource-sync-status — 按任务 ID 查询同步状态
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-sync-status --base-id BASE_ID --table-id TABLE_ID --task-ids TASK1,TASK2 --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--table-id` | 是 | 数据源表 ID(sync=true) |
|
||||
| `--task-ids` | 是 | 同步任务 ID 列表(由 create/update/sync 返回),1-5 个 |
|
||||
|
||||
任务状态:`RUNNING`(进行中)、`FINISHED`(完成)、`FAILED`(失败,含 errorCode + errorMessage)。
|
||||
|
||||
### +datasource-get-config — 获取数据源配置
|
||||
|
||||
```bash
|
||||
dws aitable +datasource-get-config --base-id BASE_ID --table-id TABLE_ID --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 目标 Base ID |
|
||||
| `--table-id` | 是 | 数据源表 ID(sync=true) |
|
||||
|
||||
返回当前同步配置详情(sourceConfig、是否自动同步、同步状态等)。仅适用于数据源表,普通表会报错。
|
||||
|
||||
## 错误码与排查
|
||||
|
||||
| 场景 | 表现 | 排查 |
|
||||
|------|------|------|
|
||||
| 同步运行中重复触发 | errorCode=4014,status=FAILED | 幂等冲突,稍后重试即可 |
|
||||
| 非数据源表触发 sync | 参数错误返回 | 确认 table 的 sync=true,用 `+base-get` / `+table-list` 检查 |
|
||||
| sourceConfig 缺必填字段 | 创建/更新失败 | 检查 processCode/name/iconUrl/url 是否从 list-sources 原样透传 |
|
||||
| dataType 与时间字段不匹配 | 创建失败 | recent_time 需 recentDays;time_range 需 startDate+endDate;start_time 需 startDate |
|
||||
|
||||
## 能力边界
|
||||
|
||||
| 能力 | 状态 |
|
||||
|------|------|
|
||||
| OA 审批数据源 | 已支持 |
|
||||
| 其他数据源类型 | 待后续开放 |
|
||||
| 全量同步 | 已支持 |
|
||||
| 增量同步 | 待后续开放 |
|
||||
| 自动同步 | 已支持(--auto + autoSyncSetting) |
|
||||
| 删除数据源表 | 走普通表删除,不走 datasource 命令 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- sourceConfig 是 **JSON 字符串**(不是 JSON 对象),CLI flag 传入时需要用单引号包裹
|
||||
- list-sources 返回的 keepRemovedFields / splitParentTableField / enableDataSyncOaDetailList 不要透传,由调用方按需设置
|
||||
- create/update 后自动触发一次同步,返回 taskId;用 sync-status 查最终结果
|
||||
- sync 单次最多 5 张表,超出拆分多次调用
|
||||
- sync-status 单次最多 5 个 taskId,超出拆分多次调用
|
||||
- get-config 仅适用于数据源表(sync=true),普通表会报错
|
||||
@@ -0,0 +1,128 @@
|
||||
# AI 表格错误恢复指南
|
||||
|
||||
> 当 CLI 命令返回错误时,按本文档的映射表判断恢复动作。
|
||||
|
||||
## 1. 错误响应结构
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"summary": "Failed to create records",
|
||||
"trace_id": "2104a64c17790723347215232e085e"
|
||||
}
|
||||
```
|
||||
|
||||
- `status: "error"` 表示操作失败
|
||||
- `summary` 包含错误摘要信息
|
||||
- `trace_id` 用于问题追踪
|
||||
|
||||
## 2. 常见错误与恢复动作
|
||||
|
||||
### 2.1 记录操作错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| `Failed to create records` | cellValue 格式错误或字段类型不匹配 | 先 `field get` 确认字段类型,再按 [cell-value](./aitable-cell-value.md) 规范重构值 |
|
||||
| `record not found` | record-id 不存在或已删除 | 用 `record query` 重新查询确认目标记录 |
|
||||
| rating 字段写入超出 max | 值超出字段配置范围 | 检查字段 config 的 min/max,确保值在范围内 |
|
||||
| singleSelect 写入对象格式但 id 不存在 | option id 无效 | 改用 name 字符串写入(推荐),或先 `field get` 获取有效 option id |
|
||||
|
||||
### 2.2 字段操作错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| `Failed to create field` | config 格式错误或必填项缺失 | 检查 [field-properties](./aitable-field-properties.md) 中该类型的必填 config |
|
||||
| `field not found` | field-id 不存在 | 用 `field get` 获取最新字段列表 |
|
||||
| formula 创建失败 | 公式语法错误或引用字段名不匹配 | 先 `field get` 确认字段精确名称,再检查公式语法(见 [formula-guide](./aitable-formula-guide.md)) |
|
||||
| 删除主字段失败 | 主字段(第一列)不可删除 | 改为更新字段名或类型,不能删除 |
|
||||
|
||||
### 2.3 Base/Table 操作错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| `base not found` | base-id 错误或无权限 | 确认 base-id 正确;尝试 `base list` 或 `base search` 重新定位 |
|
||||
| `table not found` | table-id 错误 | 用 `table get --base-id <baseId>` 不带 table-ids 查看所有表 |
|
||||
| 表名重复 | 同 Base 下已存在同名表 | 系统会自动续号(如"原名 1"),无需额外处理 |
|
||||
|
||||
### 2.4 视图操作错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| `view not found` | view-id 错误 | 用 `view get --base-id <baseId> --table-id <tableId>` 查看所有视图 |
|
||||
| 删除最后一个视图 | 表至少保留一个视图 | 不可删除唯一视图 |
|
||||
|
||||
### 2.5 filters/sort 错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| filters 无效被忽略 | 根节点不是 and/or,或 operands 格式错误 | 确保 filters 根节点是 `{"operator":"and"/"or", "operands":[...]}` 结构 |
|
||||
| sort 无效 | fieldId 不存在 | 先 `field get` 确认字段 ID |
|
||||
| 筛选结果为空 | 条件过严或字段值不匹配 | 放宽条件验证;注意 singleSelect 筛选值用 option name 或 id |
|
||||
|
||||
### 2.6 导入导出错误
|
||||
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| 导出任务超时 | 数据量大,异步任务未完成 | 用 `export data --task-id <taskId>` 轮询直到完成 |
|
||||
| 导入文件格式错误 | 不支持的文件格式或文件损坏 | 确认文件为 .xlsx 格式且未加密 |
|
||||
|
||||
## 3. 重试策略
|
||||
|
||||
### 3.1 可重试的错误
|
||||
|
||||
| 错误类型 | 重试方式 | 最大重试次数 |
|
||||
|---------|---------|------------|
|
||||
| 网络超时 / 5xx | 等待 2s 后原样重试 | 2 |
|
||||
| 导出任务未完成 | 轮询 task-id | 5(间隔 3s) |
|
||||
| 并发写入冲突 | 串行重试 | 1 |
|
||||
|
||||
### 3.2 不可重试的错误(立即停止)
|
||||
|
||||
| 错误类型 | 原因 | 处理方式 |
|
||||
|---------|------|---------|
|
||||
| 权限不足 / 403 | 用户对该 Base 无权限 | 停止操作,提示用户确认权限 |
|
||||
| 参数格式错误 | 请求结构不合法 | 修正参数后重试,不要原样重试 |
|
||||
| 资源不存在 / 404 | ID 错误或资源已删除 | 重新查询定位资源 |
|
||||
| 配额超限 / 429 | API 调用频率过高 | 等待后重试,并降低并发 |
|
||||
|
||||
### 3.3 重试前检查清单
|
||||
|
||||
在重试前,先确认:
|
||||
1. ❓ 错误是暂时性的还是永久性的?
|
||||
2. ❓ 参数有没有明显错误需要修正?
|
||||
3. ❓ 是否需要先查询最新状态再重试?
|
||||
|
||||
## 4. 调试技巧
|
||||
|
||||
### 4.1 使用 --verbose 获取详细信息
|
||||
|
||||
```bash
|
||||
dws aitable record create \
|
||||
--base-id <baseId> \
|
||||
--table-id <tableId> \
|
||||
--records '[...]' \
|
||||
--verbose --format json
|
||||
```
|
||||
|
||||
`--verbose` 会输出请求/响应的详细信息,帮助定位问题。
|
||||
|
||||
### 4.2 使用 --dry-run 预览
|
||||
|
||||
```bash
|
||||
dws aitable record create \
|
||||
--base-id <baseId> \
|
||||
--table-id <tableId> \
|
||||
--records '[...]' \
|
||||
--dry-run --format json
|
||||
```
|
||||
|
||||
`--dry-run` 只预览不执行,适合在不确定参数是否正确时先验证。
|
||||
|
||||
## 5. 错误预防最佳实践
|
||||
|
||||
1. **写记录前先读字段结构** — `field get` 确认字段类型和 ID
|
||||
2. **写字段前先读 field-properties** — 确认 config 的必填项和格式
|
||||
3. **formula 字段先确认引用字段名** — `[字段名]` 必须精确匹配
|
||||
4. **options 更新传完整列表** — 更新 singleSelect/multipleSelect 的 options 是全量覆盖
|
||||
5. **大批量操作分批执行** — 单次最多 100 条记录
|
||||
6. **使用 --format json** — 确保输出可解析,方便错误判断
|
||||
@@ -0,0 +1,113 @@
|
||||
# export & import — 导入导出
|
||||
|
||||
## 导出数据(两阶段轮询)
|
||||
|
||||
`export data` 为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。
|
||||
|
||||
> ⚠️ **`--format` 冲突警告**:`export data` 的 `--format` 是**导出格式**(excel/attachment 等),不是全局输出格式。**此命令禁止追加全局 `--format json`**,否则会覆盖导出格式导致 `INVALID_EXPORT_FORMAT` 错误。输出默认就是 JSON,无需额外指定。
|
||||
|
||||
```bash
|
||||
# 第一步:创建任务(按 scope 传必要参数)——注意:不要加 --format json!
|
||||
dws aitable export data --base-id <BASE_ID> --scope table --table-id <TABLE_ID> --format excel --timeout-ms 1000
|
||||
|
||||
# 第二步:拿 taskId 继续轮询,直到返回 downloadUrl
|
||||
dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 3000
|
||||
```
|
||||
|
||||
### 参数约束
|
||||
|
||||
| scope | 必传参数 |
|
||||
|-------|----------|
|
||||
| `all` | 只需 `--base-id` |
|
||||
| `table` | 必须 `--table-id` |
|
||||
| `view` | 必须 `--table-id` + `--view-id` |
|
||||
|
||||
## 导入文件(三步流程)
|
||||
|
||||
当用户要求将 Excel(`.xlsx`)或 CSV 文件完整导入 AI 表格时,**不需要自己解析文件内容**,直接使用文件级导入。
|
||||
|
||||
> **无需手动解析 CSV/Excel 再逐条 record create**,效率极低且容易出错。
|
||||
|
||||
```bash
|
||||
# 第 1 步:申请上传凭证
|
||||
dws aitable import upload --base-id <BASE_ID> \
|
||||
--file-name data.xlsx --file-size <字节数> --format json
|
||||
# → 返回 uploadUrl 和 importId
|
||||
|
||||
# 第 2 步:上传文件到 OSS(注意:Content-Type 必须设为空)
|
||||
curl -X PUT "<uploadUrl>" -H "Content-Type:" --data-binary @data.xlsx
|
||||
|
||||
# 第 3 步:触发导入(新建表模式)
|
||||
dws aitable import data --import-id <importId> --format json
|
||||
# → 返回 status: success 和新建的 tableIds
|
||||
|
||||
# 第 3 步(替代):追加到已有表
|
||||
dws aitable import data --import-id <importId> --table-id <TABLE_ID> --format json
|
||||
# → 数据作为新行追加到指定表中
|
||||
```
|
||||
|
||||
### 步骤说明
|
||||
|
||||
| 步骤 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| 申请上传凭证 | `import upload --base-id <ID> --file-name <名称> --file-size <字节>` | `--file-size` 必须与实际文件大小一致 |
|
||||
| 上传文件 | HTTP PUT(curl 等) | **必须** 带 `-H "Content-Type:"` 将 Content-Type 设为空,否则 OSS 返回 403 |
|
||||
| 触发导入 | `import data --import-id <ID> [--table-id <TABLE_ID>]` | 同步等待,大多一次调用即返回结果;超时可用相同 importId 重试 |
|
||||
|
||||
### import data 参数
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--import-id` | ✅ | `import upload` 返回的 importId |
|
||||
| `--table-id` | ❌ | 传入时数据追加到该已有表;不传则每个 Sheet 新建独立的数据表 |
|
||||
| `--timeout` | ❌ | 最长等待秒数,默认且推荐 30 |
|
||||
| `--header-row` | ❌ | 表头所在行号(从 1 开始),数据从下一行读取。不传则自动识别 |
|
||||
| `--src-sheet-name` | ❌ | 源文件中的 Sheet 名称,多 Sheet 文件时指定。不传则用第一个 Sheet |
|
||||
| `--field-mapping` | ❌ | 字段映射 JSON(`{"目标字段名":"源列名"}`)。不传则按列名自动匹配 |
|
||||
|
||||
### 两种导入模式
|
||||
|
||||
| 模式 | 触发条件 | 效果 |
|
||||
|------|----------|------|
|
||||
| **新建表导入** | 不传 `--table-id` | 每个 Sheet 自动新建为独立数据表 |
|
||||
| **追加导入** | 传入 `--table-id` | 数据作为新行追加到指定已有表,按列名自动匹配字段 |
|
||||
|
||||
### 支持的文件格式:xlsx vs csv
|
||||
|
||||
| 特性 | xlsx | csv |
|
||||
|------|------|-----|
|
||||
| 新建表导入 | ✅ | ✅ |
|
||||
| 追加导入(`--table-id`) | ✅ | ✅ |
|
||||
| `--header-row` | ✅ | ❌ 不支持 |
|
||||
| `--src-sheet-name` | ✅(多 Sheet 支持) | ❌ 无 Sheet 概念 |
|
||||
| `--field-mapping` | ✅ | ✅ |
|
||||
|
||||
> **CSV 限制**:CSV 没有 Sheet 概念,且表头固定为第一行,因此 `--header-row` 和 `--src-sheet-name` 对 CSV 均不可用。
|
||||
>
|
||||
> **建议**:需要指定表头行或多 Sheet 选择时,**必须使用 xlsx 格式**。CSV 仅适用于表头在第一行的简单导入场景。
|
||||
|
||||
### 追加导入的字段匹配规则
|
||||
|
||||
追加导入时,系统按以下规则将 Excel 列映射到目标表字段:
|
||||
|
||||
1. **不传 `--field-mapping`(自动匹配)**:按字段名**精确匹配** Excel 列名和目标表字段名。如果没有任何一列匹配上,导入会失败。
|
||||
2. **传 `--field-mapping`(显式映射)**:按映射关系指定对应关系,key 为目标表字段名,value 为 Excel 列名。
|
||||
|
||||
> **追加导入失败常见原因**:Excel 列名与目标表字段名不一致(如 Excel 是"销售姓名"但表字段是"姓名"),导致自动匹配 0 个字段,报错 `"Failed to build import sheet infos from preview data"`。
|
||||
>
|
||||
> **解决方案**:
|
||||
> 1. **首选**:创建目标表时,字段名与 Excel 表头列名**保持完全一致**
|
||||
> 2. **备选**:传 `--field-mapping '{"目标字段名":"Excel列名"}'` 手动指定映射
|
||||
> 3. **兜底**:如果 import data 多次失败,改用 `record create` 逐条写入
|
||||
|
||||
### 适用场景
|
||||
|
||||
- **新建表导入**:首次导入 Excel/CSV,让系统自动建表建字段
|
||||
- **追加到已有表**:已有数据表结构,需要把 Excel 数据批量写入 → 传 `--table-id`(推荐 xlsx)
|
||||
- **需要指定表头行**:源文件前几行非数据(如注释行)→ `--header-row`(必须用 xlsx)
|
||||
- **多 Sheet 文件**:只导入特定 Sheet → `--src-sheet-name`(必须用 xlsx)
|
||||
- **不适用**:需要复杂字段级控制(如只导入部分列、数据转换)→ 解析后用 `record create`
|
||||
|
||||
> **导入数据无法整体撤销**:文件一旦导入成功,数据即写入表中,没有"撤销导入"操作。如需清理导入的测试数据,只能手动通过 `record delete` 逐条或批量删除记录;如果是新建表模式导入的,可以直接 `table delete` 删除整张表。因此:
|
||||
> - 测试/验证场景建议导入到**独立的测试表或测试 Base**,用完后整体删除
|
||||
> - 如果用户明确表示不想导入测试数据或要求先预览内容再决定,应先解析文件内容展示给用户确认,而非直接导入
|
||||
@@ -0,0 +1,238 @@
|
||||
# 字段类型 config 规范(field create / table create / field update)
|
||||
|
||||
> 适用命令:`dws aitable field create`、`dws aitable table create --fields`、`dws aitable field update --config`
|
||||
>
|
||||
> 本文件是 DWS AI 表格字段 config 的 **source of truth**。创建/更新字段时,必须严格按此规范构造 JSON。
|
||||
|
||||
## 1. 顶层规则
|
||||
|
||||
- `table create --fields` 和 `field create --fields` 中每个字段对象:`{"fieldName":"xxx", "type":"xxx", "config":{...}}`
|
||||
- `field create --name --type --config` 中 config 单独传 JSON 字符串
|
||||
- `field update --config` 只传 config 部分
|
||||
- 不需要 config 的类型(如 text、checkbox、attachment)可省略 config 字段
|
||||
|
||||
## 2. 字段类型速查
|
||||
|
||||
| type | 需要 config | config 核心字段 | 说明 |
|
||||
|------|-------------|----------------|------|
|
||||
| `text` | ❌ | — | 纯文本 |
|
||||
| `number` | 可选 | `formatter` | 数字格式 |
|
||||
| `singleSelect` | ✅ | `options` | 单选 |
|
||||
| `multipleSelect` | ✅ | `options` | 多选 |
|
||||
| `date` | 可选 | `formatter` | 日期格式 |
|
||||
| `currency` | 可选 | `currencyType`, `formatter` | 货币 |
|
||||
| `progress` | 可选 | `formatter`, `min`, `max`, `customizeRange` | 进度条 |
|
||||
| `rating` | 可选 | `min`, `max`, `icon` | 评分 |
|
||||
| `checkbox` | ❌ | — | 勾选框 |
|
||||
| `user` | 可选 | `multiple` | 人员 |
|
||||
| `department` | 可选 | `multiple` | 部门 |
|
||||
| `group` | 可选 | `multiple` | 群组 |
|
||||
| `url` | ❌ | — | 链接 |
|
||||
| `richText` | ❌ | — | 富文本 |
|
||||
| `telephone` | ❌ | — | 电话 |
|
||||
| `email` | ❌ | — | 邮箱 |
|
||||
| `attachment` | ❌ | — | 附件 |
|
||||
| `geolocation` | ❌ | — | 地理位置 |
|
||||
| `formula` | ✅ | `formula` | 公式(只读字段) |
|
||||
| `unidirectionalLink` | ✅ | `linkedTableId`, `multiple` | 单向关联 |
|
||||
| `bidirectionalLink` | ✅ | `linkedTableId`, `multiple` | 双向关联 |
|
||||
| `creator` | ❌ | — | 系统字段:创建人(只读) |
|
||||
| `lastModifier` | ❌ | — | 系统字段:最后编辑人(只读) |
|
||||
| `createdTime` | ❌ | — | 系统字段:创建时间(只读) |
|
||||
| `lastModifiedTime` | ❌ | — | 系统字段:最后编辑时间(只读) |
|
||||
|
||||
## 3. 各类型 config 详解
|
||||
|
||||
### 3.1 number(数字)
|
||||
|
||||
config 字段:`formatter`
|
||||
|
||||
可选值:
|
||||
- `INT` — 整数
|
||||
- `FLOAT_1` — 1 位小数
|
||||
- `FLOAT_2` — 2 位小数(默认)
|
||||
- `FLOAT_3` — 3 位小数
|
||||
- `FLOAT_4` — 4 位小数
|
||||
- `THOUSAND` — 千分位整数
|
||||
- `THOUSAND_FLOAT` — 千分位 + 小数
|
||||
- `PERCENT` — 百分比(整数)
|
||||
- `PERCENT_FLOAT` — 百分比(小数)
|
||||
|
||||
```json
|
||||
{"fieldName": "工时", "type": "number", "config": {"formatter": "FLOAT_2"}}
|
||||
```
|
||||
|
||||
```json
|
||||
{"fieldName": "完成率", "type": "number", "config": {"formatter": "PERCENT"}}
|
||||
```
|
||||
|
||||
### 3.2 singleSelect / multipleSelect(单选 / 多选)
|
||||
|
||||
config 字段:`options`(必填)
|
||||
|
||||
options 结构:
|
||||
- `options` 是数组,每项至少包含 `name`
|
||||
- 创建时只传 `name`,`id` 由系统生成
|
||||
- **更新时**:已有选项必须回传原 `id`(从 `field get` 获取),新增选项不传 id
|
||||
|
||||
```json
|
||||
{
|
||||
"fieldName": "优先级",
|
||||
"type": "singleSelect",
|
||||
"config": {
|
||||
"options": [
|
||||
{"name": "紧急"},
|
||||
{"name": "高"},
|
||||
{"name": "中"},
|
||||
{"name": "低"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更新已有字段时(保留原选项 + 新增):
|
||||
```json
|
||||
{
|
||||
"options": [
|
||||
{"id": "opt_existing_1", "name": "紧急"},
|
||||
{"id": "opt_existing_2", "name": "高"},
|
||||
{"id": "opt_existing_3", "name": "中"},
|
||||
{"name": "极低"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> 更新 options 是**全量覆盖**,不是追加!不传的旧选项会被删除,关联的单元格数据丢失。
|
||||
|
||||
### 3.3 date(日期)
|
||||
|
||||
config 字段:`formatter`
|
||||
|
||||
可选值:
|
||||
- `YYYY-MM-DD`(默认)
|
||||
- `YYYY-MM-DD HH:mm`
|
||||
- `YYYY-MM-DD HH:mm:ss`
|
||||
- `YYYY/MM/DD`
|
||||
- `YYYY/MM/DD HH:mm`
|
||||
|
||||
```json
|
||||
{"fieldName": "截止日期", "type": "date", "config": {"formatter": "YYYY-MM-DD"}}
|
||||
```
|
||||
|
||||
```json
|
||||
{"fieldName": "创建时间", "type": "date", "config": {"formatter": "YYYY-MM-DD HH:mm"}}
|
||||
```
|
||||
|
||||
### 3.4 currency(货币)
|
||||
|
||||
config 字段:`currencyType`(必填)、`formatter`(可选)
|
||||
|
||||
currencyType 可选值:
|
||||
`CNY` | `HKD` | `USD` | `EUR` | `GBP` | `MOP` | `VND` | `JPY` | `KRW` | `AED` | `AUD` | `BRL` | `CAD` | `CHF` | `INR` | `IDR` | `MXN` | `MYR` | `PHP` | `PLN` | `RUB` | `SGD` | `THB` | `TRY` | `TWD`
|
||||
|
||||
formatter 可选值(控制小数位):`INT` | `FLOAT_1` | `FLOAT_2`(默认)| `FLOAT_3` | `FLOAT_4`
|
||||
|
||||
```json
|
||||
{"fieldName": "预算", "type": "currency", "config": {"currencyType": "CNY", "formatter": "FLOAT_2"}}
|
||||
```
|
||||
|
||||
### 3.5 progress(进度)
|
||||
|
||||
config 字段:`formatter`(固定为 `PERCENT`)、`customizeRange`、`min`、`max`
|
||||
|
||||
- 默认范围:0~1(即 0%~100%)
|
||||
- 自定义范围时 `customizeRange` 必须为 `true`
|
||||
|
||||
```json
|
||||
{"fieldName": "完成度", "type": "progress", "config": {"formatter": "PERCENT"}}
|
||||
```
|
||||
|
||||
自定义范围:
|
||||
```json
|
||||
{"fieldName": "进度", "type": "progress", "config": {"formatter": "PERCENT", "customizeRange": true, "min": 0, "max": 1}}
|
||||
```
|
||||
|
||||
### 3.6 rating(评分)
|
||||
|
||||
config 字段:`min`、`max`、`icon`
|
||||
|
||||
- `min`:固定为 `1`
|
||||
- `max`:1~10,默认 `5`
|
||||
- `icon`:默认 `star`
|
||||
|
||||
```json
|
||||
{"fieldName": "满意度", "type": "rating", "config": {"min": 1, "max": 5, "icon": "star"}}
|
||||
```
|
||||
|
||||
### 3.7 user / department / group(人员 / 部门 / 群组)
|
||||
|
||||
config 字段:`multiple`
|
||||
|
||||
- `multiple`:`true`(多选,默认)| `false`(单选)
|
||||
|
||||
```json
|
||||
{"fieldName": "负责人", "type": "user", "config": {"multiple": false}}
|
||||
```
|
||||
|
||||
```json
|
||||
{"fieldName": "协作部门", "type": "department", "config": {"multiple": true}}
|
||||
```
|
||||
|
||||
### 3.8 formula(公式)
|
||||
|
||||
config 字段:`formula`(必填)
|
||||
|
||||
- 公式中引用字段使用**方括号 + 字段名**:`[字段名]`
|
||||
- 支持的函数:参考钉钉 AI 表格公式文档
|
||||
|
||||
```json
|
||||
{"fieldName": "合计", "type": "formula", "config": {"formula": "[单价] * [数量]"}}
|
||||
```
|
||||
|
||||
```json
|
||||
{"fieldName": "是否逾期", "type": "formula", "config": {"formula": "IF([截止日期] < NOW(), \"是\", \"否\")"}}
|
||||
```
|
||||
|
||||
> ⚠️ formula 字段创建后为**只读**,不能通过 record create/update 写入值。
|
||||
|
||||
### 3.9 unidirectionalLink(单向关联)
|
||||
|
||||
config 字段:`linkedTableId`(必填)、`multiple`
|
||||
|
||||
- `linkedTableId`:目标表的 tableId
|
||||
- `multiple`:`true`(多选,默认)| `false`(单选)
|
||||
|
||||
```json
|
||||
{"fieldName": "关联项目", "type": "unidirectionalLink", "config": {"linkedTableId": "tblXXXXXX", "multiple": true}}
|
||||
```
|
||||
|
||||
### 3.10 bidirectionalLink(双向关联)
|
||||
|
||||
config 字段:`linkedTableId`(必填)、`multiple`
|
||||
|
||||
- 与单向关联参数相同
|
||||
- 创建后系统会**自动**在被关联表创建反向字段
|
||||
|
||||
```json
|
||||
{"fieldName": "关联任务", "type": "bidirectionalLink", "config": {"linkedTableId": "tblYYYYYY", "multiple": true}}
|
||||
```
|
||||
|
||||
## 4. AI 字段(ai-config)
|
||||
|
||||
AI 字段不使用 config,而使用独立的 `--ai-config` 参数。详见 [aitable-field.md](./aitable-field.md) 中的 AI 字段创建示例。
|
||||
|
||||
核心规则:
|
||||
- `outputType` 必须与 `--type` 对应:text→text, select→singleSelect, multiSelect→multipleSelect, number→number, currency→currency, image/video→attachment
|
||||
- `prompt` 中必须至少包含一个 `fieldRef` 引用
|
||||
- 纯文本 prompt 会被后端拒绝
|
||||
|
||||
## 5. 常见错误
|
||||
|
||||
| 错误 | 说明 |
|
||||
|------|------|
|
||||
| options 更新时不传已有选项的 id | 会被视为新选项,旧选项被删除,关联数据丢失 |
|
||||
| options 更新时只传新增项 | 全量覆盖,旧选项全部丢失 |
|
||||
| formula 字段尝试写入值 | 只读字段,record create/update 会报错 |
|
||||
| linkedTableId 传表名而非 ID | 必须传 tableId(如 `tblXXX`),不接受表名 |
|
||||
| progress 值写入 50 表示 50% | 实际应写入 0.5(range 0~1) |
|
||||
| rating 值超出 max | 写入会报错 |
|
||||
@@ -0,0 +1,174 @@
|
||||
# field — 字段管理
|
||||
|
||||
## field get — 获取字段详情
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable field get [flags]
|
||||
Example:
|
||||
dws aitable field get --base-id <BASE_ID> --table-id <TABLE_ID>
|
||||
dws aitable field get --base-id <BASE_ID> --table-id <TABLE_ID> --field-ids fld1,fld2
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--field-ids string 字段 ID 列表,逗号分隔,单次最多 10 个
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
返回字段的完整配置(含 options 等)。不要假设未指定 `--table-ids` 的 `table get` 枚举结果含字段;字段目录和配置以 `field get` 返回为准。
|
||||
|
||||
## field create — 创建字段
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable field create [flags]
|
||||
Example:
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "状态" --type "singleSelect" --config '{"options":[{"name":"待办"},{"name":"进行中"},{"name":"已完成"}]}'
|
||||
|
||||
# 或者使用批量创建模式:
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--fields '[{"fieldName":"状态","type":"singleSelect","config":{"options":[{"name":"待办"}]}}]'
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--name string 要创建的单字段名称(与 --type 配合使用,替代 --fields)
|
||||
--type string 要创建的单字段类型(需要配合 --name,参考 table create 的内置类型)
|
||||
--config string 单字段配置 JSON(需要配合 --name/--type,结构参考 table create)
|
||||
--ai-config string 单字段 AI 配置 JSON(需要配合 --name/--type)
|
||||
--fields string 批量新增字段 JSON 数组,单次最多 15 个;每个字段的配置写在其 config/aiConfig 内
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
`field create` 有且只有两种输入模式:
|
||||
|
||||
- 单字段模式:必须同时传 `--name` 和 `--type`;`--config`、`--ai-config` 只作为该字段的附加配置。
|
||||
- 批量模式:只传 `--fields`;字段配置写在数组内各对象的 `config` / `aiConfig` 中。
|
||||
|
||||
两种模式严格互斥。`--fields` 不能与 `--name`、`--type`、`--config` 或 `--ai-config` 混用;单独传 `--config` 也会报错,不会被静默忽略。
|
||||
|
||||
例如创建单选字段时,单字段模式的 `--config` 是一个配置对象;批量模式则把同一对象放入对应字段元素的 `config`:
|
||||
|
||||
```bash
|
||||
# 单字段模式
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "部门" --type singleSelect \
|
||||
--config '{"options":[{"name":"技术部"},{"name":"产品部"}]}'
|
||||
|
||||
# 批量模式
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--fields '[{"fieldName":"部门","type":"singleSelect","config":{"options":[{"name":"技术部"},{"name":"产品部"}]}}]'
|
||||
```
|
||||
|
||||
允许部分成功,返回结果逐项标明成功/失败状态。
|
||||
|
||||
### AI 字段创建示例
|
||||
|
||||
```bash
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "AI摘要" --type text \
|
||||
--ai-config '{
|
||||
"outputType":"text",
|
||||
"prompt":[
|
||||
{"type":"text","value":"请将下面内容总结成不超过80字的中文摘要:"},
|
||||
{"type":"fieldRef","fieldId":"fld_content"}
|
||||
],
|
||||
"autoRecompute":true,
|
||||
"enableWebSearch":false,
|
||||
"enableThinking":true
|
||||
}' --format json
|
||||
```
|
||||
|
||||
说明:
|
||||
- `outputType` 与字段类型需一致(如 `outputType=text` 配 `--type text`)
|
||||
- `prompt` 里通过 `fieldRef` 引用已有字段
|
||||
- `autoRecompute=true` 表示引用字段变化后自动重算
|
||||
- **AI 字段的 prompt 必须至少包含一个 `fieldRef` 引用**,纯文本 prompt 会被后端拒绝
|
||||
|
||||
### 关联字段与跨表引用字段
|
||||
|
||||
创建 `lookup`(关联引用)和 `filterUp`(查找引用)字段时,config 格式有严格要求:
|
||||
|
||||
#### bidirectionalLink / unidirectionalLink(关联字段)
|
||||
|
||||
```bash
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "关联客户" --type bidirectionalLink \
|
||||
--config '{"linkedTableId":"<目标表tableId>","multiple":true}' --format json
|
||||
```
|
||||
|
||||
#### lookup(关联引用,通过已有关联字段取值)
|
||||
|
||||
**前置条件**:本表必须已有一个 bidirectionalLink 或 unidirectionalLink 类型的关联字段。
|
||||
|
||||
```bash
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "客户城市" --type lookup \
|
||||
--config '{"associateField":"<本表关联字段的fieldId>","valuesField":"<关联目标表中要取值的字段fieldId>","aggregator":"CONCATENATE"}' --format json
|
||||
```
|
||||
|
||||
config 必填字段:
|
||||
- `associateField`:**本表中**已有的关联字段(bidirectionalLink/unidirectionalLink)的 fieldId
|
||||
- `valuesField`:**关联目标表中**要取值的字段 fieldId
|
||||
- `aggregator`:聚合方式,可选 `SUM`|`AVERAGE`|`COUNT`|`MAX`|`MIN`|`CONCATENATE`
|
||||
|
||||
> 常见错误:`associateField` 不是目标表的 tableId,也不是目标表的字段 ID,而是**本表中关联字段自身的 fieldId**。
|
||||
|
||||
#### filterUp(查找引用,无需关联字段,直接跨表取值)
|
||||
|
||||
```bash
|
||||
# 基本用法:字段对常量匹配
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "客户总金额" --type filterUp \
|
||||
--config '{"targetSheet":"<目标表tableId>","filters":[{"fieldId":"<目标表字段Id>","operator":"equal","value":"匹配值","link":"AND"}],"valuesField":"<目标表中要取值的字段Id>","aggregator":"SUM"}' --format json
|
||||
|
||||
# 进阶用法:字段对字段动态匹配(currentSheetFieldId)
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "本城市订单金额" --type filterUp \
|
||||
--config '{"targetSheet":"<目标表tableId>","filters":[{"fieldId":"<目标表字段Id>","operator":"equal","currentSheetFieldId":"<本表字段Id>","link":"AND"}],"valuesField":"<目标表中要取值的字段Id>","aggregator":"SUM"}' --format json
|
||||
```
|
||||
|
||||
config 必填字段:
|
||||
- `targetSheet`:目标表的 tableId
|
||||
- `filters`:至少一条筛选规则
|
||||
- `fieldId`:目标表中用于匹配的字段 fieldId
|
||||
- `operator`:仅支持 `equal`、`contain`(不支持 not_equal/not_contain)
|
||||
- `value`:常量匹配值(与 `currentSheetFieldId` 二选一)
|
||||
- `currentSheetFieldId`:本表中用于动态匹配的字段 fieldId(与 `value` 二选一,实现每行按本表字段值去目标表筛选)
|
||||
- `link`:多条件时的逻辑关系,`AND` 或 `OR`(单条件时可省略,多条件时建议显式指定;所有 filter 的 link 必须统一)
|
||||
- `valuesField`:目标表中要取值的字段 fieldId
|
||||
- `aggregator`:聚合方式,可选 `SUM`|`AVERAGE`|`COUNT`|`MAX`|`MIN`|`CONCATENATE`
|
||||
|
||||
## field update — 更新字段
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable field update [flags]
|
||||
Example:
|
||||
dws aitable field update --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --name "新字段名"
|
||||
dws aitable field update --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --config '{"options":[{"name":"A"},{"name":"B"}]}'
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--config string 字段配置 JSON (不修改时省略)
|
||||
--ai-config string AI 配置 JSON (不修改时省略)
|
||||
--field-id string Field ID (必填)
|
||||
--name string 新字段名称 (不修改时省略)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
- 不可变更字段类型
|
||||
- 更新 singleSelect/multipleSelect 的 options 时需传入完整列表,已有选项应回传原 id
|
||||
- `--name` / `--config` / `--ai-config` 至少传一个
|
||||
|
||||
## field delete — 删除字段
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable field delete [flags]
|
||||
Example:
|
||||
dws aitable field delete --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --yes
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--field-id string 待删除字段 ID (必填)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
不可逆。禁止删除主字段和最后一个字段。
|
||||
@@ -0,0 +1,169 @@
|
||||
# filters & sort — 筛选排序语法参考
|
||||
|
||||
> 视图(view)配置的 filter/sort/group **整体写入**请优先用 `view update filter` / `view update sort` / `view update group` 子命令,详见 [aitable-view-config.md](./aitable-view-config.md)。本文件聚焦于 `record query --filters` 与 view config filter 的语法和差异。
|
||||
|
||||
## filters 结构规范
|
||||
|
||||
### 强制规则
|
||||
|
||||
1. **根节点必须是逻辑操作符**:`"operator"` 必须是 `"and"` 或 `"or"`,不能是 `"eq"` 等比较操作符
|
||||
2. 比较操作必须放在根节点的 `"operands"` 数组内的对象中
|
||||
3. `singleSelect` 和 `multipleSelect` 字段,推荐使用 **选项的 exact String 名称 (name)** 作为比较值
|
||||
4. fieldId 必须通过 `field get` 获取,不能直接用字段名称
|
||||
|
||||
### 精简防呆模板
|
||||
|
||||
CLI 同时兼容两种子条件写法(推荐格式 A):
|
||||
|
||||
**格式 A(operands 数组,推荐):**
|
||||
```json
|
||||
{
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{"operator": "eq", "operands": ["fld_state", "进行中"]}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**格式 B(fieldId/value 对象,CLI 自动转换):**
|
||||
```json
|
||||
{
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{"fieldId": "fld_state", "operator": "eq", "value": "进行中"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
4 种衍生:
|
||||
- **OR 查询**:根节点 `"operator"` 改为 `"or"`
|
||||
- **多条件 AND**:在 `"operands"` 数组中增加对象
|
||||
- **文本包含**:内层 `"operator"` 改为 `"contain"`
|
||||
- **为空判断**:`"operator":"un_exist"`,operands 只需 `["fieldId"]`
|
||||
|
||||
### 支持的操作符(已验证完整列表)
|
||||
|
||||
| 操作符 | 含义 | operands 格式 |
|
||||
|--------|------|--------------|
|
||||
| `eq` / `ne` | 等于 / 不等于 | `["fieldId", "value"]` |
|
||||
| `contain` / `exclusive` | 包含 / 不包含(文本模糊) | `["fieldId", "value"]` |
|
||||
| `gt` / `gte` / `lt` / `lte` | 大于 / ≥ / 小于 / ≤ | `["fieldId", "numStr"]` |
|
||||
| `exist` / `un_exist` | 有值 / 为空 | `["fieldId"]`(无需第二项) |
|
||||
| `any_of` / `none_of` / `all_of` | 包含任一 / 不包含任一 / 全包含(多选字段) | `["fieldId", "optionName"]` |
|
||||
| `date_eq` / `before` / `after` | 日期等于 / 早于 / 晚于 | `["fieldId", "dateStr"]` |
|
||||
| `not_before` / `not_after` | 不早于(≥) / 不晚于(≤) | `["fieldId", "2026-05-22"]` |
|
||||
|
||||
> **操作符拼写必须严格匹配上表**,CLI 会在调用前校验,错误拼写会被拒绝。
|
||||
>
|
||||
> **没有 `date_between`(区间)操作符**,也**不支持 `from_now`**——date 字段不支持区间/相对过滤,传了会被 CLI 拒绝。范围查询用 `not_before` + `not_after` 组合,见下方专节。
|
||||
|
||||
### 日期字段过滤(date / 创建时间 / 修改时间)
|
||||
|
||||
日期类字段的过滤规则与其它字段**不同**,是线上反馈最高频的踩坑点。**经集成测试实测**确认的规则:
|
||||
|
||||
1. **只能用日期专用操作符**:`date_eq` / `before` / `after` / `not_before` / `not_after` / `exist` / `un_exist`(与前端筛选 UI 的「等于 / 早于 / 晚于 / 早于或等于 / 晚于或等于 / 不为空 / 为空」一一对应)。
|
||||
2. **比较值用日期字符串**,如 `"2026-05-22"`(也接受 RFC3339 / 毫秒时间戳,内部统一转成毫秒比较)。读取返回的是带时区 RFC3339(如 `"2026-05-22T00:00:00+08:00"`)。
|
||||
3. **通用操作符 `eq` / `ne` / `gt` / `gte` / `lt` / `lte` / `contain` 对 date 字段无效**——无论传 ISO 字符串还是毫秒时间戳,都会**静默返回 0 条**。这是后端 date 字段的比较规则,不是 bug,CLI 也无法在本地拦截(不知道字段类型),务必用对操作符。
|
||||
4. **没有区间操作符 `date_between`**,也**不支持 `from_now`(相对天数)**——均会静默返回 0 条,CLI 已直接拒绝。范围查询用 `not_before`(≥起点)+ `not_after`(≤终点)两个条件 `and` 组合。
|
||||
|
||||
| 需求 | 操作符 | 示例 operands |
|
||||
|------|--------|--------------|
|
||||
| 等于某天 | `date_eq` | `["fldDate", "2026-05-22"]` |
|
||||
| 早于 / 晚于(不含当天) | `before` / `after` | `["fldDate", "2026-05-22"]` |
|
||||
| 不早于(≥) / 不晚于(≤) | `not_before` / `not_after` | `["fldDate", "2026-05-22"]` |
|
||||
| 有值 / 为空 | `exist` / `un_exist` | `["fldDate"]` |
|
||||
|
||||
**日期区间查询(替代 between)**——查 `2026-05-01 ~ 2026-05-31`(含端点):
|
||||
|
||||
```bash
|
||||
dws aitable record query --base-id X --table-id Y \
|
||||
--filters '{"operator":"and","operands":[{"operator":"not_before","operands":["fldDate","2026-05-01"]},{"operator":"not_after","operands":["fldDate","2026-05-31"]}]}'
|
||||
```
|
||||
|
||||
### 常见错误拼写(CLI 会自动提示纠正)
|
||||
|
||||
| 错误写法 | 正确写法 | 说明 |
|
||||
|------------|-----------|------|
|
||||
| `equal` / `equals` / `is` / `==` | `eq` | 等于 |
|
||||
| `not_equal` / `not_equals` / `is_not` / `!=` | `ne` | 不等于 |
|
||||
| `like` / `contains` / `include` | `contain` | 文本包含 |
|
||||
| `greater_than` | `gt` | 大于 |
|
||||
| `less_than` | `lt` | 小于 |
|
||||
| `not_eq` / `not_contain` / `is_empty` | `ne` / `exclusive` / `un_exist` | 其他易混淆 |
|
||||
|
||||
### 错误示例
|
||||
|
||||
❌ **缺失根节点 and/or**(API 将忽略该 filter,返回全表):
|
||||
```json
|
||||
{"operator":"eq","operands":["fldXXX","本科"]}
|
||||
```
|
||||
|
||||
❌ **传入选项 ID 而非名称**(可能导致匹配不到 0 记录):
|
||||
```json
|
||||
{"operator":"and","operands":[{"operator":"eq","operands":["fldXXX","CXzrOHK9JI"]}]}
|
||||
```
|
||||
|
||||
### 完整示例
|
||||
|
||||
单条件:
|
||||
```bash
|
||||
dws aitable record query --base-id X --table-id Y \
|
||||
--filters '{"operator":"and","operands":[{"operator":"eq","operands":["fldStatusId","进行中"]}]}'
|
||||
```
|
||||
|
||||
多条件 AND:
|
||||
```bash
|
||||
dws aitable record query --base-id X --table-id Y \
|
||||
--filters '{"operator":"and","operands":[{"operator":"eq","operands":["fldStatusId","进行中"]},{"operator":"gt","operands":["fldStockId","0"]}]}'
|
||||
```
|
||||
|
||||
## sort 结构规范
|
||||
|
||||
`--sort` 传 JSON 数组,排序方向字段**必须是 `direction`**,不要使用 `order`。
|
||||
|
||||
```bash
|
||||
--sort '[{"fieldId":"fldXXX","direction":"desc"}]'
|
||||
```
|
||||
|
||||
多字段排序:
|
||||
```bash
|
||||
--sort '[{"fieldId":"fldPriority","direction":"desc"},{"fieldId":"fldCreatedAt","direction":"asc"}]'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## view update --config 中的 filter / sort 格式
|
||||
|
||||
> **重要区分**:`record query --filters` 和 `view update --config` 中的 filter **格式不同**!
|
||||
|
||||
| 场景 | filter 格式 | 说明 |
|
||||
|------|-------------|------|
|
||||
| `record query --filters` | **对象**:`{"operator":"and","operands":[...]}` | 直接传最外层逻辑对象 |
|
||||
| `view update --config` 的 filter | **数组**:`[{"operator":"and","operands":[...]}]` | 外面多一层数组包裹 |
|
||||
| `view update --config` 的 sort | **数组**:`[{"fieldId":"X","direction":"asc"}]` | 与 record query --sort 一致 |
|
||||
|
||||
### 正确示例
|
||||
|
||||
```bash
|
||||
# view update 设置筛选(filter 是数组)
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"filter":[{"operator":"and","operands":[{"operator":"eq","operands":["fldStatus","待处理"]}]}]}'
|
||||
|
||||
# view update 设置排序(sort 是数组)
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"sort":[{"fieldId":"fldPriority","direction":"desc"}]}'
|
||||
|
||||
# 同时设置 filter + sort + visibleFieldIds
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"filter":[{"operator":"and","operands":[{"operator":"eq","operands":["fldStatus","进行中"]}]}],"sort":[{"fieldId":"fldDate","direction":"asc"}],"visibleFieldIds":["fld1","fld2","fld3"]}'
|
||||
```
|
||||
|
||||
### CLI 自动容错
|
||||
|
||||
CLI 会自动修正以下常见错误格式(不会报错,但建议直接使用正确格式):
|
||||
|
||||
| 错误写法 | CLI 自动修正为 |
|
||||
|----------|---------------|
|
||||
| `"filter":{"operator":"and",...}` (对象) | `"filter":[{"operator":"and",...}]` (数组) |
|
||||
| `"sort":{"fieldId":"X","direction":"asc"}` (对象) | `"sort":[{"fieldId":"X","direction":"asc"}]` (数组) |
|
||||
| 子条件用 MCP 简写 `{"fieldId":"X","operator":"eq","value":"Y"}` | 自动转为 `{"operator":"eq","operands":["X","Y"]}` |
|
||||
@@ -0,0 +1,130 @@
|
||||
# form — 表单管理
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `form list` | 列出数据表下所有表单视图 |
|
||||
| `form get` | 按 viewId 取单个表单详情(list_form_views + viewIds 过滤) |
|
||||
| `form create` | 创建表单视图(等价于 `view create --view-type FormDesigner`) |
|
||||
| `form update` | 更新表单标题或描述 |
|
||||
| `form delete` | 删除表单视图(不可逆) |
|
||||
| `form field list` | 列出表单可见字段 |
|
||||
| `form field update` | 更新字段必填/描述 |
|
||||
| `form field hide` | 在表单中隐藏/显示字段(不影响底层数据表字段) |
|
||||
| `form share get` | 获取分享配置 |
|
||||
| `form share update` | 开启/关闭分享 |
|
||||
| `form questions create` | 添加题目(等价于 `field create`,命令位置上的别名) |
|
||||
| `form questions delete` | 删除题目(等价于 `field delete`,命令位置上的别名) |
|
||||
|
||||
## 建议操作顺序
|
||||
|
||||
```bash
|
||||
# 1) 列出数据表下的表单视图
|
||||
dws aitable form list --base-id BASE_ID --table-id TABLE_ID --format json
|
||||
|
||||
# 2) 查看单个表单详情
|
||||
dws aitable form get --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID --format json
|
||||
|
||||
# 3) 查看表单字段配置
|
||||
dws aitable form field list --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID --format json
|
||||
|
||||
# 4) 查看分享配置
|
||||
dws aitable form share get --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID --format json
|
||||
```
|
||||
|
||||
开启并取得可发送链接的最短闭环使用 canonical shortcut:
|
||||
|
||||
```bash
|
||||
dws aitable form create --base-id BASE_ID --table-id TABLE_ID --name "表单名" --format json
|
||||
dws aitable +form-share-update --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID --enabled true --format json
|
||||
dws aitable +form-share-get --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID --format json
|
||||
```
|
||||
|
||||
从最后一次返回直接读取 `data.shareFormUuid`,分享地址为 `https://alidocs.dingtalk.com/i/form/{shareFormUuid}`。字段已存在时不要再调用 Help、Catalog、`form get`,也不要换 `--verbose`、`raw`、`pretty` 重复请求。用户还要求发送时,把该完整 URL 交给 Chat 的发送命令并检查真实发送回执。
|
||||
|
||||
## 要点
|
||||
|
||||
- **创建表单**有两种等价方式:
|
||||
- `form create --name "表单名"`(推荐,语义清晰)
|
||||
- `view create --view-type FormDesigner --name "表单名"`(底层一致)
|
||||
- `form update` 支持 `--title` 与 `--name` 两个等价参数;至少需传一项
|
||||
- `form field update` 必须传 `--required` 或 `--field-description` 至少一项
|
||||
- `form field hide` 仅控制字段在表单中的可见性,不影响底层数据表字段
|
||||
- **题目管理**与字段管理本质相同(题目 = 表格字段):
|
||||
- `form questions create` 与 `field create` 入参完全一致(`--fields` JSON 或 `--name --type`)
|
||||
- `form questions delete` 与 `field delete` 入参完全一致(必传 `--field-id`)
|
||||
- 设置必填要在 create 后用 `form field update --required true` 单独调一次
|
||||
|
||||
## form 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 返回 viewId/name/title/createdAt |
|
||||
| `form get` | 按 viewId 取单个表单 | `--base-id` `--table-id` `--view-id` | 内部基于 list_form_views 过滤 |
|
||||
| `form create` | 创建表单视图 | `--base-id` `--table-id` `--name` | viewType=FormDesigner |
|
||||
| `form update` | 更新表单 | `--base-id` `--table-id` `--view-id` | `--title`/`--name`(等价)和 `--description` 至少传一项;同时传 title/name 时 title 优先 |
|
||||
| `form delete` | 删除表单 | `--base-id` `--table-id` `--view-id` `--yes` | 不可逆 |
|
||||
|
||||
## form field 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `form field list` | 列出表单字段 | `--base-id` `--table-id` `--view-id` | 返回 fieldId/name/type/required/hidden/description(hidden=true 的字段不在此返回) |
|
||||
| `form field update` | 更新表单字段 | `--base-id` `--table-id` `--view-id` `--field-id` | `--required` 或 `--field-description` 至少一项 |
|
||||
| `form field hide` | 切换字段隐藏 | `--base-id` `--table-id` `--view-id` `--field-id` `--hidden` | `--hidden true` 隐藏 / `--hidden false` 显示 |
|
||||
|
||||
## form questions 子命令
|
||||
|
||||
`form questions create/delete` 与 `field create/delete` 入参、行为完全一致,只是命令位置归属于 `form` 命令组,方便从表单视角操作题目。
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `form questions create` | 添加题目 | `--base-id` `--table-id` + (`--fields` 或 `--name --type`) | 入参与 `field create` 完全一致 |
|
||||
| `form questions delete` | 删除题目 | `--base-id` `--table-id` `--field-id` `--yes` | 入参与 `field delete` 完全一致;不可逆;批量需多次调用 |
|
||||
|
||||
## form share 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `form share get` | 获取分享配置 | `--base-id` `--table-id` `--view-id` | 返回 enabled/status/shareFormUuid |
|
||||
| `form share update` | 开启/关闭分享 | `--base-id` `--table-id` `--view-id` `--enabled` | `--enabled true` 开启 / `--enabled false` 关闭。注意:UI 上"发布并分享"按钮是另一概念,本命令只切换内部 enabled 标志,开启后需在 UI 刷新页面才会看到分享面板 |
|
||||
|
||||
## 完整工作流示例
|
||||
|
||||
> **占位符约定**:
|
||||
> - `BASE_ID` 来自 `dws aitable base list` / `base search` 返回的 `data.bases[].baseId`
|
||||
> - `TABLE_ID` 来自 `dws aitable base get --base-id BASE_ID` 返回的 `data.tables[].tableId`
|
||||
> - `VIEW_ID` 来自步骤 1 `form create` 返回的 `data.viewId`
|
||||
> - `FIELD_ID` 来自步骤 2 `form questions create` 返回的 `data.results[].fieldId`
|
||||
|
||||
```bash
|
||||
# 1) 创建表单 → 取返回的 data.viewId 作为 VIEW_ID
|
||||
dws aitable form create --base-id BASE_ID --table-id TABLE_ID --name "员工信息收集" --format json
|
||||
|
||||
# 2) 添加题目 → 取返回的 data.results[].fieldId 作为 FIELD_ID
|
||||
dws aitable form questions create --base-id BASE_ID --table-id TABLE_ID \
|
||||
--fields '[{"fieldName":"姓名","type":"text"},{"fieldName":"邮箱","type":"text"}]' --format json
|
||||
|
||||
# 3) 配置表单标题与描述
|
||||
dws aitable form update --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
|
||||
--title "员工信息收集" --description "请填写您的基本信息" --format json
|
||||
|
||||
# 4) 设置题目必填(FIELD_ID 来自步骤 2)
|
||||
dws aitable form field update --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
|
||||
--field-id FIELD_ID --required true --format json
|
||||
|
||||
# 5) 隐藏不需要的题目
|
||||
dws aitable form field hide --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
|
||||
--field-id FIELD_ID --hidden true --format json
|
||||
|
||||
# 6) 开启分享(注意:开启后需 UI 刷新页面才会看到分享面板)
|
||||
dws aitable form share update --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_ID \
|
||||
--enabled true --format json
|
||||
```
|
||||
|
||||
## 返回结构补充
|
||||
|
||||
- `form list` 返回 `data.formViews[]`,**每条仅含** `viewId/name/title/createdAt`;`shareFormUuid` 不在此返回,请用 `form share get` 单独获取。
|
||||
- `form get` 返回结构与 `form list` 完全一致(`data.formViews[]`),仅含一条记录(与请求 viewId 一致)。Agent 提取时仍走 `data.formViews[0]`。
|
||||
- `form field list` 仅返回**未隐藏**的字段;`hidden=true` 的字段不在此返回,如需查看全部字段请用 `field get`。
|
||||
@@ -0,0 +1,224 @@
|
||||
# AI 表格公式字段指南
|
||||
|
||||
> 当用户要创建 formula 类型字段、编写表内计算公式、做派生指标时,必须先读本文档。
|
||||
|
||||
## 1. 何时使用 formula 字段
|
||||
|
||||
| 场景 | 用 formula | 不用 formula |
|
||||
|------|-----------|-------------|
|
||||
| 长期展示在表中的派生值(如"总价=单价×数量") | ✅ | |
|
||||
| 条件标记(如"超期=IF(截止日期<TODAY(),'是','否')") | ✅ | |
|
||||
| 文本拼接(如"全名=姓&名") | ✅ | |
|
||||
| 一次性统计分析(如"本月总销售额") | | ✅ 用 record stats 服务端聚合 |
|
||||
| 跨表查找引用 | | ✅ 用 lookup 字段(见下方说明) |
|
||||
|
||||
## 2. 创建 formula 字段
|
||||
|
||||
```bash
|
||||
dws aitable field create \
|
||||
--base-id <baseId> \
|
||||
--table-id <tableId> \
|
||||
--name "总价" \
|
||||
--type formula \
|
||||
--config '{"formula": "[单价] * [数量]"}' \
|
||||
--format json
|
||||
```
|
||||
|
||||
### config 结构
|
||||
|
||||
```json
|
||||
{
|
||||
"formula": "<公式表达式>"
|
||||
}
|
||||
```
|
||||
|
||||
- `formula` 是唯一必填字段
|
||||
- 表达式中引用字段使用 **方括号 + 字段名**:`[字段名]`
|
||||
- 字段名必须精确匹配(含空格、大小写)
|
||||
|
||||
## 3. 公式语法
|
||||
|
||||
### 3.1 引用规则
|
||||
|
||||
| 引用方式 | 语法 | 说明 |
|
||||
|---------|------|------|
|
||||
| 引用本表字段 | `[字段名]` | 字段名必须精确匹配 |
|
||||
| 引用关联表字段 | 不支持 | 需要用 lookup 字段 |
|
||||
|
||||
### 3.2 常用函数分类
|
||||
|
||||
#### 数值计算
|
||||
|
||||
| 函数 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `+` `-` `*` `/` | 四则运算 | `[单价] * [数量]` |
|
||||
| `SUM(...)` | 求和 | `SUM([Q1], [Q2], [Q3], [Q4])` |
|
||||
| `ROUND(value, digits)` | 四舍五入 | `ROUND([金额] * 0.1, 2)` |
|
||||
| `ABS(value)` | 绝对值 | `ABS([差额])` |
|
||||
| `MAX(a, b, ...)` | 最大值 | `MAX([成绩1], [成绩2])` |
|
||||
| `MIN(a, b, ...)` | 最小值 | `MIN([报价1], [报价2])` |
|
||||
|
||||
#### 文本处理
|
||||
|
||||
| 函数 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `&` | 文本拼接 | `[姓] & [名]` |
|
||||
| `CONCATENATE(...)` | 拼接多个值 | `CONCATENATE([城市], "-", [区])` |
|
||||
| `LEFT(text, n)` | 取左侧 n 字符 | `LEFT([编号], 4)` |
|
||||
| `RIGHT(text, n)` | 取右侧 n 字符 | `RIGHT([手机], 4)` |
|
||||
| `LEN(text)` | 文本长度 | `LEN([备注])` |
|
||||
| `UPPER(text)` / `LOWER(text)` | 大小写转换 | `UPPER([代码])` |
|
||||
|
||||
#### 逻辑判断
|
||||
|
||||
| 函数 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `IF(条件, 真值, 假值)` | 条件判断 | `IF([金额] > 1000, "大额", "普通")` |
|
||||
| `AND(a, b, ...)` | 逻辑与 | `IF(AND([状态]="完成", [评分]>=4), "优秀", "")` |
|
||||
| `OR(a, b, ...)` | 逻辑或 | `IF(OR([等级]="A", [等级]="B"), "通过", "未通过")` |
|
||||
| `NOT(expr)` | 逻辑非 | `NOT([已归档])` |
|
||||
| `SWITCH(expr, v1, r1, v2, r2, ..., default)` | 多条件匹配 | `SWITCH([状态], "待办","🔴", "进行中","🟡", "完成","🟢", "")` |
|
||||
|
||||
#### 日期函数
|
||||
|
||||
| 函数 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `TODAY()` | 当前日期 | `IF([截止日期] < TODAY(), "已逾期", "正常")` |
|
||||
| `NOW()` | 当前时间 | `NOW()` |
|
||||
| `YEAR(date)` / `MONTH(date)` / `DAY(date)` | 提取年/月/日 | `YEAR([创建时间])` |
|
||||
| `DATEDIF(start, end, unit)` | 日期差 | `DATEDIF([开始], [结束], "d")` 返回天数 |
|
||||
| `DATEADD(date, count, unit)` | 日期加减 | `DATEADD([创建时间], 7, "d")` |
|
||||
|
||||
> `DATEDIF` 的 unit 参数:`"y"`=年, `"m"`=月, `"d"`=天
|
||||
|
||||
#### 空值处理
|
||||
|
||||
| 函数 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `BLANK()` | 空值常量 | `IF([备注] = BLANK(), "无", [备注])` |
|
||||
| `IF(field, ...)` | 字段为空时视为 false | `IF([评分], [评分], 0)` |
|
||||
|
||||
## 4. 常见公式模板
|
||||
|
||||
### 4.1 计算类
|
||||
|
||||
```
|
||||
// 含税价格
|
||||
[不含税价] * (1 + [税率])
|
||||
|
||||
// 完成率百分比
|
||||
[已完成数] / [总数]
|
||||
|
||||
// 折扣后价格
|
||||
[原价] * (1 - [折扣率])
|
||||
```
|
||||
|
||||
### 4.2 状态标记类
|
||||
|
||||
```
|
||||
// 逾期标记
|
||||
IF([截止日期] < TODAY(), "⚠️ 已逾期", "正常")
|
||||
|
||||
// 优先级标签
|
||||
SWITCH([优先级], "紧急","🔴P0", "高","🟠P1", "中","🟡P2", "低","🟢P3", "")
|
||||
|
||||
// 进度状态
|
||||
IF([进度] >= 1, "✅ 已完成", IF([进度] > 0, "🔄 进行中", "⏳ 未开始"))
|
||||
```
|
||||
|
||||
### 4.3 文本拼接类
|
||||
|
||||
```
|
||||
// 编号生成
|
||||
"PRJ-" & [项目编码] & "-" & [序号]
|
||||
|
||||
// 地址拼接
|
||||
[省] & [市] & [区] & [详细地址]
|
||||
```
|
||||
|
||||
## 5. 注意事项与限制
|
||||
|
||||
### 5.1 formula 字段是只读的
|
||||
|
||||
- formula 字段的值由系统自动计算,**不能通过 `record create/update` 写入**
|
||||
- 如果用户要"设置某个计算结果",应引导其修改源字段
|
||||
|
||||
### 5.2 字段名必须精确
|
||||
|
||||
- 公式中的 `[字段名]` 必须与表中实际字段名完全一致
|
||||
- 创建 formula 字段前,先通过 `field get` 确认字段名
|
||||
|
||||
### 5.3 循环引用
|
||||
|
||||
- formula 字段不能引用自身
|
||||
- 不能形成 A→B→A 的循环引用
|
||||
|
||||
### 5.4 与跨表引用字段的区别
|
||||
|
||||
钉钉 AI 表格有两种跨表取值方式:`lookup`(关联引用)和 `filterUp`(查找引用)。
|
||||
|
||||
| 维度 | formula | lookup (关联引用) | filterUp (查找引用) |
|
||||
|------|---------|-----------------|-------------------|
|
||||
| 字段类型 | `formula` | `lookup` | `filterUp` |
|
||||
| 数据来源 | 本表字段 | 通过已有关联字段(bidirectionalLink/unidirectionalLink)取关联表字段 | 直接指定目标表 + 筛选条件取值 |
|
||||
| 前置条件 | 无 | 必须先有关联字段 | 无需关联字段 |
|
||||
| 适用场景 | 本表内计算、条件判断 | "我关联了某条记录,取它的某个字段值" | "在另一张表里按条件查找记录并聚合取值" |
|
||||
|
||||
#### lookup config(已验证)
|
||||
|
||||
```json
|
||||
{
|
||||
"associateField": "<本表中的关联字段 fieldId(bidirectionalLink/unidirectionalLink 类型)>",
|
||||
"valuesField": "<关联目标表中要取值的字段 fieldId>",
|
||||
"aggregator": "SUM|AVERAGE|COUNT|MAX|MIN|CONCATENATE"
|
||||
}
|
||||
```
|
||||
|
||||
创建示例:
|
||||
```bash
|
||||
dws aitable field create --base-id <baseId> --table-id <tableId> \
|
||||
--name "关联名称" --type lookup \
|
||||
--config '{"associateField":"<linkFieldId>","valuesField":"<targetFieldId>","aggregator":"CONCATENATE"}'
|
||||
```
|
||||
|
||||
#### filterUp config(已验证)
|
||||
|
||||
```json
|
||||
{
|
||||
"targetSheet": "<目标表 tableId>",
|
||||
"filters": [
|
||||
{
|
||||
"fieldId": "<目标表字段Id>",
|
||||
"operator": "equal|contain",
|
||||
"value": "<匹配值>",
|
||||
"link": "AND"
|
||||
}
|
||||
],
|
||||
"valuesField": "<目标表中要取值的字段Id>",
|
||||
"aggregator": "SUM|AVERAGE|COUNT|MAX|MIN|CONCATENATE"
|
||||
}
|
||||
```
|
||||
|
||||
> `filters` 必须非空(至少一条筛选规则)。
|
||||
> `filters[].operator` 仅支持:`equal`、`contain`(`not_equal`/`not_contain`/`is_empty` 等均不支持)。
|
||||
> `filters[].link` 统一为 `"AND"` 或 `"OR"`。
|
||||
|
||||
### 5.5 创建前检查清单
|
||||
|
||||
1. 已通过 `field get` 确认所有引用字段的精确名称
|
||||
2. 引用字段不包含 formula/lookup 等只读字段(可能导致二次计算延迟)
|
||||
3. 公式语法正确(括号匹配、函数名正确)
|
||||
4. 字段类型兼容(数值运算的字段确实是 number 类型)
|
||||
|
||||
## 6. 更新 formula 字段
|
||||
|
||||
```bash
|
||||
dws aitable field update \
|
||||
--base-id <baseId> \
|
||||
--table-id <tableId> \
|
||||
--field-id <fieldId> \
|
||||
--config '{"formula": "[新字段A] + [新字段B]"}' \
|
||||
--format json
|
||||
```
|
||||
|
||||
更新时只需传新的 `formula` 表达式,系统会自动重新计算所有记录。
|
||||
@@ -0,0 +1,56 @@
|
||||
# 主键文档管理
|
||||
|
||||
## 适用场景
|
||||
|
||||
当需要为 AI 表格中的记录创建或查询关联的主键文档时使用。主键文档是 primaryDoc 类型字段对应的钉钉在线文档,可通过 `dws doc` 进行内容读写。
|
||||
|
||||
## 命令
|
||||
|
||||
### 查询主键文档
|
||||
|
||||
```bash
|
||||
dws aitable +record-primary-doc-get --base-id BASE_ID --table-id TABLE_ID --record-id RECORD_ID
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `--base-id`(必填):Base ID
|
||||
- `--table-id`(必填):Table ID
|
||||
- `--record-id`(必填):Record ID
|
||||
|
||||
**返回:** `data.nodeId` — 主键文档的 nodeId,可直接传给 `dws doc read/update` 的 `--node` 参数。若该记录尚未创建主键文档,`nodeId` 为 null。
|
||||
|
||||
### 创建主键文档
|
||||
|
||||
```bash
|
||||
dws aitable +record-primary-doc-create --base-id BASE_ID --table-id TABLE_ID --field-id FIELD_ID --record-id RECORD_ID
|
||||
```
|
||||
|
||||
**参数:**
|
||||
- `--base-id`(必填):Base ID
|
||||
- `--table-id`(必填):Table ID
|
||||
- `--field-id`(必填):主键字段 ID,必须是 primaryDoc 类型(通过 `dws aitable field get` 查看字段类型)
|
||||
- `--record-id`(必填):Record ID
|
||||
|
||||
**返回:** `data.nodeId` — 创建或已存在的主键文档 nodeId。
|
||||
|
||||
**幂等性:** 若该记录已有主键文档,直接返回已有文档的 nodeId,不会重复创建。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `fieldId` 必须是 primaryDoc 类型,否则返回 `INVALID_FIELD_TYPE` 错误
|
||||
- `primaryDoc` 是建表时的首字段能力,不能在已有普通首字段之后补建,也不能把普通字段改成 primaryDoc。需要该能力时应新建以 primaryDoc 为首字段的数据表并迁移数据;未经用户明确授权不要自动迁移。
|
||||
- 传入不存在的 `recordId` 会返回 `RECORD_NOT_FOUND` 错误
|
||||
- 创建后可通过 `dws doc update --node <nodeId>` 写入文档内容,或 `dws doc read --node <nodeId>` 读取
|
||||
|
||||
## 典型工作流
|
||||
|
||||
```bash
|
||||
# 1. 查询字段目录,拿到 primaryDoc 字段的 fieldId
|
||||
dws aitable field get --base-id BASE_ID --table-id TABLE_ID
|
||||
|
||||
# 2. 为记录创建主键文档
|
||||
dws aitable +record-primary-doc-create --base-id BASE_ID --table-id TABLE_ID --field-id FIELD_ID --record-id RECORD_ID
|
||||
|
||||
# 3. 拿到返回的 nodeId,用 dws doc 写入内容
|
||||
dws doc update --node <data.nodeId> --content "# 项目方案\n\n文档正文内容..."
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
# record create — 新增记录
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable record create [flags]
|
||||
Example:
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldTextId":"文本内容","fldNumId":123}}]'
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--records string 记录列表 JSON 数组,单次最多 100 条 (必填,与 --records-file 二选一)
|
||||
--records-file string 从文件读取 records JSON(替代 --records,适合超长数据或 Windows 环境)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
## Windows / 超长 JSON 推荐
|
||||
|
||||
将 records JSON 写入文件,用 `--records-file ./records.json` 传入,避免命令行截断和引号转义问题。
|
||||
|
||||
## 常见错误(严格避免)
|
||||
|
||||
| 错误 | 说明 |
|
||||
|------|------|
|
||||
| 参数名用 `--data` | ❌ 参数名是 `--records`,不是 `--data` |
|
||||
| cells key 用字段名 | ❌ cells key 必须是 fieldId(如 `fldXXX`),不是字段名称(如 `"课程名称"`) |
|
||||
| 不先获取 fieldId | ❌ 必须先 `field get` 获取 fieldId,再写入记录 |
|
||||
| 单次超 100 条 | ❌ 单次最多 100 条,超过需分批 |
|
||||
| 附件/图片字段直传 URL | ❌ 严禁 `{"url":"https://..."}` — 会触发 TIMEOUT_ERROR。必须先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。详见 [aitable-attachment.md](./aitable-attachment.md) |
|
||||
|
||||
## 正确流程
|
||||
|
||||
```bash
|
||||
# 先获取 fieldId
|
||||
dws aitable field get --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
# 从返回中提取 fieldId(如 fldABC123)
|
||||
|
||||
# 再用 fieldId 写入记录
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldABC123":"Python入门"}}]' --format json
|
||||
|
||||
# 从创建响应的 data.newRecordIds[] 提取新 ID,并回读确认真实写入值
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--record-ids <NEW_RECORD_ID> --format json
|
||||
```
|
||||
|
||||
创建成功以 `data.newRecordIds[]` 为 ID 来源;不要把整个 `data` 当作单个 recordId,也不要只以退出码作为写入成功证据。
|
||||
|
||||
## cells 写入格式
|
||||
|
||||
各字段类型的写入格式见 [aitable-cell-value.md](./aitable-cell-value.md)。
|
||||
@@ -0,0 +1,20 @@
|
||||
# record delete — 删除记录
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable record delete [flags]
|
||||
Example:
|
||||
dws aitable record delete --base-id <BASE_ID> --table-id <TABLE_ID> --record-ids rec1,rec2 --yes
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--record-ids string 待删除记录 ID 列表,逗号分隔,最多 100 条 (必填)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **不可逆操作**,调用前建议先 `record query` 确认目标记录
|
||||
- 需要先通过 `record query` 获取 recordId
|
||||
- 单次最多删除 100 条记录
|
||||
@@ -0,0 +1,97 @@
|
||||
# 行记录变更历史(record history-list)
|
||||
|
||||
按 recordId 查询单条记录的全部变更历史,用于审计、回溯字段变更、定位操作人。
|
||||
|
||||
## 命令
|
||||
|
||||
```
|
||||
dws aitable record history-list \
|
||||
--base-id BASE_ID --table-id TABLE_ID --record-id REC_ID \
|
||||
[--offset N] [--limit M]
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 所属 Base ID(必填,可用 `--base` 别名) |
|
||||
| `--table-id` | 所属 Table ID(必填) |
|
||||
| `--record-id` | 目标记录 ID(必填,单条;不支持批量) |
|
||||
| `--offset` | 分页偏移量,默认 0 |
|
||||
| `--limit` | 每页返回数量,范围 [1, 50],默认 20 |
|
||||
|
||||
## 返回结构
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"data": {
|
||||
"histories": [
|
||||
{
|
||||
"type": "field_change", // 变更类型
|
||||
"action": "update", // 操作动作: create / update / delete
|
||||
"newValue": "{\"...\":\"...\"}", // 变更后的值(JSON 字符串)
|
||||
"oldValue": "{\"...\":\"...\"}", // 变更前的值(JSON 字符串)
|
||||
"operateTime": 1733123456789, // 操作时间(毫秒级时间戳)
|
||||
"typeChangedFields": "{...}", // 类型变更的字段信息(JSON 字符串)
|
||||
"version": 7 // 版本号(单调递增)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`newValue` / `oldValue` / `typeChangedFields` 是 JSON 字符串(不是 JSON 对象),需要二次 `JSON.parse` 才能拿到结构化值。
|
||||
|
||||
## 字段含义速查
|
||||
|
||||
| 字段 | 用途 |
|
||||
|------|------|
|
||||
| `type` | 高层分类:`record_create` / `field_change` / `record_delete` 等。先按 type 过滤大类。 |
|
||||
| `action` | 三态:`create` / `update` / `delete`。比 type 粗,但便于按"动作"统计。 |
|
||||
| `version` | 单调递增整数;同一 record 越新值越大。**用作"上一条 vs 这一条"的稳定排序键**。 |
|
||||
| `operateTime` | 毫秒时间戳;可格式化成可读时间。多条同 version 的极端场景用 operateTime 兜底排序。 |
|
||||
|
||||
## 典型用法
|
||||
|
||||
### 1. 看一条记录被改过几次
|
||||
|
||||
```bash
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --format json \
|
||||
| jq '.data.histories[] | {version, action, operateTime}'
|
||||
```
|
||||
|
||||
### 2. 翻页拉全量历史
|
||||
|
||||
```bash
|
||||
# 第 1 页(最新 20 条)
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --limit 50 --offset 0
|
||||
|
||||
# 第 2 页
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --limit 50 --offset 50
|
||||
```
|
||||
|
||||
`limit` 上限 50,需要更多请增加 `offset` 翻页。
|
||||
|
||||
### 3. 回溯某字段最近一次值
|
||||
|
||||
```bash
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --limit 50 --format json \
|
||||
| jq '[.data.histories[] | select(.action == "update")][0].oldValue'
|
||||
```
|
||||
|
||||
### 4. 找出删除事件(如果存在 delete history)
|
||||
|
||||
```bash
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --format json \
|
||||
| jq '.data.histories[] | select(.action == "delete") | {version, operateTime}'
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 一次只能查一条 record;如需批量审计多条记录请循环调用。
|
||||
- 仅返回**字段值变更**与**记录生命周期事件**;视图、字段定义、表结构变更不在此 history 里。
|
||||
- 历史保留时长由 server 决定,过老的记录可能不再返回。
|
||||
|
||||
## 与其他 record 命令的关系
|
||||
|
||||
- 想看记录"现在长什么样" → `record query` / `record get`
|
||||
- 想看记录"过去长什么样、什么时候改的" → `record history-list`(本命令)
|
||||
- 想看"这张表整体改过什么" → 当前 CLI 不支持表级 history;只能逐 record 查
|
||||
@@ -0,0 +1,47 @@
|
||||
# 行命名规则枚举键(recordNameKey)映射
|
||||
|
||||
`dws aitable table update --record-name-key <枚举键>` 用于设置数据表的"行命名规则"——卡片/详情页里"行"的展示别名。**取值是固定枚举,不是字段 ID**;传非法值服务端返回 `INVALID_RECORD_NAME_KEY`。
|
||||
|
||||
## 中文 → 枚举键(按 UI 下拉顺序)
|
||||
|
||||
| 用户说 | --record-name-key | 用户说 | --record-name-key |
|
||||
|---|---|---|---|
|
||||
| 记录 | `ji_lu`(默认) | 项目 | `project` |
|
||||
| 任务 | `task` | 事件 | `event` |
|
||||
| 请求 | `request` | 活动 | `campaign` |
|
||||
| 目标 | `objective` | 交付物 | `deliverable` |
|
||||
| 资产 | `asset` | 客户 | `customer` |
|
||||
| 订单 | `order` | 联系人 | `contact` |
|
||||
| 物料/物品 | `item` | 问题 | `question` 或 `issue` |
|
||||
| 工单 | `ticket` | 候选人 | `candidate` |
|
||||
| 商机/机会 | `opportunity` | 会议 | `meeting` |
|
||||
| 成员 | `member` | OKR | `okr` |
|
||||
|
||||
## 其他常用键(按场景分组)
|
||||
|
||||
- **业务流程**:`approval` / `application` / `case` / `decision` / `delivery` / `payment` / `purchase_order` / `quote` / `release`
|
||||
- **HR / 财务**:`employee` / `expense` / `budget` / `invoice`
|
||||
- **产品 / 研发**:`feature` / `feedback` / `idea` / `bug` / `requirement` / `risk` / `sprint` / `story` / `subtask` / `epic`
|
||||
- **CRM**:`account` / `lead` / `prospect` / `deal`
|
||||
- **运营 / 支持**:`note` / `report` / `topic` / `session` / `service`
|
||||
- **资源 / 通用**:`file` / `document` / `product` / `team` / `user` / `vendor` / `key_result` / `metric`
|
||||
|
||||
完整集合较大(共 273 个),服务端校验;以上未列出的合法键也可直接传(如 `goal` / `okr` / `pillar` / `phase` / `milestone` 等)。
|
||||
|
||||
## 使用示例
|
||||
|
||||
```bash
|
||||
# 用户说"把这张表的行叫'任务'吧" → 传 task
|
||||
dws aitable table update --base-id BASE --table-id TBL --record-name-key task
|
||||
|
||||
# 用户说"换成项目" → 传 project
|
||||
dws aitable table update --base-id BASE --table-id TBL --record-name-key project
|
||||
|
||||
# 用户说"恢复成默认(记录)" → 传 ji_lu
|
||||
dws aitable table update --base-id BASE --table-id TBL --record-name-key ji_lu
|
||||
```
|
||||
|
||||
## 注意
|
||||
|
||||
- recordNameKey **不会在 `table get` 响应里回显**(`get_tables` DTO 设计上不暴露该字段);写入是否成功以 `table update` 的 set response 是否回填 `recordNameKey` 字段为准。
|
||||
- 中文别名是 server 内置 i18n,UI 显示用户对应的国际化文案,CLI 必须传英文枚举键。
|
||||
@@ -0,0 +1,120 @@
|
||||
# record query — 查询记录
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable record query [flags]
|
||||
Example:
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID>
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --record-ids rec1,rec2
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --query "关键词" --limit 50
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--cursor string 分页游标,首次不传
|
||||
--field-ids string 返回字段 ID 列表,逗号分隔,单次最多 100 个
|
||||
--filters string 结构化过滤条件 JSON
|
||||
--query string 全文关键词搜索
|
||||
--limit int 单次最大记录数,默认 100,最大 100
|
||||
--record-ids string 指定记录 ID 列表,逗号分隔,单次最多 100 个
|
||||
--sort string 排序条件 JSON 数组
|
||||
--table-id string Table ID (必填)
|
||||
--all 启用自动翻页,循环获取并合并所有记录后统一输出
|
||||
--page-limit int 自动翻页最大页数(仅 --all 时生效)。默认 50,设为 0 表示无限制
|
||||
```
|
||||
|
||||
两种模式: 按 ID 取(传 record-ids,忽略 filters/sort)或条件查(filters+sort+cursor 分页)。
|
||||
|
||||
## 自动翻页(--all + --page-limit)
|
||||
|
||||
- 传入 `--all` 启用自动翻页,CLI 自动循环获取并合并所有记录后统一输出
|
||||
- `--page-limit` 控制最大翻页次数,默认 50 页(5000 条),设为 0 表示无限制
|
||||
- 页间间隔 200ms,中途网络错误会 graceful stop 并输出已获取的数据
|
||||
- **被截断时**(达到 page-limit 但仍有数据):输出中包含 `"hasMore": true` 和 `"cursor": "..."` 字段,可通过 `--cursor` 从断点继续拉取
|
||||
- 适用于需要一次性获取全量数据的场景(如导出、统计、批量处理)
|
||||
|
||||
```bash
|
||||
# 默认(最多 50 页 = 5000 条)
|
||||
dws aitable record query --base-id X --table-id Y --all
|
||||
# 无限制(拉完为止)
|
||||
dws aitable record query --base-id X --table-id Y --all --page-limit 0
|
||||
# 从上次断点继续
|
||||
dws aitable record query --base-id X --table-id Y --all --cursor "上次返回的cursor"
|
||||
```
|
||||
|
||||
## 排序参数规范
|
||||
|
||||
`--sort` 需要传 JSON 数组,排序方向字段必须是 `direction`(`asc` 或 `desc`),不要使用 `order`。
|
||||
|
||||
正确示例:
|
||||
```bash
|
||||
--sort '[{"fieldId":"wm8ns9bw2vmucb45xj3ix","direction":"desc"}]'
|
||||
```
|
||||
|
||||
## filters 结构
|
||||
|
||||
详细语法见 [aitable-filter-sort.md](./aitable-filter-sort.md)。
|
||||
|
||||
快速模板:
|
||||
```json
|
||||
{"operator":"and","operands":[{"operator":"eq","operands":["<fieldId>","<value>"]}]}
|
||||
```
|
||||
|
||||
> **singleSelect/multipleSelect 过滤**:filters 中可传 option id 或 option name,但建议优先用 **option id**(通过 `field get` 获取),更可靠。
|
||||
|
||||
## 减少响应体积
|
||||
|
||||
字段较多时,用 `--field-ids` 仅返回需要的字段,可显著减少返回数据量。
|
||||
|
||||
## 常见错误
|
||||
|
||||
- `--filters` 根节点直接用 `"operator":"eq"` → API 静默忽略,返回全表
|
||||
- `--sort` 用 `"order":"desc"` → 必须用 `"direction":"desc"`
|
||||
- 不加 `--field-ids` 拉全字段 → 大表响应体积过大
|
||||
- 全量拉取后在 context 里手动统计 → 应优先用 `--filters` 服务端过滤
|
||||
|
||||
## record query-empty — 找空行
|
||||
|
||||
`record query-empty` 是与 `record query` 平行的独立子命令,专门按表内顺序扫描出"完全没填用户字段"的空行。
|
||||
|
||||
```bash
|
||||
dws aitable record query-empty --base-id BASE_ID --table-id TABLE_ID
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` / `--base` | 必填 |
|
||||
| `--table-id` | 必填 |
|
||||
| `--limit` | 单次**扫描预算**(不是返回数);范围 [1, 100],默认 100 |
|
||||
| `--cursor` | 分页游标。响应中 `nextCursor` 非空 → 用它翻页继续扫;nextCursor 为空(或不存在)→ 已扫完整表 |
|
||||
|
||||
返回结构:
|
||||
|
||||
```jsonc
|
||||
{ "data": { "records": [...], "nextCursor": "..." } }
|
||||
```
|
||||
|
||||
### 关键语义
|
||||
|
||||
1. **`--limit` 是扫描预算不是返回数**:可能扫了 100 条但全部非空,本页 `records: []`。
|
||||
2. **本页空 records ≠ 全表无空行**:必须看 `nextCursor`,nextCursor 还在就要继续翻。
|
||||
3. **空行定义**:除系统字段(recordId / 创建人 / 创建时间 / 修改人 / 修改时间)外,所有 cell 都是 null、空字符串、空集合或空 Map。一般是用户在 UI 上"插入空行"产生的。
|
||||
|
||||
### 典型用法
|
||||
|
||||
```bash
|
||||
# 扫一页,看本页有没有空行
|
||||
dws aitable record query-empty --base-id BASE --table-id TBL
|
||||
|
||||
# 翻页
|
||||
dws aitable record query-empty --base-id BASE --table-id TBL --cursor <上次的nextCursor>
|
||||
|
||||
# 把整表扫完(手动循环 cursor)
|
||||
NC=""
|
||||
while : ; do
|
||||
R=$(dws aitable record query-empty --base-id BASE --table-id TBL ${NC:+--cursor "$NC"} --format json)
|
||||
echo "$R" | jq '.data.records[] | .recordId'
|
||||
NC=$(echo "$R" | jq -r '.data.nextCursor // empty')
|
||||
[ -z "$NC" ] && break
|
||||
done
|
||||
```
|
||||
@@ -0,0 +1,54 @@
|
||||
# 行记录分享链接(record share-url)
|
||||
|
||||
按 recordId 批量获取记录的分享链接,把某行单独发给同事查看。
|
||||
|
||||
## 命令
|
||||
|
||||
```
|
||||
dws aitable record share-url \
|
||||
--base-id BASE_ID --table-id TABLE_ID \
|
||||
--record-ids rec1,rec2,rec3 \
|
||||
[--view-id VIEW_ID]
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 所属 Base ID(必填,可用 `--base` 别名) |
|
||||
| `--table-id` | 所属 Table ID(必填) |
|
||||
| `--record-ids` | 目标 Record ID 列表,CSV 逗号分隔,**单次最多 20 条**(必填) |
|
||||
| `--view-id` | 视图 ID(可选)。带上后链接打开会落在该视图上下文里 |
|
||||
|
||||
## 返回结构
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"data": {
|
||||
"items": [
|
||||
{ "recordId": "rec1", "shareUrl": "https://..." },
|
||||
{ "recordId": "rec2", "shareUrl": "https://..." }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`shareUrl` 为 null 表示该条获取失败(不影响其他条目)。
|
||||
|
||||
## 典型用法
|
||||
|
||||
```bash
|
||||
# 一次拿一条记录的链接
|
||||
dws aitable record share-url --base-id BASE --table-id TBL --record-ids rec1
|
||||
|
||||
# 批量拿,配合 jq 过滤出 url
|
||||
dws aitable record share-url --base-id BASE --table-id TBL --record-ids rec1,rec2,rec3 --format json \
|
||||
| jq '.data.items[] | {recordId, shareUrl}'
|
||||
|
||||
# 带视图上下文(链接打开时落在指定视图)
|
||||
dws aitable record share-url --base-id BASE --table-id TBL --record-ids rec1 --view-id viw_VIP
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **单次最多 20 条**,超出请客户端拆批。
|
||||
- 该链接是分享链接(不是源文档链接),打开后看到的是该 record 的只读详情页。
|
||||
- 取消单条分享 / 关闭整表分享当前 CLI 不支持,需要在 AI 表格 Web 端操作。
|
||||
@@ -0,0 +1,59 @@
|
||||
# record stats / group-stats — 服务端聚合统计
|
||||
|
||||
统计任务优先使用服务端聚合,不要先用 `record query --all` 下载全表再计算。
|
||||
|
||||
## 命令选择
|
||||
|
||||
| 需求 | 命令 | 底层接口 |
|
||||
|------|------|----------|
|
||||
| 总数、求和、平均值、最大/最小值、中位数、完整率等标量统计 | `record stats` | `query_records_stats` |
|
||||
| 按字段分组统计 | `record group-stats` + `--group` | `query_stats` |
|
||||
| 满足条件的唯一门店/客户/商品数量 | `record group-stats` + `distinct`,不传 `--group` | `query_stats` |
|
||||
|
||||
## 不分组统计
|
||||
|
||||
```bash
|
||||
dws aitable record stats \
|
||||
--base-id <BASE_ID> \
|
||||
--table-id <TABLE_ID> \
|
||||
--stats '[{"fieldId":"<FIELD_ID>","statsType":"COUNT"}]' \
|
||||
--format json
|
||||
```
|
||||
|
||||
- `statsType` 必须大写。
|
||||
- `--stats` 单次最多 20 项,同一 `fieldId` 不得重复;同字段多个指标拆成多次调用。
|
||||
- 支持基础类型 `COUNT`、`COUNT_COLUMN`、`SUM`、`AVG`、`MAX`、`MIN`,以及运行时支持的 `MEDIAN`、`STANDARD_DEVIATION`、`RANGE`、`DISTINCT`、`DISTINCT_RATIO`、完整率、勾选率和日期统计类型。
|
||||
- 统计全部匹配记录时省略 `--limit`;传入 limit 会改变统计范围。
|
||||
- 可选参数:`--filters`、`--sort`、`--keyword`、`--search-field-ids`、`--data-version`。
|
||||
|
||||
## 分组或去重统计
|
||||
|
||||
```bash
|
||||
dws aitable record group-stats \
|
||||
--base-id <BASE_ID> \
|
||||
--table-id <TABLE_ID> \
|
||||
--group '[{"fieldId":"<GROUP_FIELD_ID>","direction":"ASC","fieldConfig":null,"arraySplitMode":true}]' \
|
||||
--stats '[{"fieldId":"<VALUE_FIELD_ID>","statsType":"avg"}]' \
|
||||
--limit 1000 \
|
||||
--format json
|
||||
```
|
||||
|
||||
- `statsType` 必须小写;基础类型为 `sum`、`avg`、`count`、`max`、`min`,后端还可能支持 `median`、`distinct`、`distinct_ratio` 等高级类型。
|
||||
- `--group` 和 `--sort` 都是 JSON 数组编码后的字符串,CLI 会原样映射到 MCP 的 `group` / `sortDsl`。
|
||||
- 分组结果最多 1000 行。不要依赖服务端 limit 选择 Top N;应在基数不超过 1000 时取完整分组结果后排序。
|
||||
- 条件唯一实体计数不传 `--group`,对实体字段使用 `distinct`。
|
||||
|
||||
## 过滤条件
|
||||
|
||||
```bash
|
||||
--filters '{"operator":"and","operands":[{"operator":"gt","operands":["fldAmount",0]}]}'
|
||||
```
|
||||
|
||||
- 根节点必须是 `and` / `or`。
|
||||
- `lt`、`gt`、`lte`、`gte` 的值必须是 JSON 数字,不能写成数字字符串。
|
||||
- 单选/多选字段建议使用 `field get` 返回的 option ID。
|
||||
- 所有 Base、table、field 和 option ID 都必须从当前目标 Base 的实时元数据取得,不能复用示例或历史 ID。
|
||||
|
||||
## 降级边界
|
||||
|
||||
只有用户要求记录明细、少量校验样本、精确分位数输入,或聚合接口明确失败时,才使用 `record query`。需要先逐行运算再聚合的指标必须依赖表内已有且可直接聚合的公式字段;没有该字段时停止并请用户先在 AI 表格页面创建,不能遍历全表本地二次计算。
|
||||
@@ -0,0 +1,66 @@
|
||||
# record update — 更新记录
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws aitable record update [flags]
|
||||
Example:
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"fldStatusId":"已完成"}}]'
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--records string 待更新记录 JSON 数组,单次最多 100 条;cells key 支持 fieldId 或当前表内唯一字段名,推荐 fieldId (必填,与 --records-file 二选一)
|
||||
--records-file string 从文件读取 records JSON(替代 --records,适合超长数据或 Windows 环境)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
只需传入需修改的字段,未传入的保持原值。每条记录必须含 recordId 和 cells。
|
||||
|
||||
## cells key:优先使用 fieldId,也支持唯一字段名
|
||||
|
||||
`cells` 的 key 有两种写法:
|
||||
|
||||
- fieldId(推荐):不受字段重命名或重名影响,通过 `field get` 获取。
|
||||
- 当前表内唯一的字段名:按名称精确匹配;如果存在同名字段,必须改用 fieldId。
|
||||
|
||||
同一字段同时通过 fieldId 和字段名传入时,fieldId 对应的值优先。
|
||||
|
||||
```bash
|
||||
# 推荐:fieldId
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"fldStatusId":"已完成"}}]' --format json
|
||||
|
||||
# 便捷写法:当前表内唯一字段名
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"状态":"已完成"}}]' --format json
|
||||
```
|
||||
|
||||
## 推荐参数形式
|
||||
|
||||
公开、稳定的批量入口是 `--records`(或 `--records-file`),格式为 JSON 数组;即使只改一条记录,推荐也包在数组里。CLI 仍保留隐藏的 `--record-id` + `--cells` 兼容入口,但它不会出现在常规帮助中,自动化脚本应优先使用 `--records`。
|
||||
|
||||
| 不推荐或无效写法 | 推荐写法 |
|
||||
|---|---|
|
||||
| `--record-id recXXX --cells '{"fldX":"值"}'`(隐藏兼容入口) | `--records '[{"recordId":"recXXX","cells":{"fldX":"值"}}]'` |
|
||||
| `--id recXXX --data '{"fldX":"值"}'` | 同上 |
|
||||
| `--record-id recXXX --field fldX --value "新值"` | 同上 |
|
||||
|
||||
## 单条更新模板(直接复制)
|
||||
|
||||
```bash
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"<RECORD_ID>","cells":{"<FIELD_ID>":"新值"}}]' --format json
|
||||
|
||||
# 从更新响应的 data.recordIds[] 提取成功记录 ID,并回读确认真实值
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--record-ids <RECORD_ID> --format json
|
||||
```
|
||||
|
||||
更新响应不返回“受影响字段”;以 `data.recordIds[]` 确定成功记录,再用查询回读验证。
|
||||
|
||||
## 引号转义提示
|
||||
|
||||
- Linux/macOS:外层用单引号 `'[...]'`,内部 JSON 用双引号即可
|
||||
- Windows PowerShell:外层用双引号 `"[...]"`,内部双引号需转义为 `\"`
|
||||
- 或将 JSON 写入临时文件,用 `--records-file ./records.json` 规避转义
|
||||
@@ -0,0 +1,89 @@
|
||||
# 行记录 Upsert(record upsert)
|
||||
|
||||
按 `recordId` 是否存在,自动把入参拆分到 update 链路或 create 链路:批次混合"已存在改 + 新出现建"时用,省掉客户端按 ID 分批的逻辑。
|
||||
|
||||
## 命令
|
||||
|
||||
```
|
||||
dws aitable record upsert \
|
||||
--base-id BASE_ID --table-id TABLE_ID \
|
||||
--records '[{"recordId":"<可选>","cells":{...}}, ...]'
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填(可用 `--base` 别名) |
|
||||
| `--table-id` | 必填 |
|
||||
| `--records` | 待 upsert 的记录 JSON 数组,**单次最多 100 条**(必填)|
|
||||
| `--records-file` | 从文件读入(命令行 JSON 太长时用),与 `--records` 互斥优先级更高 |
|
||||
|
||||
## --records 结构
|
||||
|
||||
每项 JSON:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"recordId": "rec1", // 可选;带 → update,缺省 → create
|
||||
"cells": { // 必填;key 是 fieldId,value 按字段类型
|
||||
"fldTitleId": "新标题",
|
||||
"fldNumberId": 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cells` 写入格式与 `record create` / `record update` **完全一致**(key 必须是 fieldId 不是字段名;按字段类型见 [aitable-cell-value.md](./aitable-cell-value.md))。
|
||||
|
||||
## 返回结构
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"data": {
|
||||
"createdRecordIds": ["recX", "recY"], // 不带 recordId 的项产出
|
||||
"updatedRecordIds": ["recA", "recB"] // 带 recordId 的项产出
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`createdRecordIds` 顺序对应入参里**不带 recordId**的项(按出现顺序汇总),同理 `updatedRecordIds` 对应**带 recordId**的项。
|
||||
|
||||
## 典型用法
|
||||
|
||||
```bash
|
||||
# 1) 全部新建:所有项都不带 recordId
|
||||
dws aitable record upsert --base-id BASE --table-id TBL --records '[
|
||||
{"cells":{"fldTitleId":"任务1","fldStatusId":"待办"}},
|
||||
{"cells":{"fldTitleId":"任务2","fldStatusId":"待办"}}
|
||||
]'
|
||||
|
||||
# 2) 全部更新:所有项都带 recordId
|
||||
dws aitable record upsert --base-id BASE --table-id TBL --records '[
|
||||
{"recordId":"rec1","cells":{"fldStatusId":"已完成"}},
|
||||
{"recordId":"rec2","cells":{"fldStatusId":"已完成"}}
|
||||
]'
|
||||
|
||||
# 3) 混合:第 1 条更新(带 recordId),第 2 条创建(不带)
|
||||
dws aitable record upsert --base-id BASE --table-id TBL --records '[
|
||||
{"recordId":"rec1","cells":{"fldStatusId":"已完成"}},
|
||||
{"cells":{"fldTitleId":"新增任务","fldStatusId":"待办"}}
|
||||
]'
|
||||
|
||||
# 4) 长 JSON 用文件
|
||||
dws aitable record upsert --base-id BASE --table-id TBL --records-file ./batch.json
|
||||
```
|
||||
|
||||
## 与 record create / record update 的关系
|
||||
|
||||
| 场景 | 命令 |
|
||||
|------|------|
|
||||
| 确定全是新增 | `record create` |
|
||||
| 确定全是更新(每条独立 cells) | `record update` |
|
||||
| 确定全是更新(共享同一 cells) | `record batch-update` |
|
||||
| **不确定有没有,按 recordId 自动分流** | `record upsert`(本命令) |
|
||||
|
||||
`record upsert` 的 `--records` 入参格式与 `record update` 完全相同,唯一差别是 `recordId` 字段在 upsert 里是可选的。如果批次确定全是更新或全是新建,用专用命令更清晰;批次混合时(典型场景:定时同步外部数据,源里既有已存在的也有新出现的),用 upsert。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **单次最多 100 条**(创建 + 更新合计),超出请客户端拆批。
|
||||
- `cells` 的 key 必须是 fieldId 不是字段名(先用 `record query` 或 `field get` 拿 fieldId)。
|
||||
- 只读字段(formula / lookup / 系统字段)不能写入 — upsert 链路与 update 链路同样限制。
|
||||
@@ -0,0 +1,243 @@
|
||||
# 视图配置(view get/update <attr>)
|
||||
|
||||
按属性局部读/写视图配置。每个属性独立子命令,typed flag 友好,agent 不必拼 JSON。
|
||||
向后兼容:`view update --config '{...}'` 一次多属性入口仍可用。
|
||||
|
||||
## viewType × 支持矩阵
|
||||
|
||||
| viewType | card | timebar | aggregate | filter / sort / group | visible-fields | field-widths | name |
|
||||
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| Grid | | | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Kanban | ✅ | | | ✅ | ✅ | | ✅ |
|
||||
| Gallery | ✅ | | | ✅ | ✅ | | ✅ |
|
||||
| Gantt | | ✅ | | ✅ | ✅ | | ✅ |
|
||||
| Calendar | | | | ✅ | ✅ | | ✅ |
|
||||
| FormDesigner | (走 `form` 系列命令) | | | | | | |
|
||||
|
||||
> card 在 Kanban 走 `kanbanCard`,在 Gallery 走 `galleryCard`,CLI 自动按 viewType dispatch(preflight 1 次 `get_views`)。timebar 仅 Gantt 支持;Calendar 服务端未暴露任何 timebar 配置。
|
||||
|
||||
> **Gantt 视图必须两步创建**:`view create --view-type Gantt` 只创建空壳(`ganttTimebar: {}`),**必须**紧跟 `view update timebar --start-field <日期字段ID>` 绑定时间轴字段,否则视图打开是空白。`view create --config` 不接受 `ganttTimebar`,请在创建后使用专属子命令。
|
||||
|
||||
## 创建:view create
|
||||
|
||||
`--view-type` 支持 `Grid`、`Kanban`、`Gantt`、`Calendar`、`Gallery`、`FormDesigner`。创建时通过 `--config` JSON 设置可见字段:
|
||||
|
||||
```bash
|
||||
# --config JSON:可同时配置可见字段、筛选、排序和分组;主字段必须排第一
|
||||
dws aitable view create --base-id BASE_ID --table-id TABLE_ID \
|
||||
--view-type Grid --name "任务视图" \
|
||||
--config '{"visibleFieldIds":["fldPrimary","fldStatus","fldOwner"],"sort":[{"fieldId":"fldStatus","direction":"asc"}]}'
|
||||
```
|
||||
|
||||
创建阶段的 `--config` 是 JSON 对象,并且只接受以下 4 个 key:
|
||||
|
||||
| key | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `visibleFieldIds` | `string[]` | fieldId 数组,不接受字段名;至少一个,主字段必须排第一 |
|
||||
| `filter` | `object[]` | 筛选规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
| `sort` | `object[]` | 排序规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
| `group` | `object[]` | 分组规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
|
||||
描述使用独立的 `--desc '{"content":[]}'`;`description`、`fieldWidths`、`aggregate`、`kanbanCard`、`ganttTimebar`、`galleryCard` 等其他 key 会在调用服务端前被拒绝,并提示对应的 `view update` 子命令。
|
||||
|
||||
## 读取:view get <attr>
|
||||
|
||||
所有 `view get <attr>` 共用 `--base-id` / `--table-id` / `--view-id`,输出是该属性子块的 JSON(不存在时输出 `{}`)。viewType 不匹配会报错并指明应该选哪种视图。
|
||||
|
||||
```bash
|
||||
dws aitable view get card --view-id VIEW_ID --format json # Kanban / Gallery
|
||||
dws aitable view get timebar --view-id VIEW_ID --format json # Gantt
|
||||
dws aitable view get aggregate --view-id VIEW_ID --format json # Grid
|
||||
dws aitable view get filter --view-id VIEW_ID --format json # 所有
|
||||
dws aitable view get sort --view-id VIEW_ID --format json
|
||||
dws aitable view get group --view-id VIEW_ID --format json
|
||||
dws aitable view get visible-fields --view-id VIEW_ID --format json
|
||||
dws aitable view get field-widths --view-id VIEW_ID --format json # Grid
|
||||
```
|
||||
|
||||
## 写入:view update <attr>
|
||||
|
||||
所有 `view update <attr>` 共用 `--base-id` / `--table-id` / `--view-id`。
|
||||
**typed flag + `--json` 可混用**;冲突时 typed flag 优先并 stderr 提示。
|
||||
card / timebar / aggregate 三类写入有 viewType 校验(preflight 1 次 get_views)。
|
||||
|
||||
### view update card(Kanban / Gallery)
|
||||
|
||||
服务端按 viewType 分发到 `kanbanCard` 或 `galleryCard`。typed flag 共享。
|
||||
|
||||
| flag | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `--cover-field-id` | string | 封面字段 ID(Kanban / Gallery 通用),与 `--no-cover` 互斥 |
|
||||
| `--no-cover` | bool | 清除封面(等价 `coverFieldId="NONE"`) |
|
||||
| `--cover-resize-mode` | string | `cover` / `contain` / `stretch` |
|
||||
| `--hidden-field-title` | bool | 隐藏字段名标题(仅 Kanban 生效) |
|
||||
| `--cover-mode` | string | `none` / `auto` / `custom`(仅 Gallery 生效) |
|
||||
| `--display-field-name` | bool | 是否显示字段名(仅 Gallery 生效) |
|
||||
| `--json` | JSON | 完整 card 子块对象 |
|
||||
|
||||
```bash
|
||||
dws aitable view update card --view-id KANBAN_ID --cover-field-id fldAttachment --cover-resize-mode contain
|
||||
dws aitable view update card --view-id KANBAN_ID --no-cover
|
||||
dws aitable view update card --view-id GALLERY_ID --cover-mode auto
|
||||
dws aitable view update card --view-id GALLERY_ID --json '{"coverMode":"custom","coverFieldId":"fldX","displayFieldName":true}'
|
||||
```
|
||||
|
||||
### view update timebar(仅 Gantt)
|
||||
|
||||
| flag | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `--start-field` | string (date fieldId) | 开始日期字段 |
|
||||
| `--end-field` | string (date fieldId) | 结束日期字段 |
|
||||
| `--display-field-id` | string | 时间条上显示的标题字段 |
|
||||
| `--timeline-scale` | string | `year` / `quarter` / `month` / `weeks` |
|
||||
| `--color-configs` | JSON 数组 | 颜色配置数组(结构由下游协议定义;清空传 `[]`) |
|
||||
| `--official-holiday` | bool | 是否标注法定节假日 |
|
||||
| `--json` | JSON | 完整 ganttTimebar 子块 |
|
||||
|
||||
```bash
|
||||
dws aitable view update timebar --view-id GANTT_ID --start-field fldStart --end-field fldEnd --timeline-scale month
|
||||
dws aitable view update timebar --view-id GANTT_ID --official-holiday=true
|
||||
```
|
||||
|
||||
### view update aggregate(仅 Grid)
|
||||
|
||||
值是 `map[fieldId]→AggregateAction string`;传 null 清除某个字段聚合。
|
||||
|
||||
| flag | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `--field-id` | string | 配合 `--action` 设置**单字段**聚合 |
|
||||
| `--action` | string | `SUM`/`AVG`/`MAX`/`MIN`/`MEDIAN`/`RANGE`/`TOTAL`/`DISTINCT`/`EXIST`/`UN_EXIST`/`CHECKED`/`EARLIEST_DATE` 等(按字段类型可用) |
|
||||
| `--clear-field-id` | string (CSV) | 一/多个字段 ID,清除其聚合 |
|
||||
| `--json` | JSON | 完整 aggregate map |
|
||||
|
||||
```bash
|
||||
dws aitable view update aggregate --view-id GRID_ID --field-id fldX --action SUM
|
||||
dws aitable view update aggregate --view-id GRID_ID --clear-field-id fldA,fldB
|
||||
dws aitable view update aggregate --view-id GRID_ID --json '{"fldX":"AVG","fldY":null}'
|
||||
```
|
||||
|
||||
### view update field-widths(仅 Grid)
|
||||
|
||||
| flag | 类型 |
|
||||
|------|------|
|
||||
| `--field-id` + `--width` | string + int(单字段) |
|
||||
| `--json` | `{fldId: width, ...}` |
|
||||
|
||||
```bash
|
||||
dws aitable view update field-widths --view-id GRID_ID --field-id fldX --width 200
|
||||
dws aitable view update field-widths --view-id GRID_ID --json '{"fldA":120,"fldB":200}'
|
||||
```
|
||||
|
||||
### view update visible-fields(通用)
|
||||
|
||||
整组替换可见字段列表与顺序。`field get` 返回的第一个字段是系统行索引/主字段;无论它显示为 text 还是 primaryDoc,都必须保留在数组第一位,且不能隐藏。不要仅凭字段类型猜主字段。
|
||||
|
||||
> ⚠️ 注意:服务端**只接受 reorder,不接受真"隐藏字段"**——如果传入的列表比当前 columns 短,缺失的字段不会被隐藏。需要真正隐藏字段请到 AI 表格 Web UI。
|
||||
|
||||
| flag | 类型 |
|
||||
|------|------|
|
||||
| `--field-ids` | string (CSV) |
|
||||
| `--json` | string 数组 JSON(与 `--field-ids` 同传时 `--json` 优先) |
|
||||
|
||||
```bash
|
||||
dws aitable view update visible-fields --view-id VIEW_ID --field-ids fldPrimary,fldA,fldB
|
||||
dws aitable view update visible-fields --view-id VIEW_ID --json '["fldPrimary","fldA","fldB"]'
|
||||
```
|
||||
|
||||
### 列顺序最短闭环
|
||||
|
||||
用户说“客户名称最左、状态在金额前”时,不要用通用 `+view-update --config` 探索:
|
||||
|
||||
1. `dws aitable field get --base-id <B> --table-id <T> --format json` 取字段有序列表;第一个 fieldId 固定为数组第 1 项。目标 viewId 从真实上下文或 `view get` 返回中取得。
|
||||
2. `dws aitable view get visible-fields ...` 取当前完整列数组;必须保留全部现有字段,因为该接口只支持 reorder,不是真隐藏。
|
||||
3. 只重排目标:`[主字段, 客户名称, ..., 状态, 金额, ...]`,其他字段保持相对顺序;一次执行 `view update visible-fields`。
|
||||
4. 再次 `view get visible-fields`,数组完全一致才算完成。遇到 `PRIMARY_FIELD_CANNOT_BE_MOVED/HIDDEN` 立即停止,重新按步骤 1 构造一次;禁止继续猜排列。
|
||||
|
||||
“固定/冻结左侧列”与“放到最左边”不是同一操作。只有 Grid 支持冻结;若要冻结主字段后的目标列,需要冻结前 N 列(例如目标位于第 2 列则 count=2):
|
||||
|
||||
```bash
|
||||
dws aitable +view-set-frozen-cols --base-id <B> --table-id <T> --view-id <V> --count <N>
|
||||
dws aitable +view-get-frozen-cols --base-id <B> --table-id <T> --view-id <V>
|
||||
```
|
||||
|
||||
Kanban/Gallery 等视图只调整列顺序,不尝试冻结。
|
||||
|
||||
### view update filter / sort / group(通用,纯 --json)
|
||||
|
||||
```bash
|
||||
dws aitable view update filter --view-id VIEW_ID --json '[{"operator":"and","operands":[{"operator":"eq","operands":["fldX","value"]}]}]'
|
||||
dws aitable view update sort --view-id VIEW_ID --json '[{"fieldId":"fldX","direction":"asc"}]'
|
||||
dws aitable view update group --view-id VIEW_ID --json '[{"fieldId":"fldX","direction":"asc"}]'
|
||||
```
|
||||
|
||||
> filter/sort/group 入参格式与 `record query --filters`(对象格式)**不同**:view config 这边外层必须是数组。传对象 CLI 会自动 wrap,建议直接用数组。详见 [aitable-filter-sort.md](./aitable-filter-sort.md)。
|
||||
|
||||
### view update name(重命名)
|
||||
|
||||
```bash
|
||||
dws aitable view update name --view-id VIEW_ID --name "新视图名"
|
||||
```
|
||||
|
||||
等价于 `dws aitable view update --view-id VIEW_ID --name "新视图名"`,无 `config` 参数。
|
||||
|
||||
## 服务端字段速查(与 dws CLI 关系)
|
||||
|
||||
| dws 子命令 | 服务端 `update_view.config` 子键 | 服务端 Java 模型 |
|
||||
|---|---|---|
|
||||
| `view update card`(Kanban) | `kanbanCard` | `KanbanCardUpdateInput` |
|
||||
| `view update card`(Gallery) | `galleryCard` | `GalleryCardUpdateInput` |
|
||||
| `view update timebar` | `ganttTimebar` | `GanttTimebarUpdateInput` |
|
||||
| `view update aggregate` | `aggregate` | `Map<fieldId, AggregateAction>` |
|
||||
| `view update visible-fields` | `visibleFieldIds` | `List<String>` |
|
||||
| `view update filter / sort / group` | `filter` / `sort` / `group` | `List<Object>` |
|
||||
| `view update field-widths` | `fieldWidths` | `Map<String, Object>` |
|
||||
| `view update name` | (不在 config 内)`newViewName` 顶层 | — |
|
||||
|
||||
## 典型工作流
|
||||
|
||||
### 排查"Kanban 卡片为啥不显示封面"
|
||||
|
||||
```bash
|
||||
dws aitable view get card --view-id KANBAN_ID --format json
|
||||
# → 看 coverFieldId 是不是 "NONE" 或缺失;不是再看 coverResizeMode 是不是 contain 导致裁掉
|
||||
```
|
||||
|
||||
### 创建可用的 Gantt 视图(必须两步)
|
||||
|
||||
```bash
|
||||
# 第 1 步:创建 Gantt 视图
|
||||
dws aitable view create --base-id BASE_ID --table-id TABLE_ID \
|
||||
--view-type Gantt --name "项目甘特图" -f json
|
||||
# → 记录返回的 viewId
|
||||
|
||||
# 第 2 步(必须):绑定日期字段,否则视图为空
|
||||
dws aitable view update timebar --base-id BASE_ID --table-id TABLE_ID \
|
||||
--view-id VIEW_ID --start-field fldDateStart
|
||||
# 可选:加结束日期、标题字段、时间尺度
|
||||
# --end-field fldDateEnd --display-field-id fldName --timeline-scale month
|
||||
```
|
||||
|
||||
### 把 Gantt 时间轴改成季度尺度并加节假日
|
||||
|
||||
```bash
|
||||
dws aitable view update timebar --view-id GANTT_ID \
|
||||
--timeline-scale quarter --official-holiday=true
|
||||
```
|
||||
|
||||
### 用 dws 脚本批量替换 Kanban 封面字段
|
||||
|
||||
```bash
|
||||
for v in viw1 viw2 viw3; do
|
||||
dws aitable view update card --view-id $v --cover-field-id fldNewCover --cover-resize-mode cover --format json | jq .status
|
||||
done
|
||||
```
|
||||
|
||||
### 一次性多属性更新(仍走 legacy --config)
|
||||
|
||||
```bash
|
||||
dws aitable view update --view-id VIEW_ID --config '{
|
||||
"visibleFieldIds":["fldPrimary","fldA","fldB"],
|
||||
"filter":[{"operator":"and","operands":[]}],
|
||||
"kanbanCard":{"coverFieldId":"fldImg","coverResizeMode":"contain"}
|
||||
}'
|
||||
```
|
||||
@@ -0,0 +1,198 @@
|
||||
# 视图扩展操作(lock / frozen-cols / row-height / fill-color-rule / duplicate)
|
||||
|
||||
本文档讲 5 项视图操作命令:
|
||||
|
||||
- 锁定 / 解锁视图:`view lock` / `view get lock`
|
||||
- 冻结列:`view update frozen-cols` / `view get frozen-cols`
|
||||
- 行高:`view update row-height` / `view get row-height`
|
||||
- 数据高亮规则(条件填色):`view update fill-color-rule` / `view get fill-color-rule`
|
||||
- 复制视图:`view duplicate`
|
||||
|
||||
> **与 [aitable-view-config.md](./aitable-view-config.md) 的分工**:
|
||||
> - `aitable-view-config.md` 讲 `view get/update <attr>` 中 8 个属性:filter / sort / group / visible-fields / field-widths / aggregate / card / timebar。
|
||||
> - 本文档讲上面 5 项额外能力(包括 attr 形式的 frozen-cols / row-height / fill-color-rule,以及顶层独立的 lock / duplicate)。
|
||||
> 这 5 项**不能**通过 `view update --config '{...}'` 写入,必须用各自专属子命令。
|
||||
|
||||
## 命令矩阵
|
||||
|
||||
| 子命令 | 用途 | 必填参数 | 适用 viewType |
|
||||
|---|---|---|---|
|
||||
| `view lock [--off]` | 锁定(默认)/ 解锁视图 | `--base-id --table-id --view-id` | 全部 |
|
||||
| `view get lock` | 读取锁定状态 | `--base-id --table-id --view-id` | 全部 |
|
||||
| `view update frozen-cols --count N` | 冻结左侧 N 列(0 取消) | `--base-id --table-id --view-id --count` | Grid |
|
||||
| `view get frozen-cols` | 读取冻结列数 | `--base-id --table-id --view-id` | Grid |
|
||||
| `view update row-height --cell-height N` | 设置单元格高度(像素) | `--base-id --table-id --view-id --cell-height` | Grid |
|
||||
| `view get row-height` | 读取单元格高度 | `--base-id --table-id --view-id` | Grid |
|
||||
| `view update fill-color-rule --json '[...]'` | 全量覆盖条件填色规则 | `--base-id --table-id --view-id --json` | Grid |
|
||||
| `view get fill-color-rule` | 读取条件填色规则 | `--base-id --table-id --view-id` | 全部(其他视图返回 `[]`) |
|
||||
| `view duplicate [--new-name X]` | 复制视图 | `--base-id --table-id --view-id` | 全部 |
|
||||
|
||||
## 视图锁定 / 解锁
|
||||
|
||||
```bash
|
||||
# 锁定(默认)
|
||||
dws aitable view lock --view-id VIEW_ID
|
||||
|
||||
# 解锁
|
||||
dws aitable view lock --view-id VIEW_ID --off
|
||||
|
||||
# 查询当前是否锁定
|
||||
dws aitable view get lock --view-id VIEW_ID --format json
|
||||
# → {"data": {"baseId": ..., "tableId": ..., "viewId": ..., "locked": true|false}}
|
||||
```
|
||||
|
||||
锁定的视图禁止他人修改其配置(filter/sort/group/字段顺序等),但记录读写不受影响。锁定状态可重复 set,幂等。
|
||||
|
||||
## 冻结列(仅 Grid)
|
||||
|
||||
```bash
|
||||
# 冻结从首列起 1 列
|
||||
dws aitable view update frozen-cols --view-id VIEW_ID --count 1
|
||||
|
||||
# 取消冻结
|
||||
dws aitable view update frozen-cols --view-id VIEW_ID --count 0
|
||||
|
||||
# 查询当前冻结列数
|
||||
dws aitable view get frozen-cols --view-id VIEW_ID --format json
|
||||
# → {"data": {..., "count": 1}} count 为 null 表示视图未显式设置
|
||||
```
|
||||
|
||||
`--count` 必须 ≥ 0;负数会被拒绝。
|
||||
|
||||
## 行高(仅 Grid)
|
||||
|
||||
⚠️ **`--cell-height` 只接受 4 档枚举:32 / 56 / 88 / 128**(与前端 CELL_HEIGHTS 约定一致),其他值会被拒绝。默认值为 32。
|
||||
|
||||
```bash
|
||||
# 设置行高 — 推荐档位 32 / 56 / 88 / 128
|
||||
dws aitable view update row-height --view-id VIEW_ID --cell-height 56
|
||||
|
||||
# 查询当前行高
|
||||
dws aitable view get row-height --view-id VIEW_ID --format json
|
||||
# → {"data": {..., "cellHeight": 56}} cellHeight 为 null 表示视图未显式设置(前端按 32 渲染)
|
||||
```
|
||||
|
||||
## 数据高亮规则(条件填色,仅 Grid)
|
||||
|
||||
`view update fill-color-rule` **整组覆盖**,传 `--json '[]'` 清空所有规则。
|
||||
|
||||
### 规则结构
|
||||
|
||||
每条规则 JSON 结构:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"type": "cell" | "row" | "column" | "preRow",
|
||||
"formatFieldId": "fldX", // 命中规则后被高亮的字段(cell/column 类型有意义)
|
||||
"format": { "color": "firstLine5" }, // ⚠️ 必须用 FORMAT_COLORS 代号,不接受 hex
|
||||
"filters": [ // 当前固定 1 条
|
||||
{
|
||||
"fieldId": "fldX", // ⚠️ 不是 operands[0]
|
||||
"symbol": "GT", // ⚠️ 不是 operator;大写枚举
|
||||
"value": 100 // 部分 symbol(EXIST/UN_EXIST)不需要 value
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### color 合法值(FORMAT_COLORS)
|
||||
|
||||
`firstLine1` ~ `firstLine11`(共 11 档色码,对应前端调色盘)。**不接受 `#FF0000` 这种 hex**。
|
||||
|
||||
### filter.symbol 合法值
|
||||
|
||||
| 类别 | symbol |
|
||||
|---|---|
|
||||
| 数值/通用比较 | `GT` / `LT` / `GTE` / `LTE` / `EQ` / `NE` |
|
||||
| 文本 | `CONTAIN` / `EXCLUSIVE` |
|
||||
| 存在性(无 value) | `EXIST` / `UN_EXIST` |
|
||||
| 多选 / 集合 | `ALL_OF` / `ANY_OF` / `NONE_OF` |
|
||||
| 日期 | `BEFORE` / `AFTER` / `NOT_BEFORE` / `NOT_AFTER` / `DATE_EQ` / `FROM_NOW` / `DATE_BETWEEN` |
|
||||
|
||||
> **与 `record query --filters` / `view update filter` 的格式不同**:那两处用 `{operator, operands}` 结构;这里是 `{fieldId, symbol, value}`。不要混用。
|
||||
|
||||
### 典型用法
|
||||
|
||||
```bash
|
||||
# 1) 给金额字段 > 100 的单元格上 firstLine5 色
|
||||
dws aitable view update fill-color-rule --view-id GRID_ID --json '[
|
||||
{
|
||||
"type":"cell",
|
||||
"formatFieldId":"fldAmount",
|
||||
"format":{"color":"firstLine5"},
|
||||
"filters":[{"fieldId":"fldAmount","symbol":"GT","value":100}]
|
||||
}
|
||||
]'
|
||||
|
||||
# 2) 清空所有规则
|
||||
dws aitable view update fill-color-rule --view-id GRID_ID --json '[]'
|
||||
|
||||
# 3) 查询当前规则
|
||||
dws aitable view get fill-color-rule --view-id GRID_ID --format json
|
||||
# → {"data": [...]} 数组
|
||||
```
|
||||
|
||||
> **写入后请用 `view get fill-color-rule` 二次确认实际生效**,以读到的 `data` 数组为准。
|
||||
|
||||
## 复制视图
|
||||
|
||||
```bash
|
||||
# 显式命名
|
||||
dws aitable view duplicate --view-id VIEW_ID --new-name "副本视图"
|
||||
|
||||
# 系统自动命名(一般是 "原视图名 (副本)")
|
||||
dws aitable view duplicate --view-id VIEW_ID --format json
|
||||
# → {"data": {..., "viewId": "<新视图ID>", "sourceViewId": "<原视图ID>", "viewName": "..."}}
|
||||
```
|
||||
|
||||
复制会保留源视图的 filter / sort / group / visible-fields / card / timebar 等全部配置;新视图的 viewId 与源视图独立。
|
||||
|
||||
## 这些字段不能用 `view update --config '{...}'` 写
|
||||
|
||||
下列字段必须用对应的专属子命令;如果错塞进 `view update --config`,CLI 会在 stderr 提示对应子命令并拒绝把字段当 view config 处理:
|
||||
|
||||
| 错误用法 | 应改用 |
|
||||
|---|---|
|
||||
| `--config '{"flags":1}'` | `view lock` / `view lock --off` |
|
||||
| `--config '{"frozenColCount":2}'` | `view update frozen-cols --count N` |
|
||||
| `--config '{"cellHeight":56}'` | `view update row-height --cell-height N` |
|
||||
| `--config '{"rowHeightLevel":"tall"}'` | `view update row-height --cell-height N`(合法档位 32/56/88/128) |
|
||||
| `--config '{"conditionalFormats":[...]}'` | `view update fill-color-rule --json '[...]'` |
|
||||
|
||||
## 典型工作流
|
||||
|
||||
### 配置一个"金额超阈值红色高亮"的 Grid 视图
|
||||
|
||||
```bash
|
||||
BASE=baseXXX; TABLE=tblYYY; VIEW=viwGridZZ; FLD=fldAmount
|
||||
|
||||
# 1) 关键字段冻结,避免横向滚动看不到
|
||||
dws aitable view update frozen-cols --base-id $BASE --table-id $TABLE --view-id $VIEW --count 1
|
||||
|
||||
# 2) 加大行高让数据更易读
|
||||
dws aitable view update row-height --base-id $BASE --table-id $TABLE --view-id $VIEW --cell-height 56
|
||||
|
||||
# 3) 金额 > 100 的单元格上色
|
||||
dws aitable view update fill-color-rule --base-id $BASE --table-id $TABLE --view-id $VIEW --json "[
|
||||
{\"type\":\"cell\",\"formatFieldId\":\"$FLD\",\"format\":{\"color\":\"firstLine5\"},
|
||||
\"filters\":[{\"fieldId\":\"$FLD\",\"symbol\":\"GT\",\"value\":100}]}
|
||||
]"
|
||||
|
||||
# 4) 锁定视图,防止他人改坏
|
||||
dws aitable view lock --base-id $BASE --table-id $TABLE --view-id $VIEW
|
||||
```
|
||||
|
||||
### 复制一个"金牌客户"视图给销售团队
|
||||
|
||||
```bash
|
||||
dws aitable view duplicate --view-id viw_VIP_template --new-name "金牌客户-华东区"
|
||||
# 取返回里 data.viewId 进一步定制
|
||||
```
|
||||
|
||||
### 排查"我设置了高亮规则为啥没生效"
|
||||
|
||||
```bash
|
||||
# 看实际生效的 conditionalFormats
|
||||
dws aitable view get fill-color-rule --view-id VIEW_ID --format json
|
||||
# → 如果是 [] 说明上次写入失败;常见原因:color 用了 hex(必须 firstLineN)/ filter 用了 operator(必须 symbol)
|
||||
```
|
||||
@@ -0,0 +1,384 @@
|
||||
# workflow — 自动化工作流管理
|
||||
|
||||
创建 / 更新 / 启停 / 手动执行 / 查询执行历史 / 查看 / 列出 Base 下的自动化工作流("当 X 时自动 Y" 流程)。
|
||||
适用场景:用户要求创建自动化、修改流程、停掉或恢复流程、立即执行流程、核对执行结果或查询已有流程。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `workflow edit-example` | 获取工作流编辑文档与 workflow-dsl/v1 示例 |
|
||||
| `workflow create` | 创建并发布自动化工作流 |
|
||||
| `workflow update` | 更新并发布已有自动化工作流 |
|
||||
| `workflow list` | 列出 Base 下所有工作流(含状态/创建人/最后修改时间),支持分页 |
|
||||
| `workflow get` | 获取单个工作流详情(含 flowSchema 完整节点定义) |
|
||||
| `workflow enable` | 启用指定工作流(按配置的触发条件自动执行) |
|
||||
| `workflow disable` | 禁用指定工作流(高危,建议 `--yes` 二次确认) |
|
||||
| `workflow run` | 立即执行指定工作流(会产生真实副作用,需确认) |
|
||||
| `workflow history` | 按状态、时间和分页条件查询工作流执行历史 |
|
||||
|
||||
> `workflow edit-example` 无参数;其他子命令的 `--base-id` 必填(可用隐藏别名 `--base`)。
|
||||
|
||||
## DSL 入参格式与最小 Demo
|
||||
|
||||
先运行 `workflow edit-example` 获取服务端提供的最新编辑文档和示例。`workflow create/update` 的 `--dsl` 接收钉钉 AI 表格 `workflow-dsl/v1` JSON object。
|
||||
|
||||
复杂工作流还应注意:
|
||||
|
||||
1. 使用 `workflow edit-example` 获取最新 DSL Guide、结构和示例。
|
||||
2. 涉及数据表、字段或视图的节点,先用 `table get` / `field get` / `view list` 确认真实 `sheetId`、`fieldId`、`viewId`。
|
||||
3. create 和 update 都提交完整的 workflow-dsl/v1 JSON object,并检查所有 `next`、`loopEntry`、branch `to` 和 ref。
|
||||
|
||||
以下 Demo 表示“每天 09:00 触发,并向 Base 所有者发送消息”,不依赖数据表、字段或视图 ID:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "workflow-dsl/v1",
|
||||
"name": "每日提醒",
|
||||
"description": "可选说明",
|
||||
"trigger": "start",
|
||||
"steps": {
|
||||
"start": {
|
||||
"type": "Scheduled",
|
||||
"next": "send",
|
||||
"data": {
|
||||
"mode": "daily",
|
||||
"time": "09:00",
|
||||
"timezone": "GMT+08:00"
|
||||
}
|
||||
},
|
||||
"send": {
|
||||
"type": "SendMessage",
|
||||
"data": {
|
||||
"title": "定时任务已触发",
|
||||
"to": {
|
||||
"users": [{"ref": "$.system_node.ownerUserId"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
将上述 JSON 保存为 `workflow.json` 后创建工作流:
|
||||
|
||||
```bash
|
||||
dws aitable workflow create \
|
||||
--base-id BASE_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
```
|
||||
|
||||
保存创建结果中的 `data.flowId`。更新时修改 `workflow.json` 中的完整目标定义,例如修改 `name`、`description` 或消息 `title`,然后调用:
|
||||
|
||||
```bash
|
||||
dws aitable workflow update \
|
||||
--base-id BASE_ID \
|
||||
--workflow-id FLOW_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
```
|
||||
|
||||
create 和 update 都必须同时满足 `status=success`、`data.valid=true`、`data.issues=[]` 才表示发布成功;update 返回的 `data.flowId` 应与传入的 `FLOW_ID` 一致。以上仅为最小 Demo,复杂节点的 `type` 和 `data` 结构以钉钉 AI 表格 MCP 最新 DSL 文档为准。
|
||||
|
||||
## 命令详情
|
||||
|
||||
### workflow edit-example — 获取编辑文档与示例
|
||||
|
||||
```bash
|
||||
dws aitable workflow edit-example --format json
|
||||
```
|
||||
|
||||
该命令无业务参数,调用 `aitable/edit_workflow_example` 返回服务端提供的工作流编辑文档和示例。创建或更新复杂工作流前优先调用它,避免依赖可能过期的本地 DSL 结构。
|
||||
|
||||
### workflow create — 创建并发布工作流
|
||||
|
||||
```bash
|
||||
# 大 DSL 推荐从文件读取
|
||||
dws aitable workflow create \
|
||||
--base-id BASE_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
|
||||
# 也支持 stdin
|
||||
cat workflow.json | dws aitable workflow create --base-id BASE_ID --dsl - --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 所属 Base ID |
|
||||
| `--dsl` | 是 | workflow-dsl/v1 JSON object;支持内联 JSON、`@filepath`、`-` stdin |
|
||||
| `--locale` | 否 | 请求语言,如 `zh-CN` / `zh_CN` |
|
||||
|
||||
创建成功返回发布结果:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"valid": true,
|
||||
"flowId": "G-FLOW-XXXXXX",
|
||||
"flowSchema": {},
|
||||
"stepNodeIds": {},
|
||||
"referenceMap": {},
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
关键语义:
|
||||
|
||||
- `create` 非幂等,CLI 不自动重试。若网络中断导致结果不确定,先 `workflow list` 按名称确认是否已创建,再决定是否重试。
|
||||
- `status=success` 只说明 workflow-edit 正常返回;如果 `data.valid=false`,仍表示 DSL 未通过校验或发布,必须读取 `issues` 修正。
|
||||
- 创建并发布后,用 `workflow list` 确认 `status`;需要运行但状态为 `STOP` 时再调用 `workflow enable`。
|
||||
|
||||
### workflow update — 更新并发布工作流
|
||||
|
||||
```bash
|
||||
# 先留底现有详情,再提交完整目标 DSL
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json > /tmp/workflow-backup.json
|
||||
dws aitable workflow update \
|
||||
--base-id BASE_ID \
|
||||
--workflow-id WORKFLOW_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh_CN \
|
||||
--format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 所属 Base ID |
|
||||
| `--workflow-id` | 是 | 目标工作流 ID,对应 list 的 `flowId` |
|
||||
| `--dsl` | 是 | 完整目标 workflow-dsl/v1 JSON object;支持内联、`@filepath`、`-` stdin |
|
||||
| `--locale` | 否 | 请求语言,如 `zh-CN` / `zh_CN` |
|
||||
|
||||
返回结构与 create 相同,成功时 `flowId` 应为目标工作流。update 使用 AI 表格瞬态错误重试;最终仍必须检查 `data.valid` 和 `issues`,并用 `workflow get/list` 验证发布结果与运行状态。
|
||||
|
||||
### workflow run — 立即执行工作流
|
||||
|
||||
```bash
|
||||
# 记录类触发器
|
||||
dws aitable workflow run --base-id BASE_ID --workflow-id WORKFLOW_ID \
|
||||
--table-id TABLE_ID --record-ids RECORD_ID_1,RECORD_ID_2
|
||||
|
||||
# 定时触发器不传 table-id / record-ids
|
||||
dws aitable workflow run --base-id BASE_ID --workflow-id WORKFLOW_ID
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 所属 Base ID |
|
||||
| `--workflow-id` | 是 | 目标工作流 ID |
|
||||
| `--table-id` | 条件必填 | 记录类触发器绑定的数据表;必须与触发器配置一致 |
|
||||
| `--record-ids` | 条件必填 | 记录类触发器的记录 ID,1–5 个、逗号分隔且不可重复 |
|
||||
|
||||
`run` 启动真实异步执行,工作流中的发消息、写记录等动作会实际发生;执行前必须取得用户确认。返回项中的 `executionId` 是本次执行标识,可与 `workflow history` 项目的 `instanceId` 匹配。网络结果不确定时不要直接重复执行,先按该标识查询历史。
|
||||
|
||||
### workflow history — 查询执行历史
|
||||
|
||||
```bash
|
||||
dws aitable workflow history --base-id BASE_ID --workflow-id WORKFLOW_ID \
|
||||
--status failed --after-time 1786000000000 --before-time 1787000000000 \
|
||||
--page 0 --size 50
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填 |
|
||||
| `--workflow-id` | 必填;CLI 会映射为 MCP 的 `flowId` |
|
||||
| `--status` | 可选:`success` / `failed` / `running` / `break` / `untrigger` |
|
||||
| `--after-time` | 可选,Unix 毫秒开始时间 |
|
||||
| `--before-time` | 可选,Unix 毫秒结束时间;与 after-time 同传时必须更大 |
|
||||
| `--page` | 可选,从 0 开始,默认 0 |
|
||||
| `--size` | 可选,默认 20,范围 `[1, 100]` |
|
||||
|
||||
返回 `totalCount` 和 `list`。`running` 是非终态;`success`、`failed`、`break`、`untrigger` 是终态。
|
||||
|
||||
### workflow list — 列出工作流
|
||||
|
||||
```bash
|
||||
dws aitable workflow list --base-id BASE_ID --format json
|
||||
dws aitable workflow list --base-id BASE_ID --limit 50 --offset 100
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填 |
|
||||
| `--limit` | 可选,分页大小 `[1, 100]`,不传走服务端默认 20 |
|
||||
| `--offset` | 可选,分页偏移量 `>= 0`,不传走服务端默认 0 |
|
||||
|
||||
返回结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"flowId": "G-FLOW-XXXXXX", // ★ 注意字段名是 flowId
|
||||
"name": "流程1",
|
||||
"description": "当创建记录时,就更新记录",
|
||||
"status": "RUNNING", // RUNNING / STOP
|
||||
"creatorStaffId": "281493",
|
||||
"lastModifier": { "name": "李普阳", "staffId": "281493" },
|
||||
"gmtModified": 1780318540000,
|
||||
"versionId": "G-FLOW-VER-XXXXXX",
|
||||
"icons": ["..."], // 触发器+动作的图标
|
||||
"isSubFlow": false,
|
||||
"opPermissions": { "canEdit": true }
|
||||
}
|
||||
],
|
||||
"recordCount": 1, // Base 下总数
|
||||
"runningCount": 1 // RUNNING 状态的数量
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 标识字段服务端在 `list` 里叫 **`flowId`**,但在 `enable` / `disable` 出参里叫 **`workflowId`**。CLI `--workflow-id` 传任一即可(同值)。
|
||||
- `status` 是字符串枚举:`RUNNING`(启用中)/ `STOP`(已禁用),**不是** boolean。
|
||||
- `runningCount` 是当前 Base 下 status=RUNNING 的工作流数,方便快速判断「有几个流程在跑」。
|
||||
|
||||
### workflow get — 获取单个工作流详情
|
||||
|
||||
```bash
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填 |
|
||||
| `--workflow-id` | 必填,对应 list 出参里的 `flowId` |
|
||||
|
||||
返回完整工作流配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"name": "流程1",
|
||||
"namespace": "...",
|
||||
"status": "RUNNING",
|
||||
"versionId": "G-FLOW-VER-XXXXXX",
|
||||
"versionNo": 14,
|
||||
"versionStatus": "...",
|
||||
"accessor": {...}, // 访问者信息
|
||||
"corpId": "...",
|
||||
"flowAttribute": {...}, // 流程顶层属性
|
||||
"flowSchema": {...}, // ★ 流程节点定义(触发器/动作/分支等)
|
||||
"gmtCreate": 1780317804000,
|
||||
"gmtModified": 1780318540000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`flowSchema` 是完整的节点 DAG,结构因流程而异(条件触发器 vs 定时触发器、单分支 vs 多分支等)。agent 应按需读取关心字段,不要试图建静态 schema。
|
||||
|
||||
### workflow enable — 启用工作流
|
||||
|
||||
```bash
|
||||
dws aitable workflow enable --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
```
|
||||
|
||||
返回 `{workflowId, enabled: true}` —— **`enabled: true` 是动作确认,不是当前状态查询**。要确认真启用了,必须再 `workflow list` 看 `status` 是否变成 `"RUNNING"` 或 `runningCount` 是否加 1。
|
||||
|
||||
### workflow disable — 禁用工作流(高危)
|
||||
|
||||
```bash
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id WORKFLOW_ID --yes --format json
|
||||
```
|
||||
|
||||
返回 `{workflowId, disabled: true}` —— 同样是动作确认。禁用后该工作流不再自动触发。
|
||||
|
||||
**风险**:直接影响业务自动化(如停掉「记录创建后自动发通知」会让通知断流)。建议:
|
||||
- 操作前先 `workflow get` 留底当前配置
|
||||
- 脚本场景显式传 `--yes`;交互场景让用户在 prompt 中再次确认
|
||||
|
||||
## 能力边界
|
||||
|
||||
| 能力 | 状态 |
|
||||
|------|------|
|
||||
| 新建工作流 | ✅ 创建并发布 |
|
||||
| 修改工作流配置 | ✅ 更新并发布 |
|
||||
| 列出工作流 | ✅ |
|
||||
| 看工作流详情(含 flowSchema) | ✅ |
|
||||
| 启用/禁用 | ✅ |
|
||||
| 查看运行历史/执行日志 | ✅ `workflow history` |
|
||||
| 手动触发/单次运行 | ✅ `workflow run`(需确认) |
|
||||
| 删除工作流 | ❌ 暂未开放 |
|
||||
|
||||
## 错误码速查
|
||||
|
||||
| 场景 | code | type | 备注 |
|
||||
|------|------|------|------|
|
||||
| create/update 返回 `valid=false` | — | success envelope | 读取 `data.issues` 修正 DSL,不能当作发布成功 |
|
||||
| create 下游失败 | `CREATE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | create 不自动重试;先 list 排查是否已创建 |
|
||||
| update 下游失败 | `UPDATE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | update 会重试瞬态错误,最终失败时保留 DSL 和 workflowId 排查 |
|
||||
| `workflow-id` 不存在调 get | `GET_WORKFLOW_ERROR` | `SYSTEM_ERROR` | message 可能为 null,先 `workflow list` 核对 ID |
|
||||
| `workflow-id` 不存在调 enable | `ENABLE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | message 含 "场域中不存在该 namespace" |
|
||||
| `workflow-id` 不存在调 disable | `DISABLE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | 同上 |
|
||||
| `--limit` < 1 或 > 100 | (CLI 层拦截) | — | `--limit 必须在 [1, 100] 范围内,got N` |
|
||||
| `--offset` < 0 | (CLI 层拦截) | — | `--offset 必须 >= 0,got N` |
|
||||
|
||||
> 拿到 `*_WORKFLOW_ERROR / SYSTEM_ERROR` 时,先 `workflow list` 自查目标 ID 是否还存在、是否在当前 Base 下。
|
||||
|
||||
## 典型工作流
|
||||
|
||||
### 创建并确认一个工作流
|
||||
|
||||
```bash
|
||||
# 1. 按本文 DSL Demo 生成 /tmp/workflow.json
|
||||
dws aitable workflow create --base-id BASE_ID --dsl @/tmp/workflow.json --locale zh-CN --format json \
|
||||
| tee /tmp/workflow-result.json
|
||||
|
||||
# 2. valid 必须为 true;保存 flowId
|
||||
jq '{valid: .data.valid, flowId: .data.flowId, issues: .data.issues}' /tmp/workflow-result.json
|
||||
|
||||
# 3. 确认运行状态,需要时显式启用
|
||||
FLOW_ID=$(jq -r '.data.flowId' /tmp/workflow-result.json)
|
||||
dws aitable workflow list --base-id BASE_ID --format json \
|
||||
| jq --arg id "$FLOW_ID" '.data.list[] | select(.flowId == $id) | {flowId, name, status}'
|
||||
```
|
||||
|
||||
### 看看 Base 里有哪些自动化在跑
|
||||
|
||||
```bash
|
||||
dws aitable workflow list --base-id BASE_ID --format json | jq '.data | {total: .recordCount, running: .runningCount, items: .list | map({name, status, flowId})}'
|
||||
```
|
||||
|
||||
### 临时停掉某个流程做调试
|
||||
|
||||
```bash
|
||||
# 1. 留底当前状态
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json > /tmp/wf-backup.json
|
||||
|
||||
# 2. 禁用
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id WORKFLOW_ID --yes --format json
|
||||
|
||||
# 3. 调试做完后重启
|
||||
dws aitable workflow enable --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
|
||||
# 4. 确认 status=RUNNING
|
||||
dws aitable workflow list --base-id BASE_ID --format json | jq '.data.list[] | select(.flowId == "WORKFLOW_ID") | .status'
|
||||
```
|
||||
|
||||
### 批量关掉某个 Base 下所有 workflow(调试 / 迁移前清场)
|
||||
|
||||
```bash
|
||||
for WF in $(dws aitable workflow list --base-id BASE_ID --limit 100 --format json | jq -r '.data.list[] | select(.status == "RUNNING") | .flowId'); do
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id "$WF" --yes --format json | jq .status
|
||||
done
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `--workflow-id` 接受的就是 `list` 返回里的 `flowId`(同值,CLI 屏蔽了服务端字段名差异)。
|
||||
- create / update 的 `--dsl` 必须是 JSON object,不能传数组、字符串化的二次 JSON 或 FlowSchema。
|
||||
- 本文 Demo 可直接用于最小定时消息工作流;复杂节点应以钉钉 AI 表格 MCP 最新 DSL 文档为准。
|
||||
- `status=success` 且 `data.valid=false` 仍是 DSL 校验失败;`issues` 才是下一步修复依据。
|
||||
- create 不自动重试;update 仅对网络/5xx/`retryable:true` 瞬态错误自动重试。
|
||||
- enable / disable 出参里的 `enabled` / `disabled` 是 **动作确认 flag**,不是当前状态字段。要确认真生效请走 `workflow list` 查 `status`。
|
||||
- `workflow get` 的 `flowSchema` 结构随触发器/动作类型变化,不要假设固定字段。
|
||||
- `workflow run` 不自动重试;结果不确定时用 `workflow history` 按 executionId / instanceId 核对。
|
||||
- 删除工作流当前仍未开放。
|
||||
Reference in New Issue
Block a user