目录
- 页面代码
- 样式代码
- 页面展示
页面代码
dialog.vue
<!-- 上传文件 -->
<template>
<el-dialog
title="上传文件"
:visible.sync="dialogVisible"
width="60%"
top="6vh"
:close-on-click-modal="false"
@close="handleClose"
>
<ele-form
ref="submitRef"
v-model="formData"
inline
:form-desc="formDesc"
:request-fn="handleSubmit"
:is-show-submit-btn="true"
:is-show-cancel-btn="true"
submit-btn-text="确定"
:is-show-error-notify="false"
@cancel="handleClose"
>
<template v-slot:attachmentList>
<el-upload
ref="uploadRef"
v-loading="uploadLoading"
class="upload_demo"
list-type="picture-card"
:accept="fileTypeList.join(',')"
action="/supervise_basic/upload/oss/fileupload"
name="files"
multiple
:file-list="fileList"
:headers="{ 'X-Token': getToken() }"
:data="{ relativePath: 'SCWS/' }"
:on-success="onSuccessHandler"
:on-error="onErrorHandler"
:on-remove="onRemoveHandler"
:before-upload="beforeUploadHandler"
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{ file }" class="el_upload_preview_list">
<!-- pdf 文件展示文件名 -->
<div v-if="['application/pdf'].includes(file.raw.type)" class="pdfContainer">
{{ file.name }}
</div>
<!-- 图片预览 -->
<el-image
v-else
:id="'image' + file.uid"
class="el-upload-list__item-thumbnail"
:src="file.url"
:preview-src-list="[file.url]"
/>
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in" />
</span>
<span class="el-upload-list__item-delete" @click="onRemoveHandler(file)">
<i class="el-icon-delete" />
</span>
</span>
</div>
<template v-slot:tip>
<div class="el_upload_tip">
仅支持上传{{ fileTypeList.join('/') }}格式文件,且不超过{{ fileMaxSize }}MB。
</div>
</template>
</el-upload>
</template>
</ele-form>
</el-dialog>
</template>
<script>
import _ from 'lodash.clonedeep'
import { getToken } from '@/utils/tool'
import { uploadBloodFile } from '@/api/blood_api.js'
export default {
name: 'UploadFileDialog',
components: {},
data() {
return {
dialogVisible: true,
rowData: {},
formData: {
attachmentList: []
},
uploadLoading: false,
fileTypeList: ['.png', '.jpg', '.jpeg', '.pdf'],
fileMaxSize: 5,
fileList: [],
getToken
}
},
computed: {
formDesc() {
return {
xbrq: {
type: 'date',
layout: 24,
label: '日期',
required: true,
attrs: {
valueFormat: 'yyyy-MM-dd'
},
class: {
textareaTop: true
},
style: {
marginBottom: '10px'
}
},
attachmentList: {
type: 'upload',
layout: 24,
label: '上传文件',
required: true
}
}
}
},
watch: {
dialogVisible() {
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.clearValidate()
}
},
created() {
const list = []
this.fileTypeList.forEach((item) => {
list.push(item, item.toUpperCase())
this.fileTypeList = list
})
},
methods: {
open(rowData) {
console.log('rowData----', rowData)
this.rowData = _(rowData)
this.dialogVisible = true
},
beforeUploadHandler(file) {
const ext = file.name.substring(file.name.lastIndexOf('.'))
const isLt = file.size / 1024 / 1024 < this.fileMaxSize
if (!this.fileTypeList.includes(ext)) {
this.$message.error(`请上传${this.fileTypeList.map((item) => item)}格式的文件!`)
return false // 会调用 on-remove 钩子
} else if (!isLt) {
this.$message.error('上传文件大小不能超过 5MB!')
return false // 会调用 on-remove 钩子
} else {
this.uploadLoading = true
return true
}
},
onRemoveHandler(file, fileList) {
/**
* fileList 有无值取决于是上传失败调用 on-remove 钩子,还是手动点击删除按钮删除文件,详细解释如①②:
* ① 如果文件上传失败(before-upload 中return false)会自动调用 on-remove 钩子(不用我们自己处理删除文件),此时第二个参数 fileList 有值(为数组);
* ② 如果手动点击删除文件按钮删除,此时 fileList 是没有的,为 undefined;
* 因此通过 fileList 来判断是否执行 on-remove 钩子中我们自己处理移除文件(避免:已经上传了N张图片后,上传不符合要求的图片时调用当前方法导致第 N-1 张图片被删除)
*/
if (fileList) return
const { uploadFiles } = this.$refs.uploadRef
uploadFiles.splice(
uploadFiles.findIndex((item) => item.uid === file.uid),
1
)
this.formData.attachmentList.splice(
this.formData.attachmentList.findIndex(
(item) => item.uid === file.uid && item.filename === file.name
),
1
)
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.validateField('attachmentList')
},
// eslint-disable-next-line handle-callback-err
onErrorHandler(err, file, fileList) {
this.uploadLoading = false
this.$message.error(`${file.name}文件上传失败,请重新上传!`)
},
// 文件上传成功
onSuccessHandler(response, file) {
this.uploadLoading = false
console.log('response----', response)
const fileList = response.data.fileUploadInfoList
? response.data.fileUploadInfoList.map((item) => {
return {
filename: item.filename,
saved_filename: item.path,
filetype: item.fileType,
uid: file.uid
}
})
: []
this.formData.attachmentList.push(...fileList)
// 部分表单校验
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.validateField('attachmentList')
},
// 预览 pdf、图片
handlePictureCardPreview(file) {
// 预览pdf
if (['application/pdf'].includes(file.raw.type)) {
window.open(file.url)
return
}
// 预览文件
const imageDom = document.getElementById('image' + file.uid)
imageDom && imageDom.click()
},
handleSubmit() {
this.$refs.submitRef.validate().then((valid) => {
const { id, voucher_no } = this.rowData
const { attachmentList, xbrq } = this.formData
const params = {
id,
voucher_no,
xgws: attachmentList.map((item) => {
return {
wsmc: item.filename,
wsdz: item.saved_filename,
xbrq: xbrq
}
})
}
uploadBloodFile(params).then((res) => {
this.$common.CheckCode(res, res.msg || '上传成功', () => {
this.handleClose()
this.$emit('update')
})
})
})
},
handleClose() {
this.rowData = {}
for (const key in this.formData) {
if (this.formData[key] && this.formData[key].constructor === Array) {
this.formData[key] = []
} else if (this.formData[key] && this.formData[key].constructor === Object) {
this.formData[key] = {}
} else {
this.formData[key] = ''
}
}
this.dialogVisible = false
}
}
}
</script>
<style lang='scss' scoped>
@import '@/styles/dialog-style.scss';
</style>
样式代码
@/styles/dialog-style.scss
::v-deep .el-dialog {
min-width: 760px;
.el-dialog__header {
font-weight: 700;
border-left: 3px solid #00a4ff;
}
.el-dialog__headerbtn {
top: 13px;
}
.ele-form {
.el-form-item__error {
top: 75%;
}
.el-form-item {
margin-bottom: 0;
}
.ele-form-btns {
width: 100%;
.el-form-item__content {
text-align: right;
}
}
// ele-form 表单项为 textarea 时,当前表单项和上一个表单项校验提示文字位置调整
.textareaTop {
& + .el-form-item__error {
// 上一个表单项检验提示文字位置
top: 65% !important;
}
}
.currentTextarea {
& + .el-form-item__error {
// 当前 textarea 表单项检验提示文字位置
top: 92% !important;
}
}
}
.upload_demo {
margin-top: 8px;
& + .el-form-item__error {
top: 156px !important;
}
}
}
.dialog_section_title {
margin: 10px -20px;
padding: 10px 20px;
// background-color: #eee;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
border-left: 3px solid #00a4ff;
font-weight: 700;
text-align: left;
}
.noData {
padding: 10px 0;
text-align: center;
color: #ccc;
}
.el_upload_tip {
margin-top: 15px;
line-height: 20px;
text-align: left;
color: red;
}
.el_upload_preview_list {
height: 100%;
// el-uplaod组件卡片预览类型预览pdf样式
.pdfContainer {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.blue-theme {
.dialog_section_title {
border-top: 1px solid #202936;
border-bottom: 1px solid #202936;
}
}
.night-theme {
.dialog_section_title {
border-top: 1px solid #202936;
border-bottom: 1px solid #202936;
}
}
页面展示