@amaster.ai/pi-lark 0.1.2-beta.61 → 0.1.2-beta.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/lark-approval/SKILL.md +2 -2
- package/skills/lark-approval/references/lark-approval-instances-initiated.md +5 -0
- package/skills/lark-approval/references/lark-approval-tasks-add-sign.md +68 -20
- package/skills/lark-approval/references/lark-approval-tasks-query.md +5 -0
- package/skills/lark-base/SKILL.md +110 -7
- package/skills/lark-base/references/lark-base-data-query.md +2 -6
- package/skills/lark-base/references/lark-base-field-extension.md +170 -0
- package/skills/lark-base/references/lark-base-field-lookup.md +1 -1
- package/skills/lark-base/references/lark-base-filter-condition.md +32 -5
- package/skills/lark-base/references/lark-base-form-detail.md +1 -1
- package/skills/lark-base/references/lark-base-form-submit.md +2 -2
- package/skills/lark-base/references/lark-base-record-history-list.md +1 -1
- package/skills/lark-base/references/lark-base-record-query-and-analysis-sop.md +95 -205
- package/skills/lark-base/references/lark-base-template-center.md +5 -1
- package/skills/lark-calendar/SKILL.md +6 -0
- package/skills/lark-calendar/references/lark-calendar-join-event.md +43 -0
- package/skills/lark-drive/references/lark-drive-member-remove.md +2 -1
- package/skills/lark-im/SKILL.md +14 -1
- package/skills/lark-markdown/SKILL.md +1 -1
- package/skills/lark-meeting/SKILL.md +6 -2
- package/skills/lark-meeting/references/lark-minutes-summary.md +1 -0
- package/skills/lark-meeting/references/lark-minutes-todo.md +39 -1
- package/skills/lark-meeting/references/lark-minutes-upload.md +6 -0
- package/skills/lark-meeting/references/lark-vc-agent-meeting-end.md +26 -0
- package/skills/lark-meeting/references/lark-vc-agent-meeting-invite.md +32 -0
- package/skills/lark-meeting/references/lark-vc-agent-meeting-join.md +8 -2
- package/skills/lark-meeting/references/lark-vc-meeting-countdown.md +103 -0
- package/skills/lark-meeting/references/lark-vc-meeting-events.md +1 -0
- package/skills/lark-meeting/references/lark-vc-meeting-screenshot.md +34 -0
- package/skills/lark-meeting/scenes/create-and-edit-minutes.md +25 -3
- package/skills/lark-meeting/scenes/live-meeting-attend.md +63 -6
- package/skills/lark-meeting/scenes/live-meeting-interact.md +32 -3
- package/skills/lark-sheets/SKILL.md +76 -60
- package/skills/lark-sheets/references/lark-sheets-batch-update.md +83 -14
- package/skills/lark-sheets/references/lark-sheets-chart.md +296 -159
- package/skills/lark-sheets/references/lark-sheets-conditional-format.md +5 -3
- package/skills/lark-sheets/references/lark-sheets-filter.md +1 -1
- package/skills/lark-sheets/references/lark-sheets-formula-translation.md +78 -65
- package/skills/lark-sheets/references/lark-sheets-formula-verify.md +21 -17
- package/skills/lark-sheets/references/lark-sheets-pivot-table.md +2 -1
- package/skills/lark-sheets/references/lark-sheets-range-operations.md +1 -1
- package/skills/lark-sheets/references/lark-sheets-read-data.md +7 -4
- package/skills/lark-sheets/references/lark-sheets-search-replace.md +4 -4
- package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +2 -2
- package/skills/lark-sheets/references/lark-sheets-sparkline.md +1 -0
- package/skills/lark-sheets/references/lark-sheets-styles-put.md +3 -3
- package/skills/lark-sheets/references/lark-sheets-visual-standards.md +6 -4
- package/skills/lark-sheets/references/lark-sheets-workbook.md +3 -1
- package/skills/lark-sheets/references/lark-sheets-write-cells.md +50 -48
- package/skills/lark-sheets/scripts/lark_chart_layout_check.py +472 -0
- package/skills/lark-slides/SKILL.md +2 -0
- package/skills/lark-slides/references/cli/lark-slides-add-slide.md +6 -6
- package/skills/lark-slides/references/cli/lark-slides-delete-slide.md +3 -3
- package/skills/lark-slides/references/cli/lark-slides-replace-slide.md +11 -11
- package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-get.md +1 -1
- package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-replace.md +2 -2
- package/skills/lark-slides/references/workflow/slides-editing.md +11 -11
- package/skills/lark-slides/references/xml/slides_xml_schema_definition.xml +2 -0
- package/skills/lark-base/references/lark-base-cell-value.md +0 -165
- package/skills/lark-base/references/lark-base-data-analysis-pandas.md +0 -93
- package/skills/lark-base/references/lark-base-data-analysis-python-stdlib.md +0 -120
- package/skills/lark-base/references/lark-base-record-batch-create.md +0 -63
- package/skills/lark-base/references/lark-base-record-batch-update.md +0 -57
- package/skills/lark-base/references/lark-base-record-query-and-analysis-cloud-sop.md +0 -145
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
## 最小读-改-写闭环
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
21
|
+
PRES_ID="xml_presentation_id_here"
|
|
22
22
|
SID="slide_id_here"
|
|
23
23
|
|
|
24
24
|
# 1. 读原页,从 XML 里挑出要改的块的 3 位 short id(如 bUn / bab)
|
|
25
25
|
lark-cli slides xml_presentation.slide get --as user \
|
|
26
|
-
--params "{\"xml_presentation_id\":\"$
|
|
26
|
+
--params "{\"xml_presentation_id\":\"$PRES_ID\",\"slide_id\":\"$SID\"}"
|
|
27
27
|
|
|
28
28
|
# 2. 用 +replace-slide 直接改那个块(不需要搬原 XML)
|
|
29
29
|
lark-cli slides +replace-slide --as user \
|
|
30
|
-
--presentation "$
|
|
30
|
+
--presentation "$PRES_ID" --slide-id "$SID" \
|
|
31
31
|
--parts '[{"action":"block_replace","block_id":"bUn","replacement":"<shape type=\"text\" topLeftX=\"80\" topLeftY=\"80\" width=\"800\" height=\"120\"><content textType=\"title\"><p>新标题</p></content></shape>"}]'
|
|
32
32
|
```
|
|
33
33
|
|
|
@@ -42,12 +42,12 @@ lark-cli slides +replace-slide --as user \
|
|
|
42
42
|
```bash
|
|
43
43
|
# 读时拿当前 revision_id
|
|
44
44
|
REV=$(lark-cli slides xml_presentation.slide get --as user \
|
|
45
|
-
--params "{\"xml_presentation_id\":\"$
|
|
45
|
+
--params "{\"xml_presentation_id\":\"$PRES_ID\",\"slide_id\":\"$SID\"}" \
|
|
46
46
|
--jq '.data.revision_id')
|
|
47
47
|
|
|
48
48
|
# 写时传该版本号,服务端以此为 base
|
|
49
49
|
lark-cli slides +replace-slide --as user \
|
|
50
|
-
--presentation "$
|
|
50
|
+
--presentation "$PRES_ID" --slide-id "$SID" --revision-id "$REV" \
|
|
51
51
|
--parts '[{"action":"block_replace","block_id":"bUn","replacement":"<shape type=\"rect\" topLeftX=\"100\" topLeftY=\"100\" width=\"200\" height=\"100\"/>"}]'
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -65,7 +65,7 @@ lark-cli slides +replace-slide --as user \
|
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
lark-cli slides +replace-slide --as user \
|
|
68
|
-
--presentation "$
|
|
68
|
+
--presentation "$PRES_ID" --slide-id "$SID" \
|
|
69
69
|
--parts '[{"action":"block_replace","block_id":"bab","replacement":"<shape type=\"text\" topLeftX=\"80\" topLeftY=\"80\" width=\"800\" height=\"120\"><content textType=\"title\"><p>新标题</p></content></shape>"}]'
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -83,7 +83,7 @@ lark-cli slides +replace-slide --as user \
|
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
85
|
lark-cli slides +replace-slide --as user \
|
|
86
|
-
--presentation "$
|
|
86
|
+
--presentation "$PRES_ID" --slide-id "$SID" \
|
|
87
87
|
--parts "$(jq -n --arg token "$FILE_TOKEN" \
|
|
88
88
|
'[{action:"block_insert",insertion:("<img src=\""+$token+"\" topLeftX=\"500\" topLeftY=\"100\" width=\"200\" height=\"150\"/>"),insert_before_block_id:"baa"}]')"
|
|
89
89
|
```
|
|
@@ -96,7 +96,7 @@ lark-cli slides +replace-slide --as user \
|
|
|
96
96
|
| `insertion` | 是 | 要插入的完整 XML 片段 |
|
|
97
97
|
| `insert_before_block_id` | 否 | 插到这个块之前;省略(不提供此字段)则追加到页面末尾 |
|
|
98
98
|
|
|
99
|
-
> **`<img>` 必须用 `file_token`**,不能用外链 URL——先 `slides +media-upload --file ./pic.png --presentation $
|
|
99
|
+
> **`<img>` 必须用 `file_token`**,不能用外链 URL——先 `slides +media-upload --file ./pic.png --presentation $PRES_ID` 拿 token。
|
|
100
100
|
|
|
101
101
|
### 批量 parts
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ lark-cli slides +replace-slide --as user \
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
lark-cli slides +replace-slide --as user \
|
|
107
|
-
--presentation "$
|
|
107
|
+
--presentation "$PRES_ID" --slide-id "$SID" \
|
|
108
108
|
--parts '[{"action":"block_replace","block_id":"bab","replacement":"<shape type=\"text\" topLeftX=\"80\" topLeftY=\"80\" width=\"800\" height=\"120\"><content textType=\"title\"><p>新标题</p></content></shape>"},{"action":"block_insert","insertion":"<img src=\"<file_token>\" topLeftX=\"700\" topLeftY=\"400\" width=\"180\" height=\"100\"/>"}]'
|
|
109
109
|
```
|
|
110
110
|
|
|
@@ -116,11 +116,11 @@ lark-cli slides +replace-slide --as user \
|
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
118
|
# 从文件读
|
|
119
|
-
lark-cli slides +replace-slide --as user --presentation "$
|
|
119
|
+
lark-cli slides +replace-slide --as user --presentation "$PRES_ID" --slide-id "$SID" \
|
|
120
120
|
--parts @parts.json
|
|
121
121
|
|
|
122
122
|
# 从 stdin 读
|
|
123
|
-
cat parts.json | lark-cli slides +replace-slide --as user --presentation "$
|
|
123
|
+
cat parts.json | lark-cli slides +replace-slide --as user --presentation "$PRES_ID" --slide-id "$SID" \
|
|
124
124
|
--parts -
|
|
125
125
|
```
|
|
126
126
|
|
|
@@ -1297,6 +1297,7 @@
|
|
|
1297
1297
|
- autoStartAt: 有序列表起始编号, 可选, 取值范围 [1, 32767]; 显式指定时从当前段落起重置计数器, 未指定时沿用同一 content 内的前序计数器
|
|
1298
1298
|
- bulletChar: 自定义列表符号字符, 可选
|
|
1299
1299
|
- marginLeft: 段落左侧缩进宽度
|
|
1300
|
+
- marginRight: 段落右侧缩进宽度
|
|
1300
1301
|
- indent: 首行缩进宽度
|
|
1301
1302
|
- tabStopPos/defaultTabSize: 段落级 Tab 配置, 覆盖 content 同名配置
|
|
1302
1303
|
</xs:documentation>
|
|
@@ -1329,6 +1330,7 @@
|
|
|
1329
1330
|
<xs:attribute name="autoStartAt" type="sml:AutoStartAtType" use="optional"/>
|
|
1330
1331
|
<xs:attribute name="bulletChar" type="sml:BulletCharType" use="optional"/>
|
|
1331
1332
|
<xs:attribute name="marginLeft" type="xs:double" use="optional" />
|
|
1333
|
+
<xs:attribute name="marginRight" type="xs:double" use="optional" />
|
|
1332
1334
|
<xs:attribute name="indent" type="sml:NonNegativeDouble" use="optional"/>
|
|
1333
1335
|
<xs:attribute name="tabStopPos" type="sml:TabStopPosType" use="optional"/>
|
|
1334
1336
|
<xs:attribute name="defaultTabSize" type="sml:TabSizeType" use="optional"/>
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
# base CellValue 规范(lark-base-cell-value)
|
|
2
|
-
|
|
3
|
-
> 适用命令:`lark-cli base +record-batch-create`、`lark-cli base +record-batch-update`
|
|
4
|
-
|
|
5
|
-
本文件定义 **shortcut 写记录** 时 `CellValue` 的推荐格式,目标是让 AI 一次写对。不同命令的外层 JSON 形状不同,但每个 cell 都以本文为 source of truth。
|
|
6
|
-
|
|
7
|
-
## 1. 顶层规则(必须遵守)
|
|
8
|
-
|
|
9
|
-
- `--json` 必须是 JSON 对象。
|
|
10
|
-
- `+record-batch-create --json` 使用 `{"create_records":[{"字段名或字段ID": CellValue}, ...]}`,数组中的每个对象代表一条新 Record。
|
|
11
|
-
- `+record-batch-update --json` 使用 `{"update_records":{"rec_xxx":{"字段名或字段ID": CellValue}, ...}}`,以 `record_id` 定位每条待更新 Record。
|
|
12
|
-
- 一次 payload 里同一字段只用一种 key(字段名或字段 ID),不要重复。
|
|
13
|
-
- 写入前先 `+field-list` 获取字段 `type/style/multiple`,再构造值。
|
|
14
|
-
- 需要清空字段时优先传 `null`(字段允许清空时)。
|
|
15
|
-
|
|
16
|
-
## 2. 各类型 CellValue
|
|
17
|
-
|
|
18
|
-
### 2.1 text
|
|
19
|
-
|
|
20
|
-
text 字段的 `style.type` 影响单元格检查逻辑:
|
|
21
|
-
`type=plain` 传 Markdown 格式的字符串。
|
|
22
|
-
`type=url` 传一个带 title 的 Markdown 格式链接,或单独传一个链接。
|
|
23
|
-
`type=phone` 传合法电话号码。
|
|
24
|
-
`type=email` 传合法邮箱字符串。
|
|
25
|
-
|
|
26
|
-
```json
|
|
27
|
-
{
|
|
28
|
-
"标题": "Hello, [lark-cli](https://github.com/larksuite/cli)",
|
|
29
|
-
"官网": "[官网](https://example.com)",
|
|
30
|
-
"联系电话": "1380000000000",
|
|
31
|
-
"邮箱": "owner@example.com"
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### 2.2 number
|
|
36
|
-
|
|
37
|
-
用 JSON number,不要用带单位或千分位的字符串。货币、百分比、进度、评分等数字类字段也按数字写入,展示格式由字段配置决定。
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{
|
|
41
|
-
"工时": 12.5,
|
|
42
|
-
"预算": 3000,
|
|
43
|
-
"完成度": 0.65,
|
|
44
|
-
"评分": 4
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### 2.3 select(单选/多选)
|
|
49
|
-
|
|
50
|
-
`select` 字段统一传选项名称数组。`multiple=false` 时数组只能包含一个元素,`multiple=true` 时可以包含多个元素。只支持写入字段中已有的选项;构造 CellValue 前先用 `+field-list` 或 `+field-search-options` 确认目标选项存在。
|
|
51
|
-
|
|
52
|
-
```json
|
|
53
|
-
{
|
|
54
|
-
"单选": ["Todo"],
|
|
55
|
-
"多选": ["后端", "高优"]
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
读取单元格时与写入的数据结构一致。
|
|
60
|
-
|
|
61
|
-
### 2.4 datetime
|
|
62
|
-
|
|
63
|
-
写入可省略时区偏移量,系统会按 Base 时区解析输入字符串;优先使用 `YYYY-MM-DD HH:mm`。Base 默认按分钟展示,但底层以毫秒级精度存储时间
|
|
64
|
-
|
|
65
|
-
```json
|
|
66
|
-
{
|
|
67
|
-
"截止时间": "2026-03-24 10:00"
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
读取单元格时,日期时间输出为标准 RFC3339 字符串并固定保留三位毫秒,例如 `"2026-03-24T10:00:00.000+08:00"`。
|
|
72
|
-
|
|
73
|
-
### 2.5 checkbox
|
|
74
|
-
|
|
75
|
-
用 JSON boolean:`true` 或 `false`,不要用 `"true"`、`"是"`、`1`。
|
|
76
|
-
|
|
77
|
-
```json
|
|
78
|
-
{
|
|
79
|
-
"已完成": true
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### 2.6 user / group_chat
|
|
84
|
-
|
|
85
|
-
`user` 和 `group_chat` 字段统一传对象数组。`multiple=false` 时数组只能包含一个元素,`multiple=true` 时可以包含多个元素。每个元素至少包含 `id`;人员字段传用户 ID(如 `ou_xxx`),群字段传群 ID(如 `oc_xxx`)。
|
|
86
|
-
|
|
87
|
-
> **人员字段:不要猜 ID。** 不知道 `open_id` 时,先用 `lark-contact` 查 id:`lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user`。
|
|
88
|
-
|
|
89
|
-
> **群组字段:不要猜 ID。** 不知道 `chat_id` 时,先用 `lark-im` 搜群:`lark-cli im +chat-search --query "<群名关键词>" --as user`;取结果里的 `oc_xxx`。
|
|
90
|
-
|
|
91
|
-
```json
|
|
92
|
-
{
|
|
93
|
-
"负责人": [
|
|
94
|
-
{ "id": "ou_xxx" },
|
|
95
|
-
{ "id": "ou_xxx2" }
|
|
96
|
-
],
|
|
97
|
-
"协作群": [
|
|
98
|
-
{ "id": "oc_xxx" }
|
|
99
|
-
]
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
读取单元格时仍为对象数组,每个元素为 `{id, name}`,例如 `[{"id":"ou_xxx","name":"张三"}]`。
|
|
104
|
-
|
|
105
|
-
### 2.7 link
|
|
106
|
-
|
|
107
|
-
用对象数组,元素包含 `id`,值为目标记录的 `record_id`。不要传记录标题;先用 `+record-list` / `+record-search` 找到目标记录 ID。
|
|
108
|
-
|
|
109
|
-
```json
|
|
110
|
-
{
|
|
111
|
-
"关联任务": [
|
|
112
|
-
{ "id": "<record_id>" }
|
|
113
|
-
]
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
读取单元格时与写入的数据结构一致。
|
|
118
|
-
|
|
119
|
-
### 2.8 location
|
|
120
|
-
|
|
121
|
-
- 读取:`{lng, lat, full_address}`,三个成员均非空。
|
|
122
|
-
- 写入:`{lng, lat}`,经纬度均为数字;`full_address` 由平台根据坐标解析,不允许手动指定。
|
|
123
|
-
- 筛选行为:按照 `full_address` 做字符串筛选,将 Location 当作文本列使用文本 operator。
|
|
124
|
-
|
|
125
|
-
```json
|
|
126
|
-
{
|
|
127
|
-
"坐标": {
|
|
128
|
-
"lng": 116.397428,
|
|
129
|
-
"lat": 39.90923
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
### 2.9 attachment(不作为普通 CellValue 写入)
|
|
136
|
-
|
|
137
|
-
读取单元格时,附件为数组,每个元素为 `{file_token, size, name}`,例如 `[{"file_token":"box_xxx","size":1024,"name":"report.pdf"}]`。
|
|
138
|
-
|
|
139
|
-
- 追加附件:使用 `lark-cli base +record-upload-attachment --record-id <record_id> --field-id <field_id> --file <path>`;可重复 `--file` 一次追加多个附件,不能用普通记录操作接口写附件值。
|
|
140
|
-
- 删除附件:使用 `lark-cli base +record-remove-attachment --record-id <record_id> --field-id <field_id> --file-token <file_token> --yes`;可重复 `--file-token` 一次删除同一单元格里的多个附件。
|
|
141
|
-
- 下载附件:使用 `lark-cli base +record-download-attachment --record-id <record_id> --file-token <file_token> --output <dir>`;不传 `--file-token` 时下载整行所有附件,也可重复 `--file-token` 只下载指定附件。Base 附件必须用这个命令下载,用其他下载入口可能失败。
|
|
142
|
-
|
|
143
|
-
## 3. 只读字段(不要写)
|
|
144
|
-
|
|
145
|
-
写记录时,`auto_number`、`lookup`、`formula`、`created_at/updated_at`、`created_by/updated_by` 均为只读字段。
|
|
146
|
-
|
|
147
|
-
写入只读字段通常不会更新数据;返回里可能出现 `ignored_fields`,reason 会说明 `READONLY`。看到这种返回时,不要重试同一 payload,应移除只读字段,只写存储字段。
|
|
148
|
-
|
|
149
|
-
读取单元格时,`auto_number`、`formula`、`lookup` 为 `string | null`;`created_at`、`updated_at` 为 RFC3339 字符串或 `null`;`created_by`、`updated_by` 为 `array<{id, name}>`。
|
|
150
|
-
|
|
151
|
-
## 4. 完整示例
|
|
152
|
-
|
|
153
|
-
```json
|
|
154
|
-
{
|
|
155
|
-
"标题": "Created from shortcut",
|
|
156
|
-
"状态": ["Todo"],
|
|
157
|
-
"标签": ["高优", "外部依赖"],
|
|
158
|
-
"工时": 8,
|
|
159
|
-
"截止时间": "2026-03-24 10:00",
|
|
160
|
-
"已完成": false,
|
|
161
|
-
"负责人": [{ "id": "ou_123" }],
|
|
162
|
-
"关联任务": [{ "id": "rec_456" }],
|
|
163
|
-
"坐标": { "lng": 116.397428, "lat": 39.90923 }
|
|
164
|
-
}
|
|
165
|
-
```
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Base NDJSON:pandas 示例
|
|
2
|
-
|
|
3
|
-
仅在统一数据分析 SOP 已选择 pandas 后读取。本页不重复 Base 的粒度与关系规则,只展示对应实现。
|
|
4
|
-
|
|
5
|
-
示例假设 `records.ndjson` 包含 `record_id`、`日期`、`状态`、`金额`、`负责人`、`标签`、`关联客户`;`customers.ndjson` 包含 `record_id`、`客户名称`。多值列使用统一数据分析 SOP 定义的数组结构。
|
|
6
|
-
|
|
7
|
-
## 加载与日期解析
|
|
8
|
-
|
|
9
|
-
```python
|
|
10
|
-
import pandas as pd
|
|
11
|
-
|
|
12
|
-
records = pd.read_json("records.ndjson", lines=True)
|
|
13
|
-
raw_dates = records["日期"].astype("string")
|
|
14
|
-
records["日期_local"] = pd.to_datetime(
|
|
15
|
-
raw_dates.str.slice(0, 10), format="%Y-%m-%d", errors="coerce"
|
|
16
|
-
)
|
|
17
|
-
records["日期_instant"] = pd.to_datetime(
|
|
18
|
-
raw_dates, format="ISO8601", utc=True, errors="coerce"
|
|
19
|
-
)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
按来源 Base 的日、周、月分组使用 `日期_local`;计算真实时长、排序或跨时区比较使用 `日期_instant`。实际任务只需构造所需的一列。
|
|
23
|
-
|
|
24
|
-
## 集合谓词:保持 record 粒度
|
|
25
|
-
|
|
26
|
-
筛选“状态”包含“进行中”的记录,并在 record 粒度汇总:
|
|
27
|
-
|
|
28
|
-
```python
|
|
29
|
-
active = records[records["状态"].map(lambda values: "进行中" in values)]
|
|
30
|
-
summary = {
|
|
31
|
-
"records_count": len(active),
|
|
32
|
-
"amount_sum": active["金额"].sum(min_count=1),
|
|
33
|
-
}
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## 单数组展开:切换到人员粒度
|
|
37
|
-
|
|
38
|
-
```python
|
|
39
|
-
owners = records[["record_id", "负责人"]].explode("负责人", ignore_index=True)
|
|
40
|
-
owners = owners[owners["负责人"].notna()].assign(
|
|
41
|
-
user_id=lambda df: df["负责人"].map(lambda user: user["id"]),
|
|
42
|
-
user_name=lambda df: df["负责人"].map(lambda user: user["name"]),
|
|
43
|
-
)
|
|
44
|
-
by_owner = (
|
|
45
|
-
owners.groupby(["user_id", "user_name"], as_index=False)
|
|
46
|
-
.agg(records_count=("record_id", "nunique"))
|
|
47
|
-
.sort_values("records_count", ascending=False)
|
|
48
|
-
)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Link JOIN:先建立边表
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
edges = (
|
|
55
|
-
records[["record_id", "关联客户"]]
|
|
56
|
-
.rename(columns={"record_id": "source_record_id"})
|
|
57
|
-
.explode("关联客户", ignore_index=True)
|
|
58
|
-
)
|
|
59
|
-
edges = edges[edges["关联客户"].notna()].assign(
|
|
60
|
-
target_record_id=lambda df: df["关联客户"].map(lambda link: link["id"])
|
|
61
|
-
)[["source_record_id", "target_record_id"]]
|
|
62
|
-
|
|
63
|
-
customers = pd.read_json("customers.ndjson", lines=True).rename(
|
|
64
|
-
columns={"record_id": "target_record_id"}
|
|
65
|
-
)
|
|
66
|
-
joined = edges.merge(
|
|
67
|
-
customers[["target_record_id", "客户名称"]],
|
|
68
|
-
on="target_record_id",
|
|
69
|
-
how="left",
|
|
70
|
-
)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## 多数组共现:显式生成行内笛卡尔积
|
|
74
|
-
|
|
75
|
-
连续两次 `explode` 表示同一 source record 内的 `负责人 × 标签`:
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
pairs = (
|
|
79
|
-
records[["record_id", "负责人", "标签"]]
|
|
80
|
-
.explode("负责人", ignore_index=True)
|
|
81
|
-
.explode("标签", ignore_index=True)
|
|
82
|
-
.dropna(subset=["负责人", "标签"])
|
|
83
|
-
.assign(
|
|
84
|
-
user_id=lambda df: df["负责人"].map(lambda user: user["id"]),
|
|
85
|
-
user_name=lambda df: df["负责人"].map(lambda user: user["name"]),
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
cooccurrence = (
|
|
89
|
-
pairs.groupby(["user_id", "user_name", "标签"], as_index=False)
|
|
90
|
-
.agg(records_count=("record_id", "nunique"))
|
|
91
|
-
.sort_values("records_count", ascending=False)
|
|
92
|
-
)
|
|
93
|
-
```
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# Base NDJSON:Python 标准库示例
|
|
2
|
-
|
|
3
|
-
仅在统一数据分析 SOP 已选择 Python 标准库后读取。本页不重复 Base 的粒度与关系规则,只展示对应实现。
|
|
4
|
-
|
|
5
|
-
示例假设 `records.ndjson` 包含 `record_id`、`日期`、`状态`、`金额`、`负责人`、`标签`、`关联客户`;`customers.ndjson` 包含 `record_id`、`客户名称`。多值列使用统一数据分析 SOP 定义的数组结构。
|
|
6
|
-
|
|
7
|
-
## 加载与日期解析
|
|
8
|
-
|
|
9
|
-
NDJSON 每行是一条独立 JSON record;按行读取即可,不要先把文件整体载入字符串。
|
|
10
|
-
|
|
11
|
-
```python
|
|
12
|
-
import json
|
|
13
|
-
from datetime import date, datetime
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def read_ndjson(path):
|
|
17
|
-
with open(path, encoding="utf-8") as stream:
|
|
18
|
-
for line in stream:
|
|
19
|
-
if line.strip():
|
|
20
|
-
yield json.loads(line)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
records = list(read_ndjson("records.ndjson"))
|
|
24
|
-
for record in records:
|
|
25
|
-
raw_date = record["日期"]
|
|
26
|
-
record["日期_local"] = date.fromisoformat(raw_date[:10]) if raw_date else None
|
|
27
|
-
record["日期_instant"] = datetime.fromisoformat(raw_date) if raw_date else None
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
按来源 Base 的日、周、月分组使用 `日期_local`;计算真实时长、排序或跨时区比较使用 `日期_instant`。实际任务只需构造所需的一项。
|
|
31
|
-
|
|
32
|
-
## 集合谓词:保持 record 粒度
|
|
33
|
-
|
|
34
|
-
筛选“状态”包含“进行中”的记录,并在 record 粒度汇总:
|
|
35
|
-
|
|
36
|
-
```python
|
|
37
|
-
active = [record for record in records if "进行中" in record["状态"]]
|
|
38
|
-
amounts = [record["金额"] for record in active if record["金额"] is not None]
|
|
39
|
-
summary = {
|
|
40
|
-
"records_count": len(active),
|
|
41
|
-
"amount_sum": sum(amounts) if amounts else None,
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## 单数组展开:切换到人员粒度
|
|
46
|
-
|
|
47
|
-
用嵌套循环表达 lateral expansion;按人员 `id` 聚合,`name` 只用于展示。
|
|
48
|
-
|
|
49
|
-
```python
|
|
50
|
-
from collections import defaultdict
|
|
51
|
-
|
|
52
|
-
record_ids_by_owner = defaultdict(set)
|
|
53
|
-
owner_names = {}
|
|
54
|
-
for record in records:
|
|
55
|
-
for owner in record["负责人"]:
|
|
56
|
-
record_ids_by_owner[owner["id"]].add(record["record_id"])
|
|
57
|
-
owner_names[owner["id"]] = owner["name"]
|
|
58
|
-
|
|
59
|
-
by_owner = sorted(
|
|
60
|
-
(
|
|
61
|
-
{
|
|
62
|
-
"user_id": user_id,
|
|
63
|
-
"user_name": owner_names[user_id],
|
|
64
|
-
"records_count": len(record_ids),
|
|
65
|
-
}
|
|
66
|
-
for user_id, record_ids in record_ids_by_owner.items()
|
|
67
|
-
),
|
|
68
|
-
key=lambda row: (-row["records_count"], row["user_id"]),
|
|
69
|
-
)
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Link JOIN:先建立目标表索引
|
|
73
|
-
|
|
74
|
-
目标表的 `record_id` 是唯一主键,可直接建立哈希索引;Link 的 `id` 用于索引查找。
|
|
75
|
-
|
|
76
|
-
```python
|
|
77
|
-
customers = {
|
|
78
|
-
customer["record_id"]: customer
|
|
79
|
-
for customer in read_ndjson("customers.ndjson")
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
joined = []
|
|
83
|
-
for record in records:
|
|
84
|
-
for link in record["关联客户"]:
|
|
85
|
-
customer = customers.get(link["id"])
|
|
86
|
-
joined.append(
|
|
87
|
-
{
|
|
88
|
-
"source_record_id": record["record_id"],
|
|
89
|
-
"target_record_id": link["id"],
|
|
90
|
-
"客户名称": customer["客户名称"] if customer else None,
|
|
91
|
-
}
|
|
92
|
-
)
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## 多数组共现:显式生成行内笛卡尔积
|
|
96
|
-
|
|
97
|
-
两层嵌套循环表示同一 source record 内的 `负责人 × 标签`:
|
|
98
|
-
|
|
99
|
-
```python
|
|
100
|
-
record_ids_by_pair = defaultdict(set)
|
|
101
|
-
owner_names = {}
|
|
102
|
-
for record in records:
|
|
103
|
-
for owner in record["负责人"]:
|
|
104
|
-
owner_names[owner["id"]] = owner["name"]
|
|
105
|
-
for tag in record["标签"]:
|
|
106
|
-
record_ids_by_pair[(owner["id"], tag)].add(record["record_id"])
|
|
107
|
-
|
|
108
|
-
cooccurrence = sorted(
|
|
109
|
-
(
|
|
110
|
-
{
|
|
111
|
-
"user_id": user_id,
|
|
112
|
-
"user_name": owner_names[user_id],
|
|
113
|
-
"标签": tag,
|
|
114
|
-
"records_count": len(record_ids),
|
|
115
|
-
}
|
|
116
|
-
for (user_id, tag), record_ids in record_ids_by_pair.items()
|
|
117
|
-
),
|
|
118
|
-
key=lambda row: (-row["records_count"], row["user_id"], row["标签"]),
|
|
119
|
-
)
|
|
120
|
-
```
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# base +record-batch-create
|
|
2
|
-
|
|
3
|
-
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
|
|
4
|
-
|
|
5
|
-
批量创建记录。
|
|
6
|
-
|
|
7
|
-
## 适用场景(重点)
|
|
8
|
-
|
|
9
|
-
- 适合导入 CSV / Excel、外部系统一次性写入新数据。
|
|
10
|
-
- 先把每条输入数据映射为独立的字段对象,再组装到 `create_records`。
|
|
11
|
-
|
|
12
|
-
## 推荐命令
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
lark-cli base +record-batch-create --base-token <base_token> --table-id <table_id> \
|
|
16
|
-
--json '{"create_records":[{"标题":"任务 A","状态":"Open"},{"标题":"任务 B","状态":"Done"}]}'
|
|
17
|
-
|
|
18
|
-
lark-cli base +record-batch-create --base-token <base_token> --table-id <table_id> --json @batch-create.json
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## 参数
|
|
22
|
-
|
|
23
|
-
| 参数 | 必填 | 说明 |
|
|
24
|
-
|------|------|------|
|
|
25
|
-
| `--base-token <token>` | 是 | Base Token |
|
|
26
|
-
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
|
27
|
-
| `--json <body>` | 是 | 批量创建请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@<file_path>` 从文件读取 |
|
|
28
|
-
|
|
29
|
-
## API
|
|
30
|
-
|
|
31
|
-
`POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_create`
|
|
32
|
-
|
|
33
|
-
## `--json` 结构
|
|
34
|
-
|
|
35
|
-
本节只说明 `+record-batch-create` 的外层 JSON 形状;CellValue 统一看 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
|
36
|
-
|
|
37
|
-
对象形态:
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
{"create_records":[{"标题":"任务 A","状态":"Open"},{"标题":"任务 B","状态":"Done"}]}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
| 字段 | 类型 | 必填 | 说明 |
|
|
44
|
-
|------|------|------|------|
|
|
45
|
-
| `create_records` | `Array<Map<FieldNameOrID, CellValue>>` | 是 | 记录字段对象数组;每条记录可以提交不同字段,单次最多 200 条 |
|
|
46
|
-
|
|
47
|
-
## 返回重点
|
|
48
|
-
|
|
49
|
-
返回 `record_id_list` 和可选的 `ignored_fields`。
|
|
50
|
-
|
|
51
|
-
## 坑点
|
|
52
|
-
|
|
53
|
-
- 每个 `create_records` 元素都是独立的记录字段对象,只提交该记录需要写入的字段。
|
|
54
|
-
- 单次最多 200 条;`1254104` 表示超过单批上限,拆成多个批次。
|
|
55
|
-
- `1254045` 表示字段不存在,重新 `+field-list` 后使用真实字段名或 `field_id`。
|
|
56
|
-
- `1254015` 表示 CellValue 类型不匹配,按真实 Field schema 和 CellValue 规范修正。
|
|
57
|
-
- 返回 `ignored_fields` / `READONLY` 时,从普通 Record 写入中移除 Formula、Lookup、系统字段和自动编号等只读字段。
|
|
58
|
-
- 同一 Table 连续批量写入使用串行执行;`1254291` 表示并发写冲突,短暂等待后重试当前批次。
|
|
59
|
-
- `select` 字段只支持写入字段中已有的选项;构造 CellValue 前先用 `+field-list` 或 `+field-search-options` 确认目标选项存在。
|
|
60
|
-
|
|
61
|
-
## 参考
|
|
62
|
-
|
|
63
|
-
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# base +record-batch-update (batch update)
|
|
2
|
-
|
|
3
|
-
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
|
|
4
|
-
|
|
5
|
-
通过 `update_records` 为每条记录提交字段值。
|
|
6
|
-
|
|
7
|
-
## 推荐命令
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
lark-cli base +record-batch-update --base-token <base_token> --table-id <table_id> \
|
|
11
|
-
--json '{"update_records":{"<record_id_a>":{"状态":["完成"]},"<record_id_b>":{"分数":20}}}'
|
|
12
|
-
|
|
13
|
-
lark-cli base +record-batch-update --base-token <base_token> --table-id <table_id> --json @batch-update.json
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## 参数
|
|
17
|
-
|
|
18
|
-
| 参数 | 必填 | 说明 |
|
|
19
|
-
|------|------|------|
|
|
20
|
-
| `--base-token <token>` | 是 | Base Token |
|
|
21
|
-
| `--table-id <id_or_name>` | 是 | 表 ID 或表名 |
|
|
22
|
-
| `--json <body>` | 是 | 批量更新请求体,必须是 JSON 对象。支持直接传 JSON 字符串,或 `@<file_path>` 从文件读取 |
|
|
23
|
-
|
|
24
|
-
## API
|
|
25
|
-
|
|
26
|
-
`POST /open-apis/base/v3/bases/:base_token/tables/:table_id/records/batch_update`
|
|
27
|
-
|
|
28
|
-
## `--json` 结构
|
|
29
|
-
|
|
30
|
-
本节只说明 `+record-batch-update` 的外层 JSON 形状;CellValue 统一看 [lark-base-cell-value.md](lark-base-cell-value.md)。
|
|
31
|
-
|
|
32
|
-
对象形态:
|
|
33
|
-
|
|
34
|
-
```json
|
|
35
|
-
{"update_records":{"recA":{"状态":["完成"]},"recB":{"分数":20}}}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
| 字段 | 类型 | 必填 | 说明 |
|
|
39
|
-
|------|------|------|------|
|
|
40
|
-
| `update_records` | `Map<RecordID, Map<FieldNameOrID, CellValue>>` | 是 | record ID 到字段更新对象的映射(单次最多 200 条) |
|
|
41
|
-
|
|
42
|
-
## 返回重点
|
|
43
|
-
|
|
44
|
-
成功响应只包含可选的 `ignored_fields`;没有忽略字段时 `data` 为空对象。请求不会预先校验 record ID 是否存在,因此需要确认实际写入结果时,应再用 `+record-get` 读回目标记录。
|
|
45
|
-
|
|
46
|
-
## 坑点
|
|
47
|
-
|
|
48
|
-
- 单次最多更新 200 条记录;`1254104` 表示超过单批上限,拆成多个批次。
|
|
49
|
-
- `1254045` 表示字段不存在,重新 `+field-list` 后使用真实字段名或 `field_id`。
|
|
50
|
-
- `1254015` 表示 CellValue 类型不匹配,按真实 Field schema 和 CellValue 规范修正。
|
|
51
|
-
- 命令不会自动做字段/行映射转换,传什么就发什么。
|
|
52
|
-
- 如果字段映射包含只读字段,返回里可能出现 `ignored_fields` / `READONLY`;移除 Formula、Lookup、系统字段和自动编号等只读字段。
|
|
53
|
-
- 同一 Table 连续批量写入使用串行执行;`1254291` 表示并发写冲突,短暂等待后重试当前批次。
|
|
54
|
-
|
|
55
|
-
## 参考
|
|
56
|
-
|
|
57
|
-
- [lark-base-cell-value.md](lark-base-cell-value.md) — CellValue 格式规范
|