效果图:
代码
<template>
<div class="custom-file-upload">
<div class="upload">
<!-- 显示已选择的文件 -->
<div class="file-list">
<div v-for="(item, index) in state.filsList" :key="index" class="file-item">
<div v-if="item.url.includes('.pdf')" @click="priviewPdf(item.url)" class="img filePdf">
<div style="text-align: center;">
<div class="overHiden" style="font-size: 14px;" :title="item.wjmc">{{ item.wjmc }}</div>
<el-icon><Document /></el-icon>
</div>
</div>
<el-image
class="img"
:src="state.baseUrl + '/file/file/preview?accessToken='+state.token+'&'+'filePath='+item.url"
:preview-src-list="[state.baseUrl + '/file/file/preview?accessToken='+state.token+'&'+'filePath='+item.url]"
show-progress
fit="cover"
v-else
/>
<!-- <img @click="priviewImg(item.src)" v-else class="img" :src="state.baseUrl + '/file/file/preview?accessToken='+state.token+'&'+'filePath='+item.url" /> -->
<el-icon @click="removeFile(index)" class="delete"><CloseBold /></el-icon>
</div>
<!-- 自定义样式的div -->
<div class="upload-btn" @click="openFileSelector">
<el-icon><Plus /></el-icon>
</div>
</div>
</div>
<!-- 隐藏的文件输入 -->
<input
type="file"
ref="fileInput"
@change="handleFileChange"
multiple
accept=".jpg,.png,.pdf"
style="display: none;"
/>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus';
import { uploadFile } from '@/api/index'
import { getToken } from '@/utils/tools'
const fileInput = ref(null)
const emits = defineEmits(['successFile', 'handleRemove'])
const props = defineProps({
filsList: Object
});
const state = reactive({
filsList: [] as any,
token: getToken()
})
onMounted(() => {
state.filsList = props.filsList
})
watch(
() => props.filsList,
(newList, oldList) => {
state.filsList = newList
}
)
// 打开文件选择对话框
const openFileSelector = () => {
fileInput.value.click()
}
// 处理文件选择
const handleFileChange = (e: any) => {
const params = {
files: e.target.files[0]
}
var filename = e.target.files[0].name
// console.log(e.target.files[0])
// 上传文件接口
uploadFile(params).then((res: any) => {
state.filsList.push({
url: res[0],
wjmc: filename
})
console.log(state.filsList)
ElMessage.success('上传成功')
// emits('successFile', res[0], filename)
emits('successFile', state.filsList)
}).catch((_) => {
ElMessage.success('上传失败')
})
}
// 查看pdf文件
const priviewPdf = (url: any) => {
var pdfUrl = window.origin + `/file/file/preview?accessToken=${state.token}&filePath=${url}`
window.open(pdfUrl, '_blank')
}
// 移除文件
const removeFile = (index:any) => {
// state.filsList.splice(index, 1)
emits('handleRemove', index)
}
// 格式化文件大小
const formatSize = (size:any) => {
if (size < 1024) return size + ' B'
if (size < 1048576) return (size / 1024).toFixed(1) + ' KB'
return (size / 1048576).toFixed(1) + ' MB'
}
// 重置filelist
const resetFil = () => {
state.filsList = []
}
// 导出对象
defineExpose({ resetFil });
</script>
<style scoped>
.custom-file-upload {
align-items: center;
display: flex;
/* max-width: 400px; */
}
.upload{
align-items: center;
display: flex;
}
.upload-btn {
display: flex;
align-items: center;
justify-content: center;
color: white;
border-radius: 4px;
border: 1px solid #cdd0d6;
background-color: #fafafa;
width: 148px;
height: 148px;
font-size: 28px;
transition: background-color 0.3s;
color: #909399;
cursor: pointer;
}
.upload-btn:hover {
border: 1px dashed #66b1ff;
}
.upload-btn i {
margin-right: 8px;
}
.file-list {
display: flex;
align-items: center;
flex-wrap: wrap;
margin-top: 8px;
cursor: pointer;
}
.file-item {
display: flex;
align-items: center;
height: 148px;
width: 148px;
border-radius: 4px;
margin-right: 4px;
position: relative;
}
.delete{
position: absolute;
right: 4px;
top: 4px;
}
.img{
height: 148px;
width: 148px;
border-radius: 4px;
}
.filePdf{
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
border-radius: 4px;
border: 1px solid #cdd0d6;
}
.file-item button {
background: none;
border: none;
color: #909399;
cursor: pointer;
font-size: 16px;
}
.file-item button:hover {
color: #f56c6c;
}
.overHiden{
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 溢出内容隐藏 */
text-overflow: ellipsis; /* 溢出时显示省略号 */
}
</style>
使用
// 引入
import uploadFile from '@/components/uploadFile/index.vue'
const uploadFileRef = ref<any>(null);
dom结构
<uploadFile
@successFile="onSuccess"
@handleRemove="handleRemove"
:filsList="state.ruleForm.files"
ref="uploadFileRef"
/>
事件
// 上传成功--返回图片地址
const onSuccess = (list:any) => {
state.ruleForm.files = list
}
// 删除上传图片--返回下表删除
const handleRemove = (index: any) => {
state.ruleForm.files.splice(index, 1)
}