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