效果图:
完整代码:
- 上传文件组件代码
<template>
<div>
<!-- 上传文件提示语 例:尺寸:375px*384px -->
<p class="tip" style="margin:0" v-if="params.fileTip">{{params.fileTip}}</p>
<div :class="params.imageCard?'image-card':''">
<!-- 文件上传输入框(隐藏) -->
<input type="file" @change="uploadSubmit($event)" ref="fileUpload" style="display: none;" :multiple="params.multiple" multipleaccept="image/*">
<!-- 上传按钮 -->
<div v-if="!params.imageCard&&fileList.length<params.limit">
<el-button :size="params.buttonSize" type="primary" @click="uploadBtn">{{params.buttonText}}</el-button>
</div>
<!-- 上传图片框 -->
<div v-else-if="params.imageCard&&(fileList.length<params.limit)||params.limit===0">
<div class="card-box" :style="params.previewImageStyle" @click="uploadBtn">+</div>
</div>
<!-- 图片展示列表 -->
<div class="preview-image" v-if="type==='image'">
<div :style="params.previewImageStyle" class="image-box" v-for="(item,index) of fileList" :key="index">
<img :src="item.url" :style="params.previewImageStyle">
<img src="@/assets/delete.png" alt="删除" class="del" @click="fileDel(index)">
<img src="@/assets/turn_left.png" alt="左移" class="turn left" v-if="index>0" @click="fileLeft(index)">
<img src="@/assets/turn_right.png" alt="右移" class="turn right" v-if="index<fileList.length-1" @click="fileRight(index)">
</div>
</div>
<!-- 文件展示列表 -->
<div class="preview-file" v-if="type==='file'">
<div class="file-box" v-for="(item,index) of fileList" :key="index">
<span>{{item.path}}</span>
<img src="@/assets/delete.png" alt="删除" @click="fileDel(index)">
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props:{
type:{
type:String,
default:'image'//image:上传列表展示图片;file:上传列表展示文件名/路径
},
uploadParams:{
type:Object,
default:{}
},
fileList:{
type:Array,
default:[] //已上传文件集合
},
uploadRequest:{
type:Function //上传函数
}
},
computed:{
params:function(){
return Object.assign({
buttonSize:'mini', //上传按钮尺寸,参考el-button尺寸
buttonText:'点击上传', //上传按钮文案
fileTip:null, //上传提示语,例:尺寸:375px*384px
fileSize:null, //允许上传的文件大小
previewImageStyle:'width:100px;height:100px', //展示图片大小样式
multiple:false, //是否多传
limit:0, //文件数量限制
imageCard:false //上传按钮是否显示图片上传框
},this.uploadParams);
},
},
methods:{
//点击上传
uploadBtn:function(){
this.$refs.fileUpload.click();
},
//清空文件选择器
fileClear:function(){
this.$refs.fileUpload.val("");
},
//文件提交
uploadSubmit:function(e){
let files = e.target.files;
let limit=this.uploadParams.limit-this.fileList.length;
let fileData=[];
// 判断文件数量
if(this.uploadParams.limit>0&&files.length>limit){
for(let i=0;i<limit;i++){
fileData.push(files[i])
}
this.$message({
showClose: true,
message: `图片不得超过${this.uploadParams.limit}张`,
type: "warning"
});
}else{
fileData=files
}
//判断文件大小
if(this.uploadParams.fileSize){
for (let file of fileData) {
if (file.size > this.uploadParams.fileSize * 1024 * 1024) {
this.$message({
showClose: true,
message: file.name + `图片超过${this.uploadParams.fileSize}M,无法上传!`,
type: "error"
});
this.$refs.fileUpload.value=null;
return;
}
}
}
//调用自定义上传接口
this.uploadRequest(fileData)
//清空文件选择器
this.$refs.fileUpload.value=null;
},
//文件删除
fileDel:function(index){
let fileData=this.fileList;
fileData.splice(index, 1);
this.$emit('fileChange',fileData)
},
//文件左移
fileLeft:function(index){
let fileData=this.fileList;
let item=fileData.splice(index, 1)
fileData.splice(index-1,0,item[0]);
this.$emit('fileChange',fileData)
},
//文件右移
fileRight:function(index){
let fileData=this.fileList;
let item=fileData.splice(index, 1)
fileData.splice(index+1,0,item[0]);
this.$emit('fileChange',fileData)
},
}
}
</script>
<style lang="scss" scoped>
.image-card{
display: flex;
}
.card-box{
box-sizing: border-box;
border: 1px dashed #ccc;
font-size: 30px;
display: flex;
justify-content: center;
align-items: center;
color: #ccc;
border-radius: 4px;
cursor: pointer;
margin: 0 5px 5px 0;
}
.tip{
font-size: 12px;
color:#ff0000;
margin-left: 10px;
}
.preview-image{
display: flex;
box-sizing: border-box;
// padding: 10px 0;
}
.image-box{
position: relative;
margin: 0 5px 5px 0;
border:1px solid #eee;
box-sizing: content-box;
.del{
position: absolute;
top:-11px;
right: -11px;
width: 22px;
height: 22px;
cursor: pointer;
display: none;
}
img{
object-fit: cover;
}
}
.image-box:hover .turn,.image-box:hover .del{
display: block;
}
.turn{
width: 25px;
height: 25px;
position: absolute;
top:50%;
cursor: pointer;
// border-radius: 50%;
transform: translateY(-10px);
display: none;
}
.left{
left: 0;
}
.right{
right:0;
}
.file-box{
height: 32px;
display: flex;
align-items: center;
cursor: pointer;
line-height: auto;
img{
width: 20px;
height: 20px;
margin: 2px 0 0 10px;
display: none;
}
}
.file-box:hover{
color: #999;
}
.file-box:hover img{
display: block;
}
</style>
2.父组件部分代码
<file-upload type='image' :uploadParams='uploadParams' :uploadRequest='uploadFile' :fileList='poster'>
<script>
import axios from 'axios'
import fileUpload from '@/components/FileUpload'
export default {
components:{
fileUpload
},
data(){
return{
poster:[], //上传文件集合
imgurl:this.$http.uploadUrl, //后台接口
uploadParams:{
buttonSize:'mini', //上传按钮尺寸,参考el-button尺寸
buttonText:'点击上传', //上传按钮文案
fileTip:null, //上传提示语,例:尺寸:375px*384px
fileSize:null, //允许上传的文件大小
previewImageStyle:'width:100px;height:100px', //展示图片大小样式
multiple:false, //是否多传
limit:0, //文件数量限制
imageCard:false //上传按钮是否显示图片上传框
},
}
},
methods:{
uploadFile(fileData) {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
this.formData = new FormData()
for (let i of fileData) {
this.formData.append("files", i);
}
this.formData.append('purposeId', 9)
let ax = axios.create({
// 打包删除
headers: {
'Content-Type': 'multipart/form-data',
token: sessionStorage.getItem('token')
}
})
ax.post(this.imgurl+'/console-api/file-upload-multi', this.formData)
.then(res => {
if (res.data.code==200) {
this.poster=[...this.poster,...res.data.data];
this.$message({
showClose: true,
message: "图片上传完成",
type: "success"
});
}
loading.close();
})
.catch(res => {
this.$message({
showClose: true,
message: '上传失败! 请联系管理员 ... ',
type: 'error'
})
loading.close();
})
},
//上传文件更新(位置移动、文件删除)
fileChange:function(data){
this.poster=data;
},
}
}
</script>