超大量更新

This commit is contained in:
zeaslity
2026-04-29 09:46:36 +08:00
parent ed945abdf1
commit e7c301023c
349 changed files with 83923 additions and 560 deletions

View File

@@ -0,0 +1,39 @@
### V1
你是一名优秀的飞书多维表格开发专家,你非常善于阅读并搜集在线的资料,并根据资料完成开发工作。
请你阅读 [飞书多维表格开发文档](https://open.feishu.cn/document/server-docs/docs/bitable-v1/bitable-overview) 将飞书多维表格的开发文档,包含所有子页面,整理成一份完整的参考文档.
提示:飞书文档页面存在复制页面的button, 可以直接复制为Markdown格式提供给大模型参考,请熟练使用
注意:
1. 先拉取完整的开发文档,注意不同子页面之间的关联关系
2. 后期我会将此部分开发文档制作为AgentSkills
3. 将完整的文档输出到 18-基础架构及交付部署特战队\10-飞书多维表格 目录下
### V2
你完成的很好
1. 现在实现的参考文档中,存在大量的在线链接的内容,我希望的是可以完全离线使用的完整文档
2. 请你将在线内容全部下载到本地,并整理成一份完整的参考文档
3. 需要将Go SDK的示例代码也一并下载一份
4. 请研究[飞书API参考文档](https://feishu.apifox.cn/) 将GolangSDK调用的使用说明 也一并写入文档中
请你按照上面的要求,重新生成一份完整的参考文档v2版本
### V3
请你详细的阅读飞书的官方文档,完成如下要求的深度研究
1. 飞书能够实现的功能有哪些
2. 飞书API接口实现的功能有哪些
3. 飞书GO SDK能够实现的功能有哪些
4. 飞书所有的功能是否都支持API接口修改
5. 飞书能否作为项目协同的前端页面平台
6. 飞书免费版能否畅快的使用,不受限制
### V4
使用dds-to-skill技能你现在需要根据 [飞书多维表格开发文档-完整参考-v2.md](18-基础架构及交付部署特战队\10-飞书多维表格\飞书多维表格开发文档-完整参考-v2.md) 为大模型制作一份可以参考使用的AgentSkills
要求如下:
1. 输出目录为 18-基础架构及交付部署特战队\10-飞书多维表格
2. 需要按照AgentSkills的渐进式暴露原则,实现文档的转换

View File

@@ -0,0 +1,20 @@
# 全局自检结果
## 结构完整性
- ✅ S1 PASS: 系统级 Skill = 1
- ✅ S2 PASS: 模块级 Skills = 6
- ✅ S3 PASS: 横切 Skills = 4>=3
- ✅ S4 PASS: 所有 Skill 含 scripts/verify.sh
- ✅ S5 PASS: 已执行 11 个 verify.sh全部通过
## 内容质量
- ✅ C1 PASS: 所有 SKILL.md < 500
- C2 PASS: 所有 SKILL.md Plan/Verify/Execute/Pitfalls
- C3 PASS: 所有 SKILL.md 动态注入命令 >= 2
## Reference 质量
- ✅ R1 PASS: 所有 Skill reference 含 DDS-Section 与 DDS-Lines
- ✅ R2 PASS: 模块级 Skill 均含 API + 安全/依赖 + [TBD] 缺失标注文件
## 总计: 10 PASS / 0 FAIL

View File

@@ -0,0 +1,58 @@
# 飞书多维表格 AgentSkillsv2 离线文档转换产物)
本套 Skills 基于 `飞书多维表格开发文档-完整参考-v2.md` 生成,遵循「渐进式暴露」:
1. 先进入系统级 Skill 判断变更范围。
2. 再进入对应模块级 Skill 执行实现/改造。
3. 叠加横切 Skill 处理契约、鉴权、并发、SDK 接入。
4. 最后下钻 `reference/` 读取可溯源设计细节(含 DDS 章节与行号)。
## Skill 清单(最终命名)
### 系统级1
- `developing-feishu-bitable-system`
### 模块级6
- `developing-bitable-app-metadata`
- `developing-bitable-table-view`
- `developing-bitable-record`
- `developing-bitable-field`
- `developing-bitable-role-member`
- `developing-bitable-event-callback`
### 横切4
- `designing-bitable-contracts`
- `implementing-bitable-auth-access`
- `managing-bitable-write-concurrency`
- `implementing-bitable-go-sdk`
## 命名候选与选择理由
| Skill | 候选名 | 选择 | 理由 |
|---|---|---|---|
| 系统级 | `developing-bitable-system` / `developing-feishu-bitable-system` / `developing-lark-bitable-system` | `developing-feishu-bitable-system` | 同时保留平台域feishu和产品域bitable检索命中更稳定。 |
| App | `developing-bitable-app` / `developing-bitable-app-metadata` / `developing-bitable-app-core` | `developing-bitable-app-metadata` | 文档对 App 主要是元数据与高级权限开关,`metadata` 语义更准确。 |
| Table/View | `developing-bitable-table` / `developing-bitable-view` / `developing-bitable-table-view` | `developing-bitable-table-view` | 视图严格依附数据表,合并后可减少重复规则。 |
| Record | `developing-bitable-record` / `developing-bitable-row` / `developing-bitable-record-crud` | `developing-bitable-record` | 与 OpenAPI 资源命名一致,便于映射接口。 |
| Field | `developing-bitable-field` / `developing-bitable-schema-field` / `developing-bitable-column` | `developing-bitable-field` | 与文档“字段 Field”章节一致。 |
| Role/Member | `developing-bitable-role` / `developing-bitable-role-member` / `developing-bitable-advanced-permission` | `developing-bitable-role-member` | 将角色与协作者放在同一模块,贴合高级权限操作闭环。 |
| Event/Callback | `developing-bitable-event` / `developing-bitable-event-callback` / `developing-bitable-webhook` | `developing-bitable-event-callback` | 同时覆盖事件与回调两条接入路径。 |
| 契约 | `designing-bitable-contracts` / `designing-bitable-openapi` / `managing-bitable-contracts` | `designing-bitable-contracts` | 以设计导向统一 API/错误码/资源 ID 契约。 |
| 鉴权 | `implementing-bitable-auth` / `implementing-bitable-auth-access` / `managing-bitable-token-auth` | `implementing-bitable-auth-access` | 同时包含 token 与权限模型。 |
| 并发 | `managing-bitable-concurrency` / `managing-bitable-write-concurrency` / `implementing-bitable-retry` | `managing-bitable-write-concurrency` | 明确聚焦写操作并发与幂等。 |
| Go SDK | `implementing-bitable-sdk` / `implementing-bitable-go-sdk` / `developing-bitable-sdk-integration` | `implementing-bitable-go-sdk` | 技术栈指向清晰,避免多语言混淆。 |
## 目录约定
每个 Skill 目录均包含:
- `SKILL.md`
- `reference/`(按章节分层,含 `DDS-Section` + `DDS-Lines`
- `examples/skeleton.md`
- `scripts/verify.sh`
## 渐进式使用建议
1. 先读 `developing-feishu-bitable-system/SKILL.md`
2. 根据变更资源进入对应模块 Skill。
3. 若涉及跨模块约束,再叠加横切 Skill。
4. 编码或审查时仅按需展开目标 `reference/*.md`,避免一次性加载全量文档。

View File

@@ -0,0 +1,79 @@
---
name: designing-bitable-contracts
description: 统一飞书多维表格 API 契约设计与审查Guides cross-module contract design for Feishu Bitable。包含资源 ID 规范、OpenAPI 路径方法、请求响应字段与错误码一致性。触发场景 Trigger: 新增接口、变更字段、排查上下游契约不一致、做跨模块发布评审。关键词 Keywords: contract, openapi, path, error code, app_token, table_id, bitable。
argument-hint: "<scope> <change> - e.g., 'record api add field', 'role api error-code align'"
allowed-tools:
- Read
- Glob
- Grep
- Bash
---
# Designing Bitable Contracts
用于跨模块统一 API 契约,重点防止路径、参数、错误码与资源 ID 在不同模块实现中产生漂移。
## Quick Context
```bash
# 汇总 Bitable 相关接口定义
!`rg -n "OpenAPI Specification|/bitable/v1/apps|错误码|requestBody|responses" -S . | head -n 150`
# 扫描资源 ID 使用位置
!`rg -n "app_token|table_id|view_id|record_id|field_id|role_id|member_id" -S . | head -n 150`
```
## Plan
### 产物清单
- [ ] 资源 ID 与路径映射表
- [ ] 请求/响应字段差异清单
- [ ] 错误码冲突清单
- [ ] 兼容性评审结论
### 决策点
1. 变更是向后兼容还是破坏性变更?
2. 是否需要引入新错误码或复用现有错误码?
3. 是否影响多模块消费方SDK、回调、下游服务
## Verify
### 资源一致性
- [ ] 资源 ID 语义统一,见 `reference/01-resource-ids/dependencies.md`
- [ ] 路径层级与资源归属无冲突
### OpenAPI 一致性
- [ ] 方法、路径、参数、响应字段对齐 `reference/02-openapi-contract/apis.md`
- [ ] 请求体可选项与默认语义明确
### 错误模型一致性
- [ ] 同错误码语义一致,见 `reference/03-error-model/apis.md`
- [ ] 失败场景有明确排查建议
## Execute
### 1. 建立契约基线
1. 汇总当前模块接口矩阵。
2. 锁定资源 ID 与路径层级。
### 2. 比较差异
1. 对请求字段做新增/删除/语义变化对比。
2. 对响应字段做兼容性对比。
3. 对错误码做含义冲突检查。
### 3. 输出决策
1. 明确兼容级别(兼容/有条件兼容/不兼容)。
2. 给出迁移步骤与回滚策略。
## Pitfalls
1. **同一资源使用多个命名**:如 token/id 混用导致歧义,见 `reference/01-resource-ids/dependencies.md`
2. **只改请求不改响应示例**:上下游生成代码不一致,见 `reference/02-openapi-contract/apis.md`
3. **错误码复用语义冲突**:排障不可控,见 `reference/03-error-model/apis.md`
## Related References
- `reference/01-resource-ids/dependencies.md`
- `reference/02-openapi-contract/apis.md`
- `reference/03-error-model/apis.md`
- `reference/04-compatibility/state-machine.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,19 @@
## 资源 ID 规范
- DDS-Section: 接入指南-参数说明 / A.1 概述
- DDS-Lines: L399-L468, L111-L257
### Extract
| 资源 | ID 字段 |
|---|---|
| App | `app_token` |
| Table | `table_id` |
| View | `view_id` |
| Record | `record_id` |
| Field | `field_id` |
| Role | `role_id` |
| Member | `member_id` |
规则ID 应与路径段一一对应,禁止跨资源复用。

View File

@@ -0,0 +1,17 @@
## OpenAPI 契约骨架
- DDS-Section: A.10~A.49 OpenAPI Specification
- DDS-Lines: L1938-L16470
### Extract
- 路径命名统一前缀:`/bitable/v1/apps/{app_token}`
- 子资源按层次展开:`tables -> views/records/fields``roles -> members`
- 请求体和响应体均以标准 JSON schema 描述,含 code/msg/data 包装。
## 字段级审查要点
- 请求字段是否含示例值与必填标注。
- 响应字段是否覆盖新增字段。
- 分页字段 `page_token`/`has_more` 是否一致。

View File

@@ -0,0 +1,16 @@
## 错误码模型
- DDS-Section: 各 OpenAPI 的错误码章节
- DDS-Lines: L1957+, L2239+, L2461+, L4723+, L7594+
### Extract
| 类别 | 示例 |
|---|---|
| 参数错误 | `WrongRequestJson`, `WrongRequestBody`, `WrongFieldId` |
| 资源错误 | `WrongBaseToken`, `app_token 不存在` |
| 并发/处理冲突 | `OperationTypeError`、并发写限制 |
| 幂等冲突 | `client token and try again` |
要求:同错误码在不同模块中保持相同语义与排查动作。

View File

@@ -0,0 +1,15 @@
## 版本与兼容策略
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未给出正式的 API 版本升级策略deprecate 生命周期、灰度窗口、双写方案)。
### 最小补充信息清单
1. 向后兼容判定标准
2. 破坏性变更发布流程
3. 旧版本下线时间线

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,82 @@
---
name: developing-bitable-app-metadata
description: 指导飞书多维表格 App 元数据模块开发Guides Bitable app metadata module development。包含获取/更新元数据、高级权限开关、参数与错误码校验。触发场景 Trigger: 新增或修改 app 级配置、切换 advanced permission、排查 app_token 级接口失败。关键词 Keywords: bitable, app, metadata, app_token, advanced permission, 高级权限。
argument-hint: "<action> <app_token> - e.g., 'get metadata appbxxx', 'update app name+permission appbxxx'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable App Metadata
用于处理 `app_token` 级别能力:读取/更新多维表格元数据与高级权限开关,确保调用身份、前置权限、错误码处理一致。
## Quick Context
```bash
# 定位 app 级接口定义与调用处
!`rg -n "bitable/v1/apps/\{app_token\}|app/update|app/get" -S . | head -n 80`
# 定位高级权限相关逻辑
!`rg -n "advanced.*permission|roles|OperationTypeError|app_token" -S . | head -n 80`
```
## Plan
### 产物清单
- [ ] App 元数据读取与更新调用点
- [ ] 参数映射(`app_token`, `name`, `is_advanced`
- [ ] 错误码与重试策略
- [ ] 权限前置检查
### 决策点
1. 本次更新是仅改名称,还是同时改高级权限开关?
2. 是否接受“非原子更新”带来的部分成功状态?
3. 调用身份选择用户态还是应用态 token
## Verify
### API 契约
- [ ] 路径与方法与 `reference/02-app-openapi/apis.md` 一致
- [ ] 请求体字段只包含本次所需字段,避免误改
### 权限与鉴权
- [ ] token 身份与权限范围匹配,见 `reference/03-security/security-model.md`
- [ ] 高级权限开关后续 Role/Member 流程已准备
### 风险控制
- [ ] 已处理接口“先改名后开关权限”的部分成功场景
- [ ]`app_token` 错误、无访问权限、未开启高级权限错误有明确分支
## Execute
### 1. 读取当前状态
1. 调用 `GET /bitable/v1/apps/{app_token}`,确认当前名称与权限开关。
2. 记录变更前快照,作为回滚基线。
### 2. 执行更新
1. 调用 `PUT /bitable/v1/apps/{app_token}`
2. 若同时变更多项,先按接口语义评估“部分成功”影响。
3. 对已知可重试错误(如权限生效延迟)实施有限重试。
### 3. 验证结果
1. 再次读取元数据核对结果。
2. 若开启高级权限,立即验证 Role/Member 接口是否可用。
## Pitfalls
1. **把元数据更新当作原子事务**:接口本身可能部分成功,先读 `reference/02-app-openapi/apis.md`
2. **开启高级权限后立即操作角色失败**:存在生效延迟,见 `reference/03-security/security-model.md`
3. **调用身份不匹配**:用户态与应用态 token 混用会造成权限异常,见 `reference/03-security/security-model.md`
4. **遗漏 app_token 来源校验**URL/块信息提取错误会导致全链路失败,见 `reference/01-resource-overview/dependencies.md`
## Related References
- `reference/01-resource-overview/dependencies.md`
- `reference/02-app-openapi/apis.md`
- `reference/03-security/security-model.md`
- `reference/04-db-schema/db-schema.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,22 @@
## App 资源定位与依赖
- DDS-Section: 资源:多维表格应用 App / 接入指南-参数说明 app_token
- DDS-Lines: L111-L128, L399-L423
### Extract
| 项 | 内容 |
|---|---|
| 主标识 | `app_token` |
| 获取方式 | 多维表格 URL、文档 block token 拆分、相关 API 返回 |
| 下游依赖 | Table/View/Record/Field/Role/Member 均依赖 `app_token` |
## 调用链路
- DDS-Section: 接入指南-内容
- DDS-Lines: L294-L303
### Extract
`App -> Table -> (View / Record / Field)`,以及 `App -> Role -> Member`

View File

@@ -0,0 +1,31 @@
## 获取多维表格元数据
- DDS-Section: A.10 获取多维表格元数据
- DDS-Lines: L1932-L2205
### Extract
| 方法 | 路径 | 关键参数 |
|---|---|---|
| GET | `/bitable/v1/apps/{app_token}` | `app_token` |
关键约束:
- 支持 20 QPS以接口描述为准
- 错误码含 `WrongBaseToken``OperationTypeError`
## 更新多维表格元数据
- DDS-Section: A.11 更新多维表格元数据
- DDS-Lines: L2206-L2430
### Extract
| 方法 | 路径 | 请求体关键字段 |
|---|---|---|
| PUT | `/bitable/v1/apps/{app_token}` | `name`, `is_advanced` |
关键约束:
- 接口非原子:先改名,后切换高级权限
- 写接口常见 10 QPS且不建议并发写
- 高级权限开关对后续 Role/Member 接口可用性有直接影响

View File

@@ -0,0 +1,23 @@
## token 与访问身份
- DDS-Section: 接入指南-鉴权
- DDS-Lines: L311-L371
### Extract
| 方式 | 适用 |
|---|---|
| `user_access_token` | 用户身份调用 |
| `tenant_access_token` | 应用身份调用 |
## 高级权限开关前置
- DDS-Section: A.7 概述 / A.11 更新多维表格元数据
- DDS-Lines: L1547-L1561, L2229-L2233, L2286-L2289
### Extract
- 飞书文档/飞书表格/知识库中的多维表格不支持开启高级权限。
- 开启高级权限存在生效延迟,可能返回 `OperationTypeError`
- 发生无访问权限时,应检查高级权限设置中是否为应用主体授权。

View File

@@ -0,0 +1,15 @@
## 服务端持久化结构
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未提供 App 元数据在业务系统侧的数据库结构。
### 最小补充信息清单
1. App 元数据缓存表是否存在(字段与 TTL
2. 高级权限开关状态是否持久化本地
3. App 配置变更的审计日志模型

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,87 @@
---
name: developing-bitable-event-callback
description: 指导飞书多维表格事件与回调模块开发Guides Bitable event and callback integration development。包含事件类型、长连接/HTTP 回调模式、验签解密参数、3 秒响应与重推去重策略。触发场景 Trigger: 新增事件订阅、接入回调服务、排查重复推送与签名校验失败。关键词 Keywords: event, callback, websocket, webhook, verificationToken, eventEncryptKey, bitable。
argument-hint: "<mode> <event-type> - e.g., 'websocket bitable_record_changed', 'http callback card action'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable Event & Callback
用于搭建与维护飞书事件/回调接入通道,统一消息投递语义、幂等消费、验签解密配置与故障处理。
## Quick Context
```bash
# 定位事件处理器、回调路由与 SDK dispatcher
!`rg -n "EventDispatcher|OnP2|OnCustomizedEvent|webhook/event|callback" -S . | head -n 120`
# 定位 3 秒响应、重推、去重逻辑
!`rg -n "3 秒|重推|event_id|idempot|retry|verificationToken|eventEncryptKey" -S . | head -n 120`
```
## Plan
### 产物清单
- [ ] 事件订阅清单与处理器映射
- [ ] 回调模式(长连接/HTTP决策
- [ ] 验签解密配置与密钥管理
- [ ] 重推去重与失败告警策略
### 决策点
1. 采用长连接模式还是 HTTP 回调模式?
2. 是否开启加密策略(需要 verificationToken/eventEncryptKey
3. 幂等去重键是否统一为 `event_id`
## Verify
### 事件契约
- [ ] 事件类型与字段对齐 `reference/01-event-types/events-topics.md`
- [ ] 处理器注册方法与事件版本匹配v1/v2
### 接入模式
- [ ] 模式选择与网络前置条件对齐 `reference/02-callback-modes/dependencies.md`
- [ ] HTTP 模式已提供稳定回调地址与快速响应路径
### 安全与语义
- [ ] 验签/解密参数配置对齐 `reference/03-security/security-model.md`
- [ ] 3 秒响应与重推语义对齐 `reference/04-delivery-semantics/state-machine.md`
## Execute
### 1. 建立接入通道
1. 长连接模式:初始化 SDK ws client 并注册 dispatcher。
2. HTTP 模式:暴露 `/webhook/event` 路由并接入 handler。
### 2. 注册事件处理器
1. 按事件版本选择 `OnCustomizedEvent``OnP2*` 方法。
2. 在处理器内抽取 `event_id`, `tenant_key`, 资源 ID。
### 3. 落地幂等与超时控制
1. 处理链路控制在 3 秒内返回 ACK。
2. 业务处理异步化,核心字段入队。
3.`event_id` 去重,避免重推重复消费。
### 4. 异常处理
1. 验签/解密失败:快速拒绝并记录上下文。
2. 下游不可用:入队重试并上报告警。
## Pitfalls
1. **使用错误的事件版本处理器**v1/v2 结构不同,见 `reference/01-event-types/events-topics.md`
2. **处理超时超过 3 秒**:平台会重推,见 `reference/04-delivery-semantics/state-machine.md`
3. **开启加密后仍传空密钥**:会导致解密失败,见 `reference/03-security/security-model.md`
4. **长连接当广播使用**:实际是集群随机分发,见 `reference/02-callback-modes/dependencies.md`
## Related References
- `reference/01-event-types/events-topics.md`
- `reference/02-callback-modes/dependencies.md`
- `reference/03-security/security-model.md`
- `reference/04-delivery-semantics/state-machine.md`
- `reference/05-db-schema/db-schema.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,14 @@
## Bitable 事件清单
- DDS-Section: A.8 多维表格字段变更 / A.9 多维表格记录变更
- DDS-Lines: L1599-L1712, L1815-L1915
### Extract
| 事件类型 | 场景 | 关键字段 |
|---|---|---|
| `drive.file.bitable_field_changed_v1` | 字段变更 | `event_id`, `event_type`, `table_id`, `field_id` |
| `drive.file.bitable_record_changed_v1` | 记录变更 | `event_id`, `event_type`, `table_id`, `record_id` |
字段:`tenant_key`, `token`, `subscriber_id_list` 需一并保留用于追踪与授权判定。

View File

@@ -0,0 +1,21 @@
## 回调接入模式
- DDS-Section: 3.5 事件与回调处理 / B.4 处理事件 / B.5 处理回调
- DDS-Lines: L86-L92, L16849-L17083, L17147-L17397
### Extract
| 模式 | 特点 | 前置条件 |
|---|---|---|
| 长连接WebSocket | 接入快、免内网穿透、集群非广播 | 运行环境可访问公网 |
| HTTP 回调 | 传统 webhook平台主动 POST | 需要公网可达地址 |
## 框架集成
- DDS-Section: B.4/B.5 示例代码
- DDS-Lines: L17028-L17081, L17358-L17397
### Extract
支持原生 HTTP、Gin、Hertz 三类接入方式。

View File

@@ -0,0 +1,14 @@
## 验签与解密配置
- DDS-Section: B.4 处理事件 / B.5 处理回调
- DDS-Lines: L16980-L17018, L17294-L17316
### Extract
| 参数 | 说明 |
|---|---|
| `verificationToken` | 用于签名验证 |
| `eventEncryptKey` | 用于消息解密 |
若在开发者后台启用加密策略,则必须传递上述参数。

View File

@@ -0,0 +1,16 @@
## 投递语义状态流
- DDS-Section: 事件/回调处理说明 / FAQ
- DDS-Lines: L89, L16871, L17196, L18207-L18209
### Extract
```text
RECEIVED -> ACK(<3s) -> DONE
RECEIVED -> TIMEOUT(>=3s) -> RETRY_PUSH -> DEDUPE_BY_EVENT_ID -> DONE
```
规则:
- 必须在 3 秒内完成 ACK。
- 超时会触发重推,消费侧必须幂等。

View File

@@ -0,0 +1,15 @@
## 事件存储结构
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未给出事件落库模型(去重表、死信表、重试表)。
### 最小补充信息清单
1. `event_id` 去重存储 TTL
2. 失败事件重试与死信策略
3. 事件审计字段定义

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,86 @@
---
name: developing-bitable-field
description: 指导飞书多维表格 Field 模块开发Guides Bitable field module development。包含字段 CRUD、字段类型 property 配置、全量更新语义、字段变更事件处理。触发场景 Trigger: 新增/更新/删除字段、扩展字段类型配置、排查 field_id 与 property 不匹配问题。关键词 Keywords: field, field_id, property, option, relation, bitable。
argument-hint: "<action> <app_token table_id field_id?> - e.g., 'create field appbxxx tblxxx', 'update field property appbxxx tblxxx fldxxx'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable Field
用于字段资源开发:字段列表与增删改、字段类型 `property` 配置、全量更新风险控制,以及字段变更事件消费。
## Quick Context
```bash
# 定位字段 API 与字段类型处理
!`rg -n "app-table-field|fields/\{field_id\}|property|options|table_id" -S . | head -n 120`
# 定位字段事件与幂等逻辑
!`rg -n "bitable_field_changed|field_changed|client_token|幂等" -S . | head -n 100`
```
## Plan
### 产物清单
- [ ] Field CRUD 调用封装
- [ ] 各字段类型 `property` 映射
- [ ] 更新语义防护(全量覆盖)
- [ ] 字段变更事件消费链路
### 决策点
1. 本次是新增字段还是全量更新字段?
2. 是否涉及关联字段(单向/双向)与跨表依赖?
3. 字段变更是否需要同步下游读写映射?
## Verify
### 契约与结构
- [ ] API 路径、方法对齐 `reference/01-field-openapi/apis.md`
- [ ] 字段类型与 `property` 结构对齐 `reference/02-field-types/db-schema.md`
### 事件与一致性
- [ ] 字段变更事件字段对齐 `reference/03-field-events/events-topics.md`
- [ ] 更新后已验证字段列表与读写兼容
### 权限
- [ ] token 与权限范围对齐 `reference/04-security/security-model.md`
## Execute
### 1. 字段读取
1.`list fields` 获取当前字段与类型。
2. 基于目标类型准备 `property` 请求体。
### 2. 字段写操作
1. 新增字段:调用 `create`,最小化初始属性。
2. 更新字段:调用 `update` 前先合并旧属性,避免误删。
3. 删除字段:确认下游表达式/关联/报表依赖后执行。
### 3. 关联字段处理
1. 单向/双向关联字段需显式绑定目标 `table_id`
2. 双向关联应检查返回的反向字段信息。
### 4. 事件消费
1. 消费 `bitable_field_changed`
2.`event_id` 去重,刷新本地字段缓存。
## Pitfalls
1. **把字段更新当成增量 patch**:接口是全量更新,易误删旧选项,见 `reference/02-field-types/db-schema.md`
2. **关联字段只改一侧**:双向关联会产生不一致,见 `reference/02-field-types/db-schema.md`
3. **删字段前未清理筛选或公式依赖**:可能导致查询失败,先查 `reference/01-field-openapi/apis.md`
4. **字段变更事件重复消费**:需按 event_id 去重,见 `reference/03-field-events/events-topics.md`
## Related References
- `reference/01-field-openapi/apis.md`
- `reference/02-field-types/db-schema.md`
- `reference/03-field-events/events-topics.md`
- `reference/04-security/security-model.md`
- `reference/05-state-machine/state-machine.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,18 @@
## Field API 矩阵
- DDS-Section: A.37~A.40(列出/新增/更新/删除字段)
- DDS-Lines: L12086-L13934
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/bitable/v1/apps/{app_token}/tables/{table_id}/fields` | 列出字段 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/fields` | 新增字段 |
| PUT | `/bitable/v1/apps/{app_token}/tables/{table_id}/fields/{field_id}` | 更新字段 |
| DELETE | `/bitable/v1/apps/{app_token}/tables/{table_id}/fields/{field_id}` | 删除字段 |
约束:
- 写接口不建议并发。
- 常见写接口频控 10 QPS。

View File

@@ -0,0 +1,39 @@
## 字段基础结构
- DDS-Section: A.3 数据结构 / A.5 字段编辑指南
- DDS-Lines: L571-L580, L719-L738
### Extract
| 字段 | 类型 | 说明 |
|---|---|---|
| `field_id` | string | 字段 ID |
| `field_name` | string | 字段名 |
| `type` | int | 字段类型编码 |
| `property` | object | 类型相关属性 |
## 关键类型 property
- DDS-Section: A.5 字段编辑指南(数字、单选/多选、日期、人员、关联、公式、自动编号)
- DDS-Lines: L738-L1344
### Extract
| 类型 | 关键 property |
|---|---|
| 单选/多选 | `options[]` |
| 单向/双向关联 | `table_id`, `table_name`, `back_field_*` |
| 自动编号 | `type`, `options[]`, `rule_option_type` |
更新语义:
- 字段更新为全量更新,`property` 会被完全覆盖。
## DB Schema
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档无后端数据库字段字典表定义(字段元数据持久化)。

View File

@@ -0,0 +1,21 @@
## 字段变更事件
- DDS-Section: A.8 多维表格字段变更
- DDS-Lines: L1595-L1712
### Extract
| 事件类型 | 关键字段 |
|---|---|
| `drive.file.bitable_field_changed_v1` | `event_id`, `event_type`, `tenant_key`, `table_id`, `field_id` |
## 消费策略
- DDS-Section: 事件回调说明
- DDS-Lines: L89, L18209
### Extract
- 3 秒内响应,否则重推。
- 建议 `event_id` 去重 + 字段缓存增量刷新。

View File

@@ -0,0 +1,13 @@
## 字段接口权限模型
- DDS-Section: 接入指南-鉴权 / 字段相关 OpenAPI security
- DDS-Lines: L311-L371, L12108+, L12678+, L13147+
### Extract
| 项 | 说明 |
|---|---|
| token | 支持 tenant/user 两种调用身份 |
| 高级权限影响 | 部分无访问权限由高级权限策略导致 |
| 用户标识字段 | 某些字段(如人员)涉及 user_id 权限要求 |

View File

@@ -0,0 +1,15 @@
## 字段状态机
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未定义字段生命周期状态机draft/active/deprecated 等)。
### 最小补充信息清单
1. 字段启用/停用状态定义
2. 变更审批与回滚流程
3. 对历史记录的兼容策略

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,88 @@
---
name: developing-bitable-record
description: 指导飞书多维表格 Record 模块开发Guides Bitable record module development。包含记录 CRUD、批量写入、筛选表达式、附件字段协同与变更事件消费。触发场景 Trigger: 新增/更新/删除记录、批量写入、按条件检索、排查 record_id 或 fields 映射问题。关键词 Keywords: record, fields, batch_update, filter, file_token, bitable。
argument-hint: "<action> <app_token table_id record_id?> - e.g., 'batch_update appbxxx tblxxx', 'get record appbxxx tblxxx recxxx'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable Record
用于记录资源生命周期开发:单条与批量 CRUD、`fields` 结构映射、筛选表达式、附件字段联动与记录变更事件处理。
## Quick Context
```bash
# 定位记录接口与批量操作
!`rg -n "app-table-record|records/batch_|/records/\{record_id\}|filter" -S . | head -n 100`
# 定位幂等键、重试与附件 file_token 处理
!`rg -n "client_token|幂等|file_token|batch_get_tmp_download_url|OperationTypeError" -S . | head -n 100`
```
## Plan
### 产物清单
- [ ] 记录 CRUD 与批量接口封装
- [ ] `fields` 映射层(字段类型到值结构)
- [ ] 幂等与重试控制
- [ ] 记录变更事件消费逻辑
### 决策点
1. 写入是单条还是批量(最多 500 条)?
2. 是否需要 `client_token` 幂等保护?
3. 是否要同时处理附件上传/下载链路?
## Verify
### API 与参数
- [ ] 路径、方法、分页参数与 `reference/01-record-openapi/apis.md` 对齐
- [ ] `fields` 结构映射与 `reference/02-record-structure/db-schema.md` 对齐
### 事件与幂等
- [ ] 记录变更事件消费字段对齐 `reference/03-events/events-topics.md`
- [ ] 写接口幂等与重试策略明确(含 UUID client_token
### 安全与权限
- [ ] 鉴权模式、字段级敏感信息权限对齐 `reference/04-security/security-model.md`
## Execute
### 1. 读取与检索
1.`list/get` 获取基线数据和分页状态。
2. 按需增加筛选表达式,避免全量扫描。
### 2. 写入与批量
1. 单条场景使用 `create/update/delete`
2. 批量场景使用 `batch_create/batch_update/batch_delete`,每次不超过 500。
3. 对写请求设置串行化策略,必要时附 `client_token`
### 3. 附件协同
1. 先上传素材拿到 `file_token`
2. 再写入记录附件字段。
3. 下载时先从记录读取 `file_token` 再调用下载接口。
### 4. 事件消费
1. 处理 `bitable_record_changed` 事件。
2. 使用 `event_id` 去重,避免超时重推导致重复处理。
## Pitfalls
1. **批量写超出上限**:单次最多 500 条,见 `reference/01-record-openapi/apis.md`
2. **fields 结构硬编码错误**:不同字段类型值结构不同,见 `reference/02-record-structure/db-schema.md`
3. **未使用幂等键导致重复写入**:重试场景可能产生重复副作用,见 `reference/01-record-openapi/apis.md`
4. **附件流程顺序错误**:必须先拿 file_token 再写记录,见 `reference/02-record-structure/db-schema.md`
5. **事件重复消费**3 秒超时会重推,见 `reference/03-events/events-topics.md`
## Related References
- `reference/01-record-openapi/apis.md`
- `reference/02-record-structure/db-schema.md`
- `reference/03-events/events-topics.md`
- `reference/04-security/security-model.md`
- `reference/05-state-machine/state-machine.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,23 @@
## Record API 矩阵
- DDS-Section: A.29~A.36(检索/列出/新增/更新/删除/批量)
- DDS-Lines: L7926-L12085
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/{record_id}` | 检索记录 |
| GET | `/bitable/v1/apps/{app_token}/tables/{table_id}/records` | 列出记录 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/records` | 新增记录 |
| PUT | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/{record_id}` | 更新记录 |
| DELETE | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/{record_id}` | 删除记录 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/batch_create` | 批量新增 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/batch_update` | 批量更新 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/records/batch_delete` | 批量删除 |
关键约束:
- 批量接口单次最多 500。
- 写接口不建议并发。
- 部分批量接口支持 `client_token` 幂等。

View File

@@ -0,0 +1,34 @@
## 记录数据结构
- DDS-Section: A.3 数据结构(记录/fields/value
- DDS-Lines: L475-L571
### Extract
| 字段 | 类型 | 说明 |
|---|---|---|
| `record_id` | string | 记录唯一标识 |
| `fields` | map | 字段名到值的映射 |
`fields` 值结构按字段类型变化(文本、数字、人员、附件、关联等)。
## 附件字段协同
- DDS-Section: A.6 附件字段说明
- DDS-Lines: L1370-L1534
### Extract
1. 先调用上传素材接口获取 `file_token`
2. 再通过记录写接口将附件写入字段。
3. 下载时先通过记录读取 `file_token`,再调用下载接口。
## 本地 DB Schema
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未给出记录在业务系统持久化时的表结构与索引。

View File

@@ -0,0 +1,23 @@
## 记录变更事件
- DDS-Section: A.9 多维表格记录变更
- DDS-Lines: L1811-L1915
### Extract
| 事件 | 说明 |
|---|---|
| `drive.file.bitable_record_changed_v1` | 记录变更事件 |
关键字段:`event_id`, `event_type`, `tenant_key`, `table_id`, `record_id`
## 投递语义
- DDS-Section: 事件与回调处理说明
- DDS-Lines: L89, L18209
### Extract
- 接收端需在 3 秒内响应,否则重推。
- 消费端需做基于 `event_id` 的幂等去重。

View File

@@ -0,0 +1,13 @@
## Record 接口鉴权
- DDS-Section: 接入指南-鉴权 / 记录 API security 声明
- DDS-Lines: L311-L371, L8529+, L9268+, L9842+
### Extract
| 维度 | 说明 |
|---|---|
| token | `tenant_access_token``user_access_token` |
| 权限失败 | 高级权限或文档协作者权限未覆盖时会拒绝 |
| ID 字段 | `app_token` + `table_id` + `record_id` 需一致来源 |

View File

@@ -0,0 +1,15 @@
## 状态机定义
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未定义 Record 业务状态机(状态枚举、转移守卫、补偿动作)。
### 最小补充信息清单
1. 记录业务状态集合(如 draft/active/archived
2. 转移触发条件与角色权限
3. 转移失败补偿策略

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,86 @@
---
name: developing-bitable-role-member
description: 指导飞书多维表格高级权限 Role/Member 模块开发Guides Bitable advanced permission role/member development。包含角色管理、协作者管理、前置开关检查与权限联动。触发场景 Trigger: 配置高级权限角色、批量增删协作者、排查 role_id/member_id 相关鉴权失败。关键词 Keywords: role, member, advanced permission, role_id, member_id, bitable。
argument-hint: "<action> <app_token role_id?> - e.g., 'create role appbxxx', 'add members appbxxx rolxxx'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable Role & Member
用于高级权限域开发角色Role与协作者Member的增删改查及其与元数据开关、文档权限的联动处理。
## Quick Context
```bash
# 定位角色与协作者 API
!`rg -n "app-role|roles/\{role_id\}|role-member|members" -S . | head -n 120`
# 定位高级权限前置与无权限错误处理
!`rg -n "is_advanced|OperationTypeError|无访问权限|permission-member" -S . | head -n 100`
```
## Plan
### 产物清单
- [ ] Role API 封装
- [ ] Member API 封装(含批量)
- [ ] 高级权限开关前置检查
- [ ] 权限联动处理(文档权限)
### 决策点
1. 当前 app 是否已开启高级权限?
2. 是否需要同时同步云文档协作者权限?
3. 成员操作是否采用批量接口?
## Verify
### API 与参数
- [ ] 角色接口对齐 `reference/01-role-openapi/apis.md`
- [ ] 协作者接口对齐 `reference/02-member-openapi/apis.md`
### 前置与权限
- [ ] 开关前置、延迟生效、无权限分支对齐 `reference/03-security/security-model.md`
- [ ] 与文档权限联动策略对齐 `reference/04-dependencies/dependencies.md`
### 风险控制
- [ ] 批量操作有容量与失败处理策略
- [ ] 删除角色前已确认成员迁移或清理方案
## Execute
### 1. 前置检查
1. 调用 app 元数据接口确认高级权限已开启。
2. 若未开启,先走 app metadata 更新流程。
### 2. 角色管理
1. `list/create/update/delete role` 按资源策略执行。
2. 变更后回读角色详情,校验权限范围。
### 3. 协作者管理
1. 通过 `list/create/delete` 或批量接口维护成员。
2. 视场景同步云文档权限,避免“高级权限已加但文档无权限”。
### 4. 错误恢复
1. 对延迟生效错误(`OperationTypeError`)实施短周期重试。
2. 对权限缺失错误直接中止并返回修复建议。
## Pitfalls
1. **未开启高级权限就调用 Role/Member**:必然失败,见 `reference/03-security/security-model.md`
2. **只加高级权限不加文档权限**:用户仍可能不可访问,见 `reference/04-dependencies/dependencies.md`
3. **角色删除前未迁移成员**:造成权限漂移,需先清理成员,见 `reference/02-member-openapi/apis.md`
4. **忽略开启延迟**:开关后立即调用可能报错,见 `reference/03-security/security-model.md`
## Related References
- `reference/01-role-openapi/apis.md`
- `reference/02-member-openapi/apis.md`
- `reference/03-security/security-model.md`
- `reference/04-dependencies/dependencies.md`
- `reference/05-db-schema/db-schema.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,18 @@
## Role API 矩阵
- DDS-Section: A.41~A.44(列出/新增/删除/更新自定义角色)
- DDS-Lines: L13935-L15372
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/bitable/v1/apps/{app_token}/roles` | 列出角色 |
| POST | `/bitable/v1/apps/{app_token}/roles/{role_id}` | 新增角色 |
| DELETE | `/bitable/v1/apps/{app_token}/roles/{role_id}` | 删除角色 |
| PUT | `/bitable/v1/apps/{app_token}/roles/{role_id}` | 更新角色 |
约束:
- 角色接口依赖高级权限开启。
- 写操作建议串行处理。

View File

@@ -0,0 +1,15 @@
## Member API 矩阵
- DDS-Section: A.45~A.49(批量删/批量增/列出/新增/删除协作者)
- DDS-Lines: L15373-L16470
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/bitable/v1/apps/{app_token}/roles/{role_id}/members/batch_delete` | 批量删除协作者 |
| POST | `/bitable/v1/apps/{app_token}/roles/{role_id}/members/batch_create` | 批量新增协作者 |
| GET | `/bitable/v1/apps/{app_token}/roles/{role_id}/members` | 列出协作者 |
| POST | `/bitable/v1/apps/{app_token}/roles/{role_id}/members` | 新增协作者 |
| DELETE | `/bitable/v1/apps/{app_token}/roles/{role_id}/members/{member_id}` | 删除协作者 |

View File

@@ -0,0 +1,13 @@
## 高级权限前置与异常
- DDS-Section: A.7 概述 / A.11 更新元数据
- DDS-Lines: L1547-L1565, L2229-L2233, L2286-L2289
### Extract
| 规则 | 说明 |
|---|---|
| 开关前置 | Role/Member 调用前必须开启高级权限 |
| 生效延迟 | 开启后短时可能报 `OperationTypeError` |
| 无权限 | 需在高级权限中加入包含应用的群并授予读写 |

View File

@@ -0,0 +1,19 @@
## 权限联动依赖
- DDS-Section: A.7 概述
- DDS-Lines: L1559-L1561
### Extract
- 高级权限协作者与云文档协作者是两套身份体系。
- 新增高级权限协作者后,建议通过 drive 权限接口同步文档权限。
## 上下游依赖
- DDS-Section: 接入指南-内容
- DDS-Lines: L294-L303
### Extract
`App(is_advanced=true) -> Role -> Member`

View File

@@ -0,0 +1,15 @@
## 权限域数据库结构
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未描述 Role/Member 在业务侧持久化结构与审计表。
### 最小补充信息清单
1. 角色权限项结构与版本字段
2. 成员-角色关系表唯一键
3. 权限变更审计日志表

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,83 @@
---
name: developing-bitable-table-view
description: 指导飞书多维表格 Table 与 View 模块开发Guides Bitable table and view module development。包含数据表管理、视图管理、分页与错误处理、写接口并发约束。触发场景 Trigger: 新增/删除数据表、创建/删除视图、调整视图属性、排查 table_id/view_id 相关错误。关键词 Keywords: table, view, table_id, view_id, bitable, openapi。
argument-hint: "<action> <app_token/table_id/view_id> - e.g., 'create table appbxxx', 'delete view tblxxx vewxxx'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Developing Bitable Table & View
聚焦 `table_id``view_id` 资源生命周期,包括列表、创建、删除、更新,以及上游 App 与下游 Record/Field 的依赖影响。
## Quick Context
```bash
# 定位表和视图相关接口
!`rg -n "app-table|tables/\{table_id\}|views|app-table-view" -S . | head -n 100`
# 定位写接口并发与限流防护逻辑
!`rg -n "QPS|batch|并发|OperationTypeError|retry|client_token" -S . | head -n 80`
```
## Plan
### 产物清单
- [ ] Table API 调用点与参数封装
- [ ] View API 调用点与参数封装
- [ ] 分页遍历/幂等/重试策略
- [ ] 资源删除后的下游影响评估
### 决策点
1. 是否需要批量建表/删表能力?
2. 视图变更是否影响既有筛选与展示语义?
3. 是否有并发写风险(同 app 同时发多个写请求)?
## Verify
### API 对齐
- [ ] Table 接口路径与方法对齐 `reference/02-table-openapi/apis.md`
- [ ] View 接口路径与方法对齐 `reference/03-view-openapi/apis.md`
### 约束检查
- [ ] QPS、并发写限制已按 `reference/02-table-openapi/apis.md``reference/03-view-openapi/apis.md` 落地
- [ ] 删除类操作前已验证依赖关系Record/Field/业务视图)
### 安全检查
- [ ] token 模式与权限范围匹配,见 `reference/04-security/security-model.md`
## Execute
### 1. 数据表操作
1.`list tables` 确认目标是否已存在。
2. 执行 `create / batch_create / delete / batch_delete`
3. 对写请求串行化,避免同 app 并发写。
### 2. 视图操作
1.`list views` 获取目标 `view_id`
2. 执行 `create / update / delete / get`
3. 修改后做一次读取回放,确认属性生效。
### 3. 失败处理
1. 对参数类错误立即失败并回传上下文。
2. 对可恢复错误(冲突、短暂不可用)使用有限重试。
## Pitfalls
1. **删除表前未处理下游依赖**Record/Field/业务配置悬空,先看 `reference/01-resource-model/dependencies.md`
2. **同一 app 并发写表/视图**:会触发并发写限制,先看 `reference/02-table-openapi/apis.md`
3. **view_id 获取方式错误**:不同形态下取值路径不同,先看 `reference/01-resource-model/dependencies.md`
4. **分页处理缺失**list 接口有 `page_token`,漏处理会丢数据,见 `reference/02-table-openapi/apis.md`
## Related References
- `reference/01-resource-model/dependencies.md`
- `reference/02-table-openapi/apis.md`
- `reference/03-view-openapi/apis.md`
- `reference/04-security/security-model.md`
- `reference/05-db-schema/db-schema.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,16 @@
## 资源关系
- DDS-Section: 资源:数据表 Table / 资源:视图 View / 接入指南-参数说明
- DDS-Lines: L130-L170, L442-L452
### Extract
| 资源 | 标识 | 关系 |
|---|---|---|
| Table | `table_id` | 归属 `app_token` |
| View | `view_id` | 归属 `table_id` |
获取建议:
- `table_id` 可通过列出数据表接口获取。
- `view_id` 可通过列出视图接口获取(部分场景不可直接从 doc block 得到)。

View File

@@ -0,0 +1,20 @@
## 数据表接口矩阵
- DDS-Section: A.12~A.17(更新/列出/新增/批量新增/删除/批量删除数据表)
- DDS-Lines: L2431-L4013
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| PUT | `/bitable/v1/apps/{app_token}/tables/{table_id}` | 更新数据表 |
| GET | `/bitable/v1/apps/{app_token}/tables` | 列出数据表 |
| POST | `/bitable/v1/apps/{app_token}/tables` | 新增数据表 |
| POST | `/bitable/v1/apps/{app_token}/tables/batch_create` | 批量新增 |
| DELETE | `/bitable/v1/apps/{app_token}/tables/{table_id}` | 删除数据表 |
| POST | `/bitable/v1/apps/{app_token}/tables/batch_delete` | 批量删除 |
约束:
- 写接口常见 10 QPS读接口常见 20 QPS。
- 不支持并发写接口。

View File

@@ -0,0 +1,19 @@
## 视图接口矩阵
- DDS-Section: A.20~A.24(更新/检索/列出/新增/删除视图)
- DDS-Lines: L4700-L6501
### Extract
| 方法 | 路径 | 说明 |
|---|---|---|
| PUT | `/bitable/v1/apps/{app_token}/tables/{table_id}/views/{view_id}` | 更新视图 |
| GET | `/bitable/v1/apps/{app_token}/tables/{table_id}/views/{view_id}` | 检索视图 |
| GET | `/bitable/v1/apps/{app_token}/tables/{table_id}/views` | 列出视图 |
| POST | `/bitable/v1/apps/{app_token}/tables/{table_id}/views` | 新增视图 |
| DELETE | `/bitable/v1/apps/{app_token}/tables/{table_id}/views/{view_id}` | 删除视图 |
约束:
- 写接口不建议并发。
- 出现计算超时类错误时可按文档建议重试。

View File

@@ -0,0 +1,13 @@
## 鉴权与权限
- DDS-Section: 接入指南-鉴权 / 各接口 security 定义
- DDS-Lines: L311-L371, L2458+, L5575+
### Extract
| 维度 | 说明 |
|---|---|
| token 类型 | `tenant_access_token` / `user_access_token` |
| 权限异常 | 无访问权限常见于高级权限配置未覆盖应用主体 |
| 额外要求 | 商店应用场景需关注 `tenant_key` |

View File

@@ -0,0 +1,15 @@
## 本地持久化结构
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未提供 Table/View 在业务系统落地时的数据库结构定义。
### 最小补充信息清单
1. 表视图缓存模型(主键、唯一键)
2. 软删除或硬删除策略
3. 变更审计字段与索引

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,114 @@
---
name: developing-feishu-bitable-system
description: 指导飞书多维表格系统级开发与跨模块一致性Guides system-level development for Feishu Bitable。包含模块边界、全局约束、鉴权模型、事件交付和变更路由。触发场景 Trigger: 跨模块改造、资源模型调整、接口策略统一、事件接入方案选择。关键词 Keywords: feishu, bitable, system, architecture, app, table, record, field, role, event, callback。
argument-hint: "<change-scope> <goal> - e.g., 'record+field add batch update', 'role enable advanced permission'"
allowed-tools:
- Read
- Glob
- Grep
- Bash
---
# Developing Feishu Bitable System
用于统一飞书多维表格的系统级决策:先判定变更影响域,再路由到对应模块 Skill并叠加横切约束契约、鉴权、并发、SDK
## Quick Context
```bash
# 扫描仓库中的 Bitable 资源路径与调用热点
!`rg -n "bitable/v1/apps|tables|views|records|fields|roles|members" -S . | head -n 80`
# 扫描鉴权与事件接入相关实现
!`rg -n "WithUserAccessToken|WithTenantAccessToken|WithTenantKey|EventDispatcher|verificationToken|eventEncryptKey" -S . | head -n 80`
```
## Architecture Overview
```text
Client/Job
-> App Metadata
-> Table/View
-> Record
-> Field
-> Role/Member (advanced permission)
-> Event/Callback Inbound
Cross-cut: Contracts / Auth / Write-Concurrency / Go SDK
```
## Module Registry
| 模块 | 职责 | 对应 Skill |
|---|---|---|
| App Metadata | app 元数据与高级权限开关 | `developing-bitable-app-metadata` |
| Table & View | 数据表与视图管理 | `developing-bitable-table-view` |
| Record | 记录 CRUD 与批量操作 | `developing-bitable-record` |
| Field | 字段定义、类型与属性变更 | `developing-bitable-field` |
| Role & Member | 高级权限角色与协作者 | `developing-bitable-role-member` |
| Event & Callback | 事件订阅、回调处理、3 秒响应约束 | `developing-bitable-event-callback` |
## Plan
### 产物清单
- [ ] 变更影响模块清单(主模块 + 受影响模块)
- [ ] 需要叠加的横切 Skill 清单
- [ ] 契约变更面(路径/字段/错误码/权限)
- [ ] 风险与回滚点(重点是写并发和幂等)
### 决策点
1. 变更是否跨越两个及以上资源模块?
2. 是否触及写接口(需执行串行化与幂等策略)?
3. 是否涉及高级权限开关或角色策略?
4. 是否需要事件/回调通道而非轮询读取?
## Verify
### 架构边界
- [ ] 变更只在目标模块内落地,跨模块依赖已在 `reference/01-architecture-overview/dependencies.md` 对齐
- [ ] 新增能力没有绕过 App/Table 资源层级
### 全局约束
- [ ] QPS 与批量上限已对齐 `reference/02-global-constraints/apis.md`
- [ ] 写接口并发冲突风险已评估并规避(串行或幂等键)
### 安全与权限
- [ ] token 模式与调用身份已对齐 `reference/03-auth-and-permissions/security-model.md`
- [ ] 高级权限开启前置条件与延迟影响已覆盖
### 事件与回调
- [ ] 事件订阅/回调路径满足 3 秒响应约束,见 `reference/04-event-delivery/events-topics.md`
## Execute
### 1. 识别变更类型
1. 标注主资源:`app/table/view/record/field/role/member/event`
2. 判断是否含写操作:`create/update/delete/batch_*`
3. 判断是否含权限变化:高级权限开关、角色或协作者变更。
### 2. 路由到模块 Skill
1. 单模块改动:直接进入对应模块 Skill。
2. 跨模块改动:按调用链顺序执行(上游契约先变更、下游消费后变更)。
3. 若涉及 SDK 接入方式或调用风格,叠加 `implementing-bitable-go-sdk`
### 3. 叠加横切校验
1. 契约:执行 `designing-bitable-contracts` 检查路径、参数、错误码。
2. 鉴权:执行 `implementing-bitable-auth-access` 检查 token 与权限。
3. 并发:执行 `managing-bitable-write-concurrency` 检查 QPS、幂等、重试。
### 4. 输出变更包
1. 给出变更影响矩阵(模块 × 接口 × 权限 × 风险)。
2. 明确灰度步骤与回滚触发条件。
## Pitfalls
1. **把 Role/Member 当作普通 CRUD 资源处理**:高级权限开关未完成时直接调用会失败,先查 `reference/03-auth-and-permissions/security-model.md`
2. **多写接口并发提交**:文档明确不支持并发写接口,需先查 `reference/02-global-constraints/apis.md`
3. **事件通道没有 3 秒响应保障**:会触发重推与重复消费,先查 `reference/04-event-delivery/events-topics.md`
4. **跨模块修改只改调用方不改契约源**:导致路径或字段漂移,先对照 `reference/01-architecture-overview/dependencies.md`
## Related References
- `reference/01-architecture-overview/dependencies.md`:资源层次、模块依赖、调用链
- `reference/02-global-constraints/apis.md`QPS、批量上限、写并发、幂等约束
- `reference/03-auth-and-permissions/security-model.md`token 模型与高级权限前置条件
- `reference/04-event-delivery/events-topics.md`:事件体、回调模式、重推约束

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,30 @@
## 资源分层与模块边界
- DDS-Section: A.1 概述 / A.2 接入指南(形态、内容)
- DDS-Lines: L111-L257, L272-L303
### Extract
| 层级 | 资源 | 核心标识 | 说明 |
|---|---|---|---|
| L1 | App | `app_token` | 多维表格应用根资源 |
| L2 | Table | `table_id` | App 下的数据容器 |
| L2 | Role | `role_id` | App 下高级权限角色 |
| L3 | View | `view_id` | Table 下视图 |
| L3 | Record | `record_id` | Table 下记录 |
| L3 | Field | `field_id` | Table 下字段 |
| L3 | Member | `member_id` | Role 下协作者 |
## 跨模块依赖链路
- DDS-Section: A.2 接入指南 / A.6 附件字段说明 / A.7 高级权限概述
- DDS-Lines: L302-L303, L1410-L1534, L1547-L1588
### Extract
| 源模块 | 目标模块 | 协议/接口 | 依赖说明 |
|---|---|---|---|
| Record | Drive Media | upload/download API | 附件字段依赖 file_token |
| RoleMember | Drive Permission | permission-member/create | 高级权限协作者建议同步文档权限 |
| EventCallback | 业务模块 | WebSocket/HTTP callback | 事件回调驱动记录或字段消费逻辑 |

View File

@@ -0,0 +1,38 @@
## 全局频控与批量约束
- DDS-Section: 接入指南-限制 / 各 OpenAPI Specification 描述
- DDS-Lines: L377-L384, L1954+, L2233+, L2635+, L8529+, L10629+
### Extract
| 规则 | 约束 |
|---|---|
| QPS | 多数读接口 20 QPS写接口常见 10 QPS以具体接口描述为准 |
| 批量记录操作 | 单次最多 500 条batch create/update/delete |
| 批量结果 | 接口语义为整体成功或失败,不提供部分成功结果 |
## 写并发与幂等
- DDS-Section: 接入指南注意事项 / 各接口错误码说明
- DDS-Lines: L309, L2067+, L3050+, L3339+, L9483+, L10847+, L12965+
### Extract
| 规则 | 说明 |
|---|---|
| 写并发 | 同一多维表格不建议并发调用写接口 |
| 幂等键 | 部分写接口支持 `client_token`,要求 UUID 格式 |
| 幂等冲突 | 发生冲突时需重生成幂等键再重试 |
## DB Schema
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未给出服务端数据库表结构、索引、迁移策略。若需要落地后端存储,请补充:
1. 业务表与映射表 DDL
2. 索引与唯一键策略
3. 迁移与回滚方案

View File

@@ -0,0 +1,27 @@
## token 鉴权模型
- DDS-Section: 接入指南-鉴权 / Golang SDK 调用说明
- DDS-Lines: L311-L371, L39-L41, L67-L69, L16503
### Extract
| 身份 | token | 说明 |
|---|---|---|
| 用户身份 | `user_access_token` | 用户态调用,刷新后旧 token 失效 |
| 应用身份 | `tenant_access_token` | 应用态调用SDK 可托管生命周期 |
| 商店应用补充 | `tenant_key` | ISV 场景调用需显式传入 |
## 高级权限模型
- DDS-Section: A.7 概述 / 更新多维表格元数据
- DDS-Lines: L1547-L1565, L2226-L2233, L2286-L2289
### Extract
| 规则 | 说明 |
|---|---|
| 开启前置 | 调用 Role/Member 接口前需先开启高级权限 |
| 延迟生效 | 开启后短时间可能返回 `OperationTypeError`,需重试 |
| 权限联动 | 高级权限协作者与云文档协作者不同,必要时同步文档权限 |
| 非原子更新 | 更新元数据接口先改名称再开关权限,可能部分成功 |

View File

@@ -0,0 +1,38 @@
## Bitable 事件定义
- DDS-Section: A.8 多维表格字段变更 / A.9 多维表格记录变更
- DDS-Lines: L1599-L1712, L1815-L1915
### Extract
| 事件类型 | 关键字段 |
|---|---|
| `drive.file.bitable_field_changed_v1` | `event_id`, `event_type`, `tenant_key`, `table_id`, `field_id` |
| `drive.file.bitable_record_changed_v1` | `event_id`, `event_type`, `tenant_key`, `table_id`, `record_id` |
## 回调交付约束
- DDS-Section: Golang SDK-处理事件 / 处理回调
- DDS-Lines: L89, L16853-L16873, L17196-L17263, L18209
### Extract
| 约束 | 说明 |
|---|---|
| 响应时限 | 接收端需在 3 秒内响应,否则会触发重推 |
| 长连接模式 | SDK 支持 WebSocket 长连接;集群模式非广播 |
| HTTP 回调模式 | 需公网地址,接收 POST 推送 |
| 验签/解密 | 若启用加密策略需提供 `verificationToken``eventEncryptKey` |
## 消费幂等
- DDS-Section: 事件与回调说明
- DDS-Lines: L1706, L1846, L18209
### Extract
| 建议 | 原因 |
|---|---|
| 以 `event_id` 做去重 | 重推场景下避免重复处理 |
| 记录 `tenant_key + resource_id` | 多租户隔离与重放定位 |

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,84 @@
---
name: implementing-bitable-auth-access
description: 指导飞书多维表格鉴权与访问控制实现Guides authentication and access control for Feishu Bitable。包含 tenant/user token 选择、商店应用 tenant_key、高级权限开关与协作者联动。触发场景 Trigger: 鉴权失败排查、身份模式切换、权限策略改造、Role/Member 接口不可用问题。关键词 Keywords: auth, access, tenant_access_token, user_access_token, tenant_key, advanced permission。
argument-hint: "<auth-scope> <scenario> - e.g., 'tenant token app-level api', 'role-member no-permission'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Implementing Bitable Auth & Access
用于统一 Bitable 的鉴权和权限控制实现确保调用身份、token 生命周期和高级权限策略在跨模块场景下保持一致。
## Quick Context
```bash
# 扫描 token 与身份调用代码
!`rg -n "WithUserAccessToken|WithTenantAccessToken|WithTenantKey|tenant_access_token|user_access_token" -S . | head -n 120`
# 扫描高级权限开关与无权限处理
!`rg -n "is_advanced|OperationTypeError|无访问权限|roles|members" -S . | head -n 120`
```
## Plan
### 产物清单
- [ ] 身份模式选择矩阵user/tenant
- [ ] token 获取、刷新、缓存策略
- [ ] 高级权限前置校验
- [ ] 权限异常处理流程
### 决策点
1. 场景是否必须用户身份user token
2. 是否为商店应用,需要补 `tenant_key`
3. 是否涉及高级权限域Role/Member
## Verify
### token 模型
- [ ] token 类型选择与接口权限匹配,见 `reference/01-token-model/security-model.md`
- [ ] user token 刷新后旧 token 失效逻辑已处理
### 高级权限
- [ ] app 高级权限开关前置检查已落地,见 `reference/02-advanced-permission/security-model.md`
- [ ] Role/Member 与文档协作者权限联动策略已覆盖
### SDK 选项
- [ ] SDK 请求级 auth 选项使用正确,见 `reference/03-sdk-auth-options/dependencies.md`
## Execute
### 1. 身份选择
1. 先按接口需求判断 user/tenant 身份。
2. 商店应用场景补传 `tenant_key`
### 2. token 生命周期
1. tenant token 优先使用 SDK 托管缓存。
2. user token 自建刷新与失效处理。
### 3. 权限联动
1. 高级权限接口前确认 `is_advanced=true`
2. 必要时同步云文档权限协作者。
### 4. 错误收敛
1. 将鉴权失败细分为身份不匹配、token 失效、权限未开通。
2. 每类返回明确修复动作。
## Pitfalls
1. **把 user token 当 tenant token 用**:调用语义错误,见 `reference/01-token-model/security-model.md`
2. **商店应用漏传 tenant_key**:跨租户调用失败,见 `reference/03-sdk-auth-options/dependencies.md`
3. **高级权限未开启就调角色接口**:直接失败,见 `reference/02-advanced-permission/security-model.md`
4. **只配高级权限不配文档权限**:用户仍无访问权,见 `reference/02-advanced-permission/security-model.md`
## Related References
- `reference/01-token-model/security-model.md`
- `reference/02-advanced-permission/security-model.md`
- `reference/03-sdk-auth-options/dependencies.md`
- `reference/04-session-lifecycle/state-machine.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,17 @@
## 身份与 token 模型
- DDS-Section: 接入指南-鉴权
- DDS-Lines: L311-L371
### Extract
| 身份 | token | 语义 |
|---|---|---|
| 用户身份 | `user_access_token` | 刷新后旧 token 失效 |
| 应用身份 | `tenant_access_token` | 有效期 2 小时,可刷新并短时新旧并存 |
## token 选择建议
- 用户行为归因场景优先 user token。
- 平台级批处理场景优先 tenant token。

View File

@@ -0,0 +1,13 @@
## 高级权限访问模型
- DDS-Section: A.7 概述 / A.11 更新元数据
- DDS-Lines: L1547-L1561, L2229-L2233, L2286-L2289
### Extract
| 规则 | 说明 |
|---|---|
| 前置开关 | `is_advanced` 未开启时 Role/Member 不可用 |
| 生效延迟 | 开启后可能短时返回 `OperationTypeError` |
| 权限联动 | 高级权限协作者与文档协作者是两套体系 |

View File

@@ -0,0 +1,16 @@
## SDK 鉴权选项
- DDS-Section: 3.3 请求级选项 / B.3 调用服务端 API
- DDS-Lines: L65-L72, L16706-L16722
### Extract
| 选项 | 用途 |
|---|---|
| `WithUserAccessToken(...)` | 用户态调用 |
| `WithTenantAccessToken(...)` | 手动传租户 token |
| `WithTenantKey(...)` | 商店应用指定租户 |
| `WithHeaders(...)` | 透传自定义头 |
SDK 可托管 tenant token 生命周期,但不托管 user token 生命周期。

View File

@@ -0,0 +1,15 @@
## 会话/令牌状态机
- DDS-Section: 全文
- DDS-Lines: L1-L18211
### Extract
[TBD] 文档未给出统一的 token 状态机与失效传播规范。
### 最小补充信息清单
1. user token 刷新触发条件与缓存失效策略
2. tenant token 刷新提前量与失败降级策略
3. 多实例 token 缓存一致性策略

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,86 @@
---
name: implementing-bitable-go-sdk
description: 指导飞书多维表格 Go SDK 集成实现Guides Feishu Bitable integration with Go SDK。包含 Client 初始化、强类型 API 调用、raw API 兜底、事件/回调接入与请求级选项。触发场景 Trigger: 新接入 Go SDK、补齐未封装 API、接入事件回调、排查 SDK 调用失败。关键词 Keywords: go sdk, larksuite, bitable v1, client.Do, dispatcher, websocket。
argument-hint: "<task> <api-or-scenario> - e.g., 'typed call list records', 'raw call unsupported api', 'event websocket setup'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Implementing Bitable Go SDK
用于建立 Go SDK 的统一调用与接入模式覆盖初始化、API 访问、事件回调与未封装接口兜底。
## Quick Context
```bash
# 扫描 Go SDK 初始化与调用方式
!`rg -n "lark.NewClient|client\.Bitable\.V1|client\.Do\(|WithUserAccessToken|WithTenantKey" -S . | head -n 150`
# 扫描事件回调 dispatcher 与路由
!`rg -n "dispatcher\.NewEventDispatcher|OnP2|OnCustomizedEvent|webhook/event" -S . | head -n 150`
```
## Plan
### 产物清单
- [ ] SDK Client 初始化模板
- [ ] 强类型 API 调用模板
- [ ] Raw API 调用兜底模板
- [ ] 事件/回调接入模板
### 决策点
1. 目标接口是否有 SDK 强类型方法?
2. 身份调用是否需要 user token 或 tenant key
3. 事件接入选长连接还是 HTTP 回调?
## Verify
### SDK 初始化
- [ ] 初始化参数与缓存策略对齐 `reference/01-sdk-bootstrap/dependencies.md`
- [ ] 请求级选项使用正确
### API 调用策略
- [ ] 强类型调用优先,兜底 raw 调用,见 `reference/02-typed-vs-raw/apis.md`
- [ ] 失败分支统一输出 code/msg/logid
### 事件回调
- [ ] dispatcher 注册方式与模式选择对齐 `reference/03-event-callback/events-topics.md`
- [ ] 验签解密参数对齐 `reference/04-auth/security-model.md`
## Execute
### 1. 初始化 Client
1. 使用 `lark.NewClient(appId, appSecret, ...)`
2. 按场景配置 token cache、tenant key、请求超时。
### 2. 强类型 API 调用
1. 使用 `client.Bitable.V1.<Resource>.<Action>`
2. 统一封装 `resp.Success()` 与错误输出。
### 3. Raw API 兜底
1. 对未封装或历史版本接口使用 `client.Do()`
2. 明确 HTTP 方法、路径、path/query/body 参数。
### 4. 事件与回调
1. 使用 dispatcher 注册处理器。
2. 根据接入模式挂接 ws 或 HTTP handler。
3. 控制 3 秒内应答并落地幂等去重。
## Pitfalls
1. **所有接口都走 raw 调用**:失去类型安全与可维护性,见 `reference/02-typed-vs-raw/apis.md`
2. **user/tenant token 混用**:会触发权限异常,见 `reference/04-auth/security-model.md`
3. **事件处理器注册版本不匹配**:导致解析失败,见 `reference/03-event-callback/events-topics.md`
4. **忽略 logid 输出**:线上排障困难,见 `reference/02-typed-vs-raw/apis.md`
## Related References
- `reference/01-sdk-bootstrap/dependencies.md`
- `reference/02-typed-vs-raw/apis.md`
- `reference/03-event-callback/events-topics.md`
- `reference/04-auth/security-model.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,15 @@
## SDK 初始化与能力
- DDS-Section: 3.1 安装与初始化 / B.1 服务端 SDK / B.2 开发前准备
- DDS-Lines: L25-L41, L16479-L16520, L16572-L16580
### Extract
| 项 | 内容 |
|---|---|
| 安装 | `go get -u github.com/larksuite/oapi-sdk-go/v3@latest` |
| 初始化 | `lark.NewClient(appID, appSecret, ...)` |
| token 托管 | SDK 可托管 tenant token 生命周期 |
扩展:支持自定义缓存、超时与 HTTP Client。

View File

@@ -0,0 +1,14 @@
## 强类型调用与 raw 兜底
- DDS-Section: 3.2 Bitable v1 调用范式 / 3.4 历史或未封装 API 原生调用 / B.3 调用服务端 API
- DDS-Lines: L43-L63, L72-L84, L16594-L16820
### Extract
| 模式 | 方式 | 适用 |
|---|---|---|
| 强类型 | `client.Bitable.V1.<Resource>.<Action>` | 常规已封装接口 |
| Raw | `client.Do(context, ApiReq{...})` | 历史版本/未封装接口 |
统一错误处理建议:输出 `code + msg + request/log id`

View File

@@ -0,0 +1,15 @@
## SDK 事件与回调接入
- DDS-Section: 3.5 事件与回调处理 / B.4 / B.5
- DDS-Lines: L86-L92, L16843-L17397
### Extract
| 能力 | 说明 |
|---|---|
| Event Dispatcher | `dispatcher.NewEventDispatcher` 注册事件处理器 |
| 长连接模式 | SDK 提供 WebSocket 通道接收事件/回调 |
| HTTP 模式 | 可集成原生 HTTP/Gin/Hertz |
注意:长连接是集群分发,不是广播。

View File

@@ -0,0 +1,14 @@
## SDK 鉴权选项
- DDS-Section: 3.3 请求级选项 / B.3 请求选项
- DDS-Lines: L65-L72, L16706-L16722
### Extract
| 选项 | 用途 |
|---|---|
| `WithUserAccessToken` | 用户态请求 |
| `WithTenantAccessToken` | 应用态请求 |
| `WithTenantKey` | 商店应用租户隔离 |
| `WithHeaders` | 自定义请求头 |

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,85 @@
---
name: managing-bitable-write-concurrency
description: 指导飞书多维表格写并发与可靠性治理Guides write concurrency and reliability management for Feishu Bitable。包含 QPS 限制、同资源串行写、幂等键策略、超时重试与失败回退。触发场景 Trigger: 批量写入优化、并发写冲突排查、重试机制设计、高频任务稳定性治理。关键词 Keywords: concurrency, qps, idempotency, client_token, retry, batch, bitable。
argument-hint: "<write-path> <load-profile> - e.g., 'records/batch_update high-throughput', 'fields/update conflict-fix'"
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Managing Bitable Write Concurrency
用于治理 Bitable 写路径的稳定性:限流、串行化、幂等、重试和回滚,避免在高频调用时出现冲突或重复写。
## Quick Context
```bash
# 扫描写接口与批量调用点
!`rg -n "create|update|delete|batch_create|batch_update|batch_delete|client_token" -S . | head -n 150`
# 扫描并发冲突、频控、重试逻辑
!`rg -n "QPS|并发|OperationTypeError|retry|timeout|backoff|idempot" -S . | head -n 150`
```
## Plan
### 产物清单
- [ ] 写接口分类与容量画像
- [ ] 串行化/限流策略
- [ ] 幂等键策略
- [ ] 重试与失败回退方案
### 决策点
1. 哪些接口必须串行(同 app/table
2. 哪些接口必须携带 `client_token`
3. 哪些错误可重试、重试上限是多少?
## Verify
### 限流与容量
- [ ] QPS 与批量上限对齐 `reference/01-qps-limits/apis.md`
- [ ] 批量接口单次容量未超过文档约束
### 冲突与幂等
- [ ] 同资源写请求串行化,见 `reference/02-write-conflict/state-machine.md`
- [ ] 幂等键规则与冲突处理对齐 `reference/03-idempotency/apis.md`
### 重试策略
- [ ] 重试只用于可恢复错误,见 `reference/04-retry-policy/dependencies.md`
- [ ] 不可恢复错误直接失败并回传定位信息
## Execute
### 1. 写路径分层
1. 按资源拆分写队列app/table/record/field/role。
2. 同队列内串行,跨队列受全局限流控制。
### 2. 幂等落地
1. 对支持幂等的接口统一生成 UUID `client_token`
2. 幂等冲突时不盲目重放,先刷新 token 再重试。
### 3. 重试与退避
1. 可重试错误采用指数退避 + 上限次数。
2. 达到上限后进入人工排查通道。
### 4. 观测与告警
1. 记录冲突率、重试率、最终失败率。
2. 关键阈值越界时触发告警。
## Pitfalls
1. **把所有写接口并发放开**:同资源并发写会触发冲突,见 `reference/02-write-conflict/state-machine.md`
2. **幂等键格式不规范**:非 UUID 会直接失败,见 `reference/03-idempotency/apis.md`
3. **把不可恢复错误也重试**:放大故障面,见 `reference/04-retry-policy/dependencies.md`
4. **批量写超限**:单次超过 500 条会失败,见 `reference/01-qps-limits/apis.md`
## Related References
- `reference/01-qps-limits/apis.md`
- `reference/02-write-conflict/state-machine.md`
- `reference/03-idempotency/apis.md`
- `reference/04-retry-policy/dependencies.md`

View File

@@ -0,0 +1,4 @@
# Skeleton Example
- 仅提供调用骨架,不包含完整业务实现。
- 实际编码前先对照 `reference/` 校验参数、权限、错误码与频控限制。

View File

@@ -0,0 +1,15 @@
## 接口频控与批量上限
- DDS-Section: 接入指南-限制 / 各 OpenAPI 描述
- DDS-Lines: L377-L384, L1954+, L2233+, L8529+, L10629+, L11217+
### Extract
| 维度 | 约束 |
|---|---|
| 读接口 QPS | 常见 20 QPS |
| 写接口 QPS | 常见 10 QPS |
| 批量写 | 单次最多 500 条记录 |
说明:具体值以目标接口章节为准。

View File

@@ -0,0 +1,15 @@
## 写冲突状态流
- DDS-Section: 接入指南注意事项 / 各 API 错误码
- DDS-Lines: L309, L2067+, L3050+, L3339+
### Extract
```text
READY -> WRITE_REQUEST
WRITE_REQUEST + parallel_same_resource -> CONFLICT(OperationTypeError)
WRITE_REQUEST + serialized -> SUCCESS
```
策略:同 app更细可到 table写请求串行化。

View File

@@ -0,0 +1,15 @@
## 幂等键规则
- DDS-Section: 记录/字段批量写相关错误码与参数
- DDS-Lines: L9343, L9483, L10707, L10847, L10893, L12777, L12965, L13005
### Extract
| 规则 | 说明 |
|---|---|
| key 字段 | `client_token` |
| 格式 | 标准 UUID |
| 冲突处理 | 重新生成幂等键后重试 |
不满足格式会返回幂等键格式错误。

View File

@@ -0,0 +1,14 @@
## 重试策略依赖
- DDS-Section: 接口错误说明 / 事件重推说明
- DDS-Lines: L3654, L3913, L4896, L5356, L5734, L6058, L18209
### Extract
| 错误类型 | 建议 |
|---|---|
| 服务器计算超时 | 可有限重试 |
| 并发写冲突 | 串行化后重试 |
| 参数/权限错误 | 不重试,直接修正 |
| 回调超时重推 | 消费端按 event_id 去重 |

View File

@@ -0,0 +1,47 @@
#!/bin/bash
# verify.sh - skill structure/content quick validation
set -e
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS+1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL+1))
}
check_cmd() {
local desc="$1"
shift
if "$@"; then
pass "$desc"
else
fail "$desc"
fi
}
SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
check_cmd "SKILL.md exists" test -f "$SKILL_DIR/SKILL.md"
check_cmd "reference dir exists" test -d "$SKILL_DIR/reference"
line_count=$(wc -l < "$SKILL_DIR/SKILL.md")
if [ "$line_count" -lt 500 ]; then
pass "SKILL.md < 500 lines"
else
fail "SKILL.md < 500 lines"
fi
check_cmd "has Plan" grep -q '^## Plan' "$SKILL_DIR/SKILL.md"
check_cmd "has Verify" grep -q '^## Verify' "$SKILL_DIR/SKILL.md"
check_cmd "has Execute" grep -q '^## Execute' "$SKILL_DIR/SKILL.md"
check_cmd "has Pitfalls" grep -q '^## Pitfalls' "$SKILL_DIR/SKILL.md"
check_cmd "reference has DDS-Section" grep -rq 'DDS-Section:' "$SKILL_DIR/reference"
check_cmd "reference has DDS-Lines" grep -rq 'DDS-Lines:' "$SKILL_DIR/reference"
echo "RESULT: $PASS PASS / $FAIL FAIL"
[ $FAIL -eq 0 ]

View File

@@ -0,0 +1,134 @@
[
{
"Skill": "designing-bitable-contracts",
"Lines": 79,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 4,
"DDSLines": 4
},
{
"Skill": "developing-bitable-app-metadata",
"Lines": 82,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 7,
"DDSLines": 7
},
{
"Skill": "developing-bitable-event-callback",
"Lines": 87,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 6,
"DDSLines": 6
},
{
"Skill": "developing-bitable-field",
"Lines": 86,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 8,
"DDSLines": 8
},
{
"Skill": "developing-bitable-record",
"Lines": 88,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 8,
"DDSLines": 8
},
{
"Skill": "developing-bitable-role-member",
"Lines": 86,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 6,
"DDSLines": 6
},
{
"Skill": "developing-bitable-table-view",
"Lines": 83,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 5,
"DDSLines": 5
},
{
"Skill": "developing-feishu-bitable-system",
"Lines": 114,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 10,
"DDSLines": 10
},
{
"Skill": "implementing-bitable-auth-access",
"Lines": 84,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 4,
"DDSLines": 4
},
{
"Skill": "implementing-bitable-go-sdk",
"Lines": 86,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 4,
"DDSLines": 4
},
{
"Skill": "managing-bitable-write-concurrency",
"Lines": 85,
"VerifyExists": true,
"HasPlan": true,
"HasVerify": true,
"HasExecute": true,
"HasPitfalls": true,
"CmdCount": 2,
"DDSSection": 4,
"DDSLines": 4
}
]

View File

@@ -0,0 +1,220 @@
---
name: developing-feishu-bitable
description: >
飞书多维表格BitableGo SDK 全栈开发指导 SkillFull-stack development guide for Feishu/Lark Bitable using Go SDK。涵盖 oapi-sdk-go 初始化、App/Table/View/Record/Field CRUD API、字段类型与数据结构、记录筛选 Filter 语法、事件订阅(字段变更/记录变更)、长连接/Webhook 事件处理、高级权限Role/Member管理。触发场景 Trigger: 使用 Go 开发飞书多维表格集成时、调用 Bitable API 时、处理多维表格事件回调时、操作字段/记录/视图时。关键词 Keywords: feishu, lark, bitable, 多维表格, Go SDK, oapi-sdk-go, app_token, table_id, record, field, view, filter, event, webhook, 长连接, tenant_access_token, 高级权限。
argument-hint: "<action> <target> - e.g., 'create record', 'list fields', 'subscribe event', 'filter records'"
allowed-tools:
- Read
- Glob
- Grep
---
# Developing Feishu Bitable
本 Skill 是飞书多维表格BitableGo 后端开发的唯一全栈向导。基于 `oapi-sdk-go/v3` SDK覆盖
App/Table/View/Record/Field/Role/Member 全部资源的 CRUD API、字段类型系统、记录筛选公式、
事件订阅(字段变更 + 记录变更)、长连接/HTTP 回调模式、以及高级权限管理。
**核心技术栈**Go ≥ 1.18 · `github.com/larksuite/oapi-sdk-go/v3` · REST API · WebSocket 长连接
## Quick Context
```bash
# 动态注入:查看项目中已有的 Bitable 相关代码
!`grep -rn "larkbitable\|Bitable\|bitable\|AppTableRecord\|AppTableField" --include="*.go" . | head -30`
# 动态注入:查看 SDK 依赖版本
!`grep "oapi-sdk-go" go.mod 2>/dev/null || echo "SDK not in go.mod"`
# 动态注入:查看事件处理相关代码
!`grep -rn "EventDispatcher\|OnP2\|larkws\|webhook" --include="*.go" . | head -20`
```
## Plan
### 产物清单
- [ ] SDK Client 初始化模块(含 token 缓存配置)
- [ ] Bitable CRUD 服务层Record/Field/View/Table 操作封装)
- [ ] 字段类型映射与序列化/反序列化逻辑
- [ ] 记录筛选 Filter 构建器
- [ ] 事件订阅处理器(记录变更 / 字段变更)
- [ ] 高级权限管理Role/Member如需要
### 决策点
1. **凭证模式选择**`tenant_access_token`纯后端服务vs `user_access_token`代用户操作。SDK 自动管理 tenant token 的获取与缓存,但不管理 user token。
2. **事件接收模式**推荐长连接WebSocket免内网穿透、无需解密验签生产集群部署时注意集群模式为随机分发而非广播。
3. **批量操作策略**:批量 APIbatch_create/batch_update/batch_delete单次限 500 条,结果全成功或全失败,无部分结果。
## Verify
> 验证按 SDK 初始化 → API 调用 → 字段处理 → 事件 → 权限 顺序。
### SDK 初始化验证
- [ ] `lark.NewClient(appID, appSecret)` 中 appID/appSecret 来自开发者后台,不硬编码
- [ ] `lark.WithEnableTokenCache(true)` 已启用(默认开启)
- [ ] 商店应用调用时附带 `larkcore.WithTenantKey(tenantKey)`
### API 调用验证
- [ ] 所有 API 调用统一使用 Builder 模式:`NewXxxReqBuilder().XxxField(val).Build()`
- [ ] 分页查询使用 `PageToken` + `PageSize`(单次最多 500 条记录)
- [ ] API 路径中的 `app_token``table_id` 来自配置或动态获取,不硬编码
- [ ] 响应处理先检查 `resp.Success()`,失败时记录 `resp.Code``resp.Msg``resp.RequestId()`
### 字段类型验证
- [ ] 字段 type 枚举与 `reference/02-data-model/field-types.md` 一致1=文本, 2=数字, 3=单选...
- [ ] 写入日期字段使用 **毫秒级 Unix 时间戳**number
- [ ] 写入人员字段使用 `[{"id": "ou_xxx"}]` 格式
- [ ] 写入单向关联字段使用 `["record_id_1", "record_id_2"]` 格式
- [ ] 数字字段写入用 number 类型,读取时返回 string需类型转换
### 事件处理验证
- [ ] 长连接 `dispatcher.NewEventDispatcher("", "")` 两个参数填**空字符串**
- [ ] HTTP 回调模式需传入正确的 `verificationToken``eventEncryptKey`
- [ ] 事件处理在 **3 秒内**完成,否则触发超时重推
- [ ] 记录变更事件类型与 `reference/04-events/record-changed.md` 中 action 枚举一致
- [ ] 公式字段值变化**不会触发**记录变更事件
### 权限验证
- [ ] 使用 `tenant_access_token` 前,确认应用已加入目标多维表格的协作者列表
- [ ] 高级权限 API 调用前,确认多维表格已开启高级权限
## Execute
> 开发顺序SDK 初始化 → CRUD API → 字段处理 → 筛选 → 事件 → 权限
### Step 1SDK Client 初始化
```go
import lark "github.com/larksuite/oapi-sdk-go/v3"
client := lark.NewClient(appID, appSecret,
lark.WithEnableTokenCache(true), // 自动管理 tenant_access_token
)
// 方法映射client.Bitable.V1.<资源>.<动作>(ctx, req)
```
**关键约束**
- SDK **仅**托管 `tenant_access_token``user_access_token` 需自行获取与刷新
- 未封装的 API 可用 `client.Do()` 原生调用(参考 `reference/01-sdk-guide/raw-api-call.md`
### Step 2Record CRUD 实现
`reference/03-api-reference/record-apis.md` 中的 OpenAPI Spec 实现:
```go
// 列出记录(分页)
req := larkbitable.NewListAppTableRecordReqBuilder().
AppToken(appToken).TableId(tableId).
PageSize(500). // 单次最多 500
Filter(filterExpression). // 可选筛选
Build()
resp, err := client.Bitable.V1.AppTableRecord.List(ctx, req)
// 新增记录
fields := map[string]interface{}{
"文本字段": "value",
"数字字段": 42, // 写入用 number
"日期字段": 1672531200000, // 毫秒 Unix 时间戳
"人员字段": []map[string]string{{"id": "ou_xxx"}},
"单选字段": "选项A",
"多选字段": []string{"选项A", "选项B"},
}
```
### Step 3字段类型处理
根据 `reference/02-data-model/field-types.md``reference/02-data-model/field-edit-guide.md`
| type 值 | 类型 | 写入格式 | 读取格式 |
|---------|------|---------|---------|
| 1 | 多行文本 | `string` | `string` |
| 2 | 数字 | `number` | `string`(需转换!) |
| 3 | 单选 | `string`(选项名) | `string` |
| 4 | 多选 | `[]string` | `[]string` |
| 5 | 日期 | `number`(ms timestamp) | `number` |
| 7 | 复选框 | `boolean` | `boolean` |
| 11 | 人员 | `[{"id":"ou_xxx"}]` | `[{name,id,email}]` |
| 17 | 附件 | 需先上传获取 file_token | `[{file_token,name,url}]` |
| 18 | 单向关联 | `["record_id"]` | `["record_id"]` |
**注意**:双向关联(21)、公式(20)、查找引用(19) **不支持写入**
### Step 4记录筛选 Filter 构建
根据 `reference/03-api-reference/filter-guide.md`
```
// 语法CurrentValue.[字段名] 运算符 值
filter := `CurrentValue.[状态] = "进行中"`
filter := `AND(CurrentValue.[类型]="需求", CurrentValue.[优先级]>=3)`
filter := `CurrentValue.[创建时间] > TODAY()`
// ⚠️ URL 编码注意:+ 号须编码为 %2B
```
### Step 5事件订阅处理
根据 `reference/04-events/record-changed.md``reference/01-sdk-guide/event-handling.md`
```go
// 推荐:长连接模式(免内网穿透)
eventHandler := dispatcher.NewEventDispatcher("", ""). // 必须空串
OnCustomizedEvent("drive.file.bitable_record_changed_v1",
func(ctx context.Context, event *larkevent.EventReq) error {
// event.Body 中 action_list 包含变更详情
// action: record_added / record_edited / record_deleted
return nil // 3 秒内返回
})
cli := larkws.NewClient(appID, appSecret,
larkws.WithEventHandler(eventHandler),
larkws.WithLogLevel(larkcore.LogLevelDebug),
)
cli.Start(ctx) // 阻塞主线程
```
### Step 6高级权限管理如适用
根据 `reference/05-permissions/role-member-apis.md`
1. 先通过更新元数据 API 开启高级权限
2. 创建自定义角色(`AppRole.Create`
3. 为角色添加协作者(`AppRoleMember.Create`
4. 开启后可能有延迟,遇到 `OperationTypeError` 需重试
## Pitfalls
1. **数字字段读写类型不一致**:写入时是 `number`,但列出记录时返回 `string`,需做类型转换。忽略此差异会导致 JSON 反序列化失败。(参考 `reference/02-data-model/field-types.md`
2. **日期字段用毫秒而非秒**:日期字段的 value 是**毫秒级** Unix 时间戳。若误传秒级时间戳,结果日期将是 1970 年附近。(参考 `reference/02-data-model/field-types.md`
3. **长连接 EventDispatcher 参数必须为空串**:使用长连接模式时 `dispatcher.NewEventDispatcher("", "")`传非空值会导致签名验证失败。HTTP 回调模式才需要传 verificationToken 和 encryptKey。参考 `reference/01-sdk-guide/event-handling.md`
4. **批量操作全成功或全失败**`batch_create`/`batch_update`/`batch_delete` 不存在部分成功的结果。若其中一条记录有问题,整个请求全部失败。(参考 `reference/03-api-reference/record-apis.md`
5. **公式字段变化不触发事件**:记录变更事件 `drive.file.bitable_record_changed_v1` 不会因公式字段值的变化而触发。如果业务依赖公式结果变化,需通过轮询方式检测。(参考 `reference/04-events/record-changed.md`
6. **同一时刻对同一多维表格仅一次写操作**:并发写入同一张多维表格可能导致数据冲突。需用串行写入队列或乐观锁策略。(参考 `reference/03-api-reference/record-apis.md`
7. **字段更新是全量覆盖**:更新字段的 `property` 是全量替换而非增量 merge。更新单选/多选字段时必须传入完整的 options 列表,否则未传入的选项会被删除。(参考 `reference/02-data-model/field-edit-guide.md`
8. **Filter 中 + 号须 URL 编码为 %2B**:在日期表达式如 `TODAY()+1` 中,`+` 需编码为 `%2B`,否则服务端会将其解析为空格。(参考 `reference/03-api-reference/filter-guide.md`
## Related References
| 需要了解... | 查阅... |
|------------|--------|
| Go SDK 安装初始化、Client 构建 | `reference/01-sdk-guide/sdk-setup.md` |
| 原生调用未封装 API | `reference/01-sdk-guide/raw-api-call.md` |
| 事件/回调处理(长连接+HTTP | `reference/01-sdk-guide/event-handling.md` |
| Bitable 资源模型App/Table/View/Record/Field | `reference/02-data-model/resource-model.md` |
| 字段类型系统type 枚举、读写格式) | `reference/02-data-model/field-types.md` |
| 字段 Property 编辑指南 | `reference/02-data-model/field-edit-guide.md` |
| Record CRUD API含 OpenAPI Spec | `reference/03-api-reference/record-apis.md` |
| Table/View/Field/App API | `reference/03-api-reference/table-view-field-apis.md` |
| 记录筛选 Filter 公式语法 | `reference/03-api-reference/filter-guide.md` |
| 附件上传/下载 | `reference/03-api-reference/attachment.md` |
| 记录变更事件action + 回调体) | `reference/04-events/record-changed.md` |
| 字段变更事件 | `reference/04-events/field-changed.md` |
| 高级权限 Role/Member API | `reference/05-permissions/role-member-apis.md` |
| 鉴权模式与 QPS 限制 | `reference/05-permissions/auth-and-limits.md` |
| SDK 常见问题与排错 | `reference/06-faq/common-issues.md` |

View File

@@ -0,0 +1,129 @@
// bitable_client.go - 飞书多维表格 SDK Client 初始化骨架
//
// 设计决策:
// 1. 使用 tenant_access_token纯后端服务场景
// 2. 启用 token 缓存SDK 自动管理 token 生命周期)
// 3. 通过环境变量注入 App ID/Secret避免硬编码
package bitable
import (
"context"
"fmt"
"os"
lark "github.com/larksuite/oapi-sdk-go/v3"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkbitable "github.com/larksuite/oapi-sdk-go/v3/service/bitable/v1"
)
// Config 存储多维表格连接配置
type Config struct {
AppID string // 飞书应用 App ID
AppSecret string // 飞书应用 App Secret
AppToken string // 目标多维表格的 app_token
TableID string // 目标数据表的 table_id
}
// Client 封装飞书 Bitable SDK Client
type Client struct {
larkClient *lark.Client
config Config
}
// NewClient 创建 Bitable Client
func NewClient(cfg Config) *Client {
client := lark.NewClient(cfg.AppID, cfg.AppSecret,
lark.WithEnableTokenCache(true), // 自动管理 tenant_access_token
)
return &Client{
larkClient: client,
config: cfg,
}
}
// NewClientFromEnv 从环境变量创建 Client
func NewClientFromEnv() *Client {
return NewClient(Config{
AppID: os.Getenv("FEISHU_APP_ID"),
AppSecret: os.Getenv("FEISHU_APP_SECRET"),
AppToken: os.Getenv("FEISHU_APP_TOKEN"),
TableID: os.Getenv("FEISHU_TABLE_ID"),
})
}
// ListRecords 列出记录(带分页)
// filter: 筛选表达式,如 `CurrentValue.[状态]="进行中"`
func (c *Client) ListRecords(ctx context.Context, filter string, pageToken string) ([]*larkbitable.AppTableRecord, string, error) {
builder := larkbitable.NewListAppTableRecordReqBuilder().
AppToken(c.config.AppToken).
TableId(c.config.TableID).
PageSize(500) // 单次最多 500
if filter != "" {
builder.Filter(filter)
}
if pageToken != "" {
builder.PageToken(pageToken)
}
resp, err := c.larkClient.Bitable.V1.AppTableRecord.List(ctx, builder.Build())
if err != nil {
return nil, "", fmt.Errorf("list records: %w", err)
}
if !resp.Success() {
return nil, "", fmt.Errorf("list records failed: code=%d msg=%s requestId=%s",
resp.Code, resp.Msg, resp.RequestId())
}
nextPageToken := ""
if resp.Data.PageToken != nil {
nextPageToken = *resp.Data.PageToken
}
return resp.Data.Items, nextPageToken, nil
}
// CreateRecord 新增单条记录
// fields: map[string]interface{} 字段名 -> 值
func (c *Client) CreateRecord(ctx context.Context, fields map[string]interface{}) (string, error) {
req := larkbitable.NewCreateAppTableRecordReqBuilder().
AppToken(c.config.AppToken).
TableId(c.config.TableID).
AppTableRecord(larkbitable.NewAppTableRecordBuilder().
Fields(fields).
Build()).
Build()
resp, err := c.larkClient.Bitable.V1.AppTableRecord.Create(ctx, req)
if err != nil {
return "", fmt.Errorf("create record: %w", err)
}
if !resp.Success() {
return "", fmt.Errorf("create record failed: code=%d msg=%s requestId=%s",
resp.Code, resp.Msg, resp.RequestId())
}
return *resp.Data.Record.RecordId, nil
}
// UpdateRecord 更新单条记录
// fields: 需要更新的字段(增量更新)
func (c *Client) UpdateRecord(ctx context.Context, recordID string, fields map[string]interface{}) error {
req := larkbitable.NewUpdateAppTableRecordReqBuilder().
AppToken(c.config.AppToken).
TableId(c.config.TableID).
RecordId(recordID).
AppTableRecord(larkbitable.NewAppTableRecordBuilder().
Fields(fields).
Build()).
Build()
resp, err := c.larkClient.Bitable.V1.AppTableRecord.Update(ctx, req)
if err != nil {
return fmt.Errorf("update record: %w", err)
}
if !resp.Success() {
return fmt.Errorf("update record failed: code=%d msg=%s requestId=%s",
resp.Code, resp.Msg, resp.RequestId())
}
return nil
}

View File

@@ -0,0 +1,87 @@
// event_handler.go - 飞书多维表格事件处理骨架
//
// 设计决策:
// 1. 使用长连接模式(推荐):免内网穿透、无需解密验签
// 2. EventDispatcher 参数必须为空字符串(长连接要求)
// 3. 事件处理需在 3 秒内完成,耗时操作应异步化
package bitable
import (
"context"
"encoding/json"
"fmt"
"log"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkevent "github.com/larksuite/oapi-sdk-go/v3/event"
"github.com/larksuite/oapi-sdk-go/v3/event/dispatcher"
larkws "github.com/larksuite/oapi-sdk-go/v3/ws"
)
// RecordAction 记录变更事件中的单个操作
type RecordAction struct {
Action string `json:"action"` // record_added / record_edited / record_deleted
RecordID string `json:"record_id"`
BeforeValue []FieldValue `json:"before_value"`
AfterValue []FieldValue `json:"after_value"`
}
// FieldValue 字段值
type FieldValue struct {
FieldID string `json:"field_id"`
FieldValue string `json:"field_value"` // JSON 序列化后的字符串
}
// RecordChangedEvent 记录变更事件体
type RecordChangedEvent struct {
Event struct {
FileToken string `json:"file_token"` // 多维表格 app_token
FileType string `json:"file_type"` // 固定 "bitable"
TableID string `json:"table_id"`
ActionList []RecordAction `json:"action_list"`
OperatorID struct {
OpenID string `json:"open_id"`
UnionID string `json:"union_id"`
UserID string `json:"user_id"`
} `json:"operator_id"`
} `json:"event"`
}
// RecordChangeHandler 记录变更回调函数类型
type RecordChangeHandler func(ctx context.Context, event RecordChangedEvent) error
// StartEventListener 启动长连接事件监听器
//
// appID, appSecret: 飞书应用凭证
// handler: 记录变更事件处理函数
//
// ⚠️ 此函数会阻塞主线程
func StartEventListener(appID, appSecret string, handler RecordChangeHandler) error {
// ⚠️ 长连接模式:两个参数必须为空字符串
eventHandler := dispatcher.NewEventDispatcher("", "").
OnCustomizedEvent("drive.file.bitable_record_changed_v1",
func(ctx context.Context, event *larkevent.EventReq) error {
var parsed RecordChangedEvent
if err := json.Unmarshal(event.Body, &parsed); err != nil {
log.Printf("parse event failed: %v", err)
return nil // 解析失败也要返回 nil避免重推
}
// 委托给业务处理器
if err := handler(ctx, parsed); err != nil {
log.Printf("handle event failed: %v", err)
// 不返回 error避免触发重推
// 如需重试,在 handler 内部实现异步重试
}
return nil // 3 秒内返回
})
cli := larkws.NewClient(appID, appSecret,
larkws.WithEventHandler(eventHandler),
larkws.WithLogLevel(larkcore.LogLevelDebug),
)
fmt.Println("starting bitable event listener...")
return cli.Start(context.Background()) // 阻塞主线程
}

View File

@@ -0,0 +1,101 @@
# 事件与回调处理
- **DDS-Section**: 3.5 事件与回调处理 / B.4 处理事件 / B.5 处理回调
- **DDS-Lines**: L86-L91, L16843-L17528
## Extract
### 两种事件接收模式
| 模式 | 优势 | 限制 |
|------|------|------|
| **长连接WebSocket** | 免内网穿透、无需解密验签、SDK 内置鉴权 | 仅限企业自建应用,每应用最多 50 连接 |
| **HTTP 回调Webhook** | 支持所有应用类型 | 需公网地址、需处理解密验签 |
### 关键约束
- 长连接模式是**集群分发**,不是广播;同应用多实例时由随机一个实例消费
- 无论哪种模式,事件处理**需在 3 秒内完成**,否则触发超时重推
- HTTP 回调模式服务端需在 3 秒内返回 HTTP 200 状态码
### 长连接示例(推荐)
```go
package main
import (
"context"
"fmt"
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
larkevent "github.com/larksuite/oapi-sdk-go/v3/event"
"github.com/larksuite/oapi-sdk-go/v3/event/dispatcher"
larkws "github.com/larksuite/oapi-sdk-go/v3/ws"
)
func main() {
// ⚠️ 长连接模式:两个参数必须填空字符串
eventHandler := dispatcher.NewEventDispatcher("", "").
OnCustomizedEvent("drive.file.bitable_record_changed_v1",
func(ctx context.Context, event *larkevent.EventReq) error {
fmt.Printf("record changed: %s\n", string(event.Body))
return nil // 3 秒内返回
})
cli := larkws.NewClient("YOUR_APP_ID", "YOUR_APP_SECRET",
larkws.WithEventHandler(eventHandler),
larkws.WithLogLevel(larkcore.LogLevelDebug),
)
// 启动客户端,主线程阻塞
err := cli.Start(context.Background())
if err != nil {
panic(err)
}
}
```
### HTTP 回调模式示例
```go
// HTTP 模式:需传入 verificationToken 和 eventEncryptKey
handler := dispatcher.NewEventDispatcher("verificationToken", "eventEncryptKey")
handler = handler.OnCustomizedEvent("drive.file.bitable_record_changed_v1",
func(ctx context.Context, event *larkevent.EventReq) error {
fmt.Println(string(event.Body))
return nil
})
http.HandleFunc("/webhook/event", httpserverext.NewEventHandlerFunc(handler,
larkevent.WithLogLevel(larkcore.LogLevelDebug)))
http.ListenAndServe(":9999", nil)
```
### Gin 框架集成
```bash
go get -u github.com/larksuite/oapi-sdk-gin
```
```go
gin.POST("/webhook/event", sdkginext.NewEventHandlerFunc(handler))
```
### 事件版本说明
| 版本 | 注册方法 | 说明 |
|------|---------|------|
| v2.0 | `OnP2XxxV1(...)` | P2 前缀 = v2.0 版本事件结构 |
| v1.0 | `OnCustomizedEvent("event_key", ...)` | 自定义事件 key |
### 回调处理(卡片交互等)
长连接模式下处理卡片回传交互:
```go
eventHandler := dispatcher.NewEventDispatcher("", "").
OnP2CardActionTrigger(func(ctx context.Context, event *callback.CardActionTriggerEvent) (*callback.CardActionTriggerResponse, error) {
fmt.Println(larkcore.Prettify(event))
return nil, nil
})
```
HTTP 模式下处理旧版卡片回调(使用 `larkcard.NewCardActionHandler`)。

View File

@@ -0,0 +1,30 @@
# 原生调用未封装 API
- **DDS-Section**: 3.4 历史/未封装 API 的原生调用
- **DDS-Lines**: L72-L84
## Extract
当 SDK 暂未提供强类型方法时,可用 `client.Do()` 进行原生调用:
```go
resp, err := client.Do(context.Background(), &larkcore.ApiReq{
HttpMethod: http.MethodGet,
ApiPath: "https://open.feishu.cn/open-apis/contact/v3/users/:user_id",
PathParams: larkcore.PathParams{"user_id": "ou_xxx"},
QueryParams: larkcore.QueryParams{"user_id_type": []string{"open_id"}},
SupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeUser},
})
```
### 使用场景
- SDK 版本落后于 API 更新
- 历史版本接口调用
- 特殊参数需求(如自定义 Header
### 注意事项
- `ApiPath` 使用完整的 API URL
- `PathParams` 中的键名对应 URL 中的 `:key` 占位符
- `SupportedAccessTokenTypes` 必须指定凭证类型

View File

@@ -0,0 +1,73 @@
# Go SDK 安装与初始化
- **DDS-Section**: 3. Golang SDK 调用说明 / B.2 开发前准备
- **DDS-Lines**: L23-L97, L16549-L16586
## Extract
### 安装
```bash
go get -u github.com/larksuite/oapi-sdk-go/v3@latest
```
### Client 初始化
```go
import lark "github.com/larksuite/oapi-sdk-go/v3"
client := lark.NewClient(appID, appSecret,
// lark.WithMarketplaceApp(), // 商店应用时启用
lark.WithEnableTokenCache(true), // 默认启用,自动管理 tenant_access_token
)
```
### 关键约束
| 约束 | 说明 |
|------|------|
| Token 托管 | SDK 自动获取和缓存 `tenant_access_token``app_access_token`,无需手动管理 |
| user_access_token | SDK **不**托管,需自行实现获取/刷新逻辑 |
| 商店应用 | 调用时需补 `larkcore.WithTenantKey(tenantKey)` |
### Bitable API 调用范式
SDK 方法映射规则:`client.Bitable.V1.<资源>.<动作>(ctx, req)`
```go
req := larkbitable.NewListAppTableRecordReqBuilder().
AppToken("app_token").
TableId("table_id").
PageSize(20).
Build()
resp, err := client.Bitable.V1.AppTableRecord.List(context.Background(), req)
if err != nil {
// 网络错误
panic(err)
}
if !resp.Success() {
// 业务错误
fmt.Println(resp.Code, resp.Msg, resp.RequestId())
return
}
fmt.Println(larkcore.Prettify(resp.Data))
```
### 请求级选项
| 选项 | 用途 |
|------|------|
| `larkcore.WithUserAccessToken(...)` | 用户态调用 |
| `larkcore.WithTenantAccessToken(...)` | 手动传租户 token |
| `larkcore.WithTenantKey(...)` | 商店应用必须设置 |
| `larkcore.WithHeaders(...)` | 透传自定义 Header |
### 本地示例代码位置
| 路径 | 内容 |
|------|------|
| `offline-docs-v2/go-sdk-examples/oapi-sdk-go/sample/apiall/bitablev1/` | Bitable v1 全量 API 样例 |
| `offline-docs-v2/go-sdk-examples/oapi-sdk-go/sample/api/bitable2.go` | 复杂字段示例 |
| `offline-docs-v2/go-sdk-examples/oapi-sdk-go-demo/` | 官方场景化 Demo |
| `offline-docs-v2/go-sdk-examples/bitablev1-curated/` | 精选拷贝 |

View File

@@ -0,0 +1,136 @@
# 字段 Property 编辑指南
- **DDS-Section**: A.5 字段编辑指南 - Property 说明
- **DDS-Lines**: L734-L1370
## Extract
> ⚠️ **关键约束**:更新字段时为**全量更新**`property` 会被完全覆盖。更新单选/多选字段时,必须传入完整的 options 列表。
### 数字字段 Property
| 名称 | 类型 | 说明 | 默认值 |
|------|------|------|--------|
| `formatter` | string | 数字显示格式 | `"0.0"` |
**formatter 对照表**
| 格式 | formatter 值 |
|------|-------------|
| 整数 | `"0"` |
| 保留1位小数 | `"0.0"` |
| 保留2位小数 | `"0.00"` |
| 千分位 | `"1,000"` |
| 千分位(小数) | `"1,000.00"` |
| 百分比 | `"%"` |
| 百分比(小数) | `"0.00%"` |
| 人民币 | `"¥"` |
| 人民币(小数) | `"¥0.00"` |
| 美元 | `"$"` |
| 美元(小数) | `"$0.00"` |
```json
{
"field_name": "数字",
"type": 2,
"property": {
"formatter": "0.00"
}
}
```
### 单选/多选字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `options` | array | 选项列表 |
| `options[].name` | string | 选项名 |
| `options[].id` | string | 选项 ID更新时如果保留已有选项需传入 |
| `options[].color` | int | 选项颜色0-54 |
**⚠️ 更新时必须传入完整 options 列表**
```json
// 新增字段:只需 name 和 color
{
"field_name": "任务状态",
"type": 3,
"property": {
"options": [
{"name": "待处理", "color": 0},
{"name": "进行中", "color": 1}
]
}
}
// 更新字段:保留已有选项需带上 id
{
"field_name": "任务状态",
"type": 3,
"property": {
"options": [
{"name": "待处理", "color": 0, "id": "optXXX1"},
{"name": "进行中", "color": 1, "id": "optXXX2"},
{"name": "已完成", "color": 2} // 新增选项不需要 id
]
}
}
```
### 日期字段 Property
| 名称 | 类型 | 说明 | 默认值 |
|------|------|------|--------|
| `date_formatter` | string | 日期显示格式 | `"yyyy/MM/dd"` |
| `auto_fill` | boolean | 新记录自动填写创建时间 | `false` |
### 人员字段 Property
| 名称 | 类型 | 说明 | 默认值 |
|------|------|------|--------|
| `multiple` | boolean | 允许添加多个成员 | `false` |
### 单向关联字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `table_id` | string | 关联的数据表 ID必填 |
| `multiple` | boolean | 允许关联多条记录 |
### 双向关联字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `table_id` | string | 关联的数据表 ID必填 |
| `back_field_name` | string | 对向关联字段名(必填) |
| `multiple` | boolean | 允许关联多条记录 |
### 公式字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `formula_expression` | string | 公式表达式(⚠️ 创建/更新字段时不支持设置公式表达式) |
| `formatter` | string | 显示格式 |
### 创建时间/最后更新时间字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `date_formatter` | string | 日期显示格式 |
### 自动编号字段 Property
| 名称 | 类型 | 说明 |
|------|------|------|
| `auto_serial` | object | 编号规则配置 |
| `auto_serial.type` | string | 类型:`auto_increment_number`(自增数字), `custom`(自定义) |
| `auto_serial.options` | array | 自定义规则列表 |
| `auto_serial.options[].type` | string | 规则项类型:`system_number`(自增编号), `fixed_text`(固定字符), `created_time`(创建时间) |
| `auto_serial.options[].value` | string | 与类型对应的取值 |
### 各字段类型的 API 支持情况
| 操作 | 支持的字段类型 | 不支持 |
|------|-------------|--------|
| 新增/更新记录 | 文本、单选、多选、日期、人员、附件、复选框、超链接、数字、单向关联、电话、地理位置 | 双向关联、公式、查找引用 |
| 新增/更新字段 | 文本、单选、多选、日期、数字、人员、附件、单向/双向关联、复选框、超链接、公式(不支持设表达式)、创建人、修改人、创建时间、更新时间、自动编号、电话、地理位置 | 查找引用 |

View File

@@ -0,0 +1,107 @@
# 字段类型系统
- **DDS-Section**: A.3 数据结构 / A.5 字段编辑指南 - 字段概述
- **DDS-Lines**: L479-L604, L717-L733
## Extract
### 字段 type 枚举
| type 值 | 类型名 | 读取格式 | 写入格式 | 可写入 |
|---------|--------|---------|---------|--------|
| 1 | 多行文本 | `string` | `string` | ✅ |
| 2 | 数字 | `string` ⚠️ | `number` | ✅ |
| 3 | 单选 | `string` | `string`(选项名) | ✅ |
| 4 | 多选 | `[]string` | `[]string` | ✅ |
| 5 | 日期 | `number`(ms) | `number`(ms timestamp) | ✅ |
| 7 | 复选框 | `boolean` | `boolean` | ✅ |
| 11 | 人员 | `[{name,id,en_name,email}]` | `[{"id":"ou_xxx"}]` | ✅ |
| 13 | 电话号码 | `string` | `string`(正则 `(\+)?\d*`) | ✅ |
| 15 | 超链接 | `{text,link}` | `{text,link}` | ✅ |
| 17 | 附件 | `[{file_token,name,type,size,url,tmp_url}]` | 需先上传获取 file_token | ✅ |
| 18 | 单向关联 | `[]string`(record_id) | `[]string`(record_id) | ✅ |
| 19 | 查找引用 | - | - | ❌ |
| 20 | 公式 | 取决于公式返回类型 | - | ❌ |
| 21 | 双向关联 | 只读 | - | ❌ |
| 22 | 地理位置 | `{location,pname,cityname,adname,address,name,full_address}` | 同结构 | ✅ |
| 1001 | 创建时间 | `number`(ms) | - | ❌(自动) |
| 1002 | 最后更新时间 | `number`(ms) | - | ❌(自动) |
| 1003 | 创建人 | `{name,id,en_name,email}` | - | ❌(自动) |
| 1004 | 修改人 | `{name,id,en_name,email}` | - | ❌(自动) |
| 1005 | 自动编号 | `string` | - | ❌(自动) |
### ⚠️ 关键陷阱:数字字段读写不一致
- **写入时**:值为 `number` 类型(如 `42``3.14`
- **读取时**:值为 `string` 类型(如 `"42"``"3.14"`
- 必须在代码中做类型转换
### 人员对象结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | 名字 |
| `id` | string | user open_id |
| `en_name` | string | 英文名 |
| `email` | string | 邮箱 |
### 超链接对象结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `text` | string | 文本名称 |
| `link` | string | 超链接 URL |
### 附件对象结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `file_token` | string | 附件 token |
| `name` | string | 附件名称 |
| `type` | string | MIME 类型,如 `image/png` |
| `size` | int | 大小(字节) |
| `url` | string | 附件 URL需鉴权下载 |
| `tmp_url` | string | 临时下载链接(需 access token |
### 地理位置对象结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `location` | string | 经纬度 |
| `pname` | string | 省 |
| `cityname` | string | 市 |
| `adname` | string | 区 |
| `address` | string | 详细地址 |
| `name` | string | 地名 |
| `full_address` | string | 完整地址 |
### Record 结构
```json
{
"record_id": "recn0hoyXL",
"fields": {
"字段名1": "值",
"字段名2": 42
}
}
```
- `fields``map[string]interface{}`key 为字段名(非 field_idvalue 类型随字段类型而异
### 视图结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `view_id` | string | 视图 ID |
| `view_name` | string | 视图名称 |
| `view_type` | string | 类型grid, kanban, gallery, gantt |
### 字段结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `field_id` | string | 字段 ID |
| `field_name` | string | 字段名 |
| `type` | int | 字段类型枚举 |
| `property` | object | 字段属性,因类型而异(见 field-edit-guide.md |

View File

@@ -0,0 +1,81 @@
# Bitable 资源模型
- **DDS-Section**: A.1 概述 / A.2 接入指南 - 2.内容
- **DDS-Lines**: L107-L260, L268-L310
## Extract
### 资源层级
```
Bitable App (app_token)
├── Table (table_id) # 最多 100 个/App
│ ├── View (view_id) # 最多 200 个/Table
│ ├── Field (field_id) # 最多 150 个/Table
│ └── Record (record_id) # 最多 20000 条/Table
├── Role (role_id) # 最多 30 个/App高级权限
│ └── Member (member_id) # 最多 200 个/Role
└── Dashboard # 仪表盘
```
### 资源标识符
| 标识符 | 唯一范围 | 获取方式 |
|--------|---------|---------|
| `app_token` | 全局唯一 | URL 中直接获取,或从文档 block 中解析 |
| `table_id` | App 内唯一 | URL 中获取或 `List Table` API |
| `view_id` | App 内唯一 | URL 中获取或 `List View` API |
| `record_id` | App 内唯一 | `List Record` API |
| `field_id` | App 内唯一 | `List Field` API |
| `role_id` | App 内唯一 | `List Role` API |
| `member_id` | Role 内唯一 | `List Member` API |
### API 基础路径
```
https://open.feishu.cn/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/:record_id
```
### app_token 获取方式
**Bitable App**(独立多维表格):
- URL 中直接截取:`feishu.cn/base/<app_token>`
**Bitable Doc Block**(文档内嵌):
- 调用「获取文档所有块」API`bitable.token` 字段值用 `_` 分隔 = `app_token_tableId`
**Bitable Sheet Block**(表格内嵌):
- 调用「获取表格元数据」API`blockType=BITABLE_BLOCK``blockToken``_` 分隔
### 多维表格三种形态
| 形态 | URL 特征 | 说明 |
|------|---------|------|
| Bitable App | `feishu.cn/base` | 飞书云文档中独立创建 |
| Bitable Doc Block | `feishu.cn/docs``feishu.cn/docx` | 飞书文档中插入 |
| Bitable Sheet Block | `feishu.cn/sheets` | 飞书表格中新建 |
### 每种资源的 API 方法一览
| 资源 | 方法 |
|------|------|
| App | Get, Update |
| Table | List, Create, BatchCreate, Delete, BatchDelete |
| View | List, Create, Delete, Get, Update |
| Record | List, Get, Create, BatchCreate, Update, BatchUpdate, Delete, BatchDelete |
| Field | List, Create, Update, Delete |
| Role | List, Create, Update, Delete |
| Member | List, Create, Delete, BatchCreate, BatchDelete |
| Dashboard | List, Copy |
| Form | GetMeta, UpdateMeta, ListFields, UpdateField |
### 容量限制
| 资源 | 限制 |
|------|------|
| 记录 | 最多 20,000 条/表 |
| 字段 | 最多 150 个/表 |
| 视图 | 最多 200 个/表 |
| 数据表 | 最多 100 个/App |
| 自定义权限 | 最多 30 条/App |
| 权限协作者 | 最多 200 个/角色 |

View File

@@ -0,0 +1,74 @@
# 附件字段说明
- **DDS-Section**: A.6 附件字段说明
- **DDS-Lines**: L1370-L1541
## Extract
### 附件对象结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `file_token` | string | 附件 token用于下载 |
| `name` | string | 附件名称 |
| `type` | string | MIME 类型,如 `image/png` |
| `size` | int | 文件大小(字节) |
| `url` | string | 附件 URL |
| `tmp_url` | string | 临时下载链接(需 access token 鉴权) |
### 上传附件
**步骤**
1. 先调用云空间文件上传 API 获得 `file_token`
2. 再将 `file_token` 写入记录的附件字段
**上传接口**`POST /open-apis/drive/v1/medias/upload_all`
```go
// 上传文件到多维表格
req := larkdrive.NewUploadAllMediaReqBuilder().
Body(larkdrive.NewUploadAllMediaReqBodyBuilder().
FileName("test.pdf").
ParentType("bitable_file").
ParentNode(appToken).
Size(fileSize).
File(fileReader).
Build()).
Build()
resp, err := client.Drive.V1.Media.UploadAll(ctx, req)
// 从 resp 中获取 file_token
```
**写入记录**
```json
{
"fields": {
"附件字段": [{"file_token": "获得的file_token"}]
}
}
```
### 下载附件
**方式一**:使用 `tmp_url`(临时下载链接)
- 附件对象中的 `tmp_url` 字段提供临时下载能力
- 需要携带 `access_token` 进行鉴权
**方式二**:使用云空间下载 API
- `GET /open-apis/drive/v1/medias/:file_token/download`
```go
req := larkdrive.NewDownloadMediaReqBuilder().
FileToken(fileToken).
Build()
resp, err := client.Drive.V1.Media.Download(ctx, req)
// resp.File 即文件内容io.Reader
```
### 注意事项
- `parent_type` 对于多维表格固定为 `"bitable_file"`
- `parent_node` 为多维表格的 `app_token`
- 上传大文件时需要使用分片上传 API

View File

@@ -0,0 +1,81 @@
# 记录筛选 Filter 公式指南
- **DDS-Section**: A.4 记录筛选开发指南
- **DDS-Lines**: L614-L707
## Extract
### 语法基础
- 表达式语法:`CurrentValue.[字段名]`C 和 V 必须**大写**
- 支持公式语法,可通过 `AND``OR` 组合
- ⚠️ URL 编码注意:`+` 号需编码为 `%2B`
### 常用运算符
| 逻辑 | 表达式 |
|------|--------|
| 为空 | `CurrentValue.[字段名] = ""` |
| 不为空 | `NOT(CurrentValue.[字段名] = "")` |
| 等于 | `CurrentValue.[字段名] = "值"` |
| 不等于 | `CurrentValue.[字段名] != "值"` |
| 大于等于 | `CurrentValue.[字段名] >= 10.5` |
| 小于等于 | `CurrentValue.[字段名] <= "值"` |
| 包含 | `CurrentValue.[字段名].contains("值")` |
| 不包含 | `NOT(CurrentValue.[字段名].contains("值"))` |
| 与 | `AND(表达式1, 表达式2)``表达式1&&表达式2` |
| 或 | `OR(表达式1, 表达式2)` |
### 日期表达式
| 场景 | 表达式 |
|------|--------|
| 今天 | `CurrentValue.[日期] = TODAY()` |
| 昨天 | `CurrentValue.[日期] = TODAY()-1` |
| 明天 | `CurrentValue.[日期] = TODAY()%2B1` |
| 本周 | `AND(TODAY()-(WEEKDAY(TODAY(),2)-1)<=CurrentValue.[日期], CurrentValue.[日期]<=TODAY()%2B(7-WEEKDAY(TODAY(),2)))` |
| 本月 | `AND(DATE(YEAR(TODAY()),MONTH(TODAY()),1)<=CurrentValue.[日期], CurrentValue.[日期]<=DATE(YEAR(TODAY()),MONTH(TODAY())%2B1,0))` |
| 过去 N 天 | `today()-N%2B1 <= CurrentValue.[日期]&&CurrentValue.[日期] <= today()` |
| 未来 N 天 | `today()<= CurrentValue.[日期]&&CurrentValue.[日期] <= today()%2BN-1` |
| 日期范围 | `CurrentValue.[日期] > TODATE("2021-06-01")&&CurrentValue.[日期] < TODATE("2021-06-30")` |
### 各字段类型筛选示例
| 字段类型 | 示例 |
|---------|------|
| 多行文本 | `CurrentValue.[字段名]="内容a"` |
| 单选 | `CurrentValue.[字段名]="选项内容a"` |
| 多选 | `CurrentValue.[字段名]="选项内容a"` |
| 人员 | `CurrentValue.[人员]="姓名"` |
| 电话号码 | `CurrentValue.[电话号码]="+2020202020"` |
| 日期 | `CurrentValue.[日期] = TODAY()` |
| 数字 | `CurrentValue.[字段名]=1` |
| 复选框 | `CurrentValue.[字段名]=1`1=选中) |
| 超链接 | `CurrentValue.[超链接]="文本值"`(匹配文本部分) |
| 公式 | 数字返回值不需引号:`CurrentValue.[公式]=123` |
| 创建人/修改人 | `CurrentValue.[创建人]="人名"` |
| 创建时间/更新时间 | `CurrentValue.[创建时间]>TODAY()` |
| 自动编号 | `CurrentValue.[自动编号]="001no20220624"` |
| 单向关联 | `CurrentValue.[关联字段]="内容"` |
### Go 代码中使用 Filter
```go
import "net/url"
// 构建 filter 表达式
filter := `AND(CurrentValue.[状态]="进行中", CurrentValue.[优先级]>=3)`
req := larkbitable.NewListAppTableRecordReqBuilder().
AppToken(appToken).
TableId(tableId).
Filter(filter). // SDK 会自动处理 URL 编码
PageSize(500).
Build()
```
### ⚠️ 常见陷阱
1. `CurrentValue` 首字母 C 和 V 必须大写
2. `+` 号在 URL 中会被解析为空格,必须编码为 `%2B`(如 `TODAY()+1``TODAY()%2B1`
3. 字段名使用方括号 `[]` 包裹,中间为字段名原文(非 field_id

View File

@@ -0,0 +1,102 @@
# Record CRUD API 参考
- **DDS-Section**: A.1 概述 - 资源:记录 Record / A.29-A.36 记录 API
- **DDS-Lines**: L172-L196, L8506-L12086
## Extract
### API 路径总览
| 操作 | 方法 | 路径 |
|------|------|------|
| 列出记录 | `GET` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records` |
| 检索记录 | `GET` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/:record_id` |
| 新增记录 | `POST` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records` |
| 新增多条 | `POST` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/batch_create` |
| 更新记录 | `PUT` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/:record_id` |
| 更新多条 | `POST` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/batch_update` |
| 删除记录 | `DELETE` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/:record_id` |
| 删除多条 | `POST` | `/open-apis/bitable/v1/apps/:app_token/tables/:table_id/records/batch_delete` |
### Go SDK 方法映射
```go
client.Bitable.V1.AppTableRecord.List(ctx, req)
client.Bitable.V1.AppTableRecord.Get(ctx, req)
client.Bitable.V1.AppTableRecord.Create(ctx, req)
client.Bitable.V1.AppTableRecord.BatchCreate(ctx, req)
client.Bitable.V1.AppTableRecord.Update(ctx, req)
client.Bitable.V1.AppTableRecord.BatchUpdate(ctx, req)
client.Bitable.V1.AppTableRecord.Delete(ctx, req)
client.Bitable.V1.AppTableRecord.BatchDelete(ctx, req)
```
### 关键约束
| 约束 | 说明 |
|------|------|
| 单次列出上限 | **500 条**(通过 `page_token` 分页) |
| 批量操作上限 | **500 条/次** |
| 批量结果 | **全部成功或全部失败**,无部分结果 |
| 并发写入 | 同一时刻对同一多维表格最好**只请求一次写操作** |
| 权限 | 读取需「查看、评论和导出」;写入需「查看、评论、编辑和管理」 |
### 列出记录 - 关键参数
| 参数 | 类型 | 说明 |
|------|------|------|
| `app_token` | string | 多维表格 token必填 |
| `table_id` | string | 数据表 ID必填 |
| `view_id` | string | 视图 ID可选指定视图范围 |
| `filter` | string | 筛选表达式(可选,语法见 filter-guide.md |
| `sort` | string | 排序条件(可选) |
| `field_names` | string | 指定返回的字段名(可选,逗号分隔) |
| `page_size` | int | 每页数量(可选,最大 500 |
| `page_token` | string | 分页标记(可选) |
### 新增/更新记录 - 请求体
```json
{
"fields": {
"文本字段": "hello",
"数字字段": 42,
"单选字段": "选项A",
"多选字段": ["选项A", "选项B"],
"日期字段": 1672531200000,
"复选框": true,
"人员字段": [{"id": "ou_xxx"}],
"超链接": {"text": "飞书", "link": "https://www.feishu.cn"},
"电话号码": "+8613800138000",
"单向关联": ["recXXX1", "recXXX2"]
}
}
```
### 批量新增 - 请求体
```json
{
"records": [
{"fields": {"字段1": "值1"}},
{"fields": {"字段1": "值2"}}
]
}
```
### 批量删除 - 请求体
```json
{
"records": ["recXXX1", "recXXX2"]
}
```
### 删除结果结构
```json
{
"deleted": true,
"record_id": "recXXX"
}
```

View File

@@ -0,0 +1,71 @@
# Table / View / Field / App API 参考
- **DDS-Section**: A.1 概述 - 各资源方法列表 / A.10-A.28, A.37-A.40
- **DDS-Lines**: L111-L260, L1932-L7926, L12655-L13935
## Extract
### App API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 获取元数据 | `GET` | `/open-apis/bitable/v1/apps/:app_token` | `client.Bitable.V1.App.Get` |
| 更新元数据 | `PUT` | `/open-apis/bitable/v1/apps/:app_token` | `client.Bitable.V1.App.Update` |
更新元数据可用于:修改多维表格名称、**开启/关闭高级权限**。
### Table API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 列出数据表 | `GET` | `.../tables` | `client.Bitable.V1.AppTable.List` |
| 新增数据表 | `POST` | `.../tables` | `client.Bitable.V1.AppTable.Create` |
| 新增多个表 | `POST` | `.../tables/batch_create` | `client.Bitable.V1.AppTable.BatchCreate` |
| 删除数据表 | `DELETE` | `.../tables/:table_id` | `client.Bitable.V1.AppTable.Delete` |
| 删除多个表 | `POST` | `.../tables/batch_delete` | `client.Bitable.V1.AppTable.BatchDelete` |
### View API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 列出视图 | `GET` | `.../views` | `client.Bitable.V1.AppTableView.List` |
| 检索视图 | `GET` | `.../views/:view_id` | `client.Bitable.V1.AppTableView.Get` |
| 新增视图 | `POST` | `.../views` | `client.Bitable.V1.AppTableView.Create` |
| 更新视图 | `PATCH` | `.../views/:view_id` | `client.Bitable.V1.AppTableView.Patch` |
| 删除视图 | `DELETE` | `.../views/:view_id` | `client.Bitable.V1.AppTableView.Delete` |
### Field API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 列出字段 | `GET` | `.../fields` | `client.Bitable.V1.AppTableField.List` |
| 新增字段 | `POST` | `.../fields` | `client.Bitable.V1.AppTableField.Create` |
| 更新字段 | `PUT` | `.../fields/:field_id` | `client.Bitable.V1.AppTableField.Update` |
| 删除字段 | `DELETE` | `.../fields/:field_id` | `client.Bitable.V1.AppTableField.Delete` |
### Dashboard API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 列出仪表盘 | `GET` | `.../dashboards` | `client.Bitable.V1.AppDashboard.List` |
| 复制仪表盘 | `POST` | `.../dashboards/:block_id/copy` | `client.Bitable.V1.AppDashboard.Copy` |
### Form API
| 操作 | 方法 | 路径 | SDK 方法 |
|------|------|------|---------|
| 获取表单元数据 | `GET` | `.../forms/:form_id` | `client.Bitable.V1.AppTableFormField` |
| 更新表单元数据 | `PATCH` | `.../forms/:form_id` | (同上) |
| 列出表单问题 | `GET` | `.../forms/:form_id/fields` | (同上) |
| 更新表单问题 | `PATCH` | `.../forms/:form_id/fields/:field_id` | (同上) |
### 权限要求
| 操作类型 | 所需权限 |
|---------|---------|
| 读取List/Get | `查看、评论和导出多维表格` |
| 写入Create/Update/Delete | `查看、评论、编辑和管理多维表格` |
### 凭证支持
所有 Bitable API 同时支持 `tenant_access_token``user_access_token`

View File

@@ -0,0 +1,65 @@
# 多维表格字段变更事件
- **DDS-Section**: A.8 多维表格字段变更
- **DDS-Lines**: L1595-L1810
## Extract
### 事件概述
| 属性 | 值 |
|------|------|
| 事件类型 | `drive.file.bitable_field_changed_v1` |
| 支持的应用类型 | 自建应用、商店应用 |
| 权限要求 | 查看、评论、编辑和管理多维表格 **或** 查看、评论、编辑和管理云空间中所有文件 |
| 推送方式 | Webhook |
| 字段权限要求 | 获取用户 user ID仅自建应用 |
### 事件体核心字段
| 名称 | 类型 | 说明 |
|------|------|------|
| `file_type` | string | 文档类型,固定 `"bitable"` |
| `file_token` | string | 多维表格 token即 app_token |
| `table_id` | string | 数据表 ID |
| `operator_id` | user_id | 操作人(含 union_id, user_id, open_id |
| `action_list` | array | 字段变更操作列表 |
| `revision` | int | 数据表版本号 |
| `update_time` | int | 变更时间(时间戳) |
| `subscriber_id_list` | array | 订阅用户列表 |
### action_list 中每个操作的结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `action` | string | 操作类型(如 field_added, field_edited, field_deleted |
| `field_id` | string | 字段 ID |
| `before_value` | object | 操作前的字段定义 |
| `after_value` | object | 操作后的字段定义 |
### before_value / after_value 字段定义结构
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 字段 ID |
| `name` | string | 字段名字 |
| `type` | int | 字段类型 |
| `description` | string | 字段描述 |
| `property` | object | 字段属性(含 formatter, date_formatter, auto_fill, multiple, table_id, options 等) |
### property 中嵌套结构
**数字/公式字段**`formatter` (string)
**日期/创建时间/更新时间字段**`date_formatter` (string), `auto_fill` (boolean)
**人员/关联字段**`multiple` (boolean), `table_id` (string), `table_name` (string)
**双向关联**`back_field_name`, `back_field_id`
**自动编号**`auto_serial.type`, `auto_serial.options[]`
**单选/多选**`options[].name`, `options[].id`, `options[].color`
**公式**`formula_expression`
**地理位置**`input_type`
### 使用场景
- 监控字段结构变化,自动更新本地 Schema 映射
- 检测字段被删除/重命名,发送报警通知
- 审计字段配置变更历史

Some files were not shown because too many files have changed in this diff Show More