2022.07.20更新:

1. 优化图片、文件上传组件交互逻辑;
2. 图片组件增加预览功能。
master
vdpAdmin 2022-07-20 17:51:10 +08:00
parent 1ddfaa17ed
commit 27ab8eab0a
7 changed files with 114 additions and 55 deletions

View File

@ -37,7 +37,7 @@ export function createDesigner(vueInstance) {
this.formConfig = deepClone(defaultFormConfig) this.formConfig = deepClone(defaultFormConfig)
//输出版本信息和语雀链接 //输出版本信息和语雀链接
console.info(`%cVariantForm %cVer${VARIANT_FORM_VERSION} %chttps://www.yuque.com/variantdev/vform`, console.info(`%cVariantForm %cVer${VARIANT_FORM_VERSION} %chttps://www.yuque.com/visualdev/vform`,
"color:#409EFF;font-size: 22px;font-weight:bolder", "color:#409EFF;font-size: 22px;font-weight:bolder",
"color:#999;font-size: 12px", "color:#999;font-size: 12px",
"color:#333" "color:#333"

View File

@ -10,17 +10,17 @@
:multiple="field.options.multipleSelect" :file-list="fileList" :multiple="field.options.multipleSelect" :file-list="fileList"
:show-file-list="field.options.showFileList" :class="{'hideUploadDiv': uploadBtnHidden}" :show-file-list="field.options.showFileList" :class="{'hideUploadDiv': uploadBtnHidden}"
:limit="field.options.limit" :on-exceed="handleFileExceed" :before-upload="beforeFileUpload" :limit="field.options.limit" :on-exceed="handleFileExceed" :before-upload="beforeFileUpload"
:on-success="handleFileUpload" :on-error="handelUploadError" :on-remove="handleFileRemove"> :on-success="handleFileUpload" :on-error="handleUploadError">
<div slot="tip" class="el-upload__tip" <div slot="tip" class="el-upload__tip"
v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div> v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
<i slot="default" class="el-icon-plus avatar-uploader-icon"></i> <i slot="default" class="el-icon-plus avatar-uploader-icon"></i>
<template #file="{ file }"> <template #file="{ file }">
<div class="upload-file-list"> <div class="upload-file-list">
<span class="upload-file-name" :title="file.name">{{file.name}}</span> <span class="upload-file-name" :title="file.name">{{file.name}}</span>
<a :href="file.url" download=""> <a :href="file.url" download="" target="_blank">
<i class="el-icon-download file-action" :title="i18nt('render.hint.downloadFile')"></i></a> <i class="el-icon-download file-action" :title="i18nt('render.hint.downloadFile')"></i></a>
<i class="el-icon-delete file-action" :title="i18nt('render.hint.removeFile')" v-if="!field.options.disabled" <i class="el-icon-delete file-action" :title="i18nt('render.hint.removeFile')" v-if="!field.options.disabled"
@click="removeUploadFile(file.name)"></i> @click="removeUploadFile(file.name, file.url, file.uid)"></i>
</div> </div>
</template> </template>
</el-upload> </el-upload>
@ -73,7 +73,7 @@
data() { data() {
return { return {
oldFieldValue: null, //fieldchange oldFieldValue: null, //fieldchange
fieldModel: null, fieldModel: [],
rules: [], rules: [],
uploadHeaders: {}, uploadHeaders: {},
@ -120,17 +120,10 @@
methods: { methods: {
handleFileExceed() { handleFileExceed() {
let uploadLimit = this.field.options.limit /* 此行不能注释下一行ES6模板字符串需要用到 */ let uploadLimit = this.field.options.limit
this.$message.warning( this.i18nt('render.hint.uploadExceed').replace('${uploadLimit}', uploadLimit) ) this.$message.warning( this.i18nt('render.hint.uploadExceed').replace('${uploadLimit}', uploadLimit) )
}, },
updateUploadFieldModelAndEmitDataChange(fileList) {
let oldValue = deepClone(this.fieldModel)
this.fieldModel = deepClone(fileList)
this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
},
beforeFileUpload(file) { beforeFileUpload(file) {
let fileTypeCheckResult = false let fileTypeCheckResult = false
let extFileName = file.name.substring(file.name.lastIndexOf('.') + 1) let extFileName = file.name.substring(file.name.lastIndexOf('.') + 1)
@ -176,29 +169,57 @@
return true return true
}, },
updateFieldModelAndEmitDataChangeForUpload(fileList, customResult, defaultResult) {
let oldValue = deepClone(this.fieldModel)
if (!!customResult && !!customResult.name && !!customResult.url) {
this.fieldModel.push({
name: customResult.name,
url: customResult.url
})
} else if (!!defaultResult && !!defaultResult.name && !!defaultResult.url) {
this.fieldModel.push({
name: defaultResult.name,
url: defaultResult.url
})
} else {
this.fieldModel = deepClone(fileList)
}
this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
},
handleFileUpload(res, file, fileList) { handleFileUpload(res, file, fileList) {
if (file.status === 'success') { if (file.status === 'success') {
//this.fileList.push(file) /* this.fileList!! */ let customResult = null
this.updateUploadFieldModelAndEmitDataChange(fileList)
this.fileList = deepClone(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit
if (!!this.field.options.onUploadSuccess) { if (!!this.field.options.onUploadSuccess) {
let mountFunc = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess) let mountFunc = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess)
mountFunc.call(this, res, file, fileList) customResult = mountFunc.call(this, res, file, fileList)
} }
this.updateFieldModelAndEmitDataChangeForUpload(fileList, customResult, res)
this.fileList = deepClone(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit
} }
}, },
handleFileRemove(file, fileList) { // handleFileRemove(file, fileList) {
this.fileList = deepClone(fileList) //this.fileList = fileList // this.fileList = deepClone(fileList) //this.fileList = fileList
this.updateUploadFieldModelAndEmitDataChange(fileList) // this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit // this.uploadBtnHidden = fileList.length >= this.field.options.limit
//
// if (!!this.field.options.onFileRemove) {
// let customFn = new Function('file', 'fileList', this.field.options.onFileRemove)
// customFn.call(this, file, fileList)
// }
// },
if (!!this.field.options.onFileRemove) { updateFieldModelAndEmitDataChangeForRemove(deletedFileIdx, fileList) {
let customFn = new Function('file', 'fileList', this.field.options.onFileRemove) let oldValue = deepClone(this.fieldModel)
customFn.call(this, file, fileList) this.fieldModel.splice(deletedFileIdx, 1)
} this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
}, },
removeUploadFile(fileName) { removeUploadFile(fileName) {
@ -213,7 +234,7 @@
if (foundIdx >= 0) { if (foundIdx >= 0) {
this.fileList.splice(foundIdx, 1) this.fileList.splice(foundIdx, 1)
this.updateUploadFieldModelAndEmitDataChange(this.fileList) this.updateFieldModelAndEmitDataChangeForRemove(foundIdx, this.fileList)
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
if (!!this.field.options.onFileRemove) { if (!!this.field.options.onFileRemove) {
@ -223,7 +244,7 @@
} }
}, },
handelUploadError(err, file, fileList) { handleUploadError(err, file, fileList) {
if (!!this.field.options.onUploadError) { if (!!this.field.options.onUploadError) {
let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError) let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
customFn.call(this, err, file, fileList) customFn.call(this, err, file, fileList)

View File

@ -10,9 +10,9 @@
<template> <template>
<div class="field-wrapper" :class="{'design-time-bottom-margin': !!this.designer}"> <div class="field-wrapper" :class="{'design-time-bottom-margin': !!this.designer}">
<el-form-item v-if="!!field.formItemFlag" :label="label" :label-width="labelWidth + 'px'" <el-form-item v-if="!!field.formItemFlag && (!field.options.hidden || (designState === true))"
:label="label" :label-width="labelWidth + 'px'"
:title="field.options.labelTooltip" :title="field.options.labelTooltip"
v-show="!field.options.hidden || (designState === true)"
:rules="rules" :prop="getPropName()" :rules="rules" :prop="getPropName()"
:class="[selected ? 'selected' : '', labelAlign, customClass, field.options.required ? 'required' : '']" :class="[selected ? 'selected' : '', labelAlign, customClass, field.options.required ? 'required' : '']"
@click.native.stop="selectField(field)"> @click.native.stop="selectField(field)">

View File

@ -10,11 +10,18 @@
list-type="picture-card" :class="{'hideUploadDiv': uploadBtnHidden}" list-type="picture-card" :class="{'hideUploadDiv': uploadBtnHidden}"
:limit="field.options.limit" :on-exceed="handlePictureExceed" :limit="field.options.limit" :on-exceed="handlePictureExceed"
:before-upload="beforePictureUpload" :before-upload="beforePictureUpload"
:on-success="handlePictureUpload" :on-error="handelUploadError" :on-remove="handlePictureRemove"> :on-success="handlePictureUpload" :on-error="handleUploadError" :on-remove="handlePictureRemove">
<div slot="tip" class="el-upload__tip" <div slot="tip" class="el-upload__tip"
v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div> v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
<i class="el-icon-plus avatar-uploader-icon"></i> <i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload> </el-upload>
<el-dialog title="" v-if="showPreviewDialogFlag" :visible.sync="showPreviewDialogFlag"
v-dialog-drag append-to-body width="60%"
:show-close="true" custom-class="drag-dialog small-padding-dialog"
:close-on-click-modal="true" :close-on-press-escape="true" :destroy-on-close="true">
<img :src="previewUrl" width="100%" alt="" />
</el-dialog>
</form-item-wrapper> </form-item-wrapper>
</template> </template>
@ -62,7 +69,7 @@
data() { data() {
return { return {
oldFieldValue: null, //fieldchange oldFieldValue: null, //fieldchange
fieldModel: null, fieldModel: [],
rules: [], rules: [],
uploadHeaders: {}, uploadHeaders: {},
@ -76,6 +83,8 @@
fileList: [], // fileList: [], //
uploadBtnHidden: false, uploadBtnHidden: false,
previewUrl: '',
showPreviewDialogFlag: false,
} }
}, },
computed: { computed: {
@ -106,17 +115,10 @@
methods: { methods: {
handlePictureExceed() { handlePictureExceed() {
let uploadLimit = this.field.options.limit /* 此行不能注释下一行ES6模板字符串需要用到 */ let uploadLimit = this.field.options.limit
this.$message.warning( this.i18nt('render.hint.uploadExceed').replace('${uploadLimit}', uploadLimit) ) this.$message.warning( this.i18nt('render.hint.uploadExceed').replace('${uploadLimit}', uploadLimit) )
}, },
updateUploadFieldModelAndEmitDataChange(fileList) {
let oldValue = deepClone(this.fieldModel)
this.fieldModel = deepClone(fileList)
this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
},
beforePictureUpload(file) { beforePictureUpload(file) {
let fileTypeCheckResult = false let fileTypeCheckResult = false
if (!!this.field.options && !!this.field.options.fileTypes) { if (!!this.field.options && !!this.field.options.fileTypes) {
@ -161,23 +163,59 @@
return true return true
}, },
updateFieldModelAndEmitDataChangeForUpload(fileList, customResult, defaultResult) {
let oldValue = deepClone(this.fieldModel)
if (!!customResult && !!customResult.name && !!customResult.url) {
this.fieldModel.push({
name: customResult.name,
url: customResult.url
})
} else if (!!defaultResult && !!defaultResult.name && !!defaultResult.url) {
this.fieldModel.push({
name: defaultResult.name,
url: defaultResult.url
})
} else {
this.fieldModel = deepClone(fileList)
}
this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
},
handlePictureUpload(res, file, fileList) { handlePictureUpload(res, file, fileList) {
if (file.status === 'success') { if (file.status === 'success') {
//this.fileList.push(file) /* this.fileList!! */ let customResult = null
this.updateUploadFieldModelAndEmitDataChange(fileList)
this.fileList = deepClone(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit
if (!!this.field.options.onUploadSuccess) { if (!!this.field.options.onUploadSuccess) {
let customFn = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess) let customFn = new Function('result', 'file', 'fileList', this.field.options.onUploadSuccess)
customFn.call(this, res, file, fileList) customResult = customFn.call(this, res, file, fileList)
} }
this.updateFieldModelAndEmitDataChangeForUpload(fileList, customResult, res)
this.fileList = deepClone(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit
} }
}, },
updateFieldModelAndEmitDataChangeForRemove(file, fileList) {
let oldValue = deepClone(this.fieldModel)
let foundFileIdx = -1
this.fileList.map((fi, idx) => {
if ((fi.name === file.name) && ((fi.url === file.url) || (!!fi.uid && fi.uid === file.uid))) { /* 这个判断有问题?? */
foundFileIdx = idx
}
})
if (foundFileIdx > -1) {
this.fieldModel.splice(foundFileIdx, 1)
}
this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue)
},
handlePictureRemove(file, fileList) { handlePictureRemove(file, fileList) {
this.updateFieldModelAndEmitDataChangeForRemove(file, fileList)
this.fileList = deepClone(fileList) //this.fileList = fileList this.fileList = deepClone(fileList) //this.fileList = fileList
this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit this.uploadBtnHidden = fileList.length >= this.field.options.limit
if (!!this.field.options.onFileRemove) { if (!!this.field.options.onFileRemove) {
@ -186,7 +224,7 @@
} }
}, },
handelUploadError(err, file, fileList) { handleUploadError(err, file, fileList) {
if (!!this.field.options.onUploadError) { if (!!this.field.options.onUploadError) {
let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError) let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
customFn.call(this, err, file, fileList) customFn.call(this, err, file, fileList)

View File

@ -1,6 +1,6 @@
<template> <template>
<el-form-item :label="i18nt('designer.setting.defaultValue')"> <el-form-item v-if="!hasConfig('optionItems')" :label="i18nt('designer.setting.defaultValue')">
<el-input v-if="!hasConfig('optionItems')" type="text" v-model="optionModel.defaultValue" <el-input type="text" v-model="optionModel.defaultValue"
@change="emitDefaultValueChange"></el-input> @change="emitDefaultValueChange"></el-input>
</el-form-item> </el-form-item>
</template> </template>

View File

@ -269,7 +269,7 @@
this.deleteFromRowIdData(formRowIndex) this.deleteFromRowIdData(formRowIndex)
this.deleteFromFieldSchemaData(formRowIndex) this.deleteFromFieldSchemaData(formRowIndex)
this.handelSubFormRowDelete(oldSubFormData, deletedDataRow) this.handleSubFormRowDelete(oldSubFormData, deletedDataRow)
this.handleSubFormRowChange(oldSubFormData) this.handleSubFormRowChange(oldSubFormData)
}).catch(() => { }).catch(() => {
// //
@ -297,7 +297,7 @@
} }
}, },
handelSubFormRowDelete(subFormData, deletedDataRow) { handleSubFormRowDelete(subFormData, deletedDataRow) {
if (!!this.widget.options.onSubFormRowDelete) { if (!!this.widget.options.onSubFormRowDelete) {
let customFunc = new Function('subFormData', 'deletedDataRow', this.widget.options.onSubFormRowDelete) let customFunc = new Function('subFormData', 'deletedDataRow', this.widget.options.onSubFormRowDelete)
customFunc.call(this, subFormData, deletedDataRow) customFunc.call(this, subFormData, deletedDataRow)

View File

@ -5,7 +5,7 @@
<el-alert ref="fieldEditor" :title="field.options.title" :type="field.options.type" <el-alert ref="fieldEditor" :title="field.options.title" :type="field.options.type"
:description="field.options.description" :closable="field.options.closable" :description="field.options.description" :closable="field.options.closable"
:center="field.options.center" :close-text="field.options.closeText" :center="field.options.center" :close-text="field.options.closeText"
:show-icon="field.options.showIcon" :effect="field.options.effect" @close="handelCloseCustomEvent"></el-alert> :show-icon="field.options.showIcon" :effect="field.options.effect" @close="handleCloseCustomEvent"></el-alert>
</static-content-wrapper> </static-content-wrapper>
</template> </template>
@ -56,7 +56,7 @@
this.unregisterFromRefList() this.unregisterFromRefList()
}, },
methods: { methods: {
handelCloseCustomEvent() { handleCloseCustomEvent() {
if (!!this.field.options.onClose) { if (!!this.field.options.onClose) {
let changeFn = new Function(this.field.options.onClose) let changeFn = new Function(this.field.options.onClose)
changeFn.call(this) changeFn.call(this)