代码
dialog.vue
<!-- 上传、更新照片 -->
<template>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
width="30%"
top="6vh"
:close-on-click-modal="false"
@close="handleClose"
>
<ele-form
ref="submitRef"
v-model="formData"
inline
:form-desc="formDesc"
:is-show-submit-btn="false"
:is-show-error-notify="false"
>
<template v-slot:files>
<!-- 【主要代码】 -->
<el-upload
ref="uploadRef"
v-loading="uploadLoading"
class="upload_demo"
list-type="picture-card"
accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG"
action="/api/supervise_basic/upload/oss/fileupload"
name="files"
:file-list="fileList"
:headers="{ 'X-Token': getToken() }"
:data="{ relativePath: 'face/' }"
: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 }">
<el-image
:id="'image' + file.uid"
class="el-upload-list__item-thumbnail"
:src="file.type === 'update' ? sysConfigData.mon_sys_ossurl + file.url : 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>
</el-upload>
</template>
</ele-form>
<template v-slot:footer>
<el-button size="mini" @click="handleClose">取消</el-button>
<el-button type="primary" size="mini" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</template>
<script>
import _ from 'lodash.clonedeep'
import { getToken, getStore } from '@/utils/tool'
import { addFace, updateFace } from '@/api/file_cabinet.js'
// import { operationFormDesc } from '../constant/formList'
export default {
name: 'OperationDialog',
components: {},
data() {
return {
vuex: JSON.parse(getStore('vuex') || '{}'),
dialogVisible: false,
dialogType: '',
rowData: {},
formData: {
files: []
},
uploadLoading: false,
fileList: [],
getToken
}
},
computed: {
sysConfigData() {
return (this.vuex && this.vuex.app && this.vuex.app.sysConfigData) || {}
},
title() {
return this.dialogType === 'add' ? '上传照片' : '更新照片'
},
submitAx() {
return this.dialogType === 'add' ? addFace : updateFace
},
formDesc() {
// return operationFormDesc(this)
return {
xm: {
type: 'input',
label: '姓名',
layout: 24,
disabled: true
},
sfzmhm: {
type: 'input',
label: '身份证号码',
layout: 24,
disabled: true
},
dwmc: {
type: 'input',
label: '所属部门',
layout: 24,
disabled: true
},
sjhm: {
type: 'input',
label: '手机号码',
layout: 24,
disabled: true
},
files: {
type: 'upload',
label: '人脸信息',
layout: 24,
required: true
}
}
}
},
watch: {
dialogVisible() {
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.clearValidate()
},
'formData.files': {
handler(val) {
this.$nextTick(() => {
const dom = document.querySelector('.el-upload--picture-card')
// 【注意】限制只能传一张照片,有已传照片时就不显示上传控件
if (val.length) {
dom && (dom.style.display = 'none')
} else {
dom && (dom.style.display = 'inline-block')
}
})
}
}
},
created() {},
methods: {
open(type, rowData) {
this.dialogType = type
this.rowData = _(rowData)
Object.keys(this.formDesc).forEach((key) => {
this.$set(this.formData, key, rowData[key])
})
if (this.rowData.files) {
this.fileList = this.rowData.files.map((item) => {
return {
name: item.wjmc,
url: item.wjlj,
type: 'update'
}
})
}
this.dialogVisible = true
},
beforeUploadHandler(file) {
const ext = file.name.substring(file.name.lastIndexOf('.') + 1)
const types = ['png', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG']
const isLt = file.size / 1024 / 1024 < 5
if (!types.includes(ext)) {
this.$message.error(`请上传${types.map((item) => item)}格式的文件!`)
return false
} else if (!isLt) {
this.$message.error('上传文件大小不能超过 5MB!')
return false
} 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
if (file.type === 'update') {
uploadFiles.splice(
uploadFiles.findIndex((item) => item.wjlj === file.wjlj),
1
)
this.formData.files.splice(
this.formData.files.findIndex(
(item) => item.wjlj === file.url && item.wjmc === file.name
),
1
)
} else {
uploadFiles.splice(
uploadFiles.findIndex((item) => item.uid === file.uid),
1
)
this.formData.files.splice(
this.formData.files.findIndex((item) => item.uid === file.uid && item.wjmc === file.name),
1
)
}
// 【注意】删除图片,校验图片字段
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.validateField('files')
},
// 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 {
wjmc: item.filename,
wjlj: item.path,
wjgs: item.fileType,
uid: file.uid
}
})
: []
this.formData.files.push(...fileList)
// 【注意】上传成功图片,校验图片字段
this.$refs.submitRef &&
this.$refs.submitRef.$refs.form &&
this.$refs.submitRef.$refs.form.validateField('files')
},
// 预览图片
handlePictureCardPreview(file) {
const imageDom = document.getElementById('image' + file.uid)
imageDom && imageDom.click()
},
handleSubmit() {
this.$refs.submitRef.validate().then((valid) => {
const { xm, files } = this.formData
const { dwdm, yhdh } = this.rowData
const params = {
dwdm,
yhdh,
xm,
files: files.map((item) => {
const { wjmc, wjlj, wjgs } = item
return { wjmc, wjlj, wjgs }
})
}
this.submitAx(params).then((res) => {
this.$common.CheckCode(res, `${this.title}成功`, () => {
this.handleClose()
this.$emit('update')
})
})
})
},
handleClose() {
this.fileList = []
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';
>>> .el-dialog__body {
padding-bottom: 10px;
}
>>> .el-dialog .upload_demo + .el-form-item__error {
top: 100% !important;
}
</style>
dialog-style.scss
::v-deep .el-dialog {
min-width: 500px;
.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: 186px !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;
}
.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;
}
}
效果图展示
【补充】render 中写 展示图片并预览 代码
file: {
type: 'upload',
label: '附件文件',
disabled: true,
layout: 24,
attrs: {
blockSize: 'middle',
// listType: 'picture-card',
multiple: false,
params: { relativePath: 'REPORT/' },
uploadAPI: '/supervise_basic/upload/oss/fileupload',
token: getToken(),
accept: '.png,.jpg,.jpeg,.JGP,.JPEG,.PNG,.doc,.docx,.xls,.xlsx'
},
render: (h, _data, value) => {
console.log(value)
return h(
'div',
{ staticClass: 'form-file-wrapper' },
value && value.length
? value.map((item, index) => {
const wjlj = _this.sysConfigData.mon_oss_filepath + item.wjlj
if (/\.(gif|jpg|jpeg|png|GIF|JPG|JPEG|PNG)$/.test(item.wjmc)) {
// 判断是否为图片
return h('el-image', {
key: index,
staticClass: 'form-file-image',
attrs: {
src: wjlj,
fit: 'cover',
'preview-src-list': [wjlj]
}
})
} else {
// 不是图片的以链接的形式展示
return h('el-link', {
key: index,
staticClass: 'form-file-link',
attrs: {
href: wjlj,
target: '_blank',
download: item.wjmc, // 下载文件
underline: false
},
domProps: { innerText: item.wjmc }
})
}
})
: '暂无'
)
}
}
添加样式
.form-file-image {
width: 120px;
height: 120px;
margin-right: 10px;
}