<template>
  <div ref="body">
    <el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
      :on-error="handleUploadError" :data="data" name="file" :show-file-list="false" :headers="headers"
      style="display: none" ref="upload" v-if="type == 'url'">
    </el-upload>
    <div class="editor" ref="editor" :style="styles" />

    <!-- 视频弹出框 -->
    <el-popover popper-class="ql-popover" width="398" ref="popover">
      <el-form>
        <el-form-item label="视频链接">
          <el-input v-model="videoUrl" placeholder="请输入视频链接">
            <template slot="append">
              <Upload @upload="upload" :size="500" />
            </template>
          </el-input>
        </el-form-item>
        <el-form-item style="margin-top: 15px;">
          <el-button @click="closeVideo">取消</el-button>
          <el-button type="primary" @click="handleUploadSuccess()" :disabled="videoUrl == ''">确定</el-button>
        </el-form-item>
      </el-form>
    </el-popover>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import Upload from '../Upload/index.vue';
import { getToken } from "@/utils/auth";
import { View } from "@/store/modules/editor";
Quill.register(View, true);

export default {
  components: { Upload },
  name: "Editor",
  props: {
    /* 编辑器的内容 */
    value: {
      type: String,
      default: "",
    },
    /* 高度 */
    height: {
      type: Number,
      default: null,
    },
    /* 最小高度 */
    minHeight: {
      type: Number,
      default: null,
    },
    /* 只读 */
    readOnly: {
      type: Boolean,
      default: false,
    },
    /* 类型（base64格式、url格式） */
    type: {
      type: String,
      default: "url",
    }
  },
  data() {
    return {
      // 遮罩层
      fullScreenLoading: false,
      loading: false,
      uploadUrl: process.env.VUE_APP_BASE_API + "/system/file/picture/upload", // 上传的图片服务器地址
      headers: {
        Authorization: "Bearer " + getToken()
      },
      data: {},
      audioData: {},
      Quill: null,
      currentValue: "",
      options: {
        theme: "snow",
        bounds: document.body,
        debug: "warn",
        modules: {
          // 工具栏配置
          toolbar: {
            container: [
              ["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线
              ["blockquote", "code-block"],                    // 引用  代码块
              [{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表
              // [{ indent: "-1" }, { indent: "+1" }],         // 缩进
              [{ size: ["small", false, "large", "huge"] }],   // 字体大小
              [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题
              [{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色
              [{ align: [] }],                                 // 对齐方式
              ["clean"],                                       // 清除文本格式
              ["link", "image", "view"], // "audio"            // 链接、图片、视频
            ]
          }
        },
        // 自定义按钮
        customButton: function (className, icon) {
          const btn = document.querySelector(className)
          btn.classList.add(icon)
          btn.style.cssText = 'font-size: 16px; font-weight: bold'
        },
        placeholder: "请输入内容",
        readOnly: this.readOnly,
      },
      // 视频表单
      videoUrl: ''
    };
  },
  computed: {
    styles() {
      let style = {};
      if (this.minHeight) {
        style.minHeight = `${this.minHeight}px`;
      }
      if (this.height) {
        style.height = `${this.height}px`;
      }
      return style;
    },
  },
  watch: {
    value: {
      handler(val) {
        if (val !== this.currentValue) {
          this.currentValue = val === null ? "" : val;
          if (this.Quill) {
            this.Quill.pasteHTML(this.currentValue);
          }
        }
      },
      immediate: true,
    }
  },
  mounted() {
    this.init();
  },
  beforeDestroy() {
    this.Quill = null;
  },
  methods: {
    init() {
      const editor = this.$refs.editor;
      this.Quill = new Quill(editor, this.options);
      // 自定义按钮
      this.customEditor('image')
      this.customEditor('view')
      this.options.customButton('.ql-view', 'el-icon-video-camera')
      this.Quill.pasteHTML(this.currentValue);
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        const html = this.$refs.editor.children[0].innerHTML;
        const text = this.Quill.getText();
        const quill = this.Quill;
        this.currentValue = html;
        this.$emit("input", html);
        this.$emit("on-change", { html, text, quill });
      });
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        this.$emit("on-text-change", delta, oldDelta, source);
      });
      this.Quill.on("selection-change", (range, oldRange, source) => {
        this.$emit("on-selection-change", range, oldRange, source);
      });
      this.Quill.on("editor-change", (eventName, ...args) => {
        this.$emit("on-editor-change", eventName, ...args);
      });
    },

    // 自定义按钮
    customEditor(key) {
      let toolbar = this.Quill.getModule("toolbar");
      toolbar.addHandler(key, (value) => {
        if (value) {
          if (key === 'image') { this.$refs.upload.$children[0].$refs.input.click() }
          if (key === 'view') { this.$refs.popover.showPopper = true }
        } else {
          this.quill.format(key, false);
        }
      });
    },

    // 上传视频
    upload(e) {
      this.videoUrl = e.file
    },

    // 上传图片之前
    handleBeforeUpload(file) {
      this.data.multipartFile = file
    },

    // 图片上传失败
    handleUploadError() {
      this.$message.error("图片插入失败");
    },

    // 成功添加
    handleUploadSuccess(res) {
      // 获取富文本组件实例
      let quill = this.Quill;
      // 如果上传成功
      if (quill.getSelection()) {
        let length = quill.getSelection().index
        let key = res ? "image" : "view"
        let form = res ? res.data : this.videoUrl
        quill.insertEmbed(length, key, form)
        quill.setSelection(length + 1)
        this.closeVideo()
      } else {
        this.$message.error("请先聚焦于富文本输入框，再插入视频")
      }
    },

    // 关闭视频弹框
    closeVideo() {
      this.$refs.popover.showPopper = false
      this.videoUrl = ''
    },

  },
};
</script>

<style lang="scss">
.editor,
.ql-toolbar {
  white-space: pre-wrap !important;
  line-height: normal !important;
}

.quill-img {
  display: none;
}

.ql-snow .ql-tooltip[data-mode='link']::before {
  content: '请输入链接地址:';
}

.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: '保存';
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode='video']::before {
  content: '请输入视频地址:';
}

.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: '等宽字体';
}

.ql-popover {
  top: 66px;
  left: 300px;

  .el-input-group__append,
  .el-input-group__prepend {
    color: #FFFFFF;
    background-color: #1890ff;
    border-color: #1890ff;
  }
}
</style>
