Showing
48 changed files
with
2495 additions
and
91 deletions
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | "public/resource/tinymce/langs" | 5 | "public/resource/tinymce/langs" |
6 | ], | 6 | ], |
7 | "cSpell.words": [ | 7 | "cSpell.words": [ |
8 | + "ACKS", | ||
8 | "clazz", | 9 | "clazz", |
9 | "Cmds", | 10 | "Cmds", |
10 | "COAP", | 11 | "COAP", |
@@ -19,9 +20,12 @@ | @@ -19,9 +20,12 @@ | ||
19 | "noconflict", | 20 | "noconflict", |
20 | "notif", | 21 | "notif", |
21 | "PROTOBUF", | 22 | "PROTOBUF", |
23 | + "Rabbitmq", | ||
22 | "rtsp", | 24 | "rtsp", |
23 | "SCADA", | 25 | "SCADA", |
26 | + "SMTPS", | ||
24 | "SNMP", | 27 | "SNMP", |
28 | + "TSLV", | ||
25 | "UNACK", | 29 | "UNACK", |
26 | "unref", | 30 | "unref", |
27 | "vben", | 31 | "vben", |
@@ -5,6 +5,7 @@ import { defHttp } from '/@/utils/http/axios'; | @@ -5,6 +5,7 @@ import { defHttp } from '/@/utils/http/axios'; | ||
5 | enum Api { | 5 | enum Api { |
6 | GET_DEVICE_INFOS = '/tenant/deviceInfos', | 6 | GET_DEVICE_INFOS = '/tenant/deviceInfos', |
7 | GET_DEVICE_TYPE = '/device/types', | 7 | GET_DEVICE_TYPE = '/device/types', |
8 | + TENANT_QUEUE = '/tenant/queues', | ||
8 | } | 9 | } |
9 | 10 | ||
10 | export const getDeviceInfos = () => { | 11 | export const getDeviceInfos = () => { |
@@ -24,3 +25,13 @@ export const getDeviceTypes = () => { | @@ -24,3 +25,13 @@ export const getDeviceTypes = () => { | ||
24 | { joinPrefix: false } | 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,6 +3,7 @@ import { RuleChainType } from '/@/views/rule/designer/types/ruleNode'; | ||
3 | 3 | ||
4 | enum Api { | 4 | enum Api { |
5 | SAVE = '/ruleChain/metadata', | 5 | SAVE = '/ruleChain/metadata', |
6 | + GET_RULE_CHAINES = '/ruleChains', | ||
6 | } | 7 | } |
7 | 8 | ||
8 | export const getRuleChainData = (id: string) => { | 9 | export const getRuleChainData = (id: string) => { |
@@ -23,3 +24,15 @@ export const saveRuleChainData = (data: RuleChainType) => { | @@ -23,3 +24,15 @@ export const saveRuleChainData = (data: RuleChainType) => { | ||
23 | { joinPrefix: false } | 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,6 +14,7 @@ | ||
14 | import { get, omit } from 'lodash-es'; | 14 | import { get, omit } from 'lodash-es'; |
15 | import { LoadingOutlined } from '@ant-design/icons-vue'; | 15 | import { LoadingOutlined } from '@ant-design/icons-vue'; |
16 | import { useI18n } from '/@/hooks/web/useI18n'; | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
17 | + import { useDebounceFn } from '@vueuse/shared'; | ||
17 | 18 | ||
18 | const emit = defineEmits(['options-change', 'change']); | 19 | const emit = defineEmits(['options-change', 'change']); |
19 | const props = withDefaults( | 20 | const props = withDefaults( |
@@ -53,7 +54,7 @@ | @@ -53,7 +54,7 @@ | ||
53 | const { labelField, valueField = 'value', numberToString } = props; | 54 | const { labelField, valueField = 'value', numberToString } = props; |
54 | return unref(options).reduce((prev, next: Recordable) => { | 55 | return unref(options).reduce((prev, next: Recordable) => { |
55 | if (next) { | 56 | if (next) { |
56 | - const value = next[valueField]; | 57 | + const value = get(next, valueField); |
57 | prev.push({ | 58 | prev.push({ |
58 | label: next[labelField], | 59 | label: next[labelField], |
59 | value: numberToString ? `${value}` : value, | 60 | value: numberToString ? `${value}` : value, |
@@ -122,6 +123,7 @@ | @@ -122,6 +123,7 @@ | ||
122 | onChangeHook({ options }); | 123 | onChangeHook({ options }); |
123 | } | 124 | } |
124 | 125 | ||
126 | + const debounceSearchFunction = useDebounceFn(handleSearch, 300); | ||
125 | async function handleSearch(params?: string) { | 127 | async function handleSearch(params?: string) { |
126 | let { searchApi, api } = props; | 128 | let { searchApi, api } = props; |
127 | if (!searchApi || !isFunction(searchApi)) { | 129 | if (!searchApi || !isFunction(searchApi)) { |
@@ -156,7 +158,7 @@ | @@ -156,7 +158,7 @@ | ||
156 | show-search | 158 | show-search |
157 | @change="handleChange" | 159 | @change="handleChange" |
158 | :options="getOptions" | 160 | :options="getOptions" |
159 | - @search="handleSearch" | 161 | + @search="debounceSearchFunction" |
160 | v-model:value="state" | 162 | v-model:value="state" |
161 | > | 163 | > |
162 | <template #[item]="data" v-for="item in Object.keys($slots)"> | 164 | <template #[item]="data" v-for="item in Object.keys($slots)"> |
@@ -40,16 +40,19 @@ | @@ -40,16 +40,19 @@ | ||
40 | accept?: string; | 40 | accept?: string; |
41 | maxSize?: number; | 41 | maxSize?: number; |
42 | disabled?: boolean; | 42 | disabled?: boolean; |
43 | - listType?: string; | 43 | + listType?: 'text' | 'picture-card' | 'picture'; |
44 | multiple?: boolean; | 44 | multiple?: boolean; |
45 | maxFileLimit?: number; | 45 | maxFileLimit?: number; |
46 | - showUploadList?: boolean | { showPreviewIcon?: boolean; showRemoveIcon?: boolean }; | 46 | + showUploadList?: InstanceType<typeof Upload>['$props']['showUploadList']; |
47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; | 47 | transformFile?: (file: File) => string | Blob | Promise<string | Blob | File>; |
48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; | 48 | api: (file: string | Blob | Promise<string | Blob | File>) => Promise<FileItem>; |
49 | + overFileLimitHiddenUploadEntry?: boolean; | ||
49 | }>(), | 50 | }>(), |
50 | { | 51 | { |
51 | fileList: () => [], | 52 | fileList: () => [], |
52 | maxSize: 5 * 1024 * 1024, | 53 | maxSize: 5 * 1024 * 1024, |
54 | + overFileLimitHiddenUploadEntry: true, | ||
55 | + listType: 'text', | ||
53 | showUploadList: () => ({ showPreviewIcon: true, showRemoveIcon: true }), | 56 | showUploadList: () => ({ showPreviewIcon: true, showRemoveIcon: true }), |
54 | } | 57 | } |
55 | ); | 58 | ); |
@@ -75,7 +78,7 @@ | @@ -75,7 +78,7 @@ | ||
75 | 78 | ||
76 | const getMaxFileLimit = computed(() => { | 79 | const getMaxFileLimit = computed(() => { |
77 | const { maxFileLimit } = props; | 80 | const { maxFileLimit } = props; |
78 | - return isPictureCard.value ? 1 : maxFileLimit; | 81 | + return isPictureCard.value ? 1 : maxFileLimit || 1; |
79 | }); | 82 | }); |
80 | 83 | ||
81 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { | 84 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { |
@@ -131,11 +134,15 @@ | @@ -131,11 +134,15 @@ | ||
131 | :list-type="props.listType" | 134 | :list-type="props.listType" |
132 | :disabled="getDisabled" | 135 | :disabled="getDisabled" |
133 | :before-upload="handleBeforeUpload" | 136 | :before-upload="handleBeforeUpload" |
137 | + :show-upload-list="showUploadList" | ||
134 | @preview="handlePreview" | 138 | @preview="handlePreview" |
135 | @download="handleDownload" | 139 | @download="handleDownload" |
136 | :remove="handleRemove" | 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 | <div class="w-full h-full flex flex-col justify-center content-center"> | 146 | <div class="w-full h-full flex flex-col justify-center content-center"> |
140 | <Tooltip title="点击上传或拖拽上传"> | 147 | <Tooltip title="点击上传或拖拽上传"> |
141 | <InboxOutlined class="text-[3rem] !text-blue-500" /> | 148 | <InboxOutlined class="text-[3rem] !text-blue-500" /> |
@@ -135,4 +135,6 @@ export type ComponentType = | @@ -135,4 +135,6 @@ export type ComponentType = | ||
135 | | 'JavascriptEditorWithTestModal' | 135 | | 'JavascriptEditorWithTestModal' |
136 | | 'AttributeConfiguration' | 136 | | 'AttributeConfiguration' |
137 | | 'CorrelationFilters' | 137 | | 'CorrelationFilters' |
138 | - | 'RelationsQuery'; | 138 | + | 'RelationsQuery' |
139 | + | 'CredentialsCard' | ||
140 | + | 'ApiComplete'; |
@@ -241,3 +241,95 @@ export enum ScopeNameEnum { | @@ -241,3 +241,95 @@ export enum ScopeNameEnum { | ||
241 | CLIENT_SCOPE = '客户端属性', | 241 | CLIENT_SCOPE = '客户端属性', |
242 | SHARED_SCOPE = '共享属性', | 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,6 +9,7 @@ export const InputConfig: NodeItemConfigType = { | ||
9 | ...keys, | 9 | ...keys, |
10 | categoryType: RuleNodeTypeEnum.ENTRY, | 10 | categoryType: RuleNodeTypeEnum.ENTRY, |
11 | clazz: EntryCategoryComponentEnum.INPUT, | 11 | clazz: EntryCategoryComponentEnum.INPUT, |
12 | + disableAction: true, | ||
12 | maxConnectionPoint: 1, | 13 | maxConnectionPoint: 1, |
13 | backgroundColor: '#95E898', | 14 | backgroundColor: '#95E898', |
14 | configurationDescriptor: { | 15 | configurationDescriptor: { |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | 1 | +import { AlarmNoticeFieldsEnum, AlarmNoticeFieldsNameEnum } from '../../../enum/formField/external'; |
2 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | ||
4 | export const formSchemas: FormSchema[] = [ | 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,6 +3,8 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
7 | + import { AlarmNoticeFieldsEnum } from '../../../enum/formField/external'; | ||
6 | 8 | ||
7 | defineProps<{ | 9 | defineProps<{ |
8 | config: NodeData; | 10 | config: NodeData; |
@@ -16,12 +18,12 @@ | @@ -16,12 +18,12 @@ | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 18 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 19 | await validate(); |
18 | const value = getFieldsValue() || {}; | 20 | const value = getFieldsValue() || {}; |
19 | - return value; | 21 | + return useJsonParse(value?.[AlarmNoticeFieldsEnum.CONFIGURATION]).value || {}; |
20 | }; | 22 | }; |
21 | 23 | ||
22 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 24 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 25 | resetFields(); |
24 | - setFieldsValue(value); | 26 | + setFieldsValue({ [AlarmNoticeFieldsEnum.CONFIGURATION]: JSON.stringify(value, null, 2) }); |
25 | }; | 27 | }; |
26 | 28 | ||
27 | defineExpose({ | 29 | defineExpose({ |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | 1 | +import { AwsSnsFieldsEnum, AwsSnsFieldsNameEnum } from '../../../enum/formField/external'; |
2 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | ||
4 | export const formSchemas: FormSchema[] = [ | 4 | export const formSchemas: FormSchema[] = [ |
5 | { | 5 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | 6 | + field: AwsSnsFieldsEnum.TOPIC_ARN_PATTERN, |
7 | + label: AwsSnsFieldsNameEnum.TOPIC_ARN_PATTERN, | ||
7 | component: 'Input', | 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 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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,11 +3,16 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 10 | defineProps<{ |
8 | config: NodeData; | 11 | config: NodeData; |
9 | }>(); | 12 | }>(); |
10 | 13 | ||
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | ||
15 | + | ||
11 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 17 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 18 | showActionButtonGroup: false, |
@@ -15,13 +20,18 @@ | @@ -15,13 +20,18 @@ | ||
15 | 20 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 29 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 30 | resetFields(); |
24 | setFieldsValue(value); | 31 | setFieldsValue(value); |
32 | + unref(attributeConfigurationElRef)?.setFieldsValue( | ||
33 | + value?.[AwsSqsFieldsEnum.MESSAGE_ATTRIBUTES] | ||
34 | + ); | ||
25 | }; | 35 | }; |
26 | 36 | ||
27 | defineExpose({ | 37 | defineExpose({ |
@@ -31,5 +41,15 @@ | @@ -31,5 +41,15 @@ | ||
31 | </script> | 41 | </script> |
32 | 42 | ||
33 | <template> | 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 | </template> | 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 | export const formSchemas: FormSchema[] = [ | 7 | export const formSchemas: FormSchema[] = [ |
5 | { | 8 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | 9 | + field: AzureIotHubFieldsEnum.TOPIC_PATTERN, |
10 | + label: AzureIotHubFieldsNameEnum.TOPIC_PATTERN, | ||
7 | component: 'Input', | 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,11 +3,16 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 10 | defineProps<{ |
8 | config: NodeData; | 11 | config: NodeData; |
9 | }>(); | 12 | }>(); |
10 | 13 | ||
14 | + const credentialsCardElRef = ref<Nullable<InstanceType<typeof CredentialsCard>>>(); | ||
15 | + | ||
11 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 17 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 18 | showActionButtonGroup: false, |
@@ -15,13 +20,23 @@ | @@ -15,13 +20,23 @@ | ||
15 | 20 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 22 | await validate(); |
23 | + await unref(credentialsCardElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 36 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 37 | resetFields(); |
24 | setFieldsValue(value); | 38 | setFieldsValue(value); |
39 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[AzureIotHubFieldsEnum.CREDENTIALS]); | ||
25 | }; | 40 | }; |
26 | 41 | ||
27 | defineExpose({ | 42 | defineExpose({ |
@@ -31,5 +46,9 @@ | @@ -31,5 +46,9 @@ | ||
31 | </script> | 46 | </script> |
32 | 47 | ||
33 | <template> | 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 | </template> | 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 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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,6 +3,12 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 13 | defineProps<{ |
8 | config: NodeData; | 14 | config: NodeData; |
@@ -15,13 +21,36 @@ | @@ -15,13 +21,36 @@ | ||
15 | 21 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 22 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 23 | await validate(); |
24 | + await unref(attributeConfigurationElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 35 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 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 | defineExpose({ | 56 | defineExpose({ |
@@ -31,5 +60,15 @@ | @@ -31,5 +60,15 @@ | ||
31 | </script> | 60 | </script> |
32 | 61 | ||
33 | <template> | 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 | </template> | 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 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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,11 +3,16 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 10 | defineProps<{ |
8 | config: NodeData; | 11 | config: NodeData; |
9 | }>(); | 12 | }>(); |
10 | 13 | ||
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | ||
15 | + | ||
11 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 17 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 18 | showActionButtonGroup: false, |
@@ -15,13 +20,19 @@ | @@ -15,13 +20,19 @@ | ||
15 | 20 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 33 | resetFields(); |
24 | setFieldsValue(value); | 34 | setFieldsValue(value); |
35 | + unref(attributeConfigurationElRef)?.setFieldsValue(value?.[KafkaFieldsEnum.OTHER_PROPERTIES]); | ||
25 | }; | 36 | }; |
26 | 37 | ||
27 | defineExpose({ | 38 | defineExpose({ |
@@ -31,5 +42,15 @@ | @@ -31,5 +42,15 @@ | ||
31 | </script> | 42 | </script> |
32 | 43 | ||
33 | <template> | 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 | </template> | 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 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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,11 +3,16 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 10 | defineProps<{ |
8 | config: NodeData; | 11 | config: NodeData; |
9 | }>(); | 12 | }>(); |
10 | 13 | ||
14 | + const credentialsCardElRef = ref<Nullable<InstanceType<typeof CredentialsCard>>>(); | ||
15 | + | ||
11 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 17 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 18 | showActionButtonGroup: false, |
@@ -15,13 +20,19 @@ | @@ -15,13 +20,19 @@ | ||
15 | 20 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 22 | await validate(); |
23 | + await unref(credentialsCardElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 33 | resetFields(); |
24 | setFieldsValue(value); | 34 | setFieldsValue(value); |
35 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[MqttFieldsEnum.CREDENTIALS]); | ||
25 | }; | 36 | }; |
26 | 37 | ||
27 | defineExpose({ | 38 | defineExpose({ |
@@ -31,5 +42,9 @@ | @@ -31,5 +42,9 @@ | ||
31 | </script> | 42 | </script> |
32 | 43 | ||
33 | <template> | 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 | </template> | 50 | </template> |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | 1 | +import { MessagePropertiesEnum } from '../../../enum/form'; |
2 | +import { RabbitmqFieldsEnum, RabbitmqFieldsNameEnum } from '../../../enum/formField/external'; | ||
2 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | ||
4 | export const formSchemas: FormSchema[] = [ | 5 | export const formSchemas: FormSchema[] = [ |
5 | { | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | 7 | + field: RabbitmqFieldsEnum.EXCHANGE_NAME_PATTERN, |
8 | + label: RabbitmqFieldsNameEnum.EXCHANGE_NAME_PATTERN, | ||
7 | component: 'Input', | 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,11 +3,16 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 10 | defineProps<{ |
8 | config: NodeData; | 11 | config: NodeData; |
9 | }>(); | 12 | }>(); |
10 | 13 | ||
14 | + const attributeConfigurationElRef = ref<Nullable<InstanceType<typeof AttributeConfiguration>>>(); | ||
15 | + | ||
11 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 16 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 17 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 18 | showActionButtonGroup: false, |
@@ -15,13 +20,21 @@ | @@ -15,13 +20,21 @@ | ||
15 | 20 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 21 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 22 | await validate(); |
23 | + await unref(attributeConfigurationElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 32 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 33 | resetFields(); |
24 | setFieldsValue(value); | 34 | setFieldsValue(value); |
35 | + unref(attributeConfigurationElRef)?.setFieldsValue( | ||
36 | + value?.[RabbitmqFieldsEnum.CLIENT_PROPERTIES] | ||
37 | + ); | ||
25 | }; | 38 | }; |
26 | 39 | ||
27 | defineExpose({ | 40 | defineExpose({ |
@@ -31,5 +44,15 @@ | @@ -31,5 +44,15 @@ | ||
31 | </script> | 44 | </script> |
32 | 45 | ||
33 | <template> | 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 | </template> | 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 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | ||
4 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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,11 +3,18 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 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 | defineProps<{ | 11 | defineProps<{ |
8 | config: NodeData; | 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 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 18 | const [register, { validate, getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
12 | schemas: formSchemas, | 19 | schemas: formSchemas, |
13 | showActionButtonGroup: false, | 20 | showActionButtonGroup: false, |
@@ -15,13 +22,25 @@ | @@ -15,13 +22,25 @@ | ||
15 | 22 | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 23 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 24 | await validate(); |
25 | + await unref(attributeConfigurationElRef)?.validate(); | ||
26 | + await unref(credentialsCardElRef)?.validate(); | ||
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 39 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
23 | resetFields(); | 40 | resetFields(); |
24 | setFieldsValue(value); | 41 | setFieldsValue(value); |
42 | + unref(attributeConfigurationElRef)?.setFieldsValue(value?.[RestApiCallFieldsEnum.HEADERS]); | ||
43 | + unref(credentialsCardElRef)?.setFieldsValue(value?.[RestApiCallFieldsEnum.CREDENTIALS]); | ||
25 | }; | 44 | }; |
26 | 45 | ||
27 | defineExpose({ | 46 | defineExpose({ |
@@ -31,5 +50,18 @@ | @@ -31,5 +50,18 @@ | ||
31 | </script> | 50 | </script> |
32 | 51 | ||
33 | <template> | 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 | </template> | 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 | import { FormSchema } from '/@/components/Form'; | 8 | import { FormSchema } from '/@/components/Form'; |
3 | 9 | ||
4 | export const formSchemas: FormSchema[] = [ | 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 | component: 'Input', | 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 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | ||
4 | export const formSchemas: FormSchema[] = [ | 5 | export const formSchemas: FormSchema[] = [ |
5 | { | 6 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | 7 | + field: SendSMSFieldsEnum.NUMBERS_TO_TEMPLATE, |
8 | + label: SendSMSFieldsNameEnum.NUMBERS_TO_TEMPLATE, | ||
7 | component: 'Input', | 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,6 +3,7 @@ | ||
3 | import { BasicForm, useForm } from '/@/components/Form'; | 3 | import { BasicForm, useForm } from '/@/components/Form'; |
4 | import { formSchemas } from './create.config'; | 4 | import { formSchemas } from './create.config'; |
5 | import { NodeData } from '../../../types/node'; | 5 | import { NodeData } from '../../../types/node'; |
6 | + import { SendSMSFieldsEnum } from '../../../enum/formField/external'; | ||
6 | 7 | ||
7 | defineProps<{ | 8 | defineProps<{ |
8 | config: NodeData; | 9 | config: NodeData; |
@@ -16,7 +17,20 @@ | @@ -16,7 +17,20 @@ | ||
16 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { | 17 | const getValue: CreateModalDefineExposeType['getFieldsValue'] = async () => { |
17 | await validate(); | 18 | await validate(); |
18 | const value = getFieldsValue() || {}; | 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 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { | 36 | const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { |
1 | -import { NodeBindDataFieldEnum, NodeBindDataFieldNameEnum } from '../../../enum/node'; | ||
2 | import { FormSchema } from '/@/components/Form'; | 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 | export const formSchemas: FormSchema[] = [ | 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 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
3 | 3 | ||
4 | export const formSchemas: FormSchema[] = [ | 4 | export const formSchemas: FormSchema[] = [ |
5 | { | 5 | { |
6 | - field: NodeBindDataFieldEnum.NAME, | 6 | + field: 'desc', |
7 | + label: '', | ||
7 | component: 'Input', | 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 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
3 | 4 | ||
4 | export const formSchemas: FormSchema[] = [ | 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,6 +28,7 @@ | ||
28 | valueLabel?: string; | 28 | valueLabel?: string; |
29 | keyComponent?: ComponentType; | 29 | keyComponent?: ComponentType; |
30 | valueComponent?: ComponentType; | 30 | valueComponent?: ComponentType; |
31 | + allowEmpty?: boolean; | ||
31 | }>(), | 32 | }>(), |
32 | { | 33 | { |
33 | keyComponent: 'Input', | 34 | keyComponent: 'Input', |
@@ -132,7 +133,7 @@ | @@ -132,7 +133,7 @@ | ||
132 | 133 | ||
133 | list.value = valueList; | 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 | watch( | 139 | watch( |
@@ -37,8 +37,6 @@ | @@ -37,8 +37,6 @@ | ||
37 | const currentEdge = flowActionType.findEdge(props.id); | 37 | const currentEdge = flowActionType.findEdge(props.id); |
38 | 38 | ||
39 | (currentEdge!.data as EdgeData).data = data; | 39 | (currentEdge!.data as EdgeData).data = data; |
40 | - | ||
41 | - console.log(props); | ||
42 | }; | 40 | }; |
43 | 41 | ||
44 | const handleDelete = () => { | 42 | const handleDelete = () => { |
@@ -68,7 +68,7 @@ | @@ -68,7 +68,7 @@ | ||
68 | <div> | 68 | <div> |
69 | <Icon class="text-2xl dark:text-light-50" :icon="getIcon" /> | 69 | <Icon class="text-2xl dark:text-light-50" :icon="getIcon" /> |
70 | </div> | 70 | </div> |
71 | - <BasicToolbar v-bind="$props" /> | 71 | + <BasicToolbar v-if="!getData.config?.disableAction" v-bind="$props" /> |
72 | <div class="flex text-xs flex-col ml-2 text-left truncate"> | 72 | <div class="flex text-xs flex-col ml-2 text-left truncate"> |
73 | <span class="text-gray-700 w-full truncate dark:text-light-50">{{ getLabel }}</span> | 73 | <span class="text-gray-700 w-full truncate dark:text-light-50">{{ getLabel }}</span> |
74 | <span class="w-full truncate dark:text-neutral-50">{{ getName }}</span> | 74 | <span class="w-full truncate dark:text-neutral-50">{{ getName }}</span> |
@@ -97,7 +97,7 @@ | @@ -97,7 +97,7 @@ | ||
97 | <Tabs> | 97 | <Tabs> |
98 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.DETAIL]" :key="TabsPanelEnum.DETAIL"> | 98 | <Tabs.TabPane :tab="TabsPanelNameEnum[TabsPanelEnum.DETAIL]" :key="TabsPanelEnum.DETAIL"> |
99 | <Spin :spinning="spinning"> | 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 | <BasicForm @register="topFormRegister" @vue:mounted="handleTopFormMounted" /> | 101 | <BasicForm @register="topFormRegister" @vue:mounted="handleTopFormMounted" /> |
102 | <component | 102 | <component |
103 | class="rule-node-form" | 103 | class="rule-node-form" |
@@ -152,7 +152,12 @@ | @@ -152,7 +152,12 @@ | ||
152 | @apply h-full flex flex-col; | 152 | @apply h-full flex flex-col; |
153 | 153 | ||
154 | .ant-tabs-content { | 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,6 +55,11 @@ export interface NodeItemConfigType { | ||
55 | * @description 配置描述 | 55 | * @description 配置描述 |
56 | */ | 56 | */ |
57 | configurationDescriptor: ConfigurationDescriptor; | 57 | configurationDescriptor: ConfigurationDescriptor; |
58 | + | ||
59 | + /** | ||
60 | + * @description 禁用所有动作 | ||
61 | + */ | ||
62 | + disableAction?: boolean; | ||
58 | } | 63 | } |
59 | 64 | ||
60 | export interface CategoryConfigType { | 65 | export interface CategoryConfigType { |