<template>
|
<div class="">
|
<hr class="border-light m-0" v-if="isShowHr">
|
<div :class="!isShowHr&&!isList&&isUpload?'':'pt-4 pb-4'" >
|
<div v-if="isList">
|
<h6 class="font-weight-semibold mb-4">{{title}}</h6>
|
<div class="row" v-if="fileList && fileList.length">
|
<div v-for="attachment in fileList" :key="attachment.id" :class="layoutClass!==''?layoutClass:'col-sm-6 col-md-4 col-lg-6 col-xl-4'">
|
<div class="message-attachment ui-bordered p-2 mr-3 mb-3" :title="attachment.name">
|
<div v-if="isImage(attachment)" :style="{'background-image': `url(/httpImage/${attachment.url})`}" class="message-attachment-img"></div>
|
<div v-else-if="isFile(attachment)" class="message-attachment-file display-4"><i :class="fileIcon(attachment)"></i></div>
|
<div class="media-body ml-3">
|
<strong class="message-attachment-filename">{{attachment.name}}</strong>
|
<div class="text-muted small">{{Math.round(attachment.size/1024)}}KB</div>
|
<div>
|
<span v-if="isImage(attachment)"><a :href="`/httpImage/${attachment.url}`" target="_blank">查看</a> </span>
|
<a :href="`/httpImage/${attachment.url}`" :download="attachment.name">下载</a>
|
<a v-if="isDelFile" href="javascript:void(0)" @click="handleDelFile(attachment.id)">删除</a>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="text-center text-muted small pt-2 pb-2" v-if="!fileList || !fileList.length">
|
暂无附件
|
</div>
|
</div>
|
<div class="upload-content pr" :class="!isShowHr&&!isList&&isUpload?'pt-2':'pt-4 pb-2'" v-if="isUpload">
|
<div class="upload-progress" v-if="isShowProgress">
|
<b-progress variant="success" striped :style="`opacity: ${isShowProgress&&showProgress?1:0}`" :value="progressValue" height="5px"/>
|
</div>
|
<ladda-btn
|
:loading="upLoadLoading"
|
data-style="slide-down"
|
@click.native="$refs.fileInput.value='';$refs.fileInput.click()"
|
:class="uploadBtnClass"
|
>
|
<i :class="uploadBtnIcon"></i> {{uploadBtntext}}
|
</ladda-btn>
|
<input type="file" ref="fileInput" @change="handleUpLoad"/>
|
</div>
|
</div>
|
</div>
|
</template>
|
<style src="@/vendor/styles/pages/messages.scss" lang="scss"></style>
|
<script>
|
import axios from 'axios'
|
import LaddaBtn from '@/vendor/libs/ladda/Ladda'
|
import { findByIds } from '@/server/common.js'
|
export default {
|
name: 'uploadCommon',
|
props: {
|
/* 查询已有附件ids(逗号分隔) */
|
initFileIds: {
|
default: '',
|
type: String
|
},
|
/* 是否显示附件列表 */
|
isList: {
|
default: true,
|
type: Boolean
|
},
|
/* 是否显示上传控件 */
|
isUpload: {
|
default: true,
|
type: Boolean
|
},
|
/* 上传控件列表是否删除功能 */
|
isDelFile: {
|
default: true,
|
type: Boolean
|
},
|
/* 类型限制(后缀名,分隔) 传入示例'.png,.jpg' 不限制为 '' */
|
limitTypes: {
|
default: '',
|
type: String
|
},
|
/* 文件大小限制 传入示例'1M' 单位支持G、M、K、B 无单位按B计算 不限制为 '' */
|
limitSize: {
|
default: '1M',
|
type: String
|
},
|
/* 用于刷新上传组件 value时间戳字符串 */
|
refreshTimes: {
|
default: '',
|
type: String
|
},
|
|
/* 排列布局 value 1,2,3 default:3 */
|
layout: {
|
default: 3,
|
type: Number
|
},
|
/* 上传列表title */
|
title: {
|
default: '上传列表',
|
type: String
|
},
|
/* 上传按钮文字 */
|
uploadBtntext: {
|
default: '上传',
|
type: String
|
},
|
/* 上传按钮icon */
|
uploadBtnIcon: {
|
default: 'ion ion-md-cloud-upload',
|
type: String
|
},
|
uploadBtnClass: {
|
default: 'btn btn-primary',
|
type: String
|
},
|
/* 是否显示hr 线 */
|
isShowHr: {
|
default: true,
|
type: Boolean
|
},
|
/* 是否显示上传进度 */
|
isShowProgress: {
|
default: true,
|
type: Boolean
|
}
|
/**
|
* 上传组件回值方法
|
* @description 上传组件回值方法
|
* @return { function } addFilesBaBackFN 添加上传成功后返回 {fileIds,fileList}
|
* @return { function } delFilesBaBackFN 删除后返回 {fileIds,fileList}
|
*/
|
},
|
data() {
|
return {
|
userInfo: this.$store.getters.basicUserInfo,
|
fileList: [],
|
fileIds: [],
|
upLoadLoading: false,
|
showProgress: false,
|
progressValue: 0
|
}
|
},
|
computed: {
|
layoutClass() {
|
if (this.layout === 1) {
|
return 'col-12'
|
} else if (this.layout === 2) {
|
return 'col-6'
|
} else {
|
return ''
|
}
|
}
|
},
|
methods: {
|
/* 图标判断 start */
|
isImage(file) {
|
if (!file) {
|
return false
|
}
|
return /\.jpeg$|\.jpg$|\.png$|\.gif$/i.test(file.name)
|
},
|
isFile(file) {
|
if (!file) {
|
return false
|
}
|
return !/\.jpeg$|\.jpg$|\.png$|\.gif$/i.test(file.name)
|
},
|
fileIcon(file) {
|
if (!file) {
|
return false
|
}
|
let icon = 'far fa-file'
|
|
if (/\.zip$|\.tar$|\.tar\.gz$|\.rar$/i.test(file.name)) {
|
icon = 'far fa-file-archive'
|
}
|
if (/\.mp3$|\.wma$|\.ogg$|\.flac$|\.aac$/i.test(file.name)) {
|
icon = 'far fa-file-audio'
|
}
|
if (/\.avi$|\.flv$|\.wmv$|\.mov$|\.mp4$/i.test(file.name)) {
|
icon = 'far fa-file-video'
|
}
|
if (/\.js$|\.es6$|\.ts$/i.test(file.name)) {
|
icon = 'fab fa-js'
|
}
|
if (/\.doc$|\.docx$/i.test(file.name)) {
|
icon = 'far fa-file-word'
|
}
|
if (/\.xls$|\.xlsx$/i.test(file.name)) {
|
icon = 'far fa-file-excel'
|
}
|
if (/\.htm$|\.html$/i.test(file.name)) {
|
icon = 'fab fa-html5'
|
}
|
if (/\.pdf$/i.test(file.name)) {
|
icon = 'far fa-file-pdf'
|
}
|
if (/\.txt$/i.test(file.name)) {
|
icon = 'far fa-file-alt'
|
}
|
if (/\.css$/i.test(file.name)) {
|
icon = 'fab fa-css3'
|
}
|
return icon
|
},
|
/* 图标判断 end */
|
islimitTypes(fileObj) {
|
if (this.limitTypes === '') {
|
return true
|
}
|
if (this.limitTypes.indexOf(fileObj.name.replace(/^.+\./, '')) === -1) {
|
this.$toast({
|
type: 'error',
|
message: '上传类型错误!必须是' + this.limitTypes
|
})
|
return false
|
}
|
return true
|
},
|
islimitSize(fileObj) {
|
if (this.limitSize === '') {
|
return true
|
}
|
let size = 0
|
if (this.limitSize.indexOf('G') !== -1) {
|
size = this.limitSize.replace('G', '') * 1024 * 1024 * 1024
|
} else if (this.limitSize.indexOf('M') !== -1) {
|
size = this.limitSize.replace('M', '') * 1024 * 1024
|
} else if (this.limitSize.indexOf('K') !== -1) {
|
size = this.limitSize.replace('K', '') * 1024
|
} else if (this.limitSize.indexOf('B') !== -1) {
|
size = this.limitSize.replace('B', '')
|
} else {
|
size = this.limitSize
|
}
|
if (size < fileObj.size) {
|
this.$toast({
|
type: 'error',
|
message: '上传大小错误!必须小于' + this.limitSize
|
})
|
return false
|
}
|
return true
|
},
|
// 查询附件列表
|
async getFileList(fileIds) {
|
this.$store.commit('HANDLE_LOADING_OPEN')
|
let res = await findByIds({ fileIds })
|
if ((res && res.length) || res.length === 0) {
|
// this.fileList = [...this.fileList,...res]
|
this.fileList = res
|
}
|
this.$store.commit('HANDLE_LOADING_CLOSE')
|
},
|
// 上传附件
|
async handleUpLoad(e) {
|
/* 拿到上传文件 */
|
if (e.target.files.length === 0) {
|
return false
|
}
|
let file = e.target.files[0]
|
if (!this.islimitTypes(file)) {
|
return false
|
}
|
if (!this.islimitSize(file)) {
|
return false
|
}
|
/* 重置进度条 */
|
this.showProgress = true
|
this.progressValue = 0
|
/* 开启上传按钮loding */
|
this.upLoadLoading = true
|
|
/* 创建FormData文件对象 */
|
const fd = new FormData()
|
const token = JSON.parse(
|
sessionStorage.getItem('loginedInfo')
|
).access_token.split(' ')[1]
|
fd.append('file', file)
|
fd.append('fileSource', 'FDFS')
|
|
try {
|
let res = await axios({
|
method: 'post',
|
url: `data/api-f/files?access_token=${token}`,
|
data: fd,
|
onUploadProgress: progressEvent => {
|
if (
|
this.isShowProgress &&
|
progressEvent.loaded &&
|
progressEvent.total
|
) {
|
this.progressValue =
|
progressEvent.loaded / progressEvent.total * 100
|
}
|
}
|
})
|
if (res && !res.error && res.data) {
|
this.$toast({
|
type: 'success',
|
message: '上传成功!'
|
})
|
this.fileIds = [...this.fileIds, res.data.id]
|
this.fileList = [...this.fileList, res.data]
|
/* 回调传值 */
|
this.$emit('addFilesBaBackFN', {
|
fileIds: this.fileIds,
|
fileList: this.fileList
|
})
|
} else {
|
this.$toast({
|
type: 'error',
|
message: '上传失败!' + res.message
|
})
|
this.progressValue = 0
|
this.showProgress = false
|
}
|
} catch (error) {
|
this.$toast({
|
type: 'error',
|
message: '上传失败!' + error.message
|
})
|
this.progressValue = 0
|
this.showProgress = false
|
}
|
/* 结束上传按钮loding */
|
this.upLoadLoading = false
|
},
|
// 删除附件
|
handleDelFile(id) {
|
// TODO
|
this.fileList.map((iteam, index) => {
|
if (iteam.id === id) {
|
this.fileList.splice(index, 1)
|
}
|
})
|
let fileIdsIndex = this.fileIds.indexOf(id)
|
if (fileIdsIndex !== -1) {
|
this.fileIds.splice(fileIdsIndex, 1)
|
}
|
/* 回调传值 */
|
this.$emit('delFilesBaBackFN', {
|
fileIds: this.fileIds,
|
fileList: this.fileList
|
})
|
}
|
},
|
created() {},
|
watch: {
|
/* 监控初始化FileIds */
|
initFileIds: {
|
handler(newVal, oldVal) {
|
if (this.refreshTimes === '' && newVal !== oldVal) {
|
let fileIds = newVal ? newVal.split(',') : []
|
this.fileIds = Array.from(new Set([...this.fileIds, ...fileIds]))
|
if (newVal !== '') {
|
this.getFileList(newVal)
|
} else {
|
this.fileList = []
|
this.fileIds = ''
|
}
|
}
|
},
|
deep: true,
|
immediate: true
|
},
|
refreshTimes: {
|
handler(newVal, oldVal) {
|
if (newVal !== oldVal) {
|
this.fileList = []
|
this.fileIds = ''
|
if (this.initFileIds) {
|
let fileIds = this.initFileIds ? this.initFileIds.split(',') : []
|
this.fileIds = Array.from(new Set([...this.fileIds, ...fileIds]))
|
this.getFileList(this.initFileIds)
|
}
|
}
|
},
|
deep: true
|
},
|
progressValue(newVal, oldVal) {
|
if (newVal !== oldVal && newVal >= 100) {
|
setTimeout(() => {
|
this.showProgress = false
|
this.progressValue = 0
|
}, 1500)
|
}
|
}
|
},
|
components: {
|
LaddaBtn
|
}
|
}
|
</script>
|
|
<style lang="scss" >
|
.upload-img-icon {
|
width: 60px;
|
background-size: 100%;
|
background-repeat: no-repeat;
|
background-position: center;
|
}
|
.upload-progress {
|
width: 100%;
|
position: absolute;
|
left: 0;
|
top: 2px;
|
opacity: 1;
|
transition: all 0.5s;
|
}
|
.upload-content {
|
position: relative;
|
input[type='file'] {
|
position: absolute;
|
opacity: 0;
|
width: 82px;
|
height: 38px;
|
left: 0;
|
}
|
}
|
</style>
|