refactor(commands): rename status command to list and update related references
feat(feishu): update card schema to 2.0 and simplify approval card structure docs(feishu): add documentation for card json schema 2.0 changes
This commit is contained in:
parent
44bd1a4300
commit
26746335c4
@ -85,7 +85,7 @@ async def handle_command(user_id: str, text: str) -> Optional[str]:
|
|||||||
|
|
||||||
if cmd in (P+"new", P+"n"):
|
if cmd in (P+"new", P+"n"):
|
||||||
return await _cmd_new(user_id, args)
|
return await _cmd_new(user_id, args)
|
||||||
elif cmd in (P+"status", P+"list", P+"ls", P+"l"):
|
elif cmd in (P+"list", P+"ls", P+"l", P+"status"):
|
||||||
return await _cmd_status(user_id)
|
return await _cmd_status(user_id)
|
||||||
elif cmd in (P+"close", P+"c"):
|
elif cmd in (P+"close", P+"c"):
|
||||||
return await _cmd_close(user_id, args)
|
return await _cmd_close(user_id, args)
|
||||||
@ -443,7 +443,7 @@ async def _cmd_nodes(user_id: str, args: str) -> str:
|
|||||||
"""List nodes or switch active node."""
|
"""List nodes or switch active node."""
|
||||||
from config import ROUTER_MODE
|
from config import ROUTER_MODE
|
||||||
if not ROUTER_MODE:
|
if not ROUTER_MODE:
|
||||||
return "Not in router mode. Run standalone.py for multi-host support."
|
return "Not in router mode."
|
||||||
|
|
||||||
from router.nodes import get_node_registry
|
from router.nodes import get_node_registry
|
||||||
registry = get_node_registry()
|
registry = get_node_registry()
|
||||||
@ -476,29 +476,25 @@ def _cmd_help() -> str:
|
|||||||
"""Show help."""
|
"""Show help."""
|
||||||
from config import COMMAND_PREFIX as P
|
from config import COMMAND_PREFIX as P
|
||||||
return f"""**Commands:** (prefix: `{P}`)
|
return f"""**Commands:** (prefix: `{P}`)
|
||||||
{P}new <dir> [msg] [--idle N] [--perm MODE] - Create session
|
{P}new <dir> [msg] [--idle N] [--perm MODE] - Create session (alias: {P}n)
|
||||||
{P}status - Show sessions and current mode
|
{P}list - Show sessions and current mode (alias: {P}ls, {P}l, {P}status)
|
||||||
{P}close [n] - Close session (active or by number)
|
{P}close [n] - Close session (active or by number) (alias: {P}c)
|
||||||
{P}switch <n> - Switch to session by number
|
{P}switch <n> - Switch to session by number (alias: {P}s)
|
||||||
{P}perm <mode> [conv_id] - Set permission mode (default/edit/plan/bypass/auto)
|
{P}perm <mode> [conv_id] - Set permission mode (alias: {P}perm)
|
||||||
{P}stop - Interrupt the current task
|
{P}stop - Interrupt the current task (alias: {P}interrupt)
|
||||||
{P}progress - Show task progress
|
{P}progress - Show task progress (alias: {P}p)
|
||||||
{P}direct - Direct mode: messages → Claude Code (no LLM overhead)
|
{P}direct - Direct mode: messages → Claude Code
|
||||||
{P}smart - Smart mode: messages → LLM routing (default)
|
{P}smart - Smart mode: messages → LLM routing (default)
|
||||||
{P}shell <cmd> - Run shell command (bypasses LLM)
|
{P}shell <cmd> - Run shell command
|
||||||
{P}remind <time> <msg> - Set reminder (e.g. {P}remind 10m check build)
|
{P}remind <time> <msg> - Set reminder (e.g. {P}remind 10m check build)
|
||||||
{P}tasks - List background tasks
|
{P}tasks - List background tasks
|
||||||
{P}nodes - List connected host nodes
|
{P}nodes - List connected host nodes
|
||||||
{P}node <name> - Switch active node
|
{P}node <name> - Switch active node
|
||||||
{P}retry - Retry last message
|
{P}help - Show this help (alias: {P}h, {P}?)
|
||||||
{P}help - Show this help
|
|
||||||
|
|
||||||
**Permission modes** (used by {P}perm and {P}new --perm):
|
**Permission modes** (used by {P}perm and {P}new --perm):
|
||||||
default — 默认模式,遇到文件编辑操作时手动确认
|
default — 默认模式,需审批工具调用
|
||||||
edit — 自动接受文件编辑,但 shell 命令仍需手动确认
|
edit — 自动接受文件编辑,shell 命令仍需确认
|
||||||
适合:日常开发,需要对命令执行保持控制
|
|
||||||
plan — 只规划、不执行任何写操作
|
plan — 只规划、不执行任何写操作
|
||||||
适合:先预览 CC 的操作计划再决定是否执行
|
bypass — 跳过所有权限确认
|
||||||
bypass — 跳过所有权限确认,CC 自动执行一切操作
|
auto — 允许所有工具,不询问"""
|
||||||
适合:受信任的沙盒环境、自动化任务
|
|
||||||
auto — 允许所有工具,不询问(等效 bypass + dontAsk)"""
|
|
||||||
@ -149,7 +149,11 @@ def build_sessions_card(sessions: list[dict], active_conv_id: str | None, mode:
|
|||||||
|
|
||||||
|
|
||||||
def build_approval_card(conv_id: str, tool_name: str, summary: str, timeout: int = 120) -> dict:
|
def build_approval_card(conv_id: str, tool_name: str, summary: str, timeout: int = 120) -> dict:
|
||||||
"""Build an approval card for a tool call (schema 2.0, with approve/deny buttons)."""
|
"""Build an approval card for a tool call (schema 2.0, with approve/deny buttons).
|
||||||
|
|
||||||
|
Note: JSON 2.0 does NOT support "action" wrapper or "note" components.
|
||||||
|
Buttons go directly in elements; use div with small text for the note.
|
||||||
|
"""
|
||||||
return {
|
return {
|
||||||
"schema": "2.0",
|
"schema": "2.0",
|
||||||
"header": {
|
"header": {
|
||||||
@ -162,9 +166,6 @@ def build_approval_card(conv_id: str, tool_name: str, summary: str, timeout: int
|
|||||||
"tag": "markdown",
|
"tag": "markdown",
|
||||||
"content": f"**工具:** `{tool_name}`\n**参数:** {summary}",
|
"content": f"**工具:** `{tool_name}`\n**参数:** {summary}",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"tag": "action",
|
|
||||||
"actions": [
|
|
||||||
{
|
{
|
||||||
"tag": "button",
|
"tag": "button",
|
||||||
"text": {"tag": "plain_text", "content": "✅ 批准"},
|
"text": {"tag": "plain_text", "content": "✅ 批准"},
|
||||||
@ -177,13 +178,12 @@ def build_approval_card(conv_id: str, tool_name: str, summary: str, timeout: int
|
|||||||
"type": "danger",
|
"type": "danger",
|
||||||
"value": {"action": "deny", "conv_id": conv_id},
|
"value": {"action": "deny", "conv_id": conv_id},
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"tag": "note",
|
"tag": "div",
|
||||||
"elements": [
|
"text": {
|
||||||
{"tag": "plain_text", "content": f"超时 {timeout}s 自动拒绝 | 也可回复 y/n"},
|
"tag": "plain_text",
|
||||||
],
|
"content": f"超时 {timeout}s 自动拒绝 | 也可回复 y/n",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
281
docs/feishu/card_json_schema_2.md
Normal file
281
docs/feishu/card_json_schema_2.md
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
# 卡片 JSON 2.0 结构
|
||||||
|
|
||||||
|
本文档介绍卡片 JSON 2.0 的整体结构和属性说明。
|
||||||
|
|
||||||
|
## 概念说明
|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 是指在卡片 JSON 数据中,声明了 `schema` 属性为 `"2.0"` 的版本。与 1.0 版本相比,2.0 版本有较多不兼容差异和新增属性,详情参考[卡片 JSON 2.0 版本更新说明](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-breaking-changes-release-notes)。
|
||||||
|
|
||||||
|
- 在可视化搭建工具中,你可通过搭建[新版卡片](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/feishu-card-cardkit/cardkit-upgraded-version-card-release-notes),获取 2.0 版本的卡片 JSON 源代码。
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 结构支持飞书客户端 7.20 及之后版本。当使用 JSON 2.0 结构的卡片发送至低于 7.20 版本的客户端时,卡片标题可正常显示,但内容将展示兜底的升级提示文案。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 结构暂时仅支持共享卡片,不支持独享卡片配置。即 `update_multi` 参数仅支持设为 `true`。
|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 结构中,一张卡片最多支持 200 个元素(如 `tag` 为 `plain_text` 的文本元素)或组件。
|
||||||
|
|
||||||
|
## JSON 结构
|
||||||
|
|
||||||
|
以下为卡片 JSON 2.0 的整体结构。
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"schema": "2.0", // 卡片 JSON 结构的版本。默认为 1.0。要使用 JSON 2.0 结构,必须显示声明 2.0。
|
||||||
|
"config": {
|
||||||
|
"streaming_mode": true, // 卡片是否处于流式更新模式,默认值为 false。
|
||||||
|
"streaming_config": {}, // 流式更新配置。详情参考下文。
|
||||||
|
"summary": { // 卡片摘要信息。可通过该参数自定义客户端聊天栏消息预览中的展示文案。
|
||||||
|
"content": "自定义内容", // 自定义摘要信息。如果开启了流式更新模式,该参数将默认为“生成中”。
|
||||||
|
"i18n_content": { // 摘要信息的多语言配置。了解支持的所有语种。参考配置卡片多语言文档。
|
||||||
|
"zh_cn": "",
|
||||||
|
"en_us": "",
|
||||||
|
"ja_jp": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locales": [ // JSON 2.0 新增属性。用于指定生效的语言。如果配置 locales,则只有 locales 中的语言会生效。
|
||||||
|
"en_us",
|
||||||
|
"ja_jp"
|
||||||
|
],
|
||||||
|
"enable_forward": true, // 是否支持转发卡片。默认值为 true。
|
||||||
|
"update_multi": true, // 是否为共享卡片。默认值为 true,JSON 2.0 暂时仅支持设为 true,即更新卡片的内容对所有收到这张卡片的人员可见。
|
||||||
|
"width_mode": "fill", // 卡片宽度模式。支持 "compact"(紧凑宽度 400px)模式 或 "fill"(撑满聊天窗口宽度)模式。默认不填时的宽度为 600px。
|
||||||
|
"use_custom_translation": false, // 是否使用自定义翻译数据。默认值 false。为 true 时,在用户点击消息翻译后,使用 i18n 对应的目标语种作为翻译结果。若 i18n 取不到,则使用当前内容请求翻译,不使用自定义翻译数据。
|
||||||
|
"enable_forward_interaction": false, // 转发的卡片是否仍然支持回传交互。默认值 false。
|
||||||
|
"style": { // 添加自定义字号和颜色。可应用在组件 JSON 数据中,设置字号和颜色属性。
|
||||||
|
"text_size": { // 分别为移动端和桌面端添加自定义字号,同时添加兜底字号。用于在组件 JSON 中设置字号属性。支持添加多个自定义字号对象。
|
||||||
|
"cus-0": {
|
||||||
|
"default": "medium", // 在无法差异化配置字号的旧版飞书客户端上,生效的字号属性。选填。
|
||||||
|
"pc": "medium", // 桌面端的字号。
|
||||||
|
"mobile": "large" // 移动端的字号。
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": { // 分别为飞书客户端浅色主题和深色主题添加 RGBA 语法。用于在组件 JSON 中设置颜色属性。支持添加多个自定义颜色对象。
|
||||||
|
"cus-0": {
|
||||||
|
"light_mode": "rgba(5,157,178,0.52)", // 浅色主题下的自定义颜色语法
|
||||||
|
"dark_mode": "rgba(78,23,108,0.49)" // 深色主题下的自定义颜色语法
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"card_link": {
|
||||||
|
// 指定卡片整体的跳转链接。
|
||||||
|
"url": "https://www.baidu.com", // 默认链接地址。未配置指定端地址时,该配置生效。
|
||||||
|
"android_url": "https://developer.android.com/",
|
||||||
|
"ios_url": "https://developer.apple.com/",
|
||||||
|
"pc_url": "https://www.windows.com"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"title": {
|
||||||
|
// 卡片主标题。必填。要为标题配置多语言,参考配置卡片多语言文档。
|
||||||
|
"tag": "plain_text", // 文本类型的标签。可选值:plain_text 和 lark_md。
|
||||||
|
"content": "示例标题" // 标题内容。
|
||||||
|
},
|
||||||
|
"subtitle": {
|
||||||
|
// 卡片副标题。可选。
|
||||||
|
"tag": "plain_text", // 文本类型的标签。可选值:plain_text 和 lark_md。
|
||||||
|
"content": "示例文本" // 标题内容。
|
||||||
|
},
|
||||||
|
"text_tag_list": [
|
||||||
|
// 标题后缀标签,最多设置 3 个 标签,超出不展示。可选。
|
||||||
|
{
|
||||||
|
"tag": "text_tag",
|
||||||
|
"element_id": "custom_id", // 操作元素的唯一标识。用于在调用组件相关接口中指定元素。需开发者自定义。
|
||||||
|
"text": {
|
||||||
|
// 标签内容
|
||||||
|
"tag": "plain_text",
|
||||||
|
"content": "标签 1"
|
||||||
|
},
|
||||||
|
"color": "neutral" // 标签颜色
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"i18n_text_tag_list": {
|
||||||
|
// 多语言标题后缀标签。每个语言环境最多设置 3 个 tag,超出不展示。可选。同时配置原字段和国际化字段,优先生效多语言配置。
|
||||||
|
"zh_cn": [],
|
||||||
|
"en_us": [],
|
||||||
|
"ja_jp": [],
|
||||||
|
"zh_hk": [],
|
||||||
|
"zh_tw": []
|
||||||
|
},
|
||||||
|
"template": "blue", // 标题主题样式颜色。支持 "blue"|"wathet"|"turquoise"|"green"|"yellow"|"orange"|"red"|"carmine"|"violet"|"purple"|"indigo"|"grey"|"default"。默认值 default。
|
||||||
|
"icon": { // 前缀图标。
|
||||||
|
"tag": "standard_icon", // 图标类型。
|
||||||
|
"token": "chat-forbidden_outlined", // 图标的 token。仅在 tag 为 standard_icon 时生效。
|
||||||
|
"color": "orange", // 图标颜色。仅在 tag 为 standard_icon 时生效。
|
||||||
|
"img_key": "img_v2_38811724" // 图片的 key。仅在 tag 为 custom_icon 时生效。
|
||||||
|
},
|
||||||
|
"padding": "12px 8px 12px 8px" // 标题组件的内边距。JSON 2.0 新增属性。默认值 "12px",支持范围 [0,99]px。
|
||||||
|
},
|
||||||
|
"body": { // 卡片正文。
|
||||||
|
// JSON 2.0 新增布局类属性,用于控制子元素排列:
|
||||||
|
"direction": "vertical", // 正文或容器内组件的排列方向。可选值:"vertical"(垂直排列)、"horizontal"(水平排列)。默认为 "vertical"。
|
||||||
|
"padding": "12px 8px 12px 8px", // 正文或容器内组件的内边距,支持范围 [0,99]px。
|
||||||
|
"horizontal_spacing": "3px", // 正文或容器内组件的水平间距,可选值:"small"(4px)、"medium"(8px)、"large"(12px)、"extra_large"(16px)或[0,99]px。
|
||||||
|
"horizontal_align": "left", // 正文或容器内组件的水平对齐方式,可选值:"left"、"center"、"right"。默认值为 "left"。
|
||||||
|
"vertical_spacing": "4px", // 正文或容器内组件的垂直间距,可选值:"small"(4px)、"medium"(8px)、"large"(12px)、"extra_large"(16px)或[0,99]px。
|
||||||
|
"vertical_align": "center", // 正文或容器内组件的垂直对齐方式,可选值:"top"、"center"、"bottom",默认值为 "top"。
|
||||||
|
"elements": [ // 在此传入各个组件的 JSON 数据,组件将按数组顺序纵向流式排列。
|
||||||
|
{
|
||||||
|
"tag": "xxx", // 组件的标签。
|
||||||
|
"margin": "4px", // 组件的外边距,默认值 "0",支持范围 [-99,99]px。JSON 2.0 新增属性。
|
||||||
|
"element_id": "custom_id" // 操作组件的唯一标识。JSON 2.0 新增属性。用于在调用流式更新相关接口中指定组件。在同一张卡片内,该字段的值全局唯一。仅允许使用字母、数字和下划线,必须以字母开头,不得超过 20 字符。
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 属性说明
|
||||||
|
|
||||||
|
本小节介绍卡片结构中的属性。
|
||||||
|
|
||||||
|
### 全局属性
|
||||||
|
|
||||||
|
卡片全局属性包括以下字段。
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"schema": "2.0",
|
||||||
|
"config": {},
|
||||||
|
"card_link": {},
|
||||||
|
"header": {},
|
||||||
|
"body": {
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
各个字段说明如下所示。
|
||||||
|
若这些字段均不传,则卡片 JSON 为 "{}"。飞书开放平台支持发送卡片 JSON 为 "{}" 的空白卡片。
|
||||||
|
|
||||||
|
字段 | 是否必填 | 描述
|
||||||
|
---|---|---
|
||||||
|
schema | 否 | 卡片结构的版本声明。默认为 1.0 版本。要使用 JSON 2.0 结构,必须显示声明 2.0。可选值:<br>- 1.0:卡片 JSON 1.0 结构。详情参考[卡片 JSON 1.0 结构](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-structure)。<br>- 2.0:卡片 JSON 2.0 结构。支持更多字段和能力,如卡片流式更新能力、富文本组件(markdown)更多语法等。详情参考[卡片 JSON 2.0 不兼容变更&更新说明](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-breaking-changes-release-notes)。
|
||||||
|
config | 否 | 配置卡片的全局行为,包括流式更新模式(JSON 2.0 新增能力)、是否允许被转发、是否为共享卡片等。
|
||||||
|
card_link | 否 | 指定卡片整体的点击跳转链接。你可以配置一个默认链接,也可以分别为 PC 端、Android 端、iOS 端配置不同的跳转链接。
|
||||||
|
header | 否 | 标题组件相关配置。详情参考[标题](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/content-components/title)组件。
|
||||||
|
body | 否 | 卡片正文,包含一个名为 elements 的数组,用于放置各类组件。
|
||||||
|
|
||||||
|
### 卡片全局行为设置 `config`
|
||||||
|
|
||||||
|
`config` 用于配置卡片的全局行为,包括流式更新模式、是否允许被转发、是否为共享卡片等。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"streaming_mode": true, // 卡片是否处于流式更新模式,默认值为 false。
|
||||||
|
"streaming_config": { // 流式更新配置。
|
||||||
|
"print_frequency_ms": { // // 流式更新频率,单位:ms
|
||||||
|
"default": 30,
|
||||||
|
"android": 25,
|
||||||
|
"ios": 40,
|
||||||
|
"pc": 50
|
||||||
|
},
|
||||||
|
"print_step": { // // 流式更新步长,单位:字符数
|
||||||
|
"default": 2,
|
||||||
|
"android": 3,
|
||||||
|
"ios": 4,
|
||||||
|
"pc": 5
|
||||||
|
},
|
||||||
|
"print_strategy": "fast" // 流式更新策略,枚举值,可取:fast/delay
|
||||||
|
},
|
||||||
|
"summary": { // 卡片摘要信息。可通过该参数自定义客户端聊天栏消息预览中的展示文案。
|
||||||
|
"content": "自定义内容", // 自定义摘要信息。如果开启了流式更新模式,该参数将默认为“生成中”。
|
||||||
|
"i18n_content": { // 摘要信息的多语言配置。了解支持的所有语种。参考配置卡片多语言文档。
|
||||||
|
"zh_cn": "",
|
||||||
|
"en_us": "",
|
||||||
|
"ja_jp": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locales": [ // JSON 2.0 新增属性。用于指定生效的语言。如果配置 locales,则只有 locales 中的语言会生效。
|
||||||
|
"en_us",
|
||||||
|
"ja_jp"
|
||||||
|
], // 卡片支持的语言列表。
|
||||||
|
"enable_forward": true, // 是否支持转发卡片。默认值为 true。
|
||||||
|
"update_multi": true, // 是否为共享卡片。默认值为 true,JSON 2.0 暂时仅支持设为 true,即更新卡片的内容对所有收到这张卡片的人员可见。
|
||||||
|
"width_mode": "fill", // 卡片宽度模式。支持 "compact"(紧凑宽度 400px)模式 或 "fill"(撑满聊天窗口宽度)模式。默认不填时的宽度为 600px。
|
||||||
|
"use_custom_translation": false, // 是否使用自定义翻译数据。默认值 false。为 true 时,在用户点击消息翻译后,使用 i18n 对应的目标语种作为翻译结果。若 i18n 取不到,则使用当前内容请求翻译,不使用自定义翻译数据。
|
||||||
|
"enable_forward_interaction": false, // 转发的卡片是否仍然支持回传交互。默认值 false。
|
||||||
|
"style": { // 添加自定义字号和颜色。可应用在组件 JSON 数据中,设置字号和颜色属性。
|
||||||
|
"text_size": { // 分别为移动端和桌面端添加自定义字号,同时添加兜底字号。用于在组件 JSON 中设置字号属性。支持添加多个自定义字号对象。
|
||||||
|
"cus-0": {
|
||||||
|
"default": "medium", // 在无法差异化配置字号的旧版飞书客户端上,生效的字号属性。选填。
|
||||||
|
"pc": "medium", // 桌面端的字号。
|
||||||
|
"mobile": "large" // 移动端的字号。
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color": { // 分别为飞书客户端浅色主题和深色主题添加 RGBA 语法。用于在组件 JSON 中设置颜色属性。支持添加多个自定义颜色对象。
|
||||||
|
"cus-0": {
|
||||||
|
"light_mode": "rgba(5,157,178,0.52)", // 浅色主题下的自定义颜色语法
|
||||||
|
"dark_mode": "rgba(78,23,108,0.49)" // 深色主题下的自定义颜色语法
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
`config` 下的各字段说明如下表所示。
|
||||||
|
|
||||||
|
字段名称 | 是否必填 | 类型 | 默认值 | 说明
|
||||||
|
---|---|---|---|---
|
||||||
|
streaming_mode | 否 | Boolean | false | 卡片是否处于流式更新模式。详情参考[流式更新卡片](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/streaming-updates-openapi-overview)。
|
||||||
|
streaming_config | 否 | object | / | 流式更新相关配置。详情参考[流式更新卡片](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/streaming-updates-openapi-overview)。
|
||||||
|
summary | 否 | Object | / | 自定义摘要信息配置。即飞书客户端聊天栏消息预览中的文案。
|
||||||
|
content | 否 | String | 无 | 摘要文本。当 `streaming_mode` 为 `true` 时,该字段默认为“生成中”。支持自定义。
|
||||||
|
i18n_content | 否 | Object | / | 摘要文本的多语言配置。详情参考[局部国际化配置](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/configure-multi-language-content)。
|
||||||
|
enable_forward | 否 | Boolean | true | 是否允许转发卡片。取值:<br>- true:允许<br>- false:不允许
|
||||||
|
update_multi | 否 | Boolean | true | 是否为共享卡片。取值:<br>- true:是共享卡片,更新卡片的内容对所有收到这张卡片的人员可见。<br>- false:非共享卡片,仅操作用户可见卡片的更新内容。
|
||||||
|
width_mode | 否 | String | default | 卡片宽度模式。取值:<br>- default:默认宽度。PC 端宽版、iPad 端上的宽度上限为 600px。<br>- compact:紧凑宽度 400px<br>- fill:自适应屏幕宽度<br>注意:卡片搭建工具上暂时不支持 `width_mode` 属性。
|
||||||
|
use_custom_translation | 否 | Boolean | false | 是否使用自定义翻译数据。取值:<br>- true:在用户点击消息翻译后,使用 i18n 对应的目标语种作为翻译结果。若 i18n 取不到,则使用当前内容请求飞书的机器翻译。<br>- false:不使用自定义翻译数据,直接请求飞书的机器翻译。
|
||||||
|
enable_forward_interaction | 否 | Boolean | false | 转发的卡片是否仍然支持回传交互。
|
||||||
|
style | 否 | Object | 空 | 添加自定义字号和颜色。可应用于组件的 JSON 数据中,设置字号和颜色属性。
|
||||||
|
text_size | 否 | Object | 空 | 分别为移动端和桌面端添加自定义字号,同时添加兜底字号。用于在普通文本组件和富文本组件 JSON 中设置字号属性。支持添加多个自定义字号对象。详情参考[普通文本](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/content-components/plain-text)组件和[富文本(Markdown)](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/content-components/rich-text)组件。
|
||||||
|
color | 否 | Object | 空 | 分别为飞书客户端浅色主题和深色主题添加 RGBA 语法。用于在组件 JSON 中设置颜色属性。支持添加多个自定义颜色对象。详情参考[颜色枚举值](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/enumerations-for-fields-related-to-color)。
|
||||||
|
|
||||||
|
### 卡片全局跳转链接 `card_link`
|
||||||
|
|
||||||
|
`card_link` 字段用于指定卡片整体的点击跳转链接。你可以配置一个默认链接,也可以分别为 PC 端、Android 端、iOS 端配置不同的跳转链接。
|
||||||
|
|
||||||
|
```json
|
||||||
|
"card_link": {
|
||||||
|
// 指定卡片整体的跳转链接。
|
||||||
|
"url": "https://www.baidu.com", // 默认链接地址。未配置指定端地址时,该配置生效。
|
||||||
|
"android_url": "https://developer.android.com/",
|
||||||
|
"ios_url": "https://developer.apple.com/",
|
||||||
|
"pc_url": "https://www.windows.com"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
card_link 下的各字段说明如下表所示。
|
||||||
|
**注意事项**:**注意**
|
||||||
|
- url 和各端的链接(android_url、ios_url、pc_url)必填其中一个。如果不填写 url,则必须完整填写 android_url、ios_url、pc_url 三个字段。如果同时填写了 url 和 android_url、ios_url、pc_url,url 字段生效。
|
||||||
|
- 如果需要禁止某端进行跳转,可以将对应的参数值配置为 `lark://msgcard/unsupported_action`。
|
||||||
|
|
||||||
|
字段名称 | 是否必填 | 类型 | 说明
|
||||||
|
---|---|---|---
|
||||||
|
url | 否 | String | 默认的链接地址。
|
||||||
|
pc_url | 否 | String | PC 端的链接地址。
|
||||||
|
ios_url | 否 | String | iOS 端的链接地址。
|
||||||
|
android_url | 否 | String | Android 端的链接地址。
|
||||||
|
|
||||||
|
### 卡片标题 `header`
|
||||||
|
|
||||||
|
`header` 字段用于配置卡片的标题。了解`header` 字段说明,参见[标题组件](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/content-components/title)。
|
||||||
|
```json
|
||||||
|
"header": {} // 卡片标题
|
||||||
|
```
|
||||||
|
|
||||||
|
### 卡片正文 `body`
|
||||||
|
|
||||||
|
在卡片的`body`字段中,你需要添加卡片组件作为卡片正文内容,组件将按数组顺序纵向流式排列。了解卡片组件,参考[卡片 JSON 2.0 版本组件概述](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/component-json-v2-overview)。
|
||||||
|
|
||||||
|
在卡片 JSON 2.0 结构中,所有组件(标题组件除外)和元素(如 tag 为 plain_text 的文本元素)新增 element_id 属性,作为操作组件或元素的唯一标识。在同一张卡片内,该字段的值全局唯一。仅允许使用字母、数字和下划线,必须以字母开头,不得超过 20 字符。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"body": { // 卡片正文。
|
||||||
|
"elements": [ // 在此传入各个组件的 JSON 数据,组件将按数组顺序纵向流式排列。
|
||||||
|
{
|
||||||
|
"tag": "xxx", // 组件的标签。
|
||||||
|
"element_id": "custom_id" // 操作组件的唯一标识。
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
239
docs/feishu/card_json_schema_2_breaking_changes.md
Normal file
239
docs/feishu/card_json_schema_2_breaking_changes.md
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
# 卡片 JSON 2.0 版本更新说明
|
||||||
|
|
||||||
|
本文档介绍卡片 JSON 2.0 版本与 1.0 版本结构之间的不兼容变更和优化说明。了解完整的 JSON 2.0 结构数据,参考[卡片 JSON 2.0 结构](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-structure)。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 结构支持飞书客户端 7.20 及之后版本。当使用 JSON 2.0 结构的卡片发送至低于 7.20 版本的客户端时,卡片标题可正常显示,但内容将展示兜底的升级提示文案。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- 卡片 JSON 2.0 结构暂时仅支持共享卡片,不支持独享卡片配置。即 `update_multi` 参数仅支持设为 `true`。
|
||||||
|
|
||||||
|
## 不兼容变更
|
||||||
|
|
||||||
|
本小节介绍卡片 JSON 2.0 版本相对于 1.0 版本所发生的不兼容变更。
|
||||||
|
|
||||||
|
### 卡片交互有效期变更
|
||||||
|
|
||||||
|
- 1.0 结构:发出卡片的可交互时间为 30 天,可更新时间为 14 天(如果在第 14-30 天交互卡片,且交互回调动作为更新卡片,更新动作将不会生效)。
|
||||||
|
- 2.0 结构:卡片可交互和可更新时间统一为 14 天。
|
||||||
|
|
||||||
|
### 属性校验变更
|
||||||
|
|
||||||
|
在 JSON 2.0 版本中,传入不支持的属性将报错。
|
||||||
|
| **1.0 结构** | **2.0 结构** |
|
||||||
|
| ------------- | ----------- |
|
||||||
|
| 传入不支持的属性作忽略处理 | 传入不支持的属性将报错 |
|
||||||
|
|
||||||
|
### JSON 全局结构和字段变更
|
||||||
|
|
||||||
|
- **结构变更**
|
||||||
|
|
||||||
|
- JSON 2.0 版本新增 `body` 字段,`elements` 属性放置在 `body` 层级下。了解 2.0 整体结构,参考[卡片 JSON 2.0 结构](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-structure)。
|
||||||
|
- JSON 2.0 版本不再支持通过 `i18n_elements` 字段设置全局多语言。你可通过 `i18n_content` 等局部多语言字段实现组件级别的多语言配置,详情参考[配置卡片多语言](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/configure-multi-language-content)。
|
||||||
|
|
||||||
|
- **`fallback`** **字段变更**
|
||||||
|
|
||||||
|
JSON 2.0 版本暂不支持使用 `fallback` 字段配置自定义的全局降级规则。
|
||||||
|
|
||||||
|
- **默认值变更**
|
||||||
|
|
||||||
|
JSON 2.0 版本中的 `update_multi` 默认值变更为 `true`,且暂时仅支持设为 `true`。`update_multi` 属性用于设置卡片是否为共享卡片;`true` 表示设置卡片为共享卡片,更新卡片的内容对所有收到这张卡片的人员可见;`false` 表示设置卡片为独享卡片,更新卡片的内容对他人不可见。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>{<br>"schema": "1.0", // 不填默认为 1.0<br>"config": {<br>"update_multi": false // 默认值为 false。<br>},<br>"card_link": {},<br>"header": {},<br>"i18n_header": {},<br>"elements": [],<br>"i18n_elements": {},<br>"fallback": {}<br>}<br>``` | ```json<br>{<br>"schema": "2.0", // 2.0 需主动声明<br>"config": {<br>"update_multi": true // 默认值为 true,且暂时仅支持设为 `true`<br>},<br>"card_link": {},<br>"header": {},<br>"body": { // 新增 body 字段,elements 属性放置在 body 层级下。<br>"elements": [] // 不再支持 i18n_elements 字段<br>},<br>"fallback": {}<br>}<br>```
|
||||||
|
|
||||||
|
### 容器类组件布局属性默认值变更
|
||||||
|
|
||||||
|
- [表单容器](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components/containers/form-container)的 `vertical_spacing` 和 `horizontal_spacing` 字段的默认值由 `16px` 改为 `12px`,且支持开发者自定义配置。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>{<br>"margin": "0", // 容器的外边距设置。<br>"padding": "0", // 容器的内边距设置。<br>"vertical_spacing": "16px", // 容器内组件的垂直边距设置。<br>"horizontal_spacing": "16px" // 容器内组件的水平边距设置。<br>}<br>``` | ```json<br>{<br>"margin": "0",<br>"padding": "0",<br>"vertical_spacing": "12px", // 默认值变更,且支持自定义。<br>"horizontal_spacing": "12px" // 默认值变更,且支持自定义。<br>}<br>```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
- [交互容器](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components/containers/interactive-container)的 `vertical_spacing` 和 `horizontal_spacing` 字段的默认值由 `12px` 改为 `4px` 和 `8px`,且支持开发者自定义配置。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>{<br>"margin": "0", // 容器的外边距设置。<br>"padding": "4px 12px", // 容器的内边距设置。<br>"vertical_spacing": "12px", // 容器内组件的垂直边距设置。<br>"horizontal_spacing": "12px" // 容器内组件的水平边距设置。<br>}<br>``` | ```json<br>{<br>"margin": "0",<br>"padding": "4px 12px",<br>"vertical_spacing": "4px", // 默认值变更,且支持自定义。<br>"horizontal_spacing": "8px" // 默认值变更,且支持自定义。<br>}<br>```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
- [折叠面板](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components/containers/collapsible-panel)的 `padding` 字段默认值变更:
|
||||||
|
- 当折叠面板配置了边框(border)或背景色(background_color)时,标题区 `padding` 字段的默认值变更为上下边距 4px,左右边距 8px。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>// 有边框(border)或背景色(background_color)时<br>{<br>"header": {<br>"margin": "0",<br>"padding": "8px" // 标题区的内边距。<br>},<br>"margin": "0",<br>"padding": "8px",<br>"vertical_spacing": "8px",<br>"horizontal_spacing": "8px"<br>}<br>``` | ```json<br>// 有边框(border)或背景色(background_color)时<br>{<br>"header": {<br>"margin": "0",<br>"padding": "4px 8px" // 标题区的内边距默认值变更。上下边距为 4px,左右边距为 8px。<br>},<br>"margin": "0",<br>"padding": "8px",<br>"vertical_spacing": "8px",<br>"horizontal_spacing": "8px"<br>}<br>```
|
||||||
|
|
||||||
|
- 当折叠面板未配置边框(border)或背景色(background_color)时,标题区 `padding` 字段的默认值变更为 0,内容区的内边距默认值变更为上边距 8px,右、下、左边距 0。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>// 无边框(border)或背景色(background_color)时<br>{<br>"header": {<br>"margin": "0",<br>"padding": "8px 0 8px 0" // 标题区的内边距。<br>},<br>"margin": "0",<br>"padding": "0",<br>"vertical_spacing": "8px",<br>"horizontal_spacing": "8px"<br>} | ```json<br>// 无边框(border)或背景色(background_color)时<br>{<br>"header": {<br>"margin": "0",<br>"padding": "0" // 标题区的内边距默认值变更<br>},<br>"margin": "0",<br>"padding": "8px 0 0 0", // 内容区的内边距默认值变更。上边距为 8px,右、下、左边距为 0px。<br>"vertical_spacing": "8px",<br>"horizontal_spacing": "8px"<br>}
|
||||||
|
|
||||||
|
### `vertical_spacing` 和 `horizontal_spacing` 枚举值 & 映射数值变更
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
<code>vertical_spacing</code> 和 <code>horizontal_spacing</code>字段的枚举和对应的值为:<br>- small:4px<br>- medium:8px<br>- large:16px | <code>vertical_spacing</code> 和 <code>horizontal_spacing</code>字段的枚举和对应的值为:<br>- small:4px<br>- medium:8px<br>- large:12px<br>- extra_large:16px
|
||||||
|
|
||||||
|
### 标题组件配置变更
|
||||||
|
|
||||||
|
- 标题组件的 icon 配置结构变更,对齐其它组件:
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
```json<br>{<br>"header": {<br>"title": {},<br>"icon": {<br>"img_key": "img_v2_38811724" <br>},<br>"ud_icon": {<br>"token": "chat-forbidden_outlined", <br>"style": {<br>"color": "red"<br>}<br>}<br>}<br>}<br>``` | ```json<br>{<br>"header": {<br>"title": {},<br>"icon": {<br>"tag": "standard_icon",<br>"token": "chat-forbidden_outlined",<br>"color": "orange", <br>"img_key": "img_v2_38811724"<br>}<br>}<br>}<br>```
|
||||||
|
|
||||||
|
### 图片组件不再支持通栏配置
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
支持 stretch_without_padding 通栏配置,图片的宽度将撑满卡片宽度。<br>```json<br>{<br>"tag": "img",<br>"img_key": "img_v3_0238_073f1823-df2b-4377-86c6-e293f183622j",<br>"size": "stretch_without_padding" // 支持通栏配置,图片宽度将撑满卡片宽度。<br>}<br>``` | 不再支持通栏配置,但可设置 margin 字段为负数实现通栏效果。<br>```json<br>{<br>"tag": "img",<br>"img_key": "img_v3_0238_073f1823-df2b-4377-86c6-e293f183622j",<br>"size": "crop_center",<br>"margin": "4px -12px"<br>}<br>```
|
||||||
|
|
||||||
|
### 富文本(Markdown)组件废弃差异化跳转语法
|
||||||
|
|
||||||
|
2.0 结构不再支持以下差异化跳转语法。你可使用`<link></link>` 标签替代,如 `<link icon='chat_outlined' url='``https://applink.feishu.cn/client/chat/xxxxx'`` pc_url='' ios_url='' android_url=''> `` 战略研讨会 </link> `。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tag": "markdown",
|
||||||
|
"href": {
|
||||||
|
"urlVal": {
|
||||||
|
"url": "xxx",
|
||||||
|
"pc_url": "xxx",
|
||||||
|
"ios_url": "xxx",
|
||||||
|
"android_url": "xxx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content": "[差异化跳转]($urlVal)"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 兜底高度 & 宽度变更
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
- 卡片兜底高度:24px<br>- 组件宽度设置的像素值如果大于父容器宽度,会收缩限制到父容器宽度,仅在交互容器中会截断展示 | - 卡片的兜底高度:40px<br>- 组件宽度设置的像素值如果大于父容器宽度,将会截断展示
|
||||||
|
|
||||||
|
### 废弃备注组件 & 交互模块
|
||||||
|
|
||||||
|
2.0 结构不再支持[备注](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components/content-components/note)(note)组件和[交互模块](https://open.feishu.cn/document/ukTMukTMukTM/uYzM3QjL2MzN04iNzcDN/component-list/common-components-and-elements)("tag" 为 "action"),相关效果可由以下组件和属性实现:
|
||||||
|
- 备注(note)组件:可由普通文本组件配置 notation 字号、grey 字体颜色、icon 属性替代;
|
||||||
|
- 交互模块:可由按钮(button)或折叠按钮组(overflow)组件配置合适的组件间距 (`vertical_spacing` 和 `horizontal_spacing`) 替代。
|
||||||
|
|
||||||
|
## 新增属性和优化说明
|
||||||
|
|
||||||
|
本小节介绍 2.0 结构新增的属性和优化点。
|
||||||
|
|
||||||
|
### 新增 `streaming_mode` 属性,支持流式更新
|
||||||
|
|
||||||
|
2.0 结构新增 `streaming_mode` 和 `summary` 字段,支持卡片流式更新、文本流式更新能力。详情参考[流式更新 OpenAPI 调用指南](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/streaming-updates-openapi-overview)。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"schema": "2.0", // 卡片 JSON 结构的版本。默认为 1.0。
|
||||||
|
"config": {
|
||||||
|
"streaming_mode": true, // 卡片是否处于流式更新模式,默认值为 false。
|
||||||
|
"summary": {
|
||||||
|
"content": "自定义内容", // 自定义摘要信息。默认为“生成中”。
|
||||||
|
"i18n_content": { // 摘要信息的多语言配置。了解支持的所有语种。参考。
|
||||||
|
"zh_cn": "",
|
||||||
|
"en_us": "",
|
||||||
|
"ja_jp": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 新增 `element_id` 属性,用于操作组件
|
||||||
|
|
||||||
|
所有组件和元素(如 `tag` 为 `plain_text` 的文本元素)新增 `element_id` 属性,作为操作组件或元素的唯一标识。在同一张卡片内,该字段的值全局唯一。仅允许使用字母、数字和下划线,必须以字母开头,不得超过 20 字符。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tag": "button", // 组件的标签。
|
||||||
|
"element_id": "button_1" // 操作组件时的唯一标识。
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 组件统一支持布局相关能力
|
||||||
|
|
||||||
|
卡片 JSON 2.0 结构中,各类组件统一新增了一批布局类属性。
|
||||||
|
```json
|
||||||
|
// 卡片层级
|
||||||
|
{
|
||||||
|
"schema": "2.0",
|
||||||
|
"header": {
|
||||||
|
"title": {},
|
||||||
|
"padding": "4px" // 支持设置[0,99]px
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"vertical_spacing": "4px", // body 内子组件的垂直间距,支持设置[0,99]px
|
||||||
|
"padding": "4px", // body 的内边距配置,支持设置[0,99]px
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 组件
|
||||||
|
{
|
||||||
|
"tag": "xxxx",
|
||||||
|
// 各组件均新增的布局类属性
|
||||||
|
"margin": "4px", // 外边距,默认值 "0",支持范围 [-99,99]px
|
||||||
|
// 容器类组件(含elements)新增的布局类属性,用于控制子元素排列
|
||||||
|
"padding": "4px", // 内边距,支持范围 [0,99]px
|
||||||
|
"direction": "vertical", // 布局方向,支持 "vertical"|"horizontal",默认值 "vertical"
|
||||||
|
"horizontal_spacing": "3px", // 水平间距,支持范围 [0,99]px
|
||||||
|
"vertical_spacing": "4px", // 垂直间距,支持范围 [0,99]px
|
||||||
|
"horizontal_align": "left", // 水平对齐,支持 "left"|"center"|"right",默认值 "left"
|
||||||
|
"vertical_align": "center", // 垂直对齐,支持 "top"|"center"|"bottom",默认值 "top"
|
||||||
|
// 其他
|
||||||
|
"elements": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
[普通文本组件](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components/content-components/plain-text)支持配置 width 属性。可取值:
|
||||||
|
- fill:文本的宽度将与组件宽度一致,撑满组件。
|
||||||
|
- auto:文本的宽度自适应文本内容本身的长度。
|
||||||
|
- [16,999]px:自定义文本宽度。
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tag": "div",
|
||||||
|
"width": "fill", // 文本宽度。支持 "fill"|"auto"|"{{[16,999]}}px"。默认值为 fill。
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 富文本组件支持标准 markdown 语法
|
||||||
|
|
||||||
|
[卡片 JSON 2.0 结构](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-structure)支持除 `HTMLBlock` 外所有标准的 Markdown 语法和部分 HTML 语法。了解 Markdown 标准语法,请参考 [CommonMark Spec 官方文档](https://spec.commonmark.org/0.31.2/)。你也可以使用 [CommonMark playground](https://spec.commonmark.org/dingus/) 预览 Markdown 效果。了解更多,参考[富文本(Markdown)](https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-json-v2-components/content-components/rich-text)。
|
||||||
|
|
||||||
|
注意,在卡片的富文本组件中,以下语法的渲染效果与 CommonMark 有差异:
|
||||||
|
- 富文本组件支持使用一个 Enter 键作为软换行(Soft Break);支持两个 Enter 键作为硬换行(Hard Break)。软换行在渲染时可能会被忽略,具体取决于渲染器如何处理;硬换行在渲染时始终会显示为一个新行。
|
||||||
|
|
||||||
|
- 2.0 结构支持以下 HTML 语法:
|
||||||
|
- 开标签 `<br>`
|
||||||
|
- 自闭合标签 `<br/>`
|
||||||
|
- 开标签 `<hr>`
|
||||||
|
- 自闭合标签 `<hr/>`
|
||||||
|
- 闭合标签 `<person></person>`
|
||||||
|
- 闭合标签 `<local_datetime></local_datetime>`
|
||||||
|
- 闭合标签 `<at></at>`
|
||||||
|
- 闭合标签 `<a></a>`
|
||||||
|
- 闭合标签 `<text_tag></text_tag>`
|
||||||
|
- 闭合标签 `<raw></raw>`
|
||||||
|
- 闭合标签 `<link></link>`
|
||||||
|
- 闭合标签 `</font>`,支持嵌套其它标签,如 `<font color=red>red<font color=green>greenagain</font>`。其它标签包括:
|
||||||
|
- 闭合标签 `<local_datetime></local_datetime>`
|
||||||
|
- 闭合标签 `<at></at>`
|
||||||
|
- 闭合标签 `<a></a>`
|
||||||
|
- 闭合标签 `<link></link>`
|
||||||
|
- 闭合标签 `<font></font>`
|
||||||
|
|
||||||
|
### 容器类组件新增可内嵌的组件类型
|
||||||
|
|
||||||
|
JSON 2.0 结构中,表单容器、交互容器、折叠面板、分栏组件可内嵌除表单容器和表格组件外的其它所有组件。
|
||||||
|
|
||||||
|
1.0 结构 | 2.0 结构
|
||||||
|
---|---
|
||||||
|
- 表单容器:不支持内嵌表格、图表、和表单容器组件;不可直接内嵌普通文本组件<br>- 交互容器:仅支持内嵌普通文本、富文本、图片、备注、分栏、勾选器、交互容器组件<br>- 折叠面板:不支持内嵌表单容器(form)和表格组件(table)组件<br>- 分栏:不支持内嵌表格(table)、表单(form)和多图混排(img_combination)组件 | 表单容器、交互容器、折叠面板、分栏组件可内嵌除表单容器(form)和表格组件(table)外的其它所有组件。
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ Bot command prefix: {prefix}
|
|||||||
- Close/switch sessions: "关掉第一个" → run_command("{prefix}close 1")
|
- Close/switch sessions: "关掉第一个" → run_command("{prefix}close 1")
|
||||||
- Change routing mode: "切换到直连模式" → run_command("{prefix}direct")
|
- Change routing mode: "切换到直连模式" → run_command("{prefix}direct")
|
||||||
- Set a reminder: "10分钟后提醒我" → run_command("{prefix}remind 10m 提醒我")
|
- Set a reminder: "10分钟后提醒我" → run_command("{prefix}remind 10m 提醒我")
|
||||||
- Check status: "看看现在有哪些 session" → run_command("{prefix}status")
|
- Check status: "看看现在有哪些 session" → run_command("{prefix}list")
|
||||||
- Any other command the user would type manually
|
- Any other command the user would type manually
|
||||||
|
|
||||||
Available bot commands (pass verbatim to run_command):
|
Available bot commands (pass verbatim to run_command):
|
||||||
@ -59,7 +59,7 @@ Available bot commands (pass verbatim to run_command):
|
|||||||
{prefix}perm <mode> [conv_id] — permission mode: default, edit, plan, bypass
|
{prefix}perm <mode> [conv_id] — permission mode: default, edit, plan, bypass
|
||||||
{prefix}direct — direct mode (bypass LLM for CC messages)
|
{prefix}direct — direct mode (bypass LLM for CC messages)
|
||||||
{prefix}smart — smart mode (LLM routing, default)
|
{prefix}smart — smart mode (LLM routing, default)
|
||||||
{prefix}status — list sessions
|
{prefix}list — list sessions
|
||||||
{prefix}remind <Ns|Nm|Nh> <msg> — one-shot reminder
|
{prefix}remind <Ns|Nm|Nh> <msg> — one-shot reminder
|
||||||
{prefix}tasks — list background tasks
|
{prefix}tasks — list background tasks
|
||||||
|
|
||||||
|
|||||||
@ -36,9 +36,14 @@ class TestHelp:
|
|||||||
from bot.commands import handle_command
|
from bot.commands import handle_command
|
||||||
_setup_user()
|
_setup_user()
|
||||||
reply = await handle_command("user_abc123", "//help")
|
reply = await handle_command("user_abc123", "//help")
|
||||||
for cmd in ("//new", "//status", "//close", "//switch", "//perm",
|
for cmd in ("//new", "//list", "//close", "//switch", "//perm",
|
||||||
"//stop", "//progress", "//direct", "//smart", "//shell"):
|
"//stop", "//progress", "//direct", "//smart", "//shell",
|
||||||
|
"//help"):
|
||||||
assert cmd in reply, f"Missing {cmd} in help"
|
assert cmd in reply, f"Missing {cmd} in help"
|
||||||
|
# Should NOT list //retry (unimplemented)
|
||||||
|
assert "//retry" not in reply
|
||||||
|
# Should list aliases
|
||||||
|
assert "alias" in reply.lower()
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_h_alias(self):
|
async def test_h_alias(self):
|
||||||
@ -184,12 +189,12 @@ class TestSwitch:
|
|||||||
|
|
||||||
# ── //status ────────────────────────────────────────────────────────────────
|
# ── //status ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
class TestStatus:
|
class TestList:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_no_sessions(self):
|
async def test_no_sessions(self):
|
||||||
from bot.commands import handle_command
|
from bot.commands import handle_command
|
||||||
_setup_user()
|
_setup_user()
|
||||||
reply = await handle_command("user_abc123", "//status")
|
reply = await handle_command("user_abc123", "//list")
|
||||||
assert "No active sessions" in reply
|
assert "No active sessions" in reply
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@ -198,7 +203,7 @@ class TestStatus:
|
|||||||
_setup_user()
|
_setup_user()
|
||||||
_add_session("s1")
|
_add_session("s1")
|
||||||
_add_session("s2")
|
_add_session("s2")
|
||||||
reply = await handle_command("user_abc123", "//status")
|
reply = await handle_command("user_abc123", "//list")
|
||||||
assert "s1" in reply
|
assert "s1" in reply
|
||||||
assert "s2" in reply
|
assert "s2" in reply
|
||||||
|
|
||||||
@ -207,9 +212,16 @@ class TestStatus:
|
|||||||
from bot.commands import handle_command
|
from bot.commands import handle_command
|
||||||
_setup_user()
|
_setup_user()
|
||||||
_add_session("s1", activate=True)
|
_add_session("s1", activate=True)
|
||||||
reply = await handle_command("user_abc123", "//status")
|
reply = await handle_command("user_abc123", "//list")
|
||||||
assert "→" in reply
|
assert "→" in reply
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_status_alias_still_works(self):
|
||||||
|
from bot.commands import handle_command
|
||||||
|
_setup_user()
|
||||||
|
reply = await handle_command("user_abc123", "//status")
|
||||||
|
assert "No active sessions" in reply
|
||||||
|
|
||||||
|
|
||||||
# ── //perm ──────────────────────────────────────────────────────────────────
|
# ── //perm ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@ -767,20 +767,18 @@ class TestBuildApprovalCard:
|
|||||||
assert "权限审批" in card["header"]["title"]["content"]
|
assert "权限审批" in card["header"]["title"]["content"]
|
||||||
|
|
||||||
body_elements = card["body"]["elements"]
|
body_elements = card["body"]["elements"]
|
||||||
# Should have markdown, action, and note elements
|
|
||||||
tags = [e["tag"] for e in body_elements]
|
tags = [e["tag"] for e in body_elements]
|
||||||
|
# JSON 2.0: no "action" wrapper, no "note" — buttons are direct elements
|
||||||
|
assert "action" not in tags
|
||||||
|
assert "note" not in tags
|
||||||
assert "markdown" in tags
|
assert "markdown" in tags
|
||||||
assert "action" in tags
|
assert tags.count("button") == 2
|
||||||
assert "note" in tags
|
|
||||||
|
|
||||||
# Action should have 2 buttons
|
# Buttons carry approve/deny values
|
||||||
action_el = next(e for e in body_elements if e["tag"] == "action")
|
buttons = [e for e in body_elements if e["tag"] == "button"]
|
||||||
assert len(action_el["actions"]) == 2
|
assert buttons[0]["value"]["action"] == "approve"
|
||||||
# First button should be approve
|
assert buttons[0]["value"]["conv_id"] == "c1"
|
||||||
assert action_el["actions"][0]["value"]["action"] == "approve"
|
assert buttons[1]["value"]["action"] == "deny"
|
||||||
assert action_el["actions"][0]["value"]["conv_id"] == "c1"
|
|
||||||
# Second button should be deny
|
|
||||||
assert action_el["actions"][1]["value"]["action"] == "deny"
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user