关于vue-quill-editor富文本编辑器使用el-upload上传文件图片的问题(上传文件)

<template>
  <div>
    <quill-editor
      :key="key"
      ref="myEditor"
      v-model="content"
      class="editor"
      :options="editorOption"
      :disabled="disabled"
      @change="onEditorChange($event)"
    />
    <el-upload
      style="display: none"
      :class="className"
      :action="serverUrl"
      accept=".doc,.docx,.xls,.xlsx,.csv,.ppt,.pptx,.gif,.jpg,.jpeg,.png,.bmp,.zip,.rar,.war,.jar,.tar"
      name="file"
      :headers="headers"
      :show-file-list="false"
      :before-upload="beforeUpload"
      :on-success="upload"
    />
  </div>
</template>

<script>
  import 'quill/dist/quill.snow.css'
  import { tokenName, baseURL } from '@/config'
  import { quillEditor, Quill } from 'vue-quill-editor'
  import { container, ImageExtend, QuillWatch } from './ImageExtend'
  import ImageResize from 'quill-image-resize-module' // 控制图片的大小
  let timer
  let Link = Quill.import('formats/link')
  class MyLink extends Link {
    static create(value) {
      let node = undefined
      if (value && !value.href) {
        // 适应原本的Link Blot
        node = super.create(value)
      } else {
        // 自定义Link Blot
        node = super.create(value.href.link)
        // node.setAttribute('download', value.innerText);  // 左键点击即下载
        node.innerText = value.innerText
        node.download = value.innerText
      }
      return node
    }
    // static create(value) {
    //   let node = super.create(value)
    //   value = this.sanitize(value)
    //   if (!value.startsWith('http')) value = 'http://' + value
    //   node.setAttribute('href', value)
    //   return node
    // }
  }
  MyLink.blotName = 'link'
  MyLink.tagName = 'A'
  Quill.register('modules/imageResize', ImageResize)
  Quill.register('modules/ImageExtend', ImageExtend)
  Quill.register(MyLink)
  export default {
    name: 'QuillEditor',
    components: { quillEditor },
    props: {
      value: {
        type: String,
        default: '',
      },
      placeholder: {
        type: String,
        default: '请输入正文',
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      self: {
        type: Object,
        default: () => {
          return {}
        },
      },
    },
    data() {
      return {
        key: 1,
        content: this.value, // 富文本编辑器默认内容
        keepValue: '',
        className: 'uploadFile' + this.self.index,
        config: {
          headers: {
            'Blade-Auth': this.$baseToken(),
            'Content-Type': 'multipart/form-data',
            Authorization: 'Basic c3dvcmQ6c3dvcmRfc2VjcmV0',
          },
        },
        serverUrl: baseURL + '/blade-resource/oss/endpoint/put-file-attach',
        headers: {
          [tokenName]: this.$baseToken(),
          Authorization: 'Basic c3dvcmQ6c3dvcmRfc2VjcmV0',
        },
        editorOption: {
          theme: 'snow', // 主题
          placeholder: this.placeholder,
          className: 'uploadFile' + this.self.index,
          modules: {
            imageResize: {
              displayStyles: {
                backgroundColor: 'black',
                border: 'none',
                color: 'white',
              },
              modules: ['Resize', 'DisplaySize', 'Toolbar'],
            },
            ImageExtend: {
              name: 'file',
              action: baseURL + '/blade-resource/oss/endpoint/put-file-attach',
              headers: (xhr) => {
                xhr.setRequestHeader('Authorization', 'Basic c3dvcmQ6c3dvcmRfc2VjcmV0')
                xhr.setRequestHeader(tokenName, this.$baseToken())
                return xhr
              },
              response: (res) => res.data.link,
            },
            toolbar: {
              container: container,
              handlers: {
                image() {
                  QuillWatch.emit(this.quill.id)
                },
                upload(value) {
                  if (value) {
                    let className = '.' + this.quill.options.className + ' input'
                    document.querySelector(className).click()
                    // QuillWatch.emit(this.quill.id, 2)
                  }
                },
              },
            },
            clipboard: {
              matchers: [['img', this.handleCustomMatcher]], // 粘贴板,处理粘贴时候带图片
            },
          },
        },
      }
    },
    watch: {
      value(val) {
        if (this.keepValue !== val) this.content = val
      },
      placeholder(val) {
        this.editorOption.placeholder = val
        this.key++
        this.$nextTick(() => {
          let num = this.editorOption.placeholder.split('\n').length
          if (num > 3) {
            document.getElementsByClassName('ql-editor')[0].style.minHeight = 80 + num * 14 + 'px'
          }
        })
      },
    },
    methods: {
      onEditorChange({ html }) {
        clearTimeout(timer)
        timer = setTimeout(() => {
          html = html.replace(//g, '')
          this.keepValue = html
          this.$emit('input', html)
          this.$emit('getVal', html)
        }, 300)
      },
      handleCustomMatcher(node, Delta) {
        let ops = []
        ops = Delta.ops.filter((op) => op.insert.image.indexOf('base64') === -1)
        Delta.ops = ops
        return Delta
      }, // 文件上传
      upload(res, file) {
        // 获取富文本组件实例
        let quill = this.$refs.myEditor.quill
        if (res.code === 200) {
          let fileNameLength = file.name.length
          // 光标的位置
          let length = quill.getSelection().index
          // quill.insertEmbed(length, 'link', {href:res.data, innerText:file.name}, "api")
          quill.insertEmbed(length, 'link', { href: res.data, innerText: file.name })
          quill.setSelection(length + fileNameLength)
        } else {
          this.$message.error('插入失败')
        }
      },
      beforeUpload(file) {
        // 小于10
        if (file.size / 1024 / 1024 > 10) {
          this.$baseMessage('error', `上传文件大小超出限制`)
        }
        return
      },
    },
  }
</script>

<style lang="scss">
  .editor {
    line-height: 1.42;
  }
  .ql-editor {
    min-height: 150px;
  }
  .ql-toolbar.ql-snow,
  .ql-container.ql-snow {
    border: 1px solid #dcdfe6;
  }
  .ql-snow .ql-tooltip[data-mode='link']::before {
    content: '请输入完整链接:';
  }
  .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    padding-right: 0;
    content: '保存';
    border-right: 0;
  }

  .ql-snow .ql-picker.ql-size .ql-picker-label::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item::before {
    content: '14px';
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before {
    content: '10px';
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before {
    content: '18px';
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before {
    content: '32px';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item::before {
    content: '文本';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
    content: '标题1';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
    content: '标题2';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
    content: '标题3';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
    content: '标题4';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
    content: '标题5';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
    content: '标题6';
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item::before {
    content: '标准字体';
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
    content: '衬线字体';
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
    content: '等宽字体';
  }
  .quill-editor .ql-snow.ql-toolbar .ql-formats .ql-upload {
    background-image: url('./img/upload-2-line.svg') !important;
    background-size: 18px 18px;
    background-position: center center;
    background-repeat: no-repeat;
  }
</style>

你可能感兴趣的:(平常开发中的问题,vue.js,javascript,前端)