el-plus-crud 0.0.74 → 0.0.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/el-plus-crud.mjs +10 -10
- package/example/App.vue +69 -68
- package/lib/components/el-plus-form/ElPlusForm.vue +2 -1
- package/lib/components/el-plus-form/ElPlusFormDialog.vue +90 -89
- package/lib/components/el-plus-form/ElPlusFormGroup.vue +2 -1
- package/lib/components/el-plus-form/components/ElPlusFormBtn.vue +2 -1
- package/lib/components/el-plus-form/components/ElPlusFormBtns.vue +2 -1
- package/lib/components/el-plus-form/components/ElPlusFormFile.vue +49 -48
- package/lib/components/el-plus-form/components/ElPlusFormInput.vue +64 -63
- package/lib/components/el-plus-form/components/ElPlusFormLink.vue +284 -283
- package/lib/components/el-plus-form/components/ElPlusFormLkuser.vue +492 -491
- package/lib/components/el-plus-form/components/ElPlusFormNumber.vue +149 -148
- package/lib/components/el-plus-form/components/ElPlusFormPassword.vue +46 -45
- package/lib/components/el-plus-form/components/ElPlusFormQuickInput.vue +98 -97
- package/lib/components/el-plus-form/components/ElPlusFormSelect.vue +164 -163
- package/lib/components/el-plus-form/components/ElPlusFormTextarea.vue +52 -51
- package/lib/components/el-plus-form/components/ElPlusFormUpbtn.vue +146 -145
- package/lib/components/el-plus-form/components/ElPlusFormUpload.vue +371 -370
- package/lib/components/el-plus-form/components/components/file-icons/FileIcons.vue +137 -136
- package/lib/components/el-plus-table/ElPlusTable.vue +2 -1
- package/lib/components/el-plus-table/components/columnItem.vue +214 -213
- package/lib/components/el-plus-table/components/header.vue +2 -1
- package/lib/components/el-plus-table/components/settingColumn.vue +180 -179
- package/lib/components/el-plus-table/util/index.ts +148 -148
- package/lib/config/index.ts +32 -32
- package/lib/index.ts +52 -52
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/types/global.d.ts +13 -13
- package/types/{formList.d.ts → index.d.ts} +1 -0
|
@@ -1,370 +1,371 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="ele-form-upload-image" :class="{ 'ele-form-upload-file': desc.upType === 'file' }">
|
|
3
|
-
<el-upload class="ele-image-upload" v-bind="attrs" v-on="onEvents" :disabled="disabled" :fileList="currentValue || []" :class="{ 'over-limit': currentValue?.length >= attrs.limit, 'upload-disabled': attrs.disabled }">
|
|
4
|
-
<div class="upload-panel-icon">
|
|
5
|
-
<i v-if="desc.icon" :class="desc.icon" :style="{ fontSize: desc.fontSize || '14px', color: desc.color || '#C0C4CC' }"></i>
|
|
6
|
-
<el-icon v-else :style="{ fontSize: desc.fontSize || '14px', color: desc.color || '#C0C4CC' }"><Plus /></el-icon>
|
|
7
|
-
<div class="el-upload__text2" v-if="desc.upType === 'file' && desc.text2">
|
|
8
|
-
{{ desc.text2 }}
|
|
9
|
-
</div>
|
|
10
|
-
<div class="el-upload__text" v-if="desc.upType === 'file'">
|
|
11
|
-
{{ desc.text || '拖拽/点击上传' }}
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
<!-- <template #file="file">
|
|
15
|
-
<UploadShowIcon :file="file"></UploadShowIcon>
|
|
16
|
-
</template> -->
|
|
17
|
-
</el-upload>
|
|
18
|
-
|
|
19
|
-
<!-- 图片查看的站位标签 -->
|
|
20
|
-
<el-image-viewer v-if="showPreview" @close="showPreview = false" teleported :initialIndex="previewIndex" :url-list="previewList" />
|
|
21
|
-
<div v-if="!attrs.autoUpload" class="upload-hands-submit">
|
|
22
|
-
<el-button style="margin-left: 10px" size="small" type="success" @click="submit" :disabled="disabled"> 上传到服务器 </el-button>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
</template>
|
|
26
|
-
<script lang="ts">
|
|
27
|
-
export default {
|
|
28
|
-
name: 'ElPlusFormUpload',
|
|
29
|
-
inheritAttrs: false,
|
|
30
|
-
typeName: 'upload',
|
|
31
|
-
customOptions: {}
|
|
32
|
-
}
|
|
33
|
-
</script>
|
|
34
|
-
<script lang="ts" setup>
|
|
35
|
-
import { ref, computed, useAttrs, onBeforeMount, watch, inject } from 'vue'
|
|
36
|
-
import { getAttrs, getEvents } from '../mixins'
|
|
37
|
-
import { ElMessage, UploadUserFile } from 'element-plus'
|
|
38
|
-
import { Plus } from '@element-plus/icons-vue'
|
|
39
|
-
|
|
40
|
-
import * as fileTypes from '../data/file'
|
|
41
|
-
|
|
42
|
-
// 引入图标
|
|
43
|
-
import excel from '../images/icon/excel.png'
|
|
44
|
-
import pdf from '../images/icon/pdf.png'
|
|
45
|
-
import file from '../images/icon/file.png'
|
|
46
|
-
import txt from '../images/icon/txt.png'
|
|
47
|
-
import word from '../images/icon/word.png'
|
|
48
|
-
import zip from '../images/icon/zip.png'
|
|
49
|
-
import ppt from '../images/icon/ppt.png'
|
|
50
|
-
import { ICRUDConfig, IOssInfo } from 'types
|
|
51
|
-
|
|
52
|
-
const defaultConf = inject('defaultConf') as ICRUDConfig
|
|
53
|
-
|
|
54
|
-
// 图标Map
|
|
55
|
-
const iconMap = { excel, pdf, file, txt, word, zip, ppt }
|
|
56
|
-
|
|
57
|
-
const props = defineProps<{
|
|
58
|
-
modelValue?: Array<IOssInfo>
|
|
59
|
-
field: string
|
|
60
|
-
loading?: boolean
|
|
61
|
-
desc: { [key: string]: any }
|
|
62
|
-
formData: { [key: string]: any }
|
|
63
|
-
disabled?: boolean
|
|
64
|
-
}>()
|
|
65
|
-
|
|
66
|
-
const emits = defineEmits(['update:modelValue', 'validateThis'])
|
|
67
|
-
const currentValue = ref((typeof props.modelValue === 'string' ? [{ url: props.modelValue }] : props.modelValue) || [])
|
|
68
|
-
|
|
69
|
-
emits('update:modelValue', currentValue)
|
|
70
|
-
|
|
71
|
-
const attrs = ref({} as any)
|
|
72
|
-
const onEvents = ref(getEvents(props))
|
|
73
|
-
|
|
74
|
-
const showPreview = ref(false)
|
|
75
|
-
const previewIndex = ref(0)
|
|
76
|
-
const previewList = computed(() =>
|
|
77
|
-
currentValue.value
|
|
78
|
-
.map((item: any) => {
|
|
79
|
-
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(item.raw?.suffix || item.suffix) >= 0) {
|
|
80
|
-
return item.url
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
.filter((url) => url)
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
onBeforeMount(async () => {
|
|
87
|
-
// // 如果没有配置,则抛出一个警告
|
|
88
|
-
if (!defaultConf.upload || (!defaultConf.upload.action && !defaultConf.upload.minio?.getObjectAuthUrl)) {
|
|
89
|
-
console.warn('缺少文件上传配置,无法使用upload组件~')
|
|
90
|
-
}
|
|
91
|
-
attrs.value = await getAttrs(props, {
|
|
92
|
-
drag: true,
|
|
93
|
-
listType: props.desc.upType === 'file' ? 'text' : 'picture-card',
|
|
94
|
-
multiple: !!props.desc.multiple,
|
|
95
|
-
limit: props.desc.multiple ? props.desc.limit || 20 : 1,
|
|
96
|
-
autoUpload: props.desc.autoUpload ?? true,
|
|
97
|
-
accept: props.desc.accept || fileTypes[`${props.desc.upType || 'image'}Types`].join(','),
|
|
98
|
-
maxSize: props.desc.maxSize || (props.desc.upType === 'file' ? defaultConf.upload?.maxFSize : defaultConf.upload?.maxISize),
|
|
99
|
-
beforeUpload: handelUploadBefore,
|
|
100
|
-
onRemove: handelUploadRemove,
|
|
101
|
-
onSuccess: handelUploadSuccess,
|
|
102
|
-
onExceed: handleOutOfLimit,
|
|
103
|
-
onPreview: handelPreview,
|
|
104
|
-
httpRequest: handelRequest,
|
|
105
|
-
...useAttrs()
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* 处理删除
|
|
111
|
-
* @param file
|
|
112
|
-
* @param fileList
|
|
113
|
-
*/
|
|
114
|
-
function handelUploadRemove(file: UploadUserFile) {
|
|
115
|
-
handelListChange(file, 0)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* 上传成功回调
|
|
120
|
-
* @param _
|
|
121
|
-
* @param file
|
|
122
|
-
* @param fileList
|
|
123
|
-
*/
|
|
124
|
-
async function handelUploadSuccess(_: any, file: any) {
|
|
125
|
-
const { objectUrl, previewUrl } = await defaultConf.upload?.minio?.getObjectAuthUrl(file.raw.uploadId)
|
|
126
|
-
file.raw.shareUrl = objectUrl
|
|
127
|
-
file.raw.previewUrl = previewUrl
|
|
128
|
-
file.url = getFileIcon(file.raw)
|
|
129
|
-
// console.log('handelUploadSuccess: file: ', file)
|
|
130
|
-
handelListChange(file, 1)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 获取文件Icon
|
|
135
|
-
* @param file
|
|
136
|
-
*/
|
|
137
|
-
function getFileIcon(file?: any): string {
|
|
138
|
-
if (file) {
|
|
139
|
-
const suffix = (file?.suffix || '') as string
|
|
140
|
-
if (suffix) {
|
|
141
|
-
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(suffix) >= 0) {
|
|
142
|
-
// return (props.desc.upType === 'file' ? file.previewUrl : file.shareUrl) || file.furl || file.path
|
|
143
|
-
return file.shareUrl || file.furl || file.path
|
|
144
|
-
}
|
|
145
|
-
for (let i = 0; i < fileTypes.suffixTypes.length; i++) {
|
|
146
|
-
for (let j = 0; j < fileTypes.suffixTypes[i].suffixes.length; j++) {
|
|
147
|
-
if (fileTypes.suffixTypes[i].suffixes[j] === suffix) {
|
|
148
|
-
return iconMap[fileTypes.suffixTypes[i].type]
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return iconMap.file
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* 处理图片列表的修改
|
|
159
|
-
* @param file
|
|
160
|
-
* @param type 0 : 删除; 1: 新增
|
|
161
|
-
*/
|
|
162
|
-
function handelListChange(item: UploadUserFile, type: 0 | 1) {
|
|
163
|
-
if (type === 1) {
|
|
164
|
-
currentValue.value.push({
|
|
165
|
-
name: item.name,
|
|
166
|
-
furl: (item.raw as any)?.path || item.url,
|
|
167
|
-
url: getFileIcon(item.raw),
|
|
168
|
-
fsize: item.size,
|
|
169
|
-
uid: item.uid,
|
|
170
|
-
mimeType: item.raw?.type,
|
|
171
|
-
suffix: (item.raw as any).suffix,
|
|
172
|
-
busId: props.desc.busId,
|
|
173
|
-
busType: props.desc.busType
|
|
174
|
-
})
|
|
175
|
-
} else {
|
|
176
|
-
const index = currentValue.value.findIndex((file) => file.uid === item.uid)
|
|
177
|
-
if (index >= 0) {
|
|
178
|
-
currentValue.value.splice(index, 1)
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
emits('validateThis')
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* 上传之前,校验文件大小以及类型
|
|
186
|
-
* @param file
|
|
187
|
-
*/
|
|
188
|
-
async function handelUploadBefore(file: any) {
|
|
189
|
-
file.suffix = (file.name as string).substring(file.name.lastIndexOf('.'))
|
|
190
|
-
const message = validateFile(file, fileTypes[`${props.desc.upType || 'image'}Suffixes`], attrs.value.maxSize)
|
|
191
|
-
if (message !== true) {
|
|
192
|
-
ElMessage.warning(message)
|
|
193
|
-
return false
|
|
194
|
-
}
|
|
195
|
-
// 获取文件上传的路径
|
|
196
|
-
const uploadInfo = (await defaultConf.upload?.minio?.getUploadUrl(file.name)) as any
|
|
197
|
-
file.action = uploadInfo.uploadUrl
|
|
198
|
-
file.path = uploadInfo.objectUrl
|
|
199
|
-
file.previewUrl = uploadInfo.previewUrl
|
|
200
|
-
file.uploadId = uploadInfo.uploadId
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* 浏览图片
|
|
205
|
-
* @param file
|
|
206
|
-
*/
|
|
207
|
-
function handelPreview(file: any) {
|
|
208
|
-
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(file.raw?.suffix || file.suffix) >= 0) {
|
|
209
|
-
previewIndex.value = previewList.value.findIndex((item) => item === (file.raw?.shareUrl || file.raw?.path || file.furl))
|
|
210
|
-
if (previewIndex.value < 0) {
|
|
211
|
-
previewIndex.value = 0
|
|
212
|
-
}
|
|
213
|
-
showPreview.value = true
|
|
214
|
-
} else {
|
|
215
|
-
window.open(file.raw?.previewUrl || file.previewUrl, '_blank')
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* 超出上传数量
|
|
221
|
-
*/
|
|
222
|
-
function handleOutOfLimit() {
|
|
223
|
-
ElMessage.error('数量最多只能上传' + attrs.value.limit + '个图片/文件!!!')
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* 处理自定义请求
|
|
228
|
-
* @param param
|
|
229
|
-
*/
|
|
230
|
-
async function handelRequest(param: any) {
|
|
231
|
-
await defaultConf.upload?.minio?.doElUpload(param)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// 手动调用上传的方法
|
|
235
|
-
function submit() {
|
|
236
|
-
// this.$refs[this.ref].submit()
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* 校验文件
|
|
241
|
-
* @param file
|
|
242
|
-
* @param types
|
|
243
|
-
* @param maxSize
|
|
244
|
-
*/
|
|
245
|
-
function validateFile(file: any, types: Array<any>, maxSize: number) {
|
|
246
|
-
// 校验文件大小
|
|
247
|
-
if (file.size > maxSize) {
|
|
248
|
-
return '上传文件大小不能超过 ' + (maxSize / 1024 / 1024).toFixed(2) + 'M~'
|
|
249
|
-
}
|
|
250
|
-
// 开始校验文件类型
|
|
251
|
-
if (types && types.length > 0) {
|
|
252
|
-
if (types.every((type) => type !== file.suffix)) {
|
|
253
|
-
return '上传文件类型错误,请重新选择~'
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return true
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
watch(
|
|
260
|
-
() => props.modelValue,
|
|
261
|
-
(data: Array<IOssInfo> | undefined, oldData: any) => {
|
|
262
|
-
if (JSON.stringify(data) !== JSON.stringify(oldData)) {
|
|
263
|
-
// 这里初始化一下
|
|
264
|
-
currentValue.value =
|
|
265
|
-
data?.map((item: IOssInfo) => {
|
|
266
|
-
item.url = getFileIcon(item)
|
|
267
|
-
return item
|
|
268
|
-
}) || []
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
{ immediate: true }
|
|
272
|
-
)
|
|
273
|
-
</script>
|
|
274
|
-
<style lang="scss">
|
|
275
|
-
.ele-form-upload-image {
|
|
276
|
-
width: 100%;
|
|
277
|
-
display: flex;
|
|
278
|
-
|
|
279
|
-
.ele-image-upload {
|
|
280
|
-
display: flex;
|
|
281
|
-
justify-content: flex-start;
|
|
282
|
-
width: 100%;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.upload-panel-icon {
|
|
286
|
-
margin: auto;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
.upload-disabled {
|
|
290
|
-
.el-upload--picture-card {
|
|
291
|
-
cursor: not-allowed !important;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.el-icon-close-tip {
|
|
296
|
-
display: none !important;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
.el-upload--picture-card {
|
|
300
|
-
margin-bottom: 12px;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.over-limit {
|
|
304
|
-
.el-upload--picture-card {
|
|
305
|
-
display: none !important;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.el-upload--picture-card,
|
|
310
|
-
.el-upload-list--picture-card .el-upload-list__item {
|
|
311
|
-
width: 100px !important;
|
|
312
|
-
height: 100px !important;
|
|
313
|
-
border: none !important;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.el-upload-dragger {
|
|
317
|
-
display: flex;
|
|
318
|
-
padding: 0 !important;
|
|
319
|
-
min-height: 100px;
|
|
320
|
-
// height: 100px !important;
|
|
321
|
-
|
|
322
|
-
.el-upload__text {
|
|
323
|
-
font-size: 12px !important;
|
|
324
|
-
color: #999999;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
.el-upload__text2 {
|
|
328
|
-
font-size: 16px;
|
|
329
|
-
color: #303133;
|
|
330
|
-
line-height: 22px;
|
|
331
|
-
margin-top: 16px;
|
|
332
|
-
margin-bottom: 16px;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.el-progress-circle {
|
|
337
|
-
width: 90px !important;
|
|
338
|
-
height: 90px !important;
|
|
339
|
-
margin: auto;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
.el-upload-list--picture-card .el-upload-list__item-thumbnail {
|
|
343
|
-
object-fit: cover !important;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
.el-icon--close-tip {
|
|
347
|
-
display: none !important;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.ele-form-upload-file {
|
|
352
|
-
.ele-image-upload {
|
|
353
|
-
flex-direction: column;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.el-upload-list__item {
|
|
357
|
-
margin: 0 !important;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
.el-form-item--default .el-form-item__content {
|
|
361
|
-
line-height: 20px !important;
|
|
362
|
-
font-size: 12px !important;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
.el-upload-list__item-name {
|
|
366
|
-
line-height: 20px !important;
|
|
367
|
-
font-size: 12px !important;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ele-form-upload-image" :class="{ 'ele-form-upload-file': desc.upType === 'file' }">
|
|
3
|
+
<el-upload class="ele-image-upload" v-bind="attrs" v-on="onEvents" :disabled="disabled" :fileList="currentValue || []" :class="{ 'over-limit': currentValue?.length >= attrs.limit, 'upload-disabled': attrs.disabled }">
|
|
4
|
+
<div class="upload-panel-icon">
|
|
5
|
+
<i v-if="desc.icon" :class="desc.icon" :style="{ fontSize: desc.fontSize || '14px', color: desc.color || '#C0C4CC' }"></i>
|
|
6
|
+
<el-icon v-else :style="{ fontSize: desc.fontSize || '14px', color: desc.color || '#C0C4CC' }"><Plus /></el-icon>
|
|
7
|
+
<div class="el-upload__text2" v-if="desc.upType === 'file' && desc.text2">
|
|
8
|
+
{{ desc.text2 }}
|
|
9
|
+
</div>
|
|
10
|
+
<div class="el-upload__text" v-if="desc.upType === 'file'">
|
|
11
|
+
{{ desc.text || '拖拽/点击上传' }}
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
<!-- <template #file="file">
|
|
15
|
+
<UploadShowIcon :file="file"></UploadShowIcon>
|
|
16
|
+
</template> -->
|
|
17
|
+
</el-upload>
|
|
18
|
+
|
|
19
|
+
<!-- 图片查看的站位标签 -->
|
|
20
|
+
<el-image-viewer v-if="showPreview" @close="showPreview = false" teleported :initialIndex="previewIndex" :url-list="previewList" />
|
|
21
|
+
<div v-if="!attrs.autoUpload" class="upload-hands-submit">
|
|
22
|
+
<el-button style="margin-left: 10px" size="small" type="success" @click="submit" :disabled="disabled"> 上传到服务器 </el-button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
<script lang="ts">
|
|
27
|
+
export default {
|
|
28
|
+
name: 'ElPlusFormUpload',
|
|
29
|
+
inheritAttrs: false,
|
|
30
|
+
typeName: 'upload',
|
|
31
|
+
customOptions: {}
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
<script lang="ts" setup>
|
|
35
|
+
import { ref, computed, useAttrs, onBeforeMount, watch, inject } from 'vue'
|
|
36
|
+
import { getAttrs, getEvents } from '../mixins'
|
|
37
|
+
import { ElMessage, UploadUserFile } from 'element-plus'
|
|
38
|
+
import { Plus } from '@element-plus/icons-vue'
|
|
39
|
+
|
|
40
|
+
import * as fileTypes from '../data/file'
|
|
41
|
+
|
|
42
|
+
// 引入图标
|
|
43
|
+
import excel from '../images/icon/excel.png'
|
|
44
|
+
import pdf from '../images/icon/pdf.png'
|
|
45
|
+
import file from '../images/icon/file.png'
|
|
46
|
+
import txt from '../images/icon/txt.png'
|
|
47
|
+
import word from '../images/icon/word.png'
|
|
48
|
+
import zip from '../images/icon/zip.png'
|
|
49
|
+
import ppt from '../images/icon/ppt.png'
|
|
50
|
+
import { ICRUDConfig, IOssInfo } from 'types'
|
|
51
|
+
|
|
52
|
+
const defaultConf = inject('defaultConf') as ICRUDConfig
|
|
53
|
+
|
|
54
|
+
// 图标Map
|
|
55
|
+
const iconMap = { excel, pdf, file, txt, word, zip, ppt }
|
|
56
|
+
|
|
57
|
+
const props = defineProps<{
|
|
58
|
+
modelValue?: Array<IOssInfo>
|
|
59
|
+
field: string
|
|
60
|
+
loading?: boolean
|
|
61
|
+
desc: { [key: string]: any }
|
|
62
|
+
formData: { [key: string]: any }
|
|
63
|
+
disabled?: boolean
|
|
64
|
+
}>()
|
|
65
|
+
|
|
66
|
+
const emits = defineEmits(['update:modelValue', 'validateThis'])
|
|
67
|
+
const currentValue = ref((typeof props.modelValue === 'string' ? [{ url: props.modelValue }] : props.modelValue) || [])
|
|
68
|
+
|
|
69
|
+
emits('update:modelValue', currentValue)
|
|
70
|
+
|
|
71
|
+
const attrs = ref({} as any)
|
|
72
|
+
const onEvents = ref(getEvents(props))
|
|
73
|
+
|
|
74
|
+
const showPreview = ref(false)
|
|
75
|
+
const previewIndex = ref(0)
|
|
76
|
+
const previewList = computed(() =>
|
|
77
|
+
currentValue.value
|
|
78
|
+
.map((item: any) => {
|
|
79
|
+
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(item.raw?.suffix || item.suffix) >= 0) {
|
|
80
|
+
return item.url
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
.filter((url) => url)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
onBeforeMount(async () => {
|
|
87
|
+
// // 如果没有配置,则抛出一个警告
|
|
88
|
+
if (!defaultConf.upload || (!defaultConf.upload.action && !defaultConf.upload.minio?.getObjectAuthUrl)) {
|
|
89
|
+
console.warn('缺少文件上传配置,无法使用upload组件~')
|
|
90
|
+
}
|
|
91
|
+
attrs.value = await getAttrs(props, {
|
|
92
|
+
drag: true,
|
|
93
|
+
listType: props.desc.upType === 'file' ? 'text' : 'picture-card',
|
|
94
|
+
multiple: !!props.desc.multiple,
|
|
95
|
+
limit: props.desc.multiple ? props.desc.limit || 20 : 1,
|
|
96
|
+
autoUpload: props.desc.autoUpload ?? true,
|
|
97
|
+
accept: props.desc.accept || fileTypes[`${props.desc.upType || 'image'}Types`].join(','),
|
|
98
|
+
maxSize: props.desc.maxSize || (props.desc.upType === 'file' ? defaultConf.upload?.maxFSize : defaultConf.upload?.maxISize),
|
|
99
|
+
beforeUpload: handelUploadBefore,
|
|
100
|
+
onRemove: handelUploadRemove,
|
|
101
|
+
onSuccess: handelUploadSuccess,
|
|
102
|
+
onExceed: handleOutOfLimit,
|
|
103
|
+
onPreview: handelPreview,
|
|
104
|
+
httpRequest: handelRequest,
|
|
105
|
+
...useAttrs()
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 处理删除
|
|
111
|
+
* @param file
|
|
112
|
+
* @param fileList
|
|
113
|
+
*/
|
|
114
|
+
function handelUploadRemove(file: UploadUserFile) {
|
|
115
|
+
handelListChange(file, 0)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 上传成功回调
|
|
120
|
+
* @param _
|
|
121
|
+
* @param file
|
|
122
|
+
* @param fileList
|
|
123
|
+
*/
|
|
124
|
+
async function handelUploadSuccess(_: any, file: any) {
|
|
125
|
+
const { objectUrl, previewUrl } = await defaultConf.upload?.minio?.getObjectAuthUrl(file.raw.uploadId)
|
|
126
|
+
file.raw.shareUrl = objectUrl
|
|
127
|
+
file.raw.previewUrl = previewUrl
|
|
128
|
+
file.url = getFileIcon(file.raw)
|
|
129
|
+
// console.log('handelUploadSuccess: file: ', file)
|
|
130
|
+
handelListChange(file, 1)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 获取文件Icon
|
|
135
|
+
* @param file
|
|
136
|
+
*/
|
|
137
|
+
function getFileIcon(file?: any): string {
|
|
138
|
+
if (file) {
|
|
139
|
+
const suffix = (file?.suffix || '') as string
|
|
140
|
+
if (suffix) {
|
|
141
|
+
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(suffix) >= 0) {
|
|
142
|
+
// return (props.desc.upType === 'file' ? file.previewUrl : file.shareUrl) || file.furl || file.path
|
|
143
|
+
return file.shareUrl || file.furl || file.path
|
|
144
|
+
}
|
|
145
|
+
for (let i = 0; i < fileTypes.suffixTypes.length; i++) {
|
|
146
|
+
for (let j = 0; j < fileTypes.suffixTypes[i].suffixes.length; j++) {
|
|
147
|
+
if (fileTypes.suffixTypes[i].suffixes[j] === suffix) {
|
|
148
|
+
return iconMap[fileTypes.suffixTypes[i].type]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return iconMap.file
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 处理图片列表的修改
|
|
159
|
+
* @param file
|
|
160
|
+
* @param type 0 : 删除; 1: 新增
|
|
161
|
+
*/
|
|
162
|
+
function handelListChange(item: UploadUserFile, type: 0 | 1) {
|
|
163
|
+
if (type === 1) {
|
|
164
|
+
currentValue.value.push({
|
|
165
|
+
name: item.name,
|
|
166
|
+
furl: (item.raw as any)?.path || item.url,
|
|
167
|
+
url: getFileIcon(item.raw),
|
|
168
|
+
fsize: item.size,
|
|
169
|
+
uid: item.uid,
|
|
170
|
+
mimeType: item.raw?.type,
|
|
171
|
+
suffix: (item.raw as any).suffix,
|
|
172
|
+
busId: props.desc.busId,
|
|
173
|
+
busType: props.desc.busType
|
|
174
|
+
})
|
|
175
|
+
} else {
|
|
176
|
+
const index = currentValue.value.findIndex((file) => file.uid === item.uid)
|
|
177
|
+
if (index >= 0) {
|
|
178
|
+
currentValue.value.splice(index, 1)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
emits('validateThis')
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 上传之前,校验文件大小以及类型
|
|
186
|
+
* @param file
|
|
187
|
+
*/
|
|
188
|
+
async function handelUploadBefore(file: any) {
|
|
189
|
+
file.suffix = (file.name as string).substring(file.name.lastIndexOf('.'))
|
|
190
|
+
const message = validateFile(file, fileTypes[`${props.desc.upType || 'image'}Suffixes`], attrs.value.maxSize)
|
|
191
|
+
if (message !== true) {
|
|
192
|
+
ElMessage.warning(message)
|
|
193
|
+
return false
|
|
194
|
+
}
|
|
195
|
+
// 获取文件上传的路径
|
|
196
|
+
const uploadInfo = (await defaultConf.upload?.minio?.getUploadUrl(file.name)) as any
|
|
197
|
+
file.action = uploadInfo.uploadUrl
|
|
198
|
+
file.path = uploadInfo.objectUrl
|
|
199
|
+
file.previewUrl = uploadInfo.previewUrl
|
|
200
|
+
file.uploadId = uploadInfo.uploadId
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 浏览图片
|
|
205
|
+
* @param file
|
|
206
|
+
*/
|
|
207
|
+
function handelPreview(file: any) {
|
|
208
|
+
if (['.png', '.jpg', '.gif', '.jpeg'].indexOf(file.raw?.suffix || file.suffix) >= 0) {
|
|
209
|
+
previewIndex.value = previewList.value.findIndex((item) => item === (file.raw?.shareUrl || file.raw?.path || file.furl))
|
|
210
|
+
if (previewIndex.value < 0) {
|
|
211
|
+
previewIndex.value = 0
|
|
212
|
+
}
|
|
213
|
+
showPreview.value = true
|
|
214
|
+
} else {
|
|
215
|
+
window.open(file.raw?.previewUrl || file.previewUrl, '_blank')
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 超出上传数量
|
|
221
|
+
*/
|
|
222
|
+
function handleOutOfLimit() {
|
|
223
|
+
ElMessage.error('数量最多只能上传' + attrs.value.limit + '个图片/文件!!!')
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* 处理自定义请求
|
|
228
|
+
* @param param
|
|
229
|
+
*/
|
|
230
|
+
async function handelRequest(param: any) {
|
|
231
|
+
await defaultConf.upload?.minio?.doElUpload(param)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 手动调用上传的方法
|
|
235
|
+
function submit() {
|
|
236
|
+
// this.$refs[this.ref].submit()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 校验文件
|
|
241
|
+
* @param file
|
|
242
|
+
* @param types
|
|
243
|
+
* @param maxSize
|
|
244
|
+
*/
|
|
245
|
+
function validateFile(file: any, types: Array<any>, maxSize: number) {
|
|
246
|
+
// 校验文件大小
|
|
247
|
+
if (file.size > maxSize) {
|
|
248
|
+
return '上传文件大小不能超过 ' + (maxSize / 1024 / 1024).toFixed(2) + 'M~'
|
|
249
|
+
}
|
|
250
|
+
// 开始校验文件类型
|
|
251
|
+
if (types && types.length > 0) {
|
|
252
|
+
if (types.every((type) => type !== file.suffix)) {
|
|
253
|
+
return '上传文件类型错误,请重新选择~'
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return true
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
watch(
|
|
260
|
+
() => props.modelValue,
|
|
261
|
+
(data: Array<IOssInfo> | undefined, oldData: any) => {
|
|
262
|
+
if (JSON.stringify(data) !== JSON.stringify(oldData)) {
|
|
263
|
+
// 这里初始化一下
|
|
264
|
+
currentValue.value =
|
|
265
|
+
data?.map((item: IOssInfo) => {
|
|
266
|
+
item.url = getFileIcon(item)
|
|
267
|
+
return item
|
|
268
|
+
}) || []
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
{ immediate: true }
|
|
272
|
+
)
|
|
273
|
+
</script>
|
|
274
|
+
<style lang="scss">
|
|
275
|
+
.ele-form-upload-image {
|
|
276
|
+
width: 100%;
|
|
277
|
+
display: flex;
|
|
278
|
+
|
|
279
|
+
.ele-image-upload {
|
|
280
|
+
display: flex;
|
|
281
|
+
justify-content: flex-start;
|
|
282
|
+
width: 100%;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.upload-panel-icon {
|
|
286
|
+
margin: auto;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.upload-disabled {
|
|
290
|
+
.el-upload--picture-card {
|
|
291
|
+
cursor: not-allowed !important;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.el-icon-close-tip {
|
|
296
|
+
display: none !important;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.el-upload--picture-card {
|
|
300
|
+
margin-bottom: 12px;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.over-limit {
|
|
304
|
+
.el-upload--picture-card {
|
|
305
|
+
display: none !important;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.el-upload--picture-card,
|
|
310
|
+
.el-upload-list--picture-card .el-upload-list__item {
|
|
311
|
+
width: 100px !important;
|
|
312
|
+
height: 100px !important;
|
|
313
|
+
border: none !important;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.el-upload-dragger {
|
|
317
|
+
display: flex;
|
|
318
|
+
padding: 0 !important;
|
|
319
|
+
min-height: 100px;
|
|
320
|
+
// height: 100px !important;
|
|
321
|
+
|
|
322
|
+
.el-upload__text {
|
|
323
|
+
font-size: 12px !important;
|
|
324
|
+
color: #999999;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.el-upload__text2 {
|
|
328
|
+
font-size: 16px;
|
|
329
|
+
color: #303133;
|
|
330
|
+
line-height: 22px;
|
|
331
|
+
margin-top: 16px;
|
|
332
|
+
margin-bottom: 16px;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.el-progress-circle {
|
|
337
|
+
width: 90px !important;
|
|
338
|
+
height: 90px !important;
|
|
339
|
+
margin: auto;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.el-upload-list--picture-card .el-upload-list__item-thumbnail {
|
|
343
|
+
object-fit: cover !important;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.el-icon--close-tip {
|
|
347
|
+
display: none !important;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.ele-form-upload-file {
|
|
352
|
+
.ele-image-upload {
|
|
353
|
+
flex-direction: column;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.el-upload-list__item {
|
|
357
|
+
margin: 0 !important;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.el-form-item--default .el-form-item__content {
|
|
361
|
+
line-height: 20px !important;
|
|
362
|
+
font-size: 12px !important;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.el-upload-list__item-name {
|
|
366
|
+
line-height: 20px !important;
|
|
367
|
+
font-size: 12px !important;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
</style>
|
|
371
|
+
types
|