使用vue3+ts+input封装上传组件,上传文件显示文件图标
效果图:
代码
<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-imageclass="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-progressfit="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)
}