Commit 96568ed89c925d8a6613f143ebd9cefd7ec9e2f2
1 parent
90cd407d
perf: DEFECT-809 configuration center add thumbnail
Showing
7 changed files
with
91 additions
and
34 deletions
... | ... | @@ -6,8 +6,10 @@ import type { |
6 | 6 | ConfigurationCenterItemsModal, |
7 | 7 | } from './model/configurationCenterModal'; |
8 | 8 | import { getPageData } from '../../base'; |
9 | +import { FileUploadResponse } from '../../oem/model'; | |
9 | 10 | enum API { |
10 | 11 | basicUrl = '/configuration/center', |
12 | + UPLOAD = '/oss/upload', | |
11 | 13 | } |
12 | 14 | |
13 | 15 | export const getPage = (params: queryPageParams) => { |
... | ... | @@ -43,3 +45,7 @@ export const saveOrUpdateConfigurationCenter = ( |
43 | 45 | ) => { |
44 | 46 | return isUpdate ? updateConfigurationCenter(params) : saveConfigurationCenter(params); |
45 | 47 | }; |
48 | + | |
49 | +export const uploadThumbnail = (file: FormData) => { | |
50 | + return defHttp.post<FileUploadResponse>({ url: API.UPLOAD, params: file }); | |
51 | +}; | ... | ... |
src/assets/icons/configuration.svg
0 → 100644
1 | +<svg t="1667959039355" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2798" width="32" height="32"><path d="M860.068571 666.422857L726.857143 731.245714c-8.685714 4.205714-18.742857 4.205714-27.428572 0l-133.211428-64.822857A31.296 31.296 0 0 1 548.571429 638.262857V477.165714c0-11.977143 6.857143-22.948571 17.645714-28.16l133.211428-64.822857c8.685714-4.205714 18.742857-4.205714 27.428572 0l133.211428 64.822857c10.788571 5.211429 17.645714 16.182857 17.645715 28.16v161.097143c0 11.977143-6.857143 22.948571-17.645715 28.16z" fill="#B4D7FE" p-id="2799"></path><path d="M713.142857 701.988571V543.542857l-139.337143-68.571428M852.48 474.971429L713.142857 543.542857" fill="#B4D7FE" p-id="2800"></path><path d="M950.857143 146.285714H73.142857c-10.057143 0-18.285714 8.228571-18.285714 18.285715v621.714285c0 10.057143 8.228571 18.285714 18.285714 18.285715h205.714286v54.857142c0 10.057143 8.228571 18.285714 18.285714 18.285715h429.714286c10.057143 0 18.285714-8.228571 18.285714-18.285715v-54.857142H950.857143c10.057143 0 18.285714-8.228571 18.285714-18.285715V164.571429c0-10.057143-8.228571-18.285714-18.285714-18.285715zM708.571429 841.142857h-393.142858v-36.571428h393.142858v36.571428z m224-73.142857H91.428571V182.857143h841.142858v585.142857z" fill="#248BFF" p-id="2801"></path><path d="M182.857143 274.285714h201.142857v36.571429H182.857143z" fill="#B4D7FE" p-id="2802"></path><path d="M411.428571 237.714286H155.428571c-5.028571 0-9.142857 4.114286-9.142857 9.142857v457.142857c0 5.028571 4.114286 9.142857 9.142857 9.142857h256c5.028571 0 9.142857-4.114286 9.142858-9.142857V246.857143c0-5.028571-4.114286-9.142857-9.142858-9.142857z m-228.571428 36.571428h201.142857v36.571429H182.857143v-36.571429z m0 402.285715V347.428571h201.142857v329.142858H182.857143zM867.474286 452.571429l-146.285715-71.222858c-2.56-1.188571-5.302857-1.828571-8.045714-1.828571s-5.485714 0.64-8.045714 1.828571l-146.285714 71.222858c-6.217143 3.108571-10.24 9.417143-10.24 16.457142v177.371429c0 7.04 4.022857 13.348571 10.24 16.457143l146.285714 71.222857c2.56 1.188571 5.302857 1.828571 8.045714 1.828571s5.485714-0.64 8.045714-1.828571l146.285715-71.222857c6.308571-3.017143 10.24-9.417143 10.24-16.457143V469.028571c0-7.04-4.022857-13.348571-10.24-16.457142zM713.142857 418.102857l107.245714 52.205714-107.428571 52.937143c-0.64-0.365714-1.28-0.822857-1.92-1.097143l-105.142857-51.748571L713.142857 418.102857z m-128 82.834286l109.714286 54.034286v133.394285l-109.714286-53.394285V500.937143z m146.285714 187.428571V554.971429l109.714286-54.034286v134.034286l-109.714286 53.394285z" fill="#248BFF" p-id="2803"></path><path d="M347.428571 411.428571H219.428571c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h128c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285714zM859.428571 292.571429H484.571429c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h374.857142c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285715zM667.428571 356.571429H484.571429c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h182.857142c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285715zM548.571429 420.571429h-64c-10.057143 0-18.285714-8.228571-18.285715-18.285715s8.228571-18.285714 18.285715-18.285714h64c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285715zM237.714286 475.428571h-18.285715c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h18.285715c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285714z" fill="#248BFF" p-id="2804"></path><path d="M301.714286 539.428571h-82.285715c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h82.285715c10.057143 0 18.285714 8.228571 18.285714 18.285714s-8.228571 18.285714-18.285714 18.285714z" fill="#248BFF" p-id="2805"></path><path d="M274.285714 603.428571h-54.857143c-10.057143 0-18.285714-8.228571-18.285714-18.285714s8.228571-18.285714 18.285714-18.285714h54.857143c10.057143 0 18.285714 8.228571 18.285715 18.285714s-8.228571 18.285714-18.285715 18.285714z" fill="#248BFF" p-id="2806"></path></svg> | ... | ... |
src/assets/images/configuration.png
0 → 100644
871 Bytes
... | ... | @@ -4,10 +4,10 @@ |
4 | 4 | }; |
5 | 5 | </script> |
6 | 6 | <script lang="ts" setup> |
7 | - import { Upload, Spin } from 'ant-design-vue'; | |
7 | + import { Upload, Spin, Tooltip } from 'ant-design-vue'; | |
8 | 8 | import { InboxOutlined } from '@ant-design/icons-vue'; |
9 | 9 | import { useMessage } from '/@/hooks/web/useMessage'; |
10 | - import { computed, ref, unref, useAttrs } from 'vue'; | |
10 | + import { computed, ref, unref } from 'vue'; | |
11 | 11 | import { cloneDeep } from 'lodash-es'; |
12 | 12 | import { isFunction, isNumber, isObject } from '/@/utils/is'; |
13 | 13 | import { useDesign } from '/@/hooks/web/useDesign'; |
... | ... | @@ -23,8 +23,6 @@ |
23 | 23 | const { prefixCls } = useDesign('api-upload'); |
24 | 24 | const emit = defineEmits(['update:fileList', 'preview', 'download']); |
25 | 25 | |
26 | - const attrs = useAttrs(); | |
27 | - | |
28 | 26 | const { createMessage } = useMessage(); |
29 | 27 | |
30 | 28 | const loading = ref(false); |
... | ... | @@ -70,6 +68,16 @@ |
70 | 68 | return disabled ? disabled : unref(componentDisabled); |
71 | 69 | }); |
72 | 70 | |
71 | + const isPictureCard = computed(() => { | |
72 | + const { listType } = props; | |
73 | + return listType === 'picture-card'; | |
74 | + }); | |
75 | + | |
76 | + const getMaxFileLimit = computed(() => { | |
77 | + const { maxFileLimit } = props; | |
78 | + return isPictureCard.value ? 1 : maxFileLimit; | |
79 | + }); | |
80 | + | |
73 | 81 | const handleUpload = async (file: File | string | Blob | Promise<string | Blob | File>) => { |
74 | 82 | try { |
75 | 83 | setUploadStatus(true); |
... | ... | @@ -78,10 +86,10 @@ |
78 | 86 | if (api && isFunction(api)) { |
79 | 87 | const data = await api(file); |
80 | 88 | if (isObject(data) && Reflect.has(data, 'uid') && Reflect.has(data, 'name')) { |
81 | - const { fileList, maxFileLimit } = props; | |
89 | + const { fileList } = props; | |
82 | 90 | let _fileList = cloneDeep(fileList); |
83 | 91 | |
84 | - if (isNumber(maxFileLimit) && _fileList.length === maxFileLimit) { | |
92 | + if (isNumber(unref(getMaxFileLimit)) && _fileList.length === unref(getMaxFileLimit)) { | |
85 | 93 | _fileList.splice(0, 1); |
86 | 94 | } |
87 | 95 | |
... | ... | @@ -106,49 +114,36 @@ |
106 | 114 | emit('update:fileList', _fileList); |
107 | 115 | }; |
108 | 116 | |
109 | - const defaultPreview = (file: FileItem) => { | |
110 | - console.log('default preview', file); | |
111 | - }; | |
112 | - | |
113 | - const defaultDownload = (file: FileItem) => { | |
114 | - console.log('default download', file); | |
115 | - }; | |
116 | - | |
117 | 117 | const handlePreview = (file: FileItem) => { |
118 | - if (Reflect.has(attrs, 'preview')) { | |
119 | - emit('preview', file); | |
120 | - return; | |
121 | - } | |
122 | - defaultPreview(file); | |
118 | + emit('preview', file); | |
123 | 119 | }; |
124 | 120 | |
125 | 121 | const handleDownload = (file: FileItem) => { |
126 | - if (Reflect.has(attrs, 'download')) { | |
127 | - emit('download', file); | |
128 | - return; | |
129 | - } | |
130 | - defaultDownload(file); | |
122 | + emit('download', file); | |
131 | 123 | }; |
132 | 124 | </script> |
133 | 125 | |
134 | 126 | <template> |
135 | - <Upload.Dragger | |
127 | + <Upload | |
136 | 128 | class="block" |
137 | 129 | :class="prefixCls" |
138 | 130 | :file-list="props.fileList" |
131 | + :list-type="props.listType" | |
139 | 132 | :disabled="getDisabled" |
140 | 133 | :before-upload="handleBeforeUpload" |
141 | 134 | @preview="handlePreview" |
142 | 135 | @download="handleDownload" |
143 | 136 | :remove="handleRemove" |
144 | 137 | > |
145 | - <Spin :spinning="loading"> | |
138 | + <Spin v-if="!fileList.length" :spinning="loading"> | |
146 | 139 | <div class="w-full h-full flex flex-col justify-center content-center"> |
147 | - <InboxOutlined class="text-[3rem] !text-blue-500" /> | |
148 | - <div class="m-2 text-gray-400">点击上传或拖拽上传</div> | |
140 | + <Tooltip title="点击上传或拖拽上传"> | |
141 | + <InboxOutlined class="text-[3rem] !text-blue-500" /> | |
142 | + </Tooltip> | |
143 | + <div v-if="!isPictureCard" class="m-2 text-gray-400 text-sm">点击上传或拖拽上传</div> | |
149 | 144 | </div> |
150 | 145 | </Spin> |
151 | - </Upload.Dragger> | |
146 | + </Upload> | |
152 | 147 | </template> |
153 | 148 | |
154 | 149 | <style lang="less"> |
... | ... | @@ -164,6 +159,12 @@ |
164 | 159 | .ant-upload-list-item-name { |
165 | 160 | width: calc(100% - 22px); |
166 | 161 | } |
162 | + | |
163 | + .ant-upload-select-text { | |
164 | + width: 100%; | |
165 | + text-align: center; | |
166 | + border: 1px dashed #d9d9d9; | |
167 | + } | |
167 | 168 | } |
168 | 169 | } |
169 | 170 | </style> | ... | ... |
... | ... | @@ -17,6 +17,8 @@ |
17 | 17 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
18 | 18 | import { useMessage } from '/@/hooks/web/useMessage'; |
19 | 19 | import { saveOrUpdateConfigurationCenter } from '/@/api/configuration/center/configurationCenter'; |
20 | + import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | |
21 | + import { buildUUID } from '/@/utils/uuid'; | |
20 | 22 | |
21 | 23 | export default defineComponent({ |
22 | 24 | name: 'ConfigurationDrawer', |
... | ... | @@ -36,6 +38,11 @@ |
36 | 38 | setDrawerProps({ confirmLoading: false }); |
37 | 39 | isUpdate.value = !!data?.isUpdate; |
38 | 40 | if (unref(isUpdate)) { |
41 | + if (data.record.thumbnail) { | |
42 | + data.record.thumbnail = [ | |
43 | + { uid: buildUUID(), name: 'name', url: data.record.thumbnail } as FileItem, | |
44 | + ]; | |
45 | + } | |
39 | 46 | if (data.record.organizationDTO) { |
40 | 47 | await setFieldsValue(data.record); |
41 | 48 | } else { |
... | ... | @@ -51,9 +58,14 @@ |
51 | 58 | try { |
52 | 59 | const { createMessage } = useMessage(); |
53 | 60 | const values = await validate(); |
61 | + if (Reflect.has(values, 'thumbnail')) { | |
62 | + const file = (values.thumbnail || []).at(0) || {}; | |
63 | + values.thumbnail = file.url || null; | |
64 | + } | |
54 | 65 | setDrawerProps({ confirmLoading: true }); |
55 | 66 | let saveMessage = '添加成功'; |
56 | 67 | let updateMessage = '修改成功'; |
68 | + console.log(values); | |
57 | 69 | await saveOrUpdateConfigurationCenter(values, unref(isUpdate)); |
58 | 70 | closeDrawer(); |
59 | 71 | emit('success'); | ... | ... |
1 | 1 | import { BasicColumn, FormSchema } from '/@/components/Table'; |
2 | 2 | import { getOrganizationList } from '/@/api/system/system'; |
3 | 3 | import { copyTransFun } from '/@/utils/fnUtils'; |
4 | +import { FileItem } from '/@/components/Form/src/components/ApiUpload.vue'; | |
5 | +import { createImgPreview } from '/@/components/Preview'; | |
6 | +import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter'; | |
4 | 7 | export enum Platform { |
5 | 8 | PHONE = 'phone', |
6 | 9 | PC = 'pc', |
... | ... | @@ -64,6 +67,37 @@ export const searchFormSchema: FormSchema[] = [ |
64 | 67 | |
65 | 68 | export const formSchema: FormSchema[] = [ |
66 | 69 | { |
70 | + field: 'thumbnail', | |
71 | + label: '缩略图', | |
72 | + component: 'ApiUpload', | |
73 | + changeEvent: 'update:fileList', | |
74 | + valueField: 'fileList', | |
75 | + componentProps: () => { | |
76 | + return { | |
77 | + listType: 'picture-card', | |
78 | + maxFileLimit: 1, | |
79 | + api: async (file: File) => { | |
80 | + try { | |
81 | + const formData = new FormData(); | |
82 | + formData.set('file', file); | |
83 | + const { fileStaticUri, fileName } = await uploadThumbnail(formData); | |
84 | + return { | |
85 | + uid: fileStaticUri, | |
86 | + name: fileName, | |
87 | + url: fileStaticUri, | |
88 | + } as FileItem; | |
89 | + } catch (error) { | |
90 | + return {}; | |
91 | + } | |
92 | + }, | |
93 | + onPreview: (fileList: FileItem) => { | |
94 | + createImgPreview({ imageList: [fileList.url!] }); | |
95 | + }, | |
96 | + }; | |
97 | + }, | |
98 | + }, | |
99 | + | |
100 | + { | |
67 | 101 | field: 'name', |
68 | 102 | label: '组态名称', |
69 | 103 | required: true, | ... | ... |
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | import { useSyncConfirm } from '/@/hooks/component/useSyncConfirm'; |
27 | 27 | import { getBoundingClientRect } from '/@/utils/domUtils'; |
28 | 28 | import configurationSrc from '/@/assets/icons/configuration.svg'; |
29 | + import { cloneDeep } from 'lodash'; | |
29 | 30 | |
30 | 31 | const listColumn = ref(4); |
31 | 32 | |
... | ... | @@ -99,7 +100,7 @@ |
99 | 100 | if (record) { |
100 | 101 | openDrawer(true, { |
101 | 102 | isUpdate: true, |
102 | - record, | |
103 | + record: cloneDeep(record), | |
103 | 104 | }); |
104 | 105 | } else { |
105 | 106 | openDrawer(true, { |
... | ... | @@ -205,9 +206,9 @@ |
205 | 206 | <Card hoverable> |
206 | 207 | <template #cover> |
207 | 208 | <img |
208 | - class="w-48 h-48 flex justify-center items-center" | |
209 | + class="w-36 h-36 flex justify-center items-center" | |
209 | 210 | alt="example" |
210 | - :src="configurationSrc" | |
211 | + :src="item.thumbnail || configurationSrc" | |
211 | 212 | /> |
212 | 213 | </template> |
213 | 214 | <template class="ant-card-actions" #actions> |
... | ... | @@ -244,8 +245,10 @@ |
244 | 245 | </template> |
245 | 246 | <Card.Meta :title="item.name"> |
246 | 247 | <template #description> |
247 | - <div class="truncate">{{ item.organizationDTO.name }}</div> | |
248 | - <div class="truncate">{{ item.remark }} </div> | |
248 | + <div class="truncate h-11"> | |
249 | + <div class="truncate">{{ item.organizationDTO.name }}</div> | |
250 | + <div class="truncate">{{ item.remark || '' }} </div> | |
251 | + </div> | |
249 | 252 | </template> |
250 | 253 | </Card.Meta> |
251 | 254 | </Card> | ... | ... |