248 lines
6.1 KiB
Vue
248 lines
6.1 KiB
Vue
|
|
<template>
|
||
|
|
<div class="main-box">
|
||
|
|
<div class="file_box" v-for="(item, index) in fileList" :key="index">
|
||
|
|
<div class="show_file" :style="{ width: width, height: width }">
|
||
|
|
<div class="icon_box_y" :style="{ width: width, height: width }">
|
||
|
|
<svg-icon :icon="getSuffix(item.url)" />
|
||
|
|
<span class="file_name_box">{{ item.name }}</span>
|
||
|
|
</div>
|
||
|
|
<div class="load_and_del" :style="{ width: width, height: width }">
|
||
|
|
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
|
||
|
|
<DeleteFilled v-if="props.isEdit" @click="delFile(index)" />
|
||
|
|
</el-icon>
|
||
|
|
<el-icon class="load_and_del_icon" :size="18" color="#aaaaaa">
|
||
|
|
<Download @click="downloadFile(item.url)" />
|
||
|
|
</el-icon>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="file_box" v-if="fileList.length != props.limit && props.isEdit">
|
||
|
|
<div class="upload_img" :style="{ width: width, height: width }">
|
||
|
|
<div class="icon_box" :style="{ width: width, height: width }">
|
||
|
|
<el-icon :size="30" color="#aaaaaa">
|
||
|
|
<Plus />
|
||
|
|
</el-icon>
|
||
|
|
</div>
|
||
|
|
<div class="file_box_item" :style="{ width: width, height: width }">
|
||
|
|
<input
|
||
|
|
type="file"
|
||
|
|
:style="{ width: width, height: width }"
|
||
|
|
class="file_input"
|
||
|
|
id="file"
|
||
|
|
@change="fileChange"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import {
|
||
|
|
ref,
|
||
|
|
defineProps,
|
||
|
|
defineEmits,
|
||
|
|
defineExpose,
|
||
|
|
computed,
|
||
|
|
onMounted
|
||
|
|
} from "vue";
|
||
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||
|
|
import request from "@/utils/request";
|
||
|
|
import axios from "axios";
|
||
|
|
const props = defineProps({
|
||
|
|
modelValue: {
|
||
|
|
type: String,
|
||
|
|
default: ""
|
||
|
|
},
|
||
|
|
width: {
|
||
|
|
type: String,
|
||
|
|
default: "150px"
|
||
|
|
},
|
||
|
|
limit: {
|
||
|
|
type: Number,
|
||
|
|
default: 1
|
||
|
|
},
|
||
|
|
isEdit: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const fileList = ref([]);
|
||
|
|
const count = ref(0); // 上传的数量
|
||
|
|
|
||
|
|
const emits = defineEmits(["update:modelValue", "handleChange"]);
|
||
|
|
//获取后缀
|
||
|
|
const getSuffix = (fileName) => {
|
||
|
|
let suffix = "";
|
||
|
|
try {
|
||
|
|
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4);
|
||
|
|
if (suffix.indexOf("?") !== -1) suffix = suffix.replaceAll("?", "");
|
||
|
|
} catch (err) {
|
||
|
|
suffix = "";
|
||
|
|
return "OTHER";
|
||
|
|
}
|
||
|
|
// fileName无后缀返回 false
|
||
|
|
if (!suffix) return "";
|
||
|
|
// 图片格式
|
||
|
|
var imglist = ["png", "jpg", "jpeg", "bmp", "gif"];
|
||
|
|
if (imglist.includes(suffix)) return "IMG";
|
||
|
|
//txt
|
||
|
|
if (suffix === "txt") return "TXT";
|
||
|
|
//excel XLS
|
||
|
|
const excelist = ["xls", "xlsx"];
|
||
|
|
if (excelist.includes(suffix)) return "XLS";
|
||
|
|
// 匹配 word
|
||
|
|
var wordlist = ["doc", "docx"];
|
||
|
|
if (wordlist.includes(suffix)) return "DOC";
|
||
|
|
//pdf
|
||
|
|
if (suffix === "pdf") return "PDF";
|
||
|
|
//视频 音频
|
||
|
|
var videolist = [
|
||
|
|
"mp4",
|
||
|
|
"m2v",
|
||
|
|
"mkv",
|
||
|
|
"rmvb",
|
||
|
|
"wmv",
|
||
|
|
"avi",
|
||
|
|
"flv",
|
||
|
|
"mov",
|
||
|
|
"m4v"
|
||
|
|
];
|
||
|
|
if (videolist.includes(suffix)) return "VIDEO";
|
||
|
|
var musiclist = ["mp3", "wav", "wmv"];
|
||
|
|
if (musiclist.includes(suffix)) return "MUSIC";
|
||
|
|
var pptlist = ["ppt", "pptx"];
|
||
|
|
if (pptlist.includes(suffix)) return "PPT";
|
||
|
|
//压缩包
|
||
|
|
var yslist = ["7z", "rar", "zip", "apz", "ar", "hpk", "hyp", "hbc2"];
|
||
|
|
if (yslist.includes(suffix)) return "YS";
|
||
|
|
//否则返回other
|
||
|
|
return "OTHER";
|
||
|
|
};
|
||
|
|
// 删除
|
||
|
|
function delFile(index) {
|
||
|
|
fileList.value = fileList.value.filter((item, i) => {
|
||
|
|
return i !== index;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
// 文件下载
|
||
|
|
function downloadFile(url) {
|
||
|
|
window.open('/mosty-base/minio/image/download/'+url, "_blank");
|
||
|
|
}
|
||
|
|
// 选择文件
|
||
|
|
function fileChange(e) {
|
||
|
|
let file = document.getElementById("file").files[0];
|
||
|
|
let name = file.name;
|
||
|
|
let formData = new FormData();
|
||
|
|
formData.append("file", file);
|
||
|
|
axios
|
||
|
|
.post("/mosty-base/minio/image/upload/id", formData, {
|
||
|
|
"Content-type": "multipart/form-data"
|
||
|
|
})
|
||
|
|
.then((res) => {
|
||
|
|
if (res.status == 200 && res.data && res.data.code === 10000) {
|
||
|
|
let url = res.data.data;
|
||
|
|
let f = {
|
||
|
|
url: url,
|
||
|
|
name: name
|
||
|
|
};
|
||
|
|
fileList.value.push(f);
|
||
|
|
count.value = count.value + 1;
|
||
|
|
let list = fileList.value.map((item) => {
|
||
|
|
return item.url;
|
||
|
|
});
|
||
|
|
emits("handleChange", JSON.stringify(list));
|
||
|
|
} else {
|
||
|
|
ElMessage.warning("文件上传失败");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
onMounted(() => {
|
||
|
|
if (props.modelValue) {
|
||
|
|
let list = JSON.parse(props.modelValue);
|
||
|
|
list.forEach((item, index) => {
|
||
|
|
let temp = {
|
||
|
|
url: item,
|
||
|
|
name: "文件" + (index + 1)
|
||
|
|
};
|
||
|
|
fileList.value.push(temp);
|
||
|
|
});
|
||
|
|
count.value = list.length;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped lang="scss">
|
||
|
|
.main-box {
|
||
|
|
width: 100%;
|
||
|
|
.file_box {
|
||
|
|
background-color: #112b63;
|
||
|
|
border: 1px dashed #4579b5;
|
||
|
|
margin: 10px 0 0 10px;
|
||
|
|
border-radius: 5px;
|
||
|
|
position: relative;
|
||
|
|
.show_file {
|
||
|
|
overflow: hidden;
|
||
|
|
box-sizing: border-box;
|
||
|
|
&:hover > .load_and_del {
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
.load_and_del {
|
||
|
|
display: none;
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
.load_and_del_icon {
|
||
|
|
cursor: pointer;
|
||
|
|
margin-left:5px;
|
||
|
|
margin-top: 5px;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
.icon_box_y {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
flex-direction: column;
|
||
|
|
.file_name_box {
|
||
|
|
margin-top: 10px;
|
||
|
|
width: 80%;
|
||
|
|
line-height: 30px;
|
||
|
|
height: 30px;
|
||
|
|
overflow: hidden;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
::v-deep .svg-icon {
|
||
|
|
font-size: 48px;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
.upload_img {
|
||
|
|
position: relative;
|
||
|
|
.icon_box {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
flex-direction: column;
|
||
|
|
position: relative;
|
||
|
|
z-index: 1;
|
||
|
|
}
|
||
|
|
.file_box_item {
|
||
|
|
position: absolute;
|
||
|
|
opacity: 0;
|
||
|
|
z-index: 2;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
.file_input {
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
.file_box_item_show {
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|