Files
sgxt_web/src/components/MyComponents/Upload/index.vue

302 lines
7.3 KiB
Vue
Raw Normal View History

2025-04-12 14:54:02 +08:00
<template>
2025-07-10 19:51:22 +08:00
<div
class="form-item-box"
:class="props.showBtn ? 'showBtn-upload' : ''"
:style="{ width: width }"
>
2025-04-12 14:54:02 +08:00
<el-upload
v-bind="$attrs"
:headers="headers"
:multiple="false"
class="avatar-uploader"
:limit="props.limit"
:action="actionUrl"
2025-07-10 19:51:22 +08:00
:list-type="props.showBtn ? '' : 'picture-card'"
2025-04-12 14:54:02 +08:00
:file-list="fileList"
show-file-list
:on-exceed="handleExceed"
:on-success="handlerSuccess"
:before-upload="beforeImgUpload"
>
<template #default>
2025-07-10 19:51:22 +08:00
<el-button v-if="props.showBtn" size="small" type="primary"
>上传文件</el-button
>
2025-07-05 12:03:00 +08:00
<el-icon v-else> <Plus /> </el-icon>
2025-04-12 14:54:02 +08:00
</template>
2025-07-05 12:03:00 +08:00
<template #file="{ file }" v-if="!props.showBtn">
2025-04-12 14:54:02 +08:00
<div v-if="props.isImg">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
2025-07-10 19:51:22 +08:00
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
2025-07-05 12:03:00 +08:00
<el-icon> <zoom-in /></el-icon>
2025-04-12 14:54:02 +08:00
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
</span>
</span>
</div>
<div v-else>
<div class="file-wrap">
<span>
<svg-icon :icon="getSuffix(file.name)" />
</span>
<span class="file-name">{{ file.name }}</span>
</div>
<span class="el-upload-list__item-actions">
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleDownload(file)"
>
<el-icon>
<Download />
</el-icon>
</span>
<span
v-if="!disabled"
class="el-upload-list__item-delete"
@click="handleRemove(file, fileList)"
>
<el-icon>
<Delete />
</el-icon>
</span>
</span>
</div>
</template>
</el-upload>
<el-dialog v-model="dialogVisible">
<img style="width: 100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script setup>
import { COMPONENT_WIDTH } from "@/constant";
2025-07-10 19:51:22 +08:00
import { ref, defineProps, defineEmits, computed, watch, onMounted } from "vue";
2025-07-05 12:03:00 +08:00
import { ElMessage } from "element-plus";
2025-04-12 14:54:02 +08:00
import { useStore } from "vuex";
const props = defineProps({
//获取组件传值
modelValue: {
type: Array,
default: []
},
limit: {
type: Number,
default: 1
},
isImg: {
type: Boolean,
default: true
},
width: {
default: COMPONENT_WIDTH,
type: String
2025-07-05 12:03:00 +08:00
},
2025-07-10 19:51:22 +08:00
showBtn: {
type: Boolean,
default: false
2025-04-12 14:54:02 +08:00
}
});
const actionUrl = computed(() =>
props.isImg
? "/mosty-api/mosty-base/minio/image/upload/id"
: "/mosty-api/mosty-base/minio/file/upload"
);
const emits = defineEmits(["update:modelValue", "handleChange"]);
//获取后缀
const getSuffix = (fileName) => {
let suffix = "";
try {
suffix = fileName.substr(fileName.lastIndexOf(".") + 1, 4); //截取最后一个点号后4个字符
} 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";
//视频 音频
2025-07-15 19:27:43 +08:00
var videolist = [ "mp4", "m2v", "mkv", "rmvb", "wmv", "avi", "flv", "mov", "m4v" ];
2025-04-12 14:54:02 +08:00
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";
};
const store = useStore();
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const disabled = ref(false);
const headers = ref({
Authorization: store.getters.token
});
2025-07-10 19:51:22 +08:00
const fileList = ref([]);
2025-07-15 19:27:43 +08:00
;
2025-07-10 19:51:22 +08:00
watch(
() => props.modelValue,
(val) => {
let arr = val ? val : [];
if (arr && arr.length > 0) {
if (!props.sfUrl) {
fileList.value = arr.map((el) => {
return { url: `/mosty-api/mosty-base/minio/image/download/` + el };
});
} else {
fileList.value = arr.map((el) => {
return { url: el };
});
}
}
},
{ immediate: true }
);
2025-07-05 12:03:00 +08:00
2025-04-12 14:54:02 +08:00
const handlerSuccess = (res, file) => {
file.url = `/mosty-api/mosty-base/minio/image/download/` + res.data;
fileList.value.push(file);
2025-07-10 19:51:22 +08:00
let arr = props.modelValue ? props.modelValue : [];
arr.push(res.data);
emits("update:modelValue", arr);
2025-04-12 14:54:02 +08:00
emits("handleChange", props.modelValue);
};
2025-07-05 19:37:28 +08:00
2025-04-12 14:54:02 +08:00
const handleExceed = (files, fileList) => {
ElMessage.warning(`限制,只能上传${props.limit}个文件或图片`);
};
const beforeImgUpload = (file) => {
if (props.isImg) {
let isIMG = false;
if (getSuffix(file.name) === "IMG") {
isIMG = true;
}
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isIMG) {
ElMessage.error("上传图片只能是jpg/png/jpeg/bmp/gif格式!");
}
if (!isLt5M) {
ElMessage.error("上传图片大小不能超过 5MB!");
}
return isIMG && isLt5M;
} else {
return true;
}
};
//查询图片
const handlePictureCardPreview = (file) => {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
};
const handleDownload = (file) => {
window.open(file.response.data);
};
const handleRemove = (file) => {
let index = fileList.value.findIndex(function (item) {
return item.url === file.url;
});
fileList.value.splice(index, 1);
props.modelValue.splice(index, 1);
emits("handleChange", props.modelValue);
2025-07-05 19:37:28 +08:00
emits("update:modelValue", props.modelValue);
2025-04-12 14:54:02 +08:00
};
2025-07-10 19:51:22 +08:00
const propsModelValue = ref();
2025-04-12 14:54:02 +08:00
</script>
<style lang="scss" scoped>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.file-wrap {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
::v-deep .svg-icon {
font-size: 48px;
margin: 28px 0 2px 0;
}
.file-name {
width: 88%;
font-size: 14px;
line-height: 22px;
text-align: center;
overflow: hidden;
/*将对象作为弹性伸缩盒子模型显示*/
display: -webkit-box;
/*设置子元素排列方式*/
-webkit-box-orient: vertical;
/*设置显示的行数,多出的部分会显示为...*/
-webkit-line-clamp: 2;
}
}
2025-07-05 12:03:00 +08:00
</style>