Commit d7c4e079fbc08bfd26069ba6398213f28a5df646
Merge branch 'fix/DEFECT-2291' into 'main_dev'
fix: 看板组件图标能使用自定义图标 See merge request yunteng/thingskit-front!1432
Showing
18 changed files
with
788 additions
and
102 deletions
@@ -71,9 +71,12 @@ | @@ -71,9 +71,12 @@ | ||
71 | return false; | 71 | return false; |
72 | } | 72 | } |
73 | } | 73 | } |
74 | - | ||
75 | if (file.size > props.maxSize) { | 74 | if (file.size > props.maxSize) { |
76 | - createMessage.warning(`文件大小超过${Math.floor(props.maxSize / 1024 / 1024)}mb`); | 75 | + createMessage.warning( |
76 | + `文件大小超过${Math.floor( | ||
77 | + props.maxSize > 1024 * 1024 ? props.maxSize / 1024 / 1024 : props.maxSize / 1024 | ||
78 | + )}${props.maxSize > 1024 * 1024 * 1 ? 'mb' : 'kb'}` | ||
79 | + ); | ||
77 | return false; | 80 | return false; |
78 | } | 81 | } |
79 | handleUpload(file); | 82 | handleUpload(file); |
@@ -30,7 +30,7 @@ | @@ -30,7 +30,7 @@ | ||
30 | auth: 'api:yt:sceneLinkage:update', | 30 | auth: 'api:yt:sceneLinkage:update', |
31 | icon: 'clarity:note-edit-line', | 31 | icon: 'clarity:note-edit-line', |
32 | onClick: handleEdit.bind(null, record), | 32 | onClick: handleEdit.bind(null, record), |
33 | - ifShow: record.status !== 1 && record.isEdge !== 1, | 33 | + ifShow: record.status !== 1, |
34 | }, | 34 | }, |
35 | ]" | 35 | ]" |
36 | :drop-down-actions="[ | 36 | :drop-down-actions="[ |
@@ -39,7 +39,7 @@ | @@ -39,7 +39,7 @@ | ||
39 | auth: 'api:yt:sceneLinkage:delete', | 39 | auth: 'api:yt:sceneLinkage:delete', |
40 | icon: 'ant-design:delete-outlined', | 40 | icon: 'ant-design:delete-outlined', |
41 | color: 'error', | 41 | color: 'error', |
42 | - ifShow: record.status !== 1 && record.isEdge !== 1, | 42 | + ifShow: record.status !== 1, |
43 | popConfirm: { | 43 | popConfirm: { |
44 | title: '是否确认删除', | 44 | title: '是否确认删除', |
45 | confirm: handleDeleteOrBatchDelete.bind(null, record), | 45 | confirm: handleDeleteOrBatchDelete.bind(null, record), |
@@ -56,7 +56,6 @@ | @@ -56,7 +56,6 @@ | ||
56 | :loading="record.pendingStatus" | 56 | :loading="record.pendingStatus" |
57 | checkedChildren="启用" | 57 | checkedChildren="启用" |
58 | unCheckedChildren="禁用" | 58 | unCheckedChildren="禁用" |
59 | - :disabled="record.isEdge === 1" | ||
60 | @change="(checked:boolean)=>statusChange(checked,record)" | 59 | @change="(checked:boolean)=>statusChange(checked,record)" |
61 | /> | 60 | /> |
62 | </Authority> | 61 | </Authority> |
@@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
56 | </script> | 56 | </script> |
57 | 57 | ||
58 | <template> | 58 | <template> |
59 | - <BasicModal @register="register" title="组件设置" @ok="handleOk"> | 59 | + <BasicModal @register="register" title="组件设置" @ok="handleOk" :width="700"> |
60 | <!-- --> | 60 | <!-- --> |
61 | <component ref="settingFormEl" :is="getSettingComponent" /> | 61 | <component ref="settingFormEl" :is="getSettingComponent" /> |
62 | </BasicModal> | 62 | </BasicModal> |
@@ -29,6 +29,8 @@ | @@ -29,6 +29,8 @@ | ||
29 | import { MessageAlert } from './components/MessageAlert'; | 29 | import { MessageAlert } from './components/MessageAlert'; |
30 | import { createSelectWidgetKeysContext, createSelectWidgetModeContext } from './useContext'; | 30 | import { createSelectWidgetKeysContext, createSelectWidgetModeContext } from './useContext'; |
31 | import { useGetCategoryByComponentKey } from '../packages/hook/useGetCategoryByComponentKey'; | 31 | import { useGetCategoryByComponentKey } from '../packages/hook/useGetCategoryByComponentKey'; |
32 | + import { deleteFilePath } from '/@/api/oss/ossFileUploader'; | ||
33 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
32 | 34 | ||
33 | const props = defineProps<{ | 35 | const props = defineProps<{ |
34 | layout: Layout[]; | 36 | layout: Layout[]; |
@@ -227,6 +229,20 @@ | @@ -227,6 +229,20 @@ | ||
227 | return `${category} / ${componentConfig.title}`; | 229 | return `${category} / ${componentConfig.title}`; |
228 | }); | 230 | }); |
229 | 231 | ||
232 | + const countElementOccurrences = (arr) => { | ||
233 | + const countMap = {}; | ||
234 | + | ||
235 | + arr.forEach((element) => { | ||
236 | + if (countMap[element]) { | ||
237 | + countMap[element]++; | ||
238 | + } else { | ||
239 | + countMap[element] = 1; | ||
240 | + } | ||
241 | + }); | ||
242 | + | ||
243 | + return countMap; | ||
244 | + }; | ||
245 | + | ||
230 | const handleSubmit = async () => { | 246 | const handleSubmit = async () => { |
231 | const validateResult = await validate(); | 247 | const validateResult = await validate(); |
232 | if (validateResult && !validateResult.flag) { | 248 | if (validateResult && !validateResult.flag) { |
@@ -241,6 +257,59 @@ | @@ -241,6 +257,59 @@ | ||
241 | } | 257 | } |
242 | } | 258 | } |
243 | const value = getFormValues(); | 259 | const value = getFormValues(); |
260 | + const { record } = value || {}; | ||
261 | + try { | ||
262 | + const currentRecordIconUrl = ref<any>([]); | ||
263 | + // 判断当前自定义组件表单以前的自定义图片呢url | ||
264 | + currentRecord.value?.dataSource.forEach((item) => { | ||
265 | + if (item.componentInfo?.customIcon) { | ||
266 | + item.componentInfo?.customIcon.forEach((icon: FileItem) => { | ||
267 | + currentRecordIconUrl.value.push(icon.url); | ||
268 | + }); | ||
269 | + } | ||
270 | + }); | ||
271 | + // 取当前修改过后的自定义图片url | ||
272 | + const dataSourceUrl = record.dataSource?.map( | ||
273 | + (item) => item.componentInfo.customIcon?.[0].url | ||
274 | + ); | ||
275 | + | ||
276 | + // 当前自定义组件取出要进行删除的图标url | ||
277 | + const dataSourceDeleteUrl = unref(currentRecordIconUrl).filter( | ||
278 | + (item) => !dataSourceUrl?.includes(item) | ||
279 | + ); | ||
280 | + | ||
281 | + //查询外部所有组件的自定义图标的url | ||
282 | + const oldDataSource = props.layout; | ||
283 | + const customIconUrls = ref<any>([]); | ||
284 | + oldDataSource?.forEach((item: any) => { | ||
285 | + item.dataSource?.forEach((dataSource) => { | ||
286 | + if (dataSource.componentInfo?.customIcon) { | ||
287 | + dataSource.componentInfo?.customIcon.forEach((icon: FileItem) => { | ||
288 | + customIconUrls.value.push(icon.url); | ||
289 | + }); | ||
290 | + } | ||
291 | + }); | ||
292 | + }); | ||
293 | + // const dataSourceDeleteUrl = record.dataSource?.map((item) => item.componentInfo.deleteUrl); | ||
294 | + | ||
295 | + if (unref(customIconUrls) && unref(customIconUrls).length && dataSourceDeleteUrl?.length) { | ||
296 | + // 判断外部所有组件是否有dataSourceDeleteUrl使用中的url | ||
297 | + const deletePromise = unref(customIconUrls)?.filter((item) => | ||
298 | + dataSourceDeleteUrl?.includes(item) | ||
299 | + ); | ||
300 | + const deleteUrlInfo = countElementOccurrences(deletePromise); | ||
301 | + const deleteUrl = deletePromise?.filter((item) => deleteUrlInfo?.[item] == 1); | ||
302 | + Promise.all( | ||
303 | + deleteUrl.map((item) => { | ||
304 | + deleteFilePath(item); | ||
305 | + }) | ||
306 | + ); | ||
307 | + } | ||
308 | + } catch (err) { | ||
309 | + // eslint-disable-next-line no-console | ||
310 | + console.log(err); | ||
311 | + } | ||
312 | + | ||
244 | try { | 313 | try { |
245 | loading.value = true; | 314 | loading.value = true; |
246 | unref(currentMode) === DataActionModeEnum.UPDATE | 315 | unref(currentMode) === DataActionModeEnum.UPDATE |
@@ -3,15 +3,68 @@ | @@ -3,15 +3,68 @@ | ||
3 | import { useForm, BasicForm } from '/@/components/Form'; | 3 | import { useForm, BasicForm } from '/@/components/Form'; |
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
7 | + import { createImgPreview } from '/@/components/Preview'; | ||
8 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
6 | 9 | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 10 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 11 | schemas: [ |
9 | { | 12 | { |
13 | + field: ComponentConfigFieldEnum.FONT_SIZE, | ||
14 | + label: '文本字体大小', | ||
15 | + component: 'InputNumber', | ||
16 | + defaultValue: 14, | ||
17 | + componentProps: { | ||
18 | + min: 0, | ||
19 | + max: 100, | ||
20 | + formatter: (e) => { | ||
21 | + const value = e?.toString().replace(/^0/g, ''); | ||
22 | + if (value) { | ||
23 | + return value.replace(/^0/g, ''); | ||
24 | + } else { | ||
25 | + return 0; | ||
26 | + } | ||
27 | + }, | ||
28 | + }, | ||
29 | + }, | ||
30 | + { | ||
31 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
32 | + label: '操作密码', | ||
33 | + component: 'InputPassword', | ||
34 | + defaultValue: '', | ||
35 | + }, | ||
36 | + { | ||
37 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
38 | + label: '显示设备名称', | ||
39 | + component: 'Checkbox', | ||
40 | + defaultValue: option.showDeviceName, | ||
41 | + }, | ||
42 | + { | ||
43 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
44 | + label: '图标类型', | ||
45 | + component: 'RadioGroup', | ||
46 | + defaultValue: 'default', | ||
47 | + componentProps: ({ formModel }) => { | ||
48 | + return { | ||
49 | + options: [ | ||
50 | + { label: '系统默认', value: 'default' }, | ||
51 | + { label: '自定义', value: 'custom' }, | ||
52 | + ], | ||
53 | + onChange() { | ||
54 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
55 | + }, | ||
56 | + }; | ||
57 | + }, | ||
58 | + }, | ||
59 | + { | ||
10 | field: ComponentConfigFieldEnum.ICON_COLOR, | 60 | field: ComponentConfigFieldEnum.ICON_COLOR, |
11 | label: '图标颜色', | 61 | label: '图标颜色', |
12 | component: 'ColorPicker', | 62 | component: 'ColorPicker', |
13 | changeEvent: 'update:value', | 63 | changeEvent: 'update:value', |
14 | defaultValue: option.iconColor, | 64 | defaultValue: option.iconColor, |
65 | + ifShow: ({ model }) => { | ||
66 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
67 | + }, | ||
15 | }, | 68 | }, |
16 | { | 69 | { |
17 | field: ComponentConfigFieldEnum.ICON, | 70 | field: ComponentConfigFieldEnum.ICON, |
@@ -19,6 +72,9 @@ | @@ -19,6 +72,9 @@ | ||
19 | component: 'IconDrawer', | 72 | component: 'IconDrawer', |
20 | changeEvent: 'update:value', | 73 | changeEvent: 'update:value', |
21 | defaultValue: option.icon, | 74 | defaultValue: option.icon, |
75 | + ifShow: ({ model }) => { | ||
76 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
77 | + }, | ||
22 | componentProps({ formModel }) { | 78 | componentProps({ formModel }) { |
23 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | 79 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; |
24 | return { | 80 | return { |
@@ -27,34 +83,51 @@ | @@ -27,34 +83,51 @@ | ||
27 | }, | 83 | }, |
28 | }, | 84 | }, |
29 | { | 85 | { |
30 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
31 | - label: '显示设备名称', | ||
32 | - component: 'Checkbox', | ||
33 | - defaultValue: option.showDeviceName, | ||
34 | - }, | ||
35 | - { | ||
36 | - field: ComponentConfigFieldEnum.FONT_SIZE, | ||
37 | - label: '文本字体大小', | ||
38 | - component: 'InputNumber', | ||
39 | - defaultValue: 14, | ||
40 | - componentProps: { | ||
41 | - min: 0, | ||
42 | - max: 100, | ||
43 | - formatter: (e) => { | ||
44 | - const value = e?.toString().replace(/^0/g, ''); | ||
45 | - if (value) { | ||
46 | - return value.replace(/^0/g, ''); | ||
47 | - } else { | ||
48 | - return 0; | ||
49 | - } | ||
50 | - }, | 86 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, |
87 | + label: '图标', | ||
88 | + component: 'ApiUpload', | ||
89 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
90 | + changeEvent: 'update:fileList', | ||
91 | + valueField: 'fileList', | ||
92 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
93 | + componentProps: ({ formModel }) => { | ||
94 | + return { | ||
95 | + listType: 'picture-card', | ||
96 | + maxFileLimit: 1, | ||
97 | + maxSize: 50 * 1024, | ||
98 | + accept: '.svg', | ||
99 | + api: async (file: File) => { | ||
100 | + try { | ||
101 | + const formData = new FormData(); | ||
102 | + const { name } = file; | ||
103 | + formData.set('file', file); | ||
104 | + const { fileStaticUri, fileName } = await upload(formData); | ||
105 | + return { | ||
106 | + uid: fileStaticUri, | ||
107 | + name: name || fileName, | ||
108 | + url: fileStaticUri, | ||
109 | + } as FileItem; | ||
110 | + } catch (error) { | ||
111 | + return {}; | ||
112 | + } | ||
113 | + }, | ||
114 | + // showUploadList: true, | ||
115 | + onDownload() {}, | ||
116 | + onPreview: (fileList: FileItem) => { | ||
117 | + createImgPreview({ imageList: [fileList.url!] }); | ||
118 | + }, | ||
119 | + | ||
120 | + onDelete(url: string) { | ||
121 | + formModel.deleteUrl = url!; | ||
122 | + }, | ||
123 | + }; | ||
51 | }, | 124 | }, |
52 | }, | 125 | }, |
53 | { | 126 | { |
54 | - field: ComponentConfigFieldEnum.PASS_WORD, | ||
55 | - label: '操作密码', | ||
56 | - component: 'InputPassword', | ||
57 | - defaultValue: '', | 127 | + field: 'deleteUrl', |
128 | + label: '', | ||
129 | + component: 'Input', | ||
130 | + show: false, | ||
58 | }, | 131 | }, |
59 | ], | 132 | ], |
60 | showActionButtonGroup: false, | 133 | showActionButtonGroup: false, |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | fontSize: persetFontSize, | 31 | fontSize: persetFontSize, |
32 | password: persetPassword, | 32 | password: persetPassword, |
33 | } = persetOption || {}; | 33 | } = persetOption || {}; |
34 | - const { icon, iconColor, fontSize, password } = componentInfo || {}; | 34 | + const { icon, iconColor, fontSize, password, customIcon, defaultCustom } = componentInfo || {}; |
35 | 35 | ||
36 | const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | 36 | const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); |
37 | return { | 37 | return { |
@@ -41,6 +41,8 @@ | @@ -41,6 +41,8 @@ | ||
41 | fontSize: fontSize || persetFontSize || 14, | 41 | fontSize: fontSize || persetFontSize || 14, |
42 | password: password || persetPassword, | 42 | password: password || persetPassword, |
43 | commandType, | 43 | commandType, |
44 | + defaultCustom: defaultCustom || 'default', | ||
45 | + customIcon: customIcon || [], | ||
44 | }; | 46 | }; |
45 | }); | 47 | }); |
46 | 48 | ||
@@ -81,10 +83,17 @@ | @@ -81,10 +83,17 @@ | ||
81 | <main class="w-full h-full flex justify-around items-center" :style="getScale"> | 83 | <main class="w-full h-full flex justify-around items-center" :style="getScale"> |
82 | <div class="flex flex-col justify-center items-center"> | 84 | <div class="flex flex-col justify-center items-center"> |
83 | <SvgIcon | 85 | <SvgIcon |
84 | - :name="getDesign.icon" | 86 | + v-if="getDesign.defaultCustom !== 'custom'" |
87 | + :name="getDesign.icon!" | ||
85 | prefix="iconfont" | 88 | prefix="iconfont" |
86 | - :style="{ color: getDesign.iconColor }" | ||
87 | :size="getRatio ? getRatio * 60 : 60" | 89 | :size="getRatio ? getRatio * 60 : 60" |
90 | + :style="{ color: getDesign.iconColor }" | ||
91 | + /> | ||
92 | + <img | ||
93 | + v-else | ||
94 | + :src="getDesign.customIcon[0]?.url" | ||
95 | + :style="{ width: getRatio ? getRatio * 60 + 'px' : '60px' }" | ||
96 | + :alt="getDesign.customIcon[0]?.name" | ||
88 | /> | 97 | /> |
89 | <span | 98 | <span |
90 | class="mt-3 truncate text-gray-500 text-center" | 99 | class="mt-3 truncate text-gray-500 text-center" |
@@ -3,30 +3,13 @@ | @@ -3,30 +3,13 @@ | ||
3 | import { useForm, BasicForm } from '/@/components/Form'; | 3 | import { useForm, BasicForm } from '/@/components/Form'; |
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
7 | + import { createImgPreview } from '/@/components/Preview'; | ||
8 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
6 | 9 | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 10 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 11 | schemas: [ |
9 | { | 12 | { |
10 | - field: ComponentConfigFieldEnum.ICON_COLOR, | ||
11 | - label: '图标颜色', | ||
12 | - component: 'ColorPicker', | ||
13 | - changeEvent: 'update:value', | ||
14 | - defaultValue: option.iconColor, | ||
15 | - }, | ||
16 | - { | ||
17 | - field: ComponentConfigFieldEnum.ICON, | ||
18 | - label: '图标', | ||
19 | - component: 'IconDrawer', | ||
20 | - changeEvent: 'update:value', | ||
21 | - defaultValue: option.icon, | ||
22 | - componentProps({ formModel }) { | ||
23 | - const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | ||
24 | - return { | ||
25 | - color, | ||
26 | - }; | ||
27 | - }, | ||
28 | - }, | ||
29 | - { | ||
30 | field: ComponentConfigFieldEnum.FONT_SIZE, | 13 | field: ComponentConfigFieldEnum.FONT_SIZE, |
31 | label: '文本字体大小', | 14 | label: '文本字体大小', |
32 | component: 'InputNumber', | 15 | component: 'InputNumber', |
@@ -45,16 +28,106 @@ | @@ -45,16 +28,106 @@ | ||
45 | }, | 28 | }, |
46 | }, | 29 | }, |
47 | { | 30 | { |
31 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
32 | + label: '操作密码', | ||
33 | + component: 'InputPassword', | ||
34 | + defaultValue: '', | ||
35 | + }, | ||
36 | + { | ||
48 | field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | 37 | field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, |
49 | label: '显示设备名称', | 38 | label: '显示设备名称', |
50 | component: 'Checkbox', | 39 | component: 'Checkbox', |
51 | defaultValue: option.showDeviceName, | 40 | defaultValue: option.showDeviceName, |
52 | }, | 41 | }, |
53 | { | 42 | { |
54 | - field: ComponentConfigFieldEnum.PASS_WORD, | ||
55 | - label: '操作密码', | ||
56 | - component: 'InputPassword', | ||
57 | - defaultValue: '', | 43 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, |
44 | + label: '图标类型', | ||
45 | + component: 'RadioGroup', | ||
46 | + defaultValue: 'default', | ||
47 | + componentProps: ({ formModel }) => { | ||
48 | + return { | ||
49 | + options: [ | ||
50 | + { label: '系统默认', value: 'default' }, | ||
51 | + { label: '自定义', value: 'custom' }, | ||
52 | + ], | ||
53 | + onChange() { | ||
54 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
55 | + }, | ||
56 | + }; | ||
57 | + }, | ||
58 | + }, | ||
59 | + { | ||
60 | + field: ComponentConfigFieldEnum.ICON_COLOR, | ||
61 | + label: '图标颜色', | ||
62 | + component: 'ColorPicker', | ||
63 | + changeEvent: 'update:value', | ||
64 | + defaultValue: option.iconColor, | ||
65 | + ifShow: ({ model }) => { | ||
66 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
67 | + }, | ||
68 | + }, | ||
69 | + { | ||
70 | + field: ComponentConfigFieldEnum.ICON, | ||
71 | + label: '图标', | ||
72 | + component: 'IconDrawer', | ||
73 | + changeEvent: 'update:value', | ||
74 | + defaultValue: option.icon, | ||
75 | + ifShow: ({ model }) => { | ||
76 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
77 | + }, | ||
78 | + componentProps({ formModel }) { | ||
79 | + const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | ||
80 | + return { | ||
81 | + color, | ||
82 | + }; | ||
83 | + }, | ||
84 | + }, | ||
85 | + { | ||
86 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, | ||
87 | + label: '图标', | ||
88 | + component: 'ApiUpload', | ||
89 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
90 | + changeEvent: 'update:fileList', | ||
91 | + valueField: 'fileList', | ||
92 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
93 | + componentProps: ({ formModel }) => { | ||
94 | + return { | ||
95 | + listType: 'picture-card', | ||
96 | + maxSize: 50 * 1024, | ||
97 | + maxFileLimit: 1, | ||
98 | + accept: '.svg', | ||
99 | + api: async (file: File) => { | ||
100 | + try { | ||
101 | + const formData = new FormData(); | ||
102 | + const { name } = file; | ||
103 | + formData.set('file', file); | ||
104 | + const { fileStaticUri, fileName } = await upload(formData); | ||
105 | + return { | ||
106 | + uid: fileStaticUri, | ||
107 | + name: name || fileName, | ||
108 | + url: fileStaticUri, | ||
109 | + } as FileItem; | ||
110 | + } catch (error) { | ||
111 | + return {}; | ||
112 | + } | ||
113 | + }, | ||
114 | + // showUploadList: true, | ||
115 | + onDownload() {}, | ||
116 | + onPreview: (fileList: FileItem) => { | ||
117 | + createImgPreview({ imageList: [fileList.url!] }); | ||
118 | + }, | ||
119 | + | ||
120 | + onDelete(url: string) { | ||
121 | + formModel.deleteUrl = url!; | ||
122 | + }, | ||
123 | + }; | ||
124 | + }, | ||
125 | + }, | ||
126 | + { | ||
127 | + field: 'deleteUrl', | ||
128 | + label: '', | ||
129 | + component: 'Input', | ||
130 | + show: false, | ||
58 | }, | 131 | }, |
59 | ], | 132 | ], |
60 | showActionButtonGroup: false, | 133 | showActionButtonGroup: false, |
@@ -38,8 +38,17 @@ | @@ -38,8 +38,17 @@ | ||
38 | } = persetOption || {}; | 38 | } = persetOption || {}; |
39 | return { | 39 | return { |
40 | dataSource: dataSource.map((item) => { | 40 | dataSource: dataSource.map((item) => { |
41 | - const { fontColor, icon, iconColor, unit, showDeviceName, password, fontSize } = | ||
42 | - item.componentInfo; | 41 | + const { |
42 | + fontColor, | ||
43 | + icon, | ||
44 | + iconColor, | ||
45 | + unit, | ||
46 | + showDeviceName, | ||
47 | + password, | ||
48 | + fontSize, | ||
49 | + customIcon, | ||
50 | + defaultCustom, | ||
51 | + } = item.componentInfo; | ||
43 | const { | 52 | const { |
44 | attribute, | 53 | attribute, |
45 | attributeRename, | 54 | attributeRename, |
@@ -76,6 +85,8 @@ | @@ -76,6 +85,8 @@ | ||
76 | closeCommand, | 85 | closeCommand, |
77 | openService, | 86 | openService, |
78 | closeService, | 87 | closeService, |
88 | + defaultCustom: defaultCustom || 'default', | ||
89 | + customIcon: customIcon || [], | ||
79 | } as SwitchItemType; | 90 | } as SwitchItemType; |
80 | }), | 91 | }), |
81 | }; | 92 | }; |
@@ -128,11 +139,24 @@ | @@ -128,11 +139,24 @@ | ||
128 | :key="item.id" | 139 | :key="item.id" |
129 | class="flex justify-between items-center w-full px-4" | 140 | class="flex justify-between items-center w-full px-4" |
130 | > | 141 | > |
131 | - <SvgIcon | 142 | + <!-- <SvgIcon |
132 | :name="item.icon!" | 143 | :name="item.icon!" |
133 | prefix="iconfont" | 144 | prefix="iconfont" |
134 | :size="getRatio ? 30 * getRatio : 30" | 145 | :size="getRatio ? 30 * getRatio : 30" |
135 | :style="{ color: item.iconColor }" | 146 | :style="{ color: item.iconColor }" |
147 | + /> --> | ||
148 | + <SvgIcon | ||
149 | + v-if="item.defaultCustom !== 'custom'" | ||
150 | + :name="item.icon!" | ||
151 | + prefix="iconfont" | ||
152 | + :size="getRatio ? getRatio * 30 : 30" | ||
153 | + :style="{ color: item.iconColor }" | ||
154 | + /> | ||
155 | + <img | ||
156 | + v-else | ||
157 | + :src="item.customIcon[0]?.url" | ||
158 | + :style="{ width: getRatio ? getRatio * 30 + 'px' : '30px' }" | ||
159 | + :alt="item.customIcon[0]?.name" | ||
136 | /> | 160 | /> |
137 | <div | 161 | <div |
138 | class="text-gray-500 truncate mx-2" | 162 | class="text-gray-500 truncate mx-2" |
@@ -3,15 +3,68 @@ | @@ -3,15 +3,68 @@ | ||
3 | import { useForm, BasicForm } from '/@/components/Form'; | 3 | import { useForm, BasicForm } from '/@/components/Form'; |
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
7 | + import { createImgPreview } from '/@/components/Preview'; | ||
8 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
6 | 9 | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 10 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 11 | schemas: [ |
9 | { | 12 | { |
13 | + field: ComponentConfigFieldEnum.FONT_SIZE, | ||
14 | + label: '文本字体大小', | ||
15 | + component: 'InputNumber', | ||
16 | + defaultValue: 14, | ||
17 | + componentProps: { | ||
18 | + min: 0, | ||
19 | + max: 100, | ||
20 | + formatter: (e) => { | ||
21 | + const value = e?.toString().replace(/^0/g, ''); | ||
22 | + if (value) { | ||
23 | + return value.replace(/^0/g, ''); | ||
24 | + } else { | ||
25 | + return 0; | ||
26 | + } | ||
27 | + }, | ||
28 | + }, | ||
29 | + }, | ||
30 | + { | ||
31 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
32 | + label: '显示设备名称', | ||
33 | + component: 'Checkbox', | ||
34 | + defaultValue: option.showDeviceName, | ||
35 | + }, | ||
36 | + { | ||
37 | + field: ComponentConfigFieldEnum.SHOW_TIME, | ||
38 | + label: '显示时间', | ||
39 | + component: 'Checkbox', | ||
40 | + defaultValue: option.showTime, | ||
41 | + }, | ||
42 | + { | ||
43 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
44 | + label: '图标类型', | ||
45 | + component: 'RadioGroup', | ||
46 | + defaultValue: 'default', | ||
47 | + componentProps: ({ formModel }) => { | ||
48 | + return { | ||
49 | + options: [ | ||
50 | + { label: '系统默认', value: 'default' }, | ||
51 | + { label: '自定义', value: 'custom' }, | ||
52 | + ], | ||
53 | + onChange() { | ||
54 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
55 | + }, | ||
56 | + }; | ||
57 | + }, | ||
58 | + }, | ||
59 | + { | ||
10 | field: ComponentConfigFieldEnum.ICON, | 60 | field: ComponentConfigFieldEnum.ICON, |
11 | label: '开启状态图标', | 61 | label: '开启状态图标', |
12 | component: 'IconDrawer', | 62 | component: 'IconDrawer', |
13 | changeEvent: 'update:value', | 63 | changeEvent: 'update:value', |
14 | defaultValue: option.icon, | 64 | defaultValue: option.icon, |
65 | + ifShow: ({ model }) => { | ||
66 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
67 | + }, | ||
15 | componentProps({ formModel }) { | 68 | componentProps({ formModel }) { |
16 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | 69 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; |
17 | return { | 70 | return { |
@@ -24,6 +77,9 @@ | @@ -24,6 +77,9 @@ | ||
24 | label: '开启图标颜色', | 77 | label: '开启图标颜色', |
25 | component: 'ColorPicker', | 78 | component: 'ColorPicker', |
26 | changeEvent: 'update:value', | 79 | changeEvent: 'update:value', |
80 | + ifShow: ({ model }) => { | ||
81 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
82 | + }, | ||
27 | defaultValue: option.iconColor, | 83 | defaultValue: option.iconColor, |
28 | }, | 84 | }, |
29 | { | 85 | { |
@@ -32,6 +88,9 @@ | @@ -32,6 +88,9 @@ | ||
32 | component: 'IconDrawer', | 88 | component: 'IconDrawer', |
33 | changeEvent: 'update:value', | 89 | changeEvent: 'update:value', |
34 | defaultValue: option.iconClose, | 90 | defaultValue: option.iconClose, |
91 | + ifShow: ({ model }) => { | ||
92 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
93 | + }, | ||
35 | componentProps({ formModel }) { | 94 | componentProps({ formModel }) { |
36 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR_CLOSE]; | 95 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR_CLOSE]; |
37 | return { | 96 | return { |
@@ -44,37 +103,84 @@ | @@ -44,37 +103,84 @@ | ||
44 | label: '关闭图标颜色', | 103 | label: '关闭图标颜色', |
45 | component: 'ColorPicker', | 104 | component: 'ColorPicker', |
46 | changeEvent: 'update:value', | 105 | changeEvent: 'update:value', |
106 | + ifShow: ({ model }) => { | ||
107 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
108 | + }, | ||
47 | defaultValue: option.iconColorClose, | 109 | defaultValue: option.iconColorClose, |
48 | }, | 110 | }, |
49 | { | 111 | { |
50 | - field: ComponentConfigFieldEnum.FONT_SIZE, | ||
51 | - label: '文本字体大小', | ||
52 | - component: 'InputNumber', | ||
53 | - defaultValue: 14, | ||
54 | - componentProps: { | ||
55 | - min: 0, | ||
56 | - max: 100, | ||
57 | - formatter: (e) => { | ||
58 | - const value = e?.toString().replace(/^0/g, ''); | ||
59 | - if (value) { | ||
60 | - return value.replace(/^0/g, ''); | ||
61 | - } else { | ||
62 | - return 0; | ||
63 | - } | ||
64 | - }, | 112 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, |
113 | + label: '开启状态图标', | ||
114 | + component: 'ApiUpload', | ||
115 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
116 | + changeEvent: 'update:fileList', | ||
117 | + valueField: 'fileList', | ||
118 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
119 | + componentProps: ({}) => { | ||
120 | + return { | ||
121 | + listType: 'picture-card', | ||
122 | + maxSize: 50 * 1024, | ||
123 | + maxFileLimit: 1, | ||
124 | + accept: '.svg', | ||
125 | + api: async (file: File) => { | ||
126 | + try { | ||
127 | + const formData = new FormData(); | ||
128 | + const { name } = file; | ||
129 | + formData.set('file', file); | ||
130 | + const { fileStaticUri, fileName } = await upload(formData); | ||
131 | + return { | ||
132 | + uid: fileStaticUri, | ||
133 | + name: name || fileName, | ||
134 | + url: fileStaticUri, | ||
135 | + } as FileItem; | ||
136 | + } catch (error) { | ||
137 | + return {}; | ||
138 | + } | ||
139 | + }, | ||
140 | + // showUploadList: true, | ||
141 | + onDownload() {}, | ||
142 | + onPreview: (fileList: FileItem) => { | ||
143 | + createImgPreview({ imageList: [fileList.url!] }); | ||
144 | + }, | ||
145 | + }; | ||
65 | }, | 146 | }, |
66 | }, | 147 | }, |
67 | { | 148 | { |
68 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
69 | - label: '显示设备名称', | ||
70 | - component: 'Checkbox', | ||
71 | - defaultValue: option.showDeviceName, | ||
72 | - }, | ||
73 | - { | ||
74 | - field: ComponentConfigFieldEnum.SHOW_TIME, | ||
75 | - label: '显示时间', | ||
76 | - component: 'Checkbox', | ||
77 | - defaultValue: option.showTime, | 149 | + field: ComponentConfigFieldEnum.CUSTOM_ICON_CLOSE, |
150 | + label: '关闭状态图标', | ||
151 | + component: 'ApiUpload', | ||
152 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
153 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
154 | + changeEvent: 'update:fileList', | ||
155 | + valueField: 'fileList', | ||
156 | + componentProps: ({}) => { | ||
157 | + return { | ||
158 | + listType: 'picture-card', | ||
159 | + maxSize: 0 * 1024, | ||
160 | + maxFileLimit: 1, | ||
161 | + accept: '.svg', | ||
162 | + api: async (file: File) => { | ||
163 | + try { | ||
164 | + const formData = new FormData(); | ||
165 | + const { name } = file; | ||
166 | + formData.set('file', file); | ||
167 | + const { fileStaticUri, fileName } = await upload(formData); | ||
168 | + return { | ||
169 | + uid: fileStaticUri, | ||
170 | + name: name || fileName, | ||
171 | + url: fileStaticUri, | ||
172 | + } as FileItem; | ||
173 | + } catch (error) { | ||
174 | + return {}; | ||
175 | + } | ||
176 | + }, | ||
177 | + // showUploadList: true, | ||
178 | + onDownload() {}, | ||
179 | + onPreview: (fileList: FileItem) => { | ||
180 | + createImgPreview({ imageList: [fileList.url!] }); | ||
181 | + }, | ||
182 | + }; | ||
183 | + }, | ||
78 | }, | 184 | }, |
79 | ], | 185 | ], |
80 | showActionButtonGroup: false, | 186 | showActionButtonGroup: false, |
@@ -32,8 +32,19 @@ | @@ -32,8 +32,19 @@ | ||
32 | 32 | ||
33 | const { componentInfo, attributeName, attributeRename } = option; | 33 | const { componentInfo, attributeName, attributeRename } = option; |
34 | 34 | ||
35 | - const { icon, iconColor, fontColor, unit, iconClose, iconColorClose, showTime, fontSize } = | ||
36 | - componentInfo || {}; | 35 | + const { |
36 | + icon, | ||
37 | + iconColor, | ||
38 | + fontColor, | ||
39 | + unit, | ||
40 | + iconClose, | ||
41 | + iconColorClose, | ||
42 | + showTime, | ||
43 | + fontSize, | ||
44 | + customIcon, | ||
45 | + customIconClose, | ||
46 | + defaultCustom, | ||
47 | + } = componentInfo || {}; | ||
37 | return { | 48 | return { |
38 | iconColor: iconColor || persetIconColor, | 49 | iconColor: iconColor || persetIconColor, |
39 | unit: unit ?? perseUnit, | 50 | unit: unit ?? perseUnit, |
@@ -44,6 +55,9 @@ | @@ -44,6 +55,9 @@ | ||
44 | iconColorClose: iconColorClose || persetIconColorClose, | 55 | iconColorClose: iconColorClose || persetIconColorClose, |
45 | showTime: showTime ?? persetShowTime, | 56 | showTime: showTime ?? persetShowTime, |
46 | fontSize: fontSize || persetFontSize || 14, | 57 | fontSize: fontSize || persetFontSize || 14, |
58 | + defaultCustom: defaultCustom || 'default', | ||
59 | + customIcon: customIcon || [], | ||
60 | + customIconClose: customIconClose || [], | ||
47 | }; | 61 | }; |
48 | }); | 62 | }); |
49 | 63 | ||
@@ -68,10 +82,17 @@ | @@ -68,10 +82,17 @@ | ||
68 | <DeviceName :config="config" /> | 82 | <DeviceName :config="config" /> |
69 | <div class="flex flex-1 flex-col justify-center items-center"> | 83 | <div class="flex flex-1 flex-col justify-center items-center"> |
70 | <SvgIcon | 84 | <SvgIcon |
85 | + v-if="getDesign.defaultCustom !== 'custom'" | ||
71 | :name="isOpenClose ? getDesign.icon : getDesign.iconClose" | 86 | :name="isOpenClose ? getDesign.icon : getDesign.iconClose" |
72 | prefix="iconfont" | 87 | prefix="iconfont" |
73 | :size="getRatio ? getRatio * 70 : 70" | 88 | :size="getRatio ? getRatio * 70 : 70" |
74 | - :style="{ color: isOpenClose ? getDesign.iconColor : getDesign.iconColorClose }" | 89 | + :style="{ color: getDesign.iconColor }" |
90 | + /> | ||
91 | + <img | ||
92 | + v-else | ||
93 | + :src="isOpenClose ? getDesign.customIcon[0]?.url : getDesign.customIconClose[0]?.url" | ||
94 | + :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }" | ||
95 | + :alt="getDesign.customIcon[0]?.name" | ||
75 | /> | 96 | /> |
76 | <div | 97 | <div |
77 | class="text-gray-500 truncate m-2" | 98 | class="text-gray-500 truncate m-2" |
@@ -3,6 +3,9 @@ | @@ -3,6 +3,9 @@ | ||
3 | import { useForm, BasicForm } from '/@/components/Form'; | 3 | import { useForm, BasicForm } from '/@/components/Form'; |
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
7 | + import { createImgPreview } from '/@/components/Preview'; | ||
8 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
6 | 9 | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 10 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 11 | schemas: [ |
@@ -61,11 +64,37 @@ | @@ -61,11 +64,37 @@ | ||
61 | }, | 64 | }, |
62 | }, | 65 | }, |
63 | { | 66 | { |
67 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
68 | + label: '显示设备名称', | ||
69 | + component: 'Checkbox', | ||
70 | + defaultValue: option.showDeviceName, | ||
71 | + }, | ||
72 | + { | ||
73 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
74 | + label: '图标类型', | ||
75 | + component: 'RadioGroup', | ||
76 | + defaultValue: 'default', | ||
77 | + componentProps: ({ formModel }) => { | ||
78 | + return { | ||
79 | + options: [ | ||
80 | + { label: '系统默认', value: 'default' }, | ||
81 | + { label: '自定义', value: 'custom' }, | ||
82 | + ], | ||
83 | + onChange() { | ||
84 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
85 | + }, | ||
86 | + }; | ||
87 | + }, | ||
88 | + }, | ||
89 | + { | ||
64 | field: ComponentConfigFieldEnum.ICON_COLOR, | 90 | field: ComponentConfigFieldEnum.ICON_COLOR, |
65 | label: '图标颜色', | 91 | label: '图标颜色', |
66 | component: 'ColorPicker', | 92 | component: 'ColorPicker', |
67 | changeEvent: 'update:value', | 93 | changeEvent: 'update:value', |
68 | defaultValue: option.iconColor, | 94 | defaultValue: option.iconColor, |
95 | + ifShow: ({ model }) => { | ||
96 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
97 | + }, | ||
69 | }, | 98 | }, |
70 | { | 99 | { |
71 | field: ComponentConfigFieldEnum.ICON, | 100 | field: ComponentConfigFieldEnum.ICON, |
@@ -73,6 +102,9 @@ | @@ -73,6 +102,9 @@ | ||
73 | component: 'IconDrawer', | 102 | component: 'IconDrawer', |
74 | changeEvent: 'update:value', | 103 | changeEvent: 'update:value', |
75 | defaultValue: option.icon, | 104 | defaultValue: option.icon, |
105 | + ifShow: ({ model }) => { | ||
106 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
107 | + }, | ||
76 | componentProps({ formModel }) { | 108 | componentProps({ formModel }) { |
77 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | 109 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; |
78 | return { | 110 | return { |
@@ -81,10 +113,50 @@ | @@ -81,10 +113,50 @@ | ||
81 | }, | 113 | }, |
82 | }, | 114 | }, |
83 | { | 115 | { |
84 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
85 | - label: '显示设备名称', | ||
86 | - component: 'Checkbox', | ||
87 | - defaultValue: option.showDeviceName, | 116 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, |
117 | + label: '图标', | ||
118 | + component: 'ApiUpload', | ||
119 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
120 | + changeEvent: 'update:fileList', | ||
121 | + valueField: 'fileList', | ||
122 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
123 | + componentProps: ({ formModel }) => { | ||
124 | + return { | ||
125 | + maxSize: 50 * 1024, | ||
126 | + listType: 'picture-card', | ||
127 | + maxFileLimit: 1, | ||
128 | + accept: '.svg', | ||
129 | + api: async (file: File) => { | ||
130 | + try { | ||
131 | + const formData = new FormData(); | ||
132 | + const { name } = file; | ||
133 | + formData.set('file', file); | ||
134 | + const { fileStaticUri, fileName } = await upload(formData); | ||
135 | + return { | ||
136 | + uid: fileStaticUri, | ||
137 | + name: name || fileName, | ||
138 | + url: fileStaticUri, | ||
139 | + } as FileItem; | ||
140 | + } catch (error) { | ||
141 | + return {}; | ||
142 | + } | ||
143 | + }, | ||
144 | + // showUploadList: true, | ||
145 | + onDownload() {}, | ||
146 | + onPreview: (fileList: FileItem) => { | ||
147 | + createImgPreview({ imageList: [fileList.url!] }); | ||
148 | + }, | ||
149 | + onDelete(url: string) { | ||
150 | + formModel.deleteUrl = url!; | ||
151 | + }, | ||
152 | + }; | ||
153 | + }, | ||
154 | + }, | ||
155 | + { | ||
156 | + field: 'deleteUrl', | ||
157 | + label: '', | ||
158 | + component: 'Input', | ||
159 | + show: false, | ||
88 | }, | 160 | }, |
89 | ], | 161 | ], |
90 | showActionButtonGroup: false, | 162 | showActionButtonGroup: false, |
@@ -31,7 +31,6 @@ | @@ -31,7 +31,6 @@ | ||
31 | 31 | ||
32 | const getDesign = computed(() => { | 32 | const getDesign = computed(() => { |
33 | const { persetOption = {}, option } = props.config; | 33 | const { persetOption = {}, option } = props.config; |
34 | - | ||
35 | const { | 34 | const { |
36 | iconColor: persetIconColor, | 35 | iconColor: persetIconColor, |
37 | unit: perseUnit, | 36 | unit: perseUnit, |
@@ -44,7 +43,8 @@ | @@ -44,7 +43,8 @@ | ||
44 | const { componentInfo, attributeRename } = option; | 43 | const { componentInfo, attributeRename } = option; |
45 | const { functionName } = unref(getThingModelTsl) || {}; | 44 | const { functionName } = unref(getThingModelTsl) || {}; |
46 | 45 | ||
47 | - const { icon, iconColor, fontColor, unit, valueSize, fontSize } = componentInfo || {}; | 46 | + const { icon, iconColor, fontColor, unit, valueSize, fontSize, customIcon, defaultCustom } = |
47 | + componentInfo || {}; | ||
48 | return { | 48 | return { |
49 | iconColor: iconColor || persetIconColor, | 49 | iconColor: iconColor || persetIconColor, |
50 | unit: unit ?? perseUnit, | 50 | unit: unit ?? perseUnit, |
@@ -53,6 +53,8 @@ | @@ -53,6 +53,8 @@ | ||
53 | attribute: attributeRename || functionName, | 53 | attribute: attributeRename || functionName, |
54 | valueSize: valueSize || persetValueSize || 20, | 54 | valueSize: valueSize || persetValueSize || 20, |
55 | fontSize: fontSize || persetFontSize || 14, | 55 | fontSize: fontSize || persetFontSize || 14, |
56 | + defaultCustom: defaultCustom || 'default', | ||
57 | + customIcon: customIcon || [], | ||
56 | }; | 58 | }; |
57 | }); | 59 | }); |
58 | 60 | ||
@@ -78,11 +80,18 @@ | @@ -78,11 +80,18 @@ | ||
78 | <DeviceName :config="config" /> | 80 | <DeviceName :config="config" /> |
79 | <div class="flex-1 flex justify-center items-center flex-col w-full"> | 81 | <div class="flex-1 flex justify-center items-center flex-col w-full"> |
80 | <SvgIcon | 82 | <SvgIcon |
83 | + v-if="getDesign.defaultCustom !== 'custom'" | ||
81 | :name="getDesign.icon!" | 84 | :name="getDesign.icon!" |
82 | prefix="iconfont" | 85 | prefix="iconfont" |
83 | :size="getRatio ? getRatio * 70 : 70" | 86 | :size="getRatio ? getRatio * 70 : 70" |
84 | :style="{ color: getDesign.iconColor }" | 87 | :style="{ color: getDesign.iconColor }" |
85 | /> | 88 | /> |
89 | + <img | ||
90 | + v-else | ||
91 | + :src="getDesign.customIcon[0]?.url" | ||
92 | + :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }" | ||
93 | + :alt="getDesign.customIcon[0]?.name" | ||
94 | + /> | ||
86 | <h1 | 95 | <h1 |
87 | class="font-bold m-2 truncate w-full text-center" | 96 | class="font-bold m-2 truncate w-full text-center" |
88 | :style="{ | 97 | :style="{ |
@@ -3,6 +3,9 @@ | @@ -3,6 +3,9 @@ | ||
3 | import { useForm, BasicForm } from '/@/components/Form'; | 3 | import { useForm, BasicForm } from '/@/components/Form'; |
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
7 | + import { createImgPreview } from '/@/components/Preview'; | ||
8 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
6 | 9 | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 10 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 11 | schemas: [ |
@@ -60,11 +63,37 @@ | @@ -60,11 +63,37 @@ | ||
60 | }, | 63 | }, |
61 | }, | 64 | }, |
62 | { | 65 | { |
66 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
67 | + label: '显示设备名称', | ||
68 | + component: 'Checkbox', | ||
69 | + defaultValue: option.showDeviceName, | ||
70 | + }, | ||
71 | + { | ||
72 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
73 | + label: '图标类型', | ||
74 | + component: 'RadioGroup', | ||
75 | + defaultValue: 'default', | ||
76 | + componentProps: ({ formModel }) => { | ||
77 | + return { | ||
78 | + options: [ | ||
79 | + { label: '系统默认', value: 'default' }, | ||
80 | + { label: '自定义', value: 'custom' }, | ||
81 | + ], | ||
82 | + onChange() { | ||
83 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
84 | + }, | ||
85 | + }; | ||
86 | + }, | ||
87 | + }, | ||
88 | + { | ||
63 | field: ComponentConfigFieldEnum.ICON_COLOR, | 89 | field: ComponentConfigFieldEnum.ICON_COLOR, |
64 | label: '图标颜色', | 90 | label: '图标颜色', |
65 | component: 'ColorPicker', | 91 | component: 'ColorPicker', |
66 | changeEvent: 'update:value', | 92 | changeEvent: 'update:value', |
67 | defaultValue: option.iconColor, | 93 | defaultValue: option.iconColor, |
94 | + ifShow: ({ model }) => { | ||
95 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
96 | + }, | ||
68 | }, | 97 | }, |
69 | { | 98 | { |
70 | field: ComponentConfigFieldEnum.ICON, | 99 | field: ComponentConfigFieldEnum.ICON, |
@@ -72,6 +101,9 @@ | @@ -72,6 +101,9 @@ | ||
72 | component: 'IconDrawer', | 101 | component: 'IconDrawer', |
73 | changeEvent: 'update:value', | 102 | changeEvent: 'update:value', |
74 | defaultValue: option.icon, | 103 | defaultValue: option.icon, |
104 | + ifShow: ({ model }) => { | ||
105 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
106 | + }, | ||
75 | componentProps({ formModel }) { | 107 | componentProps({ formModel }) { |
76 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | 108 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; |
77 | return { | 109 | return { |
@@ -80,10 +112,50 @@ | @@ -80,10 +112,50 @@ | ||
80 | }, | 112 | }, |
81 | }, | 113 | }, |
82 | { | 114 | { |
83 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
84 | - label: '显示设备名称', | ||
85 | - component: 'Checkbox', | ||
86 | - defaultValue: option.showDeviceName, | 115 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, |
116 | + label: '图标', | ||
117 | + component: 'ApiUpload', | ||
118 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
119 | + changeEvent: 'update:fileList', | ||
120 | + valueField: 'fileList', | ||
121 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
122 | + componentProps: ({ formModel }) => { | ||
123 | + return { | ||
124 | + listType: 'picture-card', | ||
125 | + maxSize: 50 * 1024, | ||
126 | + maxFileLimit: 1, | ||
127 | + accept: '.svg', | ||
128 | + api: async (file: File) => { | ||
129 | + try { | ||
130 | + const formData = new FormData(); | ||
131 | + const { name } = file; | ||
132 | + formData.set('file', file); | ||
133 | + const { fileStaticUri, fileName } = await upload(formData); | ||
134 | + return { | ||
135 | + uid: fileStaticUri, | ||
136 | + name: name || fileName, | ||
137 | + url: fileStaticUri, | ||
138 | + } as FileItem; | ||
139 | + } catch (error) { | ||
140 | + return {}; | ||
141 | + } | ||
142 | + }, | ||
143 | + // showUploadList: true, | ||
144 | + onDownload() {}, | ||
145 | + onPreview: (fileList: FileItem) => { | ||
146 | + createImgPreview({ imageList: [fileList.url!] }); | ||
147 | + }, | ||
148 | + onDelete(url: string) { | ||
149 | + formModel.deleteUrl = url!; | ||
150 | + }, | ||
151 | + }; | ||
152 | + }, | ||
153 | + }, | ||
154 | + { | ||
155 | + field: 'deleteUrl', | ||
156 | + label: '', | ||
157 | + component: 'Input', | ||
158 | + show: false, | ||
87 | }, | 159 | }, |
88 | ], | 160 | ], |
89 | showActionButtonGroup: false, | 161 | showActionButtonGroup: false, |
@@ -40,7 +40,8 @@ | @@ -40,7 +40,8 @@ | ||
40 | 40 | ||
41 | const { componentInfo, attribute, attributeRename } = option; | 41 | const { componentInfo, attribute, attributeRename } = option; |
42 | 42 | ||
43 | - const { icon, iconColor, fontColor, unit, valueSize, fontSize } = componentInfo || {}; | 43 | + const { icon, iconColor, fontColor, unit, valueSize, fontSize, customIcon, defaultCustom } = |
44 | + componentInfo || {}; | ||
44 | return { | 45 | return { |
45 | iconColor: iconColor || persetIconColor, | 46 | iconColor: iconColor || persetIconColor, |
46 | unit: unit ?? perseUnit, | 47 | unit: unit ?? perseUnit, |
@@ -49,6 +50,8 @@ | @@ -49,6 +50,8 @@ | ||
49 | attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute, | 50 | attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute, |
50 | valueSize: valueSize || persetValueSize || 20, | 51 | valueSize: valueSize || persetValueSize || 20, |
51 | fontSize: fontSize || persetFontSize || 14, | 52 | fontSize: fontSize || persetFontSize || 14, |
53 | + defaultCustom: defaultCustom || 'default', | ||
54 | + customIcon: customIcon || [], | ||
52 | }; | 55 | }; |
53 | }); | 56 | }); |
54 | 57 | ||
@@ -73,11 +76,18 @@ | @@ -73,11 +76,18 @@ | ||
73 | <DeviceName :config="config" /> | 76 | <DeviceName :config="config" /> |
74 | <div :style="getScale" class="flex-1 flex justify-center items-center flex-col w-full"> | 77 | <div :style="getScale" class="flex-1 flex justify-center items-center flex-col w-full"> |
75 | <SvgIcon | 78 | <SvgIcon |
79 | + v-if="getDesign.defaultCustom !== 'custom'" | ||
76 | :name="getDesign.icon!" | 80 | :name="getDesign.icon!" |
77 | prefix="iconfont" | 81 | prefix="iconfont" |
78 | :size="getRatio ? getRatio * 70 : 70" | 82 | :size="getRatio ? getRatio * 70 : 70" |
79 | :style="{ color: getDesign.iconColor }" | 83 | :style="{ color: getDesign.iconColor }" |
80 | /> | 84 | /> |
85 | + <img | ||
86 | + v-else | ||
87 | + :src="getDesign.customIcon[0]?.url" | ||
88 | + :style="{ width: getRatio ? getRatio * 70 + 'px' : '70px' }" | ||
89 | + :alt="getDesign.customIcon[0]?.name" | ||
90 | + /> | ||
81 | <h1 | 91 | <h1 |
82 | class="my-4 font-bold !my-2 truncate w-full text-center" | 92 | class="my-4 font-bold !my-2 truncate w-full text-center" |
83 | :style="{ | 93 | :style="{ |
@@ -4,6 +4,10 @@ | @@ -4,6 +4,10 @@ | ||
4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | 4 | import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; |
5 | import { option } from './config'; | 5 | import { option } from './config'; |
6 | 6 | ||
7 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
8 | + import { createImgPreview } from '/@/components/Preview'; | ||
9 | + import { upload } from '/@/api/oss/ossFileUploader'; | ||
10 | + | ||
7 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | 11 | const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ |
8 | schemas: [ | 12 | schemas: [ |
9 | { | 13 | { |
@@ -60,11 +64,31 @@ | @@ -60,11 +64,31 @@ | ||
60 | }, | 64 | }, |
61 | }, | 65 | }, |
62 | { | 66 | { |
67 | + field: ComponentConfigFieldEnum.DEFAULT_CUSTOM, | ||
68 | + label: '图标类型', | ||
69 | + component: 'RadioGroup', | ||
70 | + defaultValue: 'default', | ||
71 | + componentProps: ({ formModel }) => { | ||
72 | + return { | ||
73 | + options: [ | ||
74 | + { label: '系统默认', value: 'default' }, | ||
75 | + { label: '自定义', value: 'custom' }, | ||
76 | + ], | ||
77 | + onChange() { | ||
78 | + formModel[ComponentConfigFieldEnum.CUSTOM_ICON] = []; | ||
79 | + }, | ||
80 | + }; | ||
81 | + }, | ||
82 | + }, | ||
83 | + { | ||
63 | field: ComponentConfigFieldEnum.ICON_COLOR, | 84 | field: ComponentConfigFieldEnum.ICON_COLOR, |
64 | label: '图标颜色', | 85 | label: '图标颜色', |
65 | component: 'ColorPicker', | 86 | component: 'ColorPicker', |
66 | changeEvent: 'update:value', | 87 | changeEvent: 'update:value', |
67 | defaultValue: option.iconColor, | 88 | defaultValue: option.iconColor, |
89 | + ifShow: ({ model }) => { | ||
90 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
91 | + }, | ||
68 | }, | 92 | }, |
69 | { | 93 | { |
70 | field: ComponentConfigFieldEnum.ICON, | 94 | field: ComponentConfigFieldEnum.ICON, |
@@ -73,6 +97,9 @@ | @@ -73,6 +97,9 @@ | ||
73 | changeEvent: 'update:value', | 97 | changeEvent: 'update:value', |
74 | valueField: 'value', | 98 | valueField: 'value', |
75 | defaultValue: option.icon, | 99 | defaultValue: option.icon, |
100 | + ifShow: ({ model }) => { | ||
101 | + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom'; | ||
102 | + }, | ||
76 | componentProps({ formModel }) { | 103 | componentProps({ formModel }) { |
77 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; | 104 | const color = formModel[ComponentConfigFieldEnum.ICON_COLOR]; |
78 | return { | 105 | return { |
@@ -80,6 +107,51 @@ | @@ -80,6 +107,51 @@ | ||
80 | }; | 107 | }; |
81 | }, | 108 | }, |
82 | }, | 109 | }, |
110 | + { | ||
111 | + field: ComponentConfigFieldEnum.CUSTOM_ICON, | ||
112 | + label: '图标', | ||
113 | + component: 'ApiUpload', | ||
114 | + ifShow: ({ model }) => model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] === 'custom', | ||
115 | + changeEvent: 'update:fileList', | ||
116 | + valueField: 'fileList', | ||
117 | + helpMessage: ['支持.svg格式,建议尺寸为32*32px,大小不超过50kb '], | ||
118 | + componentProps: ({ formModel }) => { | ||
119 | + return { | ||
120 | + listType: 'picture-card', | ||
121 | + maxSize: 50 * 1024, | ||
122 | + maxFileLimit: 1, | ||
123 | + accept: '.svg', | ||
124 | + api: async (file: File) => { | ||
125 | + try { | ||
126 | + const formData = new FormData(); | ||
127 | + const { name } = file; | ||
128 | + formData.set('file', file); | ||
129 | + const { fileStaticUri, fileName } = await upload(formData); | ||
130 | + return { | ||
131 | + uid: fileStaticUri, | ||
132 | + name: name || fileName, | ||
133 | + url: fileStaticUri, | ||
134 | + } as FileItem; | ||
135 | + } catch (error) { | ||
136 | + return {}; | ||
137 | + } | ||
138 | + }, | ||
139 | + onDownload() {}, | ||
140 | + onPreview: (fileList: FileItem) => { | ||
141 | + createImgPreview({ imageList: [fileList.url!] }); | ||
142 | + }, | ||
143 | + onDelete(url: string) { | ||
144 | + formModel.deleteUrl = url!; | ||
145 | + }, | ||
146 | + }; | ||
147 | + }, | ||
148 | + }, | ||
149 | + { | ||
150 | + field: 'deleteUrl', | ||
151 | + label: '', | ||
152 | + component: 'Input', | ||
153 | + show: false, | ||
154 | + }, | ||
83 | ], | 155 | ], |
84 | showActionButtonGroup: false, | 156 | showActionButtonGroup: false, |
85 | labelWidth: 120, | 157 | labelWidth: 120, |
@@ -35,7 +35,8 @@ | @@ -35,7 +35,8 @@ | ||
35 | 35 | ||
36 | return { | 36 | return { |
37 | dataSource: dataSource.map((item) => { | 37 | dataSource: dataSource.map((item) => { |
38 | - const { fontColor, icon, iconColor, unit, valueSize, fontSize } = item.componentInfo; | 38 | + const { fontColor, icon, iconColor, unit, valueSize, fontSize, customIcon, defaultCustom } = |
39 | + item.componentInfo; | ||
39 | const { attribute, attributeRename, deviceName, deviceRename, deviceId, deviceProfileId } = | 40 | const { attribute, attributeRename, deviceName, deviceRename, deviceId, deviceProfileId } = |
40 | item; | 41 | item; |
41 | const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | 42 | const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); |
@@ -50,6 +51,8 @@ | @@ -50,6 +51,8 @@ | ||
50 | id: deviceId, | 51 | id: deviceId, |
51 | valueSize: valueSize || persetValueSize || 20, | 52 | valueSize: valueSize || persetValueSize || 20, |
52 | fontSize: fontSize || persetFontSize || 14, | 53 | fontSize: fontSize || persetFontSize || 14, |
54 | + defaultCustom: defaultCustom || 'default', | ||
55 | + customIcon: customIcon || [], | ||
53 | }; | 56 | }; |
54 | }), | 57 | }), |
55 | }; | 58 | }; |
@@ -67,6 +70,8 @@ | @@ -67,6 +70,8 @@ | ||
67 | fontColor: '#357CFB', | 70 | fontColor: '#357CFB', |
68 | fontSize: 16, | 71 | fontSize: 16, |
69 | valueSize: 16, | 72 | valueSize: 16, |
73 | + defaultCustom: 'default', | ||
74 | + customIcon: [], | ||
70 | }, | 75 | }, |
71 | { | 76 | { |
72 | id: buildUUID(), | 77 | id: buildUUID(), |
@@ -79,6 +84,8 @@ | @@ -79,6 +84,8 @@ | ||
79 | fontColor: '#FFA000', | 84 | fontColor: '#FFA000', |
80 | fontSize: 16, | 85 | fontSize: 16, |
81 | valueSize: 16, | 86 | valueSize: 16, |
87 | + defaultCustom: 'default', | ||
88 | + customIcon: [], | ||
82 | }, | 89 | }, |
83 | ]); | 90 | ]); |
84 | 91 | ||
@@ -114,11 +121,24 @@ | @@ -114,11 +121,24 @@ | ||
114 | class="flex justify-between items-center mt-2" | 121 | class="flex justify-between items-center mt-2" |
115 | > | 122 | > |
116 | <div class="flex items-center"> | 123 | <div class="flex items-center"> |
117 | - <SvgIcon | 124 | + <!-- <SvgIcon |
118 | :name="item.icon!" | 125 | :name="item.icon!" |
119 | prefix="iconfont" | 126 | prefix="iconfont" |
120 | :size="getRatio ? 30 * getRatio : 30" | 127 | :size="getRatio ? 30 * getRatio : 30" |
121 | :style="{ color: item.iconColor }" | 128 | :style="{ color: item.iconColor }" |
129 | + /> --> | ||
130 | + <SvgIcon | ||
131 | + v-if="item.defaultCustom !== 'custom'" | ||
132 | + :name="item.icon!" | ||
133 | + prefix="iconfont" | ||
134 | + :size="getRatio ? getRatio * 30 : 30" | ||
135 | + :style="{ color: item.iconColor }" | ||
136 | + /> | ||
137 | + <img | ||
138 | + v-else | ||
139 | + :src="item.customIcon[0]?.url" | ||
140 | + :style="{ width: getRatio ? getRatio * 30 + 'px' : '30px' }" | ||
141 | + :alt="item.customIcon[0]?.name" | ||
122 | /> | 142 | /> |
123 | <div | 143 | <div |
124 | class="text-gray-500 ml-6" | 144 | class="text-gray-500 ml-6" |
@@ -36,4 +36,8 @@ export enum ComponentConfigFieldEnum { | @@ -36,4 +36,8 @@ export enum ComponentConfigFieldEnum { | ||
36 | MIN_NUMBER = 'minNumber', | 36 | MIN_NUMBER = 'minNumber', |
37 | MAX_NUMBER = 'maxNumber', | 37 | MAX_NUMBER = 'maxNumber', |
38 | PASS_WORD = 'password', //操作密码 | 38 | PASS_WORD = 'password', //操作密码 |
39 | + DEFAULT_CUSTOM = 'defaultCustom', | ||
40 | + DEFAULT_CUSTOM_CLOSE = 'defaultCustomClose', | ||
41 | + CUSTOM_ICON = 'customIcon', | ||
42 | + CUSTOM_ICON_CLOSE = 'customIconClose', | ||
39 | } | 43 | } |
@@ -20,6 +20,8 @@ | @@ -20,6 +20,8 @@ | ||
20 | import { useGetComponentConfig } from '../../../packages/hook/useGetComponetConfig'; | 20 | import { useGetComponentConfig } from '../../../packages/hook/useGetComponetConfig'; |
21 | import { isBoolean } from '/@/utils/is'; | 21 | import { isBoolean } from '/@/utils/is'; |
22 | import { useApp } from '../../hooks/useApp'; | 22 | import { useApp } from '../../hooks/useApp'; |
23 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | ||
24 | + import { deleteFilePath } from '/@/api/oss/ossFileUploader'; | ||
23 | 25 | ||
24 | const props = defineProps<{ | 26 | const props = defineProps<{ |
25 | sourceInfo: WidgetDataType; | 27 | sourceInfo: WidgetDataType; |
@@ -74,8 +76,56 @@ | @@ -74,8 +76,56 @@ | ||
74 | emit('update', toRaw(props.sourceInfo)); | 76 | emit('update', toRaw(props.sourceInfo)); |
75 | } | 77 | } |
76 | 78 | ||
79 | + const countElementOccurrences = (arr) => { | ||
80 | + const countMap = {}; | ||
81 | + | ||
82 | + arr.forEach((element) => { | ||
83 | + if (countMap[element]) { | ||
84 | + countMap[element]++; | ||
85 | + } else { | ||
86 | + countMap[element] = 1; | ||
87 | + } | ||
88 | + }); | ||
89 | + | ||
90 | + return countMap; | ||
91 | + }; | ||
92 | + | ||
77 | async function handleDelete() { | 93 | async function handleDelete() { |
78 | try { | 94 | try { |
95 | + const { componentData: oldDataSource } = props.rawDataSource; | ||
96 | + const customIconUrls = ref<any>([]); | ||
97 | + oldDataSource?.forEach((item: any) => { | ||
98 | + item.dataSource?.forEach((dataSource) => { | ||
99 | + if (dataSource.componentInfo?.customIcon) { | ||
100 | + dataSource.componentInfo?.customIcon.forEach((icon: FileItem) => { | ||
101 | + customIconUrls.value.push(icon.url); | ||
102 | + }); | ||
103 | + } | ||
104 | + }); | ||
105 | + }); | ||
106 | + | ||
107 | + const { dataSource: deleteDataSource } = props.sourceInfo; | ||
108 | + const dataSourceDeleteUrl = deleteDataSource.map( | ||
109 | + (item) => item.componentInfo.customIcon?.[0].url | ||
110 | + ); | ||
111 | + | ||
112 | + if (dataSourceDeleteUrl?.length) { | ||
113 | + // 判断外部所有组件是否有dataSourceDeleteUrl使用中的url | ||
114 | + const deletePromise = unref(customIconUrls)?.filter((item) => | ||
115 | + dataSourceDeleteUrl?.includes(item) | ||
116 | + ); | ||
117 | + | ||
118 | + const deleteUrlInfo = countElementOccurrences(deletePromise); | ||
119 | + const deleteUrl = deletePromise?.filter((item) => deleteUrlInfo?.[item] == 1); | ||
120 | + Promise.all( | ||
121 | + deleteUrl.map((item) => { | ||
122 | + deleteFilePath(item); | ||
123 | + }) | ||
124 | + ); | ||
125 | + } | ||
126 | + } catch (err) {} | ||
127 | + | ||
128 | + try { | ||
79 | await deleteDataComponent({ dataBoardId: unref(boardId), ids: [props.sourceInfo.id] }); | 129 | await deleteDataComponent({ dataBoardId: unref(boardId), ids: [props.sourceInfo.id] }); |
80 | createMessage.success('删除成功'); | 130 | createMessage.success('删除成功'); |
81 | emit('ok'); | 131 | emit('ok'); |