文件上传记录:
文件上传需要后端给文件服务器的地址,前端上传之后,返回文件url的外网地址,然后可以预览,下载等操作
- 子组件
<template>
<div class="file-upload" style="display:flex; flex-wrap: wrap;">
<div
class="upload-wrap"
@mouseenter="handleHover(index,'')"
@mouseleave="handleHover(index,'leave')"
v-for="(imgsrc,index) in form[photoName]"
:key="index+imgsrc.path"
>
<!-- 图片鼠标滑过出现画面 -->
<div class="review" v-if="hover&&index==index1">
<div>{{imgsrc.name}}</div>
<div class="btn-group" v-if="isImg(imgsrc.path)=='img'||isImg(imgsrc.path)=='video'">
<span @click="reviewItem(imgsrc)" title="预览">
<i class="el-icon-view"></i>
</span>
<span v-if="!noDeleteBtn" @click="removeItem(index)" title="删除">
<i class="el-icon-delete"></i>
</span>
<span v-if="importFlag" @click="importFun(imgsrc)" title="导入">
<i class="el-icon-thumb"></i>
</span>
</div>
<div class="btn-group" v-if="isFile(imgsrc.path)=='file'">
<span @click="reviewfileItem(imgsrc)" title="预览">
<i class="el-icon-view"></i>
</span>
<span style="margin-right: 10px">
<a
:href="imgsrc.path"
type="download"
:download="imgsrc.name"
target="_blank"
title="查看下载"
style="color: #fff"
>
<i class="el-icon-download"></i>
</a>
</span>
<span v-if="!noDeleteBtn" @click="removeItem(index)" title="删除">
<i class="el-icon-delete"></i>
</span>
<span v-if="importFlag" @click="importFun(imgsrc)" title="导入">
<i class="el-icon-thumb"></i>
</span>
</div>
</div>
<!-- <el-progress v-if="upload" class="progress" type="circle" :percentage="progress"></el-progress> -->
<!-- 图片回显 -->
<div
v-if="isImg(imgsrc.path)=='img'"
:style="'background:url('+imgsrc.path+')'"
class="img-wrap img-view"
></div>
<!-- 视频回显 -->
<video v-else-if="isImg(imgsrc.path)=='video'" :src="imgsrc.path" class="video-wrap"></video>
<!-- 文件回显 -->
<div class="file-review" v-else-if="isFile(imgsrc.path)=='file'">
<!-- <svg-icon
class="file"
style="width:80px; height:80px; margin-top:20px; position:absolute;left:50%;margin-left:-40px;z-index:1;"
class-name="international-icon"
icon-class="sign_files"
/> -->
<img class="file" src="@/assets/wenjian1.png" alt="" style="width:80px; height:80px; margin-top:20px; position:absolute;left:50%;margin-left:-40px;z-index:1;">
</div>
</div>
<!-- 新增 -->
<div class="upload-wrap" v-if="addFlagMore&&form[photoName].length<1">
<input
class="input"
:title="title"
type="file"
ref="uploadInput"
@change="handleChange($event,photoName)"
/>
<i class="el-icon-plus uploader-icon"></i>
<div class="title">{{title}}</div>
</div>
<div
class="upload-wrap"
v-if="!addFlagMore&&!noDeleteBtn&&(!employerFlag9||(employerFlag9&&form[photoName].length<9))"
>
<input
class="input"
:title="title"
type="file"
ref="uploadInput"
@change="handleChange($event,photoName)"
/>
<i class="el-icon-plus uploader-icon"></i>
<div class="title">{{title}}</div>
</div>
<!-- v-model:visible="dialogStatus"这样绑定控制台会提示没有值,所以改为v-model -->
<el-dialog
:title="dialogtitle"
v-model="dialogStatus"
width="40%"
top="10vh"
:append-to-body="true"
>
<img style="width:100%" v-if="imgsrc &&isImg(imgsrc)=='img'" :src="imgsrc" class="img-wrap" />
<video
style="width:100%"
v-if="imgsrc&&isImg(imgsrc)=='video'"
controls
:src="imgsrc"
class="video-wrap"
></video>
<template #footer>
<span class="dialog-footer">
<el-button size="mini" @click="dialogStatus = false">关 闭</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
// TODO: 文件Word,Excel,PDF上传
import fileUpload from '@/api/fileUpload.js'
export default {
props: {
employerFlag9: Boolean, // 用于添加九张图的标记
form: Object, // 上传的对应表单名称
photoName: String, // 上传的对应字段名称
title: String, // 标题
noDeleteBtn: Boolean, // true为没有删除按钮
importFlag: Boolean, // 导入标记
fileTypeFlag: String, // 传入文件的类型
addFlagMore: Boolean // 只能上传一张标记
},
data () {
return {
folderName: 'other', // 文件夹命上传路径 工人 custemer 雇主 employer 中介 agent 默认 other
upload: false, // 是否出现上传进度
progress: 0, // 进度条
dialogStatus: false, // 弹出框
hover: false, // 是否鼠标滑过
canShow: false,
fileShow: false,
fileType: 'img', // 文件类型
index1: null,
imgsrc: '',
switchConfig: {
imgSize: 20
},
dialogtitle: ''
}
},
computed: {
},
filters: {
filterType (type) {
if (
type === 'jpg' ||
type === 'jpeg' ||
type === 'png' ||
type === 'GIF' ||
type === 'JPG' ||
type === 'PNG' ||
type === 'gif'
) {
return 'img'
}
if (type === 'mp4') {
return 'video'
}
if (
type === 'docx' ||
type === 'doc' ||
type === 'pptx' ||
type === 'ppt' ||
type === 'xlsx' ||
type === 'xls' ||
type === 'pdf' ||
type === 'PDF' ||
type === 'zip' ||
type === 'sql' ||
type === 'html' ||
type === 'json' ||
type === 'jar' ||
type === 'js' ||
type === 'rar' ||
type === 'txt'
) {
return 'file'
}
}
},
methods: {
isImg (val) {
// 判断是图片
if (val) {
const miniTpye = val.split('.')[val.split('.').length - 1]
if (
miniTpye === 'jpeg' ||
miniTpye === 'jpg' ||
miniTpye === 'png' ||
miniTpye === 'GIF' ||
miniTpye === 'JPG' ||
miniTpye === 'PNG' ||
miniTpye === 'gif'
) {
this.fileType = 'img'
this.canShow = true
return 'img'
} else if (miniTpye === 'mp4') {
this.fileType = 'video'
this.canShow = true
return 'video'
} else {
this.canShow = false
return ''
}
} else {
this.canShow = false
return ''
}
// }
},
isFile (val) {
// 判断是文件
if (val) {
const fileType = val.split('.')[val.split('.').length - 1]
if (
fileType === 'pdf' ||
fileType === 'xls' ||
fileType === 'ppt' ||
fileType === 'pptx' ||
fileType === 'xlsx' ||
fileType === 'doc' ||
fileType === 'docx' ||
fileType === 'zip' ||
fileType === 'PDF' ||
fileType === 'sql' ||
fileType === 'html' ||
fileType === 'json' ||
fileType === 'jar' ||
fileType === 'js' ||
fileType === 'rar' ||
fileType === 'txt' ||
fileType === 'rtf'
) {
this.fileType = 'file'
this.fileShow = true
return 'file'
} else {
this.fileShow = false
return ''
}
} else {
this.fileShow = false
return ''
}
// }
},
handleChange (file, wrap) {
const uploadFile = file.target.files[0]
console.log(uploadFile, '文件')
const fileSize = uploadFile.size / 1024 / 1024
const fileName = file.target.files[0].name
const fileExtendName = fileName.split('.')[
fileName.split('.').length - 1
]
const filter = this.$options.filters.filterType
this.fileType = filter(fileExtendName)
if (uploadFile) {
if (
!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(fileName) &&
this.fileType === 'img'
) {
this.$message({
message:
'上传的文件类型不正确!可为( gif | jpg | jpeg | png | GIF | JPG | PNG)文件',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
return false
}
if (
!/\.(docx|doc|pptx|ppt|xlsx|xls|pdf|PDF|zip|sql|html|json|jar|js|rar|txt)$/.test(
fileName
) &&
this.fileType === 'file'
) {
this.$message({
message:
'上传的文件类型不正确!可为( docx | doc | pptx | ppt | xlsx | xls | pdf | PDF | zip | sql | html | json | jar | js | rar|txt )文件',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
return false
}
if (!/\.(mp4)$/.test(fileName) && this.fileType === 'video') {
this.$message({
message: '上传的文件类型不正确!只能上传MP4文件',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
return false
}
if (fileSize >= this.switchConfig.imgSize && this.fileType === 'img') {
this.$message({
message: '图片上传大小不能超过' + this.switchConfig.imgSize + 'MB',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
} else if (
fileSize >= this.switchConfig.videoSize &&
this.fileType === 'video'
) {
this.$message({
message:
'视频上传大小不能超过' + this.switchConfig.videoSize + 'MB',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
} else if (
fileSize >= this.switchConfig.fileSize &&
this.fileType === 'file'
) {
this.$message({
message: '文件上传大小不能超过' + this.switchConfig.fileSize + 'MB',
type: 'error',
showClose: true
})
this.$refs.uploadInput.value = ''
} else {
const formData = new FormData()
formData.append('file', uploadFile)
var config = {
onUploadProgress: (progressEvent) => {
this.upload = true
var complete =
((progressEvent.loaded / progressEvent.total) * 100) | 0
this.progress = complete
}
}
// http://api.gosingapore.com/hiring-communal/upload/uploadFile?folderName=other
fileUpload
.post(
'/upload/uploadFile?folderName=other' + this.folderName,
formData,
config
)
.then((res) => {
this.upload = false
if (res.code === 2000000) {
setTimeout(() => {
this.$message({
message: '上传成功',
type: 'success'
})
if (
this.photoName === 'img' ||
this.photoName === 'annexList' ||
this.photoName === 'pics' ||
this.photoName === 'customerPictures' ||
this.photoName === 'resumeAnnexList'
) {
// eslint-disable-next-line vue/no-mutating-props
this.form[this.photoName].push({
name: fileName,
path: res.data.ossUrl,
annexId: null
})
} else {
// eslint-disable-next-line vue/no-mutating-props
this.form[this.photoName] = [
{ name: fileName, path: res.data.ossUrl, annexId: null }
]
}
this.$refs.uploadInput.value = ''
}, 1000)
} else {
this.$refs.uploadInput.value = ''
}
})
.catch(() => {
this.$refs.uploadInput.value = ''
})
}
}
},
// 删除
removeItem (item) {
// eslint-disable-next-line vue/no-mutating-props
this.form[this.photoName].splice(item, 1)
},
// 预览图片
reviewItem (item) {
this.dialogStatus = true
this.imgsrc = item.path
this.dialogtitle = item.name
},
// 预览文件
reviewfileItem (item) {
window.open(`https://view.officeapps.live.com/op/view.aspx?src=${item.path}`)
},
// 鼠标移入移出
handleHover (index, type) {
this.index1 = index
// 鼠标经过事件 显示预览和删除按钮
if (type === 'leave') {
this.hover = false
} else {
this.hover = true
}
},
// 图片导入
importFun (val) {
this.$emit('importImgFun', {
obj: { annexId: null, path: val.path },
photoName: this.photoName
})
}
}
}
</script>
<style scoped lang="scss">
.file-upload {
display: inline-block;
.title {
text-align: center;
width: 120px;
bottom: 10px;
position: absolute;
//width: 100%;
left: 0;
}
transition: all 0.5s ease-in-out;
}
.file-upload:hover {
.upload-wrap {
border-color: #fff;
}
}
.review {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 102;
background-color: rgba(0, 0, 0, 0.55);
color: #fff;
// @include flex(column, space-evenly, center);
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
transition: all 0.5s ease-in-out;
animation: fadeIn 0.5s ease-in-out;
span {
cursor: pointer;
}
span:first-child {
margin-right: 15px;
i {
font-size: 16px;
}
}
}
.img-view {
background-repeat: no-repeat !important;
background-size: cover !important;
background-position: center !important;
}
.upload-wrap {
width: 120px;
height: 120px;
position: relative;
border-radius: 5px;
overflow: hidden;
border: 1px dashed #dcdcdc;
background-color: #f5f4f7;
transition: all 0.5s ease-in-out;
margin: 0 5px 5px 0;
.input,
.progress,
.img-wrap,
.video-wrap,
.uploader-icon {
position: absolute;
left: 0;
z-index: 99;
width: 100%;
height: 100%;
}
.uploader-icon {
font-size: 24px;
text-align: center;
line-height: 110px;
color: #666;
z-index: 2;
}
.input {
opacity: 0;
cursor: pointer;
}
.progress {
z-index: 100;
width: 110px;
height: 100px;
left: 5px;
top: 5px;
background-color: #f5f4f7;
/deep/ .el-progress-circle {
width: 100% !important;
height: 100% !important;
}
}
.img-wrap,
.video-wrap {
background-color: #000;
z-index: 98;
}
.file-review {
display: block;
font-size: 36px;
text-align: center;
line-height: 100px;
}
}
</style>
- 父组件
- 引用:
import fileUpload from '@/components/fileUpload/fileUpload.vue'
<!-- 第二种上传附件 -->
<div style="display: flex; flex-wrap: wrap;">
<file-upload :type="'file'" :form="form" :title="'文件上传'" :photoName="'annexList'"></file-upload>
</div>
<el-button @click="fileformclick">提交</el-button>
-
效果图:
-
预览
-
下载