vue-agent-start 0.1.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 (169) hide show
  1. package/package.json +30 -0
  2. package/pnpm-workspace.yaml +3 -0
  3. package/src/agent-flow/adapter/backend.ts +99 -0
  4. package/src/agent-flow/components/ChatIframePanel.vue +773 -0
  5. package/src/agent-flow/components/DatasetItemCard.vue +313 -0
  6. package/src/agent-flow/components/MemoryWindow.vue +104 -0
  7. package/src/agent-flow/components/PromptEditor.vue +804 -0
  8. package/src/agent-flow/components/PromptEditorTagPanel.vue +460 -0
  9. package/src/agent-flow/components/SvgIcon.vue +32 -0
  10. package/src/agent-flow/components/ToolItemCard.vue +169 -0
  11. package/src/agent-flow/components/VariableCard.vue +161 -0
  12. package/src/agent-flow/components/VariableSelector.vue +162 -0
  13. package/src/agent-flow/components/chat-iframe-types.ts +35 -0
  14. package/src/agent-flow/components/stubs/DatasetChooser.vue +70 -0
  15. package/src/agent-flow/components/stubs/Embedding.vue +22 -0
  16. package/src/agent-flow/components/stubs/ModelSelect.vue +24 -0
  17. package/src/agent-flow/components/stubs/RestfulSelectCard.vue +24 -0
  18. package/src/agent-flow/components/stubs/ToolChooser.vue +96 -0
  19. package/src/agent-flow/components/stubs/TriggersItemCard.vue +126 -0
  20. package/src/agent-flow/components/stubs/VariableModal.vue +115 -0
  21. package/src/agent-flow/index.ts +73 -0
  22. package/src/agent-flow/stores/workflow.ts +72 -0
  23. package/src/agent-flow/utils/langUtils.ts +173 -0
  24. package/src/agent-flow/workflow/Ability.vue +65 -0
  25. package/src/agent-flow/workflow/AuthorizationItem.vue +101 -0
  26. package/src/agent-flow/workflow/ConversationVar.vue +42 -0
  27. package/src/agent-flow/workflow/CustomEdge.vue +94 -0
  28. package/src/agent-flow/workflow/EnvironmentVar.vue +40 -0
  29. package/src/agent-flow/workflow/FlowDesigner.vue +2802 -0
  30. package/src/agent-flow/workflow/Icon.vue +179 -0
  31. package/src/agent-flow/workflow/NodeConfig.vue +509 -0
  32. package/src/agent-flow/workflow/NodeConfigCard.vue +460 -0
  33. package/src/agent-flow/workflow/NodeHandle.vue +147 -0
  34. package/src/agent-flow/workflow/NodeHeaderToolbar.vue +77 -0
  35. package/src/agent-flow/workflow/NodeHoverToolbar.vue +176 -0
  36. package/src/agent-flow/workflow/OutputItemCard.vue +668 -0
  37. package/src/agent-flow/workflow/ParamTableItem.vue +200 -0
  38. package/src/agent-flow/workflow/StructTable.vue +202 -0
  39. package/src/agent-flow/workflow/VarInsertField.vue +517 -0
  40. package/src/agent-flow/workflow/VarSelectField.vue +223 -0
  41. package/src/agent-flow/workflow/VariableSelectorItem.vue +48 -0
  42. package/src/agent-flow/workflow/WfField.vue +206 -0
  43. package/src/agent-flow/workflow/_config-base.css +470 -0
  44. package/src/agent-flow/workflow/composables/useNode.js +55 -0
  45. package/src/agent-flow/workflow/index.vue +53 -0
  46. package/src/agent-flow/workflow/nodeCard/AgentNodeCard.vue +180 -0
  47. package/src/agent-flow/workflow/nodeCard/AnswerNodeCard.vue +65 -0
  48. package/src/agent-flow/workflow/nodeCard/ClassifierCard.vue +152 -0
  49. package/src/agent-flow/workflow/nodeCard/CodeNodeCard.vue +139 -0
  50. package/src/agent-flow/workflow/nodeCard/ConditionNodeCard.vue +323 -0
  51. package/src/agent-flow/workflow/nodeCard/DocumentExtractorCard.vue +83 -0
  52. package/src/agent-flow/workflow/nodeCard/EndNodeCard.vue +123 -0
  53. package/src/agent-flow/workflow/nodeCard/HttpNodeCard.vue +451 -0
  54. package/src/agent-flow/workflow/nodeCard/HumanInputCard.vue +152 -0
  55. package/src/agent-flow/workflow/nodeCard/IterationCard.vue +66 -0
  56. package/src/agent-flow/workflow/nodeCard/KnowledgeRetrievalCard.vue +48 -0
  57. package/src/agent-flow/workflow/nodeCard/LLMNodeCard.vue +206 -0
  58. package/src/agent-flow/workflow/nodeCard/ListOperatorCard.vue +188 -0
  59. package/src/agent-flow/workflow/nodeCard/ParameterExtractorCard.vue +352 -0
  60. package/src/agent-flow/workflow/nodeCard/ServiceApiNodeCard.vue +188 -0
  61. package/src/agent-flow/workflow/nodeCard/StartNodeCard.vue +216 -0
  62. package/src/agent-flow/workflow/nodeCard/VariableAssignerCard.vue +125 -0
  63. package/src/agent-flow/workflow/nodeCard/VariableNodeCard.vue +121 -0
  64. package/src/agent-flow/workflow/nodes/AgentNode.vue +122 -0
  65. package/src/agent-flow/workflow/nodes/AnswerNode.vue +99 -0
  66. package/src/agent-flow/workflow/nodes/ClassifierNode.vue +199 -0
  67. package/src/agent-flow/workflow/nodes/CodeNode.vue +152 -0
  68. package/src/agent-flow/workflow/nodes/ConditionNode.vue +232 -0
  69. package/src/agent-flow/workflow/nodes/DocumentExtractorNode.vue +96 -0
  70. package/src/agent-flow/workflow/nodes/EndNode.vue +119 -0
  71. package/src/agent-flow/workflow/nodes/FileUploadNode.vue +97 -0
  72. package/src/agent-flow/workflow/nodes/HttpNode.vue +204 -0
  73. package/src/agent-flow/workflow/nodes/HumanInputNode.vue +110 -0
  74. package/src/agent-flow/workflow/nodes/IterationNode.vue +98 -0
  75. package/src/agent-flow/workflow/nodes/KnowledgeRetrievalNode.vue +253 -0
  76. package/src/agent-flow/workflow/nodes/LLMNode.vue +134 -0
  77. package/src/agent-flow/workflow/nodes/ListOperatorNode.vue +111 -0
  78. package/src/agent-flow/workflow/nodes/LoopNode.vue +94 -0
  79. package/src/agent-flow/workflow/nodes/ParameterExtractorNode.vue +147 -0
  80. package/src/agent-flow/workflow/nodes/ServiceApiNode.vue +161 -0
  81. package/src/agent-flow/workflow/nodes/StartNode.vue +199 -0
  82. package/src/agent-flow/workflow/nodes/TemplateNode.vue +103 -0
  83. package/src/agent-flow/workflow/nodes/UserInputNode.vue +92 -0
  84. package/src/agent-flow/workflow/nodes/VariableAssignerNode.vue +145 -0
  85. package/src/agent-flow/workflow/nodes/VariableNode.vue +130 -0
  86. package/src/agent-flow/workflow/nodes/_node-base.css +338 -0
  87. package/src/agent-flow/workflow/utils/node_card_form.ts +335 -0
  88. package/src/agent-flow/workflow/utils/node_config.ts +63 -0
  89. package/src/agent-flow/workflow/utils/workflow_utils.ts +151 -0
  90. package/src/agent-studio/adapters/springAgentStart.ts +390 -0
  91. package/src/agent-studio/api/index.ts +1 -0
  92. package/src/agent-studio/api/types.ts +173 -0
  93. package/src/agent-studio/components/AgentApiDocs.vue +500 -0
  94. package/src/agent-studio/components/AgentAppsPage.vue +1601 -0
  95. package/src/agent-studio/components/AgentCardGrid.vue +259 -0
  96. package/src/agent-studio/components/AgentChatPage.vue +553 -0
  97. package/src/agent-studio/components/AgentDebugPanel.vue +350 -0
  98. package/src/agent-studio/components/AgentLogsPanel.vue +391 -0
  99. package/src/agent-studio/components/AgentMonitorPanel.vue +204 -0
  100. package/src/agent-studio/components/AgentOrchestrate.vue +505 -0
  101. package/src/agent-studio/components/AgentPromptEditor.vue +237 -0
  102. package/src/agent-studio/components/AgentStudioShell.vue +227 -0
  103. package/src/agent-studio/components/AgentToolsPanel.vue +394 -0
  104. package/src/agent-studio/components/AgentVariablesPanel.vue +205 -0
  105. package/src/agent-studio/components/ApiKeyManager.vue +251 -0
  106. package/src/agent-studio/components/AppDesignDrawer.vue +3391 -0
  107. package/src/agent-studio/components/CreateAppModal.vue +737 -0
  108. package/src/agent-studio/components/SparkChart.vue +200 -0
  109. package/src/agent-studio/components/VariableEditorModal.vue +499 -0
  110. package/src/agent-studio/composables/useAgentStudio.ts +347 -0
  111. package/src/agent-studio/index.ts +60 -0
  112. package/src/agent-studio/panels/DrawerFlowDesigner.vue +203 -0
  113. package/src/agent-studio/panels/LogAnnotationPanel.vue +490 -0
  114. package/src/agent-studio/panels/MonitorPanel.vue +535 -0
  115. package/src/agent-studio/types.ts +242 -0
  116. package/src/index.ts +155 -0
  117. package/src/knowledge-hub/adapters/springAgentStart.ts +472 -0
  118. package/src/knowledge-hub/components/AddDocumentsWizard.vue +1452 -0
  119. package/src/knowledge-hub/components/CreateDatasetWizard.vue +1723 -0
  120. package/src/knowledge-hub/components/DatasetCardGrid.vue +467 -0
  121. package/src/knowledge-hub/components/DatasetDetailDrawer.vue +888 -0
  122. package/src/knowledge-hub/components/DatasetPicker.vue +65 -0
  123. package/src/knowledge-hub/components/DatasetPickerModal.vue +526 -0
  124. package/src/knowledge-hub/components/DatasetSettingsPanel.vue +908 -0
  125. package/src/knowledge-hub/components/DatasetSidebar.vue +781 -0
  126. package/src/knowledge-hub/components/DocumentChunksView.vue +802 -0
  127. package/src/knowledge-hub/components/DocumentTable.vue +552 -0
  128. package/src/knowledge-hub/components/HitTestingPanel.vue +74 -0
  129. package/src/knowledge-hub/components/KnowledgeApp.vue +66 -0
  130. package/src/knowledge-hub/components/KnowledgeHubApp.vue +504 -0
  131. package/src/knowledge-hub/components/RecallTestingPanelV2.vue +515 -0
  132. package/src/knowledge-hub/components/RetrievalConfigPopover.vue +270 -0
  133. package/src/knowledge-hub/components/RetrievalMethodPicker.vue +547 -0
  134. package/src/knowledge-hub/components/RetrievedList.vue +24 -0
  135. package/src/knowledge-hub/components/internal/KhDialog.vue +195 -0
  136. package/src/knowledge-hub/composables/useKnowledge.ts +89 -0
  137. package/src/knowledge-hub/i18n/index.ts +2 -0
  138. package/src/knowledge-hub/i18n/messages.ts +422 -0
  139. package/src/knowledge-hub/i18n/useKhI18n.ts +107 -0
  140. package/src/knowledge-hub/index.ts +46 -0
  141. package/src/knowledge-hub/styles/index.css +4 -0
  142. package/src/knowledge-hub/styles/tokens.css +138 -0
  143. package/src/knowledge-hub/types/api.ts +213 -0
  144. package/src/knowledge-hub/types/dataset.ts +88 -0
  145. package/src/knowledge-hub/types/document.ts +45 -0
  146. package/src/knowledge-hub/types/index.ts +9 -0
  147. package/src/knowledge-hub/types/retrieval.ts +46 -0
  148. package/src/provider-hub/components/CredentialForm.vue +103 -0
  149. package/src/provider-hub/components/DefaultModelsPanel.vue +270 -0
  150. package/src/provider-hub/components/GroupedModelSelect.vue +445 -0
  151. package/src/provider-hub/components/ModelCardGrid.vue +332 -0
  152. package/src/provider-hub/components/ModelParameterDrawer.vue +739 -0
  153. package/src/provider-hub/components/ModelPickerPopover.vue +1282 -0
  154. package/src/provider-hub/components/ProviderApp.vue +159 -0
  155. package/src/provider-hub/components/ProviderCredentialModal.vue +321 -0
  156. package/src/provider-hub/components/ProviderGallery.vue +131 -0
  157. package/src/provider-hub/components/ProviderHubShell.vue +1992 -0
  158. package/src/provider-hub/components/ProviderIcon.vue +130 -0
  159. package/src/provider-hub/composables/useProviderHub.ts +358 -0
  160. package/src/provider-hub/index.ts +43 -0
  161. package/src/provider-hub/svg/MiniMax.svg +1 -0
  162. package/src/provider-hub/svg/Volcengine.svg +1 -0
  163. package/src/provider-hub/svg/Zhipu.svg +1 -0
  164. package/src/provider-hub/svg/deepseek.svg +1 -0
  165. package/src/provider-hub/svg/moonshot.svg +1 -0
  166. package/src/provider-hub/svg/openai.svg +1 -0
  167. package/src/provider-hub/svg/qwen.svg +1 -0
  168. package/src/provider-hub/svg/siliconflow.svg +1 -0
  169. package/src/provider-hub/types.ts +256 -0
@@ -0,0 +1,451 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue';
3
+
4
+ import PromptEditor from '@/components/PromptEditor.vue';
5
+ import PromptEditorTagPanel from '@/components/PromptEditorTagPanel.vue';
6
+ import RestfulSelectCard from '@/components/stubs/RestfulSelectCard.vue';
7
+ import WfField from '@/workflow/WfField.vue';
8
+ import workflow_utils from '@/workflow/utils/workflow_utils';
9
+
10
+ import AuthorizationItem from '../AuthorizationItem.vue';
11
+ import ParamTableItem from '../ParamTableItem.vue';
12
+
13
+ defineProps<{
14
+ /**
15
+ * 当前节点在 vue-flow 里的真实 id —— 变量插入面板需要它来定位上游节点。
16
+ * 由 NodeConfigCard 从 selectNode.id 传下来,不要读 formState.id(formState
17
+ * 是 node.data 的深拷贝,通常没有 id 字段)。
18
+ */
19
+ nodeId?: string;
20
+ }>();
21
+
22
+ const formState: any = defineModel();
23
+
24
+ const targetElement = ref<HTMLElement | null>(null);
25
+ const restfulSelectCard = ref();
26
+ const showAttr = ref<boolean>(false);
27
+
28
+ const checkAttr = (event: any) => {
29
+ targetElement.value = event.currentTarget;
30
+ showAttr.value = true;
31
+ };
32
+ const closeAttrPanel = () => {
33
+ showAttr.value = false;
34
+ };
35
+
36
+ const openRestful = () => {
37
+ restfulSelectCard.value?.showModal?.();
38
+ };
39
+
40
+ const selectAttr = (variableSelector: any) => {
41
+ formState.value.body.BINARY = variableSelector;
42
+ showAttr.value = false;
43
+ };
44
+
45
+ const getVarSelectLabel = (variableSelector: any) =>
46
+ workflow_utils.getVariableLabel(variableSelector);
47
+
48
+ const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
49
+
50
+ /** Body type 与显示标签映射 */
51
+ const BODY_TYPES = [
52
+ { value: 'NONE', label: 'none' },
53
+ { value: 'FORM_DATA', label: 'form-data' },
54
+ { value: 'X_WWW_FORM_URLENCODED', label: 'x-www-form-urlencoded' },
55
+ { value: 'JSON', label: 'JSON' },
56
+ { value: 'RAW', label: 'raw' },
57
+ { value: 'BINARY', label: 'binary' },
58
+ ] as const;
59
+
60
+ const methodStyle = computed(() => {
61
+ const method = (formState.value.method || 'GET').toUpperCase();
62
+ const colors: Record<string, string> = {
63
+ GET: '#2563eb',
64
+ POST: '#059669',
65
+ PUT: '#d97706',
66
+ DELETE: '#dc2626',
67
+ PATCH: '#7c3aed',
68
+ };
69
+ return { '--http-method-color': colors[method] || '#6b7280' };
70
+ });
71
+
72
+ /** 非空条目计数(headers / parameters / form rows) */
73
+ const nonEmptyCount = (rows: any) =>
74
+ Array.isArray(rows) ? rows.filter((r) => r && r.name).length : 0;
75
+
76
+ const headerCount = computed(() => nonEmptyCount(formState.value.headers));
77
+ const paramCount = computed(() => nonEmptyCount(formState.value.parameters));
78
+ const bodyHasContent = computed(() => {
79
+ const t = formState.value.bodyType;
80
+ const body = formState.value.body || {};
81
+ if (t === 'NONE') return false;
82
+ if (t === 'JSON') return !!(body.JSON && String(body.JSON).trim());
83
+ if (t === 'RAW') return !!(body.RAW && String(body.RAW).trim());
84
+ if (t === 'BINARY') return !!body.BINARY;
85
+ if (t === 'FORM_DATA') return nonEmptyCount(body.FORM_DATA) > 0;
86
+ if (t === 'X_WWW_FORM_URLENCODED') return nonEmptyCount(body.X_WWW_FORM_URLENCODED) > 0;
87
+ return false;
88
+ });
89
+ const authEnabled = computed(() => {
90
+ const auth = formState.value.authorization;
91
+ return !!(auth && auth.auth_type && auth.auth_type !== 'none');
92
+ });
93
+ </script>
94
+
95
+ <template>
96
+ <PromptEditorTagPanel
97
+ :show="showAttr"
98
+ :target-element="targetElement"
99
+ :node-id="nodeId"
100
+ @close="closeAttrPanel"
101
+ @select="selectAttr"
102
+ />
103
+ <RestfulSelectCard ref="restfulSelectCard" />
104
+
105
+ <!-- API:method + URL + 超时 一体化 -->
106
+ <div class="wf-config-section">
107
+ <WfField title="API" required>
108
+ <template #operations>
109
+ <a-button type="link" size="small" @click="openRestful">
110
+ 从服务导入
111
+ </a-button>
112
+ </template>
113
+
114
+ <div class="wf-http-url" :style="methodStyle">
115
+ <a-select
116
+ v-model:value="formState.method"
117
+ :bordered="false"
118
+ size="small"
119
+ class="wf-http-method"
120
+ >
121
+ <a-select-option v-for="m in METHODS" :key="m" :value="m">
122
+ {{ m }}
123
+ </a-select-option>
124
+ </a-select>
125
+ <a-input
126
+ v-model:value="formState.url"
127
+ :bordered="false"
128
+ class="wf-http-url-input"
129
+ placeholder="/api/foo 或 https://api.example.com/endpoint"
130
+ />
131
+ <a-tooltip title="请求超时(秒),1-600">
132
+ <div class="wf-http-timeout">
133
+ <span class="wf-http-timeout-label">⏱</span>
134
+ <a-input-number
135
+ v-model:value="formState.timeoutSeconds"
136
+ :min="1"
137
+ :max="600"
138
+ :step="1"
139
+ :controls="false"
140
+ :bordered="false"
141
+ size="small"
142
+ placeholder="30"
143
+ class="wf-http-timeout-input"
144
+ />
145
+ <span class="wf-http-timeout-suffix">s</span>
146
+ </div>
147
+ </a-tooltip>
148
+ <a-tooltip title="失败重试次数(0-10)。仅在服务器无响应/超时时重试,返回错误码不重试。">
149
+ <div class="wf-http-timeout">
150
+ <span class="wf-http-timeout-label">↻</span>
151
+ <a-input-number
152
+ v-model:value="formState.maxRetries"
153
+ :min="0"
154
+ :max="10"
155
+ :step="1"
156
+ :controls="false"
157
+ :bordered="false"
158
+ size="small"
159
+ placeholder="0"
160
+ class="wf-http-timeout-input"
161
+ />
162
+ <span class="wf-http-timeout-suffix">次</span>
163
+ </div>
164
+ </a-tooltip>
165
+ </div>
166
+ </WfField>
167
+ </div>
168
+
169
+ <!-- Authorization -->
170
+ <div class="wf-config-section">
171
+ <WfField title="Authorization" foldable :default-fold="!authEnabled">
172
+ <template v-if="authEnabled" #operations>
173
+ <span class="wf-http-badge wf-http-badge-on">已启用</span>
174
+ </template>
175
+ <AuthorizationItem
176
+ v-model="formState.authorization"
177
+ name="headers"
178
+ :node-id="nodeId"
179
+ />
180
+ </WfField>
181
+ </div>
182
+
183
+ <!-- Headers -->
184
+ <div class="wf-config-section">
185
+ <WfField title="Headers" foldable :default-fold="headerCount === 0">
186
+ <template v-if="headerCount > 0" #operations>
187
+ <span class="wf-http-badge">{{ headerCount }}</span>
188
+ </template>
189
+ <ParamTableItem v-model="formState.headers" name="headers" :node-id="nodeId" />
190
+ </WfField>
191
+ </div>
192
+
193
+ <!-- Query 参数 -->
194
+ <div class="wf-config-section">
195
+ <WfField title="Query 参数" foldable :default-fold="paramCount === 0">
196
+ <template v-if="paramCount > 0" #operations>
197
+ <span class="wf-http-badge">{{ paramCount }}</span>
198
+ </template>
199
+ <ParamTableItem
200
+ v-model="formState.parameters"
201
+ name="parameters"
202
+ :node-id="nodeId"
203
+ />
204
+ </WfField>
205
+ </div>
206
+
207
+ <!-- Body -->
208
+ <div class="wf-config-section">
209
+ <WfField title="Body">
210
+ <template v-if="bodyHasContent" #operations>
211
+ <span class="wf-http-badge">{{ formState.bodyType.toLowerCase().replace(/_/g, '-') }}</span>
212
+ </template>
213
+
214
+ <!-- Body 类型切换:紧凑的 chip 风格 -->
215
+ <div class="wf-http-body-tabs">
216
+ <button
217
+ v-for="t in BODY_TYPES"
218
+ :key="t.value"
219
+ class="wf-http-body-tab"
220
+ :class="{ 'is-active': formState.bodyType === t.value }"
221
+ @click="formState.bodyType = t.value"
222
+ >
223
+ {{ t.label }}
224
+ </button>
225
+ </div>
226
+
227
+ <!-- Body 内容按类型分发 -->
228
+ <div class="wf-http-body-body">
229
+ <div v-if="formState.bodyType === 'NONE'" class="wf-http-body-empty">
230
+ 不发送 body
231
+ </div>
232
+
233
+ <div v-else-if="formState.bodyType === 'BINARY'" class="wf-http-binary">
234
+ <div class="wf-http-binary-trigger" @click="checkAttr($event)">
235
+ <template v-if="formState.body.BINARY">
236
+ <a-tag color="processing">
237
+ {{ getVarSelectLabel(formState.body.BINARY) }}
238
+ </a-tag>
239
+ </template>
240
+ <span v-else class="wf-http-binary-hint">
241
+ 点击选择二进制变量(file 类型)
242
+ </span>
243
+ </div>
244
+ </div>
245
+
246
+ <PromptEditor
247
+ v-else-if="formState.bodyType === 'JSON'"
248
+ title="JSON"
249
+ :node-id="nodeId"
250
+ v-model="formState.body.JSON"
251
+ min-height="120px"
252
+ />
253
+
254
+ <PromptEditor
255
+ v-else-if="formState.bodyType === 'RAW'"
256
+ title="RAW"
257
+ :node-id="nodeId"
258
+ v-model="formState.body.RAW"
259
+ min-height="120px"
260
+ />
261
+
262
+ <ParamTableItem
263
+ v-else-if="formState.bodyType === 'FORM_DATA'"
264
+ v-model="formState.body.FORM_DATA"
265
+ name="FORM_DATA"
266
+ :node-id="nodeId"
267
+ />
268
+
269
+ <ParamTableItem
270
+ v-else-if="formState.bodyType === 'X_WWW_FORM_URLENCODED'"
271
+ v-model="formState.body.X_WWW_FORM_URLENCODED"
272
+ name="X_WWW_FORM_URLENCODED"
273
+ :node-id="nodeId"
274
+ />
275
+ </div>
276
+ </WfField>
277
+ </div>
278
+ </template>
279
+
280
+ <style scoped>
281
+ /* -------------------------------------------------------------
282
+ * API 一体化输入条:[METHOD ▼] │ [URL] │ [⏱ 30 s]
283
+ * 三段用 1px 竖分割线分隔,整条聚焦时描个统一的 primary ring。
284
+ * ------------------------------------------------------------- */
285
+ .wf-http-url {
286
+ display: flex;
287
+ align-items: stretch;
288
+ background: #ffffff;
289
+ border: 1px solid #e5e7eb;
290
+ border-radius: 6px;
291
+ overflow: hidden;
292
+ transition: border-color 0.15s, box-shadow 0.15s;
293
+ }
294
+
295
+ .wf-http-url:focus-within {
296
+ border-color: #6366f1;
297
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.12);
298
+ }
299
+
300
+ .wf-http-method {
301
+ flex: none;
302
+ width: 88px;
303
+ border-right: 1px solid #e5e7eb;
304
+ background: color-mix(in srgb, var(--http-method-color) 10%, transparent);
305
+ }
306
+
307
+ .wf-http-method :deep(.ant-select-selector) {
308
+ padding: 0 8px !important;
309
+ font-weight: 700;
310
+ color: var(--http-method-color);
311
+ font-size: 12px;
312
+ letter-spacing: 0.4px;
313
+ }
314
+
315
+ .wf-http-url-input {
316
+ flex: 1;
317
+ min-width: 0;
318
+ }
319
+
320
+ /* 超时嵌入右侧,字号收敛、单位后缀、无 controls */
321
+ .wf-http-timeout {
322
+ display: flex;
323
+ align-items: center;
324
+ flex: none;
325
+ padding: 0 8px;
326
+ gap: 2px;
327
+ color: #6b7280;
328
+ background: #fafafa;
329
+ border-left: 1px solid #e5e7eb;
330
+ font-size: 11px;
331
+ }
332
+
333
+ .wf-http-timeout-label {
334
+ font-size: 12px;
335
+ opacity: 0.7;
336
+ }
337
+
338
+ .wf-http-timeout-input {
339
+ width: 42px;
340
+ }
341
+
342
+ .wf-http-timeout-input :deep(.ant-input-number-input) {
343
+ padding: 0 !important;
344
+ height: 30px;
345
+ font-size: 12px;
346
+ text-align: right;
347
+ color: #1f2937;
348
+ }
349
+
350
+ .wf-http-timeout-suffix {
351
+ font-size: 11px;
352
+ color: #9ca3af;
353
+ }
354
+
355
+ /* -------------------------------------------------------------
356
+ * 计数/状态徽章 —— 折叠标题右侧
357
+ * ------------------------------------------------------------- */
358
+ .wf-http-badge {
359
+ display: inline-flex;
360
+ align-items: center;
361
+ justify-content: center;
362
+ min-width: 18px;
363
+ padding: 0 6px;
364
+ height: 18px;
365
+ font-size: 10px;
366
+ font-weight: 600;
367
+ color: #4338ca;
368
+ background: #eef2ff;
369
+ border-radius: 9px;
370
+ letter-spacing: 0.2px;
371
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
372
+ text-transform: none;
373
+ }
374
+
375
+ .wf-http-badge-on {
376
+ color: #047857;
377
+ background: #d1fae5;
378
+ }
379
+
380
+ /* -------------------------------------------------------------
381
+ * Body 类型切换:更紧凑的 chip
382
+ * ------------------------------------------------------------- */
383
+ .wf-http-body-tabs {
384
+ display: flex;
385
+ align-items: center;
386
+ gap: 2px;
387
+ padding: 2px;
388
+ background: #f3f4f6;
389
+ border-radius: 6px;
390
+ overflow-x: auto;
391
+ }
392
+
393
+ .wf-http-body-tab {
394
+ flex: none;
395
+ padding: 3px 8px;
396
+ font-size: 11px;
397
+ color: #6b7280;
398
+ background: transparent;
399
+ border: none;
400
+ border-radius: 4px;
401
+ cursor: pointer;
402
+ white-space: nowrap;
403
+ transition: background 0.12s, color 0.12s;
404
+ }
405
+
406
+ .wf-http-body-tab:hover {
407
+ color: #1f2937;
408
+ }
409
+
410
+ .wf-http-body-tab.is-active {
411
+ color: #4338ca;
412
+ background: #ffffff;
413
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
414
+ font-weight: 500;
415
+ }
416
+
417
+ .wf-http-body-body {
418
+ margin-top: 8px;
419
+ }
420
+
421
+ .wf-http-body-empty {
422
+ padding: 8px 12px;
423
+ text-align: center;
424
+ font-size: 11px;
425
+ color: #9ca3af;
426
+ background: #f9fafb;
427
+ border: 1px dashed #e5e7eb;
428
+ border-radius: 6px;
429
+ }
430
+
431
+ .wf-http-binary-trigger {
432
+ display: flex;
433
+ align-items: center;
434
+ padding: 6px 10px;
435
+ min-height: 32px;
436
+ background: #f9fafb;
437
+ border: 1px dashed #d1d5db;
438
+ border-radius: 6px;
439
+ cursor: pointer;
440
+ transition: border-color 0.15s;
441
+ }
442
+
443
+ .wf-http-binary-trigger:hover {
444
+ border-color: #6366f1;
445
+ }
446
+
447
+ .wf-http-binary-hint {
448
+ font-size: 12px;
449
+ color: #9ca3af;
450
+ }
451
+ </style>
@@ -0,0 +1,152 @@
1
+ <script setup lang="ts">
2
+ import { h } from 'vue';
3
+
4
+ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
5
+
6
+ import PromptEditor from '@/components/PromptEditor.vue';
7
+ import WfField from '@/workflow/WfField.vue';
8
+
9
+ defineProps<{ nodeId?: string }>();
10
+
11
+ const formState: any = defineModel();
12
+
13
+ const APPROVAL_TYPES = [
14
+ { value: 'approve', label: '审批(是/否)' },
15
+ { value: 'form', label: '表单填写' },
16
+ { value: 'text', label: '文本回复' },
17
+ ];
18
+
19
+ const FIELD_TYPES = ['string', 'number', 'boolean', 'select'];
20
+
21
+ const addField = () => {
22
+ if (!Array.isArray(formState.value.formFields)) formState.value.formFields = [];
23
+ formState.value.formFields.push({
24
+ name: '',
25
+ label: '',
26
+ type: 'string',
27
+ required: false,
28
+ });
29
+ };
30
+
31
+ const removeField = (index: number) => {
32
+ formState.value.formFields.splice(index, 1);
33
+ };
34
+ </script>
35
+
36
+ <template>
37
+ <div class="wf-config-section">
38
+ <WfField title="介入类型" required>
39
+ <template #tooltip>
40
+ 选择需要人工做的事:审批只有是/否,表单可自定义字段,文本回复要求一段文字。
41
+ </template>
42
+ <a-select
43
+ v-model:value="formState.approvalType"
44
+ :options="APPROVAL_TYPES"
45
+ style="width: 100%"
46
+ />
47
+ </WfField>
48
+ </div>
49
+
50
+ <PromptEditor
51
+ class="wf-config-prompt"
52
+ title="提示信息"
53
+ :node-id="nodeId"
54
+ v-model="formState.prompt"
55
+ />
56
+
57
+ <div v-if="formState.approvalType === 'form'" class="wf-config-section">
58
+ <WfField title="表单字段">
59
+ <template #operations>
60
+ <a-button
61
+ :icon="h(PlusOutlined)"
62
+ size="small"
63
+ type="primary"
64
+ @click="addField"
65
+ />
66
+ </template>
67
+
68
+ <div
69
+ v-if="!formState.formFields || formState.formFields.length === 0"
70
+ class="human-empty"
71
+ >
72
+ 点击右上角 + 添加字段
73
+ </div>
74
+
75
+ <div class="human-field-list">
76
+ <div
77
+ v-for="(f, index) in formState.formFields"
78
+ :key="index"
79
+ class="human-field-row"
80
+ >
81
+ <a-input
82
+ v-model:value="f.name"
83
+ placeholder="字段名"
84
+ size="small"
85
+ style="width: 100px"
86
+ />
87
+ <a-input
88
+ v-model:value="f.label"
89
+ placeholder="显示名"
90
+ size="small"
91
+ style="flex: 1"
92
+ />
93
+ <a-select
94
+ v-model:value="f.type"
95
+ :options="FIELD_TYPES.map((t) => ({ value: t, label: t }))"
96
+ size="small"
97
+ style="width: 88px"
98
+ />
99
+ <a-checkbox v-model:checked="f.required">必填</a-checkbox>
100
+ <a-button
101
+ :icon="h(DeleteOutlined)"
102
+ size="small"
103
+ type="text"
104
+ danger
105
+ @click="removeField(index)"
106
+ />
107
+ </div>
108
+ </div>
109
+ </WfField>
110
+ </div>
111
+
112
+ <div class="wf-config-section">
113
+ <WfField title="超时(秒)" is-subtitle>
114
+ <template #tooltip>
115
+ 超过时间无响应时工作流会走超时分支或直接失败。
116
+ </template>
117
+ <a-input-number
118
+ v-model:value="formState.timeout"
119
+ :min="0"
120
+ :step="60"
121
+ style="width: 100%"
122
+ />
123
+ </WfField>
124
+ </div>
125
+ </template>
126
+
127
+ <style scoped>
128
+ .human-empty {
129
+ padding: 12px;
130
+ text-align: center;
131
+ font-size: 12px;
132
+ color: #9ca3af;
133
+ background: #f9fafb;
134
+ border: 1px dashed #e5e7eb;
135
+ border-radius: 6px;
136
+ }
137
+
138
+ .human-field-list {
139
+ display: flex;
140
+ flex-direction: column;
141
+ gap: 6px;
142
+ }
143
+
144
+ .human-field-row {
145
+ display: flex;
146
+ align-items: center;
147
+ gap: 6px;
148
+ padding: 6px;
149
+ background: #f9fafb;
150
+ border-radius: 6px;
151
+ }
152
+ </style>
@@ -0,0 +1,66 @@
1
+ <script setup lang="ts">
2
+ import VariableSelector from '@/components/VariableSelector.vue';
3
+ import WfField from '@/workflow/WfField.vue';
4
+
5
+ defineProps<{ nodeId?: string }>();
6
+
7
+ const formState: any = defineModel();
8
+
9
+ const ERROR_MODES = [
10
+ { value: 'terminate', label: '终止工作流' },
11
+ { value: 'continue', label: '跳过并继续' },
12
+ { value: 'default', label: '设默认值继续' },
13
+ ];
14
+ </script>
15
+
16
+ <template>
17
+ <div class="wf-config-section">
18
+ <WfField title="迭代变量" required>
19
+ <template #tooltip>
20
+ 从上游节点选择一个列表变量,子图会对每一项执行一次。
21
+ </template>
22
+ <VariableSelector
23
+ v-model="formState.iteratorVariableSelector"
24
+ :node-id="nodeId"
25
+ placeholder="选择要迭代的列表变量"
26
+ />
27
+ </WfField>
28
+
29
+ <WfField title="聚合输出">
30
+ <template #tooltip>
31
+ 指定子图内哪个变量作为每次迭代的返回,最终聚合成结果列表。
32
+ </template>
33
+ <VariableSelector
34
+ v-model="formState.outputVariableSelector"
35
+ :node-id="nodeId"
36
+ placeholder="选择每次迭代的输出变量"
37
+ />
38
+ </WfField>
39
+ </div>
40
+
41
+ <div class="wf-config-section">
42
+ <WfField title="并行度" is-subtitle>
43
+ <template #tooltip>
44
+ 同时并发执行的迭代数。默认串行(1),设为 N 会同时运行 N 个子图。
45
+ </template>
46
+ <a-input-number
47
+ v-model:value="formState.parallelSize"
48
+ :min="1"
49
+ :max="20"
50
+ style="width: 100%"
51
+ placeholder="1"
52
+ />
53
+ </WfField>
54
+
55
+ <WfField title="错误处理" is-subtitle>
56
+ <template #tooltip>
57
+ 某次子图执行失败时如何处理。
58
+ </template>
59
+ <a-select
60
+ v-model:value="formState.errorMode"
61
+ :options="ERROR_MODES"
62
+ style="width: 100%"
63
+ />
64
+ </WfField>
65
+ </div>
66
+ </template>