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,7 +25,7 @@ module.exports = defineConfig({
25 'plugin:jest/recommended', 25 'plugin:jest/recommended',
26 ], 26 ],
27 rules: { 27 rules: {
28 - 'no-console': 'error', 28 + 'no-console': 'off',
29 'vue/script-setup-uses-vars': 'error', 29 'vue/script-setup-uses-vars': 'error',
30 '@typescript-eslint/ban-ts-ignore': 'off', 30 '@typescript-eslint/ban-ts-ignore': 'off',
31 '@typescript-eslint/explicit-function-return-type': 'off', 31 '@typescript-eslint/explicit-function-return-type': 'off',
@@ -394,6 +394,13 @@ @@ -394,6 +394,13 @@
394 //.ant-table-tbody > tr.ant-table-row-selected td { 394 //.ant-table-tbody > tr.ant-table-row-selected td {
395 //background-color: fade(@primary-color, 8%) !important; 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 .ant-pagination { 406 .ant-pagination {
@@ -20,6 +20,12 @@ @@ -20,6 +20,12 @@
20 import { useFingerprint } from '/@/utils/useFingerprint'; 20 import { useFingerprint } from '/@/utils/useFingerprint';
21 import { GetResult } from '@fingerprintjs/fingerprintjs'; 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 type CameraRecordItem = CameraRecord & { 29 type CameraRecordItem = CameraRecord & {
24 canPlay?: boolean; 30 canPlay?: boolean;
25 isTransform?: boolean; 31 isTransform?: boolean;
@@ -252,7 +258,11 @@ @@ -252,7 +258,11 @@
252 </Authority> 258 </Authority>
253 </div> 259 </div>
254 <Space> 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 </Button> 267 </Button>
258 <Button type="primary" @click="handleChangeMode(PageMode.LIST_MODE)"> 268 <Button type="primary" @click="handleChangeMode(PageMode.LIST_MODE)">
@@ -12,7 +12,11 @@ @@ -12,7 +12,11 @@
12 12
13 <template> 13 <template>
14 <div> 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 <ListMode v-if="mode === PageMode.LIST_MODE" @switchMode="handleSwitchMode" /> 20 <ListMode v-if="mode === PageMode.LIST_MODE" @switchMode="handleSwitchMode" />
17 </div> 21 </div>
18 </template> 22 </template>
@@ -131,14 +131,19 @@ export const formSchema: FormSchema[] = [ @@ -131,14 +131,19 @@ export const formSchema: FormSchema[] = [
131 onChange: async (value) => { 131 onChange: async (value) => {
132 const res = await findMessageConfig({}); 132 const res = await findMessageConfig({});
133 let typeId: Nullable<string> = null; 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 await formActionType.setFieldsValue({ messageConfigId: typeId }); 147 await formActionType.setFieldsValue({ messageConfigId: typeId });
143 await formActionType.updateSchema({ 148 await formActionType.updateSchema({
144 field: 'messageConfigId', 149 field: 'messageConfigId',
@@ -155,14 +160,25 @@ export const formSchema: FormSchema[] = [ @@ -155,14 +160,25 @@ export const formSchema: FormSchema[] = [
155 label: '配置名称', 160 label: '配置名称',
156 required: true, 161 required: true,
157 component: 'ApiSelect', 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,14 +465,15 @@ export const formSchema: BFormSchema[] = [
465 }, 465 },
466 { 466 {
467 field: 'dateGroupGap', 467 field: 'dateGroupGap',
468 - label: '分组间隔', 468 + label: '间隔时间',
469 component: 'Select', 469 component: 'Select',
470 colProps: { span: 24 }, 470 colProps: { span: 24 },
471 - dynamicRules: ({ model }) => { 471 + dynamicRules: () => {
472 return [ 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 type: 'number', 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,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 emit('getActionFormArr'); 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 const getFieldsValueFunc = () => { 218 const getFieldsValueFunc = () => {
@@ -114,7 +114,7 @@ @@ -114,7 +114,7 @@
114 </div> 114 </div>
115 </template> 115 </template>
116 <script setup lang="ts"> 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 import ace from 'ace-builds'; 118 import ace from 'ace-builds';
119 import { Card, Button, Tooltip } from 'ant-design-vue'; 119 import { Card, Button, Tooltip } from 'ant-design-vue';
120 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题 120 import 'ace-builds/src-noconflict/theme-chrome'; // 默认设置的主题
@@ -323,7 +323,19 @@ @@ -323,7 +323,19 @@
323 }; 323 };
324 324
325 const setDisableRadio = (value) => { 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 if (item.value === value) item.disabled = false; 339 if (item.value === value) item.disabled = false;
328 else item.disabled = true; 340 else item.disabled = true;
329 }); 341 });
@@ -336,6 +348,7 @@ @@ -336,6 +348,7 @@
336 setScriptOutputData, 348 setScriptOutputData,
337 setDefaultRadio, 349 setDefaultRadio,
338 setDisableRadio, 350 setDisableRadio,
  351 + setDisableTestRadio,
339 }); 352 });
340 </script> 353 </script>
341 <style lang="less" scoped> 354 <style lang="less" scoped>
@@ -56,7 +56,15 @@ @@ -56,7 +56,15 @@
56 if (!data.innerTest) { 56 if (!data.innerTest) {
57 const rest = await getScriptManageDetail(data.record?.id); 57 const rest = await getScriptManageDetail(data.record?.id);
58 converScriptFormRef.value?.setFormData(rest); 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 if (data.scriptType) { 68 if (data.scriptType) {
61 converScriptFormRef.value?.setDisableRadio(data.scriptType); 69 converScriptFormRef.value?.setDisableRadio(data.scriptType);
62 } 70 }
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 ref="basicTreeRef" 18 ref="basicTreeRef"
19 checkable 19 checkable
20 toolbar 20 toolbar
  21 + @change="handleTreeSelect"
21 /> 22 />
22 </template> 23 </template>
23 <template #roleSlot="{ model, field }"> 24 <template #roleSlot="{ model, field }">
@@ -26,6 +27,7 @@ @@ -26,6 +27,7 @@
26 allowClear 27 allowClear
27 placeholder="请选择角色" 28 placeholder="请选择角色"
28 v-model:value="model[field]" 29 v-model:value="model[field]"
  30 + @change="handleRoleSelect"
29 :options="roleOptions.map((item) => ({ value: item.value, label: item.label }))" 31 :options="roleOptions.map((item) => ({ value: item.value, label: item.label }))"
30 > 32 >
31 <template #dropdownRender="{ menuNode: menu }"> 33 <template #dropdownRender="{ menuNode: menu }">
@@ -108,12 +110,30 @@ @@ -108,12 +110,30 @@
108 isUpdate: false, 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 const handleSuccess = async () => { 123 const handleSuccess = async () => {
112 await getRoleList(); 124 await getRoleList();
113 }; 125 };
114 const [ 126 const [
115 registerForm, 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 ] = useForm({ 137 ] = useForm({
118 labelWidth: 100, 138 labelWidth: 100,
119 schemas: accountFormSchema, 139 schemas: accountFormSchema,
@@ -225,6 +245,8 @@ @@ -225,6 +245,8 @@
225 registerRoleDrawer, 245 registerRoleDrawer,
226 handleOpenRole, 246 handleOpenRole,
227 handleSuccess, 247 handleSuccess,
  248 + handleRoleSelect,
  249 + handleTreeSelect,
228 }; 250 };
229 }, 251 },
230 }); 252 });
@@ -43,11 +43,11 @@ @@ -43,11 +43,11 @@
43 }, 43 },
44 { 44 {
45 field: 'username', 45 field: 'username',
46 - label: '账号', 46 + label: '用户名',
47 component: 'Input', 47 component: 'Input',
48 componentProps: { 48 componentProps: {
49 maxLength: 64, 49 maxLength: 64,
50 - placeholder: '请输入账号', 50 + placeholder: '请输入用户名',
51 }, 51 },
52 dynamicRules: ({ values }) => { 52 dynamicRules: ({ values }) => {
53 try { 53 try {
@@ -62,14 +62,13 @@ @@ -62,14 +62,13 @@
62 validator(_, value) { 62 validator(_, value) {
63 return new Promise((resolve, reject) => { 63 return new Promise((resolve, reject) => {
64 if (value == '' || value === undefined) { 64 if (value == '' || value === undefined) {
65 - reject('请输入账号'); 65 + reject('请输入用户名');
66 } else if (ChineseRegexp.test(value)) { 66 } else if (ChineseRegexp.test(value)) {
67 - reject('账号不能含有中文'); 67 + reject('用户名不能含有中文');
68 } else if (EmailRegexp.test(value)) { 68 } else if (EmailRegexp.test(value)) {
69 - reject('账号不能为电子邮箱格式'); 69 + reject('用户名不能为电子邮箱格式');
70 } else if (findUserName && value == findUserName?.username) { 70 } else if (findUserName && value == findUserName?.username) {
71 - console.log(1111111111);  
72 - reject('账号已存在'); 71 + reject('用户名已存在');
73 return; 72 return;
74 } else { 73 } else {
75 resolve(); 74 resolve();
@@ -7,50 +7,25 @@ @@ -7,50 +7,25 @@
7 width="500px" 7 width="500px"
8 @ok="handleSubmit" 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 </BasicDrawer> 11 </BasicDrawer>
31 </template> 12 </template>
32 <script lang="ts"> 13 <script lang="ts">
33 import { defineComponent, ref, computed, unref } from 'vue'; 14 import { defineComponent, ref, computed, unref } from 'vue';
34 import { BasicForm, useForm } from '/@/components/Form/index'; 15 import { BasicForm, useForm } from '/@/components/Form/index';
35 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 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 import { useI18n } from '/@/hooks/web/useI18n'; 17 import { useI18n } from '/@/hooks/web/useI18n';
40 import { tenantFormSchema } from '/@/views/tenant/list/tenantBaseColumns'; 18 import { tenantFormSchema } from '/@/views/tenant/list/tenantBaseColumns';
41 - import { FileItem } from '/@/components/Upload/src/typing';  
42 - import { upload } from '/@/api/oss/ossFileUploader';  
43 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi'; 19 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi';
44 import { useMessage } from '/@/hooks/web/useMessage'; 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 export default defineComponent({ 24 export default defineComponent({
47 name: 'TenantDrawer', 25 name: 'TenantDrawer',
48 components: { 26 components: {
49 BasicDrawer, 27 BasicDrawer,
50 BasicForm, 28 BasicForm,
51 - Upload,  
52 - PlusOutlined,  
53 - LoadingOutlined,  
54 }, 29 },
55 emits: ['success', 'register'], 30 emits: ['success', 'register'],
56 setup(_, { emit }) { 31 setup(_, { emit }) {
@@ -58,33 +33,7 @@ @@ -58,33 +33,7 @@
58 const { createMessage } = useMessage(); 33 const { createMessage } = useMessage();
59 34
60 const isUpdate = ref(true); 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 const [tenantForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({ 37 const [tenantForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
89 labelWidth: 100, 38 labelWidth: 100,
90 schemas: tenantFormSchema, 39 schemas: tenantFormSchema,
@@ -96,7 +45,6 @@ @@ -96,7 +45,6 @@
96 //默认传递页面数据 45 //默认传递页面数据
97 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { 46 const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
98 await resetFields(); 47 await resetFields();
99 - tenantLogo.value = '';  
100 setDrawerProps({ confirmLoading: false }); 48 setDrawerProps({ confirmLoading: false });
101 isUpdate.value = !!data?.isUpdate; 49 isUpdate.value = !!data?.isUpdate;
102 50
@@ -104,11 +52,19 @@ @@ -104,11 +52,19 @@
104 await updateSchema({ field: 'title', componentProps: { disabled: false } }); 52 await updateSchema({ field: 'title', componentProps: { disabled: false } });
105 //如果是编辑操作,设置页面数据 53 //如果是编辑操作,设置页面数据
106 if (unref(isUpdate)) { 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 getTenantRoles(data.record.tenantId).then((result) => { 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 updateSchema({ field: 'title', componentProps: { disabled: true } }); 69 updateSchema({ field: 'title', componentProps: { disabled: true } });
114 }); 70 });
@@ -126,9 +82,13 @@ @@ -126,9 +82,13 @@
126 setDrawerProps({ confirmLoading: true }); 82 setDrawerProps({ confirmLoading: true });
127 try { 83 try {
128 const values = await validate(); 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 const req = { 89 const req = {
130 id: values.id, 90 id: values.id,
131 - icon: tenantLogo.value, 91 + icon: values.icon,
132 name: values.name, 92 name: values.name,
133 enabled: values.enabled, 93 enabled: values.enabled,
134 description: values.description, 94 description: values.description,
@@ -161,9 +121,6 @@ @@ -161,9 +121,6 @@
161 tenantForm, 121 tenantForm,
162 getTitle, 122 getTitle,
163 handleSubmit, 123 handleSubmit,
164 - tenantLogo,  
165 - beforeUpload,  
166 - customUpload,  
167 loading, 124 loading,
168 }; 125 };
169 }, 126 },
@@ -3,6 +3,9 @@ import { FormSchema } from '/@/components/Form'; @@ -3,6 +3,9 @@ import { FormSchema } from '/@/components/Form';
3 import { getAllRoleList } from '/@/api/system/system'; 3 import { getAllRoleList } from '/@/api/system/system';
4 import { getTableTenantProfileApi, QueryTenantProfilesParam } from '/@/api/tenant/tenantApi'; 4 import { getTableTenantProfileApi, QueryTenantProfilesParam } from '/@/api/tenant/tenantApi';
5 import { RoleEnum } from '/@/enums/roleEnum'; 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 export function getBasicColumns(): BasicColumn[] { 10 export function getBasicColumns(): BasicColumn[] {
8 return [ 11 return [
@@ -77,23 +80,32 @@ export const tenantFormSchema: FormSchema[] = [ @@ -77,23 +80,32 @@ export const tenantFormSchema: FormSchema[] = [
77 { 80 {
78 field: 'icon', 81 field: 'icon',
79 label: '租户图标', 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 {