@huanban/rulego-editor-core 1.4.1 → 2.0.0

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 (157) hide show
  1. package/README.md +20 -8
  2. package/dist/ai/ai-chat-options.d.ts +12 -0
  3. package/dist/api/AIAssistantAPI.d.ts +29 -0
  4. package/dist/api/AIManager.d.ts +7 -1
  5. package/dist/api/ApiProvider.d.ts +17 -4
  6. package/dist/api/DebugSocketClient.d.ts +2 -0
  7. package/dist/api/GlobalConfigAPI.d.ts +35 -0
  8. package/dist/api/IoTPointTemplateAPI.d.ts +32 -0
  9. package/dist/api/MarketplaceAPI.d.ts +39 -0
  10. package/dist/api/RuleChainAPI.d.ts +23 -4
  11. package/dist/api/RuleChainVersionsAPI.d.ts +28 -0
  12. package/dist/api/SkillsAPI.d.ts +31 -0
  13. package/dist/api/UserAPI.d.ts +39 -0
  14. package/dist/api/extended-api-shared.d.ts +25 -0
  15. package/dist/api/index.d.ts +19 -2
  16. package/dist/api/public-api.test-d.d.ts +87 -0
  17. package/dist/api/response-utils.d.ts +1 -0
  18. package/dist/api/types.d.ts +86 -14
  19. package/dist/chunks/editor-core-api-BQiYFuIO.js +1157 -0
  20. package/dist/chunks/editor-core-canvas-nodes-BE9eN51s.js +6921 -0
  21. package/dist/chunks/editor-core-code-editor-DFm5Owtv.js +660 -0
  22. package/dist/chunks/{editor-core-default-components-BjF65lar.js → editor-core-default-components-BsNP8ma1.js} +98 -98
  23. package/dist/chunks/editor-core-dialogs-D9YHvzys.js +12009 -0
  24. package/dist/chunks/{editor-core-locales-i6o28vm2.js → editor-core-locales-CsqTh7Wh.js} +1723 -11
  25. package/dist/chunks/{editor-core-node-patches-BJTT3TuX.js → editor-core-node-patches-Dbi8XYxu.js} +633 -184
  26. package/dist/chunks/{editor-core-node-views-BOaPVdmN.js → editor-core-node-views-C8FQYC3E.js} +39 -29
  27. package/dist/chunks/editor-core-property-drawers-Bqmp9B_J.js +9562 -0
  28. package/dist/chunks/editor-core-settings-DcGCJSc7.js +4161 -0
  29. package/dist/chunks/editor-core-standalone-C7pzm8ZB.js +10013 -0
  30. package/dist/chunks/{editor-core-styles-C1TbLgCK.js → editor-core-styles-CwjFPfAo.js} +1203 -507
  31. package/dist/chunks/vendor-highlight-acC2fLd8.js +5868 -0
  32. package/dist/chunks/vendor-logicflow-core-runtime-DpsWXOGl.js +4 -0
  33. package/dist/chunks/vendor-logicflow-shared-C_kIdBKO.js +4 -0
  34. package/dist/core/ActionRegistry.d.ts +4 -2
  35. package/dist/core/DataAdapter.d.ts +17 -1
  36. package/dist/core/DialogProvider.d.ts +33 -0
  37. package/dist/core/EditorCore.d.ts +16 -3
  38. package/dist/core/FieldCapabilityRegistry.d.ts +4 -1
  39. package/dist/core/FieldChangeRegistry.d.ts +3 -1
  40. package/dist/core/I18nManager.d.ts +1 -1
  41. package/dist/core/IdentityProvider.d.ts +32 -0
  42. package/dist/core/OptionSourceRegistry.d.ts +4 -1
  43. package/dist/core/PropertyControlRegistry.d.ts +29 -0
  44. package/dist/core/ThemeManager.d.ts +7 -0
  45. package/dist/core/anchored-popover.d.ts +16 -0
  46. package/dist/core/assistant-dsl.d.ts +18 -0
  47. package/dist/core/business-log-config.d.ts +18 -0
  48. package/dist/core/clean-snapshot.d.ts +14 -0
  49. package/dist/core/component-localization.d.ts +17 -0
  50. package/dist/core/component-palette.d.ts +3 -0
  51. package/dist/core/connection-status.d.ts +11 -0
  52. package/dist/core/dialog-styles.d.ts +1 -0
  53. package/dist/core/editor-capabilities.d.ts +82 -1
  54. package/dist/core/editor-edge-anchors.d.ts +16 -0
  55. package/dist/core/endpoint-protocol.d.ts +15 -0
  56. package/dist/core/expression-preview.d.ts +6 -0
  57. package/dist/core/field-protocol.d.ts +19 -4
  58. package/dist/core/global-config.d.ts +47 -0
  59. package/dist/core/global-search.d.ts +31 -0
  60. package/dist/core/group-protocol.d.ts +56 -0
  61. package/dist/core/identity-provider-default.d.ts +32 -0
  62. package/dist/core/index.d.ts +31 -5
  63. package/dist/core/keymap.d.ts +10 -0
  64. package/dist/core/payload-kv.d.ts +7 -0
  65. package/dist/core/rule-chain-versions.d.ts +143 -0
  66. package/dist/core/run-analysis.d.ts +126 -0
  67. package/dist/core/runtime-field-dictionary.d.ts +3 -0
  68. package/dist/core/save-conflict.d.ts +1 -0
  69. package/dist/core/server-status.d.ts +1 -0
  70. package/dist/core/toolbar-icons.d.ts +1 -1
  71. package/dist/core/variable-completion.d.ts +13 -0
  72. package/dist/core/websocket-auth.d.ts +2 -0
  73. package/dist/defaults/analysis-locales.d.ts +241 -0
  74. package/dist/defaults/component-locale-categories.d.ts +14 -0
  75. package/dist/defaults/component-locale-data.d.ts +4 -0
  76. package/dist/defaults/component-locale-en-US.d.ts +10 -0
  77. package/dist/defaults/component-locale-summaries.d.ts +15 -0
  78. package/dist/defaults/component-locale-zh-CN.d.ts +10 -0
  79. package/dist/defaults/editor-shell-locales.d.ts +290 -0
  80. package/dist/defaults/example-chain.d.ts +2 -0
  81. package/dist/defaults/field-interaction-locales.d.ts +19 -0
  82. package/dist/defaults/global-config-locales.d.ts +166 -0
  83. package/dist/defaults/official-component-fallbacks.d.ts +2 -1
  84. package/dist/defaults/point-template-locales.d.ts +64 -0
  85. package/dist/index.cjs +2897 -2115
  86. package/dist/index.d.ts +33 -10
  87. package/dist/index.esm.js +1184 -809
  88. package/dist/index.umd.js +2874 -2092
  89. package/dist/nodes/UnknownNodeModel.d.ts +12 -1
  90. package/dist/standalone/HuanbanRulegoEditor.d.ts +145 -13
  91. package/dist/standalone/auth-fetch.d.ts +1 -0
  92. package/dist/standalone/auth-ui-defaults.d.ts +15 -0
  93. package/dist/standalone/code-editor.d.ts +7 -5
  94. package/dist/standalone/connection-status-binding.d.ts +3 -2
  95. package/dist/standalone/custom-nodes.d.ts +13 -0
  96. package/dist/standalone/drawer-locale.d.ts +12 -0
  97. package/dist/standalone/drawer-unsaved-guard.d.ts +6 -1
  98. package/dist/standalone/dynamic-field-browse.d.ts +25 -0
  99. package/dist/standalone/edge-label-quick-editor.d.ts +2 -1
  100. package/dist/standalone/editor-actions.d.ts +1 -0
  101. package/dist/standalone/editor-canvas-anchors.d.ts +19 -0
  102. package/dist/standalone/editor-canvas-shortcuts.d.ts +1 -0
  103. package/dist/standalone/editor-chain-info.d.ts +1 -0
  104. package/dist/standalone/editor-debug-data.d.ts +18 -0
  105. package/dist/standalone/editor-debug-ws.d.ts +2 -0
  106. package/dist/standalone/editor-delete.d.ts +5 -3
  107. package/dist/standalone/editor-dialog-provider.d.ts +3 -0
  108. package/dist/standalone/editor-dialogs.d.ts +25 -2
  109. package/dist/standalone/editor-global-config.d.ts +44 -0
  110. package/dist/standalone/editor-group-interactions.d.ts +1 -0
  111. package/dist/standalone/editor-host-region-styles.d.ts +1 -0
  112. package/dist/standalone/editor-host-regions.d.ts +53 -0
  113. package/dist/standalone/editor-login.d.ts +15 -0
  114. package/dist/standalone/editor-overlays.d.ts +5 -0
  115. package/dist/standalone/editor-property-drawers.d.ts +3 -1
  116. package/dist/standalone/editor-run-analysis.d.ts +81 -0
  117. package/dist/standalone/editor-run-compare.d.ts +20 -0
  118. package/dist/standalone/editor-run-waterfall.d.ts +11 -0
  119. package/dist/standalone/editor-toast.d.ts +1 -1
  120. package/dist/standalone/editor-toolbar-presentation.d.ts +12 -0
  121. package/dist/standalone/editor-toolbar.d.ts +5 -1
  122. package/dist/standalone/editor-ui-configuration.d.ts +55 -0
  123. package/dist/standalone/editor-ui-settings.d.ts +26 -0
  124. package/dist/standalone/editor-user-menu.d.ts +8 -0
  125. package/dist/standalone/editor-version-history.d.ts +82 -0
  126. package/dist/standalone/editor-workspace-shell.d.ts +47 -0
  127. package/dist/standalone/editor-workspace-styles.d.ts +1 -0
  128. package/dist/standalone/field-expression-preview.d.ts +12 -0
  129. package/dist/standalone/group-node.d.ts +19 -3
  130. package/dist/standalone/icon-utils.d.ts +7 -0
  131. package/dist/standalone/index.d.ts +17 -5
  132. package/dist/standalone/keyboard-events.d.ts +3 -0
  133. package/dist/standalone/multi-select-popover.d.ts +16 -0
  134. package/dist/standalone/node-copy.d.ts +1 -0
  135. package/dist/standalone/node-definitions.d.ts +4 -0
  136. package/dist/standalone/node-renderer-utils.d.ts +21 -0
  137. package/dist/standalone/node-theme.d.ts +2 -1
  138. package/dist/standalone/point-template-actions.d.ts +43 -0
  139. package/dist/standalone/property-field-draft.d.ts +5 -0
  140. package/dist/standalone/question-list-editor.d.ts +35 -0
  141. package/dist/standalone/shared-node-manager.d.ts +14 -0
  142. package/dist/standalone/single-select-popover.d.ts +6 -0
  143. package/dist/standalone/theme-scope.d.ts +15 -0
  144. package/dist/standalone/themes.d.ts +8 -0
  145. package/dist/standalone/variable-completion-dropdown.d.ts +18 -0
  146. package/dist/types/component.d.ts +24 -1
  147. package/dist/types/editor.d.ts +41 -0
  148. package/dist/utils/relation-utils.d.ts +19 -1
  149. package/dist/version.d.ts +2 -2
  150. package/package.json +3 -3
  151. package/vite-chunks.mjs +66 -0
  152. package/dist/chunks/editor-core-code-editor-CRki2wA_.js +0 -512
  153. package/dist/chunks/editor-core-dialogs-BMWb0WRN.js +0 -17228
  154. package/dist/chunks/editor-core-property-drawers-BPh-jj1b.js +0 -7998
  155. package/dist/chunks/editor-core-standalone-CJDytHO9.js +0 -11269
  156. package/dist/chunks/vendor-logicflow-core-runtime-Cp6IBEjB.js +0 -217
  157. package/dist/chunks/vendor-logicflow-shared-C7YynLDn.js +0 -4
@@ -1,10 +1,10 @@
1
- const S = [
1
+ const _ = [
2
2
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
3
3
  { name: "addr", label: "对象地址", type: "string", rules: [{ required: !0, message: "必填" }], desc: "对象类型:实例[:属性],如 analog-input:0、ai:1:description" },
4
4
  { name: "type", label: "类型", component: { type: "select", filterable: !0, allowCreate: !0, options: [{ label: "(自动,按响应)", value: "" }] }, desc: "可选,读取时类型由响应自带" },
5
5
  { name: "scale", label: "倍率", type: "number", desc: "工程量 scale,0=不缩放" },
6
6
  { name: "offset", label: "偏移", type: "number", desc: "工程量 offset" }
7
- ], C = [
7
+ ], $ = [
8
8
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
9
9
  { name: "addr", label: "对象地址", type: "string", rules: [{ required: !0, message: "必填" }], desc: "对象类型:实例[:属性]" },
10
10
  { name: "type", label: "值类型", component: { type: "select", filterable: !0, options: [
@@ -17,17 +17,17 @@ const S = [
17
17
  { label: "UINT16 无符号", value: "UINT16" }
18
18
  ] }, rules: [{ required: !0, message: "必填" }] },
19
19
  { name: "value", label: "写入值", type: "string", rules: [{ required: !0, message: "必填" }] }
20
- ], m = [
20
+ ], h = [
21
21
  { name: "scale", label: "缩放系数", type: "string", desc: "eng = raw*scale + offset;示例: 原始值放大10倍存储时填 0.1(235→23.5),留空不缩放" },
22
22
  { name: "offset", label: "偏移量", type: "string", desc: "示例: -50(raw*0.01-50);仅平移时 scale 须显式填 1" }
23
- ], b = {
23
+ ], S = {
24
24
  transport: { label: "传输方式", component: { type: "select", options: [{ label: "UDP (默认)", value: "udp" }, { label: "TCP", value: "tcp" }] } },
25
25
  network: { label: "网络号", desc: "FINS 网络号(DA1),默认 0", group: "advanced" },
26
26
  dstNode: { label: "目标节点号", desc: "目标 FINS 节点号(DA2),默认 0", group: "advanced" },
27
27
  srcNode: { label: "源节点号", desc: "源 FINS 节点号(SA2),默认 0", group: "advanced" },
28
28
  unit: { label: "单元地址", desc: "单元地址(DA3),默认 0", group: "advanced" },
29
29
  timeout: { label: "超时(秒)", desc: "请求超时时间,默认 5" }
30
- }, x = [
30
+ }, M = [
31
31
  { label: "BOOL 位", value: "BOOL" },
32
32
  { label: "INT16", value: "INT16" },
33
33
  { label: "UINT16", value: "UINT16" },
@@ -38,23 +38,23 @@ const S = [
38
38
  { label: "UINT64", value: "UINT64" },
39
39
  { label: "FLOAT64", value: "FLOAT64" },
40
40
  { label: "STRING 字符串", value: "STRING" }
41
- ], i = [
41
+ ], f = [
42
42
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
43
43
  { name: "addr", label: "地址", type: "string", rules: [{ required: !0, message: "必填" }], desc: "如 DM100、CIO10.0、D100:20(字符串)" },
44
- { name: "type", label: "数据类型", component: { type: "select", filterable: !0, allowCreate: !1, options: x }, rules: [{ required: !0, message: "必填" }] },
44
+ { name: "type", label: "数据类型", component: { type: "select", filterable: !0, allowCreate: !1, options: M }, rules: [{ required: !0, message: "必填" }] },
45
45
  { name: "scale", label: "缩放系数", type: "number", desc: "eng = raw*scale + offset;留空不缩放" },
46
46
  { name: "offset", label: "偏移量", type: "number", desc: "仅平移时 scale 填 1" },
47
47
  { name: "endian", label: "字节序", component: { type: "select", options: [{ label: "ABCD", value: "ABCD" }, { label: "CDAB", value: "CDAB" }, { label: "BADC", value: "BADC" }, { label: "DCBA", value: "DCBA" }] }, desc: "多字类型生效;留空使用设备默认" }
48
- ], P = [
49
- ...i.slice(0, 3),
48
+ ], L = [
49
+ ...f.slice(0, 3),
50
50
  { name: "value", label: "写入值", type: "string", rules: [{ required: !0, message: "必填" }] },
51
- i[5]
52
- ], k = [
51
+ f[5]
52
+ ], B = [
53
53
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
54
54
  { name: "addr", label: "OID", type: "string", rules: [{ required: !0, message: "必填" }], desc: "如 1.3.6.1.2.1.1.5.0;支持 ${msg.xx}" },
55
55
  { name: "op", label: "操作", tableColumn: !1, addrPrefix: "walk:", defaultValue: "get", desc: "Walk 遍历子树返回多值", component: { type: "select", options: [{ label: "Get 精确读", value: "get" }, { label: "Walk 遍历子树", value: "walk" }] } },
56
- ...m
57
- ], w = [
56
+ ...h
57
+ ], U = [
58
58
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
59
59
  { name: "addr", label: "OID", type: "string", rules: [{ required: !0, message: "必填" }], desc: "如 1.3.6.1.2.1.1.6.0;支持 ${msg.xx}" },
60
60
  { name: "type", label: "值类型", component: { type: "select", filterable: !0, allowCreate: !1, options: [
@@ -68,10 +68,10 @@ const S = [
68
68
  { label: "Counter64", value: "Counter64" }
69
69
  ] }, rules: [{ required: !0, message: "必填" }], desc: "写入需明确数据类型" },
70
70
  { name: "value", label: "写入值", type: "string", rules: [{ required: !0, message: "必填" }], desc: "支持 ${msg.xx}" }
71
- ], g = {
71
+ ], D = {
72
72
  commonAddr: { label: "公共地址(CA)", desc: "ASDU 站址,默认 1" },
73
73
  timeout: { label: "超时(秒)", desc: "默认 5" }
74
- }, q = [
74
+ }, V = [
75
75
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
76
76
  { name: "addr", label: "IOA", type: "string", rules: [{ required: !0, message: "必填" }], desc: "信息体地址,如 100(遥信)、16385(遥测)" },
77
77
  { name: "type", label: "类型标识", component: { type: "select", filterable: !0, allowCreate: !1, options: [
@@ -82,8 +82,8 @@ const S = [
82
82
  { label: "M_ME_NC_1 短浮点遥测", value: "M_ME_NC_1" },
83
83
  { label: "M_IT_NA_1 累积量", value: "M_IT_NA_1" }
84
84
  ] }, desc: "可选,仅说明用途" },
85
- ...m
86
- ], I = [
85
+ ...h
86
+ ], W = [
87
87
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
88
88
  { name: "addr", label: "IOA", type: "string", rules: [{ required: !0, message: "必填" }], desc: "信息体地址" },
89
89
  { name: "type", label: "命令类型", component: { type: "select", filterable: !0, allowCreate: !1, options: [
@@ -93,43 +93,77 @@ const S = [
93
93
  { label: "短浮点设点 C_SE_NC_1", value: "C_SE_NC_1" }
94
94
  ] }, rules: [{ required: !0, message: "必填" }] },
95
95
  { name: "value", label: "命令值", type: "string", rules: [{ required: !0, message: "必填" }], desc: "单命令 true/false;双命令 1/2;设点为数值" }
96
- ], p = [
96
+ ], w = [
97
97
  { name: "name", label: "表名", type: "string", rules: [{ required: !0, message: "必填" }] },
98
- { name: "source", label: "数据来源", component: { type: "select", options: [{ label: "文件", value: "file" }, { label: "HTTP", value: "http" }] } },
99
- { name: "path", label: "文件路径/URL", type: "string", desc: "file 为本地路径;http 为 GET 地址" },
100
- { name: "format", label: "格式", component: { type: "select", options: [{ label: "JSON", value: "json" }, { label: "CSV", value: "csv" }] } },
101
- { name: "refresh", label: "刷新间隔", type: "string", desc: "如 30s;空=默认 1 小时刷新" },
102
- { name: "headers", label: "HTTP请求头", type: "string", desc: '仅 HTTP;JSON 格式,如 {"X-Token":"xxx"}', dependsOn: { field: "source", operator: "eq", value: "http" } },
103
- { name: "timeout", label: "HTTP超时", type: "string", desc: "仅 HTTP;如 10s,默认 10s", dependsOn: { field: "source", operator: "eq", value: "http" } }
104
- ], l = (e) => ({
98
+ { name: "source", label: "数据来源", defaultValue: "inline", component: { type: "select", options: [{ label: "内联", value: "inline" }, { label: "文件", value: "file" }, { label: "HTTP", value: "http" }] } },
99
+ { name: "rows", label: "内联数据(JSON 数组)", type: "array", tableColumn: !1, jsonText: !0, desc: 'JSON 数组,每个元素是一行,如 [{"deviceId":"d1","temp":80}]', component: { type: "textarea" }, dependsOn: { field: "source", operator: "in", value: ["inline"] } },
100
+ { name: "path", label: "文件路径/URL", type: "string", desc: "file 为本地路径;http 为 GET 地址", dependsOn: { field: "source", operator: "in", value: ["file", "http"] } },
101
+ { name: "format", label: "格式", tableColumn: !1, dependsOn: { field: "source", operator: "in", value: ["file", "http"] }, component: { type: "select", options: [{ label: "JSON", value: "json" }, { label: "CSV", value: "csv" }] } },
102
+ { name: "refresh", label: "刷新间隔", type: "string", tableColumn: !1, desc: "如 30s;空=默认 1 小时刷新", dependsOn: { field: "source", operator: "in", value: ["file", "http"] } },
103
+ { name: "headers", label: "HTTP请求头", type: "string", tableColumn: !1, desc: '仅 HTTP;JSON 格式,如 {"X-Token":"xxx"}', dependsOn: { field: "source", operator: "eq", value: "http" } },
104
+ { name: "timeout", label: "HTTP超时", type: "string", tableColumn: !1, desc: "仅 HTTP;如 10s,默认 10s", dependsOn: { field: "source", operator: "eq", value: "http" } }
105
+ ], k = {
106
+ url: { label: "API地址", desc: "System One 端点", type: "string", defaultValue: "https://api.typesafe.ai/v1/systemone" },
107
+ key: { label: "API密钥", desc: "支持 ${global.xxx} 模板", type: "string", component: { type: "password" } },
108
+ model: { label: "模型", type: "string", defaultValue: "jev-latest", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1, options: [{ label: "jev-latest", value: "jev-latest" }] } },
109
+ input: { label: "输入表达式", desc: "支持 ${msg.key} 和 ${metadata.key},为空时使用消息体数据", type: "string" }
110
+ }, P = [
111
+ { label: "多选一(按胜出选项连线)", value: "choice" },
112
+ { label: "是否(True/False 两条线)", value: "noul" },
113
+ { label: "程度分级(按最接近档位连线)", value: "score" }
114
+ ], I = [
115
+ { name: "name", label: "选项名", type: "string", desc: "同时作为路由连接类型", rules: [{ required: !0, message: "该项是必须的" }] },
116
+ { name: "description", label: "选项描述", type: "string", desc: "描述选项的含义,帮助模型判断", component: { type: "textarea" } }
117
+ ], r = (e) => ({
105
118
  type: "select",
106
119
  filterable: !0,
107
120
  allowCreate: !1,
108
121
  multiple: !1,
109
122
  options: e
110
- }), s = [
123
+ }), n = [
111
124
  { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
112
125
  { name: "addr", label: "地址", type: "string", rules: [{ required: !0, message: "必填" }] },
113
126
  { name: "type", label: "数据类型", component: { type: "select", filterable: !0, allowCreate: !0 } },
114
127
  { name: "scale", label: "缩放系数", type: "string", desc: "工程量 = 原始值 × scale + offset;留空不缩放" },
115
128
  { name: "offset", label: "偏移量", type: "string", desc: "仅平移时 scale 须显式填 1" }
116
- ], o = [
117
- ...s.slice(0, 3),
129
+ ], c = [
130
+ ...n.slice(0, 3),
118
131
  { name: "value", label: "写入值", type: "string", rules: [{ required: !0, message: "必填" }], desc: "支持 ${msg.xx}/${metadata.xx} 模板" }
119
- ], y = (e = s, t = "默认点位表;若 msg.Data 带点位列表则优先使用") => ({
132
+ ], m = (e = n, l = "默认点位表;若 msg.Data 带点位列表则优先使用") => ({
120
133
  label: "点位表",
121
- desc: t,
134
+ desc: l,
122
135
  component: { type: "table", options: e }
123
- }), r = (e = "服务器地址", t = "支持 host:port 或后端协议要求的地址格式") => ({
136
+ }), i = (e = "服务器地址", l = "支持 host:port 或后端协议要求的地址格式") => ({
124
137
  ref: "primary",
125
138
  label: e,
126
- desc: t,
139
+ desc: l,
127
140
  rules: [{ required: !0, message: "必填" }],
128
141
  component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 }
129
- }), v = { label: "请求超时(秒)", desc: "默认 5 秒" }, f = {
142
+ }), p = { label: "请求超时(秒)", desc: "默认 5 秒" }, b = {
143
+ sessionKey: {
144
+ type: "string",
145
+ label: "会话Key",
146
+ desc: "设备寻址键,留空使用 RemoteAddr;支持 ${msg.deviceId} 等表达式",
147
+ component: { type: "input" },
148
+ placeholder: "${msg.deviceId}"
149
+ },
150
+ sessionTTL: {
151
+ type: "int",
152
+ label: "会话空闲超时(秒)",
153
+ desc: "空闲超过此值关闭连接;0或留空默认1800秒",
154
+ placeholder: "1800"
155
+ }
156
+ }, g = [
157
+ { name: "name", label: "名称", type: "string", rules: [{ required: !0, message: "必填" }] },
158
+ { name: "addr", label: "NodeID", type: "string", rules: [{ required: !0, message: "必填" }], desc: "如 ns=2;s=Temperature;支持 ${msg.xx}" },
159
+ { name: "type", label: "数据类型", type: "string", component: r(
160
+ ["BOOL", "INT16", "UINT16", "INT32", "UINT32", "INT64", "UINT64", "FLOAT32", "FLOAT64", "STRING"].map((e) => ({ label: e, value: e }))
161
+ ) }
162
+ ], O = {
130
163
  tcpConfig: {
131
164
  label: "TCP配置",
132
165
  group: "advanced",
166
+ dependsOn: { field: "server", operator: "prefix", value: "tcp" },
133
167
  timeout: { label: "超时时间(秒)", desc: "TCP 请求超时" },
134
168
  certFile: { label: "证书文件", desc: "TLS 客户端证书文件路径" },
135
169
  certKeyFile: { label: "密钥文件", desc: "TLS 客户端私钥文件路径" },
@@ -139,14 +173,14 @@ const S = [
139
173
  label: "RTU配置",
140
174
  group: "advanced",
141
175
  dependsOn: { field: "server", operator: "prefix", value: "rtu:" },
142
- speed: { label: "串行波特率", component: l([
176
+ speed: { label: "串行波特率", component: r([
143
177
  { label: "4800", value: 4800 },
144
178
  { label: "9600", value: 9600 },
145
179
  { label: "19200", value: 19200 },
146
180
  { label: "38400", value: 38400 }
147
181
  ]) },
148
182
  dataBits: { label: "数据位" },
149
- parity: { label: "校验位", component: l([
183
+ parity: { label: "校验位", component: r([
150
184
  { label: "无校验", value: "N" },
151
185
  { label: "偶校验", value: "E" },
152
186
  { label: "奇校验", value: "O" }
@@ -156,24 +190,24 @@ const S = [
156
190
  encodingConfig: {
157
191
  label: "编码配置",
158
192
  group: "advanced",
159
- endianness: { label: "字节序", component: l([{ label: "大端序", value: 1 }, { label: "小端序", value: 2 }]) },
160
- wordOrder: { label: "字序", component: l([{ label: "高字在前", value: 1 }, { label: "低字在前", value: 2 }]) }
193
+ endianness: { label: "字节序", component: r([{ label: "大端序", value: 1 }, { label: "小端序", value: 2 }]) },
194
+ wordOrder: { label: "字序", component: r([{ label: "高字在前", value: 1 }, { label: "低字在前", value: 2 }]) }
161
195
  }
162
- }, n = {
163
- version: { label: "SNMP版本", component: l([
196
+ }, T = {
197
+ version: { label: "SNMP版本", component: r([
164
198
  { label: "v1", value: "v1" },
165
199
  { label: "v2c", value: "v2c" },
166
200
  { label: "v3", value: "v3" }
167
201
  ]) },
168
202
  community: { label: "团体字", desc: "v1/v2c 使用;v3 时不需要", dependsOn: { field: "version", operator: "ne", value: "v3" } },
169
- timeout: v,
170
- securityLevel: { label: "安全级别(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: l([
203
+ timeout: p,
204
+ securityLevel: { label: "安全级别(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: r([
171
205
  { label: "noAuthNoPriv", value: "noAuthNoPriv" },
172
206
  { label: "authNoPriv", value: "authNoPriv" },
173
207
  { label: "authPriv", value: "authPriv" }
174
208
  ]) },
175
209
  username: { label: "用户名(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" } },
176
- authProtocol: { label: "认证协议(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: l([
210
+ authProtocol: { label: "认证协议(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: r([
177
211
  { label: "None", value: "None" },
178
212
  { label: "MD5", value: "MD5" },
179
213
  { label: "SHA", value: "SHA" },
@@ -181,14 +215,14 @@ const S = [
181
215
  { label: "SHA512", value: "SHA512" }
182
216
  ]) },
183
217
  authPassword: { label: "认证密码(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: { type: "password" } },
184
- privProtocol: { label: "加密协议(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: l([
218
+ privProtocol: { label: "加密协议(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: r([
185
219
  { label: "None", value: "None" },
186
220
  { label: "DES", value: "DES" },
187
221
  { label: "AES", value: "AES" },
188
222
  { label: "AES256", value: "AES256" }
189
223
  ]) },
190
224
  privPassword: { label: "加密密码(v3)", dependsOn: { field: "version", operator: "eq", value: "v3" }, component: { type: "password" } }
191
- }, T = {
225
+ }, C = {
192
226
  measurement: { label: "测点表名(可选)", desc: "配置后可把采集点数组映射为时序数据;支持 ${msg.xx}/${metadata.xx}" },
193
227
  tags: {
194
228
  label: "Tags(可选)",
@@ -206,17 +240,46 @@ const S = [
206
240
  { name: "source", label: "采集点字段名", type: "string" }
207
241
  ] }
208
242
  }
209
- }, A = {
243
+ }, v = {
210
244
  label: "驱动后端",
211
245
  rules: [{ required: !0, message: "必填" }],
212
- component: l([
246
+ component: r([
213
247
  { label: "OpenGemini", value: "opengemini" },
214
248
  { label: "InfluxDB", value: "influxdb" },
215
249
  { label: "TDengine", value: "tdengine" },
216
250
  { label: "TimescaleDB", value: "timescaledb" },
217
251
  { label: "Prometheus Remote Write", value: "promremote" }
218
252
  ])
219
- }, a = {
253
+ };
254
+ function K(e) {
255
+ const l = (...s) => ({ field: "driver", operator: "in", value: s }), a = (s, u) => ({
256
+ type: "string",
257
+ label: s,
258
+ dependsOn: l(...u),
259
+ rules: [{ required: !0, message: "必填" }]
260
+ });
261
+ return {
262
+ server: { ...i("服务地址", "host:port,多个地址用英文逗号分隔"), refNodes: ["x/opengeminiWrite"], dependsOn: l("opengemini") },
263
+ database: a("数据库", ["opengemini"]),
264
+ username: { type: "string", label: "用户名", dependsOn: l("opengemini") },
265
+ password: { type: "string", label: "密码", component: { type: "password" }, dependsOn: l("opengemini") },
266
+ token: { type: "string", label: "Token", component: { type: "password" }, dependsOn: l("opengemini", "influxdb") },
267
+ url: {
268
+ ...i("服务地址", "InfluxDB: http://host:8086;PromRemote: HTTP Remote Write 地址"),
269
+ refNodes: e ? ["x/influxdbWrite", "x/promremoteWrite"] : ["x/influxdbWrite"],
270
+ dependsOn: l(...e ? ["influxdb", "promremote"] : ["influxdb"])
271
+ },
272
+ bucket: a("Bucket", ["influxdb"]),
273
+ org: a("Org", ["influxdb"]),
274
+ dsn: {
275
+ ...i("DSN", "TDengine: root:taosdata@http(host:6041)/;TimescaleDB: PostgreSQL 连接串"),
276
+ refNodes: ["x/tdengineWrite", "x/timescaledbWrite"],
277
+ dependsOn: l("tdengine", "timescaledb")
278
+ },
279
+ db: a("数据库/Schema", ["tdengine", "timescaledb"])
280
+ };
281
+ }
282
+ const o = {
220
283
  "endpoint/snmp": {
221
284
  category: "iot/input-endpoint",
222
285
  notInput: !0,
@@ -224,9 +287,9 @@ const S = [
224
287
  label: "SNMP Trap",
225
288
  icon: "/images/endpoint.svg",
226
289
  desc: "监听 SNMP Trap/Inform 告警并流入规则链。",
227
- server: r("监听地址", "示例: 0.0.0.0:162"),
228
- version: n.version,
229
- community: n.community,
290
+ server: i("监听地址", "示例: 0.0.0.0:162"),
291
+ version: T.version,
292
+ community: T.community,
230
293
  router: { hide: !0 }
231
294
  },
232
295
  "endpoint/modbusServer": {
@@ -236,7 +299,7 @@ const S = [
236
299
  label: "Modbus从站",
237
300
  icon: "/images/modbus.svg",
238
301
  desc: "监听 Modbus TCP 主站连接并把写入事件送入规则链。",
239
- server: r("监听地址", "格式 tcp://host:port"),
302
+ server: i("监听地址", "格式 tcp://host:port"),
240
303
  unitId: { label: "从站地址", desc: "0 表示接受所有主站请求" },
241
304
  maxClients: { label: "最大并发连接数", group: "advanced" },
242
305
  coils: { label: "线圈区大小", group: "advanced" },
@@ -250,7 +313,7 @@ const S = [
250
313
  label: "HJ212接收",
251
314
  icon: "/images/endpoint.svg",
252
315
  desc: "接收 HJ212-2017 污染源在线监控设备上报的数据帧。",
253
- server: r("监听地址", "示例: 0.0.0.0:8005"),
316
+ server: i("监听地址", "示例: 0.0.0.0:8005"),
254
317
  router: { hide: !0 }
255
318
  },
256
319
  ws: {
@@ -258,13 +321,13 @@ const S = [
258
321
  label: "WebSocket发送",
259
322
  icon: "/images/net.svg",
260
323
  desc: "通过 WebSocket 连接或 endpoint/ws 会话发送消息。",
261
- server: r("服务地址", "ws://host:port,或 ref:// 指向 WebSocket 输入端点"),
324
+ server: i("服务地址", "ws://host:port,或 ref:// 指向 WebSocket 输入端点"),
262
325
  target: { label: "目标会话", desc: "ref:// 模式下生效;支持 IP、deviceId、* 和 ${metadata.xxx}" },
263
326
  headers: { label: "请求头", desc: "握手 HTTP Header", component: { type: "json-editor" } },
264
327
  subprotocol: { label: "子协议", desc: "Sec-WebSocket-Protocol" },
265
328
  connectTimeout: { label: "连接超时(秒)" },
266
329
  insecureSkipVerify: { label: "跳过 TLS 校验", component: { type: "switch" } },
267
- messageType: { label: "消息类型", component: l([{ label: "文本", value: "text" }, { label: "二进制", value: "binary" }]) },
330
+ messageType: { label: "消息类型", component: r([{ label: "文本", value: "text" }, { label: "二进制", value: "binary" }]) },
268
331
  heartbeatInterval: { label: "心跳间隔(秒)", desc: "0 表示关闭心跳和重连" }
269
332
  },
270
333
  "x/control/timer": {
@@ -272,7 +335,7 @@ const S = [
272
335
  label: "控制定时器",
273
336
  icon: "/images/modbus.svg",
274
337
  desc: "输入持续满足预设时间后输出状态变化。",
275
- mode: { label: "模式", rules: [{ required: !0, message: "必填" }], component: l([{ label: "TON 延时接通", value: "TON" }, { label: "TOF 延时断开", value: "TOF" }]) },
338
+ mode: { label: "模式", rules: [{ required: !0, message: "必填" }], component: r([{ label: "TON 延时接通", value: "TON" }, { label: "TOF 延时断开", value: "TOF" }]) },
276
339
  pt: { label: "预设时间", rules: [{ required: !0, message: "必填" }], desc: "如 3s,支持 ${metadata.xx}" },
277
340
  in: { label: "输入模板", desc: "如 ${metadata.start};留空取 msg.Data" },
278
341
  out: { label: "输出键", desc: "写入 metadata 的键,默认 q" }
@@ -285,74 +348,117 @@ const S = [
285
348
  timeout: { label: "喂狗超时", rules: [{ required: !0, message: "必填" }], desc: "如 10s,支持 ${metadata.xx}" },
286
349
  failsafe: { label: "故障安全值(JSON)", rules: [{ required: !0, message: "必填" }], component: { type: "json-editor" } }
287
350
  },
288
- "x/iotRead": { category: "iot/protocol-acquisition", label: "通用协议读", icon: "/images/modbus.svg", desc: "按 driver 选择工业协议读取实现。", driver: { label: "采集驱动", rules: [{ required: !0, message: "必填" }], component: l([{ label: "Modbus", value: "modbus" }, { label: "S7", value: "s7" }, { label: "EIP", value: "eip" }, { label: "SNMP", value: "snmp" }, { label: "OPC UA", value: "opcua" }, { label: "MC", value: "mc" }, { label: "FINS", value: "fins" }, { label: "DLT645", value: "dlt645" }, { label: "IEC104", value: "iec104" }, { label: "BACnet", value: "bacnet" }]) } },
289
- "x/iotWrite": { category: "iot/protocol-acquisition", label: "通用协议写", icon: "/images/modbus.svg", desc: "按 driver 选择工业协议写入实现。", driver: { label: "写入驱动", rules: [{ required: !0, message: "必填" }], component: l([{ label: "Modbus", value: "modbus" }, { label: "S7", value: "s7" }, { label: "EIP", value: "eip" }, { label: "SNMP", value: "snmp" }, { label: "MC", value: "mc" }, { label: "FINS", value: "fins" }, { label: "DLT645", value: "dlt645" }, { label: "IEC104", value: "iec104" }, { label: "BACnet", value: "bacnet" }]) } }
351
+ "x/iotRead": {
352
+ category: "iot/protocol-acquisition",
353
+ label: "通用协议读",
354
+ icon: "/images/modbus.svg",
355
+ desc: "按 driver 选择工业协议读取实现。",
356
+ driver: { label: "采集驱动", rules: [{ required: !0, message: "必填" }], component: r([{ label: "Modbus", value: "modbus" }, { label: "S7", value: "s7" }, { label: "EIP", value: "eip" }, { label: "SNMP", value: "snmp" }, { label: "OPC UA", value: "opcua" }, { label: "MC", value: "mc" }, { label: "FINS", value: "fins" }, { label: "DLT645", value: "dlt645" }, { label: "IEC104", value: "iec104" }, { label: "BACnet", value: "bacnet" }]) },
357
+ dynamicFields: { by: "driver", refs: {
358
+ modbus: "x/modbusRead",
359
+ s7: "x/s7Read",
360
+ eip: "x/eipRead",
361
+ snmp: "x/snmpRead",
362
+ opcua: "x/opcuaRead",
363
+ mc: "x/mcRead",
364
+ fins: "x/finsRead",
365
+ dlt645: "x/dlt645Read",
366
+ iec104: "x/iec104Read",
367
+ bacnet: "x/bacnetRead"
368
+ } }
369
+ },
370
+ "x/iotWrite": {
371
+ category: "iot/protocol-acquisition",
372
+ label: "通用协议写",
373
+ icon: "/images/modbus.svg",
374
+ desc: "按 driver 选择工业协议写入实现。",
375
+ driver: { label: "写入驱动", rules: [{ required: !0, message: "必填" }], component: r([{ label: "Modbus", value: "modbus" }, { label: "S7", value: "s7" }, { label: "EIP", value: "eip" }, { label: "SNMP", value: "snmp" }, { label: "OPC UA", value: "opcua" }, { label: "MC", value: "mc" }, { label: "FINS", value: "fins" }, { label: "DLT645", value: "dlt645" }, { label: "IEC104", value: "iec104" }, { label: "BACnet", value: "bacnet" }]) },
376
+ dynamicFields: { by: "driver", refs: {
377
+ modbus: "x/modbusWrite",
378
+ s7: "x/s7Write",
379
+ eip: "x/eipWrite",
380
+ snmp: "x/snmpWrite",
381
+ opcua: "x/opcuaWrite",
382
+ mc: "x/mcWrite",
383
+ fins: "x/finsWrite",
384
+ dlt645: "x/dlt645Write",
385
+ iec104: "x/iec104Write",
386
+ bacnet: "x/bacnetWrite"
387
+ } }
388
+ }
290
389
  };
291
- for (const [e, t, u] of [
292
- ["x/dlt645Read", "DLT645读", s],
293
- ["x/dlt645Write", "DLT645写", o],
294
- ["x/eipRead", "EtherNet/IP读", s],
295
- ["x/eipWrite", "EtherNet/IP写", o],
296
- ["x/iec104Read", "IEC104读", s],
297
- ["x/iec104Write", "IEC104写", o],
298
- ["x/mcRead", "MC协议读", s],
299
- ["x/mcWrite", "MC协议写", o],
300
- ["x/s7Read", "S7读", s],
301
- ["x/s7Write", "S7写", o],
302
- ["x/modbusRead", "Modbus点位读", s],
303
- ["x/modbusWrite", "Modbus点位写", o]
390
+ for (const [e, l, a] of [
391
+ ["x/dlt645Read", "DLT645读", n],
392
+ ["x/dlt645Write", "DLT645写", c],
393
+ ["x/eipRead", "EtherNet/IP读", n],
394
+ ["x/eipWrite", "EtherNet/IP写", c],
395
+ ["x/iec104Read", "IEC104读", n],
396
+ ["x/iec104Write", "IEC104写", c],
397
+ ["x/mcRead", "MC协议读", n],
398
+ ["x/mcWrite", "MC协议写", c],
399
+ ["x/s7Read", "S7读", n],
400
+ ["x/s7Write", "S7写", c],
401
+ ["x/modbusRead", "Modbus点位读", n],
402
+ ["x/modbusWrite", "Modbus点位写", c]
304
403
  ])
305
- a[e] = {
404
+ o[e] = {
306
405
  category: "iot/protocol-acquisition",
307
- label: t,
406
+ label: l,
308
407
  icon: "/images/modbus.svg",
309
408
  desc: "工业协议点位读写;msg.Data 点位列表优先于默认点位表。",
310
- server: r(),
311
- timeout: v,
312
- points: y(u)
409
+ server: i(),
410
+ timeout: p,
411
+ points: m(a)
313
412
  };
314
- Object.assign(a["x/eipRead"], { slot: { label: "CPU槽位", desc: "默认 0" }, path: { label: "CIP路径", group: "advanced" } });
315
- Object.assign(a["x/eipWrite"], { slot: { label: "CPU槽位", desc: "默认 0" }, path: { label: "CIP路径", group: "advanced" } });
316
- Object.assign(a["x/s7Read"], { rack: { label: "机架号", group: "advanced" }, slot: { label: "CPU槽位" } });
317
- Object.assign(a["x/s7Write"], { rack: { label: "机架号", group: "advanced" }, slot: { label: "CPU槽位" } });
318
- Object.assign(a["x/modbusRead"], { unitId: { label: "从机编号" }, ...f });
319
- Object.assign(a["x/modbusWrite"], { unitId: { label: "从机编号" }, ...f });
320
- Object.assign(a["x/iec104Read"], {
413
+ Object.assign(o["x/eipRead"], { slot: { label: "CPU槽位", desc: "默认 0" }, path: { label: "CIP路径", group: "advanced" } });
414
+ Object.assign(o["x/eipWrite"], { slot: { label: "CPU槽位", desc: "默认 0" }, path: { label: "CIP路径", group: "advanced" } });
415
+ Object.assign(o["x/s7Read"], { rack: { label: "机架号", group: "advanced" }, slot: { label: "CPU槽位" } });
416
+ Object.assign(o["x/s7Write"], { rack: { label: "机架号", group: "advanced" }, slot: { label: "CPU槽位" } });
417
+ Object.assign(o["x/modbusRead"], { unitId: { label: "从机编号" }, ...O });
418
+ Object.assign(o["x/modbusWrite"], { unitId: { label: "从机编号" }, ...O });
419
+ Object.assign(o["x/iec104Read"], {
321
420
  label: "IEC104读",
322
421
  icon: "/images/iot.svg",
323
422
  desc: "IEC 60870-5-104 总召唤批量采集子站遥信、遥测和遥脉。",
324
423
  server: { ref: "primary", refNodes: ["x/iec104Write"], label: "子站地址", rules: [{ required: !0, message: "必填" }], desc: "host:port,默认端口 2404", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
325
- ...g,
326
- points: { label: "采集点位表", desc: "addr=信息体地址(IOA)。若 msg.Data 带点位列表则优先使用。", component: { type: "table", options: q } }
424
+ ...D,
425
+ points: { label: "采集点位表", desc: "addr=信息体地址(IOA)。若 msg.Data 带点位列表则优先使用。", component: { type: "table", options: V } }
327
426
  });
328
- Object.assign(a["x/iec104Write"], {
427
+ Object.assign(o["x/iec104Write"], {
329
428
  label: "IEC104写",
330
429
  icon: "/images/iot-write.svg",
331
430
  desc: "IEC 104 遥控、遥调和设点命令写入子站。",
332
431
  server: { ref: "primary", refNodes: ["x/iec104Read"], label: "子站地址", rules: [{ required: !0, message: "必填" }], desc: "host:port,默认端口 2404", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
333
- ...g,
334
- points: { label: "控制点位表", desc: "type=命令类型,value=命令值。", component: { type: "table", options: I } }
432
+ ...D,
433
+ points: { label: "控制点位表", desc: "type=命令类型,value=命令值。", component: { type: "table", options: W } }
335
434
  });
336
435
  for (const e of ["x/snmpRead", "x/snmpWrite"])
337
- a[e] = {
436
+ o[e] = {
338
437
  category: "iot/protocol-acquisition",
339
438
  label: e.endsWith("Read") ? "SNMP读" : "SNMP写",
340
439
  icon: "/images/net.svg",
341
440
  desc: "通过 SNMP v1/v2c/v3 读写点位。",
342
- server: r(),
343
- ...n,
344
- points: y(e.endsWith("Read") ? k : w)
441
+ server: i(),
442
+ ...T,
443
+ points: m(e.endsWith("Read") ? B : U)
345
444
  };
346
- for (const [e, t, u] of [["x/tsdbWrite", "通用时序写", !0], ["x/tsdbQuery", "通用时序查", !1]])
347
- a[e] = {
445
+ for (const [e, l, a] of [["x/tsdbWrite", "通用时序写", !0], ["x/tsdbQuery", "通用时序查", !1]])
446
+ o[e] = {
348
447
  category: "iot/tsdb",
349
- label: t,
448
+ label: l,
350
449
  icon: "/images/db.svg",
351
- desc: "按驱动连接时序数据库;驱动为空时不虚构连接字段。",
352
- driver: A,
353
- ...u ? T : { query: { label: "查询语句", component: { type: "textarea", rows: 5 }, rules: [{ required: !0, message: "必填" }] } }
450
+ desc: "按驱动连接时序数据库。",
451
+ driver: { ...v, component: {
452
+ ...v.component,
453
+ options: v.component.options.filter((s) => a || s.value !== "promremote")
454
+ } },
455
+ ...K(a),
456
+ ...a ? C : {
457
+ command: { type: "string", label: "OpenGemini SQL", dependsOn: { field: "driver", operator: "eq", value: "opengemini" }, component: { type: "textarea", rows: 4 }, rules: [{ required: !0, message: "必填" }] },
458
+ query: { type: "string", label: "查询语句", dependsOn: { field: "driver", operator: "ne", value: "opengemini" }, component: { type: "textarea", rows: 4 }, rules: [{ required: !0, message: "必填" }] }
459
+ }
354
460
  };
355
- for (const [e, t, u, h] of [
461
+ for (const [e, l, a, s] of [
356
462
  ["x/influxdbWrite", "InfluxDB写", !1, !0],
357
463
  ["x/influxdbQuery", "InfluxDB查", !0, !1],
358
464
  ["x/tdengineWrite", "TDengine写", !1, !0],
@@ -361,20 +467,76 @@ for (const [e, t, u, h] of [
361
467
  ["x/timescaledbQuery", "TimescaleDB查", !0, !1],
362
468
  ["x/promremoteWrite", "Prometheus Remote Write", !1, !0]
363
469
  ]) {
364
- const c = e.startsWith("x/influxdb"), d = e.startsWith("x/tdengine");
365
- a[e] = {
470
+ const u = e.startsWith("x/influxdb"), y = e.startsWith("x/tdengine"), d = e.startsWith("x/timescaledb"), F = e === "x/promremoteWrite", E = e.replace(/(?:Write|Query)$/, s ? "Query" : "Write");
471
+ o[e] = {
366
472
  category: "iot/tsdb",
367
- label: t,
473
+ label: l,
368
474
  icon: "/images/db.svg",
369
475
  desc: "时序数据库连接与查询/写入节点。",
370
- [c ? "url" : d ? "dsn" : "url"]: r("服务地址", "按后端驱动填写连接地址"),
371
- ...c ? { bucket: { label: "Bucket" }, org: { label: "Org" }, token: { label: "Token", component: { type: "password" } } } : d ? { db: { label: "数据库" } } : {},
372
- ...u ? { query: { label: "查询语句", component: { type: "textarea", rows: 5 }, rules: [{ required: !0, message: "必填" }] } } : {},
373
- ...h ? T : {}
476
+ [y || d ? "dsn" : "url"]: {
477
+ ...i(y || d ? "DSN" : "服务地址", d ? "PostgreSQL 连接串" : "按后端驱动填写连接地址"),
478
+ ...F ? {} : { refNodes: [E] }
479
+ },
480
+ ...u ? {
481
+ bucket: { label: "Bucket", rules: [{ required: !0, message: "必填" }] },
482
+ org: { label: "Org", rules: [{ required: !0, message: "必填" }] },
483
+ token: { label: "Token", component: { type: "password" }, rules: [{ required: !0, message: "必填" }] }
484
+ } : y || d ? { db: { label: d ? "Schema/库" : "数据库", rules: [{ required: !0, message: "必填" }] } } : {},
485
+ ...a ? { query: { label: "查询语句", component: { type: "textarea", rows: 5 }, rules: [{ required: !0, message: "必填" }] } } : {},
486
+ ...s ? C : {}
374
487
  };
375
488
  }
376
- const N = {
377
- ...a,
489
+ const t = {
490
+ ...o,
491
+ "ai/jev": {
492
+ label: "Jev 决策",
493
+ desc: "问一个问题,按答案连线;可附带附加问题一次问完,只记录结果",
494
+ icon: "/images/intent.svg",
495
+ category: "ai",
496
+ relationTypes: [{ label: "失败", value: "Failure" }],
497
+ demoOptions: {
498
+ choice: [
499
+ { name: "createRule", description: "创建条件触发的自动化联动规则" },
500
+ { name: "control", description: "控制设备开关或调节参数" },
501
+ { name: "query", description: "查询设备当前状态或数值" }
502
+ ],
503
+ score: [
504
+ { name: "info", description: "无需处理" },
505
+ { name: "warning", description: "值班员关注" },
506
+ { name: "high", description: "尽快处理" },
507
+ { name: "critical", description: "立即处置" }
508
+ ]
509
+ },
510
+ ...k,
511
+ question: { label: "主问题", desc: "对消息提问,答案决定走哪条线", type: "string", component: { type: "textarea" } },
512
+ answerType: { label: "主答案形态", desc: "类别选多选一,程度强弱选分级,是非判断选是否", type: "string", defaultValue: "choice", component: { type: "select", options: P } },
513
+ options: { label: "主选项", desc: "每行名称就是一条连线;档位按顺序作为评分标尺", type: "array", dependsOn: { field: "answerType", operator: "ne", value: "noul" }, component: { type: "table", options: I } },
514
+ extraQuestions: {
515
+ label: "附加问题",
516
+ desc: "一次问完的其他维度,只记录结果,不影响连线",
517
+ type: "array",
518
+ component: {
519
+ type: "questionList",
520
+ options: [
521
+ { name: "id", label: "键名", type: "string" },
522
+ { name: "type", label: "类型", type: "string", defaultValue: "choice", component: { type: "select", options: P } },
523
+ { name: "question", label: "问题", type: "string", component: { type: "textarea" } },
524
+ { name: "options", label: "选项", type: "array", dependsOn: { field: "type", operator: "ne", value: "noul" }, component: { type: "table", options: I } }
525
+ ]
526
+ }
527
+ },
528
+ outputTo: { label: "结果输出", desc: "元数据不改消息体;消息负荷用结果替换消息体", type: "string", defaultValue: "metadata", component: { type: "select", options: [{ label: "元数据 msg.Metadata", value: "metadata" }, { label: "消息负荷 msg.Data", value: "data" }] } },
529
+ minConfidence: { label: "最低置信度", desc: "把握不足走 Default 线,默认 0.5,负数关闭", type: "number", defaultValue: 0.5, dependsOn: { field: "answerType", operator: "ne", value: "noul" } }
530
+ },
531
+ "ai/jevFilter": {
532
+ label: "Jev 过滤",
533
+ desc: "判断一句话对消息内容是否成立:成立走 True,不成立走 False",
534
+ icon: "/images/filter.svg",
535
+ category: "ai",
536
+ relationTypes: [{ label: "是", value: "True" }, { label: "否", value: "False" }, { label: "失败", value: "Failure" }],
537
+ ...k,
538
+ question: { label: "问题", desc: "成立概率达到 0.5 走 True,否则走 False", type: "string", component: { type: "textarea" } }
539
+ },
378
540
  "ai/agent": {
379
541
  label: "智能体",
380
542
  desc: "基于ReAct框架的AI智能体,支持调用工具和技能完成复杂任务",
@@ -723,6 +885,7 @@ const N = {
723
885
  label: "故障转移端点",
724
886
  desc: "主端点重试耗尽后按顺序切换的备用端点。不配置时不启用故障转移。",
725
887
  group: "reliability",
888
+ capabilities: { aiProvider: { kind: "chat" } },
726
889
  component: {
727
890
  type: "table",
728
891
  options: [
@@ -760,6 +923,7 @@ const N = {
760
923
  }
761
924
  },
762
925
  "ai/createImage": {
926
+ capabilities: { aiProvider: { kind: "chat" } },
763
927
  label: "图像生成",
764
928
  desc: "调用 DALL-E 或兼容接口生成图像",
765
929
  icon: "/images/generate-image.svg",
@@ -1112,6 +1276,7 @@ const N = {
1112
1276
  }
1113
1277
  },
1114
1278
  "ai/intent": {
1279
+ capabilities: { aiProvider: { kind: "chat" } },
1115
1280
  label: "意图识别",
1116
1281
  desc: "基于大模型分析用户输入的意图,并路由到对应分支",
1117
1282
  icon: "/images/intent.svg",
@@ -1484,6 +1649,7 @@ const N = {
1484
1649
  }
1485
1650
  },
1486
1651
  "ai/localIntent": {
1652
+ capabilities: { aiProvider: { kind: "embedding" } },
1487
1653
  label: "本地意图识别",
1488
1654
  desc: "基于嵌入向量的本地意图分类,无需调用LLM,通过语义相似度匹配意图",
1489
1655
  icon: "/images/intent.svg",
@@ -2725,18 +2891,12 @@ const N = {
2725
2891
  label: "空闲超时(单位:秒)",
2726
2892
  desc: ""
2727
2893
  },
2728
- concurrency: {
2729
- label: "并发数",
2730
- desc: ""
2731
- },
2894
+ concurrency: void 0,
2732
2895
  disableKeepalive: {
2733
2896
  label: "禁用keepalive",
2734
2897
  desc: ""
2735
2898
  },
2736
- maxRequestSize: {
2737
- label: "最大请求大小",
2738
- desc: "示例:10M 10K"
2739
- },
2899
+ maxRequestSize: void 0,
2740
2900
  router: {
2741
2901
  from: {
2742
2902
  path: {
@@ -2948,13 +3108,30 @@ const N = {
2948
3108
  desc: ""
2949
3109
  },
2950
3110
  maxReconnectInterval: {
2951
- label: "重连间隔,单位秒"
3111
+ label: "最大重连间隔",
3112
+ desc: "断线重连的最大间隔,支持时长写法,如 10s、1m"
2952
3113
  },
2953
3114
  qos: {
2954
3115
  label: "QOS"
2955
3116
  },
2956
3117
  cleanSession: {
2957
- label: "清除会话"
3118
+ label: "清除会话",
3119
+ desc: "连接时清除上一个会话的订阅关系和未消费消息"
3120
+ },
3121
+ dataType: {
3122
+ label: "消息数据类型",
3123
+ type: "string",
3124
+ desc: "留空自动判断:合法 JSON 按 JSON,其余按文本;二进制流选 BINARY,强制文本选 TEXT",
3125
+ component: {
3126
+ type: "select",
3127
+ clearable: !0,
3128
+ options: [
3129
+ { label: "自动判断(默认)", value: "" },
3130
+ { label: "JSON", value: "JSON" },
3131
+ { label: "TEXT 纯文本", value: "TEXT" },
3132
+ { label: "BINARY 二进制", value: "BINARY" }
3133
+ ]
3134
+ }
2958
3135
  },
2959
3136
  clientId: {
2960
3137
  label: "客户端ID",
@@ -3063,6 +3240,7 @@ const N = {
3063
3240
  label: "读超时,单位秒"
3064
3241
  },
3065
3242
  limit: {
3243
+ type: "int",
3066
3244
  label: "限制同步条数",
3067
3245
  desc: "用于批量操作,不处理超过限制数据。0:不限制。其他:超过该值则不处理"
3068
3246
  },
@@ -3139,6 +3317,8 @@ const N = {
3139
3317
  }
3140
3318
  },
3141
3319
  "endpoint/net": {
3320
+ sessionKey: { ...b.sessionKey },
3321
+ sessionTTL: { ...b.sessionTTL },
3142
3322
  notInput: !0,
3143
3323
  label: "TCP/UDP",
3144
3324
  icon: "/images/endpoint/net.svg",
@@ -3507,7 +3687,8 @@ const N = {
3507
3687
  }
3508
3688
  },
3509
3689
  "endpoint/opcua": {
3510
- category: "iot",
3690
+ category: "iot/input-endpoint",
3691
+ timeout: { ...p, type: "int" },
3511
3692
  notInput: !0,
3512
3693
  nodeType: "endpoint-node",
3513
3694
  label: "OPC_UA订阅",
@@ -3787,6 +3968,16 @@ const N = {
3787
3968
  label: "是否自动删除",
3788
3969
  desc: ""
3789
3970
  },
3971
+ queueName: {
3972
+ label: "队列名称",
3973
+ type: "string",
3974
+ desc: "留空使用自动生成的独占临时队列;固定队列名配合持久化并关闭自动删除,可保留离线期间消息"
3975
+ },
3976
+ exclusive: {
3977
+ label: "是否独占",
3978
+ type: "bool",
3979
+ desc: "true=队列仅限当前连接使用,连接断开即删除;队列名称为空时强制独占"
3980
+ },
3790
3981
  router: {
3791
3982
  from: {
3792
3983
  path: {
@@ -3947,6 +4138,8 @@ const N = {
3947
4138
  }
3948
4139
  },
3949
4140
  "endpoint/ws": {
4141
+ sessionKey: { ...b.sessionKey },
4142
+ sessionTTL: { ...b.sessionTTL },
3950
4143
  notInput: !0,
3951
4144
  label: "Websocket",
3952
4145
  icon: "/images/endpoint/websocket.svg",
@@ -4215,9 +4408,11 @@ const N = {
4215
4408
  flow: {
4216
4409
  label: "子规则链",
4217
4410
  desc: "",
4411
+ relationTypeAllowCreate: !0,
4412
+ relationTypes: [{ label: "成功", value: "Success" }, { label: "失败", value: "Failure" }],
4218
4413
  targetId: {
4219
4414
  label: "规则链ID",
4220
- desc: "",
4415
+ desc: "支持 chainId:nodeId 从子链指定节点开始;支持 ${metadata.x}/${msg.x}/${global.x} 表达式",
4221
4416
  rules: [
4222
4417
  {
4223
4418
  required: !0,
@@ -4225,12 +4420,13 @@ const N = {
4225
4420
  }
4226
4421
  ],
4227
4422
  component: {
4228
- type: "ruleChainSelector"
4423
+ type: "RuleChainSelector",
4424
+ nodePicker: !0
4229
4425
  }
4230
4426
  },
4231
4427
  extend: {
4232
4428
  label: "继承模式",
4233
- desc: "如果开启,不合并子规则链输出关系和消息"
4429
+ desc: "开启后透传子链终止分支的原始关系标签;关闭时合并子链输出并使用成功/失败关系"
4234
4430
  }
4235
4431
  },
4236
4432
  for: {
@@ -4372,10 +4568,7 @@ const N = {
4372
4568
  label: "组内执行超时,单位秒,默认0",
4373
4569
  desc: "默认0,代表不超时"
4374
4570
  },
4375
- mergeToMap: {
4376
- label: "结果合并到map",
4377
- desc: "false: 结果为[]WrapperMsg列表; true: 结果合并为Map(JSON合并字段,其他以nodeId为key)"
4378
- },
4571
+ mergeToMap: void 0,
4379
4572
  nodeType: "group-node"
4380
4573
  },
4381
4574
  inclusive: {
@@ -4450,6 +4643,16 @@ const N = {
4450
4643
  jsScript: {
4451
4644
  label: "function String(msg, metadata, msgType, dataType) {",
4452
4645
  desc: "}"
4646
+ },
4647
+ outputTo: {
4648
+ label: "输出位置",
4649
+ type: "string",
4650
+ desc: "日志输出的通道,默认双通道",
4651
+ component: { type: "select", options: [
4652
+ { label: "调试控制台 + 服务端日志", value: "both" },
4653
+ { label: "仅调试控制台", value: "console" },
4654
+ { label: "仅服务端日志", value: "logger" }
4655
+ ] }
4453
4656
  }
4454
4657
  },
4455
4658
  metadataTransform: {
@@ -4539,6 +4742,14 @@ const N = {
4539
4742
  desc: ""
4540
4743
  },
4541
4744
  net: {
4745
+ target: {
4746
+ type: "string",
4747
+ label: "目标",
4748
+ desc: "共享 endpoint 连接时按 IP/deviceId/* 寻址;支持 ${metadata.xxx}",
4749
+ component: { type: "input" },
4750
+ showWhenRef: !0,
4751
+ dependsOn: { field: "server", operator: "prefix", value: "ref://" }
4752
+ },
4542
4753
  label: "TCP/UDP",
4543
4754
  icon: "/images/net.svg",
4544
4755
  desc: "",
@@ -4611,7 +4822,7 @@ const N = {
4611
4822
  desc: "",
4612
4823
  targetId: {
4613
4824
  label: "引用节点",
4614
- desc: "引用本规则链中的其他节点",
4825
+ desc: "本链节点ID或其他链ID:节点ID;支持 ${metadata.x}/${msg.x}/${global.x} 表达式",
4615
4826
  rules: [
4616
4827
  {
4617
4828
  required: !0,
@@ -4619,11 +4830,10 @@ const N = {
4619
4830
  }
4620
4831
  ],
4621
4832
  component: {
4622
- type: "select",
4623
- filterable: !0,
4624
- allowCreate: !0,
4625
- multiple: !1,
4626
- source: "nodes"
4833
+ type: "RuleChainSelector",
4834
+ nodePicker: !0,
4835
+ allowSelf: !0,
4836
+ requireNode: !0
4627
4837
  }
4628
4838
  },
4629
4839
  tellChain: {
@@ -5744,19 +5954,21 @@ const N = {
5744
5954
  tcpConfig: {
5745
5955
  label: "TCP配置",
5746
5956
  desc: "",
5957
+ group: "advanced",
5958
+ dependsOn: { field: "server", operator: "prefix", value: "tcp" },
5747
5959
  timeout: {
5748
5960
  label: "超时时间",
5749
5961
  desc: "设置请求超时值,单位为秒"
5750
5962
  },
5751
- certPath: {
5963
+ certFile: {
5752
5964
  label: "证书路径",
5753
5965
  desc: "证书文件路径"
5754
5966
  },
5755
- keyPath: {
5967
+ certKeyFile: {
5756
5968
  label: "密钥路径",
5757
5969
  desc: "密钥文件路径"
5758
5970
  },
5759
- caPath: {
5971
+ caFile: {
5760
5972
  label: "CA证书路径",
5761
5973
  desc: "CA证书文件路径"
5762
5974
  }
@@ -5937,7 +6149,9 @@ const N = {
5937
6149
  "x/opcuaRead": {
5938
6150
  label: "OPC_UA读",
5939
6151
  icon: "/images/opcua_read.svg",
5940
- category: "iot",
6152
+ category: "iot/protocol-acquisition",
6153
+ timeout: { ...p, type: "int", defaultValue: 5 },
6154
+ points: m([...g, ...h]),
5941
6155
  desc: "<ul><li>获取消息负荷指定节点列表点位数据,并通过Success链转到下一个节点。</li></ul>",
5942
6156
  server: {
5943
6157
  ref: "primary",
@@ -6065,7 +6279,13 @@ const N = {
6065
6279
  "x/opcuaWrite": {
6066
6280
  label: "OPC_UA写",
6067
6281
  icon: "/images/opcua_write.svg",
6068
- category: "iot",
6282
+ category: "iot/protocol-acquisition",
6283
+ timeout: { ...p, type: "int", defaultValue: 5 },
6284
+ points: m([
6285
+ ...g.slice(0, 2),
6286
+ { ...g[2], rules: [{ required: !0, message: "必填" }] },
6287
+ { name: "value", label: "写入值", type: "string", rules: [{ required: !0, message: "必填" }], desc: "支持 ${msg.xx}" }
6288
+ ]),
6069
6289
  desc: "<ul><li>把消息负荷点位数据列表,写入OPCUA服务器。</li></ul>",
6070
6290
  server: {
6071
6291
  ref: "primary",
@@ -6191,6 +6411,7 @@ const N = {
6191
6411
  }
6192
6412
  },
6193
6413
  "x/opengeminiQuery": {
6414
+ category: "iot/tsdb",
6194
6415
  label: "opengemini读",
6195
6416
  icon: "/images/opengemini.svg",
6196
6417
  desc: "",
@@ -6245,6 +6466,8 @@ const N = {
6245
6466
  }
6246
6467
  },
6247
6468
  "x/opengeminiWrite": {
6469
+ category: "iot/tsdb",
6470
+ ...C,
6248
6471
  label: "opengemini写",
6249
6472
  icon: "/images/opengemini-write.svg",
6250
6473
  desc: "",
@@ -6574,6 +6797,11 @@ const N = {
6574
6797
  autoDelete: {
6575
6798
  label: "是否自动删除",
6576
6799
  desc: "true=当没有队列绑定时自动删除"
6800
+ },
6801
+ persistent: {
6802
+ label: "消息持久化",
6803
+ type: "bool",
6804
+ desc: "true=以持久化模式发布消息;目标队列也须持久化,才能在服务器重启后保留消息"
6577
6805
  }
6578
6806
  },
6579
6807
  "x/receiveEmail": {
@@ -6595,6 +6823,11 @@ const N = {
6595
6823
  label: "IMAP端口",
6596
6824
  desc: "默认: 993"
6597
6825
  },
6826
+ uid: {
6827
+ label: "登录用户UID",
6828
+ type: "string",
6829
+ desc: "部分 IMAP 服务器要求以数字 UID 登录;借共享连接时以共享节点配置为准"
6830
+ },
6598
6831
  username: {
6599
6832
  label: "用户名",
6600
6833
  rules: [
@@ -6815,22 +7048,13 @@ const N = {
6815
7048
  },
6816
7049
  db: {
6817
7050
  label: "数据库编号",
6818
- rules: [
6819
- {
6820
- required: !0,
6821
- message: "该项是必须的"
6822
- },
6823
- {
6824
- type: "integer",
6825
- required: !0,
6826
- message: "必须是整型"
6827
- }
6828
- ],
6829
- desc: "默认0"
7051
+ rules: [{ type: "integer", message: "必须是整型" }],
7052
+ desc: "默认0;借共享连接时以共享节点配置的库号为准"
6830
7053
  },
6831
7054
  cmd: {
6832
7055
  label: "执行命令,例如SET/GET/DEL/HMSET/HMGET",
6833
- desc: "支持${metadata.key}占位符读取metadata元数据,支持${msg.key}占位符读取消息负荷指定key数据,支持${data}获取消息原始负荷",
7056
+ desc: "填命令名(参数放命令参数)或含参数的完整命令;支持 ${msg.key}、${metadata.key} 变量替换",
7057
+ component: { onChange: "redisCmdOutputTo" },
6834
7058
  rules: [
6835
7059
  {
6836
7060
  required: !0,
@@ -6838,13 +7062,24 @@ const N = {
6838
7062
  }
6839
7063
  ]
6840
7064
  },
6841
- paramsExpr: {
6842
- label: "命令动态参数",
6843
- desc: '支持Expr表达式。如:["myhash2", "field1", "value1"],或者通过变量取值如:msg表示取消息负荷。命令动态参数和命令静态参数,优先取命令动态参数值。'
6844
- },
7065
+ paramsExpr: void 0,
6845
7066
  params: {
6846
- label: "命令静态参数",
6847
- desc: "支持${metadata.key}占位符读取metadata元数据,支持${msg.key}占位符读取消息负荷指定key数据,支持${data}获取消息原始负荷"
7067
+ label: "命令参数",
7068
+ desc: "每项对应一个命令参数,按顺序传入;支持 ${msg.key}、${metadata.key} 变量替换及拼接"
7069
+ },
7070
+ outputTo: {
7071
+ label: "结果输出位置",
7072
+ type: "string",
7073
+ desc: "留空默认 data,替换消息负荷;写命令建议 metadata,保留负荷并把结果写到 metadata.result",
7074
+ component: {
7075
+ type: "select",
7076
+ clearable: !0,
7077
+ placeholder: "默认 data(替换 msg 负荷)",
7078
+ options: [
7079
+ { label: "data(替换 msg 负荷,默认)", value: "data" },
7080
+ { label: "metadata(保留负荷,结果写 result 键)", value: "metadata" }
7081
+ ]
7082
+ }
6848
7083
  }
6849
7084
  },
6850
7085
  "x/redisPub": {
@@ -6878,18 +7113,8 @@ const N = {
6878
7113
  },
6879
7114
  db: {
6880
7115
  label: "数据库编号",
6881
- rules: [
6882
- {
6883
- required: !0,
6884
- message: "该项是必须的"
6885
- },
6886
- {
6887
- type: "integer",
6888
- required: !0,
6889
- message: "必须是整型"
6890
- }
6891
- ],
6892
- desc: "默认0"
7116
+ rules: [{ type: "integer", message: "必须是整型" }],
7117
+ desc: "默认0;借共享连接时以共享节点配置的库号为准"
6893
7118
  },
6894
7119
  channel: {
6895
7120
  label: "发布通道",
@@ -7652,14 +7877,18 @@ const N = {
7652
7877
  value: "Failure"
7653
7878
  },
7654
7879
  {
7655
- label: "窗口事件",
7656
- value: "window_event"
7880
+ label: "流事件",
7881
+ value: "stream_event"
7657
7882
  }
7658
7883
  ],
7659
- desc: "<ul><li>通过 SQL 做窗口聚合、分组统计或 MATCH_RECOGNIZE 模式识别。</li><li>原始数据走 Success;聚合窗口或 CEP 结果经 stream_event 输出。</li></ul>",
7884
+ desc: "通过 SQL 做窗口聚合、分组统计、模式识别或流-流 JOIN;原始数据走 Success,结果经 stream_event 输出",
7660
7885
  sql: {
7661
- label: "聚合/CEP SQL",
7662
- desc: "示例:SELECT deviceId, AVG(temperature) as avg_temp, COUNT(*) as count FROM stream GROUP BY deviceId, TumblingWindow('2s')。直接引用 msg 数据字段,不支持 ${} 占位符变量。",
7886
+ label: "聚合/CEP/JOIN SQL",
7887
+ desc: `聚合示例:
7888
+ SELECT deviceId, AVG(temperature) as avg_temp FROM stream GROUP BY deviceId, TumblingWindow('2s')
7889
+ 流-流 JOIN 示例:
7890
+ SELECT s.deviceId, v.vibration FROM tempStream s JOIN vibrationStream v WITHIN 10 SECONDS ON s.deviceId = v.deviceId
7891
+ 直接引用 msg 数据字段,不支持 \${} 占位符变量。`,
7663
7892
  rules: [
7664
7893
  {
7665
7894
  required: !0,
@@ -7676,20 +7905,30 @@ const N = {
7676
7905
  },
7677
7906
  inputFormat: {
7678
7907
  label: "数组输入模式",
7908
+ type: "string",
7909
+ group: "advanced",
7679
7910
  desc: "auto:数组逐条进流;columns:将 [{name,value}] 透视为一行宽表,适合跨字段计算。",
7680
7911
  component: { type: "select", options: [{ label: "auto 逐条进流(纵表)", value: "auto" }, { label: "columns 透视宽表", value: "columns" }] }
7681
7912
  },
7682
7913
  tables: {
7683
7914
  label: "元数据表(流-表 JOIN)",
7915
+ type: "array",
7916
+ group: "advanced",
7684
7917
  desc: "表名必须与 SQL 中 JOIN 的表名一致;文件路径或 URL 是静态配置。",
7685
- component: { type: "table", options: p }
7918
+ component: { type: "table", options: w }
7919
+ },
7920
+ streamKey: {
7921
+ label: "流名称来源(流-流 JOIN)",
7922
+ type: "string",
7923
+ group: "advanced",
7924
+ desc: "仅带 WITHIN 的流-流 JOIN 生效。填元数据键名,如 streamName,或 ${msg.stream} 表达式;结果须与 SQL 流名称一致。留空为单流模式,流-表 JOIN 无需配置"
7686
7925
  }
7687
7926
  },
7688
7927
  "x/streamTransform": {
7689
7928
  label: "流转换器",
7690
7929
  icon: "/images/stream-transform.svg",
7691
7930
  relationTypes: [{ label: "成功", value: "Success" }, { label: "假", value: "False" }, { label: "失败", value: "Failure" }],
7692
- desc: "<ul><li>通过 SQL 转换和过滤输入数据,并支持流-表 JOIN 元数据富化。</li><li>WHERE 不命中的数据走 False 链。</li></ul>",
7931
+ desc: "通过 SQL 转换、过滤流数据,支持流-表 JOIN 元数据富化;WHERE 不命中走 False 链",
7693
7932
  sql: {
7694
7933
  label: "转换SQL",
7695
7934
  desc: "示例:SELECT temperature, humidity, temperature * 1.8 + 32 as temp_fahrenheit FROM stream WHERE temperature > 20。直接引用 msg 数据字段,不支持 ${} 占位符变量。",
@@ -7709,13 +7948,17 @@ const N = {
7709
7948
  },
7710
7949
  inputFormat: {
7711
7950
  label: "数组输入模式",
7951
+ type: "string",
7952
+ group: "advanced",
7712
7953
  desc: "auto:数组逐条转换并合并输出;columns:将 [{name,value}] 透视为一行宽表后处理。",
7713
7954
  component: { type: "select", options: [{ label: "auto 逐条转换(纵表)", value: "auto" }, { label: "columns 透视宽表", value: "columns" }] }
7714
7955
  },
7715
7956
  tables: {
7716
7957
  label: "元数据表(流-表 JOIN)",
7958
+ type: "array",
7959
+ group: "advanced",
7717
7960
  desc: "表名必须与 SQL 中 JOIN 的表名一致;HTTP 表仅在 source=http 时使用请求头和超时。",
7718
- component: { type: "table", options: p }
7961
+ component: { type: "table", options: w }
7719
7962
  }
7720
7963
  },
7721
7964
  "x/bacnetRead": {
@@ -7726,7 +7969,7 @@ const N = {
7726
7969
  desc: "BACnet/IP 读取对象属性。addr 使用对象类型:实例[:属性],例如 analog-input:0 或 ai:1:description。",
7727
7970
  server: { ref: "primary", refNodes: ["x/bacnetWrite"], label: "设备地址", rules: [{ required: !0, message: "必填" }], desc: "host:port,默认端口 47808", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
7728
7971
  timeout: { label: "超时(秒)", desc: "默认 5" },
7729
- points: { label: "采集点位表", desc: "若 msg.Data 带点位列表则优先使用。", component: { type: "table", options: S } }
7972
+ points: { label: "采集点位表", desc: "若 msg.Data 带点位列表则优先使用。", component: { type: "table", options: _ } }
7730
7973
  },
7731
7974
  "x/bacnetWrite": {
7732
7975
  label: "BACnet写",
@@ -7737,7 +7980,7 @@ const N = {
7737
7980
  server: { ref: "primary", refNodes: ["x/bacnetRead"], label: "设备地址", rules: [{ required: !0, message: "必填" }], desc: "host:port,默认端口 47808", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
7738
7981
  timeout: { label: "超时(秒)", desc: "默认 5" },
7739
7982
  priority: { label: "写优先级", desc: "1-16;0 表示省略并使用设备默认优先级" },
7740
- points: { label: "控制点位表", desc: "type 为值类型,value 为写入值。", component: { type: "table", options: C } }
7983
+ points: { label: "控制点位表", desc: "type 为值类型,value 为写入值。", component: { type: "table", options: $ } }
7741
7984
  },
7742
7985
  "x/finsRead": {
7743
7986
  label: "FINS读",
@@ -7746,8 +7989,8 @@ const N = {
7746
7989
  category: "iot/protocol-acquisition",
7747
7990
  desc: "欧姆龙 FINS UDP/TCP 读取 DM/CIO/WR/HR/AR 区的字、位和字符串。D100:20 表示字符串地址和长度。",
7748
7991
  server: { ref: "primary", refNodes: ["x/finsWrite"], label: "PLC地址", rules: [{ required: !0, message: "必填" }], desc: "host:port,UDP 默认 9600", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
7749
- ...b,
7750
- points: { label: "采集点位表", component: { type: "table", options: i } }
7992
+ ...S,
7993
+ points: { label: "采集点位表", component: { type: "table", options: f } }
7751
7994
  },
7752
7995
  "x/finsWrite": {
7753
7996
  label: "FINS写",
@@ -7756,8 +7999,8 @@ const N = {
7756
7999
  category: "iot/protocol-acquisition",
7757
8000
  desc: "欧姆龙 FINS UDP/TCP 写入 DM/CIO/WR/HR/AR 区。字符串使用 D100:20 和 STRING 类型。",
7758
8001
  server: { ref: "primary", refNodes: ["x/finsRead"], label: "PLC地址", rules: [{ required: !0, message: "必填" }], desc: "host:port", component: { type: "select", filterable: !0, allowCreate: !0, multiple: !1 } },
7759
- ...b,
7760
- points: { label: "写入点位表", component: { type: "table", options: P } }
8002
+ ...S,
8003
+ points: { label: "写入点位表", component: { type: "table", options: L } }
7761
8004
  },
7762
8005
  "x/wukongimSender": {
7763
8006
  label: "WuKongIM发",
@@ -7780,7 +8023,8 @@ const N = {
7780
8023
  multiple: !1
7781
8024
  }
7782
8025
  },
7783
- uID: {
8026
+ uID: void 0,
8027
+ uid: {
7784
8028
  label: "用户ID",
7785
8029
  rules: [
7786
8030
  {
@@ -7853,7 +8097,8 @@ const N = {
7853
8097
  ]
7854
8098
  }
7855
8099
  },
7856
- channelID: {
8100
+ channelID: void 0,
8101
+ channelId: {
7857
8102
  label: "频道ID",
7858
8103
  desc: "允许使用 ${} 占位符变量。如果是个人频道填用户ID"
7859
8104
  },
@@ -8054,7 +8299,211 @@ const N = {
8054
8299
  }
8055
8300
  }
8056
8301
  }
8302
+ }, j = {
8303
+ "ai/llm": ["key"],
8304
+ "ai/agent": ["key"],
8305
+ "ai/createImage": ["key"],
8306
+ "ai/intent": ["key"],
8307
+ "ai/localIntent": ["key"],
8308
+ "endpoint/mqtt": ["password"],
8309
+ "endpoint/nats": ["password"],
8310
+ "endpoint/redis": ["password"],
8311
+ "endpoint/redis/stream": ["password"],
8312
+ "endpoint/mysql_cdc": ["password"],
8313
+ "endpoint/wukongim": ["token"],
8314
+ "endpoint/nsq": ["authToken"],
8315
+ "endpoint/pulsar": ["authToken"],
8316
+ "endpoint/opcua": ["password"],
8317
+ mqttClient: ["password"],
8318
+ sendEmail: ["password"],
8319
+ ssh: ["password"],
8320
+ restApiCall: ["proxyPassword"],
8321
+ "ci/gitClone": ["authPassword", "proxyPassword"],
8322
+ "ci/gitPush": ["authPassword", "proxyPassword"],
8323
+ "x/receiveEmail": ["password"],
8324
+ "x/redisClient": ["password"],
8325
+ "x/redisPub": ["password"],
8326
+ "x/pulsarClient": ["authToken"],
8327
+ "x/nsqClient": ["authToken"],
8328
+ "x/natsClient": ["password"],
8329
+ "x/wukongimSender": ["token"],
8330
+ "x/opcuaRead": ["password"],
8331
+ "x/opcuaWrite": ["password"],
8332
+ "x/tsdbWrite": ["password", "token"],
8333
+ "x/tsdbQuery": ["password", "token"],
8334
+ "x/opengeminiWrite": ["password", "token"],
8335
+ "x/opengeminiQuery": ["password", "token"],
8336
+ "x/influxdbWrite": ["token"],
8337
+ "x/influxdbQuery": ["token"]
8057
8338
  };
8339
+ var q;
8340
+ for (const [e, l] of Object.entries(j)) {
8341
+ const a = t[e];
8342
+ for (const s of l)
8343
+ a[s] = { ...a[s], component: { ...(q = a[s]) == null ? void 0 : q.component, type: "password" } };
8344
+ }
8345
+ const Q = {
8346
+ dbClient: ["poolSize"],
8347
+ mqttClient: ["maxReconnectInterval", "caFile", "certFile", "certKeyFile"],
8348
+ restApiCall: ["readTimeoutMs", "insecureSkipVerify", "maxParallelRequestsCount", "enableProxy", "useSystemProxyProperties", "proxyScheme", "proxyHost", "proxyPort", "proxyUser", "proxyPassword"],
8349
+ "ci/gitClone": ["proxyUrl", "proxyUsername", "proxyPassword"],
8350
+ "ci/gitPush": ["proxyUrl", "proxyUsername", "proxyPassword"],
8351
+ "endpoint/mqtt": ["maxReconnectInterval", "caFile", "certFile", "certKeyFile"],
8352
+ "endpoint/net": ["readTimeout", "encode", "packetMode", "packetSize", "delimiter", "maxPacketSize"],
8353
+ "endpoint/net_client": ["connectTimeout", "readTimeout", "reconnectInterval", "encode", "packetMode", "packetSize", "delimiter", "maxPacketSize", "heartbeatInterval", "heartbeatData"],
8354
+ "endpoint/http": ["allowCors", "certFile", "certKeyFile", "readTimeout", "writeTimeout", "idleTimeout", "disableKeepalive"],
8355
+ "endpoint/ws": ["allowCors", "certFile", "certKeyFile", "readTimeout", "writeTimeout", "idleTimeout", "disableKeepalive", "sessionKey", "sessionTTL"],
8356
+ "endpoint/ws_client": ["headers", "reconnectInterval", "heartbeatInterval", "heartbeatData", "allowText", "allowBinary"],
8357
+ "endpoint/kafka": ["sasl", "tls"],
8358
+ "endpoint/grpc/stream": ["request", "headers", "checkInterval"],
8359
+ "endpoint/wukongim": ["connectTimeout", "protoVersion", "pingInterval", "reconnect", "autoAck"],
8360
+ "endpoint/mcpServer": ["allowCors", "certFile", "certKeyFile"],
8361
+ "endpoint/nsq": ["certFile", "certKeyFile"],
8362
+ "endpoint/pulsar": ["poolSize", "certFile", "certKeyFile"]
8363
+ };
8364
+ var N;
8365
+ for (const e of ["readTimeout", "writeTimeout", "idleTimeout", "disableKeepalive"])
8366
+ (N = t["endpoint/ws"])[e] ?? (N[e] = { ...t["endpoint/http"][e] });
8367
+ for (const [e, l] of Object.entries(Q)) {
8368
+ const a = t[e];
8369
+ for (const s of l) a[s] = { ...a[s], group: "advanced" };
8370
+ }
8371
+ const H = {
8372
+ mqttClient: ["endpoint/mqtt"],
8373
+ "endpoint/mqtt": ["mqttClient", "endpoint/mqtt"],
8374
+ net: ["endpoint/net"],
8375
+ ws: ["endpoint/ws"],
8376
+ "x/kafkaProducer": ["endpoint/kafka"],
8377
+ "endpoint/kafka": ["x/kafkaProducer", "endpoint/kafka"],
8378
+ // Keep both deployed spellings as candidates; saved component types are never renamed.
8379
+ "x/redisClient": ["endpoint/redis", "endpoint/redis_stream", "endpoint/redis/stream"],
8380
+ "x/redisPub": ["endpoint/redis", "endpoint/redis_stream", "endpoint/redis/stream"],
8381
+ "endpoint/redis": ["x/redisClient", "x/redisPub", "endpoint/redis", "endpoint/redis/stream"],
8382
+ "endpoint/redis/stream": ["x/redisClient", "x/redisPub", "endpoint/redis", "endpoint/redis/stream"],
8383
+ "x/natsClient": ["endpoint/nats"],
8384
+ "endpoint/nats": ["x/natsClient", "endpoint/nats"],
8385
+ "x/rabbitmqClient": ["endpoint/rabbitmq"],
8386
+ "endpoint/rabbitmq": ["x/rabbitmqClient", "endpoint/rabbitmq"],
8387
+ "x/pulsarClient": ["endpoint/pulsar"],
8388
+ "endpoint/pulsar": ["x/pulsarClient", "endpoint/pulsar"]
8389
+ };
8390
+ var R, A;
8391
+ for (const [e, l] of Object.entries(H)) {
8392
+ const a = t[e];
8393
+ a.server = {
8394
+ ...a.server,
8395
+ ref: "primary",
8396
+ refNodes: [.../* @__PURE__ */ new Set([...((R = a.server) == null ? void 0 : R.refNodes) || [], ...l])],
8397
+ component: { ...(A = a.server) == null ? void 0 : A.component, type: "select", filterable: !0, allowCreate: !0, multiple: !1 }
8398
+ };
8399
+ }
8400
+ t["x/kafkaProducer"].server.poolRefNodes = ["endpoint/kafka"];
8401
+ t["endpoint/kafka"].server.poolRefNodes = ["x/kafkaProducer"];
8402
+ const J = {
8403
+ mqttClient: ["username", "password", "maxReconnectInterval", "cleanSession", "clientId", "caFile", "certFile", "certKeyFile"],
8404
+ net: ["protocol", "connectTimeout", "heartbeatInterval"],
8405
+ ssh: ["port", "username", "password"],
8406
+ "x/kafkaProducer": ["sasl", "tls"],
8407
+ "x/redisClient": ["password", "db", "poolSize"],
8408
+ "x/redisPub": ["password", "db", "poolSize"],
8409
+ "x/wukongimSender": ["uid", "connectTimeout", "protoVersion", "pingInterval", "reconnect", "autoAck"]
8410
+ };
8411
+ for (const [e, l] of Object.entries(J)) {
8412
+ const a = t[e];
8413
+ for (const s of l) a[s] = { ...a[s], ref: "shared" };
8414
+ }
8415
+ t.ssh.host.ref = "primary";
8416
+ for (const e of ["endpoint/redis", "endpoint/redis/stream", "x/redisClient", "x/redisPub"]) {
8417
+ const l = t[e];
8418
+ l.poolSize = { ...l.poolSize, type: "int", label: "连接池大小", desc: "留空使用默认连接池大小;借共享连接时以共享节点配置为准" };
8419
+ }
8420
+ for (const e of ["mqttClient", "endpoint/mqtt"])
8421
+ t[e].qos = {
8422
+ label: "QoS",
8423
+ desc: "服务质量等级",
8424
+ component: { type: "select", filterable: !0, allowCreate: !1, multiple: !1, options: [
8425
+ { label: "0-最多一次", value: 0 },
8426
+ { label: "1-至少一次", value: 1 },
8427
+ { label: "2-恰好一次", value: 2 }
8428
+ ] }
8429
+ };
8430
+ for (const e of ["x/rabbitmqClient", "endpoint/rabbitmq"])
8431
+ t[e].exchangeType.component = {
8432
+ type: "select",
8433
+ filterable: !0,
8434
+ allowCreate: !0,
8435
+ multiple: !1,
8436
+ options: [
8437
+ { label: "direct-直连", value: "direct" },
8438
+ { label: "fanout-广播", value: "fanout" },
8439
+ { label: "headers-头部", value: "headers" },
8440
+ { label: "topic-主题", value: "topic" }
8441
+ ]
8442
+ };
8443
+ for (const e of ["ci/gitClone", "ci/gitPush"]) {
8444
+ const l = t[e];
8445
+ l.authType.component = { type: "select", filterable: !0, allowCreate: !0, multiple: !1, options: [
8446
+ { label: "SSH密钥", value: "ssh" },
8447
+ { label: "密码", value: "password" },
8448
+ { label: "Token", value: "token" }
8449
+ ] };
8450
+ for (const a of ["authUser", "authPassword"]) l[a].dependsOn = { field: "authType", operator: "in", value: ["password", "token"] };
8451
+ l.authPemFile.dependsOn = { field: "authType", operator: "eq", value: "ssh" };
8452
+ }
8453
+ for (const e of ["proxyScheme", "proxyHost", "proxyPort", "proxyUser", "proxyPassword"])
8454
+ t.restApiCall[e].dependsOn = { field: "enableProxy", operator: "eq", value: !0 };
8455
+ for (const e of ["endpoint/opcua", "x/opcuaRead", "x/opcuaWrite"]) {
8456
+ const l = t[e];
8457
+ for (const a of ["auth", "mode", "policy"]) l[a].component.allowCreate = !1;
8458
+ for (const a of ["username", "password"]) l[a].dependsOn = { field: "auth", operator: "eq", value: "username" };
8459
+ for (const a of ["certFile", "certKeyFile"]) l[a].dependsOn = { field: "auth", operator: "eq", value: "certificate" };
8460
+ if (e === "endpoint/opcua")
8461
+ for (const a of ["auth", "username", "password", "certFile", "certKeyFile", "mode", "policy"]) l[a].group = "advanced";
8462
+ else
8463
+ l.server.refNodes = [e === "x/opcuaRead" ? "x/opcuaWrite" : "x/opcuaRead"], l.policy.component.options = ["None", "Basic128Rsa15", "Basic256", "Basic256Sha256"].map((a) => ({ label: a, value: a })), l.mode.component.options = [
8464
+ { label: "None", value: "none" },
8465
+ { label: "Sign", value: "sign" },
8466
+ { label: "SignAndEncrypt", value: "signandencrypt" }
8467
+ ];
8468
+ }
8469
+ for (const e of ["x/opengeminiWrite", "x/opengeminiQuery"])
8470
+ t[e].server.refNodes = [e === "x/opengeminiWrite" ? "x/opengeminiQuery" : "x/opengeminiWrite"];
8471
+ for (const e of ["x/tsdbWrite", "x/tsdbQuery"]) {
8472
+ const l = t[e];
8473
+ l.password = { ...l.password, label: "密码", dependsOn: { field: "driver", operator: "eq", value: "opengemini" } }, l.token = { ...l.token, label: "Token", dependsOn: { field: "driver", operator: "in", value: ["opengemini", "influxdb"] } };
8474
+ }
8475
+ const G = [
8476
+ ["dbClient", "poolSize", 0],
8477
+ ["mqttClient", "maxReconnectInterval", 0],
8478
+ ["restApiCall", "readTimeoutMs", 0],
8479
+ ["restApiCall", "maxParallelRequestsCount", 0],
8480
+ ["restApiCall", "proxyPort", 1, 65535],
8481
+ ["ssh", "port", 1, 65535],
8482
+ ["ai/createImage", "n", 1]
8483
+ ];
8484
+ for (const [e, l, a, s] of G) {
8485
+ const u = t[e][l];
8486
+ u.rules = [...u.rules || [], {
8487
+ type: "number",
8488
+ min: a,
8489
+ ...s !== void 0 ? { max: s } : {},
8490
+ message: s !== void 0 ? `数值范围 ${a}-${s}` : `不能小于 ${a}`
8491
+ }];
8492
+ }
8493
+ const x = t["ai/createImage"];
8494
+ x.prompt.component = { ...x.prompt.component, type: "textarea", rows: 3 };
8495
+ for (const [e, l] of Object.entries({
8496
+ quality: [{ label: "standard-标准", value: "standard" }, { label: "hd-高清", value: "hd" }],
8497
+ style: [{ label: "vivid-生动", value: "vivid" }, { label: "natural-自然", value: "natural" }],
8498
+ response_format: [{ label: "url-图片链接", value: "url" }, { label: "b64_json-内嵌数据", value: "b64_json" }]
8499
+ }))
8500
+ x[e].component = { type: "select", filterable: !0, allowCreate: !0, multiple: !1, options: l };
8501
+ t.exprTransform.expr.component = { type: "expr" };
8502
+ t.exprTransform.mapping.component = { type: "map" };
8503
+ t.metadataTransform.mapping.component = { type: "map" };
8504
+ t["x/otel"].metricExpr.component = { type: "expr" };
8505
+ for (const e of ["filter", "doc"])
8506
+ t["x/mongodbClient"][e].component = { type: "textarea", rows: 3 };
8058
8507
  export {
8059
- N as O
8508
+ t as O
8060
8509
  };