<template>
<div class="freePic">
<!-- -->
<el-upload
class="avatar-uploader"
:list-type="uploadType"
:action="fileuploadUrl"
:file-list="fileList"
:before-upload="fileChange"
:on-success="uploadSuccess"
:on-error="uploadFiled"
:on-exceed="overfileuploadNumber"
:beforeRemove="fileBerofeRemove"
:on-remove="fileRemove"
:limit="limit"
:disabled="!isShow"
:on-preview="handlePictureCardPreview"
:class="{hide:hideUpload}"
>
<i class="el-icon-upload" v-if="isShow" style="font-size: 50px;line-height: 1.5;"><p style="font-size: 19px;font-weight: lighter">点击上传</p></i>
<!-- <el-button style="margin-left: 10px;" size="mini" type="success" v-if="isShow" >点击上传</el-button>-->
</el-upload>
<div slot="tip" v-if="isShow" class="el-upload__tip">【请上传 {{this.suffixList.join('、')}} 文件, {{fileSize?'单个文件最大'+fileSize+'MB,':''}}<span style="color: red"> 上传{{limit?'最多'+limit:'可多'}}个</span>】</div>
<!-- 图片放大展示 -->
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import fileApi from '@/api/file-api';
export default {
/* 图片展示 upload */
name: "upload-pic-card",
props: {
/* v-model绑定的值 */
value: {
type: Array,
default: () => []
},
/* 上传文件类型*/
uploadType:{
type: String,
default: ''
},
//上传文件位置URL路径-分类
uploadUrl: {
type: String
},
/* 限制上传数量*/
limit: {
type: Number,
default: null
},
/* 允许上传文件的后缀类型 */
suffixList:{
type:Array,
default(){
return []
}
},
/* 允许上传文件的-大小 */
fileSize:{
type:Number,
default: null
},
/* 是否服务端删除图片 */
serverdel: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
isShow:{
type: Boolean,
default: false
}
},
data() {
return {
dialogImageUrl: "",//展示地址链接
dialogVisible: false,
fileList: this.value,
fileuploadUrl: fileApi.uploadFiles( `uploadChildPath=${this.uploadUrl}`), // 上传文件地址
};
},
computed: {
// 上传张数大于限制张数的时候将上传框隐藏
hideUpload() {
return !this.isShow;
}
},
watch: {
value: function(n) {
this.fileList = n
// 修改 v-model 数据
this.$emit('input', n)
},
},
methods: {
//放大展示
handlePictureCardPreview(file) {
// this.dialogImageUrl = file.url;
// this.dialogVisible = true;
this.$emit("preview",file.url);
},
// 上传文件 改变时
// 文件上传成功
uploadSuccess(response, file, fileList) {
this.$emit("warrantySuccess",response)
this.$emit('repairSuccess',response)
this.$emit('upkeepSuccess',response)
const { raw } = file
const { data, success} = response
const { type } = raw;
if(success && data) {
data.map(item=>this.fileList.push({name: item.fileName, url: item.url, type: 'image'}))
// this.fileList.push({name: data[0].fileName, url: data[0].url, type: 'image'})
this.$message({message: '文件上传成功', type: 'success',duration: 2000})
} else {
this.$message({message: '文件上传失败', type: 'warning',duration: 2000})
fileList.pop()
}
// this.loading = false
// 修改 v-model 数据
this.$emit('input', this.fileList)
if (this.limit&&this.fileList.length >= this.limit) {
document.getElementsByClassName('el-upload--picture-card')[0].style.display = 'none';
}
},
// 图片改变时大小类型验证
fileChange(file) {
// if(file.status === "ready") {
// 文件准备就绪未上传
/*
image/jpeg
image/png
const isJPG = file.type === 'image/jpeg';
*/
const FileExt = file.name.replace(/.+\./, "");
const isLt5M = this.fileSize?file.size / 1024 / 1024 > this.fileSize:false;
if (this.suffixList.length>0&&this.suffixList.toString().toLowerCase().indexOf(FileExt.toLowerCase()) === -1) {
this.$message({
type: 'warning',
message: `请上传后缀名为${this.suffixList.join(',')}文件!`
});
return false;
}else {
if(isLt5M) {
this.$notify.error({
title: '异常',
message: `上传图片大小不能超过 ${this.fileSize}MB!`,
duration: 2000
});
return false
}else {
return true
}
}
// }
},
// 文件超出上传个数
overfileuploadNumber(file, fileList) {
this.$notify.error({
title: '异常',
message: `文件最多上传${fileList.length}个`,
duration: 2000
});
},
// 文件在列表被移除前
async fileBerofeRemove(file, fileList) {
if(file.status === 'success') {
// console.log(!this.serverdel)
return new Promise((resvole, reject) => {
if(!this.serverdel) {
resvole()
return
}
this.$confirm('该操作删除文件后不可找回,请谨慎操作?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(res =>{
Promise.all([fileApi.delServerFile({url: file.url}), file.id? fileApi.delete({id: file.id}):'']).then(res => {
const [resOne, resTwo] = res;
this.$message({type: 'success', message: '文件删除成功',duration: 2000})
resvole()
}).catch(err => {
this.$message({type: 'error', message: '文件删除失败',duration: 2000})
reject()
})
}).catch(err => console.log(err))
})
}
if(file.status === "uploading") {
this.$message({type: 'warning', message: '文件上传被取消',duration: 2000})
// this.loading = false
}
},
// 文件在列表被移除后
fileRemove(file, fileList) {
// this.fileList = this.fileList.filter(item => item.uid !== file.uid); // 删除时候过滤掉被删除的内容
/*const index = this.fileList.findIndex(item => item.uid === file.uid)
this.fileList.splice(index, 1)*/
this.fileList=fileList
// 修改 v-model 数据
this.$emit('input', this.fileList)
if (this.fileList.length>0&&this.fileList.length < this.limit) {
document.getElementsByClassName('el-upload--picture-card')[0].style.display='';
}
},
// 文件上传失败
uploadFiled(err, file, fileList) {
this.$message({message: '文件上传失败', type: 'warning',duration: 2000})
this.loading = false
},
//获取文件名称
getFileName(url) {
let name = "";
if (url && url !== "") {
name = url.substring(url.lastIndexOf("/") + 1);
} else {
name = "无";
}
return name;
},
},
};
</script>
<style lang="scss" scoped>
.freePic ::v-deep .hide .el-upload--picture-card {
display: none;
}
.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;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100px;
height: 100px;
line-height: 100px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
display: block;
}
</style>
2. 调用
<uploadPicAcard uploadUrl="userDows/goods/test" v-model="goodsImgUrlList" :fileSize="5" :suffixList="suffixList_1" :uploadType="'picture-card'" :limit="8" :isShow="viewType" @preview="preview"/>
// 文件预览组件
<FilePreviewComp ref="fpc"></FilePreviewComp>
import FilePreviewComp from "@/components/file-preview";
export default {
name: 'goods-info-page',
data() {
return {
suffixList_1:['jpg','png'],
/* 货物图片 */
goodsImgUrlList: [],
viewType:false,
components: {FilePreviewComp },
methods: {
//文件预览 (1. 需要添加class:【message_box_alert】)
preview(val){
this.$refs.fpc.preview(val);
},
}
3. 预览组件 (创建组件)
<style>
.el-dialog--center .el-dialog__body{
padding: 0 30px;
}
.el-dialog__body {
padding: 0;
overflow-y: auto;
height: calc(100vh - 50px) !important;
}
</style>
<template>
<div v-if="typeS == '1'">
<el-dialog
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
:destroy-on-close="dialogDestroy"
:fullscreen="true"
width="100%"
center>
<h1 slot="title" class="title-h1">{{title}}</h1>
<iframe width="100%" height="98%" :src="previewUrl"/>
</el-dialog>
</div>
<div v-else-if="typeS == '2'">
<viewimg-comp ref="viewimgcomp" :options="{image: previewUrl, smallImgShow: false, imgHeight: '40px'}" ></viewimg-comp>
</div>
<div v-else>
<el-dialog
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
:destroy-on-close="dialogDestroy"
:fullscreen="true"
center
>
<h1 slot="title" class="title-h1">{{title}}</h1>
<iframe width="100%" height="98%" :src="previewUrl"/>
</el-dialog>
</div>
</template>
<script>
import {matchType} from "@/utils/utils";
import fileApi from "@/api/file-api";
export default {
props:{
/* previewUrl: {
type: String,
default: ''
},*/
},
data(){
return {
title:'文件预览',
typeS:'0',
dialogDestroy:true,
dialogFormVisible: false,
previewUrl:'',
}
},
mounted() {
},
methods: {
/* preview(val){
// 这里需要取下 html 的高度,因为浏览器有默认的 margin
const html = document.body.parentElement
const scrollHeight = `${html ? html.scrollHeight-130 : document.body.scrollHeight-130}px`
// const scrollWidth = `${html ? html.scrollWidth : document.body.scrollWidth}px`
this.$alert(`<iframe style="padding: 0;margin: 0" width="100%" height="${scrollHeight}" src="${fileApi.onlinePreview(val)}"/>` , '预览', {
dangerouslyUseHTMLString: true,
customClass:'message_box_alert'
});
},*/
// 文件预览
preview(val){
if (matchType(val) === "pdf"){
this.typeS='1'
this.previewUrl=val;
}else if (matchType(val) === "image"){
this.typeS='2'
this.previewUrl=val;
// 调用子组件的方法
setTimeout(() => {
return this.$refs.viewimgcomp.show()
}, 100);
}else {
this.previewUrl=`https://view.officeapps.live.com/op/view.aspx?src=${val}`
}
this.dialogFormVisible = true
}
}
}
</script>
<style lang="scss" scoped>
/*.message_box_alert {
word-break: break-all !important;
width: 100%;
}*/
.title-h1{
font-size: 17px;
color: #000000;
}
</style>
/*根据文件名后缀区分 文件类型*/
export const matchType = fileName => {
// 后缀获取
var suffix = '';
// 获取类型结果
var result = '';
try {
var flieArr = fileName.split('.');
suffix = flieArr[flieArr.length - 1].toLowerCase();
} catch (err) {
suffix = '';
}
// fileName无后缀返回 false
if (!suffix) {
result = false;
return result;
}
// 图片格式
var imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
// 进行图片匹配
result = imglist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'image';
return result;
};
// 匹配txt
var txtlist = ['txt'];
result = txtlist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'txt';
return result;
};
// 匹配 excel
var excelist = ['xls', 'xlsx'];
result = excelist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'excel';
return result;
};
// 匹配 word
var wordlist = ['doc', 'docx'];
result = wordlist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'word';
return result;
};
// 匹配 pdf
var pdflist = ['pdf'];
result = pdflist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'pdf';
return result;
};
// 匹配 ppt
var pptlist = ['ppt'];
result = pptlist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'ppt';
return result;
};
// 匹配 视频
var videolist = ['mp4', 'm2v', 'mkv'];
result = videolist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'video';
return result;
};
// 匹配 音频
var radiolist = ['mp3', 'wav', 'wmv'];
result = radiolist.some(function (item) {
return item == suffix;
});
if (result) {
result = 'radio';
return result;
}
// 其他 文件类型
result = 'other';
return result;
}