Commit 54dd5e3a7cadc8e883120735441ac5b26181cb4b

Authored by xp.Huang
2 parents 355a19bb b97242f8

Merge branch 'ft' into 'main_dev'

fix: 修复Teambition上的问题

See merge request yunteng/thingskit-front!917
... ... @@ -25,7 +25,7 @@ module.exports = defineConfig({
25 25 'plugin:jest/recommended',
26 26 ],
27 27 rules: {
28   - 'no-console': 'error',
  28 + 'no-console': 'off',
29 29 'vue/script-setup-uses-vars': 'error',
30 30 '@typescript-eslint/ban-ts-ignore': 'off',
31 31 '@typescript-eslint/explicit-function-return-type': 'off',
... ...
... ... @@ -394,6 +394,13 @@
394 394 //.ant-table-tbody > tr.ant-table-row-selected td {
395 395 //background-color: fade(@primary-color, 8%) !important;
396 396 //}
  397 + .ant-table-placeholder {
  398 + display: flex;
  399 + align-items: center;
  400 + justify-content: center;
  401 + height: 670px;
  402 + max-height: 670px;
  403 + }
397 404 }
398 405
399 406 .ant-pagination {
... ...
... ... @@ -20,6 +20,12 @@
20 20 import { useFingerprint } from '/@/utils/useFingerprint';
21 21 import { GetResult } from '@fingerprintjs/fingerprintjs';
22 22
  23 + const props = defineProps({
  24 + mode: {
  25 + type: String,
  26 + default: PageMode.SPLIT_SCREEN_MODE,
  27 + },
  28 + });
23 29 type CameraRecordItem = CameraRecord & {
24 30 canPlay?: boolean;
25 31 isTransform?: boolean;
... ... @@ -252,7 +258,11 @@
252 258 </Authority>
253 259 </div>
254 260 <Space>
255   - <Button type="primary" @click="handleChangeMode(PageMode.SPLIT_SCREEN_MODE)">
  261 + <Button
  262 + v-if="props.mode !== PageMode.SPLIT_SCREEN_MODE"
  263 + type="primary"
  264 + @click="handleChangeMode(PageMode.SPLIT_SCREEN_MODE)"
  265 + >
256 266 分屏模式
257 267 </Button>
258 268 <Button type="primary" @click="handleChangeMode(PageMode.LIST_MODE)">
... ...
... ... @@ -12,7 +12,11 @@
12 12
13 13 <template>
14 14 <div>
15   - <SplitScreenMode v-if="mode == PageMode.SPLIT_SCREEN_MODE" @switchMode="handleSwitchMode" />
  15 + <SplitScreenMode
  16 + :mode="mode"
  17 + v-if="mode == PageMode.SPLIT_SCREEN_MODE"
  18 + @switchMode="handleSwitchMode"
  19 + />
16 20 <ListMode v-if="mode === PageMode.LIST_MODE" @switchMode="handleSwitchMode" />
17 21 </div>
18 22 </template>
... ...
... ... @@ -131,14 +131,19 @@ export const formSchema: FormSchema[] = [
131 131 onChange: async (value) => {
132 132 const res = await findMessageConfig({});
133 133 let typeId: Nullable<string> = null;
134   - const options = res.map((item) => {
135   - if (item.messageType === value) typeId = item.id;
136   - return {
137   - disabled: item.messageType !== value,
138   - label: item.configName,
139   - value: item.id,
140   - };
141   - });
  134 + const options = res
  135 + .map((item) => {
  136 + if (item.messageType === value && item.status === 1) {
  137 + typeId = item.id;
  138 + }
  139 + return {
  140 + disabled: item.messageType !== value,
  141 + label: item.configName,
  142 + value: item.id,
  143 + status: item.status,
  144 + };
  145 + })
  146 + .filter((item) => item.status === 1);
142 147 await formActionType.setFieldsValue({ messageConfigId: typeId });
143 148 await formActionType.updateSchema({
144 149 field: 'messageConfigId',
... ... @@ -155,14 +160,25 @@ export const formSchema: FormSchema[] = [
155 160 label: '配置名称',
156 161 required: true,
157 162 component: 'ApiSelect',
158   - componentProps: {
159   - api: findMessageConfig,
160   - params: {
161   - messageType: ({ values }) => Reflect.get(values, 'messageType'),
162   - },
163   - immediate: true,
164   - labelField: 'configName',
165   - valueField: 'id',
  163 + componentProps: () => {
  164 + return {
  165 + api: async (params: Recordable) => {
  166 + try {
  167 + const record = await findMessageConfig(params);
  168 + return record.filter((item) => item.status === 1);
  169 + } catch (error) {
  170 + console.log(error);
  171 + return [];
  172 + }
  173 + },
  174 + params: {
  175 + messageType: ({ values }) => Reflect.get(values, 'messageType'),
  176 + },
  177 + immediate: true,
  178 + labelField: 'configName',
  179 + valueField: 'id',
  180 + getPopupContainer: () => document.body,
  181 + };
166 182 },
167 183 },
168 184 {
... ...
... ... @@ -465,14 +465,15 @@ export const formSchema: BFormSchema[] = [
465 465 },
466 466 {
467 467 field: 'dateGroupGap',
468   - label: '分组间隔',
  468 + label: '间隔时间',
469 469 component: 'Select',
470 470 colProps: { span: 24 },
471   - dynamicRules: ({ model }) => {
  471 + dynamicRules: () => {
472 472 return [
473 473 {
474   - required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE,
475   - message: '分组间隔为必填项',
  474 + // required: model[SchemaFiled.AGG] !== AggregateDataEnum.NONE,
  475 + required: true,
  476 + message: '间隔时间为必填项',
476 477 type: 'number',
477 478 },
478 479 ];
... ...
1   -import { FormSchema } from '/@/components/Form';
2   -import { findDictItemByCode } from '/@/api/system/dict';
3   -import { h, ref, unref } from 'vue';
4   -import { isExistDataManagerNameApi } from '/@/api/datamanager/dataManagerApi';
5   -import { getDeviceProfile } from '/@/api/alarm/position';
6   -import { BasicColumn, BasicTableProps } from '/@/components/Table';
7   -import { devicePage } from '/@/api/device/deviceManager';
8   -import { Tag } from 'ant-design-vue';
9   -import { DeviceRecord } from '/@/api/device/model/deviceModel';
10   -import { FETCH_SETTING } from '/@/components/Table/src/const';
11   -import { useClipboard } from '@vueuse/core';
12   -import { useMessage } from '/@/hooks/web/useMessage';
13   -
14   -const typeValue = ref('');
15   -export enum CredentialsEnum {
16   - IS_ANONYMOUS = 'anonymous',
17   - IS_BASIC = 'basic',
18   - IS_PEM = 'pem',
19   -}
20   -export const isBasic = (type: string) => {
21   - return type === CredentialsEnum.IS_BASIC;
22   -};
23   -export const isPem = (type: string) => {
24   - return type === CredentialsEnum.IS_PEM;
25   -};
26   -
27   -export enum DataSourceType {
28   - ALL = 'ALL',
29   - PRODUCT = 'PRODUCTS',
30   - DEVICE = 'DEVICES',
31   -}
32   -
33   -export enum BasicInfoFormField {
34   - DATA_SOURCE_TYPE = 'datasourceType',
35   - DATA_SOURCE_PRODUCT = 'datasourceProduct',
36   - DATA_SOURCE_DEVICE = 'datasourceDevice',
37   - CONVERT_CONFIG_ID = 'convertConfigId',
38   -}
39   -
40   -export enum DeviceStatusEnum {
41   - OFFLINE = 'OFFLINE',
42   - ONLINE = 'ONLINE',
43   - INACTIVE = 'INACTIVE',
44   -}
45   -
46   -export enum DeviceStatusNameEnum {
47   - OFFLINE = '离线',
48   - ONLINE = '在线',
49   - INACTIVE = '待激活',
50   -}
51   -
52   -export enum DeviceTypeEnum {
53   - SENSOR = 'SENSOR',
54   - DIRECT_CONNECTION = 'DIRECT_CONNECTION',
55   - GATEWAY = 'GATEWAY',
56   -}
57   -
58   -export enum DeviceTypeNameEnum {
59   - SENSOR = '网关子设备',
60   - DIRECT_CONNECTION = '直连设备',
61   - GATEWAY = '网关设备',
62   -}
63   -
64   -const handleGroupDevice = (options: DeviceRecord[]) => {
65   - const map = new Map<string, string[]>();
66   - options.forEach((item) => {
67   - if (map.has(item.profileId)) {
68   - const deviceList = map.get(item.profileId)!;
69   - deviceList.push(item.tbDeviceId);
70   - } else {
71   - map.set(item.profileId, [item.tbDeviceId]);
72   - }
73   - });
74   - const value = Array.from(map.entries()).map(([product, devices]) => ({ product, devices }));
75   -
76   - return value;
77   -};
78   -
79   -const deviceTableFormSchema: FormSchema[] = [
80   - {
81   - field: 'name',
82   - label: '设备名称',
83   - component: 'Input',
84   - colProps: { span: 9 },
85   - componentProps: {
86   - placeholder: '请输入设备名称',
87   - },
88   - },
89   - {
90   - field: 'deviceType',
91   - label: '设备类型',
92   - component: 'ApiSelect',
93   - colProps: { span: 9 },
94   - componentProps: {
95   - placeholder: '请选择设备类型',
96   - api: findDictItemByCode,
97   - params: {
98   - dictCode: 'device_type',
99   - },
100   - labelField: 'itemText',
101   - valueField: 'itemValue',
102   - },
103   - },
104   -];
105   -const { copied, copy } = useClipboard({ legacy: true });
106   -const { createMessage } = useMessage();
107   -const deviceTableColumn: BasicColumn[] = [
108   - {
109   - title: '状态',
110   - dataIndex: 'deviceState',
111   - customRender: ({ text }) => {
112   - return h(
113   - Tag,
114   - {
115   - color:
116   - text === DeviceStatusEnum.INACTIVE
117   - ? 'warning'
118   - : text === DeviceStatusEnum.OFFLINE
119   - ? 'error'
120   - : 'success',
121   - },
122   - () => DeviceStatusNameEnum[text]
123   - );
124   - },
125   - },
126   - {
127   - title: '别名/设备名称',
128   - dataIndex: 'name',
129   - customRender: ({ record }) => {
130   - return h('div', [
131   - h(
132   - 'div',
133   - {
134   - class: 'cursor-pointer',
135   - onClick: async () => {
136   - await copy(record.name);
137   - if (unref(copied)) createMessage.success('复制成功~');
138   - },
139   - },
140   - [
141   - record.alias && h('div', { class: 'truncate' }, record.alias),
142   - h('div', { class: 'text-blue-400 truncate' }, record.name),
143   - ]
144   - ),
145   - ]);
146   - },
147   - },
148   - {
149   - title: '设备类型',
150   - dataIndex: 'deviceType',
151   - customRender: ({ text }) => {
152   - return h(Tag, { color: 'success' }, () => DeviceTypeNameEnum[text]);
153   - },
154   - },
155   - {
156   - title: '所属产品',
157   - dataIndex: 'deviceProfile.name',
158   - },
159   - {
160   - title: '所属组织',
161   - dataIndex: 'organizationDTO.name',
162   - },
163   -];
164   -
165   -const TransferTableProps: BasicTableProps = {
166   - formConfig: {
167   - layout: 'inline',
168   - labelWidth: 80,
169   - schemas: deviceTableFormSchema,
170   - actionColOptions: { span: 6 },
171   - },
172   - size: 'small',
173   - maxHeight: 240,
174   - useSearchForm: true,
175   - columns: deviceTableColumn,
176   - showIndexColumn: false,
177   - fetchSetting: FETCH_SETTING,
178   -} as BasicTableProps;
179   -
180   -export const modeForm = (submitFn?: Function): FormSchema[] => {
181   - return [
182   - {
183   - field: BasicInfoFormField.CONVERT_CONFIG_ID,
184   - label: '',
185   - component: 'Input',
186   - show: false,
187   - },
188   - {
189   - field: BasicInfoFormField.DATA_SOURCE_TYPE,
190   - label: '数据源',
191   - component: 'RadioGroup',
192   - defaultValue: DataSourceType.ALL,
193   - componentProps: {
194   - options: [
195   - { label: '全部', value: DataSourceType.ALL },
196   - { label: '产品', value: DataSourceType.PRODUCT },
197   - { label: '设备', value: DataSourceType.DEVICE },
198   - ],
199   - },
200   - },
201   - {
202   - field: BasicInfoFormField.DATA_SOURCE_PRODUCT,
203   - label: '数据源产品',
204   - component: 'TransferModal',
205   - ifShow: ({ model }) => {
206   - return model[BasicInfoFormField.DATA_SOURCE_TYPE] !== DataSourceType.ALL;
207   - },
208   - valueField: 'value',
209   - changeEvent: 'update:value',
210   - componentProps: ({ formActionType }) => {
211   - const { setFieldsValue } = formActionType;
212   - return {
213   - api: getDeviceProfile,
214   - labelField: 'name',
215   - valueField: 'tbProfileId',
216   - transferProps: {
217   - listStyle: { height: '400px' },
218   - showSearch: true,
219   - filterOption: (inputValue: string, option: Recordable) => {
220   - const upperCaseInputValue = inputValue.toUpperCase();
221   - const upperCaseOptionValue = option.name.toUpperCase();
222   - return upperCaseOptionValue.includes(upperCaseInputValue);
223   - },
224   - },
225   - onChange: () => {
226   - setFieldsValue({ [BasicInfoFormField.DATA_SOURCE_DEVICE]: [] });
227   - },
228   - };
229   - },
230   - },
231   - {
232   - field: BasicInfoFormField.DATA_SOURCE_DEVICE,
233   - label: '数据源设备',
234   - component: 'TransferTableModal',
235   - ifShow: ({ model }) => {
236   - return model[BasicInfoFormField.DATA_SOURCE_TYPE] === DataSourceType.DEVICE;
237   - },
238   - valueField: 'value',
239   - changeEvent: 'update:value',
240   - componentProps: ({ formActionType }) => {
241   - const { getFieldsValue } = formActionType;
242   - const values = getFieldsValue();
243   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
244   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
245   -
246   - return {
247   - labelField: 'name',
248   - valueField: 'tbDeviceId',
249   - primaryKey: 'tbDeviceId',
250   - pendingTableProps: {
251   - ...TransferTableProps,
252   - api: devicePage,
253   - beforeFetch: (params) => {
254   - const values = getFieldsValue();
255   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
256   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
257   - if (convertConfigId) {
258   - Object.assign(params, { convertConfigId, selected: false });
259   - }
260   - return { ...params, deviceProfileIds };
261   - },
262   - } as BasicTableProps,
263   - selectedTableProps: {
264   - ...TransferTableProps,
265   - // api
266   - api: !!(convertConfigId && devices) ? devicePage : undefined,
267   - beforeFetch: (params) => {
268   - const values = getFieldsValue();
269   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
270   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
271   - if (convertConfigId) {
272   - Object.assign(params, { convertConfigId, selected: true });
273   - }
274   - return { ...params, deviceProfileIds };
275   - },
276   - } as BasicTableProps,
277   - initSelectedOptions: async ({ setSelectedTotal }) => {
278   - const values = getFieldsValue();
279   - const convertConfigId = Reflect.get(values, BasicInfoFormField.CONVERT_CONFIG_ID);
280   - const deviceProfileIds = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_PRODUCT);
281   - const devices = Reflect.get(values, BasicInfoFormField.DATA_SOURCE_DEVICE);
282   - if (convertConfigId && devices) {
283   - const { items, total } = await devicePage({
284   - page: 1,
285   - pageSize: 10,
286   - convertConfigId: values[BasicInfoFormField.CONVERT_CONFIG_ID],
287   - deviceProfileIds,
288   - selected: true,
289   - });
290   - setSelectedTotal(total);
291   - return items;
292   - }
293   - return [];
294   - },
295   - onSelectedAfter: async () => {
296   - submitFn && (await submitFn(false));
297   - },
298   - onRemoveAfter: async ({ reloadSelected }) => {
299   - submitFn && (await submitFn(false));
300   - reloadSelected();
301   - },
302   - transformValue: (_selectedRowKeys: string[], selectedRows: DeviceRecord[]) => {
303   - return handleGroupDevice(selectedRows);
304   - },
305   - };
306   - },
307   - },
308   - {
309   - field: 'type',
310   - label: '转换方式',
311   - component: 'ApiSelect',
312   - required: true,
313   - colProps: {
314   - span: 24,
315   - },
316   - componentProps({}) {
317   - return {
318   - api: findDictItemByCode,
319   - params: {
320   - dictCode: 'convert_data_to',
321   - },
322   - labelField: 'itemText',
323   - valueField: 'itemValue',
324   - onChange(value) {
325   - typeValue.value = value;
326   - },
327   - };
328   - },
329   - },
330   - {
331   - field: 'remark',
332   - label: '描述',
333   - colProps: { span: 24 },
334   - component: 'Input',
335   - componentProps: {
336   - maxLength: 255,
337   - placeholder: '请输入描述',
338   - },
339   - },
340   - ];
341   -};
342   -
343   -export const modeKafkaForm: FormSchema[] = [
344   - {
345   - field: 'name',
346   - label: '名称',
347   - colProps: { span: 12 },
348   - required: true,
349   - component: 'Input',
350   - componentProps: {
351   - maxLength: 255,
352   - placeholder: '请输入名称',
353   - },
354   - dynamicRules: () => {
355   - return [
356   - {
357   - required: true,
358   - validator(_, value) {
359   - return new Promise((resolve, reject) => {
360   - if (value == '') {
361   - reject('请输入名称');
362   - } else {
363   - resolve();
364   - }
365   - });
366   - },
367   - },
368   - ];
369   - },
370   - },
371   - {
372   - field: 'topicPattern',
373   - label: '消息主题',
374   - colProps: { span: 12 },
375   - required: true,
376   - component: 'Input',
377   - defaultValue: 'my-topic',
378   - componentProps: {
379   - maxLength: 255,
380   - placeholder: '请输入消息主题',
381   - },
382   - },
383   - {
384   - field: 'bootstrapServers',
385   - label: '服务器',
386   - colProps: { span: 12 },
387   - component: 'Input',
388   - defaultValue: 'localhost:9092',
389   - required: true,
390   - componentProps: {
391   - maxLength: 255,
392   - placeholder: 'localhost:9092',
393   - },
394   - },
395   - {
396   - field: 'retries',
397   - label: '重连次数',
398   - colProps: { span: 12 },
399   - component: 'InputNumber',
400   - defaultValue: 0,
401   - componentProps: {
402   - maxLength: 255,
403   - },
404   - },
405   - {
406   - field: 'batchSize',
407   - label: '生产者并发',
408   - colProps: { span: 12 },
409   - component: 'InputNumber',
410   - defaultValue: 16384,
411   - componentProps: {
412   - maxLength: 255,
413   - },
414   - },
415   - {
416   - field: 'linger',
417   - label: '缓存时间',
418   - colProps: { span: 12 },
419   - component: 'InputNumber',
420   - defaultValue: 0,
421   - componentProps: {
422   - maxLength: 255,
423   - },
424   - },
425   - {
426   - field: 'bufferMemory',
427   - label: '最大缓存',
428   - colProps: { span: 12 },
429   - component: 'InputNumber',
430   - defaultValue: 33554432,
431   - componentProps: {
432   - maxLength: 255,
433   - },
434   - },
435   - {
436   - field: 'acks',
437   - component: 'Select',
438   - label: '响应码',
439   - colProps: { span: 12 },
440   - defaultValue: '-1',
441   - componentProps: {
442   - placeholder: '请选择响应码',
443   - options: [
444   - { label: 'all', value: 'all' },
445   - { label: '-1', value: '-1' },
446   - { label: '0', value: '0' },
447   - { label: '1', value: '1' },
448   - ],
449   - },
450   - },
451   - {
452   - field: 'keySerializer',
453   - label: '键序列化',
454   - colProps: { span: 24 },
455   - required: true,
456   - component: 'Input',
457   - defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',
458   - componentProps: {
459   - maxLength: 255,
460   - placeholder: 'org.apache.kafka.common.serialization.StringSerializer',
461   - },
462   - },
463   - {
464   - field: 'valueSerializer',
465   - label: '值序列化',
466   - colProps: { span: 24 },
467   - required: true,
468   - component: 'Input',
469   - defaultValue: 'org.apache.kafka.common.serialization.StringSerializer',
470   - componentProps: {
471   - maxLength: 255,
472   - placeholder: 'org.apache.kafka.common.serialization.StringSerializer',
473   - },
474   - },
475   - {
476   - field: 'otherProperties',
477   - label: '其他属性',
478   - colProps: { span: 24 },
479   - component: 'JAddInput',
480   - subLabel: '不可重复',
481   - },
482   - {
483   - field: 'addMetadataKeyValuesAsKafkaHeaders',
484   - label: '是否启用',
485   - colProps: { span: 12 },
486   - component: 'Checkbox',
487   - renderComponentContent: '将消息的元数据以键值对的方式添加到Kafka消息头中',
488   - },
489   - {
490   - field: 'kafkaHeadersCharset',
491   - component: 'Select',
492   - label: '字符集',
493   - required: true,
494   - colProps: { span: 12 },
495   - defaultValue: 'UTF-8',
496   - componentProps: {
497   - placeholder: '请选择字符集编码',
498   - options: [
499   - { label: 'US-ASCII', value: 'US' },
500   - { label: 'ISO-8859-1', value: 'ISO-8859-1' },
501   - { label: 'UTF-8', value: 'UTF-8' },
502   - { label: 'UTF-16BE', value: 'UTF-16BE' },
503   - { label: 'UTF-16LE', value: 'UTF-16LE' },
504   - { label: 'UTF-16', value: 'UTF-16' },
505   - ],
506   - },
507   - ifShow: ({ values }) => {
508   - return !!values.addMetadataKeyValuesAsKafkaHeaders;
509   - },
510   - },
511   - {
512   - field: 'description',
513   - label: '说明',
514   - colProps: { span: 24 },
515   - component: 'InputTextArea',
516   - componentProps: {
517   - maxLength: 255,
518   - rows: 4,
519   - placeholder: '请输入说明',
520   - },
521   - },
522   -];
523   -
524   -export const modeMqttForm: FormSchema[] = [
525   - {
526   - field: 'name',
527   - label: '名称',
528   - colProps: { span: 12 },
529   - component: 'Input',
530   - componentProps: {
531   - maxLength: 255,
532   - placeholder: '请输入名称',
533   - },
534   - },
535   - {
536   - field: 'topicPattern',
537   - label: '主题模式',
538   - colProps: { span: 12 },
539   - required: true,
540   - component: 'Input',
541   - defaultValue: 'my-topic',
542   - componentProps: {
543   - maxLength: 255,
544   - placeholder: '请输入Topic pattern',
545   - },
546   - },
547   - {
548   - field: 'host',
549   - label: '主机',
550   - colProps: { span: 12 },
551   - component: 'Input',
552   - componentProps: {
553   - maxLength: 255,
554   - placeholder: '请输入Host',
555   - },
556   - },
557   - {
558   - field: 'port',
559   - label: '端口',
560   - colProps: { span: 12 },
561   - component: 'InputNumber',
562   - defaultValue: 1883,
563   - required: true,
564   - componentProps: {
565   - maxLength: 255,
566   - placeholder: '请输入Port',
567   - },
568   - },
569   - {
570   - field: 'connectTimeoutSec',
571   - label: '连接超时(秒)',
572   - colProps: { span: 12 },
573   - component: 'InputNumber',
574   - defaultValue: 10,
575   - required: true,
576   - componentProps: {
577   - maxLength: 255,
578   - placeholder: '请输入Connection timeout (sec)',
579   - },
580   - },
581   - {
582   - field: 'clientId',
583   - label: '客户端ID',
584   - colProps: { span: 12 },
585   - component: 'Input',
586   - componentProps: ({ formActionType }) => {
587   - const { updateSchema } = formActionType;
588   - return {
589   - onChange(e) {
590   - if (!e.data) {
591   - updateSchema({
592   - field: 'appendClientIdSuffix',
593   - show: false,
594   - });
595   - } else {
596   - updateSchema({
597   - field: 'appendClientIdSuffix',
598   - show: true,
599   - });
600   - }
601   - },
602   - maxLength: 255,
603   - placeholder: '请输入Client ID',
604   - };
605   - },
606   - },
607   - {
608   - field: 'appendClientIdSuffix',
609   - label: '',
610   - colProps: { span: 12 },
611   - defaultValue: false,
612   - component: 'Checkbox',
613   - renderComponentContent: '将服务ID作为后缀添加到客户端ID',
614   - show: false,
615   - },
616   - {
617   - field: 'cleanSession',
618   - label: '是否启用',
619   - colProps: { span: 12 },
620   - defaultValue: true,
621   - component: 'Checkbox',
622   - renderComponentContent: '清除会话',
623   - },
624   - {
625   - field: 'ssl',
626   - label: '是否启用',
627   - colProps: { span: 12 },
628   - defaultValue: false,
629   - component: 'Checkbox',
630   - renderComponentContent: '启用SSL',
631   - },
632   - {
633   - field: 'type',
634   - component: 'Select',
635   - label: '凭据类型',
636   - colProps: { span: 12 },
637   - defaultValue: 'anonymous',
638   - componentProps: {
639   - placeholder: '请选择Credentials',
640   - options: [
641   - { label: 'Anonymous', value: 'anonymous' },
642   - { label: 'Basic', value: 'basic' },
643   - { label: 'PEM', value: 'pem' },
644   - ],
645   - },
646   - },
647   - {
648   - field: 'username',
649   - label: '用户名',
650   - colProps: { span: 12 },
651   - component: 'Input',
652   - required: true,
653   - componentProps: {
654   - maxLength: 255,
655   - placeholder: '请输入用户名',
656   - },
657   - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),
658   - },
659   - {
660   - field: 'password',
661   - label: '密码',
662   - colProps: { span: 12 },
663   - component: 'InputPassword',
664   - componentProps: {
665   - maxLength: 255,
666   - placeholder: '请输入密码',
667   - },
668   - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),
669   - },
670   - {
671   - field: '4',
672   - label: '',
673   - colProps: { span: 24 },
674   - component: 'Input',
675   - slot: 'uploadAdd1',
676   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
677   - },
678   - {
679   - field: '11',
680   - label: '',
681   - colProps: { span: 24 },
682   - component: 'Input',
683   - slot: 'showImg1',
684   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
685   - },
686   - {
687   - field: '5',
688   - label: '',
689   - colProps: { span: 24 },
690   - component: 'Input',
691   - slot: 'uploadAdd2',
692   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
693   - },
694   - {
695   - field: '1111',
696   - label: '',
697   - colProps: { span: 24 },
698   - component: 'Input',
699   - slot: 'showImg2',
700   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
701   - },
702   - {
703   - field: '6',
704   - label: '',
705   - colProps: { span: 24 },
706   - component: 'Input',
707   - slot: 'uploadAdd3',
708   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
709   - },
710   - {
711   - field: '111111',
712   - label: '',
713   - colProps: { span: 24 },
714   - component: 'Input',
715   - slot: 'showImg3',
716   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
717   - },
718   - {
719   - field: 'password',
720   - label: '密码',
721   - colProps: { span: 12 },
722   - component: 'InputPassword',
723   - componentProps: {
724   - maxLength: 255,
725   - placeholder: '请输入密码',
726   - },
727   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
728   - },
729   - {
730   - field: 'description',
731   - label: '说明',
732   - colProps: { span: 24 },
733   - component: 'InputTextArea',
734   - componentProps: {
735   - maxLength: 255,
736   - rows: 4,
737   - placeholder: '请输入说明',
738   - },
739   - },
740   -];
741   -
742   -export const modeRabbitMqForm: FormSchema[] = [
743   - {
744   - field: 'name',
745   - label: '名称',
746   - colProps: { span: 12 },
747   - required: true,
748   - component: 'Input',
749   - componentProps: {
750   - maxLength: 255,
751   - placeholder: '请输入名称',
752   - },
753   - dynamicRules: () => {
754   - return [
755   - {
756   - required: true,
757   - validator(_, value) {
758   - return new Promise((resolve, reject) => {
759   - if (value == '') {
760   - reject('请输入名称');
761   - } else {
762   - resolve();
763   - }
764   - });
765   - },
766   - },
767   - ];
768   - },
769   - },
770   - {
771   - field: 'exchangeNamePattern',
772   - label: '交换名称模式',
773   - colProps: { span: 12 },
774   - component: 'Input',
775   - componentProps: {
776   - maxLength: 255,
777   - placeholder: '请输入模式',
778   - },
779   - },
780   - {
781   - field: 'routingKeyPattern',
782   - label: '路由密钥模式',
783   - colProps: { span: 12 },
784   - component: 'Input',
785   - componentProps: {
786   - maxLength: 255,
787   - placeholder: '请输入模式',
788   - },
789   - },
790   - {
791   - field: 'messageProperties',
792   - component: 'Select',
793   - label: '消息属性',
794   - colProps: { span: 12 },
795   - componentProps: {
796   - placeholder: '请选择消息属性',
797   - options: [
798   - { label: 'BASIC', value: 'BASIC' },
799   - { label: 'TEXT_PLAIN', value: 'TEXT_PLAIN' },
800   - { label: 'MINIMAL_BASIC', value: 'MINIMAL_BASIC' },
801   - { label: 'MINIMAL_PERSISTENT_BASIC', value: 'MINIMAL_PERSISTENT_BASIC' },
802   - { label: 'PERSISTENT_BASIC', value: 'PERSISTENT_BASIC' },
803   - { label: 'PERSISTENT_TEXT_PLAIN', value: 'PERSISTENT_TEXT_PLAIN' },
804   - ],
805   - },
806   - },
807   - {
808   - field: 'host',
809   - label: '主机',
810   - colProps: { span: 12 },
811   - component: 'Input',
812   - required: true,
813   - defaultValue: 'localhost',
814   - componentProps: {
815   - maxLength: 255,
816   - placeholder: 'localhost',
817   - },
818   - },
819   - {
820   - field: 'port',
821   - label: '端口',
822   - colProps: { span: 12 },
823   - component: 'InputNumber',
824   - defaultValue: 5672,
825   - required: true,
826   - componentProps: {
827   - maxLength: 255,
828   - placeholder: '请输入Port',
829   - },
830   - },
831   - {
832   - field: 'virtualHost',
833   - label: '虚拟端口(以/开头)',
834   - colProps: { span: 12 },
835   - component: 'Input',
836   - defaultValue: '/',
837   - componentProps: {
838   - maxLength: 255,
839   - placeholder: '/',
840   - },
841   - },
842   - {
843   - field: 'username',
844   - label: '用户名',
845   - colProps: { span: 12 },
846   - component: 'Input',
847   - defaultValue: 'guest',
848   - componentProps: {
849   - maxLength: 255,
850   - placeholder: '请输入用户名',
851   - },
852   - },
853   - {
854   - field: 'password',
855   - label: '密码',
856   - colProps: { span: 12 },
857   - component: 'InputPassword',
858   - defaultValue: 'guest',
859   - componentProps: {
860   - maxLength: 255,
861   - placeholder: '请输入密码',
862   - },
863   - },
864   - {
865   - field: 'automaticRecoveryEnabled',
866   - label: '是否启用',
867   - colProps: { span: 12 },
868   - component: 'Checkbox',
869   - renderComponentContent: '自动恢复',
870   - },
871   - {
872   - field: 'connectionTimeout',
873   - label: '连接超时(毫秒)',
874   - colProps: { span: 12 },
875   - component: 'InputNumber',
876   - defaultValue: 60000,
877   - componentProps: {
878   - maxLength: 255,
879   - placeholder: '请输入Connection timeout (ms)',
880   - },
881   - },
882   - {
883   - field: 'handshakeTimeout',
884   - label: '握手超时(毫秒)',
885   - colProps: { span: 12 },
886   - component: 'InputNumber',
887   - defaultValue: 10000,
888   - componentProps: {
889   - maxLength: 255,
890   - placeholder: '请输入Handshake timeout (ms)',
891   - },
892   - },
893   - {
894   - field: 'clientProperties',
895   - label: '客户端属性',
896   - colProps: { span: 24 },
897   - component: 'JAddInput',
898   - subLabel: '不可重复',
899   - },
900   - {
901   - field: 'description',
902   - label: '说明',
903   - colProps: { span: 24 },
904   - component: 'InputTextArea',
905   - componentProps: {
906   - maxLength: 255,
907   - rows: 4,
908   - placeholder: '请输入说明',
909   - },
910   - },
911   -];
912   -
913   -export const modeApiForm: FormSchema[] = [
914   - {
915   - field: 'name',
916   - label: '名称',
917   - colProps: { span: 12 },
918   - required: true,
919   - component: 'Input',
920   - componentProps: {
921   - maxLength: 255,
922   - placeholder: '请输入名称',
923   - },
924   - dynamicRules: ({ values }) => {
925   - return [
926   - {
927   - required: true,
928   - validator(_, value) {
929   - return new Promise((resolve, reject) => {
930   - if (value == '') {
931   - reject('请输入名称');
932   - } else {
933   - if (values.name) {
934   - isExistDataManagerNameApi({
935   - name: value,
936   - type:
937   - typeValue.value == ''
938   - ? 'org.thingsboard.rule.engine.rest.TbRestApiCallNode'
939   - : typeValue.value,
940   - }).then((data) => {
941   - if (data == true) {
942   - // createMessage.error('名称已存在');
943   - resolve();
944   - } else {
945   - resolve();
946   - }
947   - });
948   - } else {
949   - resolve();
950   - }
951   - }
952   - });
953   - },
954   - },
955   - ];
956   - },
957   - },
958   - {
959   - field: 'restEndpointUrlPattern',
960   - label: '端点URL模式',
961   - colProps: { span: 12 },
962   - required: true,
963   - defaultValue: 'http://localhost/api',
964   - component: 'Input',
965   - componentProps: {
966   - maxLength: 255,
967   - placeholder: '请输入Endpoint URL pattern',
968   - },
969   - },
970   - {
971   - field: 'requestMethod',
972   - component: 'Select',
973   - label: '请求方式',
974   - colProps: { span: 12 },
975   - defaultValue: 'POST',
976   - componentProps: {
977   - placeholder: '请选择Request method',
978   - options: [
979   - { label: 'GET', value: 'GET' },
980   - { label: 'POST', value: 'POST' },
981   - { label: 'PUT', value: 'PUT' },
982   - { label: 'DELETE', value: 'DELETE' },
983   - ],
984   - },
985   - },
986   - {
987   - field: 'enableProxy',
988   - label: '是否启用',
989   - colProps: { span: 12 },
990   - component: 'Checkbox',
991   - renderComponentContent: '启用代理',
992   - },
993   -
994   - {
995   - field: 'proxyHost',
996   - label: '代理主机',
997   - colProps: { span: 12 },
998   - required: true,
999   - component: 'Input',
1000   - componentProps: {
1001   - maxLength: 255,
1002   - placeholder: 'http或者https开头',
1003   - },
1004   - ifShow: ({ values }) => {
1005   - return !!values.enableProxy;
1006   - },
1007   - },
1008   - {
1009   - field: 'proxyPort',
1010   - label: '代理端口',
1011   - colProps: { span: 12 },
1012   - required: true,
1013   - component: 'InputNumber',
1014   - defaultValue: 0,
1015   - componentProps: {
1016   - maxLength: 255,
1017   - placeholder: 'http或者https开头',
1018   - },
1019   - ifShow: ({ values }) => {
1020   - return !!values.enableProxy;
1021   - },
1022   - },
1023   - {
1024   - field: 'proxyUser',
1025   - label: '代理用户',
1026   - colProps: { span: 12 },
1027   - required: true,
1028   - component: 'Input',
1029   - componentProps: {
1030   - maxLength: 255,
1031   - placeholder: '请输入代理用户',
1032   - },
1033   - ifShow: ({ values }) => {
1034   - return !!values.enableProxy;
1035   - },
1036   - },
1037   - {
1038   - field: 'proxyPassword',
1039   - label: '代理密码',
1040   - colProps: { span: 12 },
1041   - required: true,
1042   - component: 'InputPassword',
1043   - componentProps: {
1044   - maxLength: 255,
1045   - placeholder: '请输入代理密码',
1046   - },
1047   - ifShow: ({ values }) => {
1048   - return !!values.enableProxy;
1049   - },
1050   - },
1051   -
1052   - {
1053   - field: 'useSystemProxyProperties',
1054   - label: '是否启用',
1055   - colProps: { span: 12 },
1056   - component: 'Checkbox',
1057   - renderComponentContent: '使用系统代理属性',
1058   - },
1059   - {
1060   - field: 'maxParallelRequestsCount',
1061   - label: '最大并行请求数',
1062   - colProps: { span: 12 },
1063   - required: true,
1064   - component: 'InputNumber',
1065   - defaultValue: 0,
1066   - componentProps: {
1067   - maxLength: 255,
1068   - },
1069   - ifShow: ({ values }) => {
1070   - return !!values.useSystemProxyProperties;
1071   - },
1072   - },
1073   - {
1074   - field: 'ignoreRequestBody',
1075   - label: '是否启用',
1076   - colProps: { span: 12 },
1077   - component: 'Checkbox',
1078   - renderComponentContent: '无请求正文',
1079   - },
1080   - {
1081   - field: 'readTimeoutMs',
1082   - label: '读取超时(毫秒)',
1083   - colProps: { span: 12 },
1084   - required: true,
1085   - component: 'InputNumber',
1086   - defaultValue: 0,
1087   - componentProps: {
1088   - maxLength: 255,
1089   - },
1090   - ifShow: ({ values }) => {
1091   - return !values.useSystemProxyProperties;
1092   - },
1093   - },
1094   - {
1095   - field: 'maxParallelRequestsCount',
1096   - label: '最大并行请求数',
1097   - colProps: { span: 12 },
1098   - required: true,
1099   - component: 'InputNumber',
1100   - defaultValue: 0,
1101   - componentProps: {
1102   - maxLength: 255,
1103   - },
1104   - ifShow: ({ values }) => {
1105   - return !values.useSystemProxyProperties;
1106   - },
1107   - },
1108   - {
1109   - field: 'headers',
1110   - label: 'Headers',
1111   - colProps: { span: 24 },
1112   - defaultValue: { 'Content-Type': 'application/json' },
1113   - component: 'JAddInput',
1114   - subLabel: '不可重复',
1115   - },
1116   -
1117   - {
1118   - field: 'useRedisQueueForMsgPersistence',
1119   - label: '是否启用',
1120   - colProps: { span: 12 },
1121   - component: 'Checkbox',
1122   - renderComponentContent: '使用redis队列进行消息持久性',
1123   - },
1124   - {
1125   - field: 'trimQueue',
1126   - label: '是否启用',
1127   - colProps: { span: 12 },
1128   - component: 'Checkbox',
1129   - renderComponentContent: '修剪redis队列',
1130   - ifShow: ({ values }) => {
1131   - return !!values.useRedisQueueForMsgPersistence;
1132   - },
1133   - },
1134   - {
1135   - field: 'maxQueueSize',
1136   - label: 'Redis队列最大数',
1137   - colProps: { span: 12 },
1138   - required: true,
1139   - component: 'InputNumber',
1140   - defaultValue: 0,
1141   - componentProps: {
1142   - maxLength: 255,
1143   - },
1144   - ifShow: ({ values }) => {
1145   - return !!values.useRedisQueueForMsgPersistence;
1146   - },
1147   - },
1148   -
1149   - {
1150   - field: 'type',
1151   - component: 'Select',
1152   - label: '凭据类型',
1153   - colProps: { span: 12 },
1154   - defaultValue: 'anonymous',
1155   - componentProps: {
1156   - placeholder: '请选择凭据类型',
1157   - options: [
1158   - { label: 'Anonymous', value: 'anonymous' },
1159   - { label: 'Basic', value: 'basic' },
1160   - { label: 'PEM', value: 'pem' },
1161   - ],
1162   - },
1163   - },
1164   - {
1165   - field: 'username',
1166   - label: '用户名',
1167   - colProps: { span: 12 },
1168   - component: 'Input',
1169   - required: true,
1170   - componentProps: {
1171   - maxLength: 255,
1172   - placeholder: '请输入用户名',
1173   - },
1174   - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),
1175   - },
1176   - {
1177   - field: 'password',
1178   - label: '密码',
1179   - colProps: { span: 12 },
1180   - component: 'InputPassword',
1181   - required: true,
1182   - componentProps: {
1183   - maxLength: 255,
1184   - placeholder: '请输入密码',
1185   - },
1186   - ifShow: ({ values }) => isBasic(Reflect.get(values, 'type')),
1187   - },
1188   - {
1189   - field: '1',
1190   - label: '',
1191   - colProps: { span: 24 },
1192   - component: 'Input',
1193   - slot: 'uploadAdd1',
1194   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1195   - },
1196   - {
1197   - field: '11',
1198   - label: '',
1199   - colProps: { span: 24 },
1200   - component: 'Input',
1201   - slot: 'showImg1',
1202   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1203   - },
1204   - {
1205   - field: '1',
1206   - label: '',
1207   - colProps: { span: 24 },
1208   - component: 'Input',
1209   - slot: 'uploadAdd2',
1210   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1211   - },
1212   - {
1213   - field: '1111',
1214   - label: '',
1215   - colProps: { span: 24 },
1216   - component: 'Input',
1217   - slot: 'showImg2',
1218   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1219   - },
1220   - {
1221   - field: '1',
1222   - label: '',
1223   - colProps: { span: 24 },
1224   - component: 'Input',
1225   - slot: 'uploadAdd3',
1226   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1227   - },
1228   - {
1229   - field: '111111',
1230   - label: '',
1231   - colProps: { span: 24 },
1232   - component: 'Input',
1233   - slot: 'showImg3',
1234   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1235   - },
1236   - {
1237   - field: 'password',
1238   - label: '密码',
1239   - colProps: { span: 12 },
1240   - component: 'InputPassword',
1241   - componentProps: {
1242   - maxLength: 255,
1243   - placeholder: '请输入密码',
1244   - },
1245   - ifShow: ({ values }) => isPem(Reflect.get(values, 'type')),
1246   - },
1247   -
1248   - {
1249   - field: 'description',
1250   - label: '说明',
1251   - colProps: { span: 24 },
1252   - component: 'InputTextArea',
1253   - componentProps: {
1254   - maxLength: 255,
1255   - rows: 4,
1256   - placeholder: '请输入说明',
1257   - },
1258   - },
1259   -];
1   -<template>
2   - <div class="transfer-config-mode">
3   - <BasicForm :showSubmitButton="false" @register="register">
4   - <template #uploadAdd1="{ field }">
5   - <span style="display: none">{{ field }}</span>
6   - <a-upload-dragger
7   - v-model:fileList="fileList1"
8   - name="file"
9   - :key="1"
10   - :multiple="false"
11   - @change="handleChange('T', $event)"
12   - :before-upload="() => false"
13   - >
14   - <p class="ant-upload-drag-icon">
15   - <InboxOutlined />
16   - </p>
17   - <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
18   - <p class="ant-upload-hint">
19   - 支持扩展名:.jpeg .png .jpg ...
20   - <br />
21   - 文件大小:最大支持5M
22   - </p>
23   - </a-upload-dragger>
24   - </template>
25   - <template #showImg1="{ field }">
26   - <span style="display: none">{{ field }}</span>
27   - <img
28   - v-if="showImg1"
29   - :src="showImg1Pic"
30   - alt="avatar"
31   - style="width: 6.25rem; height: 6.25rem"
32   - />
33   - </template>
34   - <div style="margin-top: 50px"></div>
35   - <template #uploadAdd2="{ field }">
36   - <span style="display: none">{{ field }}</span>
37   - <a-upload-dragger
38   - v-model:fileList="fileList2"
39   - name="file"
40   - :key="2"
41   - :multiple="false"
42   - @change="handleChange('F', $event)"
43   - :before-upload="() => false"
44   - >
45   - <p class="ant-upload-drag-icon">
46   - <InboxOutlined />
47   - </p>
48   - <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
49   - <p class="ant-upload-hint">
50   - 支持扩展名:.jpeg .png .jpg ...
51   - <br />
52   - 文件大小:最大支持5M
53   - </p>
54   - </a-upload-dragger>
55   - </template>
56   - <template #showImg2="{ field }">
57   - <span style="display: none">{{ field }}</span>
58   - <img
59   - v-if="showImg2"
60   - :src="showImg2Pic"
61   - alt="avatar"
62   - style="width: 6.25rem; height: 6.25rem"
63   - />
64   - </template>
65   - <div style="margin-top: 50px"></div>
66   - <template #uploadAdd3="{ field }">
67   - <span style="display: none">{{ field }}</span>
68   - <a-upload-dragger
69   - v-model:fileList="fileList3"
70   - name="file"
71   - :key="3"
72   - :multiple="false"
73   - @change="handleChange('C', $event)"
74   - :before-upload="() => false"
75   - >
76   - <p class="ant-upload-drag-icon">
77   - <InboxOutlined />
78   - </p>
79   - <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
80   - <p class="ant-upload-hint">
81   - 支持扩展名:.jpeg .png .jpg ...
82   - <br />
83   - 文件大小:最大支持5M
84   - </p>
85   - </a-upload-dragger>
86   - </template>
87   - <template #showImg3="{ field }">
88   - <span style="display: none">{{ field }}</span>
89   - <img
90   - v-if="showImg3"
91   - :src="showImg3Pic"
92   - alt="avatar"
93   - style="width: 6.25rem; height: 6.25rem"
94   - />
95   - </template>
96   - </BasicForm>
97   - </div>
98   -</template>
99   -<script lang="ts">
100   - import { defineComponent, ref, reactive, nextTick } from 'vue';
101   - import { BasicForm, useForm } from '/@/components/Form';
102   - import { CredentialsEnum, modeMqttForm } from '../config';
103   - import { InboxOutlined } from '@ant-design/icons-vue';
104   - import { Alert, Divider, Descriptions, Upload } from 'ant-design-vue';
105   - import { uploadApi } from '/@/api/personal/index';
106   - import { useMessage } from '/@/hooks/web/useMessage';
107   -
108   - export default defineComponent({
109   - components: {
110   - BasicForm,
111   - [Alert.name]: Alert,
112   - [Divider.name]: Divider,
113   - [Descriptions.name]: Descriptions,
114   - [Descriptions.Item.name]: Descriptions.Item,
115   - InboxOutlined,
116   - [Upload.Dragger.name]: Upload.Dragger,
117   - },
118   - emits: ['next', 'prev', 'register'],
119   - setup(_, { emit }) {
120   - const showImg1 = ref(false);
121   - const showImg1Pic = ref('');
122   - const showImg2 = ref(false);
123   - const showImg2Pic = ref('');
124   - const showImg3 = ref(false);
125   - const showImg3Pic = ref('');
126   - const { createMessage } = useMessage();
127   - let caCertFileName = ref('');
128   - let privateKeyFileName = ref('');
129   - let certFileName = ref('');
130   - let fileList1: any = ref<[]>([]);
131   - let fileList2: any = ref<[]>([]);
132   - let fileList3: any = ref<[]>([]);
133   - const credentialsV: any = reactive({
134   - credentials: {
135   - type: '',
136   - },
137   - });
138   - const sonValues: any = reactive({
139   - configuration: {},
140   - });
141   - const [register, { validate, setFieldsValue, resetFields: defineClearFunc }] = useForm({
142   - labelWidth: 120,
143   - schemas: modeMqttForm,
144   - actionColOptions: {
145   - span: 14,
146   - },
147   - resetButtonOptions: {
148   - text: '上一步',
149   - },
150   - resetFunc: customResetFunc,
151   - submitFunc: customSubmitFunc,
152   - });
153   -
154   - /**
155   - * 上传图片
156   - */
157   - const handleChange = async (e, { file }) => {
158   - if (file.status === 'removed') {
159   - if (e == 'T') {
160   - fileList1.value = [];
161   - showImg1.value = false;
162   - showImg1Pic.value = '';
163   - caCertFileName.value = '';
164   - } else if (e == 'F') {
165   - fileList2.value = [];
166   - showImg2.value = false;
167   - showImg2Pic.value = '';
168   - certFileName.value = '';
169   - } else {
170   - fileList3.value = [];
171   - showImg3.value = false;
172   - showImg3Pic.value = '';
173   - privateKeyFileName.value = '';
174   - }
175   - } else {
176   - const isLt5M = file.size / 1024 / 1024 < 5;
177   - if (!isLt5M) {
178   - createMessage.error('图片大小不能超过5MB!');
179   - } else {
180   - e == 'T'
181   - ? (fileList1.value = [file])
182   - : e == 'F'
183   - ? (fileList2.value = [file])
184   - : (fileList3.value = [file]);
185   - const formData = new FormData();
186   - formData.append('file', file);
187   - const response = await uploadApi(formData);
188   - if (response.fileStaticUri) {
189   - if (e == 'T') {
190   - caCertFileName.value = response.fileStaticUri;
191   - const iscaCertFileNamePic = caCertFileName.value.split('.').pop();
192   - if (
193   - iscaCertFileNamePic == 'jpg' ||
194   - iscaCertFileNamePic == 'png' ||
195   - iscaCertFileNamePic == 'jpeg' ||
196   - iscaCertFileNamePic == 'gif'
197   - ) {
198   - showImg1.value = true;
199   - showImg1Pic.value = response.fileStaticUri;
200   - } else {
201   - showImg1.value = false;
202   - }
203   - } else if (e == 'F') {
204   - certFileName.value = response.fileStaticUri;
205   - const iscertFileNamePic = certFileName.value.split('.').pop();
206   - if (
207   - iscertFileNamePic == 'jpg' ||
208   - iscertFileNamePic == 'png' ||
209   - iscertFileNamePic == 'jpeg' ||
210   - iscertFileNamePic == 'gif'
211   - ) {
212   - showImg2.value = true;
213   - showImg2Pic.value = response.fileStaticUri;
214   - } else {
215   - showImg2.value = false;
216   - }
217   - } else {
218   - privateKeyFileName.value = response.fileStaticUri;
219   - const isprivateKeyFileNamePic = privateKeyFileName.value.split('.').pop();
220   - if (
221   - isprivateKeyFileNamePic == 'jpg' ||
222   - isprivateKeyFileNamePic == 'png' ||
223   - isprivateKeyFileNamePic == 'jpeg' ||
224   - isprivateKeyFileNamePic == 'gif'
225   - ) {
226   - showImg3.value = true;
227   - showImg3Pic.value = response.fileStaticUri;
228   - } else {
229   - showImg3.value = false;
230   - }
231   - }
232   - }
233   - }
234   - }
235   - };
236   - const setStepTwoFieldsValueFunc = (v, v1, v2) => {
237   - setFieldsValue(v);
238   - setFieldsValue({
239   - name: v1,
240   - description: v2,
241   - });
242   - setFieldsValue({
243   - password: v.credentials?.password,
244   - username: v.credentials?.username,
245   - type: v.credentials?.type,
246   - });
247   - fileList1.value = [
248   - {
249   - name: v.credentials?.caCertFileName.slice(39),
250   - uid: '1',
251   - },
252   - ];
253   - fileList2.value = [
254   - {
255   - name: v.credentials?.certFileName.slice(39),
256   - uid: '2',
257   - },
258   - ];
259   - fileList3.value = [
260   - {
261   - name: v.credentials?.privateKeyFileName.slice(39),
262   - uid: '3',
263   - },
264   - ];
265   - caCertFileName.value = v.credentials?.caCertFileName;
266   - certFileName.value = v.credentials?.certFileName;
267   - privateKeyFileName.value = v.credentials?.privateKeyFileName;
268   - const iscaCertFileNamePic = v.credentials?.caCertFileName.split('.').pop();
269   - const iscertFileNamePic = v.credentials?.certFileName.split('.').pop();
270   - const isprivateKeyFileNamePic = v.credentials?.privateKeyFileName.split('.').pop();
271   - if (
272   - iscaCertFileNamePic == 'jpg' ||
273   - iscaCertFileNamePic == 'png' ||
274   - iscaCertFileNamePic == 'jpeg' ||
275   - iscaCertFileNamePic == 'gif'
276   - ) {
277   - showImg1.value = true;
278   - showImg1Pic.value = v.credentials?.caCertFileName;
279   - } else {
280   - showImg1.value = false;
281   - }
282   - if (
283   - iscertFileNamePic == 'jpg' ||
284   - iscertFileNamePic == 'png' ||
285   - iscertFileNamePic == 'jpeg' ||
286   - iscertFileNamePic == 'gif'
287   - ) {
288   - showImg2.value = true;
289   - showImg2Pic.value = v.credentials?.certFileName;
290   - } else {
291   - showImg2.value = false;
292   - }
293   - if (
294   - isprivateKeyFileNamePic == 'jpg' ||
295   - isprivateKeyFileNamePic == 'png' ||
296   - isprivateKeyFileNamePic == 'jpeg' ||
297   - isprivateKeyFileNamePic == 'gif'
298   - ) {
299   - showImg3.value = true;
300   - showImg3Pic.value = v.credentials?.privateKeyFileName;
301   - } else {
302   - showImg3.value = false;
303   - }
304   - };
305   - const customClearStepTwoValueFunc = async () => {
306   - nextTick(() => {
307   - defineClearFunc();
308   - fileList1.value = [];
309   - fileList2.value = [];
310   - fileList3.value = [];
311   - caCertFileName.value = '';
312   - privateKeyFileName.value = '';
313   - certFileName.value = '';
314   - showImg1.value = false;
315   - showImg1Pic.value = '';
316   - showImg2.value = false;
317   - showImg2Pic.value = '';
318   - showImg3.value = false;
319   - showImg3Pic.value = '';
320   - });
321   - };
322   - async function customResetFunc() {
323   - emit('prev');
324   - }
325   - async function customSubmitFunc() {
326   - try {
327   - const values = await validate();
328   - emit('next', values);
329   - } catch (error) {
330   - } finally {
331   - }
332   - }
333   - const getSonValueFunc = async () => {
334   - sonValues.configuration = await validate();
335   - credentialsV.credentials.type = sonValues.configuration.type;
336   - if (credentialsV.credentials.type == CredentialsEnum.IS_BASIC) {
337   - credentialsV.credentials.username = sonValues.configuration.username;
338   - credentialsV.credentials.password = sonValues.configuration.password;
339   - sonValues.configuration.username = undefined;
340   - sonValues.configuration.password = undefined;
341   - } else if (credentialsV.credentials.type == CredentialsEnum.IS_PEM) {
342   - credentialsV.credentials.caCertFileName = caCertFileName.value;
343   - credentialsV.credentials.certFileName = certFileName.value;
344   - credentialsV.credentials.privateKeyFileName = privateKeyFileName.value;
345   - }
346   - if (!sonValues.configuration.clientId) {
347   - sonValues.configuration.clientId = null;
348   - }
349   - Object.assign(sonValues.configuration, credentialsV);
350   - return sonValues;
351   - };
352   - return {
353   - getSonValueFunc,
354   - register,
355   - setStepTwoFieldsValueFunc,
356   - customClearStepTwoValueFunc,
357   - fileList1,
358   - fileList2,
359   - fileList3,
360   - handleChange,
361   - caCertFileName,
362   - privateKeyFileName,
363   - certFileName,
364   - showImg1,
365   - showImg1Pic,
366   - showImg2,
367   - showImg2Pic,
368   - showImg3,
369   - showImg3Pic,
370   - };
371   - },
372   - });
373   -</script>
374   -
375   -<style lang="less" scoped>
376   - :deep(.ant-col-24) {
377   - margin-bottom: 20px !important;
378   - }
379   -
380   - :deep(.ant-btn-default) {
381   - color: white;
382   - background: #377dff;
383   - }
384   -</style>
... ... @@ -201,14 +201,18 @@
201 201 ];
202 202 });
203 203
204   - const changeOutTarget = () => {
  204 + const changeOutTarget = (e) => {
  205 + if (!e) validateFields(['outTarget']);
  206 + else clearValidate('outTarget');
205 207 emit('getActionFormArr');
206 208 };
207   - const [registerAction, { getFieldsValue, resetFields, setFieldsValue, validate, setProps }] =
208   - useForm({
209   - schemas: actionSchema,
210   - showActionButtonGroup: false,
211   - });
  209 + const [
  210 + registerAction,
  211 + { getFieldsValue, resetFields, setFieldsValue, validate, clearValidate, validateFields },
  212 + ] = useForm({
  213 + schemas: actionSchema,
  214 + showActionButtonGroup: false,
  215 + });
212 216
213 217 // 获取整个执行动作表单值
214 218 const getFieldsValueFunc = () => {
... ...
... ... @@ -114,7 +114,7 @@
114 114 </div>
115 115 </template>
116 116 <script setup lang="ts">
117   - import { ref, unref, reactive, onMounted, toRefs, computed } from 'vue';
  117 + import { ref, unref, reactive, onMounted, toRefs, computed, nextTick } from 'vue';
118 118 import ace from 'ace-builds';
119 119 import { Card, Button, Tooltip } from 'ant-design-vue';
120 120 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
... ... @@ -323,7 +323,19 @@
323 323 };
324 324
325 325 const setDisableRadio = (value) => {
326   - reportTypeOptions.scriptTypeOptions.forEach((item: any) => {
  326 + //查看和表格里面的测试点击禁用脚本类型
  327 + unref(reportTypeOptions.scriptTypeOptions).forEach((item: any) => {
  328 + if (item.value === value) item.disabled = false;
  329 + else item.disabled = true;
  330 + });
  331 + };
  332 +
  333 + const setDisableTestRadio = async (value) => {
  334 + //内部弹窗,使用上面的setDisableRadio无效
  335 + //新增里面的测试点击禁用脚本类型
  336 + await getScriptType();
  337 + await nextTick();
  338 + unref(reportTypeOptions.scriptTypeOptions).forEach((item: any) => {
327 339 if (item.value === value) item.disabled = false;
328 340 else item.disabled = true;
329 341 });
... ... @@ -336,6 +348,7 @@
336 348 setScriptOutputData,
337 349 setDefaultRadio,
338 350 setDisableRadio,
  351 + setDisableTestRadio,
339 352 });
340 353 </script>
341 354 <style lang="less" scoped>
... ...
... ... @@ -56,7 +56,15 @@
56 56 if (!data.innerTest) {
57 57 const rest = await getScriptManageDetail(data.record?.id);
58 58 converScriptFormRef.value?.setFormData(rest);
59   - } else converScriptFormRef.value?.setFormData(data.record);
  59 + if (data.text !== BusinessConvertScriptTextEnum.BUSINESS_EDIT_TEXT) {
  60 + //编辑是不能禁用脚本类型的
  61 + converScriptFormRef.value?.setDisableRadio(data.record.scriptType);
  62 + }
  63 + } else {
  64 + //从新增页面里点击的测试,禁用脚本类型
  65 + converScriptFormRef.value?.setFormData(data.record);
  66 + converScriptFormRef.value?.setDisableTestRadio(data.record.scriptType);
  67 + }
60 68 if (data.scriptType) {
61 69 converScriptFormRef.value?.setDisableRadio(data.scriptType);
62 70 }
... ...
... ... @@ -18,6 +18,7 @@
18 18 ref="basicTreeRef"
19 19 checkable
20 20 toolbar
  21 + @change="handleTreeSelect"
21 22 />
22 23 </template>
23 24 <template #roleSlot="{ model, field }">
... ... @@ -26,6 +27,7 @@
26 27 allowClear
27 28 placeholder="请选择角色"
28 29 v-model:value="model[field]"
  30 + @change="handleRoleSelect"
29 31 :options="roleOptions.map((item) => ({ value: item.value, label: item.label }))"
30 32 >
31 33 <template #dropdownRender="{ menuNode: menu }">
... ... @@ -108,12 +110,30 @@
108 110 isUpdate: false,
109 111 });
110 112 };
  113 + const clearValidateByField = (field: string) => {
  114 + clearValidate(field);
  115 + };
  116 + const handleRoleSelect = (e) => {
  117 + if (e?.length > 0) clearValidateByField('roleIds');
  118 + else validateFields(['roleIds']);
  119 + };
  120 + const handleTreeSelect = (e) => {
  121 + if (e) clearValidateByField('organizationIds');
  122 + };
111 123 const handleSuccess = async () => {
112 124 await getRoleList();
113 125 };
114 126 const [
115 127 registerForm,
116   - { setFieldsValue, updateSchema, resetFields, validate, getFieldsValue },
  128 + {
  129 + setFieldsValue,
  130 + updateSchema,
  131 + resetFields,
  132 + validate,
  133 + getFieldsValue,
  134 + clearValidate,
  135 + validateFields,
  136 + },
117 137 ] = useForm({
118 138 labelWidth: 100,
119 139 schemas: accountFormSchema,
... ... @@ -225,6 +245,8 @@
225 245 registerRoleDrawer,
226 246 handleOpenRole,
227 247 handleSuccess,
  248 + handleRoleSelect,
  249 + handleTreeSelect,
228 250 };
229 251 },
230 252 });
... ...
... ... @@ -43,11 +43,11 @@
43 43 },
44 44 {
45 45 field: 'username',
46   - label: '账号',
  46 + label: '用户名',
47 47 component: 'Input',
48 48 componentProps: {
49 49 maxLength: 64,
50   - placeholder: '请输入账号',
  50 + placeholder: '请输入用户名',
51 51 },
52 52 dynamicRules: ({ values }) => {
53 53 try {
... ... @@ -62,14 +62,13 @@
62 62 validator(_, value) {
63 63 return new Promise((resolve, reject) => {
64 64 if (value == '' || value === undefined) {
65   - reject('请输入账号');
  65 + reject('请输入用户名');
66 66 } else if (ChineseRegexp.test(value)) {
67   - reject('账号不能含有中文');
  67 + reject('用户名不能含有中文');
68 68 } else if (EmailRegexp.test(value)) {
69   - reject('账号不能为电子邮箱格式');
  69 + reject('用户名不能为电子邮箱格式');
70 70 } else if (findUserName && value == findUserName?.username) {
71   - console.log(1111111111);
72   - reject('账号已存在');
  71 + reject('用户名已存在');
73 72 return;
74 73 } else {
75 74 resolve();
... ...
... ... @@ -7,50 +7,25 @@
7 7 width="500px"
8 8 @ok="handleSubmit"
9 9 >
10   - <BasicForm @register="tenantForm">
11   - <template #iconSelect>
12   - <Upload
13   - name="avatar"
14   - accept=".png,.jpg,.jpeg,.gif"
15   - list-type="picture-card"
16   - class="avatar-uploader"
17   - :show-upload-list="false"
18   - :customRequest="customUpload"
19   - :before-upload="beforeUpload"
20   - >
21   - <img v-if="tenantLogo" :src="tenantLogo" alt="avatar" />
22   - <div v-else>
23   - <LoadingOutlined v-if="loading" />
24   - <plus-outlined v-else />
25   - <div class="ant-upload-text">上传</div>
26   - </div>
27   - </Upload>
28   - </template>
29   - </BasicForm>
  10 + <BasicForm @register="tenantForm" />
30 11 </BasicDrawer>
31 12 </template>
32 13 <script lang="ts">
33 14 import { defineComponent, ref, computed, unref } from 'vue';
34 15 import { BasicForm, useForm } from '/@/components/Form/index';
35 16 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
36   - import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';
37   - import { message, Upload } from 'ant-design-vue';
38   -
39 17 import { useI18n } from '/@/hooks/web/useI18n';
40 18 import { tenantFormSchema } from '/@/views/tenant/list/tenantBaseColumns';
41   - import { FileItem } from '/@/components/Upload/src/typing';
42   - import { upload } from '/@/api/oss/ossFileUploader';
43 19 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi';
44 20 import { useMessage } from '/@/hooks/web/useMessage';
  21 + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  22 + import { buildUUID } from '/@/utils/uuid';
45 23
46 24 export default defineComponent({
47 25 name: 'TenantDrawer',
48 26 components: {
49 27 BasicDrawer,
50 28 BasicForm,
51   - Upload,
52   - PlusOutlined,
53   - LoadingOutlined,
54 29 },
55 30 emits: ['success', 'register'],
56 31 setup(_, { emit }) {
... ... @@ -58,33 +33,7 @@
58 33 const { createMessage } = useMessage();
59 34
60 35 const isUpdate = ref(true);
61   - const tenantLogo = ref('');
62   -
63   - async function customUpload({ file }) {
64   - if (beforeUpload(file)) {
65   - tenantLogo.value = '';
66   - loading.value = true;
67   - const formData = new FormData();
68   - formData.append('file', file);
69   - const response = await upload(formData);
70   - if (response.fileStaticUri) {
71   - tenantLogo.value = response.fileStaticUri;
72   - loading.value = false;
73   - }
74   - }
75   - }
76 36
77   - const beforeUpload = (file: FileItem) => {
78   - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
79   - if (!isJpgOrPng) {
80   - message.error('只能上传图片文件!');
81   - }
82   - const isLt2M = (file.size as number) / 1024 / 1024 < 5;
83   - if (!isLt2M) {
84   - message.error('图片大小不能超过5MB!');
85   - }
86   - return isJpgOrPng && isLt2M;
87   - };
88 37 const [tenantForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
89 38 labelWidth: 100,
90 39 schemas: tenantFormSchema,
... ... @@ -96,7 +45,6 @@
96 45 //默认传递页面数据
97 46 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
98 47 await resetFields();
99   - tenantLogo.value = '';
100 48 setDrawerProps({ confirmLoading: false });
101 49 isUpdate.value = !!data?.isUpdate;
102 50
... ... @@ -104,11 +52,19 @@
104 52 await updateSchema({ field: 'title', componentProps: { disabled: false } });
105 53 //如果是编辑操作,设置页面数据
106 54 if (unref(isUpdate)) {
  55 + if (data.record.icon) {
  56 + setFieldsValue({
  57 + icon: [{ uid: buildUUID(), name: 'name', url: data.record.icon } as FileItem],
  58 + });
  59 + }
107 60 getTenantRoles(data.record.tenantId).then((result) => {
108   - Reflect.set(data.record, 'roleIds', result);
  61 + const { icon, ...params } = data.record;
  62 + console.log(icon);
109 63 //为表单赋值
110   - setFieldsValue(data.record);
111   - tenantLogo.value = data.record.icon;
  64 + setFieldsValue({
  65 + ...params,
  66 + roleIds: result,
  67 + });
112 68 //编辑模式,菜单名称为不可用
113 69 updateSchema({ field: 'title', componentProps: { disabled: true } });
114 70 });
... ... @@ -126,9 +82,13 @@
126 82 setDrawerProps({ confirmLoading: true });
127 83 try {
128 84 const values = await validate();
  85 + if (Reflect.has(values, 'icon')) {
  86 + const file = (values.icon || []).at(0) || {};
  87 + values.icon = file.url || null;
  88 + }
129 89 const req = {
130 90 id: values.id,
131   - icon: tenantLogo.value,
  91 + icon: values.icon,
132 92 name: values.name,
133 93 enabled: values.enabled,
134 94 description: values.description,
... ... @@ -161,9 +121,6 @@
161 121 tenantForm,
162 122 getTitle,
163 123 handleSubmit,
164   - tenantLogo,
165   - beforeUpload,
166   - customUpload,
167 124 loading,
168 125 };
169 126 },
... ...
... ... @@ -3,6 +3,9 @@ import { FormSchema } from '/@/components/Form';
3 3 import { getAllRoleList } from '/@/api/system/system';
4 4 import { getTableTenantProfileApi, QueryTenantProfilesParam } from '/@/api/tenant/tenantApi';
5 5 import { RoleEnum } from '/@/enums/roleEnum';
  6 +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue';
  7 +import { createImgPreview } from '/@/components/Preview';
  8 +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';
6 9
7 10 export function getBasicColumns(): BasicColumn[] {
8 11 return [
... ... @@ -77,23 +80,32 @@ export const tenantFormSchema: FormSchema[] = [
77 80 {
78 81 field: 'icon',
79 82 label: '租户图标',
80   - slot: 'iconSelect',
81   - component: 'Input',
82   - componentProps: {
83   - maxLength: 255,
84   - },
85   - dynamicRules: () => {
86   - return [
87   - {
88   - required: false,
89   - validator: (_, value) => {
90   - if (String(value).length > 255) {
91   - return Promise.reject('字数不超过255个字');
92   - }
93   - return Promise.resolve();
94   - },
  83 + component: 'ApiUpload',
  84 + changeEvent: 'update:fileList',
  85 + valueField: 'fileList',
  86 + componentProps: () => {
  87 + return {
  88 + listType: 'picture-card',
  89 + maxFileLimit: 1,
  90 + accept: '.png,.jpg,.jpeg,.gif',
  91 + api: async (file: File) => {
  92 + try {
  93 + const formData = new FormData();
  94 + formData.set('file', file);
  95 + const { fileStaticUri, fileName } = await uploadThumbnail(formData);
  96 + return {
  97 + uid: fileStaticUri,
  98 + name: fileName,
  99 + url: fileStaticUri,
  100 + } as FileItem;
  101 + } catch (error) {
  102 + return {};
  103 + }
95 104 },
96   - ];
  105 + onPreview: (fileList: FileItem) => {
  106 + createImgPreview({ imageList: [fileList.url!] });
  107 + },
  108 + };
97 109 },
98 110 },
99 111 {
... ...