<template>
  <div>
    <el-radio-group v-if="!readonly && radio"
                    class="type-radio"
                    v-model="editorType"
                    @change="typeChange">
      <el-radio label="0">富文本</el-radio>
      <el-radio label="1">markdown</el-radio>
    </el-radio-group>
    <div v-show="editorType == 0"
         class="quill"
         ref="quill"
         :class="classes">
      <div ref="editor"
           :style="styles"
           v-loading="loading"></div>

      <Upload :max-size="1000"
              :limit="100"
              @beforeUpload="beforeUpload"
              @onSuccess="editorUploadSuccess"
              style="display: none">
        <div slot="trigger">
          <el-button :id="'editorUpload' + index"
                     type="primary">点击上传</el-button>
        </div>
      </Upload>
    </div>
    <mavon-editor class="md"
                  v-model="mdVal"
                  v-show="editorType == 1"
                  ref="md"
                  :ishljs="true"
                  :subfield="false"
                  @change="mdChange"
                  @imgAdd="imgAdd" />
  </div>
</template>

<script>
import util from "@/libs/util";
import Setting from "@/setting";
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import toolbarOptions from "./options";
import { mavonEditor } from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import Upload from '@/components/upload';
import Oss from '@/components/upload/upload.js'

export default {
  name: "quill",
  components: {
    Upload,
    mavonEditor
  },
  props: {
    value: {
      type: String,
      default: ""
    },
    readonly: {
      type: Boolean,
      default: false
    },
    toTop: {
      type: Boolean,
      default: true
    },
    border: {
      type: Boolean,
      default: false
    },
    height: {
      type: Number
    },
    minHeight: {
      type: Number
    },
    /*
     * 原本的readOnly失效,对比其他项目，发现是quill版本不同导致，
     * 使用props传入elseRead = 'true'，手动隐藏工具栏
     */
    elseRead: {
      type: String, default: "false"
    },
    // 当前富文本的索引。一个页面引入多个富文本的时候会无法获取到对应的实例，所以通过在父级存储实例的方式来保存
    index: {
      type: Number,
      default: 0
    },
    // 是否需要编辑器切换
    radio: {
      type: Boolean,
      default: false
    },
    // 编辑器切换
    type: {
      type: String,
      default: '0'
    },
  },
  data () {
    const that = this
    return {
      headers: {
        token: util.local.get(Setting.tokenKey)
      },
      editorType: '0',
      mdVal: '',
      Quill: null,
      currentValue: "",
      options: {
        theme: "snow",
        bounds: document.body,
        debug: "warn",
        modules: {
          toolbar: {
            container: toolbarOptions,
            handlers: {
              "image": function (value) {
                if (value) {
                  // 调用iview图片上传
                  document.querySelector("#editorUpload" + that.index).click();
                } else {
                  this.Quill.format("image", false);
                }
              }
            }
          }
        },
        placeholder: "",
        readOnly: this.readonly
      },
      loading: false
    };
  },
  computed: {
    classes () {
      return [
        {
          "quill-no-border": !this.border
        }
      ];
    },
    styles () {
      let style = {};
      if (this.minHeight) {
        style.minHeight = `${this.minHeight}px`;
      }
      if (this.height) {
        style.height = `${this.height}px`;
      }
      return style;
    }

  },
  watch: {
    type: {
      handler (val) {
        this.editorType = val
      },
      immediate: true
    },
    value: {
      handler (val) {
        if (this.type == 0) {
          if (val !== this.currentValue) {
            this.currentValue = val;
            if (this.Quill) {
              this.Quill.pasteHTML(this.value);
            }
          }
        }
        if (!this.mdVal) this.mdVal = val
      },
      immediate: true
    }
  },
  created () {
  },
  mounted () {
    this.init();
    // 处理工具栏隐藏样式
    if (this.elseRead === "true") {
      let children = this.$refs.quill.children[0].style;
      children.padding = "0";
      children.overflow = "hidden";
      children.height = "0";
      children.borderTop = "0";
    }
  },
  beforeDestroy () {
    // 在组件销毁后销毁实例
    this.Quill = null;
  },
  methods: {
    // 富文本切换
    typeChange (val) {
      this.$emit('update:type', val)
      if (!this.mdVal) this.mdVal = this.value
    },

    init () {
      const editor = this.$refs.editor;
      // 初始化编辑器
      this.Quill = new Quill(editor, this.options);
      const ins = this.Quill
      // 默认值
      ins.pasteHTML(this.currentValue);
      if (this.toTop) {
        this.$nextTick(() => {
          window.scrollTo(0, 0)
        })
      }
      // 绑定事件
      ins.on('text-change', (delta, oldDelta, source) => {
        const html = this.$refs.editor.children[0].innerHTML;
        const text = ins.getText();
        const quill = this.Quill;
        // 更新内部的值
        this.currentValue = html;
        // 发出事件 v-model
        this.$emit('input', html);
        // 发出事件
        this.$emit('on-change', { html, text, quill });
      });
      // 将一些 quill 自带的事件传递出去
      ins.on('text-change', (delta, oldDelta, source) => {
        this.$emit('on-text-change', delta, oldDelta, source);
      });
      ins.on('selection-change', (range, oldRange, source) => {
        this.$emit('on-selection-change', range, oldRange, source);
      });
      ins.on('editor-change', (eventName, ...args) => {
        this.$emit('on-editor-change', eventName, ...args);
      });
      // 监听粘贴事件
      ins.root.addEventListener('paste', evt => {
        if (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length) {
          evt.preventDefault();
          // 检测是否粘贴的是图片
          [].forEach.call(evt.clipboardData.files, file => {
            if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
              return
            }
            // 把图片上传到oss，不然会直接把base64存到数据库
            Oss.upload(file).then(res => {
              var range = ins.getSelection()
              if (range) {
                //  在当前光标位置插入图片
                ins.insertEmbed(range.index, 'image', res.url)
                //  将光标移动到图片后面
                ins.setSelection(range.index + 1)
              }
            })
          });
        }
      }, false)
    },
    beforeUpload (file) {
      this.loading = true;
    },
    // quill图片上传
    editorUploadSuccess (file) {
      // 获取富文本组件实例
      let quill = this.Quill
      // 如果上传成功
      if (file.url) {
        // 获取光标所在位置
        let lengths;
        if (quill.getSelection() == null) {
          lengths = 1
        } else {
          lengths = quill.getSelection().index;
        }
        // 插入图片，res为服务器返回的图片链接地址
        quill.insertEmbed(lengths, 'image', file.url)
        // 调整光标到最后
        quill.setSelection(lengths + 1)
      } else {
        this.$message.success('图片插入失败')
      }
      this.loading = false
    },

    // 类型切换回调
    mdChange (val) {
      this.$emit('input', val)
    },
    // markdown图片上传
    imgAdd (pos, $file) {
      let $vm = this.$refs.md
      // 将图片上传到oss
      Oss.upload($file).then(res => {
        $vm.$img2Url(pos, res.url);
      })
    },
  }
};
</script>
<style lang="scss" scoped>
.type-radio {
    margin-bottom: 20px;
}
.quill-no-border {
    .ql-toolbar.ql-snow {
        border: none;
        border-bottom: 1px solid #e8eaec;
    }

    .ql-container.ql-snow {
        border: none;
    }
}

.else {
    .ql-toolbar.ql-snow {
        height: 0;
        overflow: hidden;
        padding: 0;
        border-top: 0;
    }
}
/deep/.ql-snow {
    position: relative;
    .ql-tooltip {
        position: absolute !important;
        top: 10px !important;
        left: 10px !important;
        transform: translateY(10px);
    }
}
.md {
    max-height: 300px;
}
/deep/.v-note-wrapper .v-note-panel {
    min-height: 200px;
}
</style>
