@lark-apaas/coding-steering 0.1.18-dev.1f9a8c4 → 0.1.18-dev.21ea0ba
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -21
- package/package.json +1 -1
- package/steering/design-html/skills/animated-video/SKILL.md +6 -4
- package/steering/design-html/skills/charts/SKILL.md +53 -10
- package/steering/design-html/skills/{data-report → data-viz}/SKILL.md +69 -11
- package/steering/design-html/skills/frontend-design/SKILL.md +36 -34
- package/steering/design-html/skills/hi-fi-design/SKILL.md +4 -2
- package/steering/design-html/skills/interactive-prototype/SKILL.md +39 -4
- package/steering/design-html/skills/mini-game/SKILL.md +71 -0
- package/steering/design-html/skills/mini-game/references/three-js.md +54 -0
- package/steering/design-html/skills/pptx-style-extract/SKILL.md +112 -0
- package/steering/design-html/skills/pptx-style-extract/font-fallback.yaml +129 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/census.py +955 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/check_v2.py +907 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/draft.py +945 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/export_consumer_md.py +75 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/export_consumer_zip.py +175 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/extract.py +765 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/ooxml.py +699 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/package.py +1120 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/parts.py +461 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/query.py +562 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/render_pages.py +679 -0
- package/steering/design-html/skills/pptx-style-extract/scripts/verify_font.py +68 -0
- package/steering/design-html/skills/pptx-style-extract/v2-format-spec.md +193 -0
- package/steering/design-html/skills/preflight/SKILL.md +51 -0
- package/steering/design-html/skills/preflight/scripts/probe.sh +108 -0
- package/steering/design-html/skills/{make-a-deck → slide-deck}/SKILL.md +52 -19
- package/steering/design-html/skills/{visual-exposure → visual-report}/SKILL.md +30 -6
- package/steering/design-html/skills/wireframe/SKILL.md +7 -5
- package/steering/nestjs-react-fullstack/skills_common/trigger-guide/SKILL.md +180 -0
- package/steering/nestjs-react-fullstack/{skills/trigger-guide/SKILL.md → skills_common/trigger-guide/references/trigger-lifecycle.md} +11 -162
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: visual-
|
|
2
|
+
name: visual-report
|
|
3
3
|
description: 用于制作可视化报告、专题视觉页、信息图、视觉长图、概念可视化、产品能力曝光、方案亮点展示等内容型 HTML 视觉作品。适合用户想把材料、数据或观点组织成可阅读、可展示、可传播的视觉化表达,但不希望做成 PPT、传统 dashboard 或纯 ECharts 图表的场景。触发词:可视化报告, 视觉报告, 可视化曝光, 视觉化曝光, 信息图, 长图, infographic, 视觉表达, 概念可视化, 亮点展示, 能力曝光
|
|
4
|
-
|
|
5
|
-
-
|
|
4
|
+
metadata:
|
|
5
|
+
display-names:
|
|
6
|
+
zh-CN: 可视化报告
|
|
7
|
+
en-US: Visual Report
|
|
6
8
|
---
|
|
7
9
|
|
|
8
10
|
# 可视化报告与专题表达
|
|
@@ -17,7 +19,7 @@ available-agents:
|
|
|
17
19
|
4. 按材料逻辑组织内容,而不是套固定目录、固定模块或固定视觉模板。参考样式只能启发表达方式,不能替代对当前材料的判断。
|
|
18
20
|
5. 把材料拆成具体阅读任务:这一段要让读者完成什么判断、理解什么关系、记住什么事实、比较什么差异、追踪什么过程、相信什么证据。不要把这些任务名直接变成目录或模块标题。
|
|
19
21
|
6. 为每个阅读任务现场生成合适的组件、视觉和布局:先说明这段内容需要什么表达方式,再落成具体 UI / 图形 / 排版 / 图表 / 截图 / 文字组合。可以创造新的结构和视觉隐喻,不受现有组件名限制;避免所有章节共享同一套组件组合。
|
|
20
|
-
7. 先写风格 brief
|
|
22
|
+
7. 先写风格 brief:主题隐喻、受众姿态、材料语言、配色逻辑和签名元素。财务报告可以像正式报告册,员工调研可以像组织研究档案,产品上市总结可以像品牌战报;这些只是启发,必须从用户材料里推导。
|
|
21
23
|
8. 建立版式系统:画幅、栅格、字号层级、颜色、图标/线条语言、强调方式和章节节奏。版式系统必须说明不同章节如何变化,而不是所有章节都用同一种上下结构。
|
|
22
24
|
9. 产出单个 HTML 文档。用户需求明确时直接做;只有主题、素材或交付形态完全无法判断时,才问少量必要问题。
|
|
23
25
|
|
|
@@ -43,6 +45,23 @@ available-agents:
|
|
|
43
45
|
|
|
44
46
|
不要为了“丰富”而乱放装饰。变化应该来自内容关系和阅读任务,而不是从组件清单里凑满页面。
|
|
45
47
|
|
|
48
|
+
## 移动端适配
|
|
49
|
+
|
|
50
|
+
可视化报告的产物(长页报告、专题页、信息图)经常在手机上被打开和转发。桌面端的多列版式、满版图文和精细间距到了 390px 宽度上会挤碎。写完桌面布局后,必须为窄屏补充响应式处理:
|
|
51
|
+
|
|
52
|
+
**页面基础**:HTML 必须包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`。
|
|
53
|
+
|
|
54
|
+
**版式折叠**:
|
|
55
|
+
|
|
56
|
+
- **多列章节**(并排图文、对比矩阵、左右证据栏):移动端折叠为单列堆叠。用 `auto-fit + minmax(320px, 1fr)` 自动折叠,或 `@media (max-width: 768px)` 显式切换。
|
|
57
|
+
- **满版主视觉 / 封面**:桌面端的固定高度大图在移动端改为 `aspect-ratio` 或 `min-height` + `max-height` 约束,避免图片撑满整屏看不到内容。
|
|
58
|
+
- **数字/指标区**:横排的 KPI 或关键数字在移动端折叠为 2 列或纵向排列,每个数字块至少 160px 宽。
|
|
59
|
+
- **图表**:图表容器的窄屏处理由 charts skill 的「窄屏适配」规则覆盖。
|
|
60
|
+
- **宽表格 / 时间线 / 矩阵**:加 `overflow-x: auto` 容器让内容可横向滚动,不要压缩到不可读。
|
|
61
|
+
- **大字标题**:桌面端 48px+ 的展示字体在移动端用 `clamp()` 或 `@media` 缩到合理范围(如 `clamp(24px, 6vw, 48px)`),避免单词撑出视口。
|
|
62
|
+
|
|
63
|
+
**字号底线**:移动端正文不低于 14px,标注 / 图注不低于 12px。
|
|
64
|
+
|
|
46
65
|
## 视觉原则
|
|
47
66
|
|
|
48
67
|
- 优先清楚,其次好看。读者应该先理解结构,再感受到风格。
|
|
@@ -50,8 +69,9 @@ available-agents:
|
|
|
50
69
|
- 默认平面化处理:内容区优先使用细边框、分隔线、浅底色、色块、表格斑马纹、编号和标签建立层级;不要给章节、卡片、图表容器加各种 `box-shadow`。
|
|
51
70
|
- 少用装饰性渐变、发光、玻璃拟态。视觉效果要帮助分组、强调或引导视线。
|
|
52
71
|
- 风格跟随内容、受众和品牌:可以正式、温和、技术、编辑化、品牌化或实验感,但不要从某个样例场景继承固定颜色、固定目录或固定组件。
|
|
53
|
-
-
|
|
72
|
+
- 每份报告应有一个可解释的签名元素。签名元素要从用户主题、材料质感和阅读任务中生成,而不是复用固定手法;它可以是任何能组织内容、建立记忆点并保持一致性的视觉规则。
|
|
54
73
|
- 真实素材优先:用户给的截图、logo、图片、图标、数据片段要优先使用。没有素材时,用清楚的占位结构和可替换文案。
|
|
74
|
+
- 数据忠实度:页面中展示的每个数值必须可溯源到用户提供的数据或可验证的计算过程。源数据不含的派生指标(同比/环比、完成率等缺少基准数据的)不编造——用"—"占位或省略。确需补充示例数据时,必须用视觉标记(虚线边框、"示例数据"标签、灰色斜体)明确区分。
|
|
55
75
|
- 允许少量动效,但只用于进入、强调或引导阅读,不做干扰理解的持续动画。
|
|
56
76
|
- 可以包含数字、图表和表格,但它们服务于报告叙事;不要为了“可视化”而把所有内容都做成图。
|
|
57
77
|
- 深色区域可以用于封面、结论、行动区或整篇报告的主视觉;只要它服务主题气质和阅读体验,而不是作为无依据的装饰。
|
|
@@ -75,4 +95,8 @@ available-agents:
|
|
|
75
95
|
- 文字密度可读,没有小字堆叠。
|
|
76
96
|
- 图标、线条、颜色和卡片样式属于同一套视觉语言。
|
|
77
97
|
- 明暗选择能解释为什么适合这个主题;无论浅色还是暗色,都保证长文、图表和表格可读。
|
|
78
|
-
- 事实性内容没有编造;不确定内容用中性描述或占位说明。
|
|
98
|
+
- 事实性内容没有编造;不确定内容用中性描述或占位说明。
|
|
99
|
+
- 页面中每个数值可溯源到用户提供的数据;缺少基准数据的派生指标(同比/环比/完成率等)没有编造数值,而是用"—"占位或省略。
|
|
100
|
+
- HTML 包含 `<meta name="viewport" content="width=device-width, initial-scale=1">`。
|
|
101
|
+
- 多列版式在 390px 视口下折叠为单列且无横向滚动;宽表格 / 矩阵有 `overflow-x: auto` 包裹。
|
|
102
|
+
- 移动端字号达到底线(正文 ≥14px、图注 ≥12px),大标题没有撑出视口。
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wireframe
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
-
|
|
3
|
+
description: 用线框图和故事板探索多种想法。触发词:wireframe, storyboard, 线框图, 故事板, 分镜, 草图, 低保真, 方案探索, 设计探索
|
|
4
|
+
metadata:
|
|
5
|
+
display-names:
|
|
6
|
+
zh-CN: 线框图
|
|
7
|
+
en-US: Wireframe
|
|
6
8
|
---
|
|
7
9
|
|
|
8
|
-
#
|
|
10
|
+
# 线框图
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
帮助用户快速探索设计想法。先访谈用户,再生成多个粗略的线框图,在锁定方向之前把设计空间勾勒出来。优先追求广度而非精细打磨:每个想法给出 3-5 种明显不同的方案。用简单的形状、占位文字和极少的颜色,把焦点留在结构和流程上。整体保持手绘草图的感觉——手写风格但清晰可读的字体;以黑白为主、点缀少量颜色;低保真、简洁。提供简单的微调控件(Tweaks);选项占地小就并排展示,占地大就用 tab 控件切换。
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trigger-guide
|
|
3
|
+
description: 自动化任务触发器代码开发指南,支持 cron 定时触发器、record_change 数据变更触发器和 webhook 触发器,包含 @Automation/@BindTrigger 装饰器用法、handler 入参解析和 Crontab 表达式规范。Use when 需要:(1) 为已创建的自动化任务/定时任务编写业务 handler,(2) 编写 automation 代码绑定触发器,或其他自动化任务相关开发
|
|
4
|
+
steering: true
|
|
5
|
+
steering-topic: trigger_guide
|
|
6
|
+
match-template-name: nestjs-react-fullstack
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 自动化任务配置与代码编写指引
|
|
10
|
+
|
|
11
|
+
### 自动化任务配置
|
|
12
|
+
|
|
13
|
+
1. 新建自动化任务触发器时无需 enable(激活),将任务创建好然后开发完代码即可。触发器随后交由用户主动操作、要求开始。
|
|
14
|
+
|
|
15
|
+
### 目录结构
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
server
|
|
19
|
+
└── modules
|
|
20
|
+
└── xxx
|
|
21
|
+
├── xxx.automation.ts
|
|
22
|
+
├── xxx.module.ts // 必须在 module 中注册自动化任务类,并且在 app.module.ts 中引用并注册该 module,否则代码将不会生效。
|
|
23
|
+
└── 其他文件(如有的话)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
文件命名规则:{模块名}.automation.ts
|
|
27
|
+
|
|
28
|
+
注意:
|
|
29
|
+
|
|
30
|
+
1. 每个模块只应该有一个存放自动化任务逻辑的文件,业务逻辑需要聚合到该文件中。
|
|
31
|
+
2. 如果该模块只有对应的自动化任务,无需编写 Controller
|
|
32
|
+
|
|
33
|
+
### 触发器类型
|
|
34
|
+
|
|
35
|
+
触发器类型(`triggerType`)有三种:
|
|
36
|
+
|
|
37
|
+
- `record_change`:记录变更触发器,**有入参**
|
|
38
|
+
- `cron`:定时触发器,**无入参**
|
|
39
|
+
- `webhook`:Webhook 触发器,**有入参**
|
|
40
|
+
|
|
41
|
+
各触发器 handler 的入参类型定义(`TaskHandlerArgs`、`DataChangeEventInput`、`WebhookEvent`)见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
42
|
+
|
|
43
|
+
### 指定值限制
|
|
44
|
+
|
|
45
|
+
1. Webhook 触发器不可以设置指定值,并且告知用户。
|
|
46
|
+
|
|
47
|
+
### 代码绑定
|
|
48
|
+
|
|
49
|
+
你需要根据触发器创建后确定的自动化任务名字(应用内唯一),编写并绑定到对应的方法上:`@BindTrigger('<任务名字>')` 中的名字必须与创建触发器时确定的名字逐字相同,不能用 trigger ID 或方法名代替。`@Automation()` 标记的类需注册为对应 `<module>.module.ts` 的 provider,且该 module 必须被 `server/app.module.ts` 直接或传递 import,否则装饰器不会生效。完整代码示例见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
50
|
+
|
|
51
|
+
### 任务代码实现约束
|
|
52
|
+
|
|
53
|
+
1. 执行自动化任务时无法获取用户信息。依赖用户信息的场景,实现路径如下:
|
|
54
|
+
- 需要查询数据库中的特定数据,给用户发消息:数据库中需要存储用户 id,使用从数据库中查询到的用户 id 进行后续操作
|
|
55
|
+
- 需要调用飞书能力给用户发消息:飞书能力不应该接受用户信息作为参数,而是应该在飞书能力配置里要求用户自己预先指定
|
|
56
|
+
|
|
57
|
+
2. 入参解析规范(仅 record_change 和 webhook 触发器):
|
|
58
|
+
- 有入参的触发器方法签名为 `async methodName(event: TaskHandlerArgs)`,`cron` 触发器无入参
|
|
59
|
+
- `content.input` 是 JSON 字符串,先用 `typeof input === 'string'` 检查类型,再用 `JSON.parse()` 解析,需添加 try-catch 错误处理
|
|
60
|
+
- `record_change`:根据操作类型获取数据:INSERT/UPDATE 使用 `after` 字段,DELETE 使用 `before` 字段
|
|
61
|
+
- `webhook`:从 `method`、`path`、`query`、`headers`、`body` 中按需取用;`body` 本身也是 JSON 字符串,需要时再次 `JSON.parse()` 解析;`query` 和 `headers` 的值均为 `string[]`
|
|
62
|
+
|
|
63
|
+
### 技术实现路径参考
|
|
64
|
+
|
|
65
|
+
以下常见需求的推荐实现路径,帮助你在平台能力限制下找到合理的技术方案;完整代码见 [触发器入参类型与代码示例](references/trigger-lifecycle.md)。
|
|
66
|
+
|
|
67
|
+
- **场景一:管理页面控制定时任务启停** —— 平台侧不支持通过 API 动态启停触发器;定时触发器始终保持开启,在任务执行时查询数据库中的开关状态决定是否执行。
|
|
68
|
+
- **场景二:定时任务通知特定用户** —— 任务执行时无法获取用户上下文;在数据库预存目标用户 ID,执行时查询再调用飞书插件发送。
|
|
69
|
+
- **场景三:记录变更触发器防抖/去重** —— 利用数据库记录最近一次处理时间戳,对比 event 时间戳进行去重。
|
|
70
|
+
- **场景四:自定义定时任务触发时间** —— cron 创建后不可动态改;平台设固定高频定时器(如每 30 分钟),执行时读数据库配置判断是否命中。
|
|
71
|
+
|
|
72
|
+
## Crontab 表达式规范
|
|
73
|
+
|
|
74
|
+
### 基本结构
|
|
75
|
+
|
|
76
|
+
Crontab 表达式由 5 个字段组成:`<minute> <hour> <day> <month> <week>`
|
|
77
|
+
|
|
78
|
+
### 字段说明
|
|
79
|
+
|
|
80
|
+
1. **minute(分钟)**:0-59 的整数
|
|
81
|
+
2. **hour(小时)**:0-23 的整数
|
|
82
|
+
3. **day(日期)**:1-31 的整数,或大写字母 `L` 表示月份的最后一天
|
|
83
|
+
4. **month(月份)**:1-12 的整数
|
|
84
|
+
5. **week(星期)**:0-6 的整数,其中 0 表示星期天
|
|
85
|
+
|
|
86
|
+
### 特殊字符
|
|
87
|
+
|
|
88
|
+
- **星号 `*`**:表示所有可能的值(每)
|
|
89
|
+
- 例:`* * * * *` 表示每分钟
|
|
90
|
+
- **逗号 `,`**:表示列表范围
|
|
91
|
+
- 例:`1,2,3 * * * *` 表示每小时的第 1、2、3 分钟
|
|
92
|
+
- **中杠 `-`**:表示数值范围
|
|
93
|
+
- 例:`1-10 * * * *` 表示每小时的第 1 到 10 分钟
|
|
94
|
+
- **正斜线 `/`**:表示间隔频率
|
|
95
|
+
- 例:`0 10-18/2 * * *` 表示每天 10 点到 18 点,每隔 2 小时执行
|
|
96
|
+
|
|
97
|
+
## 输出要求
|
|
98
|
+
|
|
99
|
+
1. 必须以 JSON 格式输出
|
|
100
|
+
2. JSON 包含两个字段:
|
|
101
|
+
- `expression`:Crontab 表达式字符串
|
|
102
|
+
- `explanation`:中文说明,简要描述执行时间
|
|
103
|
+
3. 如果用户描述不清晰,请询问具体细节
|
|
104
|
+
|
|
105
|
+
## 示例
|
|
106
|
+
|
|
107
|
+
**用户输入**:每天早上 8 点执行
|
|
108
|
+
|
|
109
|
+
**输出**:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"expression": "0 8 * * *",
|
|
114
|
+
"explanation": "每天早上 8:00 执行"
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**用户输入**:每周一到周五的上午 9 点和下午 6 点执行
|
|
119
|
+
|
|
120
|
+
**输出**:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"expression": "0 9,18 * * 1-5",
|
|
125
|
+
"explanation": "每周一至周五的 9:00 和 18:00 执行"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**用户输入**:每隔 30 分钟执行一次
|
|
130
|
+
|
|
131
|
+
**输出**:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"expression": "*/30 * * * *",
|
|
136
|
+
"explanation": "每隔 30 分钟执行一次"
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**用户输入**:每月最后一天的晚上 11 点执行
|
|
141
|
+
|
|
142
|
+
**输出**:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"expression": "0 23 L * *",
|
|
147
|
+
"explanation": "每月最后一天的 23:00 执行"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**用户输入**:每个工作日的每小时第 15 和 45 分钟执行
|
|
152
|
+
|
|
153
|
+
**输出**:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"expression": "15,45 * * * 1-5",
|
|
158
|
+
"explanation": "每周一至周五,每小时的第 15 和 45 分钟执行"
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**用户输入**:每天上午 10 点到下午 6 点,每隔 2 小时执行
|
|
163
|
+
|
|
164
|
+
**输出**:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"expression": "0 10-18/2 * * *",
|
|
169
|
+
"explanation": "每天 10:00、12:00、14:00、16:00、18:00 执行"
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## 注意事项
|
|
174
|
+
|
|
175
|
+
- 星期字段:0 和 7 都可以表示星期天(但本规范使用 0)
|
|
176
|
+
- 时间采用 24 小时制
|
|
177
|
+
- 月份和星期都从较小的数字开始计数
|
|
178
|
+
- 确保生成的表达式符合实际日历逻辑
|
|
179
|
+
- 由于技术限制,最小间隔为 30 分钟,如用户要求有误请直接拒绝用户并给出原因
|
|
180
|
+
- 输出必须是有效的 JSON 格式
|
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
name: trigger-guide
|
|
3
|
-
description: 自动化任务触发器配置与代码开发指南,支持 cron 定时触发器、record_change 数据变更触发器和 webhook 触发器,包含 @Automation/@BindTrigger 装饰器用法和 Crontab 表达式规范。Use when 需要:(1) 创建或配置自动化任务/定时任务,(2) 编写 automation 代码绑定触发器,或其他自动化任务相关开发
|
|
4
|
-
steering: true
|
|
5
|
-
steering-topic: trigger_guide
|
|
6
|
-
match-template-name: nestjs-react-fullstack
|
|
7
|
-
---
|
|
1
|
+
# 触发器入参类型与代码示例
|
|
8
2
|
|
|
9
|
-
|
|
3
|
+
本 reference 承载 nestjs-react-fullstack 触发器 handler 的入参类型定义、完整代码示例与常见实现场景。先读主 [trigger-guide](../SKILL.md) 了解目录结构、绑定约束与配置要求。
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
1. 新建自动化任务触发器时无需 enable(激活),将任务创建好然后开发完代码即可。触发器随后交由用户主动操作、要求开始。
|
|
14
|
-
|
|
15
|
-
### 目录结构
|
|
16
|
-
|
|
17
|
-
```text
|
|
18
|
-
server
|
|
19
|
-
└── modules
|
|
20
|
-
└── xxx
|
|
21
|
-
├── xxx.automation.ts
|
|
22
|
-
├── xxx.module.ts // 必须在 module 中注册自动化任务类,并且在 app.module.ts 中引用并注册该 module,否则代码将不会生效。
|
|
23
|
-
└── 其他文件(如有的话)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
文件命名规则:{模块名}.automation.ts
|
|
27
|
-
|
|
28
|
-
注意:
|
|
29
|
-
|
|
30
|
-
1. 每个模块只应该有一个存放自动化任务逻辑的文件,业务逻辑需要聚合到该文件中。
|
|
31
|
-
2. 如果该模块只有对应的自动化任务,无需编写 Controller
|
|
32
|
-
|
|
33
|
-
### 触发器类型与入参
|
|
5
|
+
## 触发器类型与入参
|
|
34
6
|
|
|
35
7
|
触发器类型(`triggerType`)有三种:
|
|
36
8
|
|
|
@@ -85,12 +57,11 @@ interface WebhookEvent {
|
|
|
85
57
|
}
|
|
86
58
|
```
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
1. Webhook 触发器不可以设置指定值,并且告知用户。
|
|
60
|
+
`DataChangeEventInput.type` 只定义 `INSERT`、`UPDATE`、`DELETE`,不包含 `UPSERT`。
|
|
90
61
|
|
|
91
|
-
|
|
62
|
+
## 代码示例
|
|
92
63
|
|
|
93
|
-
|
|
64
|
+
根据触发器创建后确定的任务名字(应用内唯一),编写并绑定到对应的方法上。使用模板已有的 `@lark-apaas/fullstack-nestjs-core` 聚合入口导入 `Automation` / `BindTrigger`,不要求项目再感知底层 trigger 包。具体代码示例如下:
|
|
94
65
|
|
|
95
66
|
```typescript
|
|
96
67
|
// 文件名:demo.automation.ts
|
|
@@ -184,23 +155,11 @@ export class DemoAutomationTasksService {
|
|
|
184
155
|
}
|
|
185
156
|
```
|
|
186
157
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
1. 执行自动化任务时无法获取用户信息。依赖用户信息的场景,实现路径如下:
|
|
190
|
-
- 需要查询数据库中的特定数据,给用户发消息:数据库中需要存储用户 id,使用从数据库中查询到的用户 id 进行后续操作
|
|
191
|
-
- 需要调用飞书能力给用户发消息:飞书能力不应该接受用户信息作为参数,而是应该在飞书能力配置里要求用户自己预先指定
|
|
192
|
-
|
|
193
|
-
2. 入参解析规范(仅 record_change 和 webhook 触发器):
|
|
194
|
-
- 有入参的触发器方法签名为 `async methodName(event: TaskHandlerArgs)`,`cron` 触发器无入参
|
|
195
|
-
- `content.input` 是 JSON 字符串,先用 `typeof input === 'string'` 检查类型,再用 `JSON.parse()` 解析,需添加 try-catch 错误处理
|
|
196
|
-
- `record_change`:根据操作类型获取数据:INSERT/UPDATE 使用 `after` 字段,DELETE 使用 `before` 字段
|
|
197
|
-
- `webhook`:从 `method`、`path`、`query`、`headers`、`body` 中按需取用;`body` 本身也是 JSON 字符串,需要时再次 `JSON.parse()` 解析;`query` 和 `headers` 的值均为 `string[]`
|
|
198
|
-
|
|
199
|
-
### 技术实现路径参考
|
|
158
|
+
## 技术实现路径参考
|
|
200
159
|
|
|
201
160
|
以下是一些常见需求的推荐实现路径,帮助你在平台能力限制下找到合理的技术方案。
|
|
202
161
|
|
|
203
|
-
|
|
162
|
+
### 场景一:用户需要管理页面控制定时任务的启停
|
|
204
163
|
|
|
205
164
|
平台侧不支持通过 API 动态启停触发器。推荐方案:**平台定时触发器始终保持开启,在任务执行时查询数据库中的开关状态,决定是否真正执行业务逻辑。**
|
|
206
165
|
|
|
@@ -233,7 +192,7 @@ export class ReportAutomationService {
|
|
|
233
192
|
}
|
|
234
193
|
```
|
|
235
194
|
|
|
236
|
-
|
|
195
|
+
### 场景二:定时任务需要将结果通知给特定用户
|
|
237
196
|
|
|
238
197
|
自动化任务执行时无法获取当前用户上下文。推荐方案:**在数据库中预存需要通知的用户 ID,任务执行时从数据库查询目标用户,再调用飞书插件发送通知。**
|
|
239
198
|
|
|
@@ -267,7 +226,7 @@ export class NotifyAutomationService {
|
|
|
267
226
|
}
|
|
268
227
|
```
|
|
269
228
|
|
|
270
|
-
|
|
229
|
+
### 场景三:记录变更触发器需要做防抖/去重
|
|
271
230
|
|
|
272
231
|
高频数据变更场景下,同一条记录可能短时间内触发多次。推荐方案:**利用数据库记录最近一次处理时间戳,对比 event 时间戳进行去重。**
|
|
273
232
|
|
|
@@ -294,7 +253,7 @@ async handleOrderChange(event: TaskHandlerArgs) {
|
|
|
294
253
|
}
|
|
295
254
|
```
|
|
296
255
|
|
|
297
|
-
|
|
256
|
+
### 场景四:用户需要自定义定时任务的触发时间
|
|
298
257
|
|
|
299
258
|
平台侧的 cron 表达式在触发器创建后无法由用户动态修改。推荐方案:**平台设置一个固定的高频定时器(如每 30 分钟执行一次),在任务执行时从数据库读取用户配置的触发时间,判断当前是否命中再决定是否执行。**
|
|
300
259
|
|
|
@@ -340,113 +299,3 @@ export class ScheduleAutomationService {
|
|
|
340
299
|
```
|
|
341
300
|
|
|
342
301
|
> 注意:由于平台最小调度间隔为 30 分钟,用户可配置的时间精度也应限制为 30 分钟的整数倍(如 `09:00`、`09:30`),前端做好校验提示。
|
|
343
|
-
|
|
344
|
-
## Crontab 表达式规范
|
|
345
|
-
|
|
346
|
-
### 基本结构
|
|
347
|
-
|
|
348
|
-
Crontab 表达式由 5 个字段组成:`<minute> <hour> <day> <month> <week>`
|
|
349
|
-
|
|
350
|
-
### 字段说明
|
|
351
|
-
|
|
352
|
-
1. **minute(分钟)**:0-59 的整数
|
|
353
|
-
2. **hour(小时)**:0-23 的整数
|
|
354
|
-
3. **day(日期)**:1-31 的整数,或大写字母 `L` 表示月份的最后一天
|
|
355
|
-
4. **month(月份)**:1-12 的整数
|
|
356
|
-
5. **week(星期)**:0-6 的整数,其中 0 表示星期天
|
|
357
|
-
|
|
358
|
-
### 特殊字符
|
|
359
|
-
|
|
360
|
-
- **星号 `*`**:表示所有可能的值(每)
|
|
361
|
-
- 例:`* * * * *` 表示每分钟
|
|
362
|
-
- **逗号 `,`**:表示列表范围
|
|
363
|
-
- 例:`1,2,3 * * * *` 表示每小时的第 1、2、3 分钟
|
|
364
|
-
- **中杠 `-`**:表示数值范围
|
|
365
|
-
- 例:`1-10 * * * *` 表示每小时的第 1 到 10 分钟
|
|
366
|
-
- **正斜线 `/`**:表示间隔频率
|
|
367
|
-
- 例:`0 10-18/2 * * *` 表示每天 10 点到 18 点,每隔 2 小时执行
|
|
368
|
-
|
|
369
|
-
## 输出要求
|
|
370
|
-
|
|
371
|
-
1. 必须以 JSON 格式输出
|
|
372
|
-
2. JSON 包含两个字段:
|
|
373
|
-
- `expression`:Crontab 表达式字符串
|
|
374
|
-
- `explanation`:中文说明,简要描述执行时间
|
|
375
|
-
3. 如果用户描述不清晰,请询问具体细节
|
|
376
|
-
|
|
377
|
-
## 示例
|
|
378
|
-
|
|
379
|
-
**用户输入**:每天早上 8 点执行
|
|
380
|
-
|
|
381
|
-
**输出**:
|
|
382
|
-
|
|
383
|
-
```json
|
|
384
|
-
{
|
|
385
|
-
"expression": "0 8 * * *",
|
|
386
|
-
"explanation": "每天早上 8:00 执行"
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**用户输入**:每周一到周五的上午 9 点和下午 6 点执行
|
|
391
|
-
|
|
392
|
-
**输出**:
|
|
393
|
-
|
|
394
|
-
```json
|
|
395
|
-
{
|
|
396
|
-
"expression": "0 9,18 * * 1-5",
|
|
397
|
-
"explanation": "每周一至周五的 9:00 和 18:00 执行"
|
|
398
|
-
}
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
**用户输入**:每隔 30 分钟执行一次
|
|
402
|
-
|
|
403
|
-
**输出**:
|
|
404
|
-
|
|
405
|
-
```json
|
|
406
|
-
{
|
|
407
|
-
"expression": "*/30 * * * *",
|
|
408
|
-
"explanation": "每隔 30 分钟执行一次"
|
|
409
|
-
}
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
**用户输入**:每月最后一天的晚上 11 点执行
|
|
413
|
-
|
|
414
|
-
**输出**:
|
|
415
|
-
|
|
416
|
-
```json
|
|
417
|
-
{
|
|
418
|
-
"expression": "0 23 L * *",
|
|
419
|
-
"explanation": "每月最后一天的 23:00 执行"
|
|
420
|
-
}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
**用户输入**:每个工作日的每小时第 15 和 45 分钟执行
|
|
424
|
-
|
|
425
|
-
**输出**:
|
|
426
|
-
|
|
427
|
-
```json
|
|
428
|
-
{
|
|
429
|
-
"expression": "15,45 * * * 1-5",
|
|
430
|
-
"explanation": "每周一至周五,每小时的第 15 和 45 分钟执行"
|
|
431
|
-
}
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**用户输入**:每天上午 10 点到下午 6 点,每隔 2 小时执行
|
|
435
|
-
|
|
436
|
-
**输出**:
|
|
437
|
-
|
|
438
|
-
```json
|
|
439
|
-
{
|
|
440
|
-
"expression": "0 10-18/2 * * *",
|
|
441
|
-
"explanation": "每天 10:00、12:00、14:00、16:00、18:00 执行"
|
|
442
|
-
}
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
## 注意事项
|
|
446
|
-
|
|
447
|
-
- 星期字段:0 和 7 都可以表示星期天(但本规范使用 0)
|
|
448
|
-
- 时间采用 24 小时制
|
|
449
|
-
- 月份和星期都从较小的数字开始计数
|
|
450
|
-
- 确保生成的表达式符合实际日历逻辑
|
|
451
|
-
- 由于技术限制,最小间隔为 30 分钟,如用户要求有误请直接拒绝用户并给出原因
|
|
452
|
-
- 输出必须是有效的 JSON 格式
|