
詳細組件內容如下面的折疊的代碼
點擊查看代碼
<template>
<div class="upload-container1">
<!-- 如果isDisabled為false且multipleFlag為true或者multipleFlag為false且fileList的長度為0,則顯示el-upload組件 -->
<el-upload v-if="!isDisabled && (multipleFlag || !multipleFlag && fileList.length == 0)" :disabled="isDisabled"
class="avatar1-uploader1" :limit="limit" :multiple="multipleFlag"
:accept="'.png,.jpg,.jpeg,.doc,.docx,.txt,.xls,.xlsx,.pdf'" element-loading-text="正在上傳"
:show-file-list="false" ref="imageUp" :http-request="doUpload" :before-upload="beforeUpload">
<!-- 顯示上傳圖標 -->
<el-icon class="avatar1-uploader1-icon">
<Plus />
</el-icon>
</el-upload>
<!-- 修改預覽區域 -->
<div v-if="fileList.length" class="previews-container">
<!-- 單/多文件預覽模式 -->
<div v-for="(file, index) in fileList" :key="index" class="multi-preview-item">
<div @click="previewImage(file)">
<img v-if="isImage(file)" :src="file.url" class="avatar1" />
<!-- 如果是圖片,則顯示圖片 -->
<div v-else class="file-preview">
<!-- 否則顯示文件預覽 -->
<el-icon class="document-icon">
<component :is="file.icon" />
</el-icon>
<!-- 顯示文件圖標 -->
<span class="filename">{{ file.name }}</span>
<!-- 顯示文件名 -->
</div>
</div>
<div class="down-file">
<el-button type="primary" @click="handleDownload(file)">下載</el-button>
<!-- 點擊下載文件 -->
</div>
<el-icon v-if="!isDisabled" class="close-icon" @click.stop="removeFile(index)">
<Close />
</el-icon>
<!-- 如果不是禁用狀態,則顯示關閉按鈕 -->
</div>
</div>
<!-- 預覽對話框 -->
<el-dialog v-model="previewVisible" width="60%" title="預覽">
<!-- 預覽圖片 -->
<div class="preview-image">
<!-- 如果是圖片,則顯示圖片 -->
<img v-if="isImage" :src="previewImageUrl" />
</div>
</el-dialog>
</div>
</template>
<script setup>
import api from '@/utils/interface'
// 導入Element Plus圖標庫中的Document、Plus、Close圖標
import {
Document,
Plus,
Close
} from '@element-plus/icons-vue'
import { ref, computed, markRaw } from 'vue';
import { storeToRefs } from 'pinia' // 注意先安裝哦
import { useStorageStore } from "@/stores/storage";
import axios from 'axios'
const store = useStorageStore();
const { user } = storeToRefs(store);
const props = defineProps({
// 圖片上傳的url
url: {
type: String,
default: ''
},
// 是否禁用
isDisabled: {
type: Boolean,
default: false
},
// 是否支持多選
multipleFlag: {
type: Boolean,
default: false
},
// 限制上傳數量
limit: {
type: Number,
default: 1
},
// 媒體名稱
mediaName: {
type: String,
default: ''
}
})
// 判斷props.url是否為空,如果為空,則kongflag為true,否則為false
let kongflag = props.url == '' ? true : false
// 定義一個空數組
let defaultArray = []
// 如果kongflag為false,則執行以下代碼
if (!kongflag) {
// 判斷props.url的后綴是否為.doc,.docx,.txt,.xls,.xlsx,.pdf中的一個,如果是,則extFlag為true,否則為false
let extFlag = '.doc,.docx,.txt,.xls,.xlsx,.pdf'.includes(props.url.split('.').pop()) ? true : false
// 將props.url按逗號分隔,得到一個數組
let urlArrary = props.url.split(',')
// 遍歷urlArrary數組
urlArrary.forEach((item, index) => {
// 將數組中的每個元素添加到defaultArray數組中
defaultArray.push({
name: props.mediaName,
type: props.url.split('.').pop(),
url: item,
icon: extFlag ? markRaw(Document) : ''
})
})
}
// 修改為數組存儲多個文件
const fileList = ref(Array.isArray(props.url) ? props.url : kongflag ? [] : defaultArray)
let multipleFlag = ref(props.multipleFlag)
let loading = ref(false)
const imageUp = ref();
const emit = defineEmits(["closeInvoice"]);
// 新增響應式數據和計算屬性
const isImage = (file) => ['png', 'jpg', 'jpeg'].includes(file.type)
const previewVisible = ref(false)
const previewImageUrl = ref('')
// 預覽圖片
const previewImage = (file) => {
// 判斷文件是否為圖片
if (!isImage(file)) {
return
}
// 設置預覽圖片的url
previewImageUrl.value = file.url
// 設置預覽圖片的可見性為true
previewVisible.value = true
}
// 新增刪除文件方法
const removeFile = (index) => {
fileList.value.splice(index, 1)
emit("closeInvoice", fileList.value)
}
const handleDownload = (item) => {
// 圖片文件直接下載
const link = document.createElement('a')
link.href = item.url;
link.setAttribute('download', item.name)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
async function doUpload(option) {
loading.value = true
const file = option.file;
let userinfo = user.value
let ext = file.name.split(".").pop();
try {
const formData = new FormData();
formData.append('file', file);
const response = await axios.post(
'/base/webback/uploadTos',
formData,
{
headers: {
"Authorization": userinfo.token,
},
}
);
if (response.data.code) {
let extFlag = '.doc,.docx,.txt,.xls,.xlsx,.pdf'.includes(ext) ? true : false
const newFile = {
name: file.name,
type: ext,
url: response.data.data.url,
icon: extFlag ? markRaw(Document) : ''
}
fileList.value.push(newFile)
imageUp.value.clearFiles();
emit("emitUrl", fileList.value) // 返回整個文件列表
loading.value = false
} else {
ElMessage({ type: 'error', message: response.data.message })
}
} catch (error) {
ElMessage({ type: 'error', message: error })
}
}
function beforeUpload(file) {
const allowedTypes = ['png', 'jpg', 'jpeg', 'doc', 'docx', 'txt', 'xls', 'xlsx', 'pdf']
const fileType = file.name.split('.').pop().toLowerCase()
const isValidType = allowedTypes.includes(fileType)
if (!isValidType) {
ElMessage.error('僅支持上傳:' + allowedTypes.join(', '))
return false
}
const isLt2M = file.size / 1024 / 1024 < 20;
if (!isLt2M) {
ElMessage.error('上傳圖片大小不能超過 20MB!');
}
return isLt2M;
}
</script>
<style scoped>
.down-file {
display: flex;
justify-content: center;
margin-top: 5px;
}
.preview-image {
width: 100%;
height: 70vh;
display: flex;
justify-content: center;
align-items: center;
overflow: auto;
}
.preview-image img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.upload-container1 {
margin-left: 35px;
width: 170px;
min-height: 170px;
}
.avatar1 {
width: 100%;
height: 155px;
display: block;
object-fit: contain;
}
:deep(.avatar1-uploader1 .el-upload) {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
:deep(.el-icon.avatar1-uploader1-icon) {
font-size: 28px;
color: #8c939d;
width: 150px;
height: 150px;
text-align: center;
}
.file-preview {
display: flex;
margin-top: 10px;
height: 125px;
flex-direction: column;
align-items: center;
padding: 10px;
}
.document-icon {
font-size: 60px;
color: #409eff;
margin-bottom: 8px;
}
.filename {
font-size: 12px;
color: #666;
word-break: break-all;
text-align: center;
max-width: 140px;
}
/* 新增多文件預覽樣式 */
.previews-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
width: 586px;
background: #f5f7fa;
padding: 10px;
margin-top: 10px;
}
.multi-preview-item {
position: relative;
width: 180px;
border: 1px solid #eee;
border-radius: 4px;
padding: 6px 0;
background: #e1e1e1;
&:hover .close-icon {
display: block;
}
}
.thumb-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.file-thumb {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.close-icon {
position: absolute;
width: 25px;
height: 25px;
line-height: 25px;
text-align: center;
right: 4px;
top: 4px;
color: red;
font-size: 24px;
background: white;
border-radius: 50%;
display: none;
cursor: pointer;
}
.document-icon-small {
font-size: 32px;
}
</style>
浙公網安備 33010602011771號