Files
laws-sinotruk-client/src/components/jero/JUpload.vue
T
2023-09-26 14:41:42 +08:00

484 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div :id="containerId" style="position: relative">
<a-upload
name="file"
:action="uploadAction"
:headers="headers"
:data="{'biz':bizPath}"
:fileList="fileList"
:beforeUpload="beforeUpload"
@change="handleChange"
:disabled="disabled"
:returnUrl="returnUrl"
:listType="complistType"
@preview="handlePreview"
@download="handleDownload"
v-bind="$attrs"
v-on="childListeners"
:showUploadList="showUploadList ? {
showDownloadIcon: isDownload
} : false"
:class="{'uploadty-disabled':disabled}">
<template>
<slot name="customButton">
<div v-if="isImageComp">
<a-icon type="plus" />
<div class="ant-upload-text">{{ text }}</div>
</div>
<a-button v-else-if="buttonVisible">
<a-icon type="upload" />
{{ text }}
</a-button>
</slot>
</template>
</a-upload>
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl" alt="">
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { getFileAccessHttpUrl, downloadFile } from '@/api/manage'
import { getFileInfo } from '@/api/api'
import { previewPdf } from '../../utils/previewPdf'
// eslint-disable-next-line no-undef
// const Base64 = require('js-base64').Base64
const FILE_TYPE_ALL = 'all'
const FILE_TYPE_IMG = 'image'
// const FILE_TYPE_TXT = 'file'
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
const FILE_TYPE_PDF = 'pdf'
// const uidGenerator = () => {
// return '-' + parseInt(Math.random() * 10000 + 1 + '', 10)
// }
const Base64 = require('js-base64').Base64
// 支持预览的文件类型
const CAN_PREVIEW_FILE_TYPE = ['pdf', 'image']
// 不支持预览的文件后缀
const CAN_PREVIEW_FILE_SUFFIX = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'mp3', 'mp4', 'flv']
const uidGenerator = () => {
return '-' + parseInt(Math.random() * 10000 + 1, 10)
}
export default {
name: 'JUpload',
data () {
return {
uploadAction: window._CONFIG.domianURL + '/sys/common/upload',
headers: {},
fileList: [],
newFileList: [],
uploadGoOn: true,
fileTypes: this.fileType,
image: false,
imageUrl: null
}
},
props: {
text: {
type: String,
required: false,
default: '点击上传'
},
fileType: {
type: String,
required: false,
default: FILE_TYPE_ALL
},
/* 这个属性用于控制文件上传的业务路径 */
bizPath: {
type: String,
required: false,
default: 'temp'
},
value: {
type: [String, Array],
required: false
},
// update-begin- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击
disabled: {
type: Boolean,
required: false,
default: false
},
// update-end- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击
// 此属性被废弃了
triggerChange: {
type: Boolean,
required: false,
default: false
},
/**
* update -- author:lvdandan -- date:20190219 -- for:Jupload组件增加是否返回url,
* true:仅返回url
* false:返回fileName filePath fileSize
*/
returnUrl: {
type: Boolean,
required: false,
default: true
},
/**
* 仅返回文件id
* true 仅返回文件id
* false 返回reurl
* */
returnId: {
type: Boolean,
required: false,
default: false
},
number: {
type: Number,
required: false,
default: 0
},
buttonVisible: {
type: Boolean,
required: false,
default: true
},
showUploadList: {
type: Boolean,
required: false,
default: true
},
isDownload: {
type: Boolean,
required: false,
default: true
}
},
watch: {
value: {
immediate: true,
handler () {
const val = this.value
if (val instanceof Array) {
if (this.returnUrl) {
this.initFileList(val.join(','))
} else {
this.initFileListArr(val)
}
} else {
this.initFileList(val)
}
}
},
fileType () {
this.fileTypes = this.fileType
}
},
computed: {
// 透传给下级组件的事件,需要排除本组件使用的change事件
childListeners () {
const result = Object.assign({},
this.$listeners
)
delete result.change
return result
},
isImageComp () {
return this.fileType === FILE_TYPE_IMG
},
complistType () {
return this.fileType === FILE_TYPE_IMG ? 'picture-card' : 'text'
}
},
created () {
const token = Vue.ls.get(ACCESS_TOKEN)
// ---------------------------- begin 图片左右换位置 -------------------------------------
this.headers = { 'X-Access-Token': token }
this.containerId = 'container-ty-' + new Date().getTime()
// ---------------------------- end 图片左右换位置 -------------------------------------
},
methods: {
initFileListArr (val) {
if (!val || val.length === 0) {
this.fileList = []
return
}
for (let a = 0; a < val.length; a++) {
this.fileList.forEach((item) => {
if (item.url === val[a]) {
item.uid = uidGenerator()
item.response.status = 'done'
}
})
}
},
async initFileList (paths) {
if (!paths || paths.length === 0) {
this.fileList = []
return
}
let arr = paths.split(',')
// 返回路径的时候,对路径进行操作,取出所属id
if (!this.returnId && arr.length > 0) {
const newArr = []
arr.map(item => {
const itemArr = item.split('/')
newArr.push(itemArr[itemArr.length - 1])
})
arr = newArr
}
const fileList = []
for (let a = 0; a < arr.length; a++) {
// 获取每一个文件的信息,组成fileList
// 突然想判断现在的fileList 中是否是历史的信息,如果是的话则先进行匹配
const isHistory = this.fileList.find(file => file.response.status === 'history' && (file.response.result || {}).id === arr[a])
console.log('isHistory===', isHistory)
if (isHistory) {
fileList.push(isHistory)
} else {
const fileObj = await this.getFileInfo(arr[a])
const url = getFileAccessHttpUrl(arr[a])
const fileName = (fileObj || {}).fileName
const fileNameNotType = fileName.substring(0, fileName.lastIndexOf('.'))
const previewUrl = (fileObj || {}).url || ''
const previewName = previewUrl.substring(previewUrl.lastIndexOf(fileNameNotType))
fileList.push({
uid: uidGenerator(),
name: (fileObj || {}).fileName,
status: 'done',
url: url,
previewName,
response: {
status: 'history',
message: arr[a],
result: fileObj
}
})
}
}
this.fileList = [...fileList]
},
handlePathChange () {
const uploadFiles = this.fileList
let path = ''
// 文件id
let fileIds = ''
if (!uploadFiles || uploadFiles.length === 0) {
path = ''
}
const arr = []
// 如果returnid为true 只返回id
if (this.returnId) {
for (let a = 0; a < uploadFiles.length; a++) {
if (uploadFiles[a].status === 'done') {
arr.push(uploadFiles[a].response.result.id)
} else {
return
}
}
if (arr.length > 0) {
fileIds = arr.join(',')
}
this.$emit('change', fileIds)
return
}
for (let a = 0; a < uploadFiles.length; a++) {
if (uploadFiles[a].status === 'done') {
arr.push(uploadFiles[a].url)
} else {
return
}
}
if (arr.length > 0) {
path = arr.join(',')
}
this.$emit('change', path)
},
beforeUpload (file) {
this.uploadGoOn = true
file.uploadGoOn = true
const fileSize = file.size // 上传的文件大小
const fileType = file.type // 上传的文件类型
if (fileSize > 1024 * 1024 * 100) {
this.$message.warning('文件大小限制为100M')
this.uploadGoOn = false
file.uploadGoOn = false
return false
}
console.log(this.fileType)
// 不等于全部类型可以上传的时候,对上传的文件进行判断
if (this.fileType !== FILE_TYPE_ALL) {
// filter(tt => fileType.indexOf(tt) > -1) 判断用户传的文件类型,和要求传的文件类型是否一致
// 当上传的图片格式为jpg时,在此组件中,会返回类型为 image/jpeg ElememntUI设计如此 所以需要把用户传下来的jpg强制改成jpeg
this.fileTypes = this.fileTypes.replace('jpg', 'jpeg')
const arr = this.fileTypes.split(',').filter(tt => fileType.indexOf(tt) > -1)
if (arr.length === 0) {
this.$message.warning(this.fileTypeErrorMessage || `请上传${this.fileTypes}文件`)
this.uploadGoOn = false
file.uploadGoOn = false
return false
}
}
if (this.fileTypes === FILE_TYPE_IMG) {
if (fileType.indexOf('image') < 0) {
this.$message.warning('请上传图片')
this.uploadGoOn = false
file.uploadGoOn = false
return false
}
}
// TODO 扩展功能验证文件大小
return true
},
handleChange (info) {
if (!info.file.status && this.uploadGoOn === false) {
info.fileList.pop()
}
let fileList = info.fileList
if (info.file.status === 'done') {
if (this.number > 0) {
fileList = fileList.slice(-this.number)
}
if (info.file.response.success) {
fileList = fileList.map((file) => {
if (file.response) {
// let reUrl = `${file.response.result.id}?token=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.response.result.fileName}`;
file.url = getFileAccessHttpUrl(file.response.result.id)
}
return file
})
} else {
info.fileList.pop()
this.uploadGoOn = false
this.$message.warn(info.file.response.message)
}
// this.$message.success(`${info.file.name} 上传成功!`);
} else if (info.file.status === 'error') {
this.$message.error(`${info.file.name} 上传失败.`)
} else if (info.file.status === 'removed') {
this.handleDelete(info.file)
}
this.fileList = fileList
if (info.file.status === 'done' || info.file.status === 'removed') {
// returnUrl为true时仅返回文件路径
if (this.returnUrl) {
this.handlePathChange()
} else {
// returnUrl为false时返回文件名称、文件路径及文件大小
this.newFileList = []
for (let a = 0; a < fileList.length; a++) {
// update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
if (fileList[a].status === 'done') {
const fileJson = {
fileName: fileList[a].name,
filePath: fileList[a].url,
fileSize: fileList[a].size
}
this.newFileList.push(fileJson)
} else {
return
}
// update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
}
this.$emit('change', this.newFileList)
}
}
},
handleDelete (file) {
// 如有需要新增 删除逻辑
console.log(file)
},
handlePreview (file) {
if (!file || !file.url) {
return
}
const fileType = file.type
// 截取文件后缀名
const fileSuffix = file.name ? file.name.split('.')[file.name.split('.').length - 1] : ''
const canPreview = fileType ? CAN_PREVIEW_FILE_TYPE.some(tt => fileType.indexOf(tt) !== -1) : CAN_PREVIEW_FILE_SUFFIX.some(tt => fileSuffix === tt)
// 判断是否为可预览格式的文件
if (!canPreview) {
this.$message.loading('该文件类型不支持预览,正在为您准备下载...').then(() => {
this.handleDownload(file)
})
return
}
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/download/${file.response.result.id}?token=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.name}`
// 图片预览,使用自己添加的组件
if (canPreview && FILE_TYPE_IMGS.includes(fileSuffix)) {
this.imageUrl = getFileAccessHttpUrl(file.response.result.id)
// 获取viewer实例
const viewer = this.$el.querySelector('.image').$viewer
// 调用show方法进行显示预览图
viewer.show()
// this.$refs.imagePreviewModal.open(file)
return
}
// pdf预览
if (canPreview && FILE_TYPE_PDF.includes(fileSuffix)) {
const url = previewPdf(file.response.result.id)
window.open(url)
return
}
// 其余可预览文件仍使用KKFile进行预览
const url = `${window._CONFIG.onlinePreviewDomainURL}?url=${encodeURIComponent(Base64.encode(fileFullUrl))}`
window.open(url)
},
getFileUrl (fileId) {
return `${window._CONFIG.domianURL}/sys/common/download/${fileId}`
},
/**
* 通过文件的id获取文件的相关信息
* @param id
*/
getFileInfo (id) {
return new Promise(resolve => {
let result = {}
getFileInfo({ id: id }).then(res => {
if (res.success) {
result = res.result
}
}).finally(() => {
resolve(result)
})
})
},
/**
* 单个文件的下载功能
* @param file
*/
handleDownload (file) {
// 下载文件
downloadFile(`/sys/common/download/${file.response.result.id}`, file.name)
}
},
mounted () {
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style lang="less" scoped>
.uploadty-disabled {
.ant-upload-list-item {
.anticon-close {
display: none;
}
.anticon-delete {
display: none;
}
}
}
</style>