@xtalpi/agentic-lab-skills 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/package.json +1 -1
  2. package/skills/lab-flow-designer/SKILL.md +66 -4
  3. package/skills/lab-flow-designer/embedded-template/SKILL.md +4 -0
  4. package/skills/lab-flow-designer/embedded-template/scripts//347/244/272/344/276/213/346/225/260/346/215/256/344/270/216/346/240/241/351/252/214/351/227/250/346/216/247.js +6 -0
  5. package/skills/lab-flow-designer/references/agentic-lab-processer.md +1 -0
  6. package/skills/lab-flow-designer/references/skill-package-layout.md +5 -0
  7. package/skills/lab-flow-designer/templates//344/270/232/345/212/241/346/265/201/347/250/213/346/226/207/346/241/243/346/250/241/346/235/277.md +169 -0
  8. package/skills/lab-flow-designer/templates//344/270/232/345/212/241/346/265/201/347/250/213/346/226/207/346/241/243/347/244/272/344/276/213.md +197 -0
  9. package/skills/lab-nocobase-flow-generator/SKILL.md +164 -0
  10. package/skills/lab-nocobase-flow-generator/examples/setting/350/241/250/350/216/267/345/217/226/345/244/226/351/203/250/346/234/215/345/212/241.js +70 -0
  11. package/skills/lab-nocobase-flow-generator/examples//346/237/245/350/257/242/345/214/226/345/255/246/345/223/201/344/277/241/346/201/257.js +30 -0
  12. package/skills/lab-nocobase-flow-generator/references/doc-standard.md +84 -0
  13. package/skills/lab-nocobase-flow-generator/references/runtime-api.md +224 -0
  14. package/skills/lab-nocobase-flow-generator/templates//350/204/232/346/234/254/351/200/273/350/276/221/346/226/207/346/241/243/346/250/241/346/235/277.md +121 -0
  15. package/skills/lab-nocobase-flow-generator/templates//350/204/232/346/234/254/351/200/273/350/276/221/346/226/207/346/241/243/347/244/272/344/276/213.md +67 -0
  16. package/skills/lab-orbit-component-builder/SKILL.md +56 -8
  17. package/skills/lab-orbit-component-builder/examples/xnb-component-template/dev/src/global.d.ts +3 -0
  18. package/skills/lab-orbit-component-builder/examples/xnb-component-template/dev/src/main.ts +6 -3
  19. package/skills/lab-orbit-component-builder/examples/xnb-component-template/package.json +4 -1
  20. package/skills/lab-orbit-component-builder/examples/xnb-component-template/src/views/bitable.vue +2 -0
  21. package/skills/lab-orbit-component-builder/examples/xnb-component-template/tsconfig.json +4 -7
  22. package/skills/lab-orbit-component-builder/examples/xnb-component-template/vite.config.ts +5 -0
  23. package/skills/lab-orbit-component-builder/examples/xnb-component-template/vite.dev.config.ts +7 -0
  24. package/skills/lab-orbit-component-builder/references/orbit-vue-conventions.md +133 -0
  25. package/skills/lab-orbit-component-builder/references/vue-template-checklist.md +66 -0
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: lab-nocobase-flow-generator
3
+ description: >-
4
+ 根据脚本逻辑文档(或用户对话描述)生成可在 NocoBase 工作流「脚本节点」中运行的 JavaScript 脚本。
5
+ 也可根据用户描述生成符合规范的脚本逻辑文档模板,供用户完善后用于脚本生成。
6
+ Use when user wants to generate a NocoBase workflow script, script logic document template, or provides a script logic document.
7
+ ---
8
+
9
+ # NocoBase 工作流脚本生成器
10
+
11
+ ## 适用场景
12
+
13
+ - 用户提供**脚本逻辑文档**(Markdown,格式见 [references/doc-standard.md](references/doc-standard.md))或在对话中描述需求,需要生成可在 NocoBase 工作流「脚本节点」中直接运行的 JavaScript 脚本。
14
+ - 用户希望生成一份**脚本逻辑文档模板**,用于梳理和描述业务需求,完善后再用本技能生成脚本。
15
+
16
+ ## 分层加载
17
+
18
+ | 需求 | 打开 |
19
+ |------|------|
20
+ | **运行时 API、Repository 操作、过滤操作符、脚本结构** | [references/runtime-api.md](references/runtime-api.md) |
21
+ | **逻辑文档格式要求与合规检查** | [references/doc-standard.md](references/doc-standard.md) |
22
+ | **数据库查询示例** | [examples/查询化学品信息.js](examples/查询化学品信息.js) |
23
+ | **外部服务调用 + setting 表示例** | [examples/setting表获取外部服务.js](examples/setting表获取外部服务.js) |
24
+ | **脚本逻辑文档模板** | [templates/脚本逻辑文档模板.md](templates/脚本逻辑文档模板.md) |
25
+ | **逻辑文档填写示例** | [templates/脚本逻辑文档示例.md](templates/脚本逻辑文档示例.md) |
26
+
27
+ ## 会话模式判定
28
+
29
+ | 模式 | 判定条件 | 行为 |
30
+ |------|----------|------|
31
+ | **从文档生成** | 用户提供了脚本逻辑文档路径,或贴入文档内容 | 先执行「文档合规预检」,通过后生成脚本 |
32
+ | **对话式生成** | 用户在对话中描述需求,未提供文档 | 通过提问补全关键信息(见§3),然后生成脚本 |
33
+ | **修改已有脚本** | 用户提供已有脚本路径,要求修改功能 | 跳过预检,按用户要求修改 |
34
+ | **生成逻辑文档** | 用户要求生成文档、模板、操作模板 | 基于模板和用户描述,生成预填充的逻辑文档并写入本地文件 |
35
+
36
+ ## 工作流
37
+
38
+ ### 第 1 步:需求收集与确认
39
+
40
+ #### A. 从文档生成
41
+
42
+ 1. 读取用户指定的逻辑文档
43
+ 2. 按 [references/doc-standard.md](references/doc-standard.md) 的合规检查清单逐项核对
44
+ 3. **若不通过**:列出缺失项和补充建议,等待用户修改后重新提交
45
+ 4. **若通过**:进入第 2 步
46
+
47
+ #### B. 对话式生成
48
+
49
+ 向用户确认以下关键信息(已明确的跳过):
50
+
51
+ | 主题 | 需要确认的内容 |
52
+ |------|----------------|
53
+ | 输入参数 | 有哪些参数?类型?哪些必填?校验规则? |
54
+ | 数据库操作 | 操作哪些表?查询/创建/更新/删除?过滤条件? |
55
+ | 外部接口 | 是否需要调用外部服务?地址从 setting 表读取还是固定?请求方法和参数? |
56
+ | 核心逻辑 | 数据处理的步骤?条件分支?循环? |
57
+ | 输出结果 | 成功/失败分别返回什么? |
58
+
59
+ #### C. 生成逻辑文档
60
+
61
+ 1. 读取 [templates/脚本逻辑文档模板.md](templates/脚本逻辑文档模板.md) 获取文档结构
62
+ 2. 参考 [templates/脚本逻辑文档示例.md](templates/脚本逻辑文档示例.md) 了解填写规范
63
+ 3. 根据用户描述的业务场景,预填充模板中的各章节(能确定的内容填入,不确定的保留占位提示)
64
+ 4. 将文档写入用户指定路径(按优先级:① 用户指定了具体路径 → 使用该路径;② 用户指定了参考文档路径 → 在该文档所在目录下生成 `【逻辑文档】{脚本名称}.md`;③ 均未指定 → 在当前工作目录下生成 `【逻辑文档】{脚本名称}.md`。**禁止**私自创建子目录)
65
+ 5. 提示用户:完善文档内容后,可直接用本技能的「从文档生成」模式生成脚本
66
+
67
+ ### 第 2 步:生成脚本
68
+
69
+ 打开 [references/runtime-api.md](references/runtime-api.md),按以下结构生成脚本:
70
+
71
+ ```
72
+ 1. 引入外部依赖(按需,无外部调用则省略)
73
+ 2. 定义辅助函数 ok() / fail()
74
+ 2b. 产物版本常量(__ARTIFACT_VERSION__ / __ARTIFACT_SKILL__)+ console.info 版本打印
75
+ 3. 解构输入参数(从 input_data)
76
+ 4. 获取 Repository
77
+ 5. 定义业务辅助函数(如 get_settings,仅需要时添加)
78
+ 6. try-catch 包裹以下所有步骤:
79
+ a. 参数校验(return fail('VALIDATION_ERROR', ...) )
80
+ b. 业务逻辑
81
+ c. return ok(data)
82
+ 7. catch 块:return fail(错误码, err_info)
83
+ ```
84
+
85
+ ### 第 3 步:输出与说明
86
+
87
+ 向用户输出:
88
+ 1. 完整的脚本代码
89
+ 2. 简要说明脚本逻辑
90
+ 3. 需要在工作流中配置的输入参数列表
91
+
92
+ ## 脚本生成规则
93
+
94
+ ### 运行时环境
95
+
96
+ - 脚本运行在 NocoBase 工作流的脚本节点中,**非 Node.js 模块**
97
+ - 顶层支持 `await`,无需包裹 async 函数
98
+ - 全局可用:`appContext`、`dayjs`、`getMessageFromError`、`input_data`
99
+ - `return` 的值作为节点输出传递给下游
100
+ - 可使用 `require('axios')`、`require('node:crypto')` 等
101
+
102
+ ### 数据库操作
103
+
104
+ - Repository 获取:`appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('表名')`
105
+ - 查询大量数据时 `pageSize` 设为 `9999` 或 `99999`
106
+ - 过滤操作符详见 [references/runtime-api.md](references/runtime-api.md) §4
107
+
108
+ ### 外部服务调用(按需)
109
+
110
+ - 仅当逻辑文档 §3.2 声明了外部服务操作时才引入 `axios`
111
+ - 使用 `const axios = require('axios')`
112
+ - 接口地址来源有两种模式:
113
+ - **固定地址**:直接写入 URL
114
+ - **setting 表配置**:通过 `getSettings()` 获取,拼接 URL(参见 [examples/setting表获取外部服务.js](examples/setting表获取外部服务.js))
115
+
116
+ ### 错误处理与返回格式
117
+
118
+ - 每个脚本顶部必须定义 `ok()` / `fail()` 辅助函数:
119
+ ```javascript
120
+ const ok = (data) => ({ success: true, error_code: null, error_message: null, http_status: null, data })
121
+ const fail = (error_code, error_message, http_status = null) => ({ success: false, error_code, error_message, http_status, data: null })
122
+ ```
123
+ - 所有业务逻辑(含参数校验)必须在 `try-catch` 内部
124
+ - 参数校验失败使用 `return fail('VALIDATION_ERROR', '...')`,**不使用 `throw`**
125
+ - 成功返回使用 `return ok(data)`
126
+ - 查询无结果不是错误,返回 `ok([])`
127
+ - 异常捕获使用 `getMessageFromError(err)` 提取信息,通过 `fail()` 返回
128
+ - 错误码枚举:`VALIDATION_ERROR` / `DB_ERROR` / `HTTP_ERROR` / `CONFIG_ERROR` / `UNKNOWN_ERROR`
129
+ - 涉及 axios 调用的脚本,catch 块中需检查 `err.response`(HTTP 错误带状态码)和 `err.request`(无响应)
130
+ - 详见 [references/runtime-api.md](references/runtime-api.md) §8、§9
131
+
132
+ ### 代码风格
133
+
134
+ - 不写多余注释,代码自解释
135
+ - 变量命名使用 snake_case(与 NocoBase 字段风格一致)
136
+ - 优先使用 `const`,仅在需要重新赋值时使用 `let`
137
+ - 不添加未使用的依赖和变量
138
+
139
+ ### 产物版本追踪
140
+
141
+ 每个生成的脚本**必须**包含版本信息,帮助用户识别产物来源和版本。
142
+
143
+ 版本块放在 `ok()`/`fail()` 定义之后、参数解构之前:
144
+
145
+ ```javascript
146
+ // --- Artifact Version ---
147
+ const __ARTIFACT_VERSION__ = '<semver>'
148
+ const __ARTIFACT_SKILL__ = 'lab-nocobase-flow-generator'
149
+ console.info(`[WorkflowScript] v${__ARTIFACT_VERSION__} (skill: ${__ARTIFACT_SKILL__})`)
150
+ ```
151
+
152
+ - **初次生成 / 从文档生成 / 对话式生成**:`__ARTIFACT_VERSION__` = `'1.0.0'`。
153
+ - **修改已有脚本**:读取现有 `__ARTIFACT_VERSION__`,按变更范围递增(patch:修复;minor:新增逻辑;major:输入输出结构变更),**不得**重置为 `1.0.0`。
154
+
155
+ ## 硬性约束
156
+
157
+ - **必须**通过 `appContext.dataSourceManager` 获取 Repository,不可直接操作数据库
158
+ - **必须**对所有异步操作做错误处理
159
+ - **禁止**硬编码敏感信息(Token、密码等)到脚本中;应从 `input_data` 或 `setting` 表获取
160
+ - **禁止**使用 `module.exports` / `export`,脚本不是模块
161
+ - **禁止**使用 `process.exit()` 或其他退出进程的操作
162
+ - `return` 的值必须是可序列化的(对象、数组、字符串、数字)
163
+ - `return` 必须使用 `ok()` / `fail()` 辅助函数,确保统一信封格式
164
+ - **必须**在 `ok()`/`fail()` 定义之后、参数解构之前包含 `__ARTIFACT_VERSION__` 和 `__ARTIFACT_SKILL__` 常量及 `console.info` 版本打印
@@ -0,0 +1,70 @@
1
+ const axios = require('axios')
2
+
3
+ const ok = (data) => ({ success: true, error_code: null, error_message: null, http_status: null, data })
4
+ const fail = (error_code, error_message, http_status = null) => ({ success: false, error_code, error_message, http_status, data: null })
5
+
6
+ // --- Artifact Version ---
7
+ const __ARTIFACT_VERSION__ = '1.0.0'
8
+ const __ARTIFACT_SKILL__ = 'lab-nocobase-flow-generator'
9
+ console.info(`[WorkflowScript] v${__ARTIFACT_VERSION__} (skill: ${__ARTIFACT_SKILL__})`)
10
+
11
+ const setting_repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('setting')
12
+
13
+ const get_settings = async () => {
14
+ const res = await setting_repo.find({ pageSize: 9999 })
15
+ const settings = {}
16
+ res.forEach(s => {
17
+ settings[s.setting_name] = s.setting_value
18
+ })
19
+ return settings
20
+ }
21
+
22
+ const { task_id } = input_data
23
+
24
+ const task_repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('task')
25
+
26
+ try {
27
+ if (!task_id) return fail('VALIDATION_ERROR', 'task_id is required')
28
+
29
+ const task = await task_repo.find({
30
+ pageSize: 1,
31
+ filter: { id: task_id }
32
+ })
33
+
34
+ if (task.length === 0) {
35
+ return ok({ task: null, processes: [] })
36
+ }
37
+
38
+ const settings = await get_settings()
39
+ if (!settings.rhea_host) return fail('CONFIG_ERROR', 'rhea_host 未在 setting 表中配置')
40
+
41
+ const res = await axios({
42
+ method: 'post',
43
+ url: `${settings.rhea_host}/api/process/list_process`,
44
+ data: {
45
+ filter: {
46
+ filter: {
47
+ operator: 'and',
48
+ conditions: [
49
+ { field: 'status', operator: 'not_in', value: ['Failed', 'Completed'] }
50
+ ]
51
+ }
52
+ },
53
+ per_page: 99999,
54
+ page: 1
55
+ }
56
+ })
57
+
58
+ return ok({
59
+ task: task[0],
60
+ processes: res.data.results.records
61
+ })
62
+ } catch (err) {
63
+ const err_info = getMessageFromError(err)
64
+ console.error('操作失败:', err)
65
+
66
+ if (err.response) return fail('HTTP_ERROR', err_info, err.response.status)
67
+ if (err.request) return fail('HTTP_ERROR', '外部服务无响应: ' + err_info)
68
+
69
+ return fail('DB_ERROR', err_info)
70
+ }
@@ -0,0 +1,30 @@
1
+ const ok = (data) => ({ success: true, error_code: null, error_message: null, http_status: null, data })
2
+ const fail = (error_code, error_message, http_status = null) => ({ success: false, error_code, error_message, http_status, data: null })
3
+
4
+ // --- Artifact Version ---
5
+ const __ARTIFACT_VERSION__ = '1.0.0'
6
+ const __ARTIFACT_SKILL__ = 'lab-nocobase-flow-generator'
7
+ console.info(`[WorkflowScript] v${__ARTIFACT_VERSION__} (skill: ${__ARTIFACT_SKILL__})`)
8
+
9
+ const { chemical_name, cas } = input_data
10
+
11
+ const chemical_repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('chemical')
12
+
13
+ try {
14
+ if (!chemical_name && !cas) return fail('VALIDATION_ERROR', 'chemical_name 或 cas 至少提供一个')
15
+
16
+ const filter = {}
17
+ if (chemical_name) filter.chemical_name = chemical_name
18
+ if (cas) filter.cas = cas
19
+
20
+ const data = await chemical_repo.find({
21
+ pageSize: 999,
22
+ filter
23
+ })
24
+
25
+ return ok(data)
26
+ } catch (err) {
27
+ const err_info = getMessageFromError(err)
28
+ console.error('查询chemical失败:', err)
29
+ return fail('DB_ERROR', err_info)
30
+ }
@@ -0,0 +1,84 @@
1
+ # 脚本逻辑文档规范
2
+
3
+ 本文档定义了产品人员编写「脚本逻辑文档」时须遵循的格式,Skill 依据此规范解析文档并生成脚本。
4
+
5
+ ---
6
+
7
+ ## 必备章节与检查项
8
+
9
+ ### §1 基本信息(必填)
10
+
11
+ 表格形式,包含:
12
+
13
+ | 字段 | 要求 |
14
+ |------|------|
15
+ | 脚本名称 | 必填,简洁描述功能 |
16
+ | 业务场景 | 必填,说明触发场景和业务目的 |
17
+ | 输入参数来源 | 必填,`input_data` / `workflow_context` / 无 |
18
+
19
+ ### §2 输入参数(必填)
20
+
21
+ 表格列出所有参数:`参数名`、`类型`、`必填`、`说明`。
22
+
23
+ 必须描述**参数校验规则**(如互斥、至少一个必填等)。
24
+
25
+ ### §3 数据操作(必填)
26
+
27
+ 分为两个子节:
28
+
29
+ #### §3.1 NocoBase 数据库操作
30
+
31
+ 每个操作一个子标题,包含:
32
+ - **数据表**:表名(必填)
33
+ - **操作类型**:`find` / `create` / `update` / `destroy`(必填)
34
+ - **关联加载**:appends 字段名列表或 `无`
35
+ - **过滤条件**:列出所有条件
36
+ - **更新/写入字段**(仅 create/update):`字段名`、`值来源`、`说明`
37
+
38
+ #### §3.2 外部服务操作(可选)
39
+
40
+ 每个接口一个子标题,包含:
41
+ - **接口地址来源**:`setting` 表配置项名称 或 固定地址(必填)
42
+ - **请求路径**:接口路径(必填)
43
+ - **请求方法**:`GET` / `POST` / `PUT` / `DELETE`(必填)
44
+ - **认证方式**:`Bearer Token` / 无 / `setting` 表配置项
45
+ - **请求参数/请求体**:JSON 示例
46
+ - **响应取值路径**:如 `res.data.results.records`
47
+
48
+ ### §4 核心逻辑(必填)
49
+
50
+ 编号步骤描述处理流程,可包含:
51
+ - **条件分支**:当 XXX 时 → 执行 A
52
+ - **循环处理**:遍历 XXX,对每条执行 ...
53
+ - **数据转换**:字段映射、计算等
54
+
55
+ ### §5 输出结果(必填)
56
+
57
+ 表格列出各场景的返回值:`场景`、`返回值`、`类型`。
58
+
59
+ 至少覆盖:成功(含空数据)、校验失败、异常。返回格式须符合标准信封格式(`ok()` / `fail()`)。
60
+
61
+ ### §6 备注(可选)
62
+
63
+ 补充说明、注意事项。
64
+
65
+ ---
66
+
67
+ ## 合规检查清单
68
+
69
+ Skill 在生成脚本前会检查以下项目:
70
+
71
+ | # | 检查项 | 阻断级别 |
72
+ |---|--------|----------|
73
+ | 1 | §1 基本信息完整 | 阻断 |
74
+ | 2 | §2 输入参数至少列出一项,或明确标注「无输入参数」 | 阻断 |
75
+ | 3 | §3 至少有一个数据操作(数据库或外部服务) | 阻断 |
76
+ | 4 | §3.1 每个数据库操作的表名和操作类型已指定 | 阻断 |
77
+ | 5 | §3.2 外部接口的地址来源、路径、方法已指定 | 阻断 |
78
+ | 6 | §4 核心逻辑步骤清晰,无歧义条件 | 阻断 |
79
+ | 7 | §5 输出结果覆盖成功/异常场景 | 建议 |
80
+ | 8 | §3.1 过滤条件使用支持的操作符 | 建议 |
81
+ | 9 | §3.2 接口认证方式已说明 | 建议 |
82
+
83
+ - **阻断**:未满足则不生成脚本,输出补充建议
84
+ - **建议**:未满足仍可生成,但提示优化
@@ -0,0 +1,224 @@
1
+ # NocoBase 工作流脚本运行时 API
2
+
3
+ ## 1. 全局对象
4
+
5
+ 脚本在 NocoBase 工作流的「脚本节点」中执行,运行时注入以下全局对象:
6
+
7
+ | 对象 | 说明 |
8
+ |------|------|
9
+ | `appContext` | NocoBase 应用上下文,用于获取数据表 Repository |
10
+ | `dayjs` | 日期处理库(已全局注入,无需 require) |
11
+ | `getMessageFromError(err)` | 从错误对象提取可读信息的工具函数 |
12
+ | `input_data` | 工作流传入的参数对象(由前一个节点或触发器提供) |
13
+
14
+ ## 2. 获取 Repository
15
+
16
+ ```javascript
17
+ const repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('表名')
18
+ ```
19
+
20
+ ## 3. Repository 操作
21
+
22
+ ### 3.1 find — 查询
23
+
24
+ ```javascript
25
+ const data = await repo.find({
26
+ pageSize: 9999, // 分页大小
27
+ filter: { // 过滤条件
28
+ field_name: 'value',
29
+ status: { $in: ['A', 'B'] },
30
+ date_field: {
31
+ $dateBefore: '2025-01-01 00:00:00',
32
+ $dateAfter: '2024-01-01 00:00:00'
33
+ },
34
+ name: { $notEmpty: true }
35
+ },
36
+ appends: ['relation_field'] // 加载关联字段(可选)
37
+ })
38
+ // 返回值: Array
39
+ ```
40
+
41
+ ### 3.2 create — 创建
42
+
43
+ ```javascript
44
+ const res = await repo.create({
45
+ values: {
46
+ field1: 'value1',
47
+ field2: 123
48
+ }
49
+ })
50
+ // 返回值: Object (创建的记录)
51
+ ```
52
+
53
+ ### 3.3 update — 更新
54
+
55
+ ```javascript
56
+ const res = await repo.update({
57
+ filter: { id: 1 }, // 或 { id: { $in: [1, 2, 3] } }
58
+ values: {
59
+ status: 'new_status'
60
+ }
61
+ })
62
+ // 返回值: Array (更新的记录)
63
+ ```
64
+
65
+ ### 3.4 destroy — 删除
66
+
67
+ ```javascript
68
+ await repo.destroy({
69
+ filter: { id: 1 }
70
+ })
71
+ ```
72
+
73
+ ## 4. 常用过滤操作符
74
+
75
+ | 操作符 | 说明 | 示例 |
76
+ |--------|------|------|
77
+ | `$eq` | 等于(默认) | `{ name: 'test' }` |
78
+ | `$ne` | 不等于 | `{ status: { $ne: 'deleted' } }` |
79
+ | `$in` | 在列表中 | `{ status: { $in: ['A', 'B'] } }` |
80
+ | `$notIn` | 不在列表中 | `{ status: { $notIn: ['X'] } }` |
81
+ | `$empty` | 为空 | `{ name: { $empty: true } }` |
82
+ | `$notEmpty` | 不为空 | `{ name: { $notEmpty: true } }` |
83
+ | `$dateBefore` | 日期早于 | `{ date: { $dateBefore: '...' } }` |
84
+ | `$dateAfter` | 日期晚于 | `{ date: { $dateAfter: '...' } }` |
85
+ | `$or` | 或条件 | `{ $or: [{ a: 1 }, { b: 2 }] }` |
86
+
87
+ ## 5. 外部 HTTP 调用(axios)
88
+
89
+ ```javascript
90
+ const axios = require('axios')
91
+
92
+ const res = await axios({
93
+ method: 'get', // 或 'post', 'put', 'delete'
94
+ url: 'http://example.com/api/xxx',
95
+ params: { key: 'val' }, // GET 参数
96
+ data: { key: 'val' }, // POST 请求体
97
+ headers: {
98
+ 'Content-Type': 'application/json',
99
+ 'Authorization': 'Bearer xxx'
100
+ }
101
+ })
102
+ // 响应: res.data
103
+ ```
104
+
105
+ ## 6. 从 setting 表读取配置(用于动态获取外部服务地址)
106
+
107
+ 当外部接口地址需要从系统配置中读取时:
108
+
109
+ ```javascript
110
+ const setting_repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('setting')
111
+
112
+ const get_settings = async () => {
113
+ const res = await setting_repo.find({ pageSize: 9999 })
114
+ const settings = {}
115
+ res.forEach(s => {
116
+ settings[s.setting_name] = s.setting_value
117
+ })
118
+ return settings
119
+ }
120
+
121
+ // 使用示例
122
+ const settings = await get_settings()
123
+ if (!settings.rhea_host) return fail('CONFIG_ERROR', 'rhea_host 未在 setting 表中配置')
124
+ const url = `${settings.rhea_host}/api/process/list_process`
125
+ ```
126
+
127
+ > **注意:** 不同项目的 setting 表字段名可能不同(`setting_name`/`name`、`setting_value`/`value`),以实际表结构为准。
128
+ > 必要配置缺失时使用 `fail('CONFIG_ERROR', ...)` 返回结构化错误,不要使用 `throw`。
129
+
130
+ ## 7. 脚本结构规范
131
+
132
+ ```javascript
133
+ // 1. 引入外部依赖(按需)
134
+ const axios = require('axios')
135
+
136
+ // 2. 辅助函数
137
+ const ok = (data) => ({ success: true, error_code: null, error_message: null, http_status: null, data })
138
+ const fail = (error_code, error_message, http_status = null) => ({ success: false, error_code, error_message, http_status, data: null })
139
+
140
+ // 3. 解构输入参数
141
+ const { param1, param2 } = input_data
142
+
143
+ // 4. 获取 Repository
144
+ const xxx_repo = appContext.dataSourceManager.dataSources.get('main').collectionManager.getRepository('xxx')
145
+
146
+ // 5. try-catch 包裹所有业务逻辑(含参数校验)
147
+ try {
148
+ if (!param1) return fail('VALIDATION_ERROR', 'param1 is required')
149
+
150
+ const data = await xxx_repo.find({ ... })
151
+
152
+ return ok(data)
153
+ } catch (err) {
154
+ const err_info = getMessageFromError(err)
155
+ console.error('操作失败:', err)
156
+ return fail('DB_ERROR', err_info)
157
+ }
158
+ ```
159
+
160
+ ## 8. 标准返回格式
161
+
162
+ 所有脚本必须通过 `ok()` / `fail()` 辅助函数返回统一的信封对象:
163
+
164
+ ```javascript
165
+ const ok = (data) => ({ success: true, error_code: null, error_message: null, http_status: null, data })
166
+ const fail = (error_code, error_message, http_status = null) => ({ success: false, error_code, error_message, http_status, data: null })
167
+ ```
168
+
169
+ **信封字段:**
170
+
171
+ | 字段 | 类型 | 成功时 | 失败时 |
172
+ |------|------|--------|--------|
173
+ | `success` | `boolean` | `true` | `false` |
174
+ | `error_code` | `string \| null` | `null` | 错误码枚举值 |
175
+ | `error_message` | `string \| null` | `null` | 可读的错误描述 |
176
+ | `http_status` | `number \| null` | `null` | HTTP 状态码(仅 `HTTP_ERROR`) |
177
+ | `data` | `any` | 业务数据 | `null` |
178
+
179
+ **错误码枚举:**
180
+
181
+ | 错误码 | 含义 | 使用场景 |
182
+ |--------|------|----------|
183
+ | `VALIDATION_ERROR` | 参数缺失或不合法 | 参数校验 |
184
+ | `DB_ERROR` | 数据库操作失败 | Repository 操作异常 |
185
+ | `HTTP_ERROR` | 外部 HTTP 调用失败 | axios 调用异常 |
186
+ | `CONFIG_ERROR` | 配置缺失 | setting 表缺少必要配置 |
187
+ | `UNKNOWN_ERROR` | 未分类异常 | catch 兜底 |
188
+
189
+ **约定:**
190
+ - 查询无结果不是错误,返回 `ok([])`,由下游节点判断
191
+ - 参数校验使用 `return fail(...)` 而非 `throw new Error(...)`
192
+ - 下游节点通过 `result.success` 判断成功/失败
193
+
194
+ ## 9. Axios 错误处理
195
+
196
+ 当脚本包含外部 HTTP 调用时,catch 块需区分错误类型:
197
+
198
+ ```javascript
199
+ } catch (err) {
200
+ const err_info = getMessageFromError(err)
201
+ console.error('操作失败:', err)
202
+
203
+ // HTTP 响应错误(4xx / 5xx)
204
+ if (err.response) return fail('HTTP_ERROR', err_info, err.response.status)
205
+
206
+ // 请求已发出但无响应(网络超时等)
207
+ if (err.request) return fail('HTTP_ERROR', '外部服务无响应: ' + err_info)
208
+
209
+ // 非 HTTP 错误(数据库或其他)
210
+ return fail('DB_ERROR', err_info)
211
+ }
212
+ ```
213
+
214
+ - `err.response` 存在 → 服务器返回了错误状态码,`err.response.status` 为 HTTP 状态码
215
+ - `err.request` 存在但无 `err.response` → 请求已发出但未收到响应
216
+ - 两者都不存在 → 非 HTTP 错误,归类为 `DB_ERROR`
217
+
218
+ ## 10. 注意事项
219
+
220
+ - 脚本顶层支持 `await`,无需包裹 async 函数
221
+ - `return` 的值会作为脚本节点的输出,传递给工作流下游节点
222
+ - `console.log` 可用于调试,日志输出到工作流执行日志
223
+ - 查询大量数据时 `pageSize` 设为较大值(如 `9999` 或 `99999`)
224
+ - 日期格式统一使用 `dayjs().format('YYYY-MM-DD HH:mm:ss')`
@@ -0,0 +1,121 @@
1
+ # 脚本逻辑文档模板
2
+
3
+ > 产品人员按此模板编写脚本需求文档,AI Skill 将根据文档内容生成可在 NocoBase 工作流中运行的脚本。
4
+
5
+ ---
6
+
7
+ ## 1. 基本信息
8
+
9
+ | 字段 | 值 |
10
+ |------|-----|
11
+ | 脚本名称 | (例:查询化学品信息) |
12
+ | 业务场景 | (简要描述脚本用途和触发场景) |
13
+ | 输入参数来源 | `input_data` / `workflow_context` / 无 |
14
+
15
+ ---
16
+
17
+ ## 2. 输入参数
18
+
19
+ > 描述脚本接收的参数,来源为工作流传入的变量。
20
+
21
+ | 参数名 | 类型 | 必填 | 说明 |
22
+ |--------|------|------|------|
23
+ | (例:chemical_name) | string | 否 | 化学品名称 |
24
+ | (例:cas) | string | 否 | CAS 编号 |
25
+
26
+ **参数校验规则:**
27
+ - (例:`chemical_name` 和 `cas` 至少填写一个)
28
+
29
+ ---
30
+
31
+ ## 3. 数据操作
32
+
33
+ ### 3.1 NocoBase 数据库操作
34
+
35
+ > 列出所有需要操作的 NocoBase 数据表及操作类型。
36
+
37
+ #### 操作 1:(描述操作目的)
38
+
39
+ | 字段 | 值 |
40
+ |------|-----|
41
+ | 数据表 | (表名,例:`chemical`) |
42
+ | 操作类型 | `find` / `create` / `update` / `destroy` |
43
+ | 关联加载 | (需要 appends 的关联字段,无则填 `无`) |
44
+
45
+ **过滤条件:**
46
+ - (例:按 `chemical_name` 精确匹配)
47
+ - (例:按 `cas` 精确匹配)
48
+ - (例:按 `status` 在 `['Available', 'Expired']` 中筛选)
49
+
50
+ **更新/写入字段(仅 create/update 时填写):**
51
+
52
+ | 字段名 | 值来源 | 说明 |
53
+ |--------|--------|------|
54
+ | (例:status) | 固定值 `'Expired'` | 更新状态 |
55
+
56
+ ---
57
+
58
+ ### 3.2 外部服务操作
59
+
60
+ > 如需调用系统外部的 HTTP 接口,在此描述。无外部操作则删除本节。
61
+
62
+ #### 接口 1:(描述接口用途)
63
+
64
+ | 字段 | 值 |
65
+ |------|-----|
66
+ | 接口地址来源 | `setting` 表配置项(配置项名称,例:`rhea_host`)/ 固定地址 |
67
+ | 请求路径 | (例:`/api/process/list_process`) |
68
+ | 请求方法 | `GET` / `POST` / `PUT` / `DELETE` |
69
+ | 认证方式 | `Bearer Token` / 无 / 其他 |
70
+
71
+ **请求参数/请求体:**
72
+
73
+ ```json
74
+ {
75
+ "说明": "在此描述请求的 JSON 结构",
76
+ "filter": {
77
+ "field": "status",
78
+ "operator": "not_in",
79
+ "value": ["Failed", "Completed"]
80
+ }
81
+ }
82
+ ```
83
+
84
+ **响应取值路径:**
85
+ - (例:`res.data.results.records` → 任务记录列表)
86
+
87
+ ---
88
+
89
+ ## 4. 核心逻辑
90
+
91
+ > 用自然语言 + 编号步骤,描述脚本的处理流程。重点描述:条件判断、数据转换、循环处理、错误处理等。
92
+
93
+ 1. 校验输入参数
94
+ 2. 查询数据表 / 调用外部接口
95
+ 3. 处理数据(过滤、转换、计算等)
96
+ 4. 写回数据表 / 返回结果
97
+
98
+ **条件分支(如有):**
99
+ - 当 XXX 时 → 执行 A 操作
100
+ - 当 YYY 时 → 执行 B 操作
101
+
102
+ **循环处理(如有):**
103
+ - 遍历查询结果,对每条记录执行 ...
104
+
105
+ ---
106
+
107
+ ## 5. 输出结果
108
+
109
+ > 描述脚本最终 return 的内容。
110
+
111
+ | 场景 | 返回值 | 类型 |
112
+ |------|--------|------|
113
+ | 成功 | (例:查询到的数据列表) | object / array / string |
114
+ | 无数据 | (例:`"No data found for ..."` 提示信息) | string |
115
+ | 异常 | (例:`"Error: 错误信息"`) | string |
116
+
117
+ ---
118
+
119
+ ## 6. 备注(可选)
120
+
121
+ - (任何补充说明、注意事项、性能要求等)