mirror of
				https://github.com/vform666/variant-form3-vite.git
				synced 2025-11-04 10:31:47 +08:00 
			
		
		
		
	2022.07.20更新:
1. 优化图片、文件上传组件交互逻辑; 2. 图片组件增加预览功能。
This commit is contained in:
		@@ -38,7 +38,7 @@ export function createDesigner(vueInstance) {
 | 
			
		||||
      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/vform3`,
 | 
			
		||||
          "color:#409EFF;font-size: 22px;font-weight:bolder",
 | 
			
		||||
          "color:#999;font-size: 12px",
 | 
			
		||||
          "color:#333"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
               :multiple="field.options.multipleSelect" :file-list="fileList"
 | 
			
		||||
               :show-file-list="field.options.showFileList" :class="{'hideUploadDiv': uploadBtnHidden}"
 | 
			
		||||
               :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">
 | 
			
		||||
      <template #tip>
 | 
			
		||||
        <div class="el-upload__tip"
 | 
			
		||||
             v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
 | 
			
		||||
@@ -21,12 +21,12 @@
 | 
			
		||||
      <template #file="{ file }">
 | 
			
		||||
        <div class="upload-file-list">
 | 
			
		||||
          <span class="upload-file-name" :title="file.name">{{file.name}}</span>
 | 
			
		||||
          <a :href="file.url" download="">
 | 
			
		||||
          <a :href="file.url" download="" target="_blank">
 | 
			
		||||
            <span class="el-icon-download file-action" :title="i18nt('render.hint.downloadFile')">
 | 
			
		||||
              <svg-icon icon-class="el-download" />
 | 
			
		||||
            </span></a>
 | 
			
		||||
          <span class="file-action" :title="i18nt('render.hint.removeFile')" v-if="!field.options.disabled"
 | 
			
		||||
            @click="removeUploadFile(file.name)"><svg-icon icon-class="el-delete" /></span>
 | 
			
		||||
            @click="removeUploadFile(file.name, file.url, file.uid)"><svg-icon icon-class="el-delete" /></span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-upload>
 | 
			
		||||
@@ -80,7 +80,7 @@
 | 
			
		||||
    data() {
 | 
			
		||||
      return {
 | 
			
		||||
        oldFieldValue: null, //field组件change之前的值
 | 
			
		||||
        fieldModel: null,
 | 
			
		||||
        fieldModel: [],
 | 
			
		||||
        rules: [],
 | 
			
		||||
 | 
			
		||||
        uploadHeaders: {},
 | 
			
		||||
@@ -127,17 +127,10 @@
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
      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) )
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      updateUploadFieldModelAndEmitDataChange(fileList) {
 | 
			
		||||
        let oldValue = deepClone(this.fieldModel)
 | 
			
		||||
        this.fieldModel = deepClone(fileList)
 | 
			
		||||
        this.syncUpdateFormModel(this.fieldModel)
 | 
			
		||||
        this.emitFieldDataChange(this.fieldModel, oldValue)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      beforeFileUpload(file) {
 | 
			
		||||
        let fileTypeCheckResult = false
 | 
			
		||||
        let extFileName = file.name.substring(file.name.lastIndexOf('.') + 1)
 | 
			
		||||
@@ -183,36 +176,63 @@
 | 
			
		||||
        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) {
 | 
			
		||||
        if (file.status === 'success') {
 | 
			
		||||
          //this.fileList.push(file)  /* 上传过程中,this.fileList是只读的,不能修改赋值!! */
 | 
			
		||||
          this.updateUploadFieldModelAndEmitDataChange(fileList)
 | 
			
		||||
          this.fileList = deepClone(fileList)
 | 
			
		||||
          this.uploadBtnHidden = fileList.length >= this.field.options.limit
 | 
			
		||||
 | 
			
		||||
          let customResult = null
 | 
			
		||||
          if (!!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) {
 | 
			
		||||
        this.fileList = deepClone(fileList)  //this.fileList = fileList
 | 
			
		||||
        this.updateUploadFieldModelAndEmitDataChange(fileList)
 | 
			
		||||
        this.uploadBtnHidden = fileList.length >= this.field.options.limit
 | 
			
		||||
      // handleFileRemove(file, fileList) {
 | 
			
		||||
      //   this.fileList = deepClone(fileList)  //this.fileList = fileList
 | 
			
		||||
      //   this.updateUploadFieldModelAndEmitDataChange(fileList)
 | 
			
		||||
      //   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) {
 | 
			
		||||
          let customFn = new Function('file', 'fileList', this.field.options.onFileRemove)
 | 
			
		||||
          customFn.call(this, file, fileList)
 | 
			
		||||
        }
 | 
			
		||||
      updateFieldModelAndEmitDataChangeForRemove(deletedFileIdx, fileList) {
 | 
			
		||||
        let oldValue = deepClone(this.fieldModel)
 | 
			
		||||
        this.fieldModel.splice(deletedFileIdx, 1)
 | 
			
		||||
        this.syncUpdateFormModel(this.fieldModel)
 | 
			
		||||
        this.emitFieldDataChange(this.fieldModel, oldValue)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      removeUploadFile(fileName) {
 | 
			
		||||
      removeUploadFile(fileName, fileUrl, fileUid) {
 | 
			
		||||
        let foundIdx = -1
 | 
			
		||||
        let foundFile = null
 | 
			
		||||
        this.fileList.forEach((file,idx) => {
 | 
			
		||||
          if (file.name === fileName) {
 | 
			
		||||
        this.fileList.forEach((file, idx) => {
 | 
			
		||||
          if ((file.name === fileName) && ((file.url === fileUrl) || (!!fileUid && file.uid === fileUid))) {
 | 
			
		||||
            foundIdx = idx
 | 
			
		||||
            foundFile = file
 | 
			
		||||
          }
 | 
			
		||||
@@ -220,7 +240,7 @@
 | 
			
		||||
 | 
			
		||||
        if (foundIdx >= 0) {
 | 
			
		||||
          this.fileList.splice(foundIdx, 1)
 | 
			
		||||
          this.updateUploadFieldModelAndEmitDataChange(this.fileList)
 | 
			
		||||
          this.updateFieldModelAndEmitDataChangeForRemove(foundIdx, this.fileList)
 | 
			
		||||
          this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
 | 
			
		||||
 | 
			
		||||
          if (!!this.field.options.onFileRemove) {
 | 
			
		||||
@@ -230,7 +250,7 @@
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      handelUploadError(err, file, fileList) {
 | 
			
		||||
      handleUploadError(err, file, fileList) {
 | 
			
		||||
        if (!!this.field.options.onUploadError) {
 | 
			
		||||
          let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
 | 
			
		||||
          customFn.call(this, err, file, fileList)
 | 
			
		||||
 
 | 
			
		||||
@@ -10,9 +10,9 @@
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <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"
 | 
			
		||||
                  v-show="!field.options.hidden || (designState === true)"
 | 
			
		||||
                  :rules="rules" :prop="getPropName()"
 | 
			
		||||
                  :class="[selected ? 'selected' : '', labelAlign, customClass, field.options.required ? 'required' : '']"
 | 
			
		||||
                  @click.stop="selectField(field)">
 | 
			
		||||
@@ -333,14 +333,17 @@
 | 
			
		||||
 | 
			
		||||
  :deep(.label-left-align) .el-form-item__label {
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    justify-content: flex-start !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  :deep(.label-center-align) .el-form-item__label {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    justify-content: center !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  :deep(.label-right-align) .el-form-item__label {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
    justify-content: flex-end !important;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,13 +10,23 @@
 | 
			
		||||
               list-type="picture-card" :class="{'hideUploadDiv': uploadBtnHidden}"
 | 
			
		||||
               :limit="field.options.limit" :on-exceed="handlePictureExceed"
 | 
			
		||||
               :before-upload="beforePictureUpload"
 | 
			
		||||
               :on-success="handlePictureUpload" :on-error="handelUploadError" :on-remove="handlePictureRemove">
 | 
			
		||||
               :on-success="handlePictureUpload" :on-error="handleUploadError"
 | 
			
		||||
               :before-remove="handleBeforeRemove" :on-remove="handlePictureRemove">
 | 
			
		||||
      <template #tip>
 | 
			
		||||
        <div class="el-upload__tip"
 | 
			
		||||
             v-if="!!field.options.uploadTip">{{field.options.uploadTip}}</div>
 | 
			
		||||
      </template>
 | 
			
		||||
      <div class="uploader-icon"><svg-icon icon-class="el-plus" /></div>
 | 
			
		||||
    </el-upload>
 | 
			
		||||
 | 
			
		||||
    <div v-if="showPreviewDialogFlag" v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']">
 | 
			
		||||
      <el-dialog title="" v-model="showPreviewDialogFlag"
 | 
			
		||||
                 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" style="width: 100%" alt="" />
 | 
			
		||||
      </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
  </form-item-wrapper>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -63,7 +73,7 @@
 | 
			
		||||
    data() {
 | 
			
		||||
      return {
 | 
			
		||||
        oldFieldValue: null, //field组件change之前的值
 | 
			
		||||
        fieldModel: null,
 | 
			
		||||
        fieldModel: [],
 | 
			
		||||
        rules: [],
 | 
			
		||||
 | 
			
		||||
        uploadHeaders: {},
 | 
			
		||||
@@ -75,8 +85,11 @@
 | 
			
		||||
          //authorization: '',  //又拍云上传签名
 | 
			
		||||
        },
 | 
			
		||||
        fileList: [],  //上传文件列表
 | 
			
		||||
        fileListBeforeRemove: [],  //删除前的文件列表
 | 
			
		||||
        uploadBtnHidden: false,
 | 
			
		||||
 | 
			
		||||
        previewUrl: '',
 | 
			
		||||
        showPreviewDialogFlag: false,
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
@@ -107,17 +120,10 @@
 | 
			
		||||
 | 
			
		||||
    methods: {
 | 
			
		||||
      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) )
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      updateUploadFieldModelAndEmitDataChange(fileList) {
 | 
			
		||||
        let oldValue = deepClone(this.fieldModel)
 | 
			
		||||
        this.fieldModel = deepClone(fileList)
 | 
			
		||||
        this.syncUpdateFormModel(this.fieldModel)
 | 
			
		||||
        this.emitFieldDataChange(this.fieldModel, oldValue)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      beforePictureUpload(file) {
 | 
			
		||||
        let fileTypeCheckResult = false
 | 
			
		||||
        if (!!this.field.options && !!this.field.options.fileTypes) {
 | 
			
		||||
@@ -162,23 +168,64 @@
 | 
			
		||||
        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) {
 | 
			
		||||
        if (file.status === 'success') {
 | 
			
		||||
          //this.fileList.push(file)  /* 上传过程中,this.fileList是只读的,不能修改赋值!! */
 | 
			
		||||
          this.updateUploadFieldModelAndEmitDataChange(fileList)
 | 
			
		||||
          this.fileList = deepClone(fileList)
 | 
			
		||||
          this.uploadBtnHidden = fileList.length >= this.field.options.limit
 | 
			
		||||
 | 
			
		||||
          let customResult = null
 | 
			
		||||
          if (!!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.fileListBeforeRemove.map((fi, idx) => {  /* 跟element-ui不同,element-plus删除文件时this.fileList数组对应元素已被删除!! */
 | 
			
		||||
          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)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      handleBeforeRemove(file, fileList) {
 | 
			
		||||
        /* 保留删除之前的文件列表!! */
 | 
			
		||||
        this.fileListBeforeRemove = deepClone(fileList)
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      handlePictureRemove(file, fileList) {
 | 
			
		||||
        this.updateFieldModelAndEmitDataChangeForRemove(file, fileList)
 | 
			
		||||
        this.fileList = deepClone(fileList)  //this.fileList = fileList
 | 
			
		||||
        this.updateUploadFieldModelAndEmitDataChange(fileList)
 | 
			
		||||
        this.uploadBtnHidden = fileList.length >= this.field.options.limit
 | 
			
		||||
 | 
			
		||||
        if (!!this.field.options.onFileRemove) {
 | 
			
		||||
@@ -187,7 +234,7 @@
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      handelUploadError(err, file, fileList) {
 | 
			
		||||
      handleUploadError(err, file, fileList) {
 | 
			
		||||
        if (!!this.field.options.onUploadError) {
 | 
			
		||||
          let customFn = new Function('error', 'file', 'fileList', this.field.options.onUploadError)
 | 
			
		||||
          customFn.call(this, err, file, fileList)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-form-item :label="i18nt('designer.setting.defaultValue')">
 | 
			
		||||
    <el-input v-if="!hasConfig('optionItems')" type="text" v-model="optionModel.defaultValue"
 | 
			
		||||
  <el-form-item v-if="!hasConfig('optionItems')" :label="i18nt('designer.setting.defaultValue')">
 | 
			
		||||
    <el-input type="text" v-model="optionModel.defaultValue"
 | 
			
		||||
              @change="emitDefaultValueChange"></el-input>
 | 
			
		||||
  </el-form-item>
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
@@ -269,7 +269,7 @@
 | 
			
		||||
          this.deleteFromRowIdData(formRowIndex)
 | 
			
		||||
          this.deleteFromFieldSchemaData(formRowIndex)
 | 
			
		||||
 | 
			
		||||
          this.handelSubFormRowDelete(oldSubFormData, deletedDataRow)
 | 
			
		||||
          this.handleSubFormRowDelete(oldSubFormData, deletedDataRow)
 | 
			
		||||
          this.handleSubFormRowChange(oldSubFormData)
 | 
			
		||||
        }).catch(() => {
 | 
			
		||||
          //
 | 
			
		||||
@@ -297,7 +297,7 @@
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      handelSubFormRowDelete(subFormData, deletedDataRow) {
 | 
			
		||||
      handleSubFormRowDelete(subFormData, deletedDataRow) {
 | 
			
		||||
        if (!!this.widget.options.onSubFormRowDelete) {
 | 
			
		||||
          let customFunc = new Function('subFormData', 'deletedDataRow', this.widget.options.onSubFormRowDelete)
 | 
			
		||||
          customFunc.call(this, subFormData, deletedDataRow)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user