<template>
<div style="width: 500px">
<el-upload
class="upload-demo"
multiple
:accept="fileType"
:limit="limitNum"
:show-file-list="false"
:http-request="uploadRequest"
>
<el-button type="primary">Click to upload</el-button>
<template #tip>
<div class="el-upload__tip">提示:只支持上传{{ tip }}格式文件</div>
<div class="fileList" v-show="fileData !== ''">
<div style="display: flex; vertical-align: middle">
<el-icon style="margin: 8px"><Document /></el-icon>
<div
class="fileName"
style="font-size: 12px; width: 500; overflow: hidden"
>
<el-tooltip
class="box-item"
effect="dark"
content="点击此处将打开预览文件"
placement="top"
>
<span class="text" @click="previewFile">
{{ fileData }}
</span>
</el-tooltip>
</div>
<el-tooltip
class="box-item"
effect="dark"
content="点击删除"
placement="top"
>
<el-icon
class="icon_del"
style="margin: 8px"
v-show="fileData"
@click.stop="deleteFile"
>
<Delete />
</el-icon>
</el-tooltip>
</div>
</div>
</template>
</el-upload>
<!-- 预览弹框 -->
<el-dialog
v-model="dialogVisible"
title="预览"
width="40%"
height="30vh"
:before-close="handleClose"
:close-on-click-modal="false"
:destroy-on-close="true"
>
<div v-if="fileData.includes('mp3')">
<audio style="width: 100%" controls :src="fileData"></audio>
</div>
<div v-else-if="fileData.includes('mp4')">
<video style="width: 100%" controls :src="fileData"></video>
</div>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, watchEffect } from 'vue'
import { reqAliOssUpload } from '@/api/aliOSS'
import axios from 'axios'
const props = defineProps({
modelValue: {
type: Array,
default: Array,
},
fileType: {
type: String,
default: 'image/*,video/*',
},
reqUrl: {
type: Number,
default: null,
},
reqType: {
type: String,
default: '',
},
reqCategory: {
type: String,
default: '',
},
limitNum: {
type: Number,
default: 4,
},
tip: {
type: String,
default: '音频',
},
})
const filesArray = ref()
//声明事件消息
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
//保存图片内存临时地址
const fileData = ref('')
watchEffect(() => {
fileData.value = props.modelValue as any
})
const uploadRequest = async (file: any) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
const res = await reqAliOssUpload(props.reqUrl, {
category: props.reqCategory,
mediaType: props.reqType,
})
const data = res.data
// 随机数
const random = Math.floor(Math.random() * 10000)
// 文件后缀
const fileSuffix = file.file.name.split('.').pop()
const params = {
key: data.dir + `${Date.now()}_${random}.${fileSuffix}`,
policy: data.policy,
OSSAccessKeyId: data.accessid,
success_action_status: '200',
signature: data.signature,
file: file.file,
}
const url = 'https://' + data.host
const config = {
headers: {
'Content-Type': 'multipart/form-data',
'Access-Control-Allow-Origin': '*',
},
}
const uploadRes = await axios.post(url, params, config)
console.log('uploadRes', uploadRes)
const filePath = 'https://' + data.host + '/' + params.key
filesArray.value = filePath
emits('update:modelValue', filePath)
}
// 删除文件
const deleteFile = () => {
emits('update:modelValue', '')
}
// 预览文件
const dialogVisible = ref(false)
const previewFile = (e: any) => {
console.log('预览', e)
dialogVisible.value = true
}
// 关闭bofang
const handleClose = () => {
dialogVisible.value = false
// 销毁弹框组件
}
</script>
<style lang="scss">
.fileList {
// 鼠标移入背景变色且字体变色
&:hover {
background-color: #f5f7fa;
}
.icon_del {
&:hover {
color: #ef1e1e;
cursor: pointer;
}
}
.fileName {
// 鼠标移入字体变色
.text {
&:hover {
color: #409eff;
text-decoration: underline;
cursor: pointer;
}
}
}
}
</style>
vue3+ts+alioss+elementplus文件上传组件封装
最新推荐文章于 2024-07-03 16:25:05 发布