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,48 @@
1
+ <script setup lang="ts">
2
+ import DatasetItemCard from '@/components/DatasetItemCard.vue';
3
+ import VariableSelector from '@/components/VariableSelector.vue';
4
+ import OutputItemCard from '@/workflow/OutputItemCard.vue';
5
+ import WfField from '@/workflow/WfField.vue';
6
+
7
+ defineProps<{ nodeId?: string }>();
8
+
9
+ const formState: any = defineModel();
10
+ </script>
11
+
12
+ <template>
13
+ <div class="wf-config-section">
14
+ <WfField title="查询变量" required>
15
+ <template #tooltip>
16
+ 作为检索关键词的上游变量,通常是用户提问。
17
+ </template>
18
+ <VariableSelector
19
+ v-model="formState.queryVariableSelector"
20
+ :node-id="nodeId"
21
+ placeholder="选择查询变量"
22
+ />
23
+ </WfField>
24
+ </div>
25
+
26
+ <div class="wf-config-section">
27
+ <WfField title="数据集" required>
28
+ <template #tooltip>
29
+ 选择一个或多个知识库;开启动态变量后可按运行时上下文切换数据集。
30
+ </template>
31
+ <DatasetItemCard v-model="formState.dataset" :node-id="nodeId">
32
+ <template #dynamic>
33
+ <VariableSelector
34
+ v-model="formState.dataset.dynamicVariableSelector"
35
+ :node-id="nodeId"
36
+ placeholder="选择动态变量"
37
+ />
38
+ </template>
39
+ </DatasetItemCard>
40
+ </WfField>
41
+ </div>
42
+
43
+ <div class="wf-config-section">
44
+ <WfField title="输出" foldable default-fold>
45
+ <OutputItemCard v-model="formState" />
46
+ </WfField>
47
+ </div>
48
+ </template>
@@ -0,0 +1,206 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+
4
+ import { getCurrentModel } from '@/adapter/backend';
5
+ import MemoryWindow from '@/components/MemoryWindow.vue';
6
+ import PromptEditor from '@/components/PromptEditor.vue';
7
+ import PromptEditorTagPanel from '@/components/PromptEditorTagPanel.vue';
8
+ import ModelPickerPopover from '../../../provider-hub/components/ModelPickerPopover.vue';
9
+ import OutputItemCard from '@/workflow/OutputItemCard.vue';
10
+ import WfField from '@/workflow/WfField.vue';
11
+ import workflow_utils from '@/workflow/utils/workflow_utils';
12
+
13
+ defineProps({
14
+ attrListGroup: {
15
+ type: Array,
16
+ default: () => [],
17
+ },
18
+ /** 当前节点 id —— 变量插入面板需要,由 NodeConfigCard 从 selectNode.id 传下来。 */
19
+ nodeId: {
20
+ type: String,
21
+ default: '',
22
+ },
23
+ });
24
+
25
+ const formState: any = defineModel();
26
+
27
+ const targetElement = ref<HTMLElement | null>(null);
28
+ const showAttr = ref<boolean>(false);
29
+ const attrTargetKey = ref<'apiKey' | null>(null);
30
+
31
+ const loadDefaultModel = async () => {
32
+ const res: any = await getCurrentModel('LLM');
33
+ const data = res?.data ?? {};
34
+ if (!formState.value.model) formState.value.model = {};
35
+ formState.value.model.modelName = data.modelName;
36
+ formState.value.model.provider = data.provider ?? data.providerName;
37
+ formState.value.model.providerName = data.provider ?? data.providerName;
38
+ formState.value.model.modelProvider = data.provider ?? data.providerName;
39
+ formState.value.model.modelType = data.modelType ?? 'LLM';
40
+ };
41
+
42
+ const checkApiKey = (event: any) => {
43
+ targetElement.value = event.currentTarget;
44
+ attrTargetKey.value = 'apiKey';
45
+ showAttr.value = true;
46
+ };
47
+
48
+ const closeAttrPanel = () => {
49
+ showAttr.value = false;
50
+ attrTargetKey.value = null;
51
+ };
52
+
53
+ const selectAttr = (variableSelector: any[]) => {
54
+ if (attrTargetKey.value === 'apiKey') {
55
+ if (!formState.value.apiKeySelector) {
56
+ formState.value.apiKeySelector = { variableSelector: [] };
57
+ }
58
+ formState.value.apiKeySelector.variableSelector = variableSelector;
59
+ }
60
+ closeAttrPanel();
61
+ };
62
+
63
+ const stopSequenceTags = ref<string[]>(
64
+ Array.isArray(formState.value?.stop) ? formState.value.stop : [],
65
+ );
66
+ const onStopChange = (val: string[]) => {
67
+ formState.value.stop = val;
68
+ };
69
+
70
+ const RESPONSE_FORMATS = [
71
+ { value: 'text', label: '文本 (text)' },
72
+ { value: 'json_object', label: 'JSON 对象' },
73
+ { value: 'json_schema', label: 'JSON Schema' },
74
+ ];
75
+ </script>
76
+
77
+ <template>
78
+ <PromptEditorTagPanel
79
+ :show="showAttr"
80
+ :target-element="targetElement"
81
+ :node-id="nodeId"
82
+ @close="closeAttrPanel"
83
+ @select="selectAttr"
84
+ />
85
+
86
+ <div class="wf-config-section">
87
+ <WfField title="模型" required>
88
+ <template #operations>
89
+ <a-button type="link" size="small" @click="loadDefaultModel">
90
+ 使用默认
91
+ </a-button>
92
+ </template>
93
+ <ModelPickerPopover
94
+ v-model="formState.model"
95
+ model-type="LLM"
96
+ placeholder="点击选择 LLM 模型"
97
+ :width="440"
98
+ />
99
+ </WfField>
100
+
101
+ <WfField title="API Key 变量" is-subtitle>
102
+ <template #tooltip>
103
+ 按用户/租户维度切换密钥时使用;未设置时走后端默认凭据。
104
+ </template>
105
+ <div class="llm-varselect" @click="checkApiKey">
106
+ <a-tag class="llm-varselect-tag">
107
+ {{
108
+ workflow_utils.getVariableLabel(
109
+ formState.apiKeySelector?.variableSelector,
110
+ ) || '点击选择变量'
111
+ }}
112
+ </a-tag>
113
+ </div>
114
+ </WfField>
115
+ </div>
116
+
117
+ <!-- SYSTEM 提示词 -->
118
+ <PromptEditor
119
+ class="wf-config-prompt"
120
+ title="SYSTEM"
121
+ :node-id="nodeId"
122
+ v-model="formState.systemPrompt.text"
123
+ />
124
+
125
+ <!-- USER 提示词 -->
126
+ <PromptEditor
127
+ class="wf-config-prompt"
128
+ title="USER"
129
+ :node-id="nodeId"
130
+ v-model="formState.userPrompt.text"
131
+ />
132
+
133
+ <div class="wf-config-section">
134
+ <WfField title="对话记忆">
135
+ <template #tooltip>
136
+ 控制注入到 prompt 的历史消息条数。开启后按最近 N 轮追加。
137
+ </template>
138
+ <MemoryWindow v-model="formState.memory" />
139
+ </WfField>
140
+ </div>
141
+
142
+ <div class="wf-config-section">
143
+ <WfField title="高级参数" foldable default-fold>
144
+ <WfField title="停止序列" is-subtitle>
145
+ <template #tooltip>
146
+ LLM 生成过程中遇到任意一个字符串会立刻停止输出。
147
+ </template>
148
+ <a-select
149
+ v-model:value="stopSequenceTags"
150
+ mode="tags"
151
+ :token-separators="[',']"
152
+ placeholder="回车或逗号分隔,最多 4 个"
153
+ style="width: 100%"
154
+ @change="onStopChange"
155
+ />
156
+ </WfField>
157
+
158
+ <WfField title="响应格式" is-subtitle>
159
+ <template #tooltip>
160
+ 选择 JSON 会指示模型返回可解析的 JSON。需要模型本身支持该模式。
161
+ </template>
162
+ <a-select
163
+ v-model:value="formState.responseFormat"
164
+ :options="RESPONSE_FORMATS"
165
+ style="width: 100%"
166
+ placeholder="默认文本"
167
+ allow-clear
168
+ />
169
+ </WfField>
170
+
171
+ <WfField title="视觉输入" is-subtitle inline>
172
+ <template #operations>
173
+ <a-switch v-model:checked="formState.vision" size="small" />
174
+ </template>
175
+ </WfField>
176
+ </WfField>
177
+ </div>
178
+
179
+ <div class="wf-config-section">
180
+ <WfField title="输出">
181
+ <OutputItemCard v-model="formState" />
182
+ </WfField>
183
+ </div>
184
+ </template>
185
+
186
+ <style scoped>
187
+ .llm-varselect {
188
+ padding: 4px 8px;
189
+ background: #f9fafb;
190
+ border: 1px dashed #d1d5db;
191
+ border-radius: 6px;
192
+ cursor: pointer;
193
+ transition: border-color 0.15s;
194
+ min-height: 28px;
195
+ display: flex;
196
+ align-items: center;
197
+ }
198
+
199
+ .llm-varselect:hover {
200
+ border-color: #6366f1;
201
+ }
202
+
203
+ .llm-varselect-tag {
204
+ margin: 0;
205
+ }
206
+ </style>
@@ -0,0 +1,188 @@
1
+ <script setup lang="ts">
2
+ import { h } from 'vue';
3
+
4
+ import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
5
+
6
+ import VariableSelector from '@/components/VariableSelector.vue';
7
+ import WfField from '@/workflow/WfField.vue';
8
+ import workflow_utils from '@/workflow/utils/workflow_utils';
9
+
10
+ defineProps<{ nodeId?: string }>();
11
+
12
+ const formState: any = defineModel();
13
+
14
+ const OPERATIONS = [
15
+ { value: 'filter', label: '过滤(filter)' },
16
+ { value: 'map', label: '映射(map)' },
17
+ { value: 'reduce', label: '归约(reduce)' },
18
+ { value: 'slice', label: '截取(slice)' },
19
+ { value: 'sort', label: '排序(sort)' },
20
+ { value: 'reverse', label: '反转(reverse)' },
21
+ { value: 'count', label: '计数(count)' },
22
+ ];
23
+
24
+ const SORT_ORDERS = [
25
+ { value: 'asc', label: '升序' },
26
+ { value: 'desc', label: '降序' },
27
+ ];
28
+
29
+ const addFilter = () => {
30
+ if (!Array.isArray(formState.value.filterConditions)) {
31
+ formState.value.filterConditions = [];
32
+ }
33
+ formState.value.filterConditions.push({
34
+ field: '',
35
+ operator: 'CONTAINS',
36
+ value: '',
37
+ });
38
+ };
39
+
40
+ const removeFilter = (index: number) => {
41
+ formState.value.filterConditions.splice(index, 1);
42
+ };
43
+ </script>
44
+
45
+ <template>
46
+ <div class="wf-config-section">
47
+ <WfField title="输入列表" required>
48
+ <VariableSelector
49
+ v-model="formState.inputVariableSelector"
50
+ :node-id="nodeId"
51
+ placeholder="选择要操作的列表变量"
52
+ />
53
+ </WfField>
54
+
55
+ <WfField title="操作类型" required>
56
+ <a-select
57
+ v-model:value="formState.operation"
58
+ :options="OPERATIONS"
59
+ style="width: 100%"
60
+ />
61
+ </WfField>
62
+ </div>
63
+
64
+ <!-- 各操作对应的额外配置 -->
65
+ <div v-if="formState.operation === 'filter'" class="wf-config-section">
66
+ <WfField title="过滤条件">
67
+ <template #tooltip>
68
+ 所有条件都满足才保留该项。留空字段名表示对整个 item 操作。
69
+ </template>
70
+ <template #operations>
71
+ <a-button
72
+ :icon="h(PlusOutlined)"
73
+ size="small"
74
+ type="primary"
75
+ @click="addFilter"
76
+ />
77
+ </template>
78
+ <div
79
+ v-if="!formState.filterConditions || formState.filterConditions.length === 0"
80
+ class="list-op-empty"
81
+ >
82
+ 点击右上角 + 添加条件
83
+ </div>
84
+ <div class="list-op-filter-list">
85
+ <div
86
+ v-for="(f, i) in formState.filterConditions"
87
+ :key="i"
88
+ class="list-op-filter-row"
89
+ >
90
+ <a-input
91
+ v-model:value="f.field"
92
+ placeholder="字段路径"
93
+ size="small"
94
+ style="flex: 1"
95
+ />
96
+ <a-select
97
+ v-model:value="f.operator"
98
+ :options="workflow_utils.conditionOperators"
99
+ size="small"
100
+ style="width: 96px"
101
+ />
102
+ <a-input
103
+ v-model:value="f.value"
104
+ placeholder="比较值"
105
+ size="small"
106
+ style="flex: 1"
107
+ />
108
+ <a-button
109
+ :icon="h(DeleteOutlined)"
110
+ size="small"
111
+ type="text"
112
+ danger
113
+ @click="removeFilter(i)"
114
+ />
115
+ </div>
116
+ </div>
117
+ </WfField>
118
+ </div>
119
+
120
+ <div v-if="formState.operation === 'map'" class="wf-config-section">
121
+ <WfField title="映射表达式">
122
+ <template #tooltip>
123
+ 以 <code>item</code> 引用当前项。示例:<code>item.name</code>、<code>item.price * 1.1</code>
124
+ </template>
125
+ <a-input
126
+ v-model:value="formState.mapExpression"
127
+ placeholder="item.name"
128
+ />
129
+ </WfField>
130
+ </div>
131
+
132
+ <div v-if="formState.operation === 'slice'" class="wf-config-section">
133
+ <WfField title="偏移" is-subtitle>
134
+ <a-input-number
135
+ v-model:value="formState.offset"
136
+ :min="0"
137
+ style="width: 100%"
138
+ />
139
+ </WfField>
140
+ <WfField title="数量" is-subtitle>
141
+ <a-input-number
142
+ v-model:value="formState.limit"
143
+ :min="0"
144
+ style="width: 100%"
145
+ />
146
+ </WfField>
147
+ </div>
148
+
149
+ <div v-if="formState.operation === 'sort'" class="wf-config-section">
150
+ <WfField title="排序字段" is-subtitle>
151
+ <a-input
152
+ v-model:value="formState.sortField"
153
+ placeholder="留空按 item 本身"
154
+ />
155
+ </WfField>
156
+ <WfField title="顺序" is-subtitle>
157
+ <a-select
158
+ v-model:value="formState.sortOrder"
159
+ :options="SORT_ORDERS"
160
+ style="width: 100%"
161
+ />
162
+ </WfField>
163
+ </div>
164
+ </template>
165
+
166
+ <style scoped>
167
+ .list-op-empty {
168
+ padding: 12px;
169
+ text-align: center;
170
+ font-size: 12px;
171
+ color: #9ca3af;
172
+ background: #f9fafb;
173
+ border: 1px dashed #e5e7eb;
174
+ border-radius: 6px;
175
+ }
176
+
177
+ .list-op-filter-list {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 6px;
181
+ }
182
+
183
+ .list-op-filter-row {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 6px;
187
+ }
188
+ </style>