html
复制代码
<template>
<div :class="$options.name">
<ul class="uploadImages">
<li
class="uploadImage"
v-loading="loadings[i]"
v-for="(a, i) in uploadImages"
:key="i"
@click="clickFile(a)"
>
<img :src="a" @load="load(a, i)" v-if="typeof a !== 'number'" />
<el-button
v-if="showRemoveBtn(a)"
class="remove-btn"
type="text"
icon="el-icon-delete"
@click.stop="remove(a, i)"
/>
</li>
</ul>
<el-alert
v-if="alertMsg !== false"
style="margin-top: 10px"
:closable="true"
:close-text="``"
:description="``"
:effect="'light'"
:show-icon="true"
:title="alertMsg || `最多可上传${limit}个图片,每个附件大小不超过${maxSize}M`"
:type="'warning'"
/>
<el-upload
style="display: none"
ref="upload"
:accept="accept"
:action="'#'"
:auto-upload="false"
:multiple="true"
:on-change="change"
:show-file-list="false"
/>
<el-image ref="image" style="display: none" src="" :preview-src-list="[previewSrc]" />
</div>
</template>
<script>
export default {
name: "sgUploadImage",
components: {},
data() {
return {
accept: `.${this.$global.resourceTypes
.find((v) => v.label == `图片`)
.suffixs.join(",.")}`,
form: {},
uploadBtn: null, //上传触发按钮
disabled: false,
alertMsg: ``, //如果为false就隐藏提示内容
limit: 1, //默认只能传1张
maxSize: 10, //默认最大传10MB的图片
imgFiles: [], //图像的base64对象数组
files: [], //图像的File对象数组
previewSrc: null,
loadings: [],
};
},
props: ["data"],
computed: {
uploadImages() {
return this.imgFiles && this.imgFiles.length ? this.imgFiles : 1;
},
},
watch: {
data: {
handler(newValue, oldValue) {
//console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
if (Object.keys(newValue || {}).length) {
this.form = JSON.parse(JSON.stringify(newValue));
} else {
this.form = {};
}
this.disabled = this.form.disabled;
this.alertMsg = this.form.alertMsg;
// 获取外部回显上传列表----------------------------------------
let files =
typeof this.form.files === `string`
? JSON.parse(this.form.files || "[]")
: this.form.files || [];
Array.isArray(files) || (files = [files]);
this.files = files;
this.imgFiles = [];
this.files.forEach((v, i) => this.getImageSrc(v, i));
// ----------------------------------------
this.form.accept && (this.accept = this.form.accept);
this.form.limit && (this.limit = this.form.limit);
this.form.maxSize && (this.maxSize = this.form.maxSize);
this.$nextTick(() => {
let width = this.form.width || 200;
let height = this.form.height || 150;
this.$el.style.setProperty("--uploadImage_width", `${width}px`);
this.$el.style.setProperty("--uploadImage_height", `${height}px`);
this.$el.style.setProperty(
"--background",
`url(http://via.placeholder.com/${width}x${height})`
);
this.uploadBtn = this.$refs.upload.$children[0].$refs.input;
this.uploadBtn.webkitdirectory = this.form.webkitdirectory; //让el-upload支持上传文件夹
});
},
deep: true, //深度监听
immediate: true, //立即执行
},
},
created() {},
mounted() {},
destroyed() {},
methods: {
load(d, idx) {
this.$set(this.loadings, idx, false);
},
getImageSrc(file, idx = this.files.length - 1) {
this.$set(this.loadings, idx, true);
if (file.path) {
this.imgFiles.push(this.$d.responseFile(file));
} else {
this.$g.file2Base64Image(file, (d) => this.imgFiles.push(d));
}
},
showRemoveBtn(d) {
return !(typeof d === "number");
},
remove(d, i) {
this.files.splice(i, 1);
this.imgFiles.splice(i, 1);
this.$emit(`change`, { files: this.files });
},
showImage(previewSrc) {
this.previewSrc = previewSrc;
this.$refs.image.showViewer = true; //显示大图
},
clickFile(d) {
if (this.disabled) return;
if (typeof d === "number") {
this.uploadBtn.click();
} else {
this.showImage(d);
}
},
change(file) {
if (this.files.length >= this.limit) {
this.$message(`最多只能上传${this.limit}个文件`);
} else {
let fileSizeMB = file.size / 1024 / 1024; //转换文件大小(单位MB)
if (this.maxSize && fileSizeMB > this.maxSize) {
this.$message(
`"${file.name}"文件大小超过${this.$g.getSize(this.maxSize * 1024 * 1024)}`
);
} else {
this.files.push(file.raw);
this.getImageSrc(file.raw);
this.$emit(`change`, { files: this.files });
}
}
},
},
};
</script>
<style lang="scss" scoped>
.sgUploadImage {
.uploadImages {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
.uploadImage {
flex-shrink: 0;
margin-right: 10px;
margin-bottom: 10px;
position: relative;
border-radius: 4px;
width: var(--uploadImage_width);
height: var(--uploadImage_height);
/*背景图片*/
background: #f5f7fa var(--background) no-repeat center / cover;
img {
width: 100%;
height: 100%;
object-position: center;
object-fit: cover;
}
&:last-of-type {
margin-bottom: 0;
}
&:hover {
.remove-btn {
opacity: 1;
pointer-events: auto;
}
}
.remove-btn {
background-color: #f56c6c;
border-radius: 88px;
box-sizing: border-box;
padding: 5px;
color: white;
cursor: pointer;
transition: 0.2s;
position: absolute;
right: 10px;
top: 10px;
opacity: 0;
pointer-events: none;
&:hover {
background-color: red;
}
}
}
}
}
</style>