Commit 67d1de3831df2c6d6446ccfdcb6e177bf6b4a6c6

Authored by 张 峰林
Committed by xp.Huang
1 parent b1aeeabc

fix: 看板组件图标能使用自定义图标

... ... @@ -71,9 +71,12 @@
71 71 return false;
72 72 }
73 73 }
74   -
75 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 80 return false;
78 81 }
79 82 handleUpload(file);
... ...
... ... @@ -30,7 +30,7 @@
30 30 auth: 'api:yt:sceneLinkage:update',
31 31 icon: 'clarity:note-edit-line',
32 32 onClick: handleEdit.bind(null, record),
33   - ifShow: record.status !== 1 && record.isEdge !== 1,
  33 + ifShow: record.status !== 1,
34 34 },
35 35 ]"
36 36 :drop-down-actions="[
... ... @@ -39,7 +39,7 @@
39 39 auth: 'api:yt:sceneLinkage:delete',
40 40 icon: 'ant-design:delete-outlined',
41 41 color: 'error',
42   - ifShow: record.status !== 1 && record.isEdge !== 1,
  42 + ifShow: record.status !== 1,
43 43 popConfirm: {
44 44 title: '是否确认删除',
45 45 confirm: handleDeleteOrBatchDelete.bind(null, record),
... ... @@ -56,7 +56,6 @@
56 56 :loading="record.pendingStatus"
57 57 checkedChildren="启用"
58 58 unCheckedChildren="禁用"
59   - :disabled="record.isEdge === 1"
60 59 @change="(checked:boolean)=>statusChange(checked,record)"
61 60 />
62 61 </Authority>
... ...
... ... @@ -56,7 +56,7 @@
56 56 </script>
57 57
58 58 <template>
59   - <BasicModal @register="register" title="组件设置" @ok="handleOk">
  59 + <BasicModal @register="register" title="组件设置" @ok="handleOk" :width="700">
60 60 <!-- -->
61 61 <component ref="settingFormEl" :is="getSettingComponent" />
62 62 </BasicModal>
... ...
... ... @@ -29,6 +29,8 @@
29 29 import { MessageAlert } from './components/MessageAlert';
30 30 import { createSelectWidgetKeysContext, createSelectWidgetModeContext } from './useContext';
31 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 35 const props = defineProps<{
34 36 layout: Layout[];
... ... @@ -227,6 +229,20 @@
227 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 246 const handleSubmit = async () => {
231 247 const validateResult = await validate();
232 248 if (validateResult && !validateResult.flag) {
... ... @@ -241,6 +257,59 @@
241 257 }
242 258 }
243 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 313 try {
245 314 loading.value = true;
246 315 unref(currentMode) === DataActionModeEnum.UPDATE
... ...
... ... @@ -3,15 +3,68 @@
3 3 import { useForm, BasicForm } from '/@/components/Form';
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 10 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 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 60 field: ComponentConfigFieldEnum.ICON_COLOR,
11 61 label: '图标颜色',
12 62 component: 'ColorPicker',
13 63 changeEvent: 'update:value',
14 64 defaultValue: option.iconColor,
  65 + ifShow: ({ model }) => {
  66 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  67 + },
15 68 },
16 69 {
17 70 field: ComponentConfigFieldEnum.ICON,
... ... @@ -19,6 +72,9 @@
19 72 component: 'IconDrawer',
20 73 changeEvent: 'update:value',
21 74 defaultValue: option.icon,
  75 + ifShow: ({ model }) => {
  76 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  77 + },
22 78 componentProps({ formModel }) {
23 79 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR];
24 80 return {
... ... @@ -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 133 showActionButtonGroup: false,
... ...
... ... @@ -31,7 +31,7 @@
31 31 fontSize: persetFontSize,
32 32 password: persetPassword,
33 33 } = persetOption || {};
34   - const { icon, iconColor, fontSize, password } = componentInfo || {};
  34 + const { icon, iconColor, fontSize, password, customIcon, defaultCustom } = componentInfo || {};
35 35
36 36 const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
37 37 return {
... ... @@ -41,6 +41,8 @@
41 41 fontSize: fontSize || persetFontSize || 14,
42 42 password: password || persetPassword,
43 43 commandType,
  44 + defaultCustom: defaultCustom || 'default',
  45 + customIcon: customIcon || [],
44 46 };
45 47 });
46 48
... ... @@ -81,10 +83,17 @@
81 83 <main class="w-full h-full flex justify-around items-center" :style="getScale">
82 84 <div class="flex flex-col justify-center items-center">
83 85 <SvgIcon
84   - :name="getDesign.icon"
  86 + v-if="getDesign.defaultCustom !== 'custom'"
  87 + :name="getDesign.icon!"
85 88 prefix="iconfont"
86   - :style="{ color: getDesign.iconColor }"
87 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 98 <span
90 99 class="mt-3 truncate text-gray-500 text-center"
... ...
... ... @@ -3,30 +3,13 @@
3 3 import { useForm, BasicForm } from '/@/components/Form';
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 10 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 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 13 field: ComponentConfigFieldEnum.FONT_SIZE,
31 14 label: '文本字体大小',
32 15 component: 'InputNumber',
... ... @@ -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 37 field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,
49 38 label: '显示设备名称',
50 39 component: 'Checkbox',
51 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 133 showActionButtonGroup: false,
... ...
... ... @@ -38,8 +38,17 @@
38 38 } = persetOption || {};
39 39 return {
40 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 52 const {
44 53 attribute,
45 54 attributeRename,
... ... @@ -76,6 +85,8 @@
76 85 closeCommand,
77 86 openService,
78 87 closeService,
  88 + defaultCustom: defaultCustom || 'default',
  89 + customIcon: customIcon || [],
79 90 } as SwitchItemType;
80 91 }),
81 92 };
... ... @@ -128,11 +139,24 @@
128 139 :key="item.id"
129 140 class="flex justify-between items-center w-full px-4"
130 141 >
131   - <SvgIcon
  142 + <!-- <SvgIcon
132 143 :name="item.icon!"
133 144 prefix="iconfont"
134 145 :size="getRatio ? 30 * getRatio : 30"
135 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 161 <div
138 162 class="text-gray-500 truncate mx-2"
... ...
... ... @@ -3,15 +3,68 @@
3 3 import { useForm, BasicForm } from '/@/components/Form';
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 10 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 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 60 field: ComponentConfigFieldEnum.ICON,
11 61 label: '开启状态图标',
12 62 component: 'IconDrawer',
13 63 changeEvent: 'update:value',
14 64 defaultValue: option.icon,
  65 + ifShow: ({ model }) => {
  66 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  67 + },
15 68 componentProps({ formModel }) {
16 69 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR];
17 70 return {
... ... @@ -24,6 +77,9 @@
24 77 label: '开启图标颜色',
25 78 component: 'ColorPicker',
26 79 changeEvent: 'update:value',
  80 + ifShow: ({ model }) => {
  81 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  82 + },
27 83 defaultValue: option.iconColor,
28 84 },
29 85 {
... ... @@ -32,6 +88,9 @@
32 88 component: 'IconDrawer',
33 89 changeEvent: 'update:value',
34 90 defaultValue: option.iconClose,
  91 + ifShow: ({ model }) => {
  92 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  93 + },
35 94 componentProps({ formModel }) {
36 95 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR_CLOSE];
37 96 return {
... ... @@ -44,37 +103,84 @@
44 103 label: '关闭图标颜色',
45 104 component: 'ColorPicker',
46 105 changeEvent: 'update:value',
  106 + ifShow: ({ model }) => {
  107 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  108 + },
47 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 186 showActionButtonGroup: false,
... ...
... ... @@ -32,8 +32,19 @@
32 32
33 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 48 return {
38 49 iconColor: iconColor || persetIconColor,
39 50 unit: unit ?? perseUnit,
... ... @@ -44,6 +55,9 @@
44 55 iconColorClose: iconColorClose || persetIconColorClose,
45 56 showTime: showTime ?? persetShowTime,
46 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 82 <DeviceName :config="config" />
69 83 <div class="flex flex-1 flex-col justify-center items-center">
70 84 <SvgIcon
  85 + v-if="getDesign.defaultCustom !== 'custom'"
71 86 :name="isOpenClose ? getDesign.icon : getDesign.iconClose"
72 87 prefix="iconfont"
73 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 97 <div
77 98 class="text-gray-500 truncate m-2"
... ...
... ... @@ -3,6 +3,9 @@
3 3 import { useForm, BasicForm } from '/@/components/Form';
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 10 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 11 schemas: [
... ... @@ -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 90 field: ComponentConfigFieldEnum.ICON_COLOR,
65 91 label: '图标颜色',
66 92 component: 'ColorPicker',
67 93 changeEvent: 'update:value',
68 94 defaultValue: option.iconColor,
  95 + ifShow: ({ model }) => {
  96 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  97 + },
69 98 },
70 99 {
71 100 field: ComponentConfigFieldEnum.ICON,
... ... @@ -73,6 +102,9 @@
73 102 component: 'IconDrawer',
74 103 changeEvent: 'update:value',
75 104 defaultValue: option.icon,
  105 + ifShow: ({ model }) => {
  106 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  107 + },
76 108 componentProps({ formModel }) {
77 109 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR];
78 110 return {
... ... @@ -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 162 showActionButtonGroup: false,
... ...
... ... @@ -31,7 +31,6 @@
31 31
32 32 const getDesign = computed(() => {
33 33 const { persetOption = {}, option } = props.config;
34   -
35 34 const {
36 35 iconColor: persetIconColor,
37 36 unit: perseUnit,
... ... @@ -44,7 +43,8 @@
44 43 const { componentInfo, attributeRename } = option;
45 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 48 return {
49 49 iconColor: iconColor || persetIconColor,
50 50 unit: unit ?? perseUnit,
... ... @@ -53,6 +53,8 @@
53 53 attribute: attributeRename || functionName,
54 54 valueSize: valueSize || persetValueSize || 20,
55 55 fontSize: fontSize || persetFontSize || 14,
  56 + defaultCustom: defaultCustom || 'default',
  57 + customIcon: customIcon || [],
56 58 };
57 59 });
58 60
... ... @@ -78,11 +80,18 @@
78 80 <DeviceName :config="config" />
79 81 <div class="flex-1 flex justify-center items-center flex-col w-full">
80 82 <SvgIcon
  83 + v-if="getDesign.defaultCustom !== 'custom'"
81 84 :name="getDesign.icon!"
82 85 prefix="iconfont"
83 86 :size="getRatio ? getRatio * 70 : 70"
84 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 95 <h1
87 96 class="font-bold m-2 truncate w-full text-center"
88 97 :style="{
... ...
... ... @@ -3,6 +3,9 @@
3 3 import { useForm, BasicForm } from '/@/components/Form';
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 10 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 11 schemas: [
... ... @@ -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 89 field: ComponentConfigFieldEnum.ICON_COLOR,
64 90 label: '图标颜色',
65 91 component: 'ColorPicker',
66 92 changeEvent: 'update:value',
67 93 defaultValue: option.iconColor,
  94 + ifShow: ({ model }) => {
  95 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  96 + },
68 97 },
69 98 {
70 99 field: ComponentConfigFieldEnum.ICON,
... ... @@ -72,6 +101,9 @@
72 101 component: 'IconDrawer',
73 102 changeEvent: 'update:value',
74 103 defaultValue: option.icon,
  104 + ifShow: ({ model }) => {
  105 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  106 + },
75 107 componentProps({ formModel }) {
76 108 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR];
77 109 return {
... ... @@ -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 161 showActionButtonGroup: false,
... ...
... ... @@ -40,7 +40,8 @@
40 40
41 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 45 return {
45 46 iconColor: iconColor || persetIconColor,
46 47 unit: unit ?? perseUnit,
... ... @@ -49,6 +50,8 @@
49 50 attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute,
50 51 valueSize: valueSize || persetValueSize || 20,
51 52 fontSize: fontSize || persetFontSize || 14,
  53 + defaultCustom: defaultCustom || 'default',
  54 + customIcon: customIcon || [],
52 55 };
53 56 });
54 57
... ... @@ -73,11 +76,18 @@
73 76 <DeviceName :config="config" />
74 77 <div :style="getScale" class="flex-1 flex justify-center items-center flex-col w-full">
75 78 <SvgIcon
  79 + v-if="getDesign.defaultCustom !== 'custom'"
76 80 :name="getDesign.icon!"
77 81 prefix="iconfont"
78 82 :size="getRatio ? getRatio * 70 : 70"
79 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 91 <h1
82 92 class="my-4 font-bold !my-2 truncate w-full text-center"
83 93 :style="{
... ...
... ... @@ -4,6 +4,10 @@
4 4 import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type';
5 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 11 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
8 12 schemas: [
9 13 {
... ... @@ -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 84 field: ComponentConfigFieldEnum.ICON_COLOR,
64 85 label: '图标颜色',
65 86 component: 'ColorPicker',
66 87 changeEvent: 'update:value',
67 88 defaultValue: option.iconColor,
  89 + ifShow: ({ model }) => {
  90 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  91 + },
68 92 },
69 93 {
70 94 field: ComponentConfigFieldEnum.ICON,
... ... @@ -73,6 +97,9 @@
73 97 changeEvent: 'update:value',
74 98 valueField: 'value',
75 99 defaultValue: option.icon,
  100 + ifShow: ({ model }) => {
  101 + return model[ComponentConfigFieldEnum.DEFAULT_CUSTOM] !== 'custom';
  102 + },
76 103 componentProps({ formModel }) {
77 104 const color = formModel[ComponentConfigFieldEnum.ICON_COLOR];
78 105 return {
... ... @@ -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 156 showActionButtonGroup: false,
85 157 labelWidth: 120,
... ...
... ... @@ -35,7 +35,8 @@
35 35
36 36 return {
37 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 40 const { attribute, attributeRename, deviceName, deviceRename, deviceId, deviceProfileId } =
40 41 item;
41 42 const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
... ... @@ -50,6 +51,8 @@
50 51 id: deviceId,
51 52 valueSize: valueSize || persetValueSize || 20,
52 53 fontSize: fontSize || persetFontSize || 14,
  54 + defaultCustom: defaultCustom || 'default',
  55 + customIcon: customIcon || [],
53 56 };
54 57 }),
55 58 };
... ... @@ -67,6 +70,8 @@
67 70 fontColor: '#357CFB',
68 71 fontSize: 16,
69 72 valueSize: 16,
  73 + defaultCustom: 'default',
  74 + customIcon: [],
70 75 },
71 76 {
72 77 id: buildUUID(),
... ... @@ -79,6 +84,8 @@
79 84 fontColor: '#FFA000',
80 85 fontSize: 16,
81 86 valueSize: 16,
  87 + defaultCustom: 'default',
  88 + customIcon: [],
82 89 },
83 90 ]);
84 91
... ... @@ -114,11 +121,24 @@
114 121 class="flex justify-between items-center mt-2"
115 122 >
116 123 <div class="flex items-center">
117   - <SvgIcon
  124 + <!-- <SvgIcon
118 125 :name="item.icon!"
119 126 prefix="iconfont"
120 127 :size="getRatio ? 30 * getRatio : 30"
121 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 143 <div
124 144 class="text-gray-500 ml-6"
... ...
... ... @@ -36,4 +36,8 @@ export enum ComponentConfigFieldEnum {
36 36 MIN_NUMBER = 'minNumber',
37 37 MAX_NUMBER = 'maxNumber',
38 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 20 import { useGetComponentConfig } from '../../../packages/hook/useGetComponetConfig';
21 21 import { isBoolean } from '/@/utils/is';
22 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 26 const props = defineProps<{
25 27 sourceInfo: WidgetDataType;
... ... @@ -74,8 +76,56 @@
74 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 93 async function handleDelete() {
78 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 129 await deleteDataComponent({ dataBoardId: unref(boardId), ids: [props.sourceInfo.id] });
80 130 createMessage.success('删除成功');
81 131 emit('ok');
... ...