Showing
48 changed files
with
2495 additions
and
91 deletions
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | "public/resource/tinymce/langs" |
6 | 6 | ], |
7 | 7 | "cSpell.words": [ |
8 | + "ACKS", | |
8 | 9 | "clazz", |
9 | 10 | "Cmds", |
10 | 11 | "COAP", |
... | ... | @@ -19,9 +20,12 @@ |
19 | 20 | "noconflict", |
20 | 21 | "notif", |
21 | 22 | "PROTOBUF", |
23 | + "Rabbitmq", | |
22 | 24 | "rtsp", |
23 | 25 | "SCADA", |
26 | + "SMTPS", | |
24 | 27 | "SNMP", |
28 | + "TSLV", | |
25 | 29 | "UNACK", |
26 | 30 | "unref", |
27 | 31 | "vben", | ... | ... |
... | ... | @@ -5,6 +5,7 @@ import { defHttp } from '/@/utils/http/axios'; |
5 | 5 | enum Api { |
6 | 6 | GET_DEVICE_INFOS = '/tenant/deviceInfos', |
7 | 7 | GET_DEVICE_TYPE = '/device/types', |
8 | + TENANT_QUEUE = '/tenant/queues', | |
8 | 9 | } |
9 | 10 | |
10 | 11 | export const getDeviceInfos = () => { |
... | ... | @@ -24,3 +25,13 @@ export const getDeviceTypes = () => { |
24 | 25 | { joinPrefix: false } |
25 | 26 | ); |
26 | 27 | }; |
28 | + | |
29 | +export const getTenantQueue = (params: Recordable) => { | |
30 | + return defHttp.get<string[]>( | |
31 | + { | |
32 | + url: Api.TENANT_QUEUE, | |
33 | + params, | |
34 | + }, | |
35 | + { joinPrefix: false } | |
36 | + ); | |
37 | +}; | ... | ... |
... | ... | @@ -3,6 +3,7 @@ import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; |
3 | 3 | |
4 | 4 | enum Api { |
5 | 5 | SAVE = '/ruleChain/metadata', |
6 | + GET_RULE_CHAINES = '/ruleChains', | |
6 | 7 | } |
7 | 8 | |
8 | 9 | export const getRuleChainData = (id: string) => { |
... | ... | @@ -23,3 +24,15 @@ export const saveRuleChainData = (data: RuleChainType) => { |
23 | 24 | { joinPrefix: false } |
24 | 25 | ); |
25 | 26 | }; |
27 | + | |
28 | +export const getRuleChains = (params: Recordable) => { | |
29 | + return defHttp.get( | |
30 | + { | |
31 | + url: Api.GET_RULE_CHAINES, | |
32 | + params, | |
33 | + }, | |
34 | + { | |
35 | + joinPrefix: false, | |
36 | + } | |
37 | + ); | |
38 | +}; | ... | ... |
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | import { get, omit } from 'lodash-es'; |
15 | 15 | import { LoadingOutlined } from '@ant-design/icons-vue'; |
16 | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
17 | + import { useDebounceFn } from '@vueuse/shared'; | |
17 | 18 | |
18 | 19 | const emit = defineEmits(['options-change', 'change']); |
19 | 20 | const props = withDefaults( |
... | ... | @@ -53,7 +54,7 @@ |
53 | 54 | const { labelField, valueField = 'value', numberToString } = props; |
54 | 55 | return unref(options).reduce((prev, next: Recordable) => { |
55 | 56 | if (next) { |
56 | - const value = next[valueField]; | |
57 | + const value = get(next, valueField); | |
57 | 58 | prev.push({ |
58 | 59 | label: next[labelField], |
59 | 60 | value: numberToString ? `${value}` : value, |
... | ... | @@ -122,6 +123,7 @@ |
122 | 123 | onChangeHook({ options }); |
123 | 124 | } |
124 | 125 | |
126 | + const debounceSearchFunction = useDebounceFn(handleSearch, 300); | |
125 | 127 | async function handleSearch(params?: string) { |
126 | 128 | let { searchApi, api } = props; |
127 | 129 | if (!searchApi || !isFunction(searchApi)) { |
... | ... | @@ -156,7 +158,7 @@ |
156 | 158 | show-search |
157 | 159 | @change="handleChange" |
158 | 160 | :options="getOptions" |
159 | - @search="handleSearch" | |
161 | + @search="debounceSearchFunction" | |
160 | 162 | v-model:value="state" |
161 | 163 | > |
162 | 164 | <template #[item]="data" v-for="item in Object.keys($slots)"> | ... | ... |
... | ... | @@ -40,16 +40,19 @@ |
40 | 40 | accept?: string; |
41 | 41 | maxSize?: number; |
42 | 42 | disabled?: boolean; |
43 | - listType?: string; | |
43 | + listType?: 'text' | 'picture-card' | 'picture'; | |
44 | 44 | multiple?: boolean; |
45 | 45 | maxFileLimit?: number; |
46 | - showUploadList?: boolean | { showPreviewIcon?: boolean; showRemoveIcon?: boolean }; | |
46 | + showUploadList?: InstanceType<typeof Upload>['$props']['showUploadList']; | |
47 | 47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; |
48 | 48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; |
49 | + overFileLimitHiddenUploadEntry?: boolean; | |
49 | 50 | }>(), |
50 | 51 | { |
51 | 52 | fileList: () => [], |
52 | 53 | maxSize: 5 * 1024 * 1024, |
54 | + overFileLimitHiddenUploadEntry: true, | |
55 | + listType: 'text', | |
53 | 56 | showUploadList: () => ({ showPreviewIcon: true, showRemoveIcon: true }), |
54 | 57 | } |
55 | 58 | ); |
... | ... | @@ -75,7 +78,7 @@ |
75 | 78 | |
76 | 79 | const getMaxFileLimit = computed(() => { |
77 | 80 | const { maxFileLimit } = props; |
78 | - return isPictureCard.value ? 1 : maxFileLimit; | |
81 | + return isPictureCard.value ? 1 : maxFileLimit || 1; | |
79 | 82 | }); |
80 | 83 | |
81 | 84 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { |
... | ... | @@ -131,11 +134,15 @@ |
131 | 134 | :list-type="props.listType" |
132 | 135 | :disabled="getDisabled" |
133 | 136 | :before-upload="handleBeforeUpload" |
137 | + :show-upload-list="showUploadList" | |
134 | 138 | @preview="handlePreview" |
135 | 139 | @download="handleDownload" |
136 | 140 | :remove="handleRemove" |
137 | 141 | > |
138 | - <Spin v-if="!fileList.length" :spinning="loading"> | |
142 | + <Spin | |
143 | + v-if="!(fileList.length >= getMaxFileLimit) || overFileLimitHiddenUploadEntry" | |
144 | + :spinning="loading" | |
145 | + > | |
139 | 146 | <div class="w-full h-full flex flex-col justify-center content-center"> |
140 | 147 | <Tooltip title="点击上传或拖拽上传"> |
141 | 148 | <InboxOutlined class="text-[3rem] !text-blue-500" /> | ... | ... |
... | ... | @@ -241,3 +241,95 @@ export enum ScopeNameEnum { |
241 | 241 | CLIENT_SCOPE = '客户端属性', |
242 | 242 | SHARED_SCOPE = '共享属性', |
243 | 243 | } |
244 | + | |
245 | +// External Queue type | |
246 | +export enum QueueTypeEnum { | |
247 | + STANDARD = 'STANDARD', | |
248 | + FIFO = 'FIFO', | |
249 | +} | |
250 | + | |
251 | +export enum QueueTypeNameEnum { | |
252 | + STANDARD = 'Standard', | |
253 | + FIFO = 'FIFO', | |
254 | +} | |
255 | + | |
256 | +// Charset encoding | |
257 | +export enum CharsetEncodingEnum { | |
258 | + US_ASCII = 'US_ASCII', | |
259 | + ISO_8859_1 = 'ISO_8859_1', | |
260 | + UTF_8 = 'UTF_8', | |
261 | + UTF_16BE = 'UTF_16BE', | |
262 | + UTF_16LE = 'UTF_16LE', | |
263 | + UTF_16 = 'UTF_16', | |
264 | +} | |
265 | + | |
266 | +export enum CharsetEncodingNameEnum { | |
267 | + US_ASCII = 'US-ASCII', | |
268 | + ISO_8859_1 = 'ISO-8859-1', | |
269 | + UTF_8 = 'UTF-8', | |
270 | + UTF_16BE = 'UTF-16BE', | |
271 | + UTF_16LE = 'UTF-16LE', | |
272 | + UTF_16 = 'UTF-16', | |
273 | +} | |
274 | + | |
275 | +// Rabbitmq Message properties | |
276 | +export enum MessagePropertiesEnum { | |
277 | + BASIC = 'BASIC', | |
278 | + TEXT_PLAIN = 'TEXT_PLAIN', | |
279 | + MINIMAL_BASIC = 'MINIMAL_BASIC', | |
280 | + MINIMAL_PERSISTENT_BASIC = 'MINIMAL_PERSISTENT_BASIC', | |
281 | + PERSISTENT_BASIC = 'PERSISTENT_BASIC', | |
282 | + PERSISTENT_TEXT_PLAIN = 'PERSISTENT_TEXT_PLAIN', | |
283 | +} | |
284 | + | |
285 | +// rest api call Request method | |
286 | +export enum RequestMethodEnum { | |
287 | + GET = 'GET', | |
288 | + POST = 'POST', | |
289 | + PUT = 'PUT', | |
290 | + DELETE = 'DELETE', | |
291 | +} | |
292 | + | |
293 | +export enum ProtocolEnum { | |
294 | + HTTP = 'HTTP', | |
295 | + HTTPS = 'HTTPS', | |
296 | +} | |
297 | + | |
298 | +export enum ProtocolNameEnum { | |
299 | + HTTP = 'http', | |
300 | + HTTPS = 'https', | |
301 | +} | |
302 | + | |
303 | +export enum EmailProtocolEnum { | |
304 | + SMTP = 'SMTP', | |
305 | + SMTPS = 'SMTPS', | |
306 | +} | |
307 | + | |
308 | +export enum EmailProtocolNameEnum { | |
309 | + SMTP = 'smtp', | |
310 | + SMTPS = 'smtps', | |
311 | +} | |
312 | + | |
313 | +export enum TSLVersionEnum { | |
314 | + TSLV1 = 'TSLV1', | |
315 | + TSLV1_1 = 'TSLV1_1', | |
316 | + TSLV1_2 = 'TSLV1_2', | |
317 | + TSLV1_3 = 'TSLV1_3', | |
318 | +} | |
319 | + | |
320 | +export enum TSLVersionNameEnum { | |
321 | + TSLV1 = 'TSLV1', | |
322 | + TSLV1_1 = 'TSLV1.1', | |
323 | + TSLV1_2 = 'TSLV1.2', | |
324 | + TSLV1_3 = 'TSLV1.3', | |
325 | +} | |
326 | + | |
327 | +export enum SMSServiceProviderEnum { | |
328 | + AWS_SNS = 'AWS_SNS', | |
329 | + TWILIO = 'TWILIO', | |
330 | +} | |
331 | + | |
332 | +export enum SMSServiceProviderNameEnum { | |
333 | + AWS_SNS = '亚马逊社交网站', | |
334 | + TWILIO = 'Twilio', | |
335 | +} | ... | ... |
1 | +// Alarm notice | |
2 | +export enum AlarmNoticeFieldsEnum { | |
3 | + CONFIGURATION = 'CONFIGURATION', | |
4 | +} | |
5 | + | |
6 | +export enum AlarmNoticeFieldsNameEnum { | |
7 | + CONFIGURATION = '配置', | |
8 | +} | |
9 | + | |
10 | +// aws sns | |
11 | +export enum AwsSnsFieldsEnum { | |
12 | + TOPIC_ARN_PATTERN = 'topicArnPattern', | |
13 | + ACCESS_KEY_ID = 'accessKeyId', | |
14 | + SECRET_ACCESS_KEY = 'secretAccessKey', | |
15 | + REGION = 'region', | |
16 | +} | |
17 | + | |
18 | +export enum AwsSnsFieldsNameEnum { | |
19 | + TOPIC_ARN_PATTERN = 'Topic ARN pattern', | |
20 | + ACCESS_KEY_ID = 'AWS Access Key ID', | |
21 | + SECRET_ACCESS_KEY = 'AWS Secret Access Key', | |
22 | + REGION = 'AWS Region', | |
23 | +} | |
24 | + | |
25 | +// Aws sqs | |
26 | +export enum AwsSqsFieldsEnum { | |
27 | + QUEUE_TYPE = 'queueType', | |
28 | + QUEUE_URL_PATTERN = 'queueUrlPattern', | |
29 | + DELAY_SECONDS = 'delaySeconds', | |
30 | + MESSAGE_ATTRIBUTES = 'messageAttributes', | |
31 | + ACCESS_KEY_ID = 'accessKeyId', | |
32 | + SECRET_ACCESS_KEY = 'secretAccessKey', | |
33 | + REGION = 'region', | |
34 | +} | |
35 | + | |
36 | +export enum AwsSqsFieldsNameEnum { | |
37 | + QUEUE_TYPE = 'Queue type', | |
38 | + QUEUE_URL_PATTERN = 'Queue URL pattern', | |
39 | + DELAY_SECONDS = 'Delay(seconds)', | |
40 | + MESSAGE_ATTRIBUTES = 'Message attributes', | |
41 | + ACCESS_KEY_ID = 'AWS Access Key ID', | |
42 | + SECRET_ACCESS_KEY = 'AWS Secret Access Key', | |
43 | + REGION = 'AWS Region', | |
44 | +} | |
45 | + | |
46 | +// Azure iot hub | |
47 | +export enum AzureIotHubFieldsEnum { | |
48 | + TOPIC_PATTERN = 'topicPattern', | |
49 | + HOST = 'host', | |
50 | + PORT = 'port', | |
51 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | |
52 | + CLIENT_ID = 'clientId', | |
53 | + CLEAN_SESSION = 'cleanSession', | |
54 | + SSL = 'ssl', | |
55 | + CREDENTIALS = 'credentials', | |
56 | + | |
57 | + TYPE = 'type', | |
58 | + SAS_KEY = 'sasKey', | |
59 | + CA_CERT = 'caCert', | |
60 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
61 | + PRIVATE_KEY = 'privateKey', | |
62 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
63 | + CERT = 'cert', | |
64 | + CERT_FILE_NAME = 'certFileName', | |
65 | + PASSWORD = 'password', | |
66 | +} | |
67 | + | |
68 | +export enum AzureIotHubFieldsNameEnum { | |
69 | + TOPIC_PATTERN = 'Topic', | |
70 | + HOST = 'Hostname', | |
71 | + PORT = 'port', | |
72 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | |
73 | + CLIENT_ID = 'Device ID', | |
74 | + CLEAN_SESSION = 'cleanSession', | |
75 | + SSL = 'ssl', | |
76 | + CREDENTIALS = 'credentials', | |
77 | + | |
78 | + TYPE = 'Credentials type', | |
79 | + SAS_KEY = 'sasKey', | |
80 | + CA_CERT = 'CA certificate file', | |
81 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
82 | + PRIVATE_KEY = 'Client private key file', | |
83 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
84 | + CERT = 'Client certificate file', | |
85 | + CERT_FILE_NAME = 'certFileName', | |
86 | + PASSWORD = 'Private key password', | |
87 | +} | |
88 | + | |
89 | +// GCP pubsub | |
90 | +export enum GcpPubsubFieldsEnum { | |
91 | + PROJECT_ID = 'projectId', | |
92 | + TOPIC_NAME = 'topicName', | |
93 | + SERVICE_ACCOUNT_KEY = 'serviceAccountKey', | |
94 | + SERVICE_ACCOUNT_KEY_FILE_NAME = 'serviceAccountKeyFileName', | |
95 | + MESSAGE_ATTRIBUTES = 'messageAttributes', | |
96 | +} | |
97 | + | |
98 | +export enum GcpPubsubFieldsNameEnum { | |
99 | + PROJECT_ID = 'GCP project ID', | |
100 | + TOPIC_NAME = 'Topic name', | |
101 | + SERVICE_ACCOUNT_KEY = 'GCP service account key file', | |
102 | + SERVICE_ACCOUNT_KEY_FILE_NAME = 'serviceAccountKeyFileName', | |
103 | + MESSAGE_ATTRIBUTES = 'Message attributes', | |
104 | +} | |
105 | + | |
106 | +// Kafka | |
107 | +export enum KafkaFieldsEnum { | |
108 | + TOPIC_PATTERN = 'topicPattern', | |
109 | + BOOTSTRAP_SERVERS = 'bootstrapServers', | |
110 | + RETRIES = 'retries', | |
111 | + BATCH_SIZE = 'batchSize', | |
112 | + LINGER = 'linger', | |
113 | + BUFFER_MEMORY = 'bufferMemory', | |
114 | + ACKS = 'acks', | |
115 | + KEY_SERIALIZER = 'keySerializer', | |
116 | + VALUE_SERIALIZER = 'valueSerializer', | |
117 | + OTHER_PROPERTIES = 'otherProperties', | |
118 | + ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS = 'addMetadataKeyValuesAsKafkaHeaders', | |
119 | + KAFKA_HEADERS_CHARSET = 'kafkaHeadersCharset', | |
120 | +} | |
121 | + | |
122 | +export enum KafkaFieldsNameEnum { | |
123 | + TOPIC_PATTERN = 'Topic pattern', | |
124 | + BOOTSTRAP_SERVERS = 'Bootstrap servers', | |
125 | + RETRIES = 'Automatically retry times if fails', | |
126 | + BATCH_SIZE = 'Produces batch size in bytes', | |
127 | + LINGER = 'Time to buffer locally(ms)', | |
128 | + BUFFER_MEMORY = 'Client buffer max size in bytes', | |
129 | + ACKS = 'Number of acknowledgments', | |
130 | + KEY_SERIALIZER = 'Key serializer', | |
131 | + VALUE_SERIALIZER = 'Value serializer', | |
132 | + OTHER_PROPERTIES = 'Other properties', | |
133 | + ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS = 'Add Message metadata key-value pairs to Kafka record headers', | |
134 | + KAFKA_HEADERS_CHARSET = 'Charset encoding', | |
135 | +} | |
136 | + | |
137 | +// Mqtt | |
138 | +export enum MqttFieldsEnum { | |
139 | + TOPIC_PATTERN = 'topicPattern', | |
140 | + HOST = 'host', | |
141 | + PORT = 'port', | |
142 | + CONNECT_TIMEOUT_SEC = 'connectTimeoutSec', | |
143 | + CLIENT_ID = 'clientId', | |
144 | + APPEND_CLIENT_ID_SUFFIX = 'appendClientIdSuffix', | |
145 | + CLEAN_SESSION = 'cleanSession', | |
146 | + SSL = 'ssl', | |
147 | + CREDENTIALS = 'credentials', | |
148 | + | |
149 | + TYPE = 'type', | |
150 | + PASSWORD = 'password', | |
151 | + CA_CERT = 'caCert', | |
152 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
153 | + PRIVATE_KEY = 'privateKey', | |
154 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
155 | + CERT = 'cert', | |
156 | + CERT_FILE_NAME = 'certFileName', | |
157 | + USERNAME = 'username', | |
158 | +} | |
159 | + | |
160 | +export enum MqttFieldsNameEnum { | |
161 | + TOPIC_PATTERN = 'Topic pattern', | |
162 | + HOST = 'Hose', | |
163 | + PORT = 'Port', | |
164 | + CONNECT_TIMEOUT_SEC = 'Connection timeout(sec)', | |
165 | + CLIENT_ID = 'Client ID', | |
166 | + APPEND_CLIENT_ID_SUFFIX = 'Add Service ID as suffix to Client ID', | |
167 | + CLEAN_SESSION = 'Clean session', | |
168 | + SSL = 'Enable SSL', | |
169 | + CREDENTIALS = 'credentials', | |
170 | + | |
171 | + TYPE = 'Credentials type', | |
172 | + PASSWORD = 'Password', | |
173 | + CA_CERT = 'Server CA certificate file', | |
174 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
175 | + PRIVATE_KEY = 'Client private key file', | |
176 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
177 | + CERT = 'Client certificate file', | |
178 | + CERT_FILE_NAME = 'certFileName', | |
179 | + USERNAME = 'Username', | |
180 | +} | |
181 | + | |
182 | +// Rabbitmq | |
183 | +export enum RabbitmqFieldsEnum { | |
184 | + EXCHANGE_NAME_PATTERN = 'exchangeNamePattern', | |
185 | + ROUTING_KEY_PATTERN = 'routingKeyPattern', | |
186 | + MESSAGE_PROPERTIES = 'messageProperties', | |
187 | + HOST = 'host', | |
188 | + PORT = 'port', | |
189 | + VIRTUAL_HOST = 'virtualHost', | |
190 | + USERNAME = 'username', | |
191 | + PASSWORD = 'password', | |
192 | + AUTOMATIC_RECOVERY_ENABLED = 'automaticRecoveryEnabled', | |
193 | + CONNECTION_TIMEOUT = 'connectionTimeout', | |
194 | + HANDSHAKE_TIMEOUT = 'handshakeTimeout', | |
195 | + CLIENT_PROPERTIES = 'clientProperties', | |
196 | +} | |
197 | + | |
198 | +export enum RabbitmqFieldsNameEnum { | |
199 | + EXCHANGE_NAME_PATTERN = 'Exchange name pattern', | |
200 | + ROUTING_KEY_PATTERN = 'Routing key pattern', | |
201 | + MESSAGE_PROPERTIES = 'Message properties', | |
202 | + HOST = 'Host', | |
203 | + PORT = 'Port', | |
204 | + VIRTUAL_HOST = 'Virtual host', | |
205 | + USERNAME = 'Username', | |
206 | + PASSWORD = 'Password', | |
207 | + AUTOMATIC_RECOVERY_ENABLED = 'Automatic recovery', | |
208 | + CONNECTION_TIMEOUT = 'Connection timeout(ms)', | |
209 | + HANDSHAKE_TIMEOUT = 'Handshake timeout(ms)', | |
210 | + CLIENT_PROPERTIES = 'Client properties', | |
211 | +} | |
212 | + | |
213 | +// Rest api call | |
214 | +export enum RestApiCallFieldsEnum { | |
215 | + REST_ENDPOINT_URL_PATTERN = 'restEndpointUrlPattern', | |
216 | + REQUEST_METHOD = 'requestMethod', | |
217 | + USE_SIMPLE_CLIENT_HTTP_FACTORY = 'useSimpleClientHttpFactory', | |
218 | + IGNORE_REQUEST_BODY = 'ignoreRequestBody', | |
219 | + ENABLE_PROXY = 'enableProxy', | |
220 | + USE_SYSTEM_PROXY_PROPERTIES = 'useSystemProxyProperties', | |
221 | + PROXY_SCHEME = 'proxyScheme', | |
222 | + PROXY_HOST = 'proxyHost', | |
223 | + PROXY_PORT = 'proxyPort', | |
224 | + PROXY_USER = 'proxyUser', | |
225 | + PROXY_PASSWORD = 'proxyPassword', | |
226 | + READ_TIMEOUT_MS = 'readTimeoutMs', | |
227 | + MAX_PARALLEL_REQUESTS_COUNT = 'maxParallelRequestsCount', | |
228 | + HEADERS = 'headers', | |
229 | + USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE = 'useRedisQueueForMsgPersistence', | |
230 | + TRIM_QUEUE = 'trimQueue', | |
231 | + MAX_QUEUE_SIZE = 'maxQueueSize', | |
232 | + CREDENTIALS = 'credentials', | |
233 | + | |
234 | + TYPE = 'type', | |
235 | + PASSWORD = 'password', | |
236 | + CA_CERT = 'caCert', | |
237 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
238 | + PRIVATE_KEY = 'privateKey', | |
239 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
240 | + CERT = 'cert', | |
241 | + CERT_FILE_NAME = 'certFileName', | |
242 | + USERNAME = 'username', | |
243 | +} | |
244 | + | |
245 | +export enum RestApiCallFieldsNameEnum { | |
246 | + REST_ENDPOINT_URL_PATTERN = 'Endpoint URL pattern', | |
247 | + REQUEST_METHOD = 'requestMethod', | |
248 | + USE_SIMPLE_CLIENT_HTTP_FACTORY = 'useSimpleClientHttpFactory', | |
249 | + IGNORE_REQUEST_BODY = 'ignoreRequestBody', | |
250 | + ENABLE_PROXY = 'enableProxy', | |
251 | + USE_SYSTEM_PROXY_PROPERTIES = 'useSystemProxyProperties', | |
252 | + PROXY_SCHEME = 'proxyScheme', | |
253 | + PROXY_HOST = 'proxyHost', | |
254 | + PROXY_PORT = 'proxyPort', | |
255 | + PROXY_USER = 'proxyUser', | |
256 | + PROXY_PASSWORD = 'proxyPassword', | |
257 | + READ_TIMEOUT_MS = 'readTimeoutMs', | |
258 | + MAX_PARALLEL_REQUESTS_COUNT = 'maxParallelRequestsCount', | |
259 | + HEADERS = 'headers', | |
260 | + USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE = 'useRedisQueueForMsgPersistence', | |
261 | + TRIM_QUEUE = 'trimQueue', | |
262 | + MAX_QUEUE_SIZE = 'maxQueueSize', | |
263 | + CREDENTIALS = 'credentials', | |
264 | + | |
265 | + TYPE = 'Credentials type', | |
266 | + PASSWORD = 'Password', | |
267 | + CA_CERT = 'Server CA certificate file', | |
268 | + CA_CERT_FILE_NAME = 'caCertFileName', | |
269 | + PRIVATE_KEY = 'Client private key file', | |
270 | + PRIVATE_KEY_FILE_NAME = 'privateKeyFileName', | |
271 | + CERT = 'Client certificate file', | |
272 | + CERT_FILE_NAME = 'certFileName', | |
273 | + USERNAME = 'Username', | |
274 | +} | |
275 | + | |
276 | +// send email | |
277 | +export enum SendEmailFieldsEnum { | |
278 | + USE_SYSTEM_SMTP_SETTINGS = 'useSystemSmtpSettings', | |
279 | + SMTP_PROTOCOL = 'smtpProtocol', | |
280 | + SMTP_HOST = 'smtpHost', | |
281 | + SMTP_PORT = 'smtpPort', | |
282 | + TIMEOUT = 'timeout', | |
283 | + ENABLE_TLS = 'enableTls', | |
284 | + TLS_VERSION = 'tlsVersion', | |
285 | + ENABLE_PROXY = 'enableProxy', | |
286 | + PROXY_HOST = 'proxyHost', | |
287 | + PROXY_PORT = 'proxyPort', | |
288 | + PROXY_USER = 'proxyUser', | |
289 | + PROXY_PASSWORD = 'proxyPassword', | |
290 | + USERNAME = 'username', | |
291 | + PASSWORD = 'password', | |
292 | +} | |
293 | + | |
294 | +export enum SendEmailFieldsNameEnum { | |
295 | + USE_SYSTEM_SMTP_SETTINGS = 'Use system SMTP settings', | |
296 | + SMTP_PROTOCOL = 'Protocol', | |
297 | + SMTP_HOST = 'SMTP host', | |
298 | + SMTP_PORT = 'SMTP port', | |
299 | + TIMEOUT = 'Timeout ms', | |
300 | + ENABLE_TLS = 'Enable TLS', | |
301 | + TLS_VERSION = 'TLS version', | |
302 | + ENABLE_PROXY = 'Enable proxy', | |
303 | + PROXY_HOST = 'Proxy host', | |
304 | + PROXY_PORT = 'Proxy port', | |
305 | + PROXY_USER = 'Proxy user', | |
306 | + PROXY_PASSWORD = 'Proxy password', | |
307 | + USERNAME = 'Username', | |
308 | + PASSWORD = 'Password', | |
309 | +} | |
310 | + | |
311 | +export enum SendSMSFieldsEnum { | |
312 | + NUMBERS_TO_TEMPLATE = 'numbersToTemplate', | |
313 | + SMS_MESSAGE_TEMPLATE = 'smsMessageTemplate', | |
314 | + USE_SYSTEM_SMS_SETTINGS = 'useSystemSmsSettings', | |
315 | + SMS_PROVIDER_CONFIGURATION = 'smsProviderConfiguration', | |
316 | + | |
317 | + ACCESS_KEY_ID = 'accessKeyId', | |
318 | + SECRET_ACCESS_KEY = 'secretAccessKey', | |
319 | + REGION = 'region', | |
320 | + TYPE = 'type', | |
321 | + NUMBER_FROM = 'numberFrom', | |
322 | + ACCOUNT_SID = 'accountSid', | |
323 | + ACCOUNT_TOKEN = 'accountToken', | |
324 | +} | |
325 | + | |
326 | +export enum SendSMSFieldsNameEnum { | |
327 | + NUMBERS_TO_TEMPLATE = 'Phone Numbers To Template', | |
328 | + SMS_MESSAGE_TEMPLATE = 'SMS message Template', | |
329 | + USE_SYSTEM_SMS_SETTINGS = 'User system SMS provider settings', | |
330 | + SMS_PROVIDER_CONFIGURATION = 'smsProviderConfiguration', | |
331 | + | |
332 | + ACCESS_KEY_ID = 'AWS访问密钥ID', | |
333 | + SECRET_ACCESS_KEY = 'AWS访问密钥', | |
334 | + REGION = 'AWS地区', | |
335 | + TYPE = 'SMS服务商类型', | |
336 | + NUMBER_FROM = '发送方电话号码', | |
337 | + ACCOUNT_SID = 'Twilio账户SID', | |
338 | + ACCOUNT_TOKEN = 'Twilio账户令牌', | |
339 | +} | ... | ... |
1 | +export enum CheckPointFieldsEnum { | |
2 | + QUEUE_NAME = 'queueName', | |
3 | +} | |
4 | + | |
5 | +export enum CheckPointFieldsNameEnum { | |
6 | + QUEUE_NAME = '队列名称', | |
7 | +} | |
8 | + | |
9 | +export enum RuleChainFieldsEnum { | |
10 | + RULE_CHAIN_ID = 'ruleChainId', | |
11 | +} | |
12 | + | |
13 | +export enum RuleChainFieldsNameEnum { | |
14 | + RULE_CHAIN_ID = '规则链', | |
15 | +} | ... | ... |
... | ... | @@ -9,6 +9,7 @@ export const InputConfig: NodeItemConfigType = { |
9 | 9 | ...keys, |
10 | 10 | categoryType: RuleNodeTypeEnum.ENTRY, |
11 | 11 | clazz: EntryCategoryComponentEnum.INPUT, |
12 | + disableAction: true, | |
12 | 13 | maxConnectionPoint: 1, |
13 | 14 | backgroundColor: '#95E898', |
14 | 15 | configurationDescriptor: { | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { AlarmNoticeFieldsEnum, AlarmNoticeFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | |
4 | 4 | export const formSchemas: FormSchema[] = [ |
5 | 5 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | - component: 'Input', | |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
6 | + field: AlarmNoticeFieldsEnum.CONFIGURATION, | |
7 | + component: 'JSONEditor', | |
8 | + label: AlarmNoticeFieldsNameEnum.CONFIGURATION, | |
9 | + valueField: 'value', | |
10 | + changeEvent: 'update:value', | |
9 | 11 | }, |
10 | 12 | ]; | ... | ... |
... | ... | @@ -3,6 +3,8 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { useJsonParse } from '/@/hooks/business/useJsonParse'; | |
7 | + import { AlarmNoticeFieldsEnum } from '../../../enum/formField/external'; | |
6 | 8 | |
7 | 9 | defineProps<{ |
8 | 10 | config: NodeData; |
... | ... | @@ -16,12 +18,12 @@ |
16 | 18 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 19 | await validate(); |
18 | 20 | const value = getFieldsValue() || {}; |
19 | - return value; | |
21 | + return useJsonParse(value?.[AlarmNoticeFieldsEnum.CONFIGURATION]).value || {}; | |
20 | 22 | }; |
21 | 23 | |
22 | 24 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 25 | resetFields(); |
24 | - setFieldsValue(value); | |
26 | + setFieldsValue({ [AlarmNoticeFieldsEnum.CONFIGURATION]: JSON.stringify(value, null, 2) }); | |
25 | 27 | }; |
26 | 28 | |
27 | 29 | defineExpose({ | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { AwsSnsFieldsEnum, AwsSnsFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | |
4 | 4 | export const formSchemas: FormSchema[] = [ |
5 | 5 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
6 | + field: AwsSnsFieldsEnum.TOPIC_ARN_PATTERN, | |
7 | + label: AwsSnsFieldsNameEnum.TOPIC_ARN_PATTERN, | |
7 | 8 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
9 | + required: true, | |
10 | + componentProps: { | |
11 | + placeholder: `请输入${AwsSnsFieldsNameEnum.TOPIC_ARN_PATTERN}`, | |
12 | + }, | |
13 | + }, | |
14 | + { | |
15 | + field: AwsSnsFieldsEnum.ACCESS_KEY_ID, | |
16 | + label: AwsSnsFieldsNameEnum.ACCESS_KEY_ID, | |
17 | + component: 'Input', | |
18 | + required: true, | |
19 | + componentProps: { | |
20 | + placeholder: `请输入${AwsSnsFieldsNameEnum.ACCESS_KEY_ID}`, | |
21 | + }, | |
22 | + }, | |
23 | + { | |
24 | + field: AwsSnsFieldsEnum.SECRET_ACCESS_KEY, | |
25 | + label: AwsSnsFieldsNameEnum.SECRET_ACCESS_KEY, | |
26 | + component: 'Input', | |
27 | + required: true, | |
28 | + componentProps: { | |
29 | + placeholder: `请输入${AwsSnsFieldsNameEnum.SECRET_ACCESS_KEY}`, | |
30 | + }, | |
31 | + }, | |
32 | + { | |
33 | + field: AwsSnsFieldsEnum.REGION, | |
34 | + label: AwsSnsFieldsNameEnum.REGION, | |
35 | + component: 'Input', | |
36 | + required: true, | |
37 | + componentProps: { | |
38 | + placeholder: `请输入${AwsSnsFieldsNameEnum.REGION}`, | |
39 | + }, | |
9 | 40 | }, |
10 | 41 | ]; | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { QueueTypeEnum, QueueTypeNameEnum } from '../../../enum/form'; | |
2 | +import { AwsSqsFieldsEnum, AwsSqsFieldsNameEnum } from '../../../enum/formField/external'; | |
3 | +import { AttributeConfiguration } from '../../../src/components/AttributeConfiguration'; | |
4 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
5 | + | |
6 | +useComponentRegister('AttributeConfiguration', AttributeConfiguration); | |
3 | 7 | |
4 | 8 | export const formSchemas: FormSchema[] = [ |
5 | 9 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
10 | + field: AwsSqsFieldsEnum.QUEUE_TYPE, | |
11 | + label: AwsSqsFieldsNameEnum.QUEUE_TYPE, | |
12 | + component: 'Select', | |
13 | + required: true, | |
14 | + componentProps: { | |
15 | + options: Object.keys(QueueTypeEnum).map((value) => ({ | |
16 | + label: QueueTypeNameEnum[value], | |
17 | + value, | |
18 | + })), | |
19 | + getPopupContainer: () => document.body, | |
20 | + placeholder: `请选择${AwsSqsFieldsNameEnum.QUEUE_TYPE}`, | |
21 | + }, | |
22 | + }, | |
23 | + { | |
24 | + field: AwsSqsFieldsEnum.QUEUE_URL_PATTERN, | |
25 | + label: AwsSqsFieldsNameEnum.QUEUE_URL_PATTERN, | |
26 | + component: 'Input', | |
27 | + required: true, | |
28 | + componentProps: { | |
29 | + placeholder: `请输入${AwsSqsFieldsNameEnum.QUEUE_URL_PATTERN}`, | |
30 | + }, | |
31 | + }, | |
32 | + { | |
33 | + field: AwsSqsFieldsEnum.DELAY_SECONDS, | |
34 | + label: AwsSqsFieldsNameEnum.DELAY_SECONDS, | |
35 | + component: 'Input', | |
36 | + required: true, | |
37 | + helpMessage: [ | |
38 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
39 | + ], | |
40 | + show: ({ model }) => model[AwsSqsFieldsEnum.QUEUE_TYPE] === QueueTypeEnum.STANDARD, | |
41 | + componentProps: { | |
42 | + placeholder: `请输入${AwsSqsFieldsNameEnum.DELAY_SECONDS}`, | |
43 | + }, | |
44 | + }, | |
45 | + { | |
46 | + field: AwsSqsFieldsEnum.MESSAGE_ATTRIBUTES, | |
47 | + label: AwsSqsFieldsNameEnum.MESSAGE_ATTRIBUTES, | |
48 | + component: 'AttributeConfiguration', | |
49 | + helpMessage: | |
50 | + 'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields', | |
51 | + slot: AwsSqsFieldsEnum.MESSAGE_ATTRIBUTES, | |
52 | + }, | |
53 | + { | |
54 | + field: AwsSqsFieldsEnum.ACCESS_KEY_ID, | |
55 | + label: AwsSqsFieldsNameEnum.ACCESS_KEY_ID, | |
56 | + component: 'Input', | |
57 | + required: true, | |
58 | + componentProps: { | |
59 | + placeholder: `请输入${AwsSqsFieldsNameEnum.ACCESS_KEY_ID}`, | |
60 | + }, | |
61 | + }, | |
62 | + { | |
63 | + field: AwsSqsFieldsEnum.SECRET_ACCESS_KEY, | |
64 | + label: AwsSqsFieldsNameEnum.SECRET_ACCESS_KEY, | |
65 | + component: 'Input', | |
66 | + required: true, | |
67 | + componentProps: { | |
68 | + placeholder: `请输入${AwsSqsFieldsNameEnum.SECRET_ACCESS_KEY}`, | |
69 | + }, | |
70 | + }, | |
71 | + { | |
72 | + field: AwsSqsFieldsEnum.REGION, | |
73 | + label: AwsSqsFieldsNameEnum.REGION, | |
7 | 74 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
75 | + required: true, | |
76 | + componentProps: { | |
77 | + placeholder: `请输入${AwsSqsFieldsNameEnum.REGION}`, | |
78 | + }, | |
9 | 79 | }, |
10 | 80 | ]; | ... | ... |
... | ... | @@ -3,11 +3,16 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { AttributeConfiguration } from '../../../src/components/AttributeConfiguration'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { AwsSqsFieldsEnum } from '../../../enum/formField/external'; | |
6 | 9 | |
7 | 10 | defineProps<{ |
8 | 11 | config: NodeData; |
9 | 12 | }>(); |
10 | 13 | |
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | |
15 | + | |
11 | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 17 | schemas: formSchemas, |
13 | 18 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +20,18 @@ |
15 | 20 | |
16 | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | |
18 | 24 | const value = getFieldsValue() || {}; |
19 | - return value; | |
25 | + const messageFields = unref(attributeConfigurationElRef)?.getFieldsValue(); | |
26 | + return { ...value, [AwsSqsFieldsEnum.MESSAGE_ATTRIBUTES]: messageFields }; | |
20 | 27 | }; |
21 | 28 | |
22 | 29 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 30 | resetFields(); |
24 | 31 | setFieldsValue(value); |
32 | + unref(attributeConfigurationElRef)?.setFieldsValue( | |
33 | + value?.[AwsSqsFieldsEnum.MESSAGE_ATTRIBUTES] | |
34 | + ); | |
25 | 35 | }; |
26 | 36 | |
27 | 37 | defineExpose({ |
... | ... | @@ -31,5 +41,15 @@ |
31 | 41 | </script> |
32 | 42 | |
33 | 43 | <template> |
34 | - <BasicForm @register="register" /> | |
44 | + <BasicForm @register="register"> | |
45 | + <template #messageAttributes="{ field, model }"> | |
46 | + <AttributeConfiguration | |
47 | + ref="attributeConfigurationElRef" | |
48 | + v-model:value="model[field]" | |
49 | + keyLabel="Name" | |
50 | + valueLabel="Value" | |
51 | + :allowEmpty="true" | |
52 | + /> | |
53 | + </template> | |
54 | + </BasicForm> | |
35 | 55 | </template> | ... | ... |
1 | +import { | |
2 | + AzureIotHubFieldsEnum, | |
3 | + AzureIotHubFieldsNameEnum, | |
4 | +} from '../../../../enum/formField/external'; | |
5 | +import { FormSchema } from '/@/components/Form'; | |
6 | + | |
7 | +export enum CredentialsTypeEnum { | |
8 | + PEM = 'cert.PEM', | |
9 | + SHARED_ACCESS_SIGNATURE = 'sas', | |
10 | +} | |
11 | + | |
12 | +export enum CredentialsTypeNameEnum { | |
13 | + PEM = 'PEM', | |
14 | + SHARED_ACCESS_SIGNATURE = 'Shared Access Signature', | |
15 | +} | |
16 | + | |
17 | +export interface FileItemType { | |
18 | + uid: string; | |
19 | + name: string; | |
20 | + data?: any; | |
21 | +} | |
22 | + | |
23 | +export const getFileData = async (file: FileItemType) => { | |
24 | + return new Promise((resolve) => { | |
25 | + const fileReader = new FileReader(); | |
26 | + fileReader.readAsText(file as unknown as File); | |
27 | + fileReader.onload = () => { | |
28 | + if (fileReader.DONE === fileReader.readyState) { | |
29 | + resolve({ | |
30 | + uid: file.uid, | |
31 | + name: file.name, | |
32 | + data: fileReader.result, | |
33 | + }); | |
34 | + } | |
35 | + }; | |
36 | + }); | |
37 | +}; | |
38 | + | |
39 | +export const credentialsTypeOptions = [ | |
40 | + { | |
41 | + label: CredentialsTypeNameEnum.SHARED_ACCESS_SIGNATURE, | |
42 | + value: CredentialsTypeEnum.SHARED_ACCESS_SIGNATURE, | |
43 | + }, | |
44 | + { label: CredentialsTypeNameEnum.PEM, value: CredentialsTypeEnum.PEM }, | |
45 | +]; | |
46 | + | |
47 | +export const formSchemas = ( | |
48 | + setType: ( | |
49 | + value: CredentialsTypeEnum, | |
50 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
51 | + ) => void | |
52 | +): FormSchema[] => { | |
53 | + return [ | |
54 | + { | |
55 | + field: AzureIotHubFieldsEnum.TYPE, | |
56 | + label: AzureIotHubFieldsNameEnum.TYPE, | |
57 | + component: 'Select', | |
58 | + required: true, | |
59 | + defaultValue: CredentialsTypeEnum.SHARED_ACCESS_SIGNATURE, | |
60 | + componentProps: ({ formActionType }) => { | |
61 | + const { setFieldsValue } = formActionType; | |
62 | + return { | |
63 | + options: credentialsTypeOptions, | |
64 | + placeholder: `请选择${AzureIotHubFieldsNameEnum.TYPE}`, | |
65 | + getPopupContainer: () => document.body, | |
66 | + onChange( | |
67 | + value: CredentialsTypeEnum, | |
68 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
69 | + ) { | |
70 | + setType(value, option); | |
71 | + setFieldsValue({ | |
72 | + [AzureIotHubFieldsEnum.CA_CERT]: [], | |
73 | + [AzureIotHubFieldsEnum.CA_CERT_FILE_NAME]: null, | |
74 | + [AzureIotHubFieldsEnum.CERT]: [], | |
75 | + [AzureIotHubFieldsEnum.CERT_FILE_NAME]: null, | |
76 | + [AzureIotHubFieldsEnum.PRIVATE_KEY]: [], | |
77 | + [AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME]: null, | |
78 | + [AzureIotHubFieldsEnum.PASSWORD]: null, | |
79 | + [AzureIotHubFieldsEnum.SAS_KEY]: null, | |
80 | + }); | |
81 | + }, | |
82 | + }; | |
83 | + }, | |
84 | + }, | |
85 | + { | |
86 | + field: AzureIotHubFieldsEnum.SAS_KEY, | |
87 | + label: AzureIotHubFieldsNameEnum.SAS_KEY, | |
88 | + required: true, | |
89 | + component: 'Input', | |
90 | + ifShow: ({ model }) => | |
91 | + model[AzureIotHubFieldsEnum.TYPE] === CredentialsTypeEnum.SHARED_ACCESS_SIGNATURE, | |
92 | + componentProps: { | |
93 | + placeholder: `请输入${AzureIotHubFieldsNameEnum.SAS_KEY}`, | |
94 | + }, | |
95 | + }, | |
96 | + { | |
97 | + field: AzureIotHubFieldsEnum.CA_CERT_FILE_NAME, | |
98 | + label: AzureIotHubFieldsNameEnum.CA_CERT_FILE_NAME, | |
99 | + component: 'InputPassword', | |
100 | + show: false, | |
101 | + }, | |
102 | + { | |
103 | + field: AzureIotHubFieldsEnum.CA_CERT, | |
104 | + label: AzureIotHubFieldsNameEnum.CA_CERT, | |
105 | + component: 'ApiUpload', | |
106 | + valueField: 'fileList', | |
107 | + changeEvent: 'update:fileList', | |
108 | + componentProps: ({ formActionType }) => { | |
109 | + const { setFieldsValue } = formActionType; | |
110 | + return { | |
111 | + overFileLimitHiddenUploadEntry: true, | |
112 | + api: getFileData, | |
113 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
114 | + setFieldsValue({ [AzureIotHubFieldsEnum.CA_CERT_FILE_NAME]: file?.[0]?.name }); | |
115 | + }, | |
116 | + }; | |
117 | + }, | |
118 | + }, | |
119 | + { | |
120 | + field: AzureIotHubFieldsEnum.CERT_FILE_NAME, | |
121 | + label: AzureIotHubFieldsNameEnum.CERT_FILE_NAME, | |
122 | + component: 'InputPassword', | |
123 | + show: false, | |
124 | + }, | |
125 | + { | |
126 | + field: AzureIotHubFieldsEnum.CERT, | |
127 | + label: AzureIotHubFieldsNameEnum.CERT, | |
128 | + component: 'ApiUpload', | |
129 | + valueField: 'fileList', | |
130 | + changeEvent: 'update:fileList', | |
131 | + required: true, | |
132 | + ifShow: ({ model }) => model[AzureIotHubFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
133 | + componentProps: ({ formActionType }) => { | |
134 | + const { setFieldsValue } = formActionType; | |
135 | + return { | |
136 | + overFileLimitHiddenUploadEntry: true, | |
137 | + api: getFileData, | |
138 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
139 | + setFieldsValue({ [AzureIotHubFieldsEnum.CERT_FILE_NAME]: file?.[0]?.name }); | |
140 | + }, | |
141 | + }; | |
142 | + }, | |
143 | + }, | |
144 | + { | |
145 | + field: AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME, | |
146 | + label: AzureIotHubFieldsNameEnum.PRIVATE_KEY_FILE_NAME, | |
147 | + component: 'InputPassword', | |
148 | + show: false, | |
149 | + }, | |
150 | + { | |
151 | + field: AzureIotHubFieldsEnum.PRIVATE_KEY, | |
152 | + label: AzureIotHubFieldsNameEnum.PRIVATE_KEY, | |
153 | + component: 'ApiUpload', | |
154 | + valueField: 'fileList', | |
155 | + changeEvent: 'update:fileList', | |
156 | + required: true, | |
157 | + ifShow: ({ model }) => model[AzureIotHubFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
158 | + componentProps: ({ formActionType }) => { | |
159 | + const { setFieldsValue } = formActionType; | |
160 | + return { | |
161 | + overFileLimitHiddenUploadEntry: true, | |
162 | + api: getFileData, | |
163 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
164 | + setFieldsValue({ [AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME]: file?.[0]?.name }); | |
165 | + }, | |
166 | + }; | |
167 | + }, | |
168 | + }, | |
169 | + { | |
170 | + field: AzureIotHubFieldsEnum.PASSWORD, | |
171 | + label: AzureIotHubFieldsNameEnum.PASSWORD, | |
172 | + component: 'InputPassword', | |
173 | + ifShow: ({ model }) => model[AzureIotHubFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
174 | + componentProps: { | |
175 | + placeholder: `请输入${AzureIotHubFieldsNameEnum.PASSWORD}`, | |
176 | + }, | |
177 | + }, | |
178 | + ]; | |
179 | +}; | ... | ... |
1 | +export { default as CredentialsCard } from './index.vue'; | ... | ... |
1 | +<script setup lang="ts"> | |
2 | + import { Collapse } from 'ant-design-vue'; | |
3 | + import { BasicForm, useForm } from '/@/components/Form'; | |
4 | + import { credentialsTypeOptions, FileItemType, formSchemas } from './config'; | |
5 | + import { ref, watch } from 'vue'; | |
6 | + import { buildUUID } from '/@/utils/uuid'; | |
7 | + import { CredentialsTypeEnum, CredentialsTypeNameEnum } from '../../../../enum/form'; | |
8 | + import { AzureIotHubFieldsEnum } from '../../../../enum/formField/external'; | |
9 | + | |
10 | + const props = withDefaults( | |
11 | + defineProps<{ | |
12 | + value?: Recordable; | |
13 | + }>(), | |
14 | + { | |
15 | + value: () => ({}), | |
16 | + } | |
17 | + ); | |
18 | + | |
19 | + const activeKey = ref('credentials'); | |
20 | + | |
21 | + const type = ref(CredentialsTypeNameEnum.SHARED_ACCESS_SIGNATURE); | |
22 | + | |
23 | + const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({ | |
24 | + schemas: formSchemas(setCredentialsType), | |
25 | + showActionButtonGroup: false, | |
26 | + layout: 'vertical', | |
27 | + }); | |
28 | + | |
29 | + function setCredentialsType( | |
30 | + _value: CredentialsTypeEnum, | |
31 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
32 | + ) { | |
33 | + type.value = option.label; | |
34 | + } | |
35 | + | |
36 | + const getFileValue = (file: FileItemType[]) => { | |
37 | + return file?.[0]?.data || null; | |
38 | + }; | |
39 | + | |
40 | + const setFileValueByKey = ( | |
41 | + value: Recordable, | |
42 | + key: AzureIotHubFieldsEnum, | |
43 | + fileNameKey: AzureIotHubFieldsEnum | |
44 | + ) => { | |
45 | + return value[key] | |
46 | + ? [{ uid: buildUUID(), name: value[fileNameKey], data: value[key] } as FileItemType] | |
47 | + : []; | |
48 | + }; | |
49 | + | |
50 | + const getValueByKey = (value: Recordable, key: AzureIotHubFieldsEnum) => { | |
51 | + return value?.[key] || null; | |
52 | + }; | |
53 | + | |
54 | + const getValues = () => { | |
55 | + const value = getFieldsValue(); | |
56 | + return { | |
57 | + [AzureIotHubFieldsEnum.CA_CERT]: getFileValue(value?.[AzureIotHubFieldsEnum.CA_CERT]), | |
58 | + [AzureIotHubFieldsEnum.CA_CERT_FILE_NAME]: getValueByKey( | |
59 | + value, | |
60 | + AzureIotHubFieldsEnum.CA_CERT_FILE_NAME | |
61 | + ), | |
62 | + [AzureIotHubFieldsEnum.CA_CERT]: getFileValue(value?.[AzureIotHubFieldsEnum.CERT]), | |
63 | + [AzureIotHubFieldsEnum.CERT_FILE_NAME]: getValueByKey( | |
64 | + value, | |
65 | + AzureIotHubFieldsEnum.CERT_FILE_NAME | |
66 | + ), | |
67 | + [AzureIotHubFieldsEnum.PRIVATE_KEY]: getFileValue(value?.[AzureIotHubFieldsEnum.PRIVATE_KEY]), | |
68 | + [AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME]: getValueByKey( | |
69 | + value, | |
70 | + AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME | |
71 | + ), | |
72 | + [AzureIotHubFieldsEnum.PASSWORD]: getValueByKey(value, AzureIotHubFieldsEnum.PASSWORD), | |
73 | + [AzureIotHubFieldsEnum.TYPE]: getValueByKey(value, AzureIotHubFieldsEnum.TYPE), | |
74 | + [AzureIotHubFieldsEnum.SAS_KEY]: getValueByKey(value, AzureIotHubFieldsEnum.SAS_KEY), | |
75 | + }; | |
76 | + }; | |
77 | + | |
78 | + const setValues = (value: Recordable) => { | |
79 | + const typeLabel = credentialsTypeOptions.find( | |
80 | + (item) => item.value === value?.[AzureIotHubFieldsEnum.TYPE] | |
81 | + )?.label; | |
82 | + type.value = typeLabel!; | |
83 | + setFieldsValue({ | |
84 | + ...value, | |
85 | + [AzureIotHubFieldsEnum.CA_CERT]: setFileValueByKey( | |
86 | + value, | |
87 | + AzureIotHubFieldsEnum.CA_CERT, | |
88 | + AzureIotHubFieldsEnum.CA_CERT_FILE_NAME | |
89 | + ), | |
90 | + [AzureIotHubFieldsEnum.CERT]: setFileValueByKey( | |
91 | + value, | |
92 | + AzureIotHubFieldsEnum.CERT, | |
93 | + AzureIotHubFieldsEnum.CERT_FILE_NAME | |
94 | + ), | |
95 | + [AzureIotHubFieldsEnum.PRIVATE_KEY]: setFileValueByKey( | |
96 | + value, | |
97 | + AzureIotHubFieldsEnum.PRIVATE_KEY, | |
98 | + AzureIotHubFieldsEnum.PRIVATE_KEY_FILE_NAME | |
99 | + ), | |
100 | + }); | |
101 | + }; | |
102 | + | |
103 | + watch( | |
104 | + () => props.value, | |
105 | + (target) => { | |
106 | + setValues(target); | |
107 | + } | |
108 | + ); | |
109 | + | |
110 | + defineExpose({ | |
111 | + validate, | |
112 | + getFieldsValue: getValues, | |
113 | + setFieldsValue: setValues, | |
114 | + }); | |
115 | +</script> | |
116 | + | |
117 | +<template> | |
118 | + <Collapse v-model:active-key="activeKey" class="credentials-card" expand-icon-position="right"> | |
119 | + <Collapse.Panel :key="activeKey" class="box-shadow bg-light-50 shadow-2xl"> | |
120 | + <template #header> | |
121 | + <section class="flex w-full h-full h-8 justify-between items-center"> | |
122 | + <div class="w-1/2 text-left">Credentials</div> | |
123 | + <div class="w-1/2 text-left font-medium text-gray-400"> | |
124 | + {{ type }} | |
125 | + </div> | |
126 | + </section> | |
127 | + </template> | |
128 | + <BasicForm @register="register" /> | |
129 | + </Collapse.Panel> | |
130 | + </Collapse> | |
131 | +</template> | |
132 | + | |
133 | +<style lang="less" scoped> | |
134 | + .credentials-card { | |
135 | + :deep(.ant-collapse) { | |
136 | + &-header { | |
137 | + @apply !px-6; | |
138 | + } | |
139 | + | |
140 | + &-content { | |
141 | + &-box { | |
142 | + @apply px-6; | |
143 | + } | |
144 | + } | |
145 | + } | |
146 | + | |
147 | + :deep(.ant-form) { | |
148 | + > .ant-row { | |
149 | + > .ant-col { | |
150 | + > .ant-row { | |
151 | + > .ant-col { | |
152 | + min-height: fit-content; | |
153 | + } | |
154 | + } | |
155 | + } | |
156 | + } | |
157 | + } | |
158 | + } | |
159 | + | |
160 | + .box-shadow { | |
161 | + box-shadow: 0 3px 1px -2px #0003, 0 2px 2px 0 #00000024, 0 1px 5px 0 #0000001f; | |
162 | + } | |
163 | +</style> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { AzureIotHubFieldsEnum, AzureIotHubFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
3 | +import { CredentialsCard } from './CredentialsCard'; | |
4 | + | |
5 | +useComponentRegister('CredentialsCard', CredentialsCard); | |
3 | 6 | |
4 | 7 | export const formSchemas: FormSchema[] = [ |
5 | 8 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
9 | + field: AzureIotHubFieldsEnum.TOPIC_PATTERN, | |
10 | + label: AzureIotHubFieldsNameEnum.TOPIC_PATTERN, | |
7 | 11 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
12 | + required: true, | |
13 | + helpMessage: | |
14 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
15 | + componentProps: { | |
16 | + placeholder: `请输入${AzureIotHubFieldsNameEnum.TOPIC_PATTERN}`, | |
17 | + }, | |
18 | + }, | |
19 | + { | |
20 | + field: AzureIotHubFieldsEnum.HOST, | |
21 | + label: AzureIotHubFieldsNameEnum.HOST, | |
22 | + component: 'Input', | |
23 | + required: true, | |
24 | + componentProps: { | |
25 | + placeholder: `请输入${AzureIotHubFieldsNameEnum.HOST}`, | |
26 | + }, | |
27 | + }, | |
28 | + { | |
29 | + field: AzureIotHubFieldsEnum.CLIENT_ID, | |
30 | + label: AzureIotHubFieldsNameEnum.CLIENT_ID, | |
31 | + component: 'Input', | |
32 | + required: true, | |
33 | + componentProps: { | |
34 | + placeholder: `请输入${AzureIotHubFieldsNameEnum.CLIENT_ID}`, | |
35 | + }, | |
36 | + }, | |
37 | + { | |
38 | + field: AzureIotHubFieldsEnum.CREDENTIALS, | |
39 | + label: '', | |
40 | + component: 'CredentialsCard', | |
41 | + slot: AzureIotHubFieldsEnum.CREDENTIALS, | |
9 | 42 | }, |
10 | 43 | ]; | ... | ... |
... | ... | @@ -3,11 +3,16 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { CredentialsCard } from './CredentialsCard'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { AzureIotHubFieldsEnum } from '../../../enum/formField/external'; | |
6 | 9 | |
7 | 10 | defineProps<{ |
8 | 11 | config: NodeData; |
9 | 12 | }>(); |
10 | 13 | |
14 | + const credentialsCardElRef = ref<Nullable<InstanceType<typeof CredentialsCard>>>(); | |
15 | + | |
11 | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 17 | schemas: formSchemas, |
13 | 18 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +20,23 @@ |
15 | 20 | |
16 | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 22 | await validate(); |
23 | + await unref(credentialsCardElRef)?.validate(); | |
18 | 24 | const value = getFieldsValue() || {}; |
19 | - return value; | |
25 | + const credentials = unref(credentialsCardElRef)?.getFieldsValue(); | |
26 | + return { | |
27 | + ...value, | |
28 | + [AzureIotHubFieldsEnum.PORT]: 8883, | |
29 | + [AzureIotHubFieldsEnum.SSL]: true, | |
30 | + [AzureIotHubFieldsEnum.CLEAN_SESSION]: true, | |
31 | + [AzureIotHubFieldsEnum.CONNECT_TIMEOUT_SEC]: 10, | |
32 | + [AzureIotHubFieldsEnum.CREDENTIALS]: credentials, | |
33 | + }; | |
20 | 34 | }; |
21 | 35 | |
22 | 36 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 37 | resetFields(); |
24 | 38 | setFieldsValue(value); |
39 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[AzureIotHubFieldsEnum.CREDENTIALS]); | |
25 | 40 | }; |
26 | 41 | |
27 | 42 | defineExpose({ |
... | ... | @@ -31,5 +46,9 @@ |
31 | 46 | </script> |
32 | 47 | |
33 | 48 | <template> |
34 | - <BasicForm @register="register" /> | |
49 | + <BasicForm @register="register"> | |
50 | + <template #credentials="{ field, model }"> | |
51 | + <CredentialsCard ref="credentialsCardElRef" v-model:value="model[field]" /> | |
52 | + </template> | |
53 | + </BasicForm> | |
35 | 54 | </template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { GcpPubsubFieldsEnum, GcpPubsubFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | +import { AttributeConfiguration } from '/@/views/rule/designer/src/components/AttributeConfiguration'; | |
3 | +import { FileItemType, getFileData } from '../../../src/components/CredentialsCard/config'; | |
4 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
5 | + | |
6 | +useComponentRegister('AttributeConfiguration', AttributeConfiguration); | |
3 | 7 | |
4 | 8 | export const formSchemas: FormSchema[] = [ |
5 | 9 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
10 | + field: GcpPubsubFieldsEnum.PROJECT_ID, | |
11 | + label: GcpPubsubFieldsNameEnum.PROJECT_ID, | |
12 | + component: 'Input', | |
13 | + required: true, | |
14 | + componentProps: { | |
15 | + placeholder: `请输入${GcpPubsubFieldsNameEnum.PROJECT_ID}`, | |
16 | + }, | |
17 | + }, | |
18 | + { | |
19 | + field: GcpPubsubFieldsEnum.TOPIC_NAME, | |
20 | + label: GcpPubsubFieldsNameEnum.TOPIC_NAME, | |
7 | 21 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
22 | + required: true, | |
23 | + componentProps: { | |
24 | + placeholder: `请输入${GcpPubsubFieldsNameEnum.TOPIC_NAME}`, | |
25 | + }, | |
26 | + }, | |
27 | + { | |
28 | + field: GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY_FILE_NAME, | |
29 | + label: GcpPubsubFieldsNameEnum.SERVICE_ACCOUNT_KEY_FILE_NAME, | |
30 | + component: 'Input', | |
31 | + show: false, | |
32 | + componentProps: { | |
33 | + placeholder: `请输入${GcpPubsubFieldsNameEnum.TOPIC_NAME}`, | |
34 | + }, | |
35 | + }, | |
36 | + { | |
37 | + field: GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY, | |
38 | + label: GcpPubsubFieldsNameEnum.SERVICE_ACCOUNT_KEY, | |
39 | + component: 'ApiUpload', | |
40 | + valueField: 'fileList', | |
41 | + changeEvent: 'update:fileList', | |
42 | + required: true, | |
43 | + componentProps: ({ formActionType }) => { | |
44 | + const { setFieldsValue } = formActionType; | |
45 | + return { | |
46 | + overFileLimitHiddenUploadEntry: true, | |
47 | + api: getFileData, | |
48 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
49 | + setFieldsValue({ [GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY_FILE_NAME]: file?.[0]?.name }); | |
50 | + }, | |
51 | + }; | |
52 | + }, | |
53 | + }, | |
54 | + { | |
55 | + field: GcpPubsubFieldsEnum.MESSAGE_ATTRIBUTES, | |
56 | + label: GcpPubsubFieldsNameEnum.MESSAGE_ATTRIBUTES, | |
57 | + component: 'AttributeConfiguration', | |
58 | + helpMessage: | |
59 | + 'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields', | |
60 | + slot: GcpPubsubFieldsEnum.MESSAGE_ATTRIBUTES, | |
9 | 61 | }, |
10 | 62 | ]; | ... | ... |
... | ... | @@ -3,6 +3,12 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { AttributeConfiguration } from '/@/views/rule/designer/src/components/AttributeConfiguration'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { GcpPubsubFieldsEnum } from '../../../enum/formField/external'; | |
9 | + import { FileItemType } from '../../../src/components/CredentialsCard/config'; | |
10 | + | |
11 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | |
6 | 12 | |
7 | 13 | defineProps<{ |
8 | 14 | config: NodeData; |
... | ... | @@ -15,13 +21,36 @@ |
15 | 21 | |
16 | 22 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 23 | await validate(); |
24 | + await unref(attributeConfigurationElRef)?.validate(); | |
18 | 25 | const value = getFieldsValue() || {}; |
19 | - return value; | |
26 | + const messageAttribute = unref(attributeConfigurationElRef)?.getFieldsValue(); | |
27 | + return { | |
28 | + ...value, | |
29 | + [GcpPubsubFieldsEnum.MESSAGE_ATTRIBUTES]: messageAttribute, | |
30 | + [GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY]: | |
31 | + value?.[GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY]?.[0]?.data || null, | |
32 | + }; | |
20 | 33 | }; |
21 | 34 | |
22 | 35 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 36 | resetFields(); |
24 | - setFieldsValue(value); | |
37 | + | |
38 | + const file = value?.[GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY] | |
39 | + ? [ | |
40 | + { | |
41 | + uid: Date.now().toString(), | |
42 | + data: value[GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY], | |
43 | + name: value[GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY_FILE_NAME], | |
44 | + } as FileItemType, | |
45 | + ] | |
46 | + : []; | |
47 | + setFieldsValue({ | |
48 | + ...value, | |
49 | + [GcpPubsubFieldsEnum.SERVICE_ACCOUNT_KEY]: file, | |
50 | + }); | |
51 | + unref(attributeConfigurationElRef)?.setFieldsValue( | |
52 | + value?.[GcpPubsubFieldsEnum.MESSAGE_ATTRIBUTES] | |
53 | + ); | |
25 | 54 | }; |
26 | 55 | |
27 | 56 | defineExpose({ |
... | ... | @@ -31,5 +60,15 @@ |
31 | 60 | </script> |
32 | 61 | |
33 | 62 | <template> |
34 | - <BasicForm @register="register" /> | |
63 | + <BasicForm @register="register"> | |
64 | + <template #messageAttributes="{ field, model }"> | |
65 | + <AttributeConfiguration | |
66 | + ref="attributeConfigurationElRef" | |
67 | + v-model:value="model[field]" | |
68 | + keyLabel="Name" | |
69 | + valueLabel="Value" | |
70 | + :allowEmpty="true" | |
71 | + /> | |
72 | + </template> | |
73 | + </BasicForm> | |
35 | 74 | </template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { KafkaFieldsEnum, KafkaFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | +import { AttributeConfiguration } from '/@/views/rule/designer/src/components/AttributeConfiguration'; | |
3 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
4 | +import { CharsetEncodingEnum, CharsetEncodingNameEnum } from '../../../enum/form'; | |
5 | + | |
6 | +useComponentRegister('AttributeConfiguration', AttributeConfiguration); | |
3 | 7 | |
4 | 8 | export const formSchemas: FormSchema[] = [ |
5 | 9 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
10 | + field: KafkaFieldsEnum.TOPIC_PATTERN, | |
11 | + label: KafkaFieldsNameEnum.TOPIC_PATTERN, | |
12 | + component: 'Input', | |
13 | + helpMessage: | |
14 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
15 | + required: true, | |
16 | + componentProps: { | |
17 | + placeholder: `请输入${KafkaFieldsEnum.TOPIC_PATTERN}`, | |
18 | + }, | |
19 | + }, | |
20 | + { | |
21 | + field: KafkaFieldsEnum.BOOTSTRAP_SERVERS, | |
22 | + label: KafkaFieldsNameEnum.BOOTSTRAP_SERVERS, | |
23 | + component: 'Input', | |
24 | + required: true, | |
25 | + componentProps: { | |
26 | + placeholder: `请输入${KafkaFieldsEnum.BOOTSTRAP_SERVERS}`, | |
27 | + }, | |
28 | + }, | |
29 | + { | |
30 | + field: KafkaFieldsEnum.RETRIES, | |
31 | + label: KafkaFieldsNameEnum.RETRIES, | |
32 | + component: 'InputNumber', | |
33 | + componentProps: { | |
34 | + min: 0, | |
35 | + placeholder: `请输入${KafkaFieldsEnum.BOOTSTRAP_SERVERS}`, | |
36 | + }, | |
37 | + }, | |
38 | + { | |
39 | + field: KafkaFieldsEnum.BATCH_SIZE, | |
40 | + label: KafkaFieldsNameEnum.BATCH_SIZE, | |
41 | + component: 'InputNumber', | |
42 | + componentProps: { | |
43 | + min: 0, | |
44 | + placeholder: `请输入${KafkaFieldsEnum.BATCH_SIZE}`, | |
45 | + }, | |
46 | + }, | |
47 | + { | |
48 | + field: KafkaFieldsEnum.LINGER, | |
49 | + label: KafkaFieldsNameEnum.LINGER, | |
50 | + component: 'InputNumber', | |
51 | + componentProps: { | |
52 | + min: 0, | |
53 | + placeholder: `请输入${KafkaFieldsEnum.LINGER}`, | |
54 | + }, | |
55 | + }, | |
56 | + { | |
57 | + field: KafkaFieldsEnum.BUFFER_MEMORY, | |
58 | + label: KafkaFieldsNameEnum.BUFFER_MEMORY, | |
59 | + component: 'InputNumber', | |
60 | + componentProps: { | |
61 | + min: 0, | |
62 | + placeholder: `请输入${KafkaFieldsEnum.BUFFER_MEMORY}`, | |
63 | + }, | |
64 | + }, | |
65 | + { | |
66 | + field: KafkaFieldsEnum.ACKS, | |
67 | + label: KafkaFieldsEnum.ACKS, | |
68 | + component: 'Select', | |
69 | + required: true, | |
70 | + componentProps: { | |
71 | + options: [ | |
72 | + { label: 'all', value: 'all' }, | |
73 | + { label: '-1', value: '-1' }, | |
74 | + { label: '0', value: '0' }, | |
75 | + { label: '1', value: '1' }, | |
76 | + ], | |
77 | + placeholder: `请选择${KafkaFieldsEnum.BUFFER_MEMORY}`, | |
78 | + getPopupContainer: () => document.body, | |
79 | + }, | |
80 | + }, | |
81 | + { | |
82 | + field: KafkaFieldsEnum.KEY_SERIALIZER, | |
83 | + label: KafkaFieldsNameEnum.KEY_SERIALIZER, | |
84 | + component: 'Input', | |
85 | + required: true, | |
86 | + componentProps: { | |
87 | + placeholder: `请输入${KafkaFieldsEnum.KEY_SERIALIZER}`, | |
88 | + }, | |
89 | + }, | |
90 | + { | |
91 | + field: KafkaFieldsEnum.VALUE_SERIALIZER, | |
92 | + label: KafkaFieldsNameEnum.VALUE_SERIALIZER, | |
7 | 93 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
94 | + required: true, | |
95 | + componentProps: { | |
96 | + placeholder: `请输入${KafkaFieldsEnum.VALUE_SERIALIZER}`, | |
97 | + }, | |
98 | + }, | |
99 | + { | |
100 | + field: KafkaFieldsEnum.OTHER_PROPERTIES, | |
101 | + label: KafkaFieldsNameEnum.OTHER_PROPERTIES, | |
102 | + component: 'AttributeConfiguration', | |
103 | + slot: KafkaFieldsEnum.OTHER_PROPERTIES, | |
104 | + }, | |
105 | + { | |
106 | + field: KafkaFieldsEnum.ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS, | |
107 | + label: KafkaFieldsNameEnum.ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS, | |
108 | + component: 'Checkbox', | |
109 | + renderComponentContent: () => ({ | |
110 | + default: () => | |
111 | + 'If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.', | |
112 | + }), | |
113 | + }, | |
114 | + { | |
115 | + field: KafkaFieldsEnum.KAFKA_HEADERS_CHARSET, | |
116 | + label: KafkaFieldsNameEnum.KAFKA_HEADERS_CHARSET, | |
117 | + component: 'Select', | |
118 | + required: true, | |
119 | + show: ({ model }) => model[KafkaFieldsEnum.ADD_METADATA_KEY_VALUES_AS_KAFKA_HEADERS], | |
120 | + componentProps: { | |
121 | + options: Object.keys(CharsetEncodingEnum).map((value) => ({ | |
122 | + label: CharsetEncodingNameEnum[value], | |
123 | + value, | |
124 | + })), | |
125 | + placeholder: `请选择${KafkaFieldsEnum.KAFKA_HEADERS_CHARSET}`, | |
126 | + getPopupContainer: () => document.body, | |
127 | + }, | |
9 | 128 | }, |
10 | 129 | ]; | ... | ... |
... | ... | @@ -3,11 +3,16 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { AttributeConfiguration } from '/@/views/rule/designer/src/components/AttributeConfiguration'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { KafkaFieldsEnum } from '../../../enum/formField/external'; | |
6 | 9 | |
7 | 10 | defineProps<{ |
8 | 11 | config: NodeData; |
9 | 12 | }>(); |
10 | 13 | |
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | |
15 | + | |
11 | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 17 | schemas: formSchemas, |
13 | 18 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +20,19 @@ |
15 | 20 | |
16 | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | |
18 | 24 | const value = getFieldsValue() || {}; |
19 | - return value; | |
25 | + const otherProperties = unref(attributeConfigurationElRef)?.getFieldsValue(); | |
26 | + return { | |
27 | + ...value, | |
28 | + [KafkaFieldsEnum.OTHER_PROPERTIES]: otherProperties, | |
29 | + }; | |
20 | 30 | }; |
21 | 31 | |
22 | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 33 | resetFields(); |
24 | 34 | setFieldsValue(value); |
35 | + unref(attributeConfigurationElRef)?.setFieldsValue(value?.[KafkaFieldsEnum.OTHER_PROPERTIES]); | |
25 | 36 | }; |
26 | 37 | |
27 | 38 | defineExpose({ |
... | ... | @@ -31,5 +42,15 @@ |
31 | 42 | </script> |
32 | 43 | |
33 | 44 | <template> |
34 | - <BasicForm @register="register" /> | |
45 | + <BasicForm @register="register"> | |
46 | + <template #otherProperties="{ field, model }"> | |
47 | + <AttributeConfiguration | |
48 | + ref="attributeConfigurationElRef" | |
49 | + v-model:value="model[field]" | |
50 | + keyLabel="Key" | |
51 | + valueLabel="Value" | |
52 | + :allowEmpty="true" | |
53 | + /> | |
54 | + </template> | |
55 | + </BasicForm> | |
35 | 56 | </template> | ... | ... |
1 | +import { MqttFieldsEnum, MqttFieldsNameEnum } from '../../../../enum/formField/external'; | |
2 | +import { FormSchema } from '/@/components/Form'; | |
3 | + | |
4 | +// Credentials type | |
5 | +export enum CredentialsTypeEnum { | |
6 | + BASIC = 'basic', | |
7 | + PEM = 'cert.PEM', | |
8 | + ANONYMOUS = 'anonymous', | |
9 | +} | |
10 | + | |
11 | +export enum CredentialsTypeNameEnum { | |
12 | + BASIC = 'Basic', | |
13 | + ANONYMOUS = 'Anonymous', | |
14 | + PEM = 'PEM', | |
15 | +} | |
16 | + | |
17 | +export interface FileItemType { | |
18 | + uid: string; | |
19 | + name: string; | |
20 | + data?: any; | |
21 | +} | |
22 | + | |
23 | +export const getFileData = async (file: FileItemType) => { | |
24 | + return new Promise((resolve) => { | |
25 | + const fileReader = new FileReader(); | |
26 | + fileReader.readAsText(file as unknown as File); | |
27 | + fileReader.onload = () => { | |
28 | + if (fileReader.DONE === fileReader.readyState) { | |
29 | + resolve({ | |
30 | + uid: file.uid, | |
31 | + name: file.name, | |
32 | + data: fileReader.result, | |
33 | + }); | |
34 | + } | |
35 | + }; | |
36 | + }); | |
37 | +}; | |
38 | + | |
39 | +export const credentialsTypeOptions = [ | |
40 | + { label: CredentialsTypeNameEnum.BASIC, value: CredentialsTypeEnum.BASIC }, | |
41 | + { label: CredentialsTypeNameEnum.ANONYMOUS, value: CredentialsTypeEnum.ANONYMOUS }, | |
42 | + { label: CredentialsTypeNameEnum.PEM, value: CredentialsTypeEnum.PEM }, | |
43 | +]; | |
44 | + | |
45 | +export const formSchemas = ( | |
46 | + setType: ( | |
47 | + value: CredentialsTypeEnum, | |
48 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
49 | + ) => void | |
50 | +): FormSchema[] => { | |
51 | + return [ | |
52 | + { | |
53 | + field: MqttFieldsEnum.TYPE, | |
54 | + label: MqttFieldsNameEnum.TYPE, | |
55 | + component: 'Select', | |
56 | + required: true, | |
57 | + defaultValue: CredentialsTypeEnum.ANONYMOUS, | |
58 | + componentProps: ({ formActionType }) => { | |
59 | + const { setFieldsValue } = formActionType; | |
60 | + return { | |
61 | + options: credentialsTypeOptions, | |
62 | + placeholder: `请选择${MqttFieldsNameEnum.TYPE}`, | |
63 | + getPopupContainer: () => document.body, | |
64 | + onChange( | |
65 | + value: CredentialsTypeEnum, | |
66 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
67 | + ) { | |
68 | + setType(value, option); | |
69 | + setFieldsValue({ | |
70 | + [MqttFieldsEnum.CA_CERT]: [], | |
71 | + [MqttFieldsEnum.CA_CERT_FILE_NAME]: null, | |
72 | + [MqttFieldsEnum.CERT]: [], | |
73 | + [MqttFieldsEnum.CERT_FILE_NAME]: null, | |
74 | + [MqttFieldsEnum.PRIVATE_KEY]: [], | |
75 | + [MqttFieldsEnum.PRIVATE_KEY_FILE_NAME]: null, | |
76 | + [MqttFieldsEnum.PASSWORD]: null, | |
77 | + }); | |
78 | + }, | |
79 | + }; | |
80 | + }, | |
81 | + }, | |
82 | + { | |
83 | + field: MqttFieldsEnum.USERNAME, | |
84 | + label: MqttFieldsNameEnum.USERNAME, | |
85 | + component: 'Input', | |
86 | + required: true, | |
87 | + ifShow: ({ model }) => model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.BASIC, | |
88 | + componentProps: { | |
89 | + placeholder: `请输入${MqttFieldsNameEnum.USERNAME}`, | |
90 | + }, | |
91 | + }, | |
92 | + { | |
93 | + field: MqttFieldsEnum.CA_CERT_FILE_NAME, | |
94 | + label: MqttFieldsNameEnum.CA_CERT_FILE_NAME, | |
95 | + component: 'InputPassword', | |
96 | + show: false, | |
97 | + }, | |
98 | + { | |
99 | + field: MqttFieldsEnum.CA_CERT, | |
100 | + label: MqttFieldsNameEnum.CA_CERT, | |
101 | + component: 'ApiUpload', | |
102 | + valueField: 'fileList', | |
103 | + changeEvent: 'update:fileList', | |
104 | + required: true, | |
105 | + ifShow: ({ model }) => model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
106 | + componentProps: ({ formActionType }) => { | |
107 | + const { setFieldsValue } = formActionType; | |
108 | + return { | |
109 | + overFileLimitHiddenUploadEntry: true, | |
110 | + api: getFileData, | |
111 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
112 | + setFieldsValue({ [MqttFieldsEnum.CA_CERT_FILE_NAME]: file?.[0]?.name }); | |
113 | + }, | |
114 | + }; | |
115 | + }, | |
116 | + }, | |
117 | + { | |
118 | + field: MqttFieldsEnum.CERT_FILE_NAME, | |
119 | + label: MqttFieldsNameEnum.CERT_FILE_NAME, | |
120 | + component: 'InputPassword', | |
121 | + show: false, | |
122 | + }, | |
123 | + { | |
124 | + field: MqttFieldsEnum.CERT, | |
125 | + label: MqttFieldsNameEnum.CERT, | |
126 | + component: 'ApiUpload', | |
127 | + valueField: 'fileList', | |
128 | + changeEvent: 'update:fileList', | |
129 | + required: true, | |
130 | + ifShow: ({ model }) => model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
131 | + componentProps: ({ formActionType }) => { | |
132 | + const { setFieldsValue } = formActionType; | |
133 | + return { | |
134 | + overFileLimitHiddenUploadEntry: true, | |
135 | + api: getFileData, | |
136 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
137 | + setFieldsValue({ [MqttFieldsEnum.CERT_FILE_NAME]: file?.[0]?.name }); | |
138 | + }, | |
139 | + }; | |
140 | + }, | |
141 | + }, | |
142 | + { | |
143 | + field: MqttFieldsEnum.PRIVATE_KEY_FILE_NAME, | |
144 | + label: MqttFieldsNameEnum.PRIVATE_KEY_FILE_NAME, | |
145 | + component: 'InputPassword', | |
146 | + show: false, | |
147 | + }, | |
148 | + { | |
149 | + field: MqttFieldsEnum.PRIVATE_KEY, | |
150 | + label: MqttFieldsNameEnum.PRIVATE_KEY, | |
151 | + component: 'ApiUpload', | |
152 | + valueField: 'fileList', | |
153 | + changeEvent: 'update:fileList', | |
154 | + required: true, | |
155 | + ifShow: ({ model }) => model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.PEM, | |
156 | + componentProps: ({ formActionType }) => { | |
157 | + const { setFieldsValue } = formActionType; | |
158 | + return { | |
159 | + overFileLimitHiddenUploadEntry: true, | |
160 | + api: getFileData, | |
161 | + 'onUpdate:fileList'(file: FileItemType[]) { | |
162 | + setFieldsValue({ [MqttFieldsEnum.PRIVATE_KEY_FILE_NAME]: file?.[0]?.name }); | |
163 | + }, | |
164 | + }; | |
165 | + }, | |
166 | + }, | |
167 | + { | |
168 | + field: MqttFieldsEnum.PASSWORD, | |
169 | + label: MqttFieldsNameEnum.PASSWORD, | |
170 | + component: 'InputPassword', | |
171 | + ifShow: ({ model }) => | |
172 | + model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.PEM || | |
173 | + model[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.BASIC, | |
174 | + componentProps: { | |
175 | + placeholder: `请输入${MqttFieldsNameEnum.PASSWORD}`, | |
176 | + }, | |
177 | + }, | |
178 | + ]; | |
179 | +}; | ... | ... |
1 | +export { default as CredentialsCard } from './index.vue'; | ... | ... |
1 | +<script setup lang="ts"> | |
2 | + import { Collapse } from 'ant-design-vue'; | |
3 | + import { BasicForm, useForm } from '/@/components/Form'; | |
4 | + import { credentialsTypeOptions, FileItemType, formSchemas } from './config'; | |
5 | + import { ref, watch } from 'vue'; | |
6 | + import { buildUUID } from '/@/utils/uuid'; | |
7 | + import { CredentialsTypeEnum, CredentialsTypeNameEnum } from './config'; | |
8 | + import { MqttFieldsEnum } from '../../../../enum/formField/external'; | |
9 | + | |
10 | + const props = withDefaults( | |
11 | + defineProps<{ | |
12 | + value?: Recordable; | |
13 | + }>(), | |
14 | + { | |
15 | + value: () => ({}), | |
16 | + } | |
17 | + ); | |
18 | + | |
19 | + const activeKey = ref('credentials'); | |
20 | + | |
21 | + const type = ref(CredentialsTypeNameEnum.ANONYMOUS); | |
22 | + | |
23 | + const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({ | |
24 | + schemas: formSchemas(setCredentialsType), | |
25 | + showActionButtonGroup: false, | |
26 | + layout: 'vertical', | |
27 | + }); | |
28 | + | |
29 | + function setCredentialsType( | |
30 | + _value: CredentialsTypeEnum, | |
31 | + option: { label: CredentialsTypeNameEnum; value: CredentialsTypeEnum } | |
32 | + ) { | |
33 | + type.value = option.label; | |
34 | + } | |
35 | + | |
36 | + const getFileValue = (file: FileItemType[]) => { | |
37 | + return file?.[0]?.data || null; | |
38 | + }; | |
39 | + | |
40 | + const setFileValueByKey = ( | |
41 | + value: Recordable, | |
42 | + key: MqttFieldsEnum, | |
43 | + fileNameKey: MqttFieldsEnum | |
44 | + ) => { | |
45 | + return value[key] | |
46 | + ? [{ uid: buildUUID(), name: value[fileNameKey], data: value[key] } as FileItemType] | |
47 | + : []; | |
48 | + }; | |
49 | + | |
50 | + const getValues = () => { | |
51 | + const value = getFieldsValue(); | |
52 | + return { | |
53 | + ...value, | |
54 | + ...(value?.[MqttFieldsEnum.TYPE] === CredentialsTypeEnum.PEM | |
55 | + ? { | |
56 | + [MqttFieldsEnum.CA_CERT]: getFileValue(value?.[MqttFieldsEnum.CA_CERT]), | |
57 | + [MqttFieldsEnum.CA_CERT]: getFileValue(value?.[MqttFieldsEnum.CERT]), | |
58 | + [MqttFieldsEnum.PRIVATE_KEY]: getFileValue(value?.[MqttFieldsEnum.PRIVATE_KEY]), | |
59 | + } | |
60 | + : {}), | |
61 | + }; | |
62 | + }; | |
63 | + | |
64 | + const setValues = (value: Recordable) => { | |
65 | + const typeLabel = credentialsTypeOptions.find( | |
66 | + (item) => item.value === value?.[MqttFieldsEnum.TYPE] | |
67 | + )?.label; | |
68 | + type.value = typeLabel!; | |
69 | + setFieldsValue({ | |
70 | + ...value, | |
71 | + [MqttFieldsEnum.CA_CERT]: setFileValueByKey( | |
72 | + value, | |
73 | + MqttFieldsEnum.CA_CERT, | |
74 | + MqttFieldsEnum.CA_CERT_FILE_NAME | |
75 | + ), | |
76 | + [MqttFieldsEnum.CERT]: setFileValueByKey( | |
77 | + value, | |
78 | + MqttFieldsEnum.CERT, | |
79 | + MqttFieldsEnum.CERT_FILE_NAME | |
80 | + ), | |
81 | + [MqttFieldsEnum.PRIVATE_KEY]: setFileValueByKey( | |
82 | + value, | |
83 | + MqttFieldsEnum.PRIVATE_KEY, | |
84 | + MqttFieldsEnum.PRIVATE_KEY_FILE_NAME | |
85 | + ), | |
86 | + }); | |
87 | + }; | |
88 | + | |
89 | + watch( | |
90 | + () => props.value, | |
91 | + (target) => { | |
92 | + setValues(target); | |
93 | + } | |
94 | + ); | |
95 | + | |
96 | + defineExpose({ | |
97 | + validate, | |
98 | + getFieldsValue: getValues, | |
99 | + setFieldsValue: setValues, | |
100 | + }); | |
101 | +</script> | |
102 | + | |
103 | +<template> | |
104 | + <Collapse v-model:active-key="activeKey" class="credentials-card" expand-icon-position="right"> | |
105 | + <Collapse.Panel :key="activeKey" class="box-shadow bg-light-50 shadow-2xl"> | |
106 | + <template #header> | |
107 | + <section class="flex w-full h-full h-8 justify-between items-center"> | |
108 | + <div class="w-1/2 text-left">Credentials</div> | |
109 | + <div class="w-1/2 text-left font-medium text-gray-400"> | |
110 | + {{ type }} | |
111 | + </div> | |
112 | + </section> | |
113 | + </template> | |
114 | + <BasicForm @register="register" /> | |
115 | + </Collapse.Panel> | |
116 | + </Collapse> | |
117 | +</template> | |
118 | + | |
119 | +<style lang="less" scoped> | |
120 | + .credentials-card { | |
121 | + :deep(.ant-collapse) { | |
122 | + &-header { | |
123 | + @apply !px-6; | |
124 | + } | |
125 | + | |
126 | + &-content { | |
127 | + &-box { | |
128 | + @apply px-6; | |
129 | + } | |
130 | + } | |
131 | + } | |
132 | + | |
133 | + :deep(.ant-form) { | |
134 | + > .ant-row { | |
135 | + > .ant-col { | |
136 | + > .ant-row { | |
137 | + > .ant-col { | |
138 | + min-height: fit-content; | |
139 | + } | |
140 | + } | |
141 | + } | |
142 | + } | |
143 | + } | |
144 | + } | |
145 | + | |
146 | + .box-shadow { | |
147 | + box-shadow: 0 3px 1px -2px #0003, 0 2px 2px 0 #00000024, 0 1px 5px 0 #0000001f; | |
148 | + } | |
149 | +</style> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { MqttFieldsEnum, MqttFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | +import { CredentialsCard } from './CredentialsCard'; | |
3 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
4 | + | |
5 | +useComponentRegister('CredentialsCard', CredentialsCard); | |
3 | 6 | |
4 | 7 | export const formSchemas: FormSchema[] = [ |
5 | 8 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
9 | + field: MqttFieldsEnum.TOPIC_PATTERN, | |
10 | + label: MqttFieldsNameEnum.TOPIC_PATTERN, | |
11 | + component: 'Input', | |
12 | + helpMessage: | |
13 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
14 | + required: true, | |
15 | + componentProps: { | |
16 | + placeholder: `请输入${MqttFieldsNameEnum.TOPIC_PATTERN}`, | |
17 | + }, | |
18 | + }, | |
19 | + { | |
20 | + field: MqttFieldsEnum.HOST, | |
21 | + label: MqttFieldsNameEnum.HOST, | |
22 | + component: 'Input', | |
23 | + required: true, | |
24 | + colProps: { span: 8 }, | |
25 | + componentProps: { | |
26 | + placeholder: `请输入${MqttFieldsNameEnum.HOST}`, | |
27 | + }, | |
28 | + }, | |
29 | + { | |
30 | + field: MqttFieldsEnum.PORT, | |
31 | + label: MqttFieldsNameEnum.PORT, | |
32 | + component: 'InputNumber', | |
33 | + required: true, | |
34 | + colProps: { span: 8 }, | |
35 | + componentProps: { | |
36 | + placeholder: `请输入${MqttFieldsNameEnum.PORT}`, | |
37 | + }, | |
38 | + }, | |
39 | + { | |
40 | + field: MqttFieldsEnum.CONNECT_TIMEOUT_SEC, | |
41 | + label: MqttFieldsNameEnum.CONNECT_TIMEOUT_SEC, | |
42 | + component: 'Input', | |
43 | + required: true, | |
44 | + colProps: { span: 8 }, | |
45 | + componentProps: { | |
46 | + placeholder: `请输入${MqttFieldsNameEnum.CONNECT_TIMEOUT_SEC}`, | |
47 | + }, | |
48 | + }, | |
49 | + { | |
50 | + field: MqttFieldsEnum.CLIENT_ID, | |
51 | + label: MqttFieldsNameEnum.CLIENT_ID, | |
7 | 52 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
53 | + helpMessage: | |
54 | + 'Hint: Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.', | |
55 | + componentProps: { | |
56 | + placeholder: `请输入${MqttFieldsNameEnum.TOPIC_PATTERN}`, | |
57 | + }, | |
58 | + }, | |
59 | + { | |
60 | + field: MqttFieldsEnum.APPEND_CLIENT_ID_SUFFIX, | |
61 | + label: MqttFieldsNameEnum.APPEND_CLIENT_ID_SUFFIX, | |
62 | + component: 'Checkbox', | |
63 | + renderComponentContent: () => ({ | |
64 | + default: () => | |
65 | + 'Hint: Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.', | |
66 | + }), | |
67 | + componentProps: ({ formModel }) => { | |
68 | + const clientId = formModel[MqttFieldsEnum.CLIENT_ID]; | |
69 | + return { | |
70 | + disabled: !clientId, | |
71 | + }; | |
72 | + }, | |
73 | + }, | |
74 | + { | |
75 | + field: MqttFieldsEnum.CLEAN_SESSION, | |
76 | + label: '', | |
77 | + component: 'Checkbox', | |
78 | + renderComponentContent: () => ({ | |
79 | + default: () => MqttFieldsNameEnum.CLEAN_SESSION, | |
80 | + }), | |
81 | + }, | |
82 | + { | |
83 | + field: MqttFieldsEnum.SSL, | |
84 | + label: '', | |
85 | + component: 'Checkbox', | |
86 | + renderComponentContent: () => ({ | |
87 | + default: () => MqttFieldsNameEnum.SSL, | |
88 | + }), | |
89 | + }, | |
90 | + { | |
91 | + field: MqttFieldsEnum.CREDENTIALS, | |
92 | + label: MqttFieldsNameEnum.CREDENTIALS, | |
93 | + component: 'CredentialsCard', | |
94 | + slot: MqttFieldsEnum.CREDENTIALS, | |
9 | 95 | }, |
10 | 96 | ]; | ... | ... |
... | ... | @@ -3,11 +3,16 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { CredentialsCard } from './CredentialsCard'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { MqttFieldsEnum } from '../../../enum/formField/external'; | |
6 | 9 | |
7 | 10 | defineProps<{ |
8 | 11 | config: NodeData; |
9 | 12 | }>(); |
10 | 13 | |
14 | + const credentialsCardElRef = ref<Nullable<InstanceType<typeof CredentialsCard>>>(); | |
15 | + | |
11 | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 17 | schemas: formSchemas, |
13 | 18 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +20,19 @@ |
15 | 20 | |
16 | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 22 | await validate(); |
23 | + await unref(credentialsCardElRef)?.validate(); | |
18 | 24 | const value = getFieldsValue() || {}; |
19 | - return value; | |
25 | + const credentialsValue = unref(credentialsCardElRef)?.getFieldsValue(); | |
26 | + return { | |
27 | + ...value, | |
28 | + [MqttFieldsEnum.CREDENTIALS]: credentialsValue, | |
29 | + }; | |
20 | 30 | }; |
21 | 31 | |
22 | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 33 | resetFields(); |
24 | 34 | setFieldsValue(value); |
35 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[MqttFieldsEnum.CREDENTIALS]); | |
25 | 36 | }; |
26 | 37 | |
27 | 38 | defineExpose({ |
... | ... | @@ -31,5 +42,9 @@ |
31 | 42 | </script> |
32 | 43 | |
33 | 44 | <template> |
34 | - <BasicForm @register="register" /> | |
45 | + <BasicForm @register="register"> | |
46 | + <template #credentials="{ field, model }"> | |
47 | + <CredentialsCard ref="credentialsCardElRef" v-model:value="model[field]" /> | |
48 | + </template> | |
49 | + </BasicForm> | |
35 | 50 | </template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { MessagePropertiesEnum } from '../../../enum/form'; | |
2 | +import { RabbitmqFieldsEnum, RabbitmqFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | |
4 | 5 | export const formSchemas: FormSchema[] = [ |
5 | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | + field: RabbitmqFieldsEnum.EXCHANGE_NAME_PATTERN, | |
8 | + label: RabbitmqFieldsNameEnum.EXCHANGE_NAME_PATTERN, | |
7 | 9 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
10 | + componentProps: { | |
11 | + placeholder: `请输入${RabbitmqFieldsNameEnum.EXCHANGE_NAME_PATTERN}`, | |
12 | + }, | |
13 | + }, | |
14 | + { | |
15 | + field: RabbitmqFieldsEnum.ROUTING_KEY_PATTERN, | |
16 | + label: RabbitmqFieldsNameEnum.ROUTING_KEY_PATTERN, | |
17 | + component: 'Input', | |
18 | + componentProps: { | |
19 | + placeholder: `请输入${RabbitmqFieldsNameEnum.ROUTING_KEY_PATTERN}`, | |
20 | + }, | |
21 | + }, | |
22 | + { | |
23 | + field: RabbitmqFieldsEnum.MESSAGE_PROPERTIES, | |
24 | + label: RabbitmqFieldsNameEnum.MESSAGE_PROPERTIES, | |
25 | + component: 'Select', | |
26 | + componentProps: { | |
27 | + allowClear: true, | |
28 | + options: Object.keys(MessagePropertiesEnum).map((value) => ({ label: value, value })), | |
29 | + placeholder: `请选择${RabbitmqFieldsNameEnum.ROUTING_KEY_PATTERN}`, | |
30 | + }, | |
31 | + }, | |
32 | + { | |
33 | + field: RabbitmqFieldsEnum.HOST, | |
34 | + label: RabbitmqFieldsNameEnum.HOST, | |
35 | + component: 'Input', | |
36 | + required: true, | |
37 | + colProps: { span: 12 }, | |
38 | + componentProps: { | |
39 | + placeholder: `请输入${RabbitmqFieldsNameEnum.HOST}`, | |
40 | + }, | |
41 | + }, | |
42 | + { | |
43 | + field: RabbitmqFieldsEnum.PORT, | |
44 | + label: RabbitmqFieldsNameEnum.PORT, | |
45 | + component: 'InputNumber', | |
46 | + required: true, | |
47 | + colProps: { span: 12 }, | |
48 | + componentProps: { | |
49 | + placeholder: `请输入${RabbitmqFieldsNameEnum.PORT}`, | |
50 | + }, | |
51 | + }, | |
52 | + { | |
53 | + field: RabbitmqFieldsEnum.VIRTUAL_HOST, | |
54 | + label: RabbitmqFieldsNameEnum.VIRTUAL_HOST, | |
55 | + component: 'Input', | |
56 | + componentProps: { | |
57 | + placeholder: `请输入${RabbitmqFieldsNameEnum.VIRTUAL_HOST}`, | |
58 | + }, | |
59 | + }, | |
60 | + { | |
61 | + field: RabbitmqFieldsEnum.USERNAME, | |
62 | + label: RabbitmqFieldsNameEnum.USERNAME, | |
63 | + component: 'Input', | |
64 | + componentProps: { | |
65 | + placeholder: `请输入${RabbitmqFieldsNameEnum.USERNAME}`, | |
66 | + }, | |
67 | + }, | |
68 | + { | |
69 | + field: RabbitmqFieldsEnum.PASSWORD, | |
70 | + label: RabbitmqFieldsNameEnum.PASSWORD, | |
71 | + component: 'Input', | |
72 | + componentProps: { | |
73 | + placeholder: `请输入${RabbitmqFieldsNameEnum.PASSWORD}`, | |
74 | + }, | |
75 | + }, | |
76 | + { | |
77 | + field: RabbitmqFieldsEnum.AUTOMATIC_RECOVERY_ENABLED, | |
78 | + component: 'Checkbox', | |
79 | + label: '', | |
80 | + renderComponentContent: () => ({ | |
81 | + default: () => RabbitmqFieldsNameEnum.AUTOMATIC_RECOVERY_ENABLED, | |
82 | + }), | |
83 | + }, | |
84 | + { | |
85 | + field: RabbitmqFieldsEnum.CONNECTION_TIMEOUT, | |
86 | + label: RabbitmqFieldsNameEnum.CONNECTION_TIMEOUT, | |
87 | + component: 'InputNumber', | |
88 | + componentProps: { | |
89 | + min: 0, | |
90 | + placeholder: `请输入${RabbitmqFieldsNameEnum.CONNECTION_TIMEOUT}`, | |
91 | + }, | |
92 | + }, | |
93 | + { | |
94 | + field: RabbitmqFieldsEnum.HANDSHAKE_TIMEOUT, | |
95 | + label: RabbitmqFieldsNameEnum.HANDSHAKE_TIMEOUT, | |
96 | + component: 'InputNumber', | |
97 | + componentProps: { | |
98 | + min: 0, | |
99 | + placeholder: `请输入${RabbitmqFieldsNameEnum.HANDSHAKE_TIMEOUT}`, | |
100 | + }, | |
101 | + }, | |
102 | + { | |
103 | + field: RabbitmqFieldsEnum.CLIENT_PROPERTIES, | |
104 | + label: RabbitmqFieldsNameEnum.CLIENT_PROPERTIES, | |
105 | + component: 'Input', | |
106 | + slot: RabbitmqFieldsEnum.CLIENT_PROPERTIES, | |
9 | 107 | }, |
10 | 108 | ]; | ... | ... |
... | ... | @@ -3,11 +3,16 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { AttributeConfiguration } from '/@/views/rule/designer/src/components/AttributeConfiguration'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { RabbitmqFieldsEnum } from '../../../enum/formField/external'; | |
6 | 9 | |
7 | 10 | defineProps<{ |
8 | 11 | config: NodeData; |
9 | 12 | }>(); |
10 | 13 | |
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | |
15 | + | |
11 | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 17 | schemas: formSchemas, |
13 | 18 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +20,21 @@ |
15 | 20 | |
16 | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | |
18 | 24 | const value = getFieldsValue() || {}; |
19 | - return value; | |
25 | + const clientProperties = unref(attributeConfigurationElRef)?.getFieldsValue(); | |
26 | + return { | |
27 | + ...value, | |
28 | + [RabbitmqFieldsEnum.CLIENT_PROPERTIES]: clientProperties, | |
29 | + }; | |
20 | 30 | }; |
21 | 31 | |
22 | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 33 | resetFields(); |
24 | 34 | setFieldsValue(value); |
35 | + unref(attributeConfigurationElRef)?.setFieldsValue( | |
36 | + value?.[RabbitmqFieldsEnum.CLIENT_PROPERTIES] | |
37 | + ); | |
25 | 38 | }; |
26 | 39 | |
27 | 40 | defineExpose({ |
... | ... | @@ -31,5 +44,15 @@ |
31 | 44 | </script> |
32 | 45 | |
33 | 46 | <template> |
34 | - <BasicForm @register="register" /> | |
47 | + <BasicForm @register="register"> | |
48 | + <template #clientProperties="{ field, model }"> | |
49 | + <AttributeConfiguration | |
50 | + ref="attributeConfigurationElRef" | |
51 | + v-model:value="model[field]" | |
52 | + keyLabel="Key" | |
53 | + valueLabel="Value" | |
54 | + :allowEmpty="true" | |
55 | + /> | |
56 | + </template> | |
57 | + </BasicForm> | |
35 | 58 | </template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { ProtocolEnum, ProtocolNameEnum, RequestMethodEnum } from '../../../enum/form'; | |
2 | +import { RestApiCallFieldsEnum, RestApiCallFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | |
4 | 5 | export const formSchemas: FormSchema[] = [ |
5 | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | + field: RestApiCallFieldsEnum.REST_ENDPOINT_URL_PATTERN, | |
8 | + label: RestApiCallFieldsNameEnum.REST_ENDPOINT_URL_PATTERN, | |
7 | 9 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
10 | + required: true, | |
11 | + helpMessage: | |
12 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
13 | + componentProps: { | |
14 | + placeholder: `请输入${RestApiCallFieldsNameEnum.REST_ENDPOINT_URL_PATTERN}`, | |
15 | + }, | |
16 | + }, | |
17 | + { | |
18 | + field: RestApiCallFieldsEnum.REQUEST_METHOD, | |
19 | + label: RestApiCallFieldsNameEnum.REQUEST_METHOD, | |
20 | + component: 'Select', | |
21 | + required: true, | |
22 | + componentProps: { | |
23 | + options: Object.keys(RequestMethodEnum).map((value) => ({ label: value, value })), | |
24 | + getPopupContainer: () => document.body, | |
25 | + placeholder: `请选择${RestApiCallFieldsNameEnum.REQUEST_METHOD}`, | |
26 | + }, | |
27 | + }, | |
28 | + { | |
29 | + field: RestApiCallFieldsEnum.ENABLE_PROXY, | |
30 | + label: '', | |
31 | + component: 'Checkbox', | |
32 | + renderComponentContent: () => ({ | |
33 | + default: () => RestApiCallFieldsNameEnum.ENABLE_PROXY, | |
34 | + }), | |
35 | + }, | |
36 | + { | |
37 | + field: RestApiCallFieldsEnum.USE_SIMPLE_CLIENT_HTTP_FACTORY, | |
38 | + label: '', | |
39 | + component: 'Checkbox', | |
40 | + show: ({ model }) => !model[RestApiCallFieldsEnum.ENABLE_PROXY], | |
41 | + renderComponentContent: () => ({ | |
42 | + default: () => RestApiCallFieldsNameEnum.USE_SIMPLE_CLIENT_HTTP_FACTORY, | |
43 | + }), | |
44 | + }, | |
45 | + { | |
46 | + field: RestApiCallFieldsEnum.IGNORE_REQUEST_BODY, | |
47 | + label: '', | |
48 | + component: 'Checkbox', | |
49 | + renderComponentContent: () => ({ | |
50 | + default: () => RestApiCallFieldsNameEnum.IGNORE_REQUEST_BODY, | |
51 | + }), | |
52 | + }, | |
53 | + { | |
54 | + field: RestApiCallFieldsEnum.USE_SYSTEM_PROXY_PROPERTIES, | |
55 | + label: '', | |
56 | + component: 'Checkbox', | |
57 | + show: ({ model }) => model[RestApiCallFieldsEnum.ENABLE_PROXY], | |
58 | + renderComponentContent: () => ({ | |
59 | + default: () => RestApiCallFieldsNameEnum.USE_SYSTEM_PROXY_PROPERTIES, | |
60 | + }), | |
61 | + }, | |
62 | + { | |
63 | + field: RestApiCallFieldsEnum.PROXY_SCHEME, | |
64 | + label: RestApiCallFieldsNameEnum.PROXY_SCHEME, | |
65 | + component: 'Select', | |
66 | + required: true, | |
67 | + colProps: { span: 8 }, | |
68 | + componentProps: { | |
69 | + options: Object.keys(ProtocolEnum).map((value) => ({ | |
70 | + label: ProtocolNameEnum[value], | |
71 | + value, | |
72 | + })), | |
73 | + getPopupContainer: () => document.body, | |
74 | + placeholder: `请选择${RestApiCallFieldsEnum.PROXY_SCHEME}`, | |
75 | + }, | |
76 | + }, | |
77 | + { | |
78 | + field: RestApiCallFieldsEnum.PROXY_HOST, | |
79 | + label: RestApiCallFieldsNameEnum.PROXY_HOST, | |
80 | + component: 'Input', | |
81 | + required: true, | |
82 | + colProps: { span: 8 }, | |
83 | + componentProps: { | |
84 | + placeholder: `请输入${RestApiCallFieldsNameEnum.PROXY_HOST}`, | |
85 | + }, | |
86 | + }, | |
87 | + { | |
88 | + field: RestApiCallFieldsEnum.PROXY_PORT, | |
89 | + label: RestApiCallFieldsNameEnum.PROXY_PORT, | |
90 | + component: 'InputNumber', | |
91 | + required: true, | |
92 | + colProps: { span: 8 }, | |
93 | + componentProps: { | |
94 | + placeholder: `请输入${RestApiCallFieldsNameEnum.PROXY_HOST}`, | |
95 | + }, | |
96 | + }, | |
97 | + { | |
98 | + field: RestApiCallFieldsEnum.PROXY_USER, | |
99 | + label: RestApiCallFieldsNameEnum.PROXY_USER, | |
100 | + component: 'Input', | |
101 | + componentProps: { | |
102 | + placeholder: `请输入${RestApiCallFieldsNameEnum.PROXY_USER}`, | |
103 | + }, | |
104 | + }, | |
105 | + { | |
106 | + field: RestApiCallFieldsEnum.PROXY_PASSWORD, | |
107 | + label: RestApiCallFieldsNameEnum.PROXY_PASSWORD, | |
108 | + component: 'Input', | |
109 | + componentProps: { | |
110 | + placeholder: `请输入${RestApiCallFieldsNameEnum.PROXY_PASSWORD}`, | |
111 | + }, | |
112 | + }, | |
113 | + { | |
114 | + field: RestApiCallFieldsEnum.READ_TIMEOUT_MS, | |
115 | + label: RestApiCallFieldsNameEnum.READ_TIMEOUT_MS, | |
116 | + component: 'InputNumber', | |
117 | + componentProps: { | |
118 | + min: 0, | |
119 | + placeholder: `请输入${RestApiCallFieldsNameEnum.READ_TIMEOUT_MS}`, | |
120 | + }, | |
121 | + }, | |
122 | + { | |
123 | + field: RestApiCallFieldsEnum.MAX_PARALLEL_REQUESTS_COUNT, | |
124 | + label: RestApiCallFieldsNameEnum.MAX_PARALLEL_REQUESTS_COUNT, | |
125 | + component: 'InputNumber', | |
126 | + componentProps: { | |
127 | + min: 0, | |
128 | + placeholder: `请输入${RestApiCallFieldsNameEnum.MAX_PARALLEL_REQUESTS_COUNT}`, | |
129 | + }, | |
130 | + }, | |
131 | + { | |
132 | + field: RestApiCallFieldsEnum.HEADERS, | |
133 | + label: RestApiCallFieldsNameEnum.HEADERS, | |
134 | + component: 'Input', | |
135 | + slot: RestApiCallFieldsEnum.HEADERS, | |
136 | + }, | |
137 | + { | |
138 | + field: RestApiCallFieldsEnum.USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE, | |
139 | + label: '', | |
140 | + component: 'Checkbox', | |
141 | + renderComponentContent: () => ({ | |
142 | + default: () => RestApiCallFieldsNameEnum.USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE, | |
143 | + }), | |
144 | + }, | |
145 | + { | |
146 | + field: RestApiCallFieldsEnum.TRIM_QUEUE, | |
147 | + label: '', | |
148 | + component: 'Checkbox', | |
149 | + ifShow: ({ model }) => model[RestApiCallFieldsEnum.USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE], | |
150 | + renderComponentContent: () => ({ | |
151 | + default: () => RestApiCallFieldsNameEnum.TRIM_QUEUE, | |
152 | + }), | |
153 | + }, | |
154 | + { | |
155 | + field: RestApiCallFieldsEnum.MAX_QUEUE_SIZE, | |
156 | + label: RestApiCallFieldsNameEnum.MAX_QUEUE_SIZE, | |
157 | + component: 'InputNumber', | |
158 | + ifShow: ({ model }) => model[RestApiCallFieldsEnum.USE_REDIS_QUEUE_FOR_MSG_PERSISTENCE], | |
159 | + componentProps: { | |
160 | + min: 0, | |
161 | + placeholder: `请输入${RestApiCallFieldsNameEnum.MAX_QUEUE_SIZE}`, | |
162 | + }, | |
163 | + }, | |
164 | + { | |
165 | + field: RestApiCallFieldsEnum.CREDENTIALS, | |
166 | + label: RestApiCallFieldsNameEnum.CREDENTIALS, | |
167 | + component: 'Input', | |
168 | + slot: RestApiCallFieldsEnum.CREDENTIALS, | |
9 | 169 | }, |
10 | 170 | ]; | ... | ... |
... | ... | @@ -3,11 +3,18 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { AttributeConfiguration } from '../../../src/components/AttributeConfiguration'; | |
7 | + import { ref, unref } from 'vue'; | |
8 | + import { CredentialsCard } from '../Mqtt/CredentialsCard'; | |
9 | + import { RestApiCallFieldsEnum } from '../../../enum/formField/external'; | |
6 | 10 | |
7 | 11 | defineProps<{ |
8 | 12 | config: NodeData; |
9 | 13 | }>(); |
10 | 14 | |
15 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | |
16 | + const credentialsCardElRef = ref<Nullable<InstanceType<typeof CredentialsCard>>>(); | |
17 | + | |
11 | 18 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | 19 | schemas: formSchemas, |
13 | 20 | showActionButtonGroup: false, |
... | ... | @@ -15,13 +22,25 @@ |
15 | 22 | |
16 | 23 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 24 | await validate(); |
25 | + await unref(attributeConfigurationElRef)?.validate(); | |
26 | + await unref(credentialsCardElRef)?.validate(); | |
18 | 27 | const value = getFieldsValue() || {}; |
19 | - return value; | |
28 | + | |
29 | + const headers = unref(attributeConfigurationElRef)?.getFieldsValue(); | |
30 | + const credentials = unref(credentialsCardElRef)?.getFieldsValue(); | |
31 | + | |
32 | + return { | |
33 | + ...value, | |
34 | + [RestApiCallFieldsEnum.HEADERS]: headers, | |
35 | + [RestApiCallFieldsEnum.CREDENTIALS]: credentials, | |
36 | + }; | |
20 | 37 | }; |
21 | 38 | |
22 | 39 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | 40 | resetFields(); |
24 | 41 | setFieldsValue(value); |
42 | + unref(attributeConfigurationElRef)?.setFieldsValue(value?.[RestApiCallFieldsEnum.HEADERS]); | |
43 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[RestApiCallFieldsEnum.CREDENTIALS]); | |
25 | 44 | }; |
26 | 45 | |
27 | 46 | defineExpose({ |
... | ... | @@ -31,5 +50,18 @@ |
31 | 50 | </script> |
32 | 51 | |
33 | 52 | <template> |
34 | - <BasicForm @register="register" /> | |
53 | + <BasicForm @register="register"> | |
54 | + <template #headers="{ field, model }"> | |
55 | + <AttributeConfiguration | |
56 | + ref="attributeConfigurationElRef" | |
57 | + v-model:value="model[field]" | |
58 | + :allowEmpty="true" | |
59 | + keyLabel="Header" | |
60 | + valueLabel="Value" | |
61 | + /> | |
62 | + </template> | |
63 | + <template #credentials="{ field, model }"> | |
64 | + <CredentialsCard ref="credentialsCardElRef" v-model:value="model[field]" /> | |
65 | + </template> | |
66 | + </BasicForm> | |
35 | 67 | </template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { | |
2 | + EmailProtocolEnum, | |
3 | + EmailProtocolNameEnum, | |
4 | + TSLVersionEnum, | |
5 | + TSLVersionNameEnum, | |
6 | +} from '../../../enum/form'; | |
7 | +import { SendEmailFieldsEnum, SendEmailFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 8 | import { FormSchema } from '/@/components/Form'; |
3 | 9 | |
4 | 10 | export const formSchemas: FormSchema[] = [ |
5 | 11 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
12 | + field: SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS, | |
13 | + label: '', | |
14 | + component: 'Checkbox', | |
15 | + renderComponentContent: () => ({ | |
16 | + default: () => SendEmailFieldsNameEnum.USE_SYSTEM_SMTP_SETTINGS, | |
17 | + }), | |
18 | + }, | |
19 | + { | |
20 | + field: SendEmailFieldsEnum.SMTP_PROTOCOL, | |
21 | + label: SendEmailFieldsNameEnum.SMTP_PROTOCOL, | |
22 | + component: 'Select', | |
23 | + required: true, | |
24 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
25 | + componentProps: { | |
26 | + options: Object.keys(EmailProtocolEnum).map((value) => ({ | |
27 | + label: EmailProtocolNameEnum[value], | |
28 | + value, | |
29 | + })), | |
30 | + placeholder: `请选择${SendEmailFieldsNameEnum.SMTP_PROTOCOL}`, | |
31 | + getPopupContainer: () => document.body, | |
32 | + }, | |
33 | + }, | |
34 | + { | |
35 | + field: SendEmailFieldsEnum.SMTP_HOST, | |
36 | + label: SendEmailFieldsNameEnum.SMTP_HOST, | |
7 | 37 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
38 | + required: true, | |
39 | + colProps: { span: 12 }, | |
40 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
41 | + componentProps: { | |
42 | + placeholder: `请输入${SendEmailFieldsNameEnum.SMTP_HOST}`, | |
43 | + }, | |
44 | + }, | |
45 | + { | |
46 | + field: SendEmailFieldsEnum.SMTP_PORT, | |
47 | + label: SendEmailFieldsNameEnum.SMTP_PORT, | |
48 | + component: 'InputNumber', | |
49 | + required: true, | |
50 | + colProps: { span: 12 }, | |
51 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
52 | + componentProps: { | |
53 | + min: 0, | |
54 | + placeholder: `请输入${SendEmailFieldsNameEnum.SMTP_PORT}`, | |
55 | + }, | |
56 | + }, | |
57 | + { | |
58 | + field: SendEmailFieldsEnum.TIMEOUT, | |
59 | + label: SendEmailFieldsNameEnum.TIMEOUT, | |
60 | + component: 'InputNumber', | |
61 | + required: true, | |
62 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
63 | + componentProps: { | |
64 | + min: 0, | |
65 | + placeholder: `请输入${SendEmailFieldsNameEnum.TIMEOUT}`, | |
66 | + }, | |
67 | + }, | |
68 | + { | |
69 | + field: SendEmailFieldsEnum.ENABLE_TLS, | |
70 | + label: '', | |
71 | + component: 'Checkbox', | |
72 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
73 | + renderComponentContent: () => ({ | |
74 | + default: () => SendEmailFieldsNameEnum.ENABLE_TLS, | |
75 | + }), | |
76 | + }, | |
77 | + { | |
78 | + field: SendEmailFieldsEnum.TLS_VERSION, | |
79 | + label: SendEmailFieldsNameEnum.TLS_VERSION, | |
80 | + component: 'Select', | |
81 | + required: true, | |
82 | + ifShow: ({ model }) => | |
83 | + model[SendEmailFieldsEnum.TLS_VERSION] && | |
84 | + !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
85 | + componentProps: { | |
86 | + options: Object.keys(TSLVersionEnum).map((value) => ({ | |
87 | + label: TSLVersionNameEnum[value], | |
88 | + value, | |
89 | + })), | |
90 | + placeholder: `请选择${SendEmailFieldsNameEnum.TLS_VERSION}`, | |
91 | + getPopupContainer: () => document.body, | |
92 | + }, | |
93 | + }, | |
94 | + { | |
95 | + field: SendEmailFieldsEnum.ENABLE_PROXY, | |
96 | + label: '', | |
97 | + component: 'Checkbox', | |
98 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
99 | + renderComponentContent: () => ({ | |
100 | + default: () => SendEmailFieldsNameEnum.ENABLE_PROXY, | |
101 | + }), | |
102 | + }, | |
103 | + { | |
104 | + field: SendEmailFieldsEnum.PROXY_HOST, | |
105 | + label: SendEmailFieldsNameEnum.PROXY_HOST, | |
106 | + component: 'Input', | |
107 | + required: true, | |
108 | + colProps: { span: 12 }, | |
109 | + ifShow: ({ model }) => | |
110 | + !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS] && model[SendEmailFieldsEnum.PROXY_HOST], | |
111 | + componentProps: { | |
112 | + placeholder: `请输入${SendEmailFieldsNameEnum.PROXY_HOST}`, | |
113 | + }, | |
114 | + }, | |
115 | + { | |
116 | + field: SendEmailFieldsEnum.PROXY_PORT, | |
117 | + label: SendEmailFieldsNameEnum.PROXY_PORT, | |
118 | + component: 'Input', | |
119 | + required: true, | |
120 | + colProps: { span: 12 }, | |
121 | + ifShow: ({ model }) => | |
122 | + !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS] && model[SendEmailFieldsEnum.PROXY_PORT], | |
123 | + componentProps: { | |
124 | + placeholder: `请输入${SendEmailFieldsNameEnum.PROXY_PORT}`, | |
125 | + }, | |
126 | + }, | |
127 | + { | |
128 | + field: SendEmailFieldsEnum.PROXY_USER, | |
129 | + label: SendEmailFieldsNameEnum.PROXY_USER, | |
130 | + component: 'Input', | |
131 | + ifShow: ({ model }) => | |
132 | + !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS] && model[SendEmailFieldsEnum.PROXY_USER], | |
133 | + componentProps: { | |
134 | + placeholder: `请输入${SendEmailFieldsNameEnum.PROXY_USER}`, | |
135 | + }, | |
136 | + }, | |
137 | + { | |
138 | + field: SendEmailFieldsEnum.PROXY_PASSWORD, | |
139 | + label: SendEmailFieldsNameEnum.PROXY_PASSWORD, | |
140 | + component: 'Input', | |
141 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
142 | + componentProps: { | |
143 | + placeholder: `请输入${SendEmailFieldsNameEnum.PROXY_PASSWORD}`, | |
144 | + }, | |
145 | + }, | |
146 | + { | |
147 | + field: SendEmailFieldsEnum.USERNAME, | |
148 | + label: SendEmailFieldsNameEnum.USERNAME, | |
149 | + component: 'Input', | |
150 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
151 | + componentProps: { | |
152 | + placeholder: `请输入${SendEmailFieldsNameEnum.USERNAME}`, | |
153 | + }, | |
154 | + }, | |
155 | + { | |
156 | + field: SendEmailFieldsEnum.PASSWORD, | |
157 | + label: SendEmailFieldsNameEnum.PASSWORD, | |
158 | + component: 'InputPassword', | |
159 | + ifShow: ({ model }) => !model[SendEmailFieldsEnum.USE_SYSTEM_SMTP_SETTINGS], | |
160 | + componentProps: { | |
161 | + placeholder: `请输入${SendEmailFieldsNameEnum.PASSWORD}`, | |
162 | + }, | |
9 | 163 | }, |
10 | 164 | ]; | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { SMSServiceProviderEnum, SMSServiceProviderNameEnum } from '../../../enum/form'; | |
2 | +import { SendSMSFieldsEnum, SendSMSFieldsNameEnum } from '../../../enum/formField/external'; | |
2 | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | |
4 | 5 | export const formSchemas: FormSchema[] = [ |
5 | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | + field: SendSMSFieldsEnum.NUMBERS_TO_TEMPLATE, | |
8 | + label: SendSMSFieldsNameEnum.NUMBERS_TO_TEMPLATE, | |
7 | 9 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
10 | + required: true, | |
11 | + helpMessage: | |
12 | + 'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
13 | + componentProps: { | |
14 | + placeholder: `请输入${SendSMSFieldsNameEnum.NUMBERS_TO_TEMPLATE}`, | |
15 | + }, | |
16 | + }, | |
17 | + { | |
18 | + field: SendSMSFieldsEnum.SMS_MESSAGE_TEMPLATE, | |
19 | + label: SendSMSFieldsNameEnum.SMS_MESSAGE_TEMPLATE, | |
20 | + component: 'InputTextArea', | |
21 | + required: true, | |
22 | + helpMessage: | |
23 | + 'Hint: use ${metadataKey} for value from metadata, $[messageKey] for value from message body', | |
24 | + componentProps: { | |
25 | + placeholder: `请输入${SendSMSFieldsNameEnum.SMS_MESSAGE_TEMPLATE}`, | |
26 | + }, | |
27 | + }, | |
28 | + { | |
29 | + field: SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS, | |
30 | + label: '', | |
31 | + component: 'Checkbox', | |
32 | + renderComponentContent: () => ({ | |
33 | + default: () => SendSMSFieldsNameEnum.USE_SYSTEM_SMS_SETTINGS, | |
34 | + }), | |
35 | + }, | |
36 | + { | |
37 | + field: SendSMSFieldsEnum.TYPE, | |
38 | + label: SendSMSFieldsNameEnum.TYPE, | |
39 | + component: 'Select', | |
40 | + required: true, | |
41 | + ifShow: ({ model }) => !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS], | |
42 | + componentProps: { | |
43 | + options: Object.keys(SMSServiceProviderEnum).map((value) => ({ | |
44 | + label: SMSServiceProviderNameEnum[value], | |
45 | + value, | |
46 | + })), | |
47 | + getPopupContainer: () => document.body, | |
48 | + placeholder: `请选择${SendSMSFieldsNameEnum.TYPE}`, | |
49 | + }, | |
50 | + }, | |
51 | + { | |
52 | + field: SendSMSFieldsEnum.NUMBER_FROM, | |
53 | + label: SendSMSFieldsNameEnum.NUMBER_FROM, | |
54 | + component: 'Input', | |
55 | + required: true, | |
56 | + helpMessage: `Phone Number in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX`, | |
57 | + ifShow: ({ model }) => | |
58 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
59 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.TWILIO, | |
60 | + componentProps: { | |
61 | + placeholder: `请输入${SendSMSFieldsEnum.NUMBER_FROM}`, | |
62 | + }, | |
63 | + }, | |
64 | + { | |
65 | + field: SendSMSFieldsEnum.ACCOUNT_SID, | |
66 | + label: SendSMSFieldsNameEnum.ACCOUNT_SID, | |
67 | + component: 'Input', | |
68 | + required: true, | |
69 | + ifShow: ({ model }) => | |
70 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
71 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.TWILIO, | |
72 | + componentProps: { | |
73 | + placeholder: `请选择${SendSMSFieldsNameEnum.ACCOUNT_SID}`, | |
74 | + }, | |
75 | + }, | |
76 | + { | |
77 | + field: SendSMSFieldsEnum.ACCOUNT_TOKEN, | |
78 | + label: SendSMSFieldsNameEnum.ACCOUNT_TOKEN, | |
79 | + component: 'Input', | |
80 | + required: true, | |
81 | + ifShow: ({ model }) => | |
82 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
83 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.TWILIO, | |
84 | + componentProps: { | |
85 | + placeholder: `请选择${SendSMSFieldsNameEnum.ACCOUNT_TOKEN}`, | |
86 | + }, | |
87 | + }, | |
88 | + { | |
89 | + field: SendSMSFieldsEnum.ACCESS_KEY_ID, | |
90 | + label: SendSMSFieldsNameEnum.ACCESS_KEY_ID, | |
91 | + component: 'Input', | |
92 | + required: true, | |
93 | + ifShow: ({ model }) => | |
94 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
95 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.AWS_SNS, | |
96 | + componentProps: { | |
97 | + placeholder: `请选择${SendSMSFieldsNameEnum.ACCESS_KEY_ID}`, | |
98 | + }, | |
99 | + }, | |
100 | + { | |
101 | + field: SendSMSFieldsEnum.SECRET_ACCESS_KEY, | |
102 | + label: SendSMSFieldsNameEnum.SECRET_ACCESS_KEY, | |
103 | + component: 'InputPassword', | |
104 | + required: true, | |
105 | + ifShow: ({ model }) => | |
106 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
107 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.AWS_SNS, | |
108 | + componentProps: { | |
109 | + placeholder: `请选择${SendSMSFieldsNameEnum.SECRET_ACCESS_KEY}`, | |
110 | + }, | |
111 | + }, | |
112 | + { | |
113 | + field: SendSMSFieldsEnum.REGION, | |
114 | + label: SendSMSFieldsNameEnum.REGION, | |
115 | + component: 'InputPassword', | |
116 | + required: true, | |
117 | + ifShow: ({ model }) => | |
118 | + !model[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS] && | |
119 | + model[SendSMSFieldsEnum.TYPE] === SMSServiceProviderEnum.AWS_SNS, | |
120 | + componentProps: { | |
121 | + placeholder: `请选择${SendSMSFieldsNameEnum.REGION}`, | |
122 | + }, | |
9 | 123 | }, |
10 | 124 | ]; | ... | ... |
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | 4 | import { formSchemas } from './create.config'; |
5 | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { SendSMSFieldsEnum } from '../../../enum/formField/external'; | |
6 | 7 | |
7 | 8 | defineProps<{ |
8 | 9 | config: NodeData; |
... | ... | @@ -16,7 +17,20 @@ |
16 | 17 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | 18 | await validate(); |
18 | 19 | const value = getFieldsValue() || {}; |
19 | - return value; | |
20 | + return { | |
21 | + [SendSMSFieldsEnum.NUMBERS_TO_TEMPLATE]: value[SendSMSFieldsEnum.NUMBERS_TO_TEMPLATE], | |
22 | + [SendSMSFieldsEnum.SMS_MESSAGE_TEMPLATE]: value[SendSMSFieldsEnum.SMS_MESSAGE_TEMPLATE], | |
23 | + [SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS]: value[SendSMSFieldsEnum.USE_SYSTEM_SMS_SETTINGS], | |
24 | + [SendSMSFieldsEnum.SMS_PROVIDER_CONFIGURATION]: { | |
25 | + [SendSMSFieldsEnum.ACCESS_KEY_ID]: value[SendSMSFieldsEnum.ACCESS_KEY_ID], | |
26 | + [SendSMSFieldsEnum.REGION]: value[SendSMSFieldsEnum.REGION], | |
27 | + [SendSMSFieldsEnum.SECRET_ACCESS_KEY]: value[SendSMSFieldsEnum.SECRET_ACCESS_KEY], | |
28 | + [SendSMSFieldsEnum.TYPE]: value[SendSMSFieldsEnum.TYPE], | |
29 | + [SendSMSFieldsEnum.ACCOUNT_SID]: value[SendSMSFieldsEnum.ACCOUNT_SID], | |
30 | + [SendSMSFieldsEnum.ACCOUNT_TOKEN]: value[SendSMSFieldsEnum.ACCOUNT_TOKEN], | |
31 | + [SendSMSFieldsEnum.NUMBER_FROM]: value[SendSMSFieldsEnum.NUMBER_FROM], | |
32 | + }, | |
33 | + }; | |
20 | 34 | }; |
21 | 35 | |
22 | 36 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | 1 | import { FormSchema } from '/@/components/Form'; |
3 | 2 | |
4 | -export const formSchemas: FormSchema[] = [ | |
5 | - { | |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | - component: 'Input', | |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
9 | - }, | |
10 | -]; | |
3 | +export const formSchemas: FormSchema[] = []; | ... | ... |
1 | +<script setup lang="ts"> | |
2 | + import { AutoComplete } from 'ant-design-vue'; | |
3 | + import get from 'lodash-es/get'; | |
4 | + import omit from 'lodash-es/omit'; | |
5 | + import { computed, ref, unref, watch, watchEffect } from 'vue'; | |
6 | + import { isFunction } from '/@/utils/is'; | |
7 | + type OptionsItem = { text: string; value: string }; | |
8 | + | |
9 | + const props = withDefaults( | |
10 | + defineProps<{ | |
11 | + value?: string; | |
12 | + api?: (arg?: Recordable) => Promise<OptionsItem[]>; | |
13 | + onSearchQuery?: boolean; | |
14 | + params?: Recordable; | |
15 | + resultField?: string; | |
16 | + valueField?: string; | |
17 | + labelField?: string; | |
18 | + immediate?: boolean; | |
19 | + }>(), | |
20 | + { | |
21 | + valueField: 'value', | |
22 | + labelField: 'label', | |
23 | + immediate: true, | |
24 | + } | |
25 | + ); | |
26 | + | |
27 | + const emit = defineEmits(['update:value', 'options-change']); | |
28 | + | |
29 | + const loading = ref(false); | |
30 | + | |
31 | + const isFirstLoad = ref(true); | |
32 | + | |
33 | + const options = ref<OptionsItem[]>([]); | |
34 | + | |
35 | + const getOptions = computed(() => { | |
36 | + const { labelField, valueField } = props; | |
37 | + | |
38 | + return unref(options).reduce((prev, next: Recordable) => { | |
39 | + if (next) { | |
40 | + const value = next[valueField]; | |
41 | + prev.push({ | |
42 | + ...omit(next, [labelField, valueField]), | |
43 | + text: next[labelField], | |
44 | + value, | |
45 | + }); | |
46 | + } | |
47 | + return prev; | |
48 | + }, [] as OptionsItem[]); | |
49 | + }); | |
50 | + | |
51 | + const fetch = async () => { | |
52 | + const api = props.api; | |
53 | + if (!api || !isFunction(api)) return; | |
54 | + options.value = []; | |
55 | + try { | |
56 | + loading.value = true; | |
57 | + const res = await api(props.params); | |
58 | + if (Array.isArray(res)) { | |
59 | + options.value = res; | |
60 | + emitChange(); | |
61 | + return; | |
62 | + } | |
63 | + if (props.resultField) { | |
64 | + options.value = get(res, props.resultField) || []; | |
65 | + } | |
66 | + emitChange(); | |
67 | + } catch (error) { | |
68 | + console.warn(error); | |
69 | + } finally { | |
70 | + loading.value = false; | |
71 | + } | |
72 | + }; | |
73 | + | |
74 | + function emitChange() { | |
75 | + emit('options-change', unref(getOptions)); | |
76 | + } | |
77 | + | |
78 | + const handleChange = (value: any) => { | |
79 | + emit('update:value', value); | |
80 | + }; | |
81 | + | |
82 | + watchEffect(() => { | |
83 | + props.immediate && fetch(); | |
84 | + }); | |
85 | + | |
86 | + watch( | |
87 | + () => props.params, | |
88 | + () => { | |
89 | + !unref(isFirstLoad) && fetch(); | |
90 | + }, | |
91 | + { deep: true } | |
92 | + ); | |
93 | +</script> | |
94 | + | |
95 | +<template> | |
96 | + <AutoComplete :value="value" @change="handleChange" :options="getOptions" /> | |
97 | +</template> | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
2 | -import { FormSchema } from '/@/components/Form'; | |
1 | +import { CheckPointFieldsEnum, CheckPointFieldsNameEnum } from '../../../enum/formField/flow'; | |
2 | +import { FormSchema, useComponentRegister } from '/@/components/Form'; | |
3 | +import ApiComplete from './ApiComplete.vue'; | |
4 | +import { getTenantQueue } from '/@/api/ruleChainDesigner'; | |
5 | + | |
6 | +useComponentRegister('ApiComplete', ApiComplete); | |
3 | 7 | |
4 | 8 | export const formSchemas: FormSchema[] = [ |
5 | 9 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | - component: 'Input', | |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
10 | + field: CheckPointFieldsEnum.QUEUE_NAME, | |
11 | + label: CheckPointFieldsNameEnum.QUEUE_NAME, | |
12 | + component: 'ApiComplete', | |
13 | + required: true, | |
14 | + helpMessage: ['从下拉列表中选择或自定义名称'], | |
15 | + valueField: 'value', | |
16 | + changeEvent: 'update:value', | |
17 | + componentProps: () => { | |
18 | + return { | |
19 | + placeholder: `请选择${CheckPointFieldsNameEnum.QUEUE_NAME}`, | |
20 | + getPopupContainer: () => document.body, | |
21 | + api: async (params: Recordable) => { | |
22 | + const options = await getTenantQueue(params); | |
23 | + return options.map((value) => ({ label: value, value })); | |
24 | + }, | |
25 | + params: { serviceType: 'TB_RULE_ENGINE' }, | |
26 | + }; | |
27 | + }, | |
9 | 28 | }, |
10 | 29 | ]; | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { h } from 'vue'; | |
2 | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | |
4 | 4 | export const formSchemas: FormSchema[] = [ |
5 | 5 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
6 | + field: 'desc', | |
7 | + label: '', | |
7 | 8 | component: 'Input', |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
9 | + renderColContent: () => | |
10 | + h( | |
11 | + 'div', | |
12 | + 'The rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.' | |
13 | + ), | |
9 | 14 | }, |
10 | 15 | ]; | ... | ... |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | |
1 | +import { RuleChainFieldsEnum, RuleChainFieldsNameEnum } from '../../../enum/formField/flow'; | |
2 | +import { getRuleChains } from '/@/api/ruleDesigner'; | |
2 | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | |
4 | 5 | export const formSchemas: FormSchema[] = [ |
5 | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | |
7 | - component: 'Input', | |
8 | - label: NodeBindDataFieldNameEnum.NAME, | |
7 | + field: RuleChainFieldsEnum.RULE_CHAIN_ID, | |
8 | + label: RuleChainFieldsNameEnum.RULE_CHAIN_ID, | |
9 | + component: 'ApiSearchSelect', | |
10 | + componentProps: () => { | |
11 | + return { | |
12 | + placeholder: '请选择所属产品', | |
13 | + showSearch: true, | |
14 | + resultField: 'data', | |
15 | + labelField: 'name', | |
16 | + valueField: 'id.id', | |
17 | + params: { | |
18 | + pageSize: 50, | |
19 | + page: 0, | |
20 | + type: 'CORE', | |
21 | + }, | |
22 | + api: getRuleChains, | |
23 | + searchApi: getRuleChains, | |
24 | + getPopupContainer: () => document.body, | |
25 | + }; | |
26 | + }, | |
9 | 27 | }, |
10 | 28 | ]; | ... | ... |
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | valueLabel?: string; |
29 | 29 | keyComponent?: ComponentType; |
30 | 30 | valueComponent?: ComponentType; |
31 | + allowEmpty?: boolean; | |
31 | 32 | }>(), |
32 | 33 | { |
33 | 34 | keyComponent: 'Input', |
... | ... | @@ -132,7 +133,7 @@ |
132 | 133 | |
133 | 134 | list.value = valueList; |
134 | 135 | |
135 | - if (!list.value.length) list.value = [{ uuid: buildShortUUID() }]; | |
136 | + if (!list.value.length && !props.allowEmpty) list.value = [{ uuid: buildShortUUID() }]; | |
136 | 137 | }; |
137 | 138 | |
138 | 139 | watch( | ... | ... |
... | ... | @@ -68,7 +68,7 @@ |
68 | 68 | <div> |
69 | 69 | <Icon class="text-2xl dark:text-light-50" :icon="getIcon" /> |
70 | 70 | </div> |
71 | - <BasicToolbar v-bind="$props" /> | |
71 | + <BasicToolbar v-if="!getData.config?.disableAction" v-bind="$props" /> | |
72 | 72 | <div class="flex text-xs flex-col ml-2 text-left truncate"> |
73 | 73 | <span class="text-gray-700 w-full truncate dark:text-light-50">{{ getLabel }}</span> |
74 | 74 | <span class="w-full truncate dark:text-neutral-50">{{ getName }}</span> | ... | ... |
... | ... | @@ -97,7 +97,7 @@ |
97 | 97 | <Tabs> |
98 | 98 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.DETAIL]" :key="TabsPanelEnum.DETAIL"> |
99 | 99 | <Spin :spinning="spinning"> |
100 | - <section v-if="shadowComponent" class="w-full h-full overflow-y-auto"> | |
100 | + <section v-if="shadowComponent" class="w-full h-full overflow-y-auto pr-4"> | |
101 | 101 | <BasicForm @register="topFormRegister" @vue:mounted="handleTopFormMounted" /> |
102 | 102 | <component |
103 | 103 | class="rule-node-form" |
... | ... | @@ -152,7 +152,12 @@ |
152 | 152 | @apply h-full flex flex-col; |
153 | 153 | |
154 | 154 | .ant-tabs-content { |
155 | - @apply flex-auto overflow-x-hidden overflow-y-auto pr-4; | |
155 | + height: calc(100% - 61px); | |
156 | + } | |
157 | + | |
158 | + .ant-spin-nested-loading, | |
159 | + .ant-spin-container { | |
160 | + @apply h-full; | |
156 | 161 | } |
157 | 162 | } |
158 | 163 | } | ... | ... |
... | ... | @@ -55,6 +55,11 @@ export interface NodeItemConfigType { |
55 | 55 | * @description 配置描述 |
56 | 56 | */ |
57 | 57 | configurationDescriptor: ConfigurationDescriptor; |
58 | + | |
59 | + /** | |
60 | + * @description 禁用所有动作 | |
61 | + */ | |
62 | + disableAction?: boolean; | |
58 | 63 | } |
59 | 64 | |
60 | 65 | export interface CategoryConfigType { | ... | ... |