<template>
  <div
    style="border: 1px solid #ccc"
    element-loading-text="正在上传文件"
    v-loading="state.loading"
  >
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="state.editor"
      :defaultConfig="state.toolbarConfig"
      :mode="state.mode"
      ref="toolbar"
    />
    <Editor
      :style="{ height: state.height, minHeight: state.minheight }"
      v-model="state.html"
      id="wangEdit"
      :defaultConfig="state.editorConfig"
      :mode="state.mode"
      ref="editor"
      @onCreated="onCreated"
      @on-change="handleChange"
      @custom-paste="customPaste"
    />
  </div>
</template>
<script setup>
import { Boot } from "@wangeditor/editor";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import attachmentModule from "@wangeditor/plugin-upload-attachment";
import { createEditor } from "@wangeditor/editor";
import { DomEditor } from "@wangeditor/editor";
import { ElMessage, ElMessageBox } from "element-plus";
import { ossdit } from "./api";
import { reactive, ref, onMounted, watch, nextTick } from "vue";
// Boot.registerModule(attachmentModule);
if (Boot.plugins.length < 13) {
  //判断如果已经插入进去，不在二次插入
  Boot.registerModule(attachmentModule);
}
const props = defineProps({
  minheight: String,
  height: String,
  modelValue: String,
  url: String,
  headers: Object,
  querybefore: Object,
  fileSize: Number,
  filekey: String,
  urlkey: String,
  namekey: String,
  uploadFn: Function,
  placeholder: String,
});
const state = reactive({
  minheight: props.minheight ?? "350px",
  height: props.height ?? "",
  filekey: props.filekey ?? "file",
  querybefore: props.querybefore ?? {},
  urlkey: props.urlkey ?? "url",
  namekey: props.namekey ?? "name",
  fileSize: props.fileSize ?? 20,
  loading: false,
  editor: null,
  status: true,
  baseurl: import.meta.env.VITE_APP_BASE_API,
  html: props.modelValue ?? "",
  // 工具栏配置
  toolbarConfig: {
    //自定义配置上传附件功能
    insertKeys: {
      index: 22, // 自定义插入的位置
      keys: ["uploadAttachment"], // “上传附件”菜单
    },
    excludeKeys: ["code", "codeBlock"],
  },
  editorConfig: {
    placeholder: props.placeholder ?? "请输入内容...",
    hoverbarKeys: {
      attachment: {
        menuKeys: ["downloadAttachment"], // “下载附件”菜单
      },
      image: {
        menuKeys: [],
      },
    },
    MENU_CONF: {
      // 上传图片
      uploadImage: {
        allowedFileTypes: ["image/png,image/jpeg,image/jpg"],
        // 上传进度的回调函数
        onProgress(progress) {},
        // 单个文件上传成功之后
        onSuccess(file, res) {},
        // 自定义插入图片
        customUpload(file, insertFn) {
          uploadfn(file, insertFn, 1);
        },
        onError(file, err, res) {},
      },
      // 上传视频
      uploadVideo: {
        // 上传进度的回调函数
        onProgress(progress) {},
        // 单个文件上传成功之后
        onSuccess(file, res) {},
        // 自定义插入视频
        customUpload(file, insertFn) {
          uploadfn(file, insertFn, 2);
        },
      },
      // 上传附件
      uploadAttachment: {
        allowedFileTypes: [
          ".pdf,.xlsx,.doc,.xls,.docx,.zip,.ppt,.pptx,.txt,.mp3",
        ],
        // 上传进度的回调函数
        onProgress(progress) {},
        // 单个文件上传成功之后
        onSuccess(file, res) {},
        // 自定义插入附件
        customUpload(file, insertFn) {
          uploadfn(file, insertFn, 3);
        },
        onError(file, err, res) {},
      },
    },
  },
  mode: "default",
});
function uploadfn(file, insertFn, i) {
  if (props.uploadFn) {
    state.loading = true;
    let fn = props.uploadFn;
    fn(file, insertFn, i, (res) => {
      state.loading = false;
    });
    return;
  }
  let fileObj = file;
  let isLt = fileObj.size / 1024 / 1024 < state.fileSize; // 判断是否小于5M
  if (!isLt) {
    return ElMessage.warning(
      `上传文件大小不能超过 ${state.fileSize} MB,请重新上传！`
    );
  }
  state.loading = true;
  handleBeforeUpload(file).then((fil) => {
    const formData = new FormData();
    formData.append(state.filekey, file);
    for (const key in state.querybefore) {
      formData.append(key, state.querybefore[key]);
    }
    ossdit(props.url, formData, props.headers).then((res) => {
      if (res.code == 200) {
        let data = res.data ? res.data : res;
        if (data[state.urlkey].indexOf(state.baseurl) == -1) {
          data[state.urlkey] = state.baseurl + data[state.urlkey];
        }
        if (i == 3) {
          insertFn("附件：" + data[state.namekey], data[state.urlkey]);
        } else {
          insertFn(data[state.urlkey], data[state.namekey]);
        }
        state.loading = false;
      }
    });
  });
}
const emit = defineEmits();
function handleChange(editor) {}
function onCreated(editor) {
  state.editor = Object.seal(editor); // 一定要用 Object.seal() ，否则会报错
}
function customPaste(editor, event, callback) {
  console.log("ClipboardEvent 粘贴事件对象", event);
  callback(true); // 返回 true ，继续默认的粘贴行为
}
import { compressAccurately } from "image-conversion";

function handleBeforeUpload(file) {
  return new Promise(async (resolve, reject) => {
    if (
      file.type == "image/jpeg" ||
      file.type == "image/jpg" ||
      file.type == "image/png"
    ) {
      // 注意这里需要用Promise函数来阻止图片没有压缩好,就直接将文件上传
      const isJPG = file.type === "image/jpeg";
      const isPng = file.type === "image/png";
      const isjpg = file.type === "image/jpg";
      const imgType = file.type;
      const imgName = file.name;
      // 每个限制返回错误信息   都需要用到reject()
      if (!isJPG && !isPng && !isjpg) {
        ElMessage.warning("上传图片只能是 JPG、PNG、jpeg 格式!");
        return reject(false); //注意这里需要用reject来返回错误的信息,防止图片自动上传
      }
      let compress = 5 * 1024; // 假设图片限制不能大于2M
      let sizeOver = file.size / 1024 > compress; //文件大小 是否大于指定大小
      if (sizeOver && compress) {
        //大于2M进行压缩
        const res = await compressAccurately(file, {
          size: compress, //需要压缩的大小
          accuracy: 0.9, //精度 0.8-0.99之间 默认值0.95
          type: "image/jpeg",
          width: 105,
          height: 105,
          orientation: 1,
          scale: 0.5,
        });
        file = res; //把得到的新的图片文件赋值给原文件,然后进行上传   得到的是bold对象
        file = new window.File([file], imgName, {
          type: imgType,
        }); //将bold对象转换为file文件
      }
      resolve(file); // 通过resolve将Promise函数返回成功回调,进行后面操作
    } else {
      resolve(file);
    }
  });
}
watch(
  () => state.html,
  (val) => {
    emit("update:modelValue", val);
  },
  { deep: true, immediate: true }
);
onMounted(() => {});
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss" scoped>
.w-e-modal button {
  height: auto;
}
</style>

