add 文件上传组件

This commit is contained in:
赵霄
2023-12-06 14:17:01 +08:00
parent a88fd94df6
commit b2c8556bee
13 changed files with 648 additions and 26 deletions
+9 -1
View File
@@ -3,6 +3,12 @@
<template v-if="fileList && fileList.length > 0">
<div v-for="file in fileList" :key="file.id" class="file-name" @click="handlePreview(file)">{{ file.fileName }}</div>
</template>
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl" alt="">
</div>
</div>
</div>
</template>
@@ -32,7 +38,9 @@ export default {
},
data () {
return {
fileList: []
fileList: [],
image: false,
imageUrl: null
}
},
watch: {
+1 -1
View File
@@ -3,7 +3,7 @@
<van-field
v-model="selectedDataNames"
:label="label"
:placeholder="$t('clickSelect') + label"
:placeholder="$t('pleaseSelect') + label"
readonly
rows="1"
autosize
+260
View File
@@ -0,0 +1,260 @@
<template>
<div class="upload-comp">
<div class="upload-box">
<input type="file" class="upload-box-input" @change="handleUpload" />
<van-button type="primary" plain>
<template #icon>
<van-icon class="iconfont" class-prefix="icon" name="shangchuan" />
</template>
{{ $t('clickToUpload') }}
</van-button>
</div>
<!--文件列表-->
<div class="file-list" v-if="fileList && fileList.length > 0">
<div class="file-item" v-for="file in fileList" :key="file.id">
<div class="file-item-name" @click="handlePreview(file)">{{ file.fileName }}</div>
<van-icon name="delete-o" @click="handleDelete(file)" />
</div>
</div>
<div id="images">
<div class="image" v-viewer="{movable: false}">
<img v-show="image" :src="imageUrl" alt="">
</div>
</div>
</div>
</template>
<script>
import { getFileInfo, uploadFile } from '../api/api'
import { previewPdf } from '../utils/previewPdf'
import Vue from 'vue'
import { ACCESS_TOKEN } from '../store/mutation-types'
import { getFileAccessHttpUrl } from '../api/manage'
const FILE_TYPE_ALL = 'all'
const FILE_TYPE_IMG = 'image'
const FILE_TYPE_IMGS = ['jpg', 'jpeg', 'png', 'raw']
const FILE_TYPE_PDF = 'pdf'
// 本系统限制可以上传的文件格式
const CAN_UPLOAD_FILE_TYPE = 'pdf,docx,doc,xlsx,xls,ppt,pptx,rar,zip,jpg,jpeg,png,avi,wmv,mov,rm,mp4,cad'
// 支持预览的文件后缀
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx']
const Base64 = require('js-base64').Base64
export default {
name: 'ZUpload',
props: {
value: {
type: String,
required: false,
default: null
},
// 文件最大大小,默认500MB
fileMaxSize: {
type: Number,
required: false,
default: 500
},
// 可以上传文件的类型
fileType: {
type: String,
required: false,
default: CAN_UPLOAD_FILE_TYPE
}
},
data () {
return {
fileList: [],
image: false,
imageUrl: null
}
},
watch: {
value: {
handler () {
this.fileList = []
if (this.value) {
this.getFileList()
}
},
immediate: true
}
},
methods: {
handleUpload (event) {
const e = window.event || event
const file = e.target.files[0]
/* 进行相关校验 */
const checkResult = this.beforeUpload(file)
if (!checkResult) {
return
}
const formData = new FormData()
formData.append('file', file)
formData.append('biz', 'temp')
uploadFile(formData).then(res => {
if (res.success) {
this.fileList.push(res.result)
this.$emit('change', this.fileList.map(item => item.id).join(','))
} else {
this.$message(res.message)
}
})
},
beforeUpload (file) {
// 校验大小
const fileSize = file.size
if (fileSize === 0) {
this.$message(this.$t('uploadFile.cannotUploadEmpty'))
return false
}
if (this.fileMaxSize && fileSize > 1024 * 1024 * this.fileMaxSize) {
this.$message(this.$t('uploadFile.pleaseUpload') + this.fileMaxSize + this.$t('uploadFile.theFollowingDocuments'))
return false
}
if (fileSize > 1024 * 1024 * 500) {
this.$message(this.$t('uploadFile.maxSize'))
return false
}
// 校验格式
const fileType = file.type
if (this.fileType === FILE_TYPE_ALL) {
return true
}
// 截取文件后缀名
const fileSuffix = (file.name ? file.name.split('.')[file.name.split('.').length - 1] : '').toLowerCase()
if (this.fileType === CAN_UPLOAD_FILE_TYPE && CAN_UPLOAD_FILE_TYPE.split(',').includes(fileSuffix)) {
return true
}
if (this.fileType === FILE_TYPE_IMG && fileType.indexOf('image') < 0) {
this.$message(this.$t('uploadFile.onlyUploadPic'))
return false
}
if (this.fileType === FILE_TYPE_IMG && FILE_TYPE_IMGS.includes(fileSuffix)) {
return true
}
if (this.fileType === FILE_TYPE_IMG && !FILE_TYPE_IMGS.includes(fileSuffix)) {
this.$message(this.$t('uploadFile.pleaseUpload') + FILE_TYPE_IMGS.join('、') + this.$t('uploadFile.file'))
return false
}
if (this.fileType.indexOf(fileSuffix) === -1) {
this.$message(this.$t('uploadFile.pleaseUpload') + `${this.fileType}` + this.$t('uploadFile.file'))
return false
}
return true
},
getFileList () {
this.fileList = []
const fileIdArr = this.value.split(',')
fileIdArr.forEach(async id => {
const fileObj = await this.getFileInfo(id)
if (fileObj.id) {
this.fileList.push(fileObj)
}
})
},
getFileInfo (id) {
let result = {}
return new Promise(resolve => {
getFileInfo({ id }).then(res => {
if (res.success) {
result = res.result
}
}).finally(() => {
resolve(result)
})
})
},
handlePreview (file) {
if (!file || !file.url) {
return
}
// 截取文件后缀名
const fileSuffix = (file.fileName ? file.fileName.split('.')[file.fileName.split('.').length - 1] : '').toLowerCase()
const canPreview = CAN_PREVIEW_FILE_SUFFIX.some(tt => fileSuffix === tt)
// 判断是否为可预览格式的文件
if (!canPreview) {
this.$message(this.$t('uploadFile.cannotPreview'))
return
}
const fileFullUrl = `${window._CONFIG.domianWebSocketURL}/sys/common/view/${file.id}?token=${Vue.ls.get(ACCESS_TOKEN)}&fullfilename=${file.fileName}`
// 图片预览,使用自己添加的组件
if (FILE_TYPE_IMGS.includes(fileSuffix)) {
this.imageUrl = getFileAccessHttpUrl(file.id)
// 获取viewer实例
const viewer = this.$el.querySelector('.image').$viewer
// 调用show方法进行显示预览图
viewer.show()
// this.$refs.imagePreviewModal.open(file)
return
}
// pdf预览
if (FILE_TYPE_PDF.includes(fileSuffix)) {
const url = previewPdf(file.id)
window.open(url)
return
}
// 其余可预览文件仍使用KKFile进行预览
const url = `${window._CONFIG.onlinePreviewDomainURL}?url=${encodeURIComponent(Base64.encode(fileFullUrl))}`
window.open(url)
},
handleDelete (file) {
const index = this.fileList.findIndex(tt => tt.id === file.id)
const fileTempList = JSON.parse(JSON.stringify(this.fileList))
this.fileList.splice(index, 1)
this.$emit('change', this.fileList.map(item => item.id).join(','))
}
},
model: {
event: 'change',
prop: 'value'
}
}
</script>
<style scoped lang="less">
@import '~@/assets/less/common.less';
.upload-comp {
padding: 0.2rem 0.32rem;
}
.upload-box {
position: relative;
width: fit-content;
&-input {
position: absolute;
z-index: 1;
height: 100%;
width: 100%;
opacity: 0;
}
}
.van-button--normal {
font-size: 0.28rem;
}
.file-list {
margin-top: 0.16rem;
}
.file-item {
color: @primary-color;
margin-bottom: 0.16rem;
display: flex;
align-items: baseline;
&-name {
word-break: break-word;
margin-right: 0.16rem;
}
}
.file-item:last-child {
margin-bottom: 0;
}
</style>