关于我在写el-upload的图片拖拽排序时,使用vuedraggable结合el-upload完成的过程中,发现el-upload的show-file-list为false之后上传按钮没了的问题,不知道是我的问题还是elementplus本身就有这个问题,先记录一下
<style lang="less" scoped>
::v-deep .hide .el-upload--picture-card {
display: none;
}
::v-deep .el-upload-list__item-actions {
.el-icon {
span {
font-size: 20px !important;
font-weight: 600;
}
}
}
::v-deep .uploadCon {
.el-upload-list__item {
display: none !important; // 这里将照片列隐藏!!!
}
}
</style>
<template>
<div class="flex">
<ul class="el-upload-list el-upload-list--picture-card">
<draggable v-model="fileList" animation="300" v-if="limit > 1" @end="dragEnd">
<template #item="{ element: item, index }">
<li class="el-upload-list__item is-success animated">
<img :src="item.url" alt="" class="el-upload-list__item-thumbnail" />
<Icon icon="ep:close" />
<span class="el-upload-list__item-actions">
<!-- 预览 -->
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(item)">
<Icon icon="ep:zoom-in" />
</span>
<!-- 删除 -->
<span class="el-upload-list__item-delete" @click="handleRemoveFileDetail(index)">
<Icon icon="ep:delete" />
</span>
</span>
</li>
</template>
</draggable>
</ul>
<el-upload
:class="[limit > 1 ? 'uploadCon' : '', { hide: hideUpload }]"
v-model:file-list="fileList"
action="#"
list-type="picture-card"
:on-success="handleAvatarSuccess"
:before-upload="beforeUpload"
:multiple="props.uploadImgDrawerTitle ? true : false"
:limit="limit"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-change="ChangeImage"
>
<Icon class="ml-5px upload_icon" icon="bi:plus" :size="24" />
</el-upload>
<el-dialog v-model="dialogVisibleImg">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</div>
</template>```
```javascript
<script lang="ts" setup>
import { ref, defineEmits, defineProps, watch, onMounted } from 'vue'
import { ElUpload, ElDialog, ElMessage } from 'element-plus'
//ElButton ElMessage
import type { UploadProps } from 'element-plus'
import { setOssToken } from '@/utils/index'
import { getOssTokenApi } from '@/api/upload/index'
import { getOssToken } from '@/utils/index'
// import OSS from 'ali-oss'
import { addImgList } from '@/api/upload'
import md5 from 'js-md5'
import { getDate } from '@/utils/utils'
import draggable from 'vuedraggable'
const props = defineProps({
link: {
type: Array,
default: () => []
},
uploadImgDrawerTitle: {
type: String,
default: ''
},
limit: {
type: Number,
default: 3
},
fileType: {
type: Array,
default: () => ['image/jpeg', 'image/png']
},
fileSize: {
type: Number,
default: 2
},
// 是否保持1:1比例,目前是保持,不是1:1的图片请传false
isOneAll: {
type: Boolean,
default: true
},
// 上传oss的所在目录,必须传入
catalogue: {
type: Object,
default: () => {},
required: true
}
})
const getOssClient = () => {
const ossData: any = getOssToken() ? JSON.parse(getOssToken()) : null
const client = ossData
? new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'oss-cn-hangzhou',
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
accessKeyId: ossData.AccessKeyId,
accessKeySecret: ossData.AccessKeySecret,
stsToken: ossData.SecurityToken,
// 填写Bucket名称。
bucket: 'dbbshop-oss'
// endPoint: 'https://oss.doubbjt.com'
})
: null
return client
}
const emit = defineEmits(['updateUrl', 'addUrlList'])
const fileList: any = ref([]) //照片墙list
const dialogImageUrl = ref('') //预览图片
const hideUpload = ref(false) //是否隐藏上传按钮
// 刷新限制上传数量
const refreshLimit = () => {
setTimeout(() => {
hideUpload.value = fileList.value.length >= props.limit
}, 500)
}
watch(
() => props.link,
(val) => {
refreshLimit()
if ((val && val.length === 0) || fileList.value.length > 0) return
fileList.value.push(...val)
},
{
immediate: true
}
)
const handleAvatarSuccess = () => {
console.log('成功')
}
const beforeUpload = async (file: any) => {
console.log(file, 'file')
if (props.fileType.length && props.fileType.indexOf(file.type) === -1) {
let str = props.fileType.map((item: any) => item.split('/')[1]).join('、')
ElMessage.error(`图片仅支持${str}格式!`)
return false
} else if (props.fileSize && file.size / 1024 / 1024 > props.fileSize) {
ElMessage.error(`建议图片大小保持${props.fileSize}MB以内!`)
return false
}
const isSize = () => {
return new Promise((resolve: any, reject) => {
const _URL = window.URL || window.webkitURL
const img = new Image()
img.onload = () => {
const valid = img.width === img.height
valid ? resolve() : reject()
}
img.src = _URL.createObjectURL(file)
}).then(
() => {
return true
},
() => {
ElMessage.error('图片尺寸建议为1:1!')
return false
}
)
}
if (props.isOneAll) {
let isSizeLimit = false
await isSize().then((res) => {
isSizeLimit = res
})
if (!isSizeLimit) return
}
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (e: any) => {
const img: any = new Image()
img.src = e?.target.result
img.onload = async () => {
const canvas = document.createElement('canvas')
let width = img.width
let height = img.height
if (width > height) {
if (width > 1000) {
width = 1000
height = (width * img.height) / img.width
}
} else {
if (height > 1000) {
height = 1000
width = (height * img.width) / img.height
}
}
canvas.width = width
canvas.height = height
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.drawImage(img, 0, 0, width, height)
}
canvas.toBlob((blob: any) => {
const newFile = new File([blob], file.name, {
type: file.type
})
uploadFile(newFile)
}, file.type)
}
}
return false // return false 阻止原始file上传
}
const uploadFile = async (newFile) => {
//import.meta.env.VITE_USER_NODE_ENV + '/' + newFile.name,
try {
// newFile.name 后续改成 日期前缀+文件名md5加密
// 获取oss token
const ossRes: any = await getOssTokenApi()
if (ossRes.data.Credentials) {
setOssToken(JSON.stringify(ossRes.data.Credentials))
} else {
ElMessage.error(ossRes.message)
}
const client: any = await getOssClient()
let times = new Date().getTime()
const fileMd5 = md5(newFile.name) + times //文件名md5加密
console.log(newFile, 'newFile')
const filesize = newFile.size //图片大小
const suffix = newFile.type //后缀
const original_name = newFile.name //原始名称
const res = await client.put(
import.meta.env.VITE_USER_NODE_ENV +
'/' +
props.catalogue.subname +
'/' +
getDate() +
'/' +
fileMd5 +
`.${newFile.type.split('/')[1]}`,
newFile
)
refreshLimit()
let url = res.url.split('com')
res.url = 'https://oss.doubbjt.com' + url[1]
console.log(res, 'res')
// ObjName为文件名字,可以只写名字,就直接储存在 bucket 的根路径,如需放在文件夹下面直接在文件名前面加上文件夹名称
// imgList.value = res.url
fileList.value.push(res)
if (props.uploadImgDrawerTitle == '添加图片') {
// 全局缺失准备数据接口,,通过准备数据进行传参
if (props.catalogue.id) {
let params = {
md5: fileMd5,
filesize: filesize,
suffix: suffix,
original_name: original_name,
subtype_id: props.catalogue.id,
link: res.url,
link_name: fileMd5
}
addImgList(params).then((res: any) => {
if (res.code == 0) {
ElMessage.success(res.message)
// cancelClick()
// getImgData(pid.value)
}
})
}
emit(
'addUrlList',
fileList.value.map((item) => item.url)
)
} else {
emit('updateUrl', res.url)
}
} catch (e) {
console.log(e)
}
}
const dialogVisibleImg = ref(false) //预览图片弹框
const handleRemove: UploadProps['onRemove'] = () => {
hideUpload.value = fileList.value.length >= props.limit
emit(
'addUrlList',
fileList.value.map((item) => item.url)
)
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisibleImg.value = true
}
const ChangeImage = () => {
refreshLimit()
}
// 删除
const handleRemoveFileDetail = (index) => {
fileList.value.splice(index, 1)
emit(
'addUrlList',
fileList.value.map((item) => item.url)
)
}
const dragEnd = () => {
emit(
'addUrlList',
fileList.value.map((item) => item.url)
)
}
onMounted(() => {
refreshLimit()
// console.log(import.meta.env.VITE_USER_NODE_ENV, 'import.meta.env.VITE_API_BASEPATH')
})
defineExpose({
fileList
})
</script>