@amaster.ai/pi-lark 0.1.8 → 0.1.9

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.
Files changed (116) hide show
  1. package/package.json +2 -2
  2. package/skills/lark-apps/SKILL.md +2 -0
  3. package/skills/lark-apps/references/lark-apps-db.md +130 -2
  4. package/skills/lark-apps/references/lark-apps-user-id-convert.md +63 -0
  5. package/skills/lark-base/SKILL.md +155 -167
  6. package/skills/lark-base/references/{lark-base-role-guide.md → lark-base-advanced-permission-and-role.md} +5 -5
  7. package/skills/lark-base/references/lark-base-app-block-data-config.md +122 -0
  8. package/skills/lark-base/references/lark-base-app.md +225 -0
  9. package/skills/lark-base/references/lark-base-cell-value.md +26 -19
  10. package/skills/lark-base/references/{dashboard-block-data-config.md → lark-base-dashboard-block-config.md} +37 -5
  11. package/skills/lark-base/references/lark-base-dashboard-block-get-data.md +1 -1
  12. package/skills/lark-base/references/lark-base-dashboard.md +9 -9
  13. package/skills/lark-base/references/lark-base-data-analysis-pandas.md +93 -0
  14. package/skills/lark-base/references/lark-base-data-analysis-python-stdlib.md +120 -0
  15. package/skills/lark-base/references/lark-base-data-query.md +8 -11
  16. package/skills/lark-base/references/lark-base-field-create.md +7 -50
  17. package/skills/lark-base/references/{formula-field-guide.md → lark-base-field-formula.md} +1 -1
  18. package/skills/lark-base/references/{lookup-field-guide.md → lark-base-field-lookup.md} +1 -1
  19. package/skills/lark-base/references/{lark-base-field-json.md → lark-base-field-schema.md} +15 -100
  20. package/skills/lark-base/references/lark-base-field-update.md +13 -51
  21. package/skills/lark-base/references/lark-base-filter-condition.md +19 -31
  22. package/skills/lark-base/references/lark-base-record-batch-create.md +5 -1
  23. package/skills/lark-base/references/lark-base-record-batch-update.md +5 -2
  24. package/skills/lark-base/references/lark-base-record-query-and-analysis-cloud-sop.md +145 -0
  25. package/skills/lark-base/references/lark-base-record-query-and-analysis-sop.md +233 -0
  26. package/skills/lark-base/references/{role-config.md → lark-base-role-config.md} +2 -2
  27. package/skills/lark-base/references/lark-base-view-set-filter.md +1 -1
  28. package/skills/lark-base/references/lark-base-workflow-schema.md +2 -2
  29. package/skills/lark-base/references/{lark-base-workflow-guide.md → lark-base-workflow.md} +1 -1
  30. package/skills/lark-calendar/SKILL.md +2 -0
  31. package/skills/lark-calendar/references/lark-calendar-create.md +4 -3
  32. package/skills/lark-doc/SKILL.md +3 -3
  33. package/skills/lark-doc/references/lark-doc-fetch.md +8 -3
  34. package/skills/lark-doc/references/lark-doc-update.md +12 -8
  35. package/skills/lark-drive/SKILL.md +5 -3
  36. package/skills/lark-drive/references/lark-drive-download.md +27 -1
  37. package/skills/lark-drive/references/lark-drive-export.md +1 -0
  38. package/skills/lark-drive/references/lark-drive-member-remove.md +59 -0
  39. package/skills/lark-drive/references/lark-drive-preview.md +21 -2
  40. package/skills/lark-drive/references/lark-drive-push.md +5 -1
  41. package/skills/lark-drive/references/lark-drive-search.md +2 -0
  42. package/skills/lark-im/SKILL.md +6 -1
  43. package/skills/lark-minutes/SKILL.md +11 -5
  44. package/skills/lark-minutes/references/lark-minutes-apply-permission.md +95 -0
  45. package/skills/lark-minutes/references/lark-minutes-detail.md +7 -6
  46. package/skills/lark-minutes/references/lark-minutes-download.md +4 -2
  47. package/skills/lark-note/SKILL.md +13 -9
  48. package/skills/lark-note/references/lark-note-detail.md +5 -2
  49. package/skills/lark-note/references/lark-note-transcript.md +2 -0
  50. package/skills/lark-shared/SKILL.md +36 -0
  51. package/skills/lark-slides/SKILL.md +54 -54
  52. package/skills/lark-slides/references/cli/lark-slides-add-slide.md +92 -0
  53. package/skills/lark-slides/references/cli/lark-slides-create.md +176 -0
  54. package/skills/lark-slides/references/cli/lark-slides-delete-slide.md +65 -0
  55. package/skills/lark-slides/references/cli/lark-slides-history.md +132 -0
  56. package/skills/lark-slides/references/cli/lark-slides-media-upload.md +103 -0
  57. package/skills/lark-slides/references/cli/lark-slides-replace-slide.md +259 -0
  58. package/skills/lark-slides/references/cli/lark-slides-screenshot.md +115 -0
  59. package/skills/lark-slides/references/{lark-slides-update-slide.md → cli/lark-slides-update-slide.md} +21 -4
  60. package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-get.md +110 -0
  61. package/skills/lark-slides/references/cli/lark-slides-xml-presentation-slide-replace.md +188 -0
  62. package/skills/lark-slides/references/cli/lark-slides-xml-presentations-get.md +157 -0
  63. package/skills/lark-slides/references/iconpark-index.json +5 -41901
  64. package/skills/lark-slides/references/iconpark.md +3 -44
  65. package/skills/lark-slides/references/lark-slides-add-slide.md +3 -90
  66. package/skills/lark-slides/references/lark-slides-create.md +3 -174
  67. package/skills/lark-slides/references/lark-slides-delete-slide.md +3 -63
  68. package/skills/lark-slides/references/lark-slides-edit-workflows.md +3 -141
  69. package/skills/lark-slides/references/lark-slides-history.md +3 -130
  70. package/skills/lark-slides/references/lark-slides-media-upload.md +3 -102
  71. package/skills/lark-slides/references/lark-slides-pptx-template-workflows.md +3 -83
  72. package/skills/lark-slides/references/lark-slides-replace-slide.md +3 -256
  73. package/skills/lark-slides/references/lark-slides-screenshot.md +3 -113
  74. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-get.md +3 -108
  75. package/skills/lark-slides/references/lark-slides-xml-presentation-slide-replace.md +3 -186
  76. package/skills/lark-slides/references/lark-slides-xml-presentations-get.md +3 -155
  77. package/skills/lark-slides/references/planning-layer.md +1 -1
  78. package/skills/lark-slides/references/slides_chart_demo.xml +5 -1415
  79. package/skills/lark-slides/references/slides_xml_schema_definition.xml +3 -3512
  80. package/skills/lark-slides/references/troubleshooting.md +3 -60
  81. package/skills/lark-slides/references/validation-checklist.md +3 -154
  82. package/skills/lark-slides/references/workflow/error-handling.md +62 -0
  83. package/skills/lark-slides/references/workflow/slides-editing.md +143 -0
  84. package/skills/lark-slides/references/workflow/template-editing.md +85 -0
  85. package/skills/lark-slides/references/workflow/validation-xml.md +156 -0
  86. package/skills/lark-slides/references/xml/iconpark-index.json +37458 -0
  87. package/skills/lark-slides/references/xml/iconpark.md +46 -0
  88. package/skills/lark-slides/references/xml/slides_chart_demo.xml +1415 -0
  89. package/skills/lark-slides/references/xml/slides_xml_schema_definition.xml +3514 -0
  90. package/skills/lark-slides/references/xml/xml-schema-quick-ref.md +497 -0
  91. package/skills/lark-slides/references/xml-schema-quick-ref.md +3 -495
  92. package/skills/lark-slides/scripts/iconpark_tool.py +1 -1
  93. package/skills/lark-slides/scripts/xml_lint.py +2989 -0
  94. package/skills/lark-slides/scripts/xml_lint_test.py +4720 -0
  95. package/skills/lark-slides/scripts/xml_text_overlap_lint.py +3 -2975
  96. package/skills/lark-slides/scripts/xml_text_overlap_lint_test.py +5 -4712
  97. package/skills/lark-task/SKILL.md +12 -0
  98. package/skills/lark-task/references/lark-task-create.md +3 -1
  99. package/skills/lark-vc/SKILL.md +15 -5
  100. package/skills/lark-vc/references/lark-vc-detail.md +11 -6
  101. package/skills/{lark-vc-agent/references/lark-vc-agent-meeting-events.md → lark-vc/references/lark-vc-meeting-events.md} +121 -20
  102. package/skills/{lark-vc-agent/references/lark-vc-agent-meeting-list-active.md → lark-vc/references/lark-vc-meeting-list-active.md} +2 -2
  103. package/skills/{lark-vc-agent/references/lark-vc-agent-meeting-message-send.md → lark-vc/references/lark-vc-meeting-message-send.md} +3 -3
  104. package/skills/lark-vc/references/lark-vc-recording.md +8 -6
  105. package/skills/lark-vc/references/vc-domain-boundaries.md +8 -1
  106. package/skills/lark-vc-agent/SKILL.md +24 -9
  107. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-join.md +2 -2
  108. package/skills/lark-vc-agent/references/lark-vc-agent-meeting-leave.md +2 -2
  109. package/skills/lark-wiki/SKILL.md +3 -1
  110. package/skills/lark-wiki/references/lark-wiki-node-copy.md +5 -19
  111. package/skills/lark-wiki/references/lark-wiki-node-create.md +19 -2
  112. package/skills/lark-wiki/references/lark-wiki-node-get.md +15 -0
  113. package/skills/lark-wiki/references/lark-wiki-node-list.md +1 -1
  114. package/skills/lark-base/references/lark-base-data-analysis-sop.md +0 -210
  115. package/skills/lark-base/references/lark-base-data-query-guide.md +0 -69
  116. package/skills/lark-base/references/lark-base-record-upsert.md +0 -63
@@ -0,0 +1,225 @@
1
+ # BaseApp(应用模式)操作指引
2
+
3
+ > 先读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md)。接口和组件字段以 CLI 当前版本的 API 元数据、[组件配置 reference](lark-base-app-block-data-config.md) 和服务端校验结果为准;不要从组件名称推断额外约束。
4
+
5
+ ## 不支持能力:先判断并停止
6
+
7
+ ### 复制 BaseApp
8
+
9
+ 本期没有 BaseApp 复制命令。用户要复制或克隆既有 BaseApp 时,直接说明当前 CLI 无法完成并停止;不要继续探索浏览器、OpenAPI 或创建类命令等替代通道,也不要发起任何写请求。
10
+
11
+ - `+base-copy` 只支持 Base,不支持 BaseApp;不得向它传入 `app_token`,也不得把复制出的 Base 描述为应用副本。
12
+ - `+app-create` 只创建全新空 BaseApp,不复制既有页面和组件。
13
+ - 不要使用 Drive copy 或其他 Base shortcut 拼装、模拟或冒充 BaseApp 复制。
14
+
15
+ ### 创建或归属 PageGroup
16
+
17
+ 当前第一阶段的页面层级能力只支持顶级 Page 节点。PageGroup 的创建、归属设置,以及把现有 Page 移入页面组均不支持。
18
+
19
+ 最终答复必须同时说明上述正向支持范围和负向限制,不能只说 PageGroup 不支持。用户命中这些诉求时,直接说明当前 CLI 无法完成并停止;不要继续探索浏览器、OpenAPI 或普通 Page 命令等替代通道,也不要读取页面后声称能完成分组或发起任何写请求。
20
+
21
+ ### 从 Workspace 移出或移除资源
22
+
23
+ 当前 CLI 只支持用 `+workspace-move-in` 把 Base 或 BaseApp 移入 Workspace,不支持从 Workspace 移出或移除资源,也没有 `workspace move-out` / `workspace remove` 命令。这类请求必须先完成只读定位,再说明限制并停止,顺序不可调换:
24
+
25
+ 1. Workspace URL 含 `/base/workspace/<workspace_token>` 时,提取其中的真实 `workspace_token`,不要把完整 URL 当作命令参数。
26
+ 2. 在同一轮立即执行 `lark-cli base +workspace-entity-list --workspace-token <workspace_token> --page-size 100 --as user`;若 `has_more=true`,继续分页直到完整。该查询是必要的只读定位步骤,不要把它留成等待用户再次选择的可选项,也不要用 `--help` 代替真实查询。
27
+ 3. 用服务端返回的 `entities[].name`、`entity_type`、`token` 和 `url` 忠实判断目标。名称完全匹配时报告真实对象;没有完全匹配时明确说明不存在精确同名实体,并原样列出可能相关的候选。不得自动去掉或补齐前后缀,也不得仅凭名称相似就声称已经定位目标。用户直接给出 token 时仍要忠实报告该 token 对应的实际名称。
28
+ 4. 定位结果报告完后,明确说明当前 CLI 无法执行 Workspace 移出/移除,并停止,不要发起任何写请求。用户在任一步骤中取消时立即停止,取消后不再调用工具。
29
+
30
+ `lark-cli drive +move` 只改变 Base 或 BaseApp 在云盘中的目录位置,不改变其 Workspace 归属,不能作为移出 Workspace 的替代方案。不要继续探索 Drive move/delete、另一个 Workspace 的 `+workspace-move-in`、浏览器、OpenAPI 或源码来拼装或冒充该操作;只有用户后续明确提出另一项受支持的操作时,才执行新的写入。
31
+
32
+ ## Token 与命令
33
+
34
+ | 对象 | 标识 | 命令 |
35
+ |---|---|---|
36
+ | Workspace | `workspace_token` | `+workspace-create` / `+workspace-entity-list` / `+workspace-move-in` |
37
+ | BaseApp | `app_token` | `+app-create/get`;重命名和删除见下方 |
38
+ | Base | `base_token` | `+base-create` 返回;表、字段、记录命令使用它 |
39
+ | Page | `page_id` | `+app-page-list/get/create/update/delete` |
40
+ | Block | `block_id` | `+app-block-list/get/create/update` |
41
+
42
+ 页面和组件命令使用 `app_token`;Base 数据命令使用 `base_token`。`+app-block-get-data` 使用 `app_token + base_token + chart_token`:CLI 参数名仍为 `--block-id`,但必须传组件返回的 `chart_token`,不能传普通 `block_id`。请求路径与仪表盘图表数据接口相同。
43
+
44
+ BaseApp / AppMode 是 Base 域能力。用户提供 `/app/` 链接时,先用 `+url-resolve`;它会返回 `app_token`,并忠实提取链接实际携带的 `workspace_token` 与 `page_id`。直接使用本指引和 `lark-cli base +...`,不要先尝试 `lark-cli apps`。
45
+
46
+ ## 查询应用
47
+
48
+ ```bash
49
+ lark-cli base +app-get --app-token <app_token>
50
+ ```
51
+
52
+ - 没有 `lark-cli base +app-list`。需要列出某个 Workspace 内的 BaseApp 时,唯一列表入口是:
53
+
54
+ ```bash
55
+ lark-cli base +workspace-entity-list \
56
+ --workspace-token <workspace_token> \
57
+ --type baseapp \
58
+ --page-size 100
59
+ ```
60
+
61
+ - 响应中的 `pages` 是页面摘要。
62
+ - `ref` 的结构是 `Base token -> 当前组件引用的 Table 名称数组`。需要操作被引用 Base 时,使用 `ref` 的 key 作为 `base_token`。
63
+ - `ref` 只描述当前组件已经引用的数据源;没有被组件引用的 Base 不会出现在其中。
64
+
65
+ ## 查询页面与组件
66
+
67
+ ```bash
68
+ lark-cli base +app-page-list --app-token <app_token> --page-size 100
69
+ lark-cli base +app-block-list \
70
+ --app-token <app_token> \
71
+ --page-id <page_id> \
72
+ --page-size 100
73
+ ```
74
+
75
+ - `+app-get` 已返回足够的页面摘要时,可直接取得目标 `page_id`;需要完整页面目录或分页确认时再用 `+app-page-list`。
76
+ - `+app-page-list` 返回的某个 Page 若 `name` 为空字符串,表示当前用户对该 Page 无权限,不表示 Page 没有标题。报告该权限状态,不要将其 `page_id` 用于后续页面或组件读写。
77
+ - 只需列表摘要时不要逐个调用 `+app-block-get` 复核;仅在用户需要单个组件详情时使用 get。
78
+ - `+app-block-list` 返回 `type=unsupported` 的组件时,只能通过列表摘要识别它的存在。当前 CLI 不支持读取详情、读取计算数据或修改此类组件;不要调用 `+app-block-get`、`+app-block-get-data` 或 `+app-block-update`,这些请求会报错。
79
+
80
+ ## 创建 Workspace
81
+
82
+ ```bash
83
+ lark-cli base +workspace-create \
84
+ --name "AppMode-空白评测空间" \
85
+ --as user
86
+ ```
87
+
88
+ ## 创建应用
89
+
90
+ ```bash
91
+ lark-cli base +app-create \
92
+ --name "销售应用" \
93
+ --workspace-token <workspace_token> \
94
+ --as user
95
+ ```
96
+
97
+ - `+app-create` 没有 `--base-token`。
98
+ - `--workspace-token` 必填;`+app-create` 只调用 App 创建接口,不创建 Workspace、Base,也不移动资源。
99
+ - `--theme-style` 可选,支持 `default|cloudBlue|fresh|softLight|future|technology`。
100
+ - 记录输出中的 `app_token` 和 `workspace_token`。
101
+
102
+ ### 创建应用的自然语言编排
103
+
104
+ 先根据用户是否指定 Workspace 和现有 Base 选择流程,再调用原子 shortcut:
105
+
106
+ | 用户提供的信息 | 执行流程 |
107
+ |---|---|
108
+ | Workspace + 现有 Base | 确认 Base 位于该 Workspace → `+app-create`;不创建备用 Base |
109
+ | Workspace,未指定 Base | `+app-create` → `+base-create` 创建空 Base → `+workspace-move-in` |
110
+ | 未指定 Workspace,指定现有 Base | 先确认该 Base 所属 Workspace;能确定时在该 Workspace 执行 `+app-create`,不能确定时请用户提供 Workspace;不创建备用 Base |
111
+ | Workspace 和 Base 都未指定 | `+workspace-create` → `+app-create` → `+base-create` 创建空 Base → `+workspace-move-in` |
112
+
113
+ 应用模式的列表组件只能引用同一 Workspace 内的一个 Base。用户指定现有 Base 时,不要因为 `+app-create` 没有接收 `base_token` 就额外创建 Base;后续在组件 `data_config.base_token` 中引用该 Base。
114
+
115
+ 多步编排中,每个成功的 shortcut 都会立即产生资源且不自动回滚。后续步骤失败时,明确报告已经成功创建的 Workspace、App 或 Base 及其 token;用户要求继续时,只重试失败步骤,不要重复创建已经成功的资源。
116
+
117
+ ## 读取图表计算结果
118
+
119
+ ```bash
120
+ lark-cli base +app-block-get-data \
121
+ --app-token <app_token> \
122
+ --base-token <base_token> \
123
+ --block-id <chart_token>
124
+ ```
125
+
126
+ - `--block-id` 的值必须取图表组件摘要中的 `chart_token`,不能使用组件的普通 `block_id`。
127
+ - `base_token` 使用当前图表组件 `data_config.base_token`;一个 App 引用多个 Base 时,不要从 `+app-get ref` 中任意选择一个 key。
128
+ - `page_id` 不参与请求。
129
+ - 返回协议与 `+dashboard-block-get-data` 完全一致。
130
+
131
+ ## 重命名应用
132
+
133
+ ```bash
134
+ lark-cli drive files patch \
135
+ --file-token <app_token> \
136
+ --type bitable \
137
+ --data '{"new_title":"新名称"}'
138
+ ```
139
+
140
+ BaseApp 与 Base 在 Drive 文件接口中都使用 `type=bitable`。`new_title` 只更新应用标题,不会重命名它引用的 Base,也不会修改 Page 或 Block。
141
+
142
+ ## 删除应用
143
+
144
+ ```bash
145
+ lark-cli drive +delete --file-token <app_token> --type bitable --yes
146
+ ```
147
+
148
+ - 删除 BaseApp 应用本体需要切到 `lark-drive`。
149
+ - BaseApp 与 Base 在 Drive 删除接口中都使用 `--type bitable`;删除 BaseApp 时 `--file-token` 传 `app_token`。
150
+ - 这是高风险写操作;执行前先确认 `app_token` 来自 `+app-get` 或 `+workspace-entity-list`。
151
+
152
+ ## Page
153
+
154
+ ### 本期不支持的 Page 能力
155
+
156
+ Page 复制和页面图标均不在本期范围。用户提出复制 Page、复制页面、克隆页面、沿用页面图标、设置或修改页面图标等需求时:
157
+
158
+ 1. 明确说明当前 CLI 不支持该能力,并确认本次没有执行任何写入。
159
+ 2. 不得调用 `+app-page-create` 冒充完整复制;空 Page 不包含原 Page 的内容、组件或图标。
160
+ 3. 不得尝试使用其他 shortcut 拼装、模拟或声称完成 Page 复制或图标设置。
161
+ 4. 在最终答复中将以下替代能力单独成段说明,但不要自动执行:
162
+
163
+ > 可用替代能力(本次未执行):当前 CLI 可以新建一个空 Page,但不会复制原 Page 的内容、组件或图标。如需新建空 Page,请明确告诉我。
164
+
165
+ 只有用户后续明确要求新建空 Page,才可以调用 `+app-page-create`。
166
+
167
+ ```bash
168
+ lark-cli base +app-page-list --app-token <app_token>
169
+ lark-cli base +app-page-create --app-token <app_token> --name "总览"
170
+ lark-cli base +app-page-update --app-token <app_token> --page-id <page_id> --name "经营总览"
171
+ lark-cli base +app-page-delete --app-token <app_token> --page-id <page_id> --yes
172
+ ```
173
+
174
+ - 同一 App 内 Page 名称必须唯一。创建或更新名称前,CLI 会读取页面列表;更新时排除当前 Page。
175
+ - 同一 Page 内组件名称必须唯一。`+app-block-create` 会分页读取该 Page 的全部组件并在创建前检查重名。
176
+ - 本期没有 Page arrange,也没有 Block delete;Block 的 `type/sub_type` 创建后不可修改。详见[本期不支持的能力](#本期不支持的能力)。
177
+
178
+ ## 本期不支持的能力
179
+
180
+ 下列能力本期不存在。用户提出时,直接说明不支持并给出可选的替代方向,不要用 Dashboard 或其他域的同名能力顶替。
181
+
182
+ | 用户诉求 | 本期状态 | 正确动作 |
183
+ |---|---|---|
184
+ | 自动排版 / 重新布局 / 美化页面组件 | 没有 App page arrange | 直接告知不支持;不要调用 `+dashboard-arrange` |
185
+ | 删除页面组件 | 没有 App block delete | 直接告知不支持,只能在 UI 处理;不要调用 `+dashboard-block-delete` |
186
+ | 修改组件位置 / 大小 / 置顶 | 布局、位置、尺寸不属于公开 Create/Update 协议 | 直接告知不支持;不要用 `+app-block-update` 做空更新伪装成移动 |
187
+ | 修改已有组件的 `type/sub_type` | `type/sub_type` 创建后不可修改 | 先读取当前 Block;无论是否已为目标类型,最终答复都要说明此约束。已匹配时说明无需写入;不匹配时说明只能在 UI 处理;不得调用或承诺用 `+app-block-update` 修改类型 |
188
+ | 修改已存在 App 的主题 | `--theme-style` 只在 `+app-create` 时生效 | 直接告知不支持;如确有必要,说明只能新建 App 时指定主题 |
189
+ | 读取或修改 `type=unsupported` 的组件 | 列表仅用于识别该组件存在,详情读取、计算数据读取和修改均不支持 | 直接告知不支持;不要调用 `+app-block-get`、`+app-block-get-data` 或 `+app-block-update`,这些请求会报错 |
190
+
191
+ `+dashboard-*` 命令只作用于 Base 内的仪表盘,`dashboard_id` 是 `blk` 开头、组件 ID 是 `cht` 开头;AppMode 的 `pge` 页面和 `wgt` 组件不属于它们的作用域。缺少能力时不要用这些命令试探,包括 `--help` 和 `--dry-run`:一次调用就是一次错误的能力归属判断。
192
+
193
+ ## 列表组件
194
+
195
+ 创建列表时使用 `--type list` 与 `--sub-type standard|grouped|collapsible|card|detail`。省略 `--sub-type` 时默认 `standard`。
196
+
197
+ ```bash
198
+ lark-cli base +app-block-create \
199
+ --app-token <app_token> \
200
+ --page-id <page_id> \
201
+ --name "待处理订单" \
202
+ --type list \
203
+ --sub-type standard \
204
+ --data-config '{"base_token":"<base_token>","table_name":"订单"}'
205
+ ```
206
+
207
+ - `data_config.base_token` 是单值:每个列表最多选择一个 Base。
208
+ - Base 必须在当前 App 的同一个 Workspace;CLI 写入前校验。
209
+ - 完整字段协议读 [lark-base-app-block-data-config.md](lark-base-app-block-data-config.md)。
210
+
211
+ ## 更新组件
212
+
213
+ `+app-block-update` 只发送显式传入的 `data_config` 字段。未传字段保持不变;数组或对象字段是否整体替换,以[组件配置 reference](lark-base-app-block-data-config.md)和服务端校验结果为准。不要为了“补全”先读取并提交全量配置。
214
+
215
+ ## 常见恢复
216
+
217
+ | 现象 | 动作 |
218
+ |---|---|
219
+ | `status=partial` | 告知已完成/失败步骤;用户要求继续时执行 `retry.command` |
220
+ | Page 重名 | 先 `+app-page-list`,选择唯一名称后重试 |
221
+ | 组件重名 | 先 `+app-block-list`,为该 Page 内的新组件选择唯一名称后重试 |
222
+ | 列表 Base 不在同一 Workspace | 用 `+workspace-entity-list` 核对;选择同 Workspace Base |
223
+ | 列表协议校验失败 | 读取组件协议文档;不要推断 title、group_by 数量或 field role |
224
+ | Block 类型选错 | 本期无法删除且类型不可改,只能在 UI 处理后重新创建 |
225
+ | 用户要 arrange / 删组件 / 调位置 / 改主题 | 按[本期不支持的能力](#本期不支持的能力)直接告知不支持;不要改用 `+dashboard-*` 命令 |
@@ -1,15 +1,14 @@
1
1
  # base CellValue 规范(lark-base-cell-value)
2
2
 
3
- > 适用命令:`lark-cli base +record-upsert`、`lark-cli base +record-batch-create`、`lark-cli base +record-batch-update`
3
+ > 适用命令:`lark-cli base +record-batch-create`、`lark-cli base +record-batch-update`
4
4
 
5
5
  本文件定义 **shortcut 写记录** 时 `CellValue` 的推荐格式,目标是让 AI 一次写对。不同命令的外层 JSON 形状不同,但每个 cell 都以本文为 source of truth。
6
6
 
7
7
  ## 1. 顶层规则(必须遵守)
8
8
 
9
9
  - `--json` 必须是 JSON 对象。
10
- - `+record-upsert`:顶层直接传字段映射:`{"字段名或字段ID": CellValue}`。
11
- - `+record-batch-create`:使用 `create_records`,其每个元素都是 `Map<FieldNameOrID, CellValue>`。
12
- - `+record-batch-update`:使用 `update_records`,其每个 value 都是 `Map<FieldNameOrID, CellValue>`。
10
+ - `+record-batch-create --json` 使用 `{"create_records":[{"字段名或字段ID": CellValue}, ...]}`,数组中的每个对象代表一条新 Record。
11
+ - `+record-batch-update --json` 使用 `{"update_records":{"rec_xxx":{"字段名或字段ID": CellValue}, ...}}`,以 `record_id` 定位每条待更新 Record。
13
12
  - 一次 payload 里同一字段只用一种 key(字段名或字段 ID),不要重复。
14
13
  - 写入前先 `+field-list` 获取字段 `type/style/multiple`,再构造值。
15
14
  - 需要清空字段时优先传 `null`(字段允许清空时)。
@@ -48,25 +47,29 @@ text 字段的 `style.type` 影响单元格检查逻辑:
48
47
 
49
48
  ### 2.3 select(单选/多选)
50
49
 
51
- `select` 字段用 `multiple` 区分单选和多选:`multiple=false` 时传选项名字符串,`multiple=true` 时传选项名数组。只支持写入字段中已有的选项;构造 CellValue 前先用 `+field-list` 或 `+field-search-options` 确认目标选项存在。
50
+ `select` 字段统一传选项名称数组。`multiple=false` 时数组只能包含一个元素,`multiple=true` 时可以包含多个元素。只支持写入字段中已有的选项;构造 CellValue 前先用 `+field-list` 或 `+field-search-options` 确认目标选项存在。
52
51
 
53
52
  ```json
54
53
  {
55
- "单选": "Todo",
54
+ "单选": ["Todo"],
56
55
  "多选": ["后端", "高优"]
57
56
  }
58
57
  ```
59
58
 
59
+ 读取单元格时与写入的数据结构一致。
60
+
60
61
  ### 2.4 datetime
61
62
 
62
- 优先用 `YYYY-MM-DD HH:mm:ss` 字符串,这是最稳妥的写法,也和常见 API 输出更容易对齐。不要写相对时间(如“明天上午”)。
63
+ 写入可省略时区偏移量,系统会按 Base 时区解析输入字符串;优先使用 `YYYY-MM-DD HH:mm`。Base 默认按分钟展示,但底层以毫秒级精度存储时间
63
64
 
64
65
  ```json
65
66
  {
66
- "截止时间": "2026-03-24 10:00:00"
67
+ "截止时间": "2026-03-24 10:00"
67
68
  }
68
69
  ```
69
70
 
71
+ 读取单元格时,日期时间输出为标准 RFC3339 字符串并固定保留三位毫秒,例如 `"2026-03-24T10:00:00.000+08:00"`。
72
+
70
73
  ### 2.5 checkbox
71
74
 
72
75
  用 JSON boolean:`true` 或 `false`,不要用 `"true"`、`"是"`、`1`。
@@ -79,7 +82,7 @@ text 字段的 `style.type` 影响单元格检查逻辑:
79
82
 
80
83
  ### 2.6 user / group_chat
81
84
 
82
- 用对象数组,元素至少包含 `id`。人员字段传用户 ID(如 `ou_xxx`),群字段传群 ID(如 `oc_xxx`);单值/多值都统一使用数组。
85
+ `user` 和 `group_chat` 字段统一传对象数组。`multiple=false` 时数组只能包含一个元素,`multiple=true` 时可以包含多个元素。每个元素至少包含 `id`;人员字段传用户 ID(如 `ou_xxx`),群字段传群 ID(如 `oc_xxx`)。
83
86
 
84
87
  > **人员字段:不要猜 ID。** 不知道 `open_id` 时,先用 `lark-contact` 查 id:`lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user`。
85
88
 
@@ -97,6 +100,8 @@ text 字段的 `style.type` 影响单元格检查逻辑:
97
100
  }
98
101
  ```
99
102
 
103
+ 读取单元格时仍为对象数组,每个元素为 `{id, name}`,例如 `[{"id":"ou_xxx","name":"张三"}]`。
104
+
100
105
  ### 2.7 link
101
106
 
102
107
  用对象数组,元素包含 `id`,值为目标记录的 `record_id`。不要传记录标题;先用 `+record-list` / `+record-search` 找到目标记录 ID。
@@ -109,9 +114,13 @@ text 字段的 `style.type` 影响单元格检查逻辑:
109
114
  }
110
115
  ```
111
116
 
117
+ 读取单元格时与写入的数据结构一致。
118
+
112
119
  ### 2.8 location
113
120
 
114
- 写入对象必须使用 `{lng, lat}`,两者都是数字;`lng` 是经度,`lat` 是纬度。不需要手动传 `full_address`,平台会根据坐标解析地址。
121
+ - 读取:`{lng, lat, full_address}`,三个成员均非空。
122
+ - 写入:`{lng, lat}`,经纬度均为数字;`full_address` 由平台根据坐标解析,不允许手动指定。
123
+ - 筛选行为:按照 `full_address` 做字符串筛选,将 Location 当作文本列使用文本 operator。
115
124
 
116
125
  ```json
117
126
  {
@@ -122,34 +131,32 @@ text 字段的 `style.type` 影响单元格检查逻辑:
122
131
  }
123
132
  ```
124
133
 
125
- 读取、筛选、转文本等场景使用 `full_address` 字符串;只有公式能访问坐标。如果用户只给地址文本,先获取或确认坐标后再写入;不要把仅有地址文本直接当作 location CellValue。
126
134
 
127
135
  ### 2.9 attachment(不作为普通 CellValue 写入)
128
136
 
137
+ 读取单元格时,附件为数组,每个元素为 `{file_token, size, name}`,例如 `[{"file_token":"box_xxx","size":1024,"name":"report.pdf"}]`。
138
+
129
139
  - 追加附件:使用 `lark-cli base +record-upload-attachment --record-id <record_id> --field-id <field_id> --file <path>`;可重复 `--file` 一次追加多个附件,不能用普通记录操作接口写附件值。
130
140
  - 删除附件:使用 `lark-cli base +record-remove-attachment --record-id <record_id> --field-id <field_id> --file-token <file_token> --yes`;可重复 `--file-token` 一次删除同一单元格里的多个附件。
131
141
  - 下载附件:使用 `lark-cli base +record-download-attachment --record-id <record_id> --file-token <file_token> --output <dir>`;不传 `--file-token` 时下载整行所有附件,也可重复 `--file-token` 只下载指定附件。Base 附件必须用这个命令下载,用其他下载入口可能失败。
132
142
 
133
143
  ## 3. 只读字段(不要写)
134
144
 
135
- 以下字段在写记录时应视为只读:
136
- - `auto_number`
137
- - `lookup`
138
- - `formula`
139
- - `created_at` / `updated_at`
140
- - `created_by` / `updated_by`
145
+ 写记录时,`auto_number`、`lookup`、`formula`、`created_at/updated_at`、`created_by/updated_by` 均为只读字段。
141
146
 
142
147
  写入只读字段通常不会更新数据;返回里可能出现 `ignored_fields`,reason 会说明 `READONLY`。看到这种返回时,不要重试同一 payload,应移除只读字段,只写存储字段。
143
148
 
149
+ 读取单元格时,`auto_number`、`formula`、`lookup` 为 `string | null`;`created_at`、`updated_at` 为 RFC3339 字符串或 `null`;`created_by`、`updated_by` 为 `array<{id, name}>`。
150
+
144
151
  ## 4. 完整示例
145
152
 
146
153
  ```json
147
154
  {
148
155
  "标题": "Created from shortcut",
149
- "状态": "Todo",
156
+ "状态": ["Todo"],
150
157
  "标签": ["高优", "外部依赖"],
151
158
  "工时": 8,
152
- "截止时间": "2026-03-24 10:00:00",
159
+ "截止时间": "2026-03-24 10:00",
153
160
  "已完成": false,
154
161
  "负责人": [{ "id": "ou_123" }],
155
162
  "关联任务": [{ "id": "rec_456" }],
@@ -1,6 +1,6 @@
1
- # dashboard block data_config SSOT
1
+ # Base Dashboard Block 配置
2
2
 
3
- Block 的 `data_config` 字段因 `type` 不同而变化。本文档是 dashboard block `data_config` 的单一事实来源(SSOT),包含组件类型、字段结构、筛选格式、约束和可复制模板。
3
+ Block 的 `data_config` 字段因 `type` 不同而变化。本文档是 Dashboard block 扁平单数据源 `data_config` 的单一事实来源(SSOT),包含组件类型、字段结构、筛选格式、约束和可复制模板。BaseApp 图表的外层结构不同,但每个 `data_sources[]` 元素复用本文的字段取值、筛选、分组、排序及规范化规则;创建或更新 App 组件时,还必须读取 [BaseApp Block data_config](lark-base-app-block-data-config.md) 了解共享 `base_token`、多数据源封装,以及 App 独有的列表组件协议。
4
4
 
5
5
  ## 支持的组件类型(`type` 枚举)
6
6
 
@@ -29,11 +29,13 @@ text: is, isNot, contains, doesNotContain, isEmpty, isNotEmpty
29
29
  number: is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty
30
30
  select(multiple=false): is, isNot, isEmpty, isNotEmpty
31
31
  select(multiple=true): is, isNot, contains, doesNotContain, isEmpty, isNotEmpty
32
- datetime: is, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty
32
+ datetime: is, isGreater, isLess, isEmpty, isNotEmpty
33
33
  checkbox: is (value: true/false)
34
34
  user / created_by / updated_by: is, isNot, isEmpty, isNotEmpty
35
35
  ```
36
36
 
37
+ `isGreaterEqual` / `isLessEqual` 不是全局不支持:它们可用于 `number`,但不能用于 `datetime` / `created_at` / `updated_at`。日期范围必须用 `isGreater` / `isLess` 配合 `ExactDate`;不要把数字字段的操作符集合套到日期字段上。
38
+
37
39
  ## data_config 通用结构
38
40
 
39
41
  | 字段 | 类型 | 说明 |
@@ -156,12 +158,42 @@ user / created_by / updated_by: is, isNot, isEmpty, isNotEmpty
156
158
  | `number` | number | is, isNot, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty | `{"field_name":"金额","operator":"isGreater","value":0}` |
157
159
  | `select` (`multiple=false`) | string(选项名) | is, isNot, isEmpty, isNotEmpty | `{"field_name":"状态","operator":"is","value":"已完成"}` |
158
160
  | `select` (`multiple=true`) | string[](选多个)/ string(选单个) | is, isNot, contains, doesNotContain, isEmpty, isNotEmpty | 多选传数组如 `["标签1","标签2"]`;单选传单个字符串 |
159
- | `datetime` / `created_at` / `updated_at` | number(Unix 毫秒时间戳,13位) | is, isGreater, isGreaterEqual, isLess, isLessEqual, isEmpty, isNotEmpty | `{"field_name":"创建日期","operator":"isGreater","value":1704038400000}` |
161
+ | `datetime` / `created_at` / `updated_at` | `["ExactDate", Unix 毫秒时间戳]` | is, isGreater, isLess, isEmpty, isNotEmpty | `{"field_name":"创建日期","operator":"isGreater","value":["ExactDate",1704038400000]}` |
160
162
  | `checkbox` | boolean | is | `{"field_name":"已审核","operator":"is","value":true}` |
161
163
  | `user` / `created_by` / `updated_by` | string 或 string[](用户 ID,格式 `ou_xxx`)。不知道 `open_id` 时先用 `lark-cli contact +search-user --query "<姓名/邮箱/手机号>" --as user` 查 id。 | is, isNot, isEmpty, isNotEmpty | `{"field_name":"负责人","operator":"is","value":"ou_xxxxxxxxxxxxxxxx"}` |
162
164
  | 所有类型(为空/不为空) | 不需要 value | isEmpty, isNotEmpty | `{"field_name":"备注","operator":"isEmpty"}` |
163
165
 
164
- > `value` 类型为 `string | number | boolean | string[]`,需根据字段类型匹配正确格式
166
+ > `value` 类型因字段而异,可为 `string | number | boolean | string[] | ["ExactDate", number]`,需按上表构造。
167
+
168
+ ### 日期筛选
169
+
170
+ 图表 `data_config.filter` 筛选 `datetime` / `created_at` / `updated_at` 字段时:
171
+
172
+ - 有值条件只能使用 `is`、`isGreater` 或 `isLess`,不得使用 `isGreaterEqual` 或 `isLessEqual`。
173
+ - `value` 必须写成 `["ExactDate", <Unix 毫秒时间戳>]`,不得直接传裸时间戳。
174
+ - `isEmpty` / `isNotEmpty` 不传 `value`。
175
+
176
+ 日期区间示例:
177
+
178
+ ```json
179
+ {
180
+ "filter": {
181
+ "conjunction": "and",
182
+ "conditions": [
183
+ {
184
+ "field_name": "派单日期",
185
+ "operator": "isGreater",
186
+ "value": ["ExactDate", 1785686400000]
187
+ },
188
+ {
189
+ "field_name": "派单日期",
190
+ "operator": "isLess",
191
+ "value": ["ExactDate", 1786032000000]
192
+ }
193
+ ]
194
+ }
195
+ }
196
+ ```
165
197
 
166
198
  ## 约束与本地校验
167
199
 
@@ -730,4 +730,4 @@ GET /open-apis/base/v3/bases/bascn_example_token/dashboards/blocks/chtxxxxxxxx/d
730
730
 
731
731
  - [lark-base-dashboard.md](lark-base-dashboard.md) — dashboard 模块总指引
732
732
  - `+dashboard-block-get` — 获取 block 元数据
733
- - [dashboard-block-data-config.md](dashboard-block-data-config.md) — data_config 结构和组件类型说明
733
+ - [Dashboard Block 配置](lark-base-dashboard-block-config.md) — data_config 结构和组件类型说明
@@ -15,8 +15,8 @@ Dashboard 是 Base 中的数据可视化看板,可以把表格数据变成**
15
15
  | 你想做什么 | 用这些命令 | 关键文档 |
16
16
  |------|-----------|---------|
17
17
  | 创建/删除/改名称 | `+dashboard-create/delete/update` | 本页下方「仪表盘管理」 |
18
- | 在仪表盘里添加组件 | `+dashboard-block-create` | 先定位 dashboard、表和字段,再读 [dashboard-block-data-config.md](dashboard-block-data-config.md) 构造 `data_config` |
19
- | 修改组件 | `+dashboard-block-update` | 先读 block 现状,再读 [dashboard-block-data-config.md](dashboard-block-data-config.md) 决定替换哪些顶层 key |
18
+ | 在仪表盘里添加组件 | `+dashboard-block-create` | 先定位 dashboard、表和字段,再读 [Dashboard Block 配置](lark-base-dashboard-block-config.md) 构造 `data_config` |
19
+ | 修改组件 | `+dashboard-block-update` | 先读 block 现状,再读 [Dashboard Block 配置](lark-base-dashboard-block-config.md) 决定替换哪些顶层 key |
20
20
  | 查看仪表盘有哪些组件 | `+dashboard-get` 或 `+dashboard-block-list` | 本页下方「查看仪表盘」 |
21
21
  | 读取图表计算结果 | `+dashboard-block-get-data` | 返回图表最终数据协议;需要 block 元数据先用 `+dashboard-block-get` |
22
22
  | 智能重排组件布局 | `+dashboard-arrange` | 用户明确要求重排,或本次会话新建仪表盘的收尾整理;无法指定 `x/y/w/h`、精确位置或尺寸 |
@@ -48,7 +48,7 @@ lark-cli base +field-list --base-token xxx --table-id <table_id>
48
48
 
49
49
  # 第 4 步:顺序创建每个组件(必须串行执行,不能并发)
50
50
  # 重要:创建组件前,先确定 dashboard_id、组件 name/type 和真实表字段
51
- # 再阅读 dashboard-block-data-config.md 了解 data_config 结构、组件类型和 filter 规则
51
+ # 再阅读 lark-base-dashboard-block-config.md 了解 data_config 结构、组件类型和 filter 规则
52
52
 
53
53
  # 第 1 个组件
54
54
  lark-cli base +dashboard-block-create \
@@ -93,7 +93,7 @@ lark-cli base +field-list --base-token xxx --table-id <table_id>
93
93
 
94
94
  # 第 4 步:顺序创建每个新组件(必须串行执行,不能并发)
95
95
  # 重要:先确定 dashboard_id、组件 name/type 和真实表字段
96
- # 再阅读 dashboard-block-data-config.md 了解 data_config 结构
96
+ # 再阅读 lark-base-dashboard-block-config.md 了解 data_config 结构
97
97
  lark-cli base +dashboard-block-create \
98
98
  --base-token xxx \
99
99
  --dashboard-id blk_xxx \
@@ -127,7 +127,7 @@ lark-cli base +field-list --base-token xxx --table-id <table_id>
127
127
 
128
128
  # 第 5 步:执行更新
129
129
  # 重要:先读取当前 block 的 name/type/data_config
130
- # 再阅读 dashboard-block-data-config.md 了解 data_config 更新规则
130
+ # 再阅读 lark-base-dashboard-block-config.md 了解 data_config 更新规则
131
131
  lark-cli base +dashboard-block-update \
132
132
  --base-token xxx \
133
133
  --dashboard-id blk_xxx \
@@ -169,7 +169,7 @@ lark-cli base +dashboard-arrange \
169
169
 
170
170
  1. 图表或指标卡:使用方式 D 读取计算结果。
171
171
  2. `text`:使用方式 C,正文位于 `data_config.text`;text 没有计算结果,但属于完整仪表盘内容。
172
- 3. get-data 返回不支持的图表类型:先用方式 C 读取真实 `data_config`,确认 `table_name`、维度、指标、聚合与筛选,再按 [数据分析 SOP](lark-base-data-analysis-sop.md) 使用 `+data-query` 重建同口径结果。字段必须来自真实配置和表结构,不得猜测;无法等价重建时明确报告限制,不能静默省略该 block。
172
+ 3. get-data 返回不支持的图表类型:先用方式 C 读取真实 `data_config`,确认 `table_name`、维度、指标、聚合与筛选,再按 [Record 查询与分析 SOP](lark-base-record-query-and-analysis-sop.md) 使用 `+data-query` 重建同口径结果。字段必须来自真实配置和表结构,不得猜测;无法等价重建时明确报告限制,不能静默省略该 block。
173
173
 
174
174
  ```bash
175
175
  # 第 1 步:列出仪表盘,定位到当前仪表盘
@@ -209,14 +209,14 @@ lark-cli base +dashboard-block-get-data --base-token xxx --block-id chtxxxxxxxx
209
209
  | 单个关键指标 | statistics | 指标卡组件 |
210
210
  | 富文本说明/标题/注释 | text | 文本组件(支持 Markdown) |
211
211
 
212
- 详细组件类型和 data_config 完整规则:[dashboard-block-data-config.md](dashboard-block-data-config.md)
212
+ 详细组件类型和 data_config 完整规则:[Dashboard Block 配置](lark-base-dashboard-block-config.md)
213
213
 
214
214
  ## 常见问题
215
215
 
216
216
  **Q: 创建组件的命令和 data_config 怎么写?**
217
217
  A:
218
218
  1. 先确定 `dashboard_id`、组件 `name`、组件 `type` 和真实表字段
219
- 2. 再读 [dashboard-block-data-config.md](dashboard-block-data-config.md) 了解:
219
+ 2. 再读 [Dashboard Block 配置](lark-base-dashboard-block-config.md) 了解:
220
220
  - 全部组件类型的可复制模板
221
221
  - filter 筛选条件格式
222
222
  - 字段类型与操作符对应表
@@ -237,7 +237,7 @@ A: 不能。`+dashboard-block-update` 只能修改 `name` 和 `data_config`,
237
237
  **Q: 更新组件的命令和 data_config 怎么写?**
238
238
  A:
239
239
  1. 先读取当前 block,确认 `block_id`、当前 `type` 和已有 `data_config`
240
- 2. 再读 [dashboard-block-data-config.md](dashboard-block-data-config.md) 了解 data_config 结构
240
+ 2. 再读 [Dashboard Block 配置](lark-base-dashboard-block-config.md) 了解 data_config 结构
241
241
 
242
242
  **data_config 更新策略(顶层 key merge)**:
243
243
  - 只传入需要修改的顶层字段(如 `series`、`filter`)
@@ -0,0 +1,93 @@
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
+ ```