Просмотр исходного кода

更新技能文档与页面配置

csk 3 недель назад
Родитель
Сommit
1bc8401818

+ 13 - 13
.agents/skills/lark-attendance/SKILL.md

@@ -7,26 +7,27 @@ metadata:
     bins: ["lark-cli"]
   cliHelp: "lark-cli attendance --help"
 ---
-
 # attendance (v1)
 
-**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),其中包含认证、权限处理**
+**CRITICAL — 开始前 MUST 先用 Read 工具读取** `../lark-shared/SKILL.md`**,其中包含认证、权限处理**
 
 ## 默认参数自动填充规则
 
 调用任何 API 时,以下参数 **必须自动填充,禁止向用户询问**:
 
-| 参数 | 固定值 | 说明                                 |
-|------|--------|------------------------------------|
+| 参数  | 固定值 | 说明  |
+| --- | --- | --- |
 | `employee_type` | `"employee_no"` | `employee_type`始终等于`"employee_no"` |
-| `user_ids` | `[]`(空数组) | `user_ids`始终等于`[]`                 |
+| `user_ids` | `[]`(空数组) | `user_ids`始终等于`[]` |
 
 ### 填充示例
 
 当构建 `--params` 参数时,自动注入上述字段:
-- `employee_type` 保持 `"employee_no"` 不变
+
+-   `employee_type` 保持 `"employee_no"` 不变
 
 当构建 `--data` 参数时,自动注入上述字段:
+
 ```json
 {
   "user_ids": [],
@@ -34,7 +35,7 @@ metadata:
 }
 ```
 
-> **注意**:`user_ids` 数组保持为空[],`employee_type` 保持 `"employee_no"` 不变。
+> **注意**:`user_ids` 数组保持为空\[\],`employee_type` 保持 `"employee_no"` 不变。
 
 ## API Resources
 
@@ -45,13 +46,12 @@ lark-cli attendance <resource> <method> [flags]  # 调用 API
 
 > **重要**:使用原生 API 时,必须先运行 `schema` 查看 `--data` / `--params` 参数结构,不要猜测字段格式。
 
-### user_tasks
+### user\_tasks
 
-- `query` — 查询用户考勤打卡记录
+-   `query` — 查询用户考勤打卡记录
 
 ## 权限表
 
-| 方法 | 所需 scope |
-|------|-----------|
-| `user_tasks.query` | `attendance:task:readonly` |
-
+| 方法  | 所需 scope |
+| --- | --- |
+| `user_tasks.query` | `attendance:task:readonly` |

+ 63 - 65
.agents/skills/lark-okr/SKILL.md

@@ -7,25 +7,24 @@ metadata:
     bins: [ "lark-cli" ]
   cliHelp: "lark-cli okr --help"
 ---
-
 # okr (v2)
 
-**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md),其中包含认证、权限处理**
+**CRITICAL — 开始前 MUST 先用 Read 工具读取** `../lark-shared/SKILL.md`**,其中包含认证、权限处理**
 
 ## Shortcuts(推荐优先使用)
 
 Shortcut 是对常用操作的高级封装(`lark-cli okr +<verb> [flags]`)。有 Shortcut 的操作优先使用。
 
-| Shortcut                                               | 说明                       |
-|--------------------------------------------------------|--------------------------|
-| [`+cycle-list`](references/lark-okr-cycle-list.md)     | 获取特定用户的 OKR 周期列表,可以按时间筛选 |
-| [`+cycle-detail`](references/lark-okr-cycle-detail.md) | 获取特定 OKR 中所有目标和关键结果的内容   |
+| Shortcut | 说明  |
+| --- | --- |
+| `+cycle-list` | 获取特定用户的 OKR 周期列表,可以按时间筛选 |
+| `+cycle-detail` | 获取特定 OKR 中所有目标和关键结果的内容 |
 
 ## 格式说明
 
-- [`ContentBlock 富文本格式`](references/lark-okr-contentblock.md) — Objective/KeyResult/Notes 字段使用的富文本格式说明
-- [`OKR 业务实体`](references/lark-okr-entities.md) 获取 OKR 实体结构,定义和关系,帮助你更好的使用 OKR 功能
-- **强烈建议** 在操作 OKR 前,阅读[`OKR 业务实体`](references/lark-okr-entities.md)以了解基础概念
+-   `ContentBlock 富文本格式` — Objective/KeyResult/Notes 字段使用的富文本格式说明
+-   `OKR 业务实体` 获取 OKR 实体结构,定义和关系,帮助你更好的使用 OKR 功能
+-   **强烈建议** 在操作 OKR 前,阅读`OKR 业务实体`以了解基础概念
 
 ## API Resources
 
@@ -38,90 +37,89 @@ lark-cli okr <resource> <method> [flags] # 调用 API
 
 ### alignments
 
-- `delete` — 删除对齐关系
-- `get` — 获取对齐关系
+-   `delete` — 删除对齐关系
+-   `get` — 获取对齐关系
 
 ### categories
 
-- `list` — 批量获取分类
+-   `list` — 批量获取分类
 
 ### cycles
 
-- `list` — 批量获取用户周期
-- `objectives_position` — 更新用户周期下全部目标的位置
-  - 请求中必须同时修改对应周期下全部目标的位置,且不允许位置重叠,否则会参数校验失败。
-- `objectives_weight` — 更新用户周期下全部目标的权重
-  - 请求中必须同时修改对应周期下全部目标的权重,且所有权重值的和必须等于 1 ,否则会参数校验失败。
+-   `list` — 批量获取用户周期
+-   `objectives_position` — 更新用户周期下全部目标的位置
+    -   请求中必须同时修改对应周期下全部目标的位置,且不允许位置重叠,否则会参数校验失败。
+-   `objectives_weight` — 更新用户周期下全部目标的权重
+    -   请求中必须同时修改对应周期下全部目标的权重,且所有权重值的和必须等于 1 ,否则会参数校验失败。
 
 ### cycle.objectives
 
-- `create` — 创建目标
-- `list` — 批量获取用户周期下的目标
+-   `create` — 创建目标
+-   `list` — 批量获取用户周期下的目标
 
 ### indicators
 
-- `patch` — 更新量化指标
+-   `patch` — 更新量化指标
 
-### key_results
+### key\_results
 
-- `delete` — 删除关键结果
-- `get` — 获取关键结果
-- `patch` — 更新关键结果
+-   `delete` — 删除关键结果
+-   `get` — 获取关键结果
+-   `patch` — 更新关键结果
 
-### key_result.indicators
+### key\_result.indicators
 
-- `list` — 获取关键结果的量化指标
+-   `list` — 获取关键结果的量化指标
 
 ### objectives
 
-- `delete` — 删除目标
-- `get` — 获取目标
-- `key_results_position` — 更新全部关键结果的位置
-  - 请求中必须同时修改对应目标下全部关键结果的位置,且不允许位置重叠,否则会参数校验失败。
-- `key_results_weight` — 更新全部关键结果的权重
-  - 请求中必须同时修改对应目标下全部关键结果的权重,且所有权重值的和必须等于 1 ,否则会参数校验失败。
-- `patch` — 更新目标
+-   `delete` — 删除目标
+-   `get` — 获取目标
+-   `key_results_position` — 更新全部关键结果的位置
+    -   请求中必须同时修改对应目标下全部关键结果的位置,且不允许位置重叠,否则会参数校验失败。
+-   `key_results_weight` — 更新全部关键结果的权重
+    -   请求中必须同时修改对应目标下全部关键结果的权重,且所有权重值的和必须等于 1 ,否则会参数校验失败。
+-   `patch` — 更新目标
 
 ### objective.alignments
 
-- `create` — 创建对齐关系
-  - 对齐不允许对齐自己的目标,且发起对齐的目标和被对齐的目标所在周期时间上必须有重叠,否则会参数校验失败。
-- `list` — 批量获取目标下的对齐关系
+-   `create` — 创建对齐关系
+    -   对齐不允许对齐自己的目标,且发起对齐的目标和被对齐的目标所在周期时间上必须有重叠,否则会参数校验失败。
+-   `list` — 批量获取目标下的对齐关系
 
 ### objective.indicators
 
-- `list` — 获取目标的量化指标
+-   `list` — 获取目标的量化指标
 
-### objective.key_results
+### objective.key\_results
 
-- `create` — 创建关键结果
-- `list` — 批量获取目标下的关键结果
+-   `create` — 创建关键结果
+-   `list` — 批量获取目标下的关键结果
 
 ## 权限表
 
-| 方法                                | 所需 scope                    |
-|-----------------------------------|-----------------------------|
-| `alignments.delete`               | `okr:okr.content:writeonly` |
-| `alignments.get`                  | `okr:okr.content:readonly`  |
-| `categories.list`                 | `okr:okr.setting:read`      |
-| `cycles.list`                     | `okr:okr.period:readonly`   |
-| `cycles.objectives_position`      | `okr:okr.content:writeonly` |
-| `cycles.objectives_weight`        | `okr:okr.content:writeonly` |
-| `cycle.objectives.create`         | `okr:okr.content:writeonly` |
-| `cycle.objectives.list`           | `okr:okr.content:readonly`  |
-| `indicators.patch`                | `okr:okr.content:writeonly` |
-| `key_results.delete`              | `okr:okr.content:writeonly` |
-| `key_results.get`                 | `okr:okr.content:readonly`  |
-| `key_results.patch`               | `okr:okr.content:writeonly` |
-| `key_result.indicators.list`      | `okr:okr.content:readonly`  |
-| `objectives.delete`               | `okr:okr.content:writeonly` |
-| `objectives.get`                  | `okr:okr.content:readonly`  |
+| 方法  | 所需 scope |
+| --- | --- |
+| `alignments.delete` | `okr:okr.content:writeonly` |
+| `alignments.get` | `okr:okr.content:readonly` |
+| `categories.list` | `okr:okr.setting:read` |
+| `cycles.list` | `okr:okr.period:readonly` |
+| `cycles.objectives_position` | `okr:okr.content:writeonly` |
+| `cycles.objectives_weight` | `okr:okr.content:writeonly` |
+| `cycle.objectives.create` | `okr:okr.content:writeonly` |
+| `cycle.objectives.list` | `okr:okr.content:readonly` |
+| `indicators.patch` | `okr:okr.content:writeonly` |
+| `key_results.delete` | `okr:okr.content:writeonly` |
+| `key_results.get` | `okr:okr.content:readonly` |
+| `key_results.patch` | `okr:okr.content:writeonly` |
+| `key_result.indicators.list` | `okr:okr.content:readonly` |
+| `objectives.delete` | `okr:okr.content:writeonly` |
+| `objectives.get` | `okr:okr.content:readonly` |
 | `objectives.key_results_position` | `okr:okr.content:writeonly` |
-| `objectives.key_results_weight`   | `okr:okr.content:writeonly` |
-| `objectives.patch`                | `okr:okr.content:writeonly` |
-| `objective.alignments.create`     | `okr:okr.content:writeonly` |
-| `objective.alignments.list`       | `okr:okr.content:readonly`  |
-| `objective.indicators.list`       | `okr:okr.content:readonly`  |
-| `objective.key_results.create`    | `okr:okr.content:writeonly` |
-| `objective.key_results.list`      | `okr:okr.content:readonly`  |
-
+| `objectives.key_results_weight` | `okr:okr.content:writeonly` |
+| `objectives.patch` | `okr:okr.content:writeonly` |
+| `objective.alignments.create` | `okr:okr.content:writeonly` |
+| `objective.alignments.list` | `okr:okr.content:readonly` |
+| `objective.indicators.list` | `okr:okr.content:readonly` |
+| `objective.key_results.create` | `okr:okr.content:writeonly` |
+| `objective.key_results.list` | `okr:okr.content:readonly` |

+ 56 - 56
.agents/skills/lark-okr/references/lark-okr-contentblock.md

@@ -82,132 +82,132 @@ OKR 的 Objective、KeyResult 中的 content/notes 字段使用 `ContentBlock` 
 
 根级别内容块。
 
-| 字段       | 类型                      | 说明      |
-|----------|-------------------------|---------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `blocks` | `ContentBlockElement[]` | 内容块元素数组 |
 
 ### ContentBlockElement
 
 内容块元素,支持段落或图库。
 
-| 字段                   | 类型                 | 说明                                         |
-|----------------------|--------------------|--------------------------------------------|
-| `block_element_type` | `BlockElementType` | 块类型:`paragraph` \| `gallery`               |
-| `paragraph`          | `ContentParagraph` | 段落内容(当 `block_element_type="paragraph"` 时) |
-| `gallery`            | `ContentGallery`   | 图库内容(当 `block_element_type="gallery"` 时)   |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `block_element_type` | `BlockElementType` | 块类型:`paragraph` \| `gallery` |
+| `paragraph` | `ContentParagraph` | 段落内容(当 `block_element_type="paragraph"` 时) |
+| `gallery` | `ContentGallery` | 图库内容(当 `block_element_type="gallery"` 时) |
 
 ### ContentParagraph
 
 段落内容。
 
-| 字段         | 类型                          | 说明          |
-|------------|-----------------------------|-------------|
-| `style`    | `ContentParagraphStyle`     | 段落样式(列表类型等) |
-| `elements` | `ContentParagraphElement[]` | 段落内元素数组     |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `style` | `ContentParagraphStyle` | 段落样式(列表类型等) |
+| `elements` | `ContentParagraphElement[]` | 段落内元素数组 |
 
 ### ContentParagraphElement
 
 段落内元素,支持文本、文档链接、提及。
 
-| 字段                       | 类型                     | 说明                                        |
-|--------------------------|------------------------|-------------------------------------------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `paragraph_element_type` | `ParagraphElementType` | 元素类型:`textRun` \| `docsLink` \| `mention` |
-| `text_run`               | `ContentTextRun`       | 文本内容                                      |
-| `docs_link`              | `ContentDocsLink`      | 飞书文档链接                                    |
-| `mention`                | `ContentMention`       | 用户提及                                      |
+| `text_run` | `ContentTextRun` | 文本内容 |
+| `docs_link` | `ContentDocsLink` | 飞书文档链接 |
+| `mention` | `ContentMention` | 用户提及 |
 
 ### ContentTextRun
 
 文本块。
 
-| 字段      | 类型                 | 说明   |
-|---------|--------------------|------|
-| `text`  | `string`           | 文本内容 |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `text` | `string` | 文本内容 |
 | `style` | `ContentTextStyle` | 文本样式 |
 
 ### ContentTextStyle
 
 文本样式。
 
-| 字段               | 类型             | 说明    |
-|------------------|----------------|-------|
-| `bold`           | `boolean`      | 是否粗体  |
-| `strike_through` | `boolean`      | 是否删除线 |
-| `back_color`     | `ContentColor` | 背景颜色  |
-| `text_color`     | `ContentColor` | 文字颜色  |
-| `link`           | `ContentLink`  | 链接    |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `bold` | `boolean` | 是否粗体 |
+| `strike_through` | `boolean` | 是否删除线 |
+| `back_color` | `ContentColor` | 背景颜色 |
+| `text_color` | `ContentColor` | 文字颜色 |
+| `link` | `ContentLink` | 链接  |
 
 ### ContentColor
 
 颜色。
 
-| 字段      | 类型        | 说明           |
-|---------|-----------|--------------|
-| `red`   | `int32`   | 红色通道 (0-255) |
-| `green` | `int32`   | 绿色通道 (0-255) |
-| `blue`  | `int32`   | 蓝色通道 (0-255) |
-| `alpha` | `float64` | 透明度 (0-1)    |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `red` | `int32` | 红色通道 (0-255) |
+| `green` | `int32` | 绿色通道 (0-255) |
+| `blue` | `int32` | 蓝色通道 (0-255) |
+| `alpha` | `float64` | 透明度 (0-1) |
 
 ### ContentParagraphStyle
 
 段落样式。
 
-| 字段     | 类型            | 说明   |
-|--------|---------------|------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `list` | `ContentList` | 列表样式 |
 
 ### ContentList
 
 列表样式。
 
-| 字段             | 类型         | 说明                                                                  |
-|----------------|------------|---------------------------------------------------------------------|
-| `list_type`    | `ListType` | 列表类型:`bullet` \| `number` \| `checkBox` \| `checkedBox` \| `indent` |
-| `indent_level` | `int32`    | 缩进层级                                                                |
-| `number`       | `int32`    | 序号(当 `list_type="number"` 时)                                        |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `list_type` | `ListType` | 列表类型:`bullet` \| `number` \| `checkBox` \| `checkedBox` \| `indent` |
+| `indent_level` | `int32` | 缩进层级 |
+| `number` | `int32` | 序号(当 `list_type="number"` 时) |
 
 ### ContentGallery
 
 图库。
 
-| 字段       | 类型                   | 说明    |
-|----------|----------------------|-------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `images` | `ContentImageItem[]` | 图片项数组 |
 
 ### ContentImageItem
 
 图片项。
 
-| 字段           | 类型        | 说明       |
-|--------------|-----------|----------|
-| `file_token` | `string`  | 文件 token |
-| `src`        | `string`  | 图片 URL   |
-| `width`      | `float64` | 宽度       |
-| `height`     | `float64` | 高度       |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `file_token` | `string` | 文件 token |
+| `src` | `string` | 图片 URL |
+| `width` | `float64` | 宽度  |
+| `height` | `float64` | 高度  |
 
 ### ContentDocsLink
 
 飞书文档链接。
 
-| 字段      | 类型       | 说明     |
-|---------|----------|--------|
-| `url`   | `string` | 链接 URL |
-| `title` | `string` | 链接标题   |
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
+| `url` | `string` | 链接 URL |
+| `title` | `string` | 链接标题 |
 
 ### ContentMention
 
 提及。
 
-| 字段        | 类型       | 说明    |
-|-----------|----------|-------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `user_id` | `string` | 用户 ID |
 
 ### ContentLink
 
 链接。
 
-| 字段    | 类型       | 说明     |
-|-------|----------|--------|
+| 字段  | 类型  | 说明  |
+| --- | --- | --- |
 | `url` | `string` | 链接 URL |
 
 ## 使用示例
@@ -310,4 +310,4 @@ OKR 的 Objective、KeyResult 中的 content/notes 字段使用 `ContentBlock` 
     }
   ]
 }
-```
+```

+ 12 - 12
.agents/skills/lark-okr/references/lark-okr-cycle-detail.md

@@ -1,6 +1,6 @@
 # okr +cycle-detail
 
-> **前置条件:** 先阅读 [`lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
+> **前置条件:** 先阅读 `lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
 
 列出指定 OKR 周期下的所有目标及其关键结果。
 
@@ -16,17 +16,17 @@ lark-cli okr +cycle-detail --cycle-id 1234567890123456789 --dry-run
 
 ## 参数
 
-| 参数                      | 必填 | 默认值    | 说明                                      |
-|-------------------------|----|--------|-----------------------------------------|
-| `--cycle-id &lt;id&gt;` | 是  | —      | OKR 周期 ID(int64 类型)。从 `+cycle-list` 获取。 |
-| `--dry-run`             | 否  | —      | 预览 API 调用而不实际执行。                        |
-| `--format <fmt>`        | 否  | `json` | 输出格式。                                   |
+| 参数  | 必填  | 默认值 | 说明  |
+| --- | --- | --- | --- |
+| `--cycle-id &lt;id&gt;` | 是   | —   | OKR 周期 ID(int64 类型)。从 `+cycle-list` 获取。 |
+| `--dry-run` | 否   | —   | 预览 API 调用而不实际执行。 |
+| `--format <fmt>` | 否   | `json` | 输出格式。 |
 
 ## 工作流程
 
-1. 使用 `lark-cli okr +cycle-list` 获取 OKR 周期 ID。
-2. 执行 `lark-cli okr +cycle-detail --cycle-id "123456"`。
-3. 报告结果:找到的目标数量、每个目标的 ID、分数、权重及其关键结果。
+1.  使用 `lark-cli okr +cycle-list` 获取 OKR 周期 ID。
+2.  执行 `lark-cli okr +cycle-detail --cycle-id "123456"`。
+3.  报告结果:找到的目标数量、每个目标的 ID、分数、权重及其关键结果。
 
 ## 输出
 
@@ -74,10 +74,10 @@ lark-cli okr +cycle-detail --cycle-id 1234567890123456789 --dry-run
   "total": 1
 }
 ```
-其中,content 和 notes 字段是 JSON 字符串,为 OKR ContentBlock 富文本格式。请参考 [lark-okr-contentblock.md](lark-okr-contentblock.md) 了解详细信息。
 
+其中,content 和 notes 字段是 JSON 字符串,为 OKR ContentBlock 富文本格式。请参考 [lark-okr-contentblock.md](lark-okr-contentblock.md) 了解详细信息。
 
 ## 参考
 
-- [lark-okr](../SKILL.md) -- 所有 OKR 命令(shortcut 和 API 接口)
-- [lark-shared](../../lark-shared/SKILL.md) -- 认证和全局参数
+-   [lark-okr](../SKILL.md) -- 所有 OKR 命令(shortcut 和 API 接口)
+-   [lark-shared](../../lark-shared/SKILL.md) -- 认证和全局参数

+ 25 - 24
.agents/skills/lark-okr/references/lark-okr-cycle-list.md

@@ -1,6 +1,6 @@
 # okr +cycle-list
 
-> **前置条件:** 先阅读 [`lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
+> **前置条件:** 先阅读 `lark-shared/SKILL.md` 了解认证、全局参数和安全规则。
 
 列出指定用户的 OKR 周期,支持可选的时间范围过滤。
 
@@ -22,20 +22,20 @@ lark-cli okr +cycle-list --user-id "ou_xxx" --dry-run
 
 ## 参数
 
-| 参数                            | 必填 | 默认值       | 说明                                                               |
-|-------------------------------|----|-----------|------------------------------------------------------------------|
-| `--user-id &lt;id&gt;`        | 是  | —         | OKR 所有者的用户 ID                                                    |
-| `--user-id-type &lt;type&gt;` | 否  | `open_id` | 用户 ID 类型:`open_id` \| `union_id` \| `user_id`                    |
-| `--time-range &lt;range&gt;`  | 否  | —         | 按时间范围过滤周期。格式:`YYYY-MM--YYYY-MM`(例如 `2025-01--2025-06`)。留空获取所有周期。 |
-| `--dry-run`                   | 否  | —         | 预览 API 调用而不实际执行。                                                 |
-| `--format &lt;fmt&gt;`        | 否  | `json`    | 输出格式。                                                            |
+| 参数  | 必填  | 默认值 | 说明  |
+| --- | --- | --- | --- |
+| `--user-id &lt;id&gt;` | 是   | —   | OKR 所有者的用户 ID |
+| `--user-id-type &lt;type&gt;` | 否   | `open_id` | 用户 ID 类型:`open_id` \| `union_id` \| `user_id` |
+| `--time-range &lt;range&gt;` | 否   | —   | 按时间范围过滤周期。格式:`YYYY-MM--YYYY-MM`(例如 `2025-01--2025-06`)。留空获取所有周期。 |
+| `--dry-run` | 否   | —   | 预览 API 调用而不实际执行。 |
+| `--format &lt;fmt&gt;` | 否   | `json` | 输出格式。 |
 
 ## 工作流程
 
-1. 获取目标用户的 `open_id`(或其他 ID 类型)。如果用户说"我的 OKR 周期",先通过 `lark-cli contact +get-user` 获取当前用户的
-   ID。
-2. 执行 `lark-cli okr +cycle-list --user-id "ou_xxx"`,可选择使用 `--time-range`。
-3. 报告结果:找到的周期数量、每个周期的 ID、开始/结束时间和状态。
+1.  获取目标用户的 `open_id`(或其他 ID 类型)。如果用户说"我的 OKR 周期",先通过 `lark-cli contact +get-user` 获取当前用户的  
+    ID。
+2.  执行 `lark-cli okr +cycle-list --user-id "ou_xxx"`,可选择使用 `--time-range`。
+3.  报告结果:找到的周期数量、每个周期的 ID、开始/结束时间和状态。
 
 ## 输出
 
@@ -64,24 +64,25 @@ lark-cli okr +cycle-list --user-id "ou_xxx" --dry-run
 ```
 
 在这个周期信息中,这些字段值得关注:
-- `id` 是这个周期的 ID,你通常需要用它在之后使用 `okr +cycle-detail` 获取 OKR 内容详情
-- `start_time` `end_time` 是周期的起止时间,总是从某个月1日开始,直到此月或之后某月的最后一日结束。
-  - 在 OKR 系统中,我们只关注这个时间的年月部分,如 “2025-01-01开始,2025-06-30结束” 的周期被称作 “2025 年 1-6 月” 周期,而 “2025-01-01开始,2025-01-31结束” 的周期被称作 “2025 年 1 月”周期。
-  - 如果一个周期从某年1月1日开始,某年12月31日结束,则它是这一年的年度周期,如 “2025-01-01开始,2025-12-31结束” 的周期就是 “2025 年” 的年度周期
-- `cycle_status` 为周期状态值,参见下文。
+
+-   `id` 是这个周期的 ID,你通常需要用它在之后使用 `okr +cycle-detail` 获取 OKR 内容详情
+-   `start_time` `end_time` 是周期的起止时间,总是从某个月1日开始,直到此月或之后某月的最后一日结束。
+    -   在 OKR 系统中,我们只关注这个时间的年月部分,如 “2025-01-01开始,2025-06-30结束” 的周期被称作 “2025 年 1-6 月” 周期,而 “2025-01-01开始,2025-01-31结束” 的周期被称作 “2025 年 1 月”周期。
+    -   如果一个周期从某年1月1日开始,某年12月31日结束,则它是这一年的年度周期,如 “2025-01-01开始,2025-12-31结束” 的周期就是 “2025 年” 的年度周期
+-   `cycle_status` 为周期状态值,参见下文。
 
 ### 周期状态值
 
-| 值         | 说明       |
-|-----------|----------|
+| 值   | 说明  |
+| --- | --- |
 | `default` | 默认状态 (0) |
-| `normal`  | 生效 (1)   |
-| `invalid` | 失效 (2)   |
-| `hidden`  | 隐藏 (3)   |
+| `normal` | 生效 (1) |
+| `invalid` | 失效 (2) |
+| `hidden` | 隐藏 (3) |
 
 在 OKR 系统中,default/normal 状态下的周期当前正常生效,invalid 状态下的周期已失效但通常仍然可以填写,hidden 状态下的周期隐藏不可见。
 
 ## 参考
 
-- [lark-okr](../SKILL.md) -- 所有 OKR 命令
-- [lark-shared](../../lark-shared/SKILL.md) -- 认证和全局参数
+-   [lark-okr](../SKILL.md) -- 所有 OKR 命令
+-   [lark-shared](../../lark-shared/SKILL.md) -- 认证和全局参数

+ 168 - 163
.agents/skills/lark-okr/references/lark-okr-entities.md

@@ -15,256 +15,261 @@ Alignment (对齐关系): Objective ↔ Objective
 Category (分类): Objective 的分组标签
 ```
 
----
+* * *
 
 ## Owner (所有者)
 
 所有者标识 OKR 实体的归属,目前仅支持用户类型。
 
-| 字段           | 类型       | 必填 | 说明                                            |
-|--------------|----------|----|-----------------------------------------------|
-| `owner_type` | `string` | 是  | 所有者类型,通常为 `"user"`。                           |
-| `user_id`    | `string` | 否  | 员工 ID,类型由请求参数 `user_id_type` 决定(默认 `open_id`) |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `owner_type` | `string` | 是   | 所有者类型,通常为 `"user"`。 |
+| `user_id` | `string` | 否   | 员工 ID,类型由请求参数 `user_id_type` 决定(默认 `open_id`) |
 
----
+* * *
 
 ## Cycle (用户周期)
 
 用户周期是 OKR 的顶层容器,代表一个时间段内的所有目标与关键结果。
 
-| 字段                | 类型        | 必填 | 说明                                         |
-|-------------------|-----------|----|--------------------------------------------|
-| `id`              | `string`  | 是  | 用户周期 ID                                    |
-| `create_time`     | `string`  | 是  | 创建时间                                       |
-| `update_time`     | `string`  | 是  | 更新时间                                       |
-| `tenant_cycle_id` | `string`  | 是  | 租户周期 ID(同一周期在不同用户下有不同的用户周期 ID,但租户周期 ID 相同) |
-| `owner`           | `Owner`   | 是  | 所有者                                        |
-| `start_time`      | `string`  | 是  | 周期开始时间。总是从某月1日开始                           |
-| `end_time`        | `string`  | 是  | 周期结束时间。到某月最后一日结束                           |
-| `cycle_status`    | `integer` | 否  | 周期状态,见下表                                   |
-| `score`           | `number`  | 否  | 周期分数,范围 [0, 1],支持一位小数                      |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 用户周期 ID |
+| `create_time` | `string` | 是   | 创建时间 |
+| `update_time` | `string` | 是   | 更新时间 |
+| `tenant_cycle_id` | `string` | 是   | 租户周期 ID(同一周期在不同用户下有不同的用户周期 ID,但租户周期 ID 相同) |
+| `owner` | `Owner` | 是   | 所有者 |
+| `start_time` | `string` | 是   | 周期开始时间。总是从某月1日开始 |
+| `end_time` | `string` | 是   | 周期结束时间。到某月最后一日结束 |
+| `cycle_status` | `integer` | 否   | 周期状态,见下表 |
+| `score` | `number` | 否   | 周期分数,范围 \[0, 1\],支持一位小数 |
 
 ### 常用术语
 
-- **当前周期**: 指周期的 start_time/end_time 所在的时间段与当前时间重叠的周期。如果有多个符合这一标准的周期,通常可以选择周期状态为default/normal的周期,其中较新的一个。当用户提及“上一个周期”,“下一个周期”一类的表述时,通常是以当前周期为准计算。
-- **所有者**: 绝大多数所有者都是用户,少部分租户启用了“团队OKR”功能,所有者可能是部门。用户身份下,只能编辑所有者为当前用户的
-  OKR。
+-   **当前周期**: 指周期的 start\_time/end\_time 所在的时间段与当前时间重叠的周期。如果有多个符合这一标准的周期,通常可以选择周期状态为default/normal的周期,其中较新的一个。当用户提及“上一个周期”,“下一个周期”一类的表述时,通常是以当前周期为准计算。
+-   **所有者**: 绝大多数所有者都是用户,少部分租户启用了“团队OKR”功能,所有者可能是部门。用户身份下,只能编辑所有者为当前用户的  
+    OKR。
 
-### 周期状态 (cycle_status)
+### 周期状态 (cycle\_status)
 
-| 值 | 常量名       | 说明          |
-|---|-----------|-------------|
-| 0 | `default` | 默认状态        |
-| 1 | `normal`  | 生效中         |
-| 2 | `invalid` | 已失效(通常仍可填写) |
-| 3 | `hidden`  | 已隐藏(不可见)    |
+| 值   | 常量名 | 说明  |
+| --- | --- | --- |
+| 0   | `default` | 默认状态 |
+| 1   | `normal` | 生效中 |
+| 2   | `invalid` | 已失效(通常仍可填写) |
+| 3   | `hidden` | 已隐藏(不可见) |
 
 > **SHORTCUT:** `okr +cycle-list` [lark-okr-cycle-list.md](lark-okr-cycle-list.md) 获取用户的周期列表,可按时间筛选
->
+> 
 > **API:** `cycles.list`
 
----
+* * *
 
 ## Objective (目标)
 
 目标是 OKR 中的 "O",属于某个用户周期,可包含多个关键结果。
 
-| 字段            | 类型             | 必填 | 说明                                                      |
-|---------------|----------------|----|---------------------------------------------------------|
-| `id`          | `string`       | 是  | 目标 ID                                                   |
-| `create_time` | `string`       | 是  | 创建时间,毫秒时间戳,shortcut 会将其解析为日期时间                          |
-| `update_time` | `string`       | 是  | 更新时间,毫秒时间戳,shortcut 会将其解析为日期时间                          |
-| `owner`       | `Owner`        | 是  | 所有者                                                     |
-| `cycle_id`    | `string`       | 是  | 所属用户周期 ID                                               |
-| `position`    | `integer`      | 是  | 排序序号,从 1 开始,范围 [1, 100]                                 |
-| `content`     | `ContentBlock` | 否  | 目标内容(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
-| `score`       | `number`       | 否  | 目标分数,范围 [0, 1],支持一位小数                                   |
-| `notes`       | `ContentBlock` | 否  | 目标备注(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
-| `weight`      | `number`       | 否  | 目标权重,范围 [0, 1],支持三位小数                                   |
-| `deadline`    | `string`       | 否  | 截止时间,毫秒时间戳,shortcut 会将其解析为日期时间                          |
-| `category_id` | `string`       | 否  | 所属分类 ID                                                 |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 目标 ID |
+| `create_time` | `string` | 是   | 创建时间,毫秒时间戳,shortcut 会将其解析为日期时间 |
+| `update_time` | `string` | 是   | 更新时间,毫秒时间戳,shortcut 会将其解析为日期时间 |
+| `owner` | `Owner` | 是   | 所有者 |
+| `cycle_id` | `string` | 是   | 所属用户周期 ID |
+| `position` | `integer` | 是   | 排序序号,从 1 开始,范围 \[1, 100\] |
+| `content` | `ContentBlock` | 否   | 目标内容(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
+| `score` | `number` | 否   | 目标分数,范围 \[0, 1\],支持一位小数 |
+| `notes` | `ContentBlock` | 否   | 目标备注(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
+| `weight` | `number` | 否   | 目标权重,范围 \[0, 1\],支持三位小数 |
+| `deadline` | `string` | 否   | 截止时间,毫秒时间戳,shortcut 会将其解析为日期时间 |
+| `category_id` | `string` | 否   | 所属分类 ID |
 
 > **SHORTCUT:**
-> - `okr +cycle-detail` [lark-okr-cycle-detail.md](lark-okr-cycle-detail.md) 获取某个用户周期下的全部目标和关键结果。时间相关的字段会以日期时间格式解析
->
+> 
+> -   `okr +cycle-detail` [lark-okr-cycle-detail.md](lark-okr-cycle-detail.md) 获取某个用户周期下的全部目标和关键结果。时间相关的字段会以日期时间格式解析
+> 
 > **API:**
-> - `cycle.objectives.list` — 获取周期下的目标列表
-> - `objectives.get` — 获取单个目标
-> - `cycle.objectives.create` — 创建目标
-> - `objectives.delete` — 删除目标
-> - `cycles.objectives_position` — 更新周期下的目标排序
-> - `cycles.objectives_weight` — 更新周期下的目标权重
+> 
+> -   `cycle.objectives.list` — 获取周期下的目标列表
+> -   `objectives.get` — 获取单个目标
+> -   `cycle.objectives.create` — 创建目标
+> -   `objectives.delete` — 删除目标
+> -   `cycles.objectives_position` — 更新周期下的目标排序
+> -   `cycles.objectives_weight` — 更新周期下的目标权重
 
----
+* * *
 
 ## KeyResult (关键结果)
 
 关键结果是 OKR 中的 "KR",属于某个目标,描述目标的可衡量成果。
 
-| 字段             | 类型             | 必填 | 说明                                                        |
-|----------------|----------------|----|-----------------------------------------------------------|
-| `id`           | `string`       | 是  | 关键结果 ID                                                   |
-| `create_time`  | `string`       | 是  | 创建时间,毫秒时间戳                                                |
-| `update_time`  | `string`       | 是  | 修改时间,毫秒时间戳                                                |
-| `owner`        | `Owner`        | 是  | 所有者                                                       |
-| `objective_id` | `string`       | 是  | 所属目标 ID                                                   |
-| `position`     | `integer`      | 是  | 排序序号,从 1 开始,范围 [1, 100]                                   |
-| `content`      | `ContentBlock` | 否  | 关键结果内容(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
-| `score`        | `number`       | 否  | 关键结果分数,范围 [0, 1],支持一位小数                                   |
-| `weight`       | `number`       | 否  | 权重,范围 [0, 1],支持三位小数                                       |
-| `deadline`     | `string`       | 否  | 截止时间,毫秒时间戳                                                |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 关键结果 ID |
+| `create_time` | `string` | 是   | 创建时间,毫秒时间戳 |
+| `update_time` | `string` | 是   | 修改时间,毫秒时间戳 |
+| `owner` | `Owner` | 是   | 所有者 |
+| `objective_id` | `string` | 是   | 所属目标 ID |
+| `position` | `integer` | 是   | 排序序号,从 1 开始,范围 \[1, 100\] |
+| `content` | `ContentBlock` | 否   | 关键结果内容(富文本),见 [ContentBlock 定义](lark-okr-contentblock.md) |
+| `score` | `number` | 否   | 关键结果分数,范围 \[0, 1\],支持一位小数 |
+| `weight` | `number` | 否   | 权重,范围 \[0, 1\],支持三位小数 |
+| `deadline` | `string` | 否   | 截止时间,毫秒时间戳 |
 
 > **API:**
-> - `objective.key_results.list` — 获取目标下的关键结果列表
-> - `key_results.get` — 获取单个关键结果
-> - `key_results.patch` — 更新关键结果
-> - `key_results.delete` — 删除关键结果
-> - `objectives.key_results_position` — 更新目标下的关键结果排序
-> - `objectives.key_results_weight` — 更新目标下的关键结果权重
+> 
+> -   `objective.key_results.list` — 获取目标下的关键结果列表
+> -   `key_results.get` — 获取单个关键结果
+> -   `key_results.patch` — 更新关键结果
+> -   `key_results.delete` — 删除关键结果
+> -   `objectives.key_results_position` — 更新目标下的关键结果排序
+> -   `objectives.key_results_weight` — 更新目标下的关键结果权重
 
----
+* * *
 
 ## Indicator (指标)
 
 指标是目标和关键结果的量化度量,可独立挂载在 Objective 或 KeyResult 上。
 
-| 字段                             | 类型              | 必填 | 说明                                 |
-|--------------------------------|-----------------|----|------------------------------------|
-| `id`                           | `string`        | 是  | 指标 ID                              |
-| `create_time`                  | `string`        | 是  | 创建时间,毫秒时间戳                         |
-| `update_time`                  | `string`        | 是  | 更新时间,毫秒时间戳                         |
-| `owner`                        | `Owner`         | 是  | 所有者                                |
-| `entity_type`                  | `integer`       | 是  | 所属实体类型:`2`=目标,`3`=关键结果             |
-| `entity_id`                    | `string`        | 是  | 所属实体 ID                            |
-| `indicator_status`             | `integer`       | 是  | 指标状态,见下表                           |
-| `status_calculate_type`        | `integer`       | 是  | 状态计算方式,见下表                         |
-| `start_value`                  | `number`        | 否  | 起始值,范围 [-99999999999, 99999999999] |
-| `target_value`                 | `number`        | 否  | 目标值,范围 [-99999999999, 99999999999] |
-| `current_value`                | `number`        | 否  | 当前值,范围 [-99999999999, 99999999999] |
-| `current_value_calculate_type` | `integer`       | 否  | 当前值计算方式,见下表                        |
-| `unit`                         | `IndicatorUnit` | 否  | 指标单位                               |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 指标 ID |
+| `create_time` | `string` | 是   | 创建时间,毫秒时间戳 |
+| `update_time` | `string` | 是   | 更新时间,毫秒时间戳 |
+| `owner` | `Owner` | 是   | 所有者 |
+| `entity_type` | `integer` | 是   | 所属实体类型:`2`\=目标,`3`\=关键结果 |
+| `entity_id` | `string` | 是   | 所属实体 ID |
+| `indicator_status` | `integer` | 是   | 指标状态,见下表 |
+| `status_calculate_type` | `integer` | 是   | 状态计算方式,见下表 |
+| `start_value` | `number` | 否   | 起始值,范围 \[-99999999999, 99999999999\] |
+| `target_value` | `number` | 否   | 目标值,范围 \[-99999999999, 99999999999\] |
+| `current_value` | `number` | 否   | 当前值,范围 \[-99999999999, 99999999999\] |
+| `current_value_calculate_type` | `integer` | 否   | 当前值计算方式,见下表 |
+| `unit` | `IndicatorUnit` | 否   | 指标单位 |
 
 ### 修改指南
 
-- **进度值**: 一般指 `current_value`,单位未提及时通常用百分制计算。
-- 当用户要求量化的更新 OKR 进度时,一般指的就是修改对应 OKR 的 Indicator。
-- OKR 在未设置量化指标时,Indicator 的内容为空。如果用户未做特别说明,更新进度时可以默认将进度以百分制设置(初始值0,目标值100,unit 参见下文设置为 0/PERCENT)
+-   **进度值**: 一般指 `current_value`,单位未提及时通常用百分制计算。
+-   当用户要求量化的更新 OKR 进度时,一般指的就是修改对应 OKR 的 Indicator。
+-   OKR 在未设置量化指标时,Indicator 的内容为空。如果用户未做特别说明,更新进度时可以默认将进度以百分制设置(初始值0,目标值100,unit 参见下文设置为 0/PERCENT)
 
-### 指标状态 (indicator_status)
+### 指标状态 (indicator\_status)
 
-| 值  | 说明  |
-|----|-----|
-| -1 | 未定义 |
-| 0  | 正常  |
-| 1  | 有风险 |
-| 2  | 已延期 |
+| 值   | 说明  |
+| --- | --- |
+| \-1 | 未定义 |
+| 0   | 正常  |
+| 1   | 有风险 |
+| 2   | 已延期 |
 
-### 状态计算方式 (status_calculate_type)
+### 状态计算方式 (status\_calculate\_type)
 
-| 值 | 说明              | 适用范围    |
-|---|-----------------|---------|
-| 0 | 手动更新            | 目标、关键结果 |
-| 1 | 基于进度和当前时间自动更新   | 目标、关键结果 |
-| 2 | 基于风险最高的关键结果状态更新 | 仅目标     |
+| 值   | 说明  | 适用范围 |
+| --- | --- | --- |
+| 0   | 手动更新 | 目标、关键结果 |
+| 1   | 基于进度和当前时间自动更新 | 目标、关键结果 |
+| 2   | 基于风险最高的关键结果状态更新 | 仅目标 |
 
-### 当前值计算方式 (current_value_calculate_type)
+### 当前值计算方式 (current\_value\_calculate\_type)
 
-| 值 | 说明            | 适用范围    |
-|---|---------------|---------|
-| 0 | 手动更新          | 目标、关键结果 |
-| 1 | 基于关键结果进度自动更新  | 仅目标     |
-| 2 | 基于拆解的关键结果进度更新 | 仅关键结果   |
+| 值   | 说明  | 适用范围 |
+| --- | --- | --- |
+| 0   | 手动更新 | 目标、关键结果 |
+| 1   | 基于关键结果进度自动更新 | 仅目标 |
+| 2   | 基于拆解的关键结果进度更新 | 仅关键结果 |
 
 ### IndicatorUnit (指标单位)
 
-| 字段           | 类型        | 必填 | 说明                                                                          |
-|--------------|-----------|----|-----------------------------------------------------------------------------|
-| `unit_type`  | `integer` | 是  | 单位类型:`0`=公共,`1`=自定义                                                         |
-| `unit_value` | `string`  | 是  | 单位值。公共类型可选:`PERCENT`(百分比)、`NONE`(无单位)、`YUAN`(元)、`DOLLAR`(美元);自定义类型字符长度不超过 5 |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `unit_type` | `integer` | 是   | 单位类型:`0`\=公共,`1`\=自定义 |
+| `unit_value` | `string` | 是   | 单位值。公共类型可选:`PERCENT`(百分比)、`NONE`(无单位)、`YUAN`(元)、`DOLLAR`(美元);自定义类型字符长度不超过 5 |
 
 > **API:**
-> - `key_result.indicators.list` — 获取关键结果的指标
-> - `objective.indicators.list` — 获取目标的指标
-> - `indicators.patch` — 更新指标
+> 
+> -   `key_result.indicators.list` — 获取关键结果的指标
+> -   `objective.indicators.list` — 获取目标的指标
+> -   `indicators.patch` — 更新指标
 
----
+* * *
 
 ## Alignment (对齐关系)
 
 对齐关系描述两个目标之间的上下对齐。
 
-| 字段                 | 类型        | 必填 | 说明                    |
-|--------------------|-----------|----|-----------------------|
-| `id`               | `string`  | 是  | 对齐 ID                 |
-| `create_time`      | `string`  | 是  | 创建时间,毫秒时间戳            |
-| `update_time`      | `string`  | 是  | 更新时间,毫秒时间戳            |
-| `from_owner`       | `Owner`   | 是  | 发起对齐的所有者              |
-| `to_owner`         | `Owner`   | 是  | 被对齐的所有者               |
-| `from_entity_type` | `integer` | 是  | 发起对齐的实体类型,固定为 `2`(目标) |
-| `from_entity_id`   | `string`  | 是  | 发起对齐的实体 ID            |
-| `to_entity_type`   | `integer` | 是  | 被对齐的实体类型,固定为 `2`(目标)  |
-| `to_entity_id`     | `string`  | 是  | 被对齐的实体 ID             |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 对齐 ID |
+| `create_time` | `string` | 是   | 创建时间,毫秒时间戳 |
+| `update_time` | `string` | 是   | 更新时间,毫秒时间戳 |
+| `from_owner` | `Owner` | 是   | 发起对齐的所有者 |
+| `to_owner` | `Owner` | 是   | 被对齐的所有者 |
+| `from_entity_type` | `integer` | 是   | 发起对齐的实体类型,固定为 `2`(目标) |
+| `from_entity_id` | `string` | 是   | 发起对齐的实体 ID |
+| `to_entity_type` | `integer` | 是   | 被对齐的实体类型,固定为 `2`(目标) |
+| `to_entity_id` | `string` | 是   | 被对齐的实体 ID |
 
 > **API:**
-> - `alignments.get` — 获取对齐关系
-> - `alignments.delete` — 删除对齐关系
-> - `objective.alignments.list` — 批量获取目标下的对齐关系
-> - `objective.alignments.create` — 创建对齐关系
+> 
+> -   `alignments.get` — 获取对齐关系
+> -   `alignments.delete` — 删除对齐关系
+> -   `objective.alignments.list` — 批量获取目标下的对齐关系
+> -   `objective.alignments.create` — 创建对齐关系
 
----
+* * *
 
 ## Category (分类)
 
 分类用于对目标进行分组标记(如"个人 OKR"、"团队 OKR"、"承诺 OKR")等。具体的分类根据租户设置而定。
 
-| 字段              | 类型             | 必填 | 说明                                                          |
-|-----------------|----------------|----|-------------------------------------------------------------|
-| `id`            | `string`       | 是  | 分类 ID                                                       |
-| `create_time`   | `string`       | 是  | 创建时间,毫秒时间戳                                                  |
-| `update_time`   | `string`       | 是  | 更新时间,毫秒时间戳                                                  |
-| `category_type` | `string`       | 是  | 分类类型:`"person"`=个人,`"team"`=团队                              |
-| `enabled`       | `boolean`      | 是  | 是否启用                                                        |
-| `color`         | `string`       | 是  | 颜色标识:`blue`、`purple`、`wathet`、`turquoise`、`indigo`、`orange` |
-| `name`          | `CategoryName` | 是  | 多语言名称                                                       |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `id` | `string` | 是   | 分类 ID |
+| `create_time` | `string` | 是   | 创建时间,毫秒时间戳 |
+| `update_time` | `string` | 是   | 更新时间,毫秒时间戳 |
+| `category_type` | `string` | 是   | 分类类型:`"person"`\=个人,`"team"`\=团队 |
+| `enabled` | `boolean` | 是   | 是否启用 |
+| `color` | `string` | 是   | 颜色标识:`blue`、`purple`、`wathet`、`turquoise`、`indigo`、`orange` |
+| `name` | `CategoryName` | 是   | 多语言名称 |
 
 ### CategoryName (分类名称)
 
-| 字段   | 类型       | 必填 | 说明  |
-|------|----------|----|-----|
-| `zh` | `string` | 否  | 中文名 |
-| `en` | `string` | 否  | 英文名 |
-| `ja` | `string` | 否  | 日文名 |
+| 字段  | 类型  | 必填  | 说明  |
+| --- | --- | --- | --- |
+| `zh` | `string` | 否   | 中文名 |
+| `en` | `string` | 否   | 英文名 |
+| `ja` | `string` | 否   | 日文名 |
 
 > **API:** `categories.list` — 批量获取租户设置的分类列表
 
----
+* * *
 
 ## 通用请求参数
 
 以下参数在多数 OKR API 中通用:
 
-| 参数                   | 位置      | 必填 | 默认值                    | 说明                                               |
-|----------------------|---------|----|------------------------|--------------------------------------------------|
-| `user_id_type`       | `query` | 否  | `"open_id"`            | 用户 ID 类型:`open_id` \| `union_id` \| `user_id`    |
-| `department_id_type` | `query` | 否  | `"open_department_id"` | 部门 ID 类型:`open_department_id` \| `department_id` |
-| `page_size`          | `query` | 否  | `10`                   | 分页大小,最大 100                                      |
-| `page_token`         | `query` | 否  | `""`                   | 分页键,首页传空串                                        |
+| 参数  | 位置  | 必填  | 默认值 | 说明  |
+| --- | --- | --- | --- | --- |
+| `user_id_type` | `query` | 否   | `"open_id"` | 用户 ID 类型:`open_id` \| `union_id` \| `user_id` |
+| `department_id_type` | `query` | 否   | `"open_department_id"` | 部门 ID 类型:`open_department_id` \| `department_id` |
+| `page_size` | `query` | 否   | `10` | 分页大小,最大 100 |
+| `page_token` | `query` | 否   | `""` | 分页键,首页传空串 |
 
----
+* * *
 
 ## 权限 Scope 说明
 
-| Scope                       | 权限类型 | 说明           |
-|-----------------------------|------|--------------|
-| `okr:okr.content:readonly`  | 读    | 读取 OKR 内容    |
-| `okr:okr.content:writeonly` | 写    | 写入/删除 OKR 内容 |
-| `okr:okr.period:readonly`   | 读    | 读取 OKR 周期    |
-| `okr:okr.setting:read`      | 读    | 读取 OKR 设置    |
+| Scope | 权限类型 | 说明  |
+| --- | --- | --- |
+| `okr:okr.content:readonly` | 读   | 读取 OKR 内容 |
+| `okr:okr.content:writeonly` | 写   | 写入/删除 OKR 内容 |
+| `okr:okr.period:readonly` | 读   | 读取 OKR 周期 |
+| `okr:okr.setting:read` | 读   | 读取 OKR 设置 |
 
 所有 OKR API 均支持 `user` 和 `tenant`(应用)两种 access token 类型。
 
 ## 参考
 
-- [OKR ContentBlock 富文本格式](lark-okr-contentblock.md) — content/notes 字段的富文本结构定义
-- [okr +cycle-list](lark-okr-cycle-list.md) — 列出用户 OKR 周期
-- [okr +cycle-detail](lark-okr-cycle-detail.md) — 获取周期下的目标与关键结果
+-   [OKR ContentBlock 富文本格式](lark-okr-contentblock.md) — content/notes 字段的富文本结构定义
+-   [okr +cycle-list](lark-okr-cycle-list.md) — 列出用户 OKR 周期
+-   [okr +cycle-detail](lark-okr-cycle-detail.md) — 获取周期下的目标与关键结果

+ 18 - 19
.agents/skills/lark-openapi-explorer/SKILL.md

@@ -6,10 +6,9 @@ metadata:
   requires:
     bins: ["lark-cli"]
 ---
-
 # OpenAPI Explorer
 
-> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../lark-shared/SKILL.md) 了解认证、身份切换和安全规则。
+> **前置条件:** 先阅读 `../lark-shared/SKILL.md` 了解认证、身份切换和安全规则。
 
 当用户的需求**无法被现有 skill 或 CLI 已注册 API 覆盖**时,使用本技能从飞书官方 markdown 文档库中逐层挖掘原生 OpenAPI 接口,然后通过 `lark-cli api` 裸调完成任务。
 
@@ -25,8 +24,8 @@ llms.txt                          ← 顶层索引,列出所有模块文档链
 
 文档入口:
 
-| 品牌 | 入口 URL |
-|------|----------|
+| 品牌  | 入口 URL |
+| --- | --- |
 | 飞书 (Feishu) | `https://open.feishu.cn/llms.txt` |
 | Lark | `https://open.larksuite.com/llms.txt` |
 
@@ -54,9 +53,9 @@ WebFetch https://open.feishu.cn/llms.txt
   → 提取问题:"列出所有模块文档链接,找出与 <用户需求关键词> 相关的链接"
 ```
 
-- 飞书品牌使用 `open.feishu.cn`
-- Lark 品牌使用 `open.larksuite.com`
-- 如不确定用户品牌,默认使用飞书
+-   飞书品牌使用 `open.feishu.cn`
+-   Lark 品牌使用 `open.larksuite.com`
+-   如不确定用户品牌,默认使用飞书
 
 ### Step 3:从模块文档定位具体 API
 
@@ -98,21 +97,21 @@ lark-cli api DELETE /open-apis/<path>
 
 向用户呈现挖掘结果时,按以下格式组织:
 
-1. **API 名称与功能**:一句话描述
-2. **HTTP 方法与路径**:`METHOD /open-apis/...`
-3. **关键参数**:列出必填和常用可选参数
-4. **所需权限**:scope 列表
-5. **调用示例**:给出 `lark-cli api` 的完整命令
-6. **注意事项**:频率限制、特殊约束等
+1.  **API 名称与功能**:一句话描述
+2.  **HTTP 方法与路径**:`METHOD /open-apis/...`
+3.  **关键参数**:列出必填和常用可选参数
+4.  **所需权限**:scope 列表
+5.  **调用示例**:给出 `lark-cli api` 的完整命令
+6.  **注意事项**:频率限制、特殊约束等
 
 如果用户使用英文交流,将以上所有内容翻译为英文。
 
 ## 安全规则
 
-- **写入/删除类 API**(POST/PUT/DELETE)调用前必须确认用户意图
-- 建议先用 `--dry-run` 预览请求(如支持)
-- 不要猜测 API 路径或参数——必须从文档中获取确认
-- 涉及敏感操作(删除群、移除成员等)时,向用户说明影响范围
+-   **写入/删除类 API**(POST/PUT/DELETE)调用前必须确认用户意图
+-   建议先用 `--dry-run` 预览请求(如支持)
+-   不要猜测 API 路径或参数——必须从文档中获取确认
+-   涉及敏感操作(删除群、移除成员等)时,向用户说明影响范围
 
 ## 使用场景示例
 
@@ -149,5 +148,5 @@ lark-cli api PATCH /open-apis/im/v1/chats/oc_xxx/announcement \
 
 ## 参考
 
-- [lark-shared](../lark-shared/SKILL.md) — 认证和全局参数
-- [lark-skill-maker](../lark-skill-maker/SKILL.md) — 如需将挖掘到的 API 固化为新 Skill
+-   [lark-shared](../lark-shared/SKILL.md) — 认证和全局参数
+-   [lark-skill-maker](../lark-skill-maker/SKILL.md) — 如需将挖掘到的 API 固化为新 Skill

+ 25 - 26
.agents/skills/lark-shared/SKILL.md

@@ -3,7 +3,6 @@ name: lark-shared
 version: 1.0.0
 description: "飞书/Lark CLI 共享基础:应用配置初始化、认证登录(auth login)、身份切换(--as user/bot)、权限与 scope 管理、Permission denied 错误处理、安全规则。当用户需要第一次配置(`lark-cli config init`)、使用登录授权(`lark-cli auth login`)、遇到权限不足、切换 user/bot 身份、配置 scope、或首次使用 lark-cli 时触发。"
 ---
-
 # lark-cli 共享规则
 
 本技能指导你如何通过lark-cli操作飞书资源, 以及有哪些注意事项。
@@ -25,8 +24,8 @@ lark-cli config init --new
 
 两种身份类型,通过 `--as` 切换:
 
-| 身份 | 标识 | 获取方式 | 适用场景 |
-|------|------|---------|---------|
+| 身份  | 标识  | 获取方式 | 适用场景 |
+| --- | --- | --- | --- |
 | user 用户身份 | `--as user` | `lark-cli auth login` 等 | 访问用户自己的资源(日历、云空间等) |
 | bot 应用身份 | `--as bot` | 自动,只需 appId + appSecret | 应用级操作,访问bot自己的资源 |
 
@@ -34,26 +33,26 @@ lark-cli config init --new
 
 输出的 `[identity: bot/user]` 代表当前身份。bot 与 user 表现差异很大,需确认身份符合目标需求:
 
-- **Bot 看不到用户资源**:无法访问用户的日历、云空间文档、邮箱等个人资源。例如 `--as bot` 查日程返回 bot 自己的(空)日历
-- **Bot 无法代表用户操作**:发消息以应用名义发送,创建文档归属 bot
-- **Bot 权限**:只需在飞书开发者后台开通 scope,无需 `auth login`
-- **User 权限**:后台开通 scope + 用户通过 `auth login` 授权,两层都要满足
-
+-   **Bot 看不到用户资源**:无法访问用户的日历、云空间文档、邮箱等个人资源。例如 `--as bot` 查日程返回 bot 自己的(空)日历
+-   **Bot 无法代表用户操作**:发消息以应用名义发送,创建文档归属 bot
+-   **Bot 权限**:只需在飞书开发者后台开通 scope,无需 `auth login`
+-   **User 权限**:后台开通 scope + 用户通过 `auth login` 授权,两层都要满足
 
 ### 权限不足处理
 
 遇到权限相关错误时,**根据当前身份类型采取不同解决方案**。
 
 错误响应中包含关键信息:
-- `permission_violations`:列出缺失的 scope (N选1)
-- `console_url`:飞书开发者后台的权限配置链接
-- `hint`:建议的修复命令
 
-#### Bot 身份(`--as bot`)
+-   `permission_violations`:列出缺失的 scope (N选1)
+-   `console_url`:飞书开发者后台的权限配置链接
+-   `hint`:建议的修复命令
+
+Bot 身份(`--as bot`)
 
 将错误中的 `console_url` 提供给用户,引导去后台开通 scope。**禁止**对 bot 执行 `auth login`。
 
-#### User 身份(`--as user`)
+User 身份(`--as user`)
 
 ```bash
 lark-cli auth login --domain <domain>           # 按业务域授权
@@ -62,34 +61,34 @@ lark-cli auth login --scope "<missing_scope>"   # 按具体 scope 授权(推
 
 **规则**:auth login 必须指定范围(`--domain` 或 `--scope`)。多次 login 的 scope 会累积(增量授权)。
 
-#### Agent 代理发起认证(推荐)
+Agent 代理发起认证(推荐)
 
 当你作为 AI agent 需要帮用户完成认证时,使用background方式 执行以下命令发起授权流程, 并将授权链接发给用户:
 
 ```bash
 # 发起授权(阻塞直到用户授权完成或过期)
 lark-cli auth login --scope "calendar:calendar:readonly"
-
 ```
 
-
 ## 更新检查
 
 lark-cli 命令执行后,如果检测到新版本,JSON 输出中会包含 `_notice.update` 字段(含 `message`、`command` 等)。
 
-**当你在输出中看到 `_notice.update` 时,完成用户当前请求后,主动提议帮用户更新**:
+**当你在输出中看到** `_notice.update` **时,完成用户当前请求后,主动提议帮用户更新**:
 
-1. 告知用户当前版本和最新版本号
-2. 提议执行更新(CLI 和 Skills 需要同时更新):
-   ```bash
-   npm update -g @larksuite/cli && npx skills add larksuite/cli -g -y
-   ```
-3. 更新完成后提醒用户:**退出并重新打开 AI Agent**以加载最新 Skills
+1.  告知用户当前版本和最新版本号
+2.  提议执行更新(CLI 和 Skills 需要同时更新):
+    
+    ```bash
+    npm update -g @larksuite/cli && npx skills add larksuite/cli -g -y
+    ```
+    
+3.  更新完成后提醒用户:**退出并重新打开 AI Agent**以加载最新 Skills
 
 **规则**:不要静默忽略更新提示。即使当前任务与更新无关,也应在完成用户请求后补充告知。
 
 ## 安全规则
 
-- **禁止输出密钥**(appSecret、accessToken)到终端明文。
-- **写入/删除操作前必须确认用户意图**。
-- 用 `--dry-run` 预览危险请求。
+-   **禁止输出密钥**(appSecret、accessToken)到终端明文。
+-   **写入/删除操作前必须确认用户意图**。
+-   用 `--dry-run` 预览危险请求。

+ 20 - 19
.claude/skills/prd-writer/SKILL.md

@@ -2,41 +2,41 @@
 name: prd-writer
 description: PRD产品需求文档撰写专家。当用户提到"写PRD"、"撰写需求"、"产品需求"、"需求背景"、"功能设计"、"撰写产品需求文档"时,必须使用此skill。按照标准PRD模板(五段式:需求背景→需求目标→流程图→功能清单→系统改造)输出专业文档。支持Mermaid流程图、数据字典、验收标准和测试用例。
 ---
-
 # PRD 产品需求文档撰写专家
 
 ## 工作原则
 
-1. **强制使用模板**:严格按照五段式结构输出(需求背景→需求目标→流程图→功能清单→系统改造),不得省略章节
-2. **模板文件**:`reference/prd-template.md`,撰写 PRD 时必须按此模板要求编写
-3. **Mermaid 强制**:所有业务流程必须使用 Mermaid 语法绘制,尤其是条件分支
-4. **结构化输出**:功能清单和系统改造必须按表格和分级标题格式输出
-5. **MECE 测试用例**:语言精简严谨,逻辑完整,不遗漏、不重复
-6. **新建文件输出**:用户要求"重写"或"新建"时,保存到新的 md 文件,不得覆盖原文件
+1.  **强制使用模板**:严格按照五段式结构输出(需求背景→需求目标→流程图→功能清单→系统改造),不得省略章节
+2.  **模板文件**:`reference/prd-template.md`,撰写 PRD 时必须按此模板要求编写
+3.  **Mermaid 强制**:所有业务流程必须使用 Mermaid 语法绘制,尤其是条件分支
+4.  **结构化输出**:功能清单和系统改造必须按表格和分级标题格式输出
+5.  **MECE 测试用例**:语言精简严谨,逻辑完整,不遗漏、不重复
+6.  **新建文件输出**:用户要求"重写"或"新建"时,保存到新的 md 文件,不得覆盖原文件
 
----
+* * *
 
 ## 输出规范
 
-1. **禁止模糊表述**:不得出现"可能"、"大概"、"优化体验"等词
-2. **数据流向闭环**:每个操作有明确的输入和输出
-3. **Mermaid 强制性**:涉及条件分支必须用 Mermaid 流程图
-4. **测试用例 MECE**:覆盖正向路径、反向路径、边界条件,不遗漏不重复
+1.  **禁止模糊表述**:不得出现"可能"、"大概"、"优化体验"等词
+2.  **数据流向闭环**:每个操作有明确的输入和输出
+3.  **Mermaid 强制性**:涉及条件分支必须用 Mermaid 流程图
+4.  **测试用例 MECE**:覆盖正向路径、反向路径、边界条件,不遗漏不重复
 
----
+* * *
 
 ## 禁止操作
 
-1. **绝对不可以不按模板规范写 PRD**:必须严格遵循 `reference/prd-template.md` 中的模板结构
-2. **不可以在没有完全理解需求分析结果时直接写 PRD**:如需求背景、需求目标、需求描述不清晰,必须主动询问用户确认
-3. **不接受口头需求**:PRD 撰写必须基于需求分析文档(.md 文件),不接受口头描述、聊天记录、截图等非文档形式的需求
-4. **不接受靠猜的需求**:所有需求细节必须有文档依据,不得自行猜测或假设;未在文档中明确的内容必须标注"待确认"并询问用户
+1.  **绝对不可以不按模板规范写 PRD**:必须严格遵循 `reference/prd-template.md` 中的模板结构
+2.  **不可以在没有完全理解需求分析结果时直接写 PRD**:如需求背景、需求目标、需求描述不清晰,必须主动询问用户确认
+3.  **不接受口头需求**:PRD 撰写必须基于需求分析文档(.md 文件),不接受口头描述、聊天记录、截图等非文档形式的需求
+4.  **不接受靠猜的需求**:所有需求细节必须有文档依据,不得自行猜测或假设;未在文档中明确的内容必须标注"待确认"并询问用户
 
----
+* * *
 
 ## 使用示例
 
 **触发场景 1:用户提供需求分析文档撰写 PRD(唯一接受的方式)**
+
 ```
 用户:根据这个需求分析文档帮我写PRD
 → 调用 prd-writer skill
@@ -47,9 +47,10 @@ description: PRD产品需求文档撰写专家。当用户提到"写PRD"、"撰
 ```
 
 **触发场景 2:用户要求完善或扩展已有 PRD**
+
 ```
 用户:帮我在这个PRD里补充测试用例和验收标准
 → 调用 prd-writer skill
 → 读取现有 PRD 文件,确认需求理解完整
 → 按 reference/prd-template.md 模板补充相应章节
-```
+```

+ 1 - 18
.claude/skills/requirements-analysis/SKILL.md

@@ -7,41 +7,28 @@ description: 需求分析 Skill - 在 PRD 撰写前进行需求调研、分析
 ## 工作原则
 
 1.  **强制使用模板**:严格按照五段式结构输出(需求背景→目标确认→流程分析→功能拆解→待确认事项),不得省略章节
-    
 2.  **模板文件**:`reference/analysis-template.md`(需求分析模板),进行分析时必须按此模板要求编写
-    
 3.  **系统现状文件**:`reference/system-status.md`,拆解功能清单时必须参考此文件,了解现有系统功能和模块划分
-    
 4.  **干系人确认**:必须与相关干系人/用户确认需求,不得基于猜测撰写
-    
 5.  **Mermaid 强制**:业务流程必须使用 Mermaid 语法绘制,包含现状流程和目标流程
-    
 6.  **结构化输出**:功能拆解清单必须按表格格式输出,明确优先级
-    
 7.  **识别待确认项**:主动识别需求中尚未确认的事项,并记录在"待确认事项"章节
-    
 
 * * *
 
 ## 输出规范
 
 1.  **禁止模糊表述**:不得出现"可能"、"大概"、"待定"等未确认的描述
-    
 2.  **数据流向闭环**:每个流程节点有明确的输入和输出
-    
 3.  **Mermaid 强制性**:涉及条件分支必须用 Mermaid 流程图
-    
 4.  **优先级明确**:所有功能必须标注优先级(P0/P1/P2)
-    
 
 * * *
 
 ## 禁止操作
 
 1.  **不可在需求不清晰时跳过**:如需求背景、目标不清晰,必须主动询问用户确认
-    
 2.  **不可编造未确认的需求细节**:所有未与干系人确认的内容必须标注"待确认",不得自行假设
-    
 
 * * *
 
@@ -101,8 +88,4 @@ description: 需求分析 Skill - 在 PRD 撰写前进行需求调研、分析
 **关键约束**:
 
 -   requirements-analysis 完成后,prd-writer 才能基于分析结果撰写 PRD
-    
--   如果 requirements-analysis 发现需求不清晰,必须先与用户确认,不得直接跳到 PRD 撰写
-    
-
-<br>
+-   如果 requirements-analysis 发现需求不清晰,必须先与用户确认,不得直接跳到 PRD 撰写

+ 30 - 2
工作空间/产研/权益/汇丰全行/产品原型/pc-demo/src/views/PageAssembly.vue

@@ -276,6 +276,7 @@
                       <el-radio-group v-model="btn.linkType" @change="handleButtonJumpTypeChange(btn)">
                         <el-radio label="h5">H5链接跳转</el-radio>
                         <el-radio label="miniProgram">小程序跳转</el-radio>
+                        <el-radio label="app">App跳转</el-radio>
                         <el-radio label="taikoo">太古地产</el-radio>
                         <el-radio label="dragon">龙腾</el-radio>
                       </el-radio-group>
@@ -298,6 +299,10 @@
                         </el-form-item>
                       </el-col>
                     </el-row>
+                    <el-form-item v-if="btn.linkType === 'app'">
+                      <template #label>pageId <span class="required-star">*</span></template>
+                      <el-input v-model="btn.appPageId" size="small" placeholder="例如:moneyPulling" @input="handleButtonJumpFieldChange(btn)" />
+                    </el-form-item>
                   </div>
                   <!-- 弹窗配置 -->
                   <div v-if="btn.actionType === 'dialog' && btn.dialog" class="dialog-config">
@@ -336,6 +341,7 @@
                         <el-radio-group v-model="btn.dialog.confirmLinkType" @change="handleDialogJumpTypeChange(btn.dialog)">
                           <el-radio label="h5">H5链接跳转</el-radio>
                           <el-radio label="miniProgram">小程序跳转</el-radio>
+                          <el-radio label="app">App跳转</el-radio>
                           <el-radio label="taikoo">太古地产</el-radio>
                           <el-radio label="dragon">龙腾</el-radio>
                         </el-radio-group>
@@ -358,6 +364,10 @@
                           </el-form-item>
                         </el-col>
                       </el-row>
+                      <el-form-item v-if="btn.dialog.confirmLinkType === 'app'">
+                        <template #label>pageId <span class="required-star">*</span></template>
+                        <el-input v-model="btn.dialog.confirmAppPageId" size="small" placeholder="例如:moneyPulling" @input="handleDialogJumpFieldChange(btn.dialog)" />
+                      </el-form-item>
                     </div>
                   </div>
                 </el-form>
@@ -538,6 +548,7 @@ export default {
         linkH5: '',
         miniAppId: '',
         miniAppPath: '',
+        appPageId: '',
         ...overrides
       }
     },
@@ -548,6 +559,7 @@ export default {
         confirmLinkH5: '',
         confirmMiniAppId: '',
         confirmMiniAppPath: '',
+        confirmAppPageId: '',
         ...overrides
       }
     },
@@ -632,6 +644,7 @@ export default {
     },
     inferButtonJumpType(btn = {}) {
       if (btn.linkType) return this.normalizePartnerJumpType(btn.linkType, btn.fixedLink || btn.link)
+      if (btn.appPageId || btn.linkApp) return 'app'
       if (btn.miniAppId || btn.miniAppPath) return 'miniProgram'
       if (btn.link === '太古地产') return 'taikoo'
       if (btn.link === '龙腾') return 'dragon'
@@ -639,6 +652,7 @@ export default {
     },
     inferDialogJumpType(dialog = {}) {
       if (dialog.confirmLinkType) return this.normalizePartnerJumpType(dialog.confirmLinkType, dialog.confirmFixedLink || dialog.confirmLink)
+      if (dialog.confirmAppPageId || dialog.confirmLinkApp) return 'app'
       if (dialog.confirmMiniAppId || dialog.confirmMiniAppPath) return 'miniProgram'
       if (dialog.confirmLink === '太古地产') return 'taikoo'
       if (dialog.confirmLink === '龙腾') return 'dragon'
@@ -650,12 +664,14 @@ export default {
       if (partnerLink) btn.link = partnerLink
       if (btn.linkType === 'h5') btn.link = btn.linkH5 || ''
       if (btn.linkType === 'miniProgram') btn.link = ''
+      if (btn.linkType === 'app') btn.link = btn.appPageId || ''
     },
     syncDialogLegacyLink(dialog) {
       const partnerLink = this.getPartnerFixedLink(dialog.confirmLinkType)
       if (partnerLink) dialog.confirmLink = partnerLink
       if (dialog.confirmLinkType === 'h5') dialog.confirmLink = dialog.confirmLinkH5 || ''
       if (dialog.confirmLinkType === 'miniProgram') dialog.confirmLink = ''
+      if (dialog.confirmLinkType === 'app') dialog.confirmLink = dialog.confirmAppPageId || ''
     },
     clearInactiveButtonJumpFields(btn) {
       btn.fixedLink = this.getPartnerFixedLink(btn.linkType)
@@ -664,6 +680,7 @@ export default {
         btn.miniAppId = ''
         btn.miniAppPath = ''
       }
+      if (btn.linkType !== 'app') btn.appPageId = ''
       this.syncButtonLegacyLink(btn)
     },
     clearInactiveDialogJumpFields(dialog) {
@@ -673,6 +690,7 @@ export default {
         dialog.confirmMiniAppId = ''
         dialog.confirmMiniAppPath = ''
       }
+      if (dialog.confirmLinkType !== 'app') dialog.confirmAppPageId = ''
       this.syncDialogLegacyLink(dialog)
     },
     normalizeButtonJumpConfig(btn) {
@@ -684,7 +702,8 @@ export default {
         fixedLink: btn.fixedLink || (this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
         linkH5: btn.linkH5 || (!this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
         miniAppId: btn.miniAppId || '',
-        miniAppPath: btn.miniAppPath || ''
+        miniAppPath: btn.miniAppPath || '',
+        appPageId: btn.appPageId || btn.linkApp || (linkType === 'app' ? legacyLink : '')
       })
       Object.keys(normalized).forEach(key => {
         btn[key] = normalized[key]
@@ -700,7 +719,8 @@ export default {
         confirmFixedLink: dialog.confirmFixedLink || (this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
         confirmLinkH5: dialog.confirmLinkH5 || (!this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
         confirmMiniAppId: dialog.confirmMiniAppId || '',
-        confirmMiniAppPath: dialog.confirmMiniAppPath || ''
+        confirmMiniAppPath: dialog.confirmMiniAppPath || '',
+        confirmAppPageId: dialog.confirmAppPageId || dialog.confirmLinkApp || (confirmLinkType === 'app' ? legacyLink : '')
       })
       Object.keys(normalized).forEach(key => {
         dialog[key] = normalized[key]
@@ -919,6 +939,7 @@ export default {
       if (btn.linkType === 'miniProgram') {
         return !!(btn.miniAppId || '').trim() && !!(btn.miniAppPath || '').trim()
       }
+      if (btn.linkType === 'app') return !!(btn.appPageId || '').trim()
       return false
     },
     getButtonJumpConfigError(btn) {
@@ -931,6 +952,9 @@ export default {
         if (this.isBlank(btn.miniAppPath)) return '页面路径未填写'
         return ''
       }
+      if (btn.linkType === 'app') {
+        return this.isBlank(btn.appPageId) ? 'pageId未填写' : ''
+      }
       return '跳转方式未选择'
     },
     isRichTextEmpty(value) {
@@ -950,6 +974,9 @@ export default {
         if (this.isBlank(dialog.confirmMiniAppPath)) return '页面路径未填写'
         return ''
       }
+      if (dialog.confirmLinkType === 'app') {
+        return this.isBlank(dialog.confirmAppPageId) ? 'pageId未填写' : ''
+      }
       return '跳转方式未选择'
     },
     getDialogConfigError(dialog) {
@@ -1020,6 +1047,7 @@ export default {
       if (dialog.confirmLinkType === 'miniProgram') {
         return !!(dialog.confirmMiniAppId || '').trim() && !!(dialog.confirmMiniAppPath || '').trim()
       }
+      if (dialog.confirmLinkType === 'app') return !!(dialog.confirmAppPageId || '').trim()
       return false
     },
     removeButton(bIdx, btnIdx) {

+ 19 - 2
工作空间/产研/权益/汇丰全行/产品原型/pc-demo/src/views/PageZoneConfig.vue

@@ -194,6 +194,7 @@
                 <el-radio-group v-model="item.jumpType" @change="handleZoneJumpTypeChange(item)">
                   <el-radio label="h5">H5链接跳转</el-radio>
                   <el-radio label="miniProgram">小程序跳转</el-radio>
+                  <el-radio label="app">App跳转</el-radio>
                   <el-radio label="taikoo">太古地产</el-radio>
                   <el-radio label="dragon">龙腾</el-radio>
                 </el-radio-group>
@@ -216,6 +217,10 @@
                   </el-form-item>
                 </el-col>
               </el-row>
+              <el-form-item v-if="item.jumpType === 'app'">
+                <template #label>pageId <span class="required-star">*</span></template>
+                <el-input v-model="item.appPageId" placeholder="例如:moneyPulling" @input="markModified" />
+              </el-form-item>
             </el-form>
           </div>
         </div>
@@ -466,6 +471,7 @@ export default {
         fixedLink: '',
         linkH5: '',
         linkApp: '',
+        appPageId: '',
         wechatAppId: '',
         wechatPath: '',
         ...overrides
@@ -483,6 +489,7 @@ export default {
     },
     inferJumpType(item = {}) {
       if (item.jumpType) return this.normalizePartnerJumpType(item.jumpType, item.fixedLink)
+      if (item.appPageId || item.linkApp) return 'app'
       if (item.wechatAppId || item.wechatPath) return 'miniProgram'
       if (item.linkH5) return 'h5'
       if (item.fixedLink === '太古地产') return 'taikoo'
@@ -492,7 +499,8 @@ export default {
     normalizeJumpConfig(item) {
       const normalized = this.createDefaultJumpConfig({
         ...item,
-        jumpType: this.inferJumpType(item)
+        jumpType: this.inferJumpType(item),
+        appPageId: item.appPageId || item.linkApp || ''
       })
       Object.keys(normalized).forEach(key => {
         item[key] = normalized[key]
@@ -510,7 +518,12 @@ export default {
         item.wechatAppId = ''
         item.wechatPath = ''
       }
-      item.linkApp = ''
+      if (item.jumpType !== 'app') {
+        item.appPageId = ''
+        item.linkApp = ''
+      } else {
+        item.linkApp = item.appPageId || ''
+      }
     },
     handleZoneJumpTypeChange(item) {
       this.clearInactiveJumpFields(item)
@@ -522,6 +535,7 @@ export default {
       if (item.jumpType === 'miniProgram') {
         return !!(item.wechatAppId || '').trim() && !!(item.wechatPath || '').trim()
       }
+      if (item.jumpType === 'app') return !!(item.appPageId || '').trim()
       return false
     },
     isRichTextEmpty(value) {
@@ -555,6 +569,9 @@ export default {
         if (this.isBlank(item.wechatPath)) return '页面路径未填写'
         return ''
       }
+      if (item.jumpType === 'app') {
+        return this.isBlank(item.appPageId) ? 'pageId未填写' : ''
+      }
       return '跳转方式未选择'
     },
     validateIdentityModule() {