<template>
    <div ref="divRef" :style="{ height, minHeight }" />
</template>

<script setup lang="ts">
import { propTypes } from "@/utils/propTypes";
import { globalHeaders } from "@/utils/request";
import { AiEditor } from "aieditor";
import "aieditor/dist/style.css";
const divRef = ref();
let aiEditor = ref<AiEditor | null>(null);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(baseUrl + '/resource/oss/upload'); // 上
const headers = ref(globalHeaders());
const props = defineProps({
    /* 编辑器的内容 */
    modelValue: propTypes.string.def(''),
    /* 高度 */
    height: propTypes.number.def(400),
    /* 最小高度 */
    minHeight: propTypes.number.def(400),
    /* 只读 */
    readOnly: propTypes.bool.def(false),
    /* 上传文件大小限制(MB) */
    fileSize: propTypes.number.def(5),
    /* 类型（base64格式、url格式） */
    type: propTypes.string.def('url'),
    placeholder: propTypes.string,
});
const emit = defineEmits(['update:modelValue']);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const initEditor = () => {
     aiEditor.value = new AiEditor({
        element: divRef.value as Element,
        placeholder: props.placeholder || '请输入内容',
        draggable: true,
        content: props.modelValue,
        toolbarKeys: ["undo", "redo", "brush", "eraser",
            "|", "heading", "font-family", "font-size",
            "|", "bold", "italic", "underline", "strike", "link", "code", "subscript", "superscript", "hr", "todo", "emoji",
            "|", "highlight", "font-color",
            "|", "align", "line-height",
            "|", "bullet-list", "ordered-list", "indent-decrease", "indent-increase", "break",
            "|", "image", "video", "attachment", "quote", "code-block", "table",
            "|", "source-code", "printer", "fullscreen",
        ],
        image: {
            allowBase64: true,
            defaultSize: 350,
            // customMenuInvoke: (editor: AiEditor) => {
            // },
            uploadUrl: uploadFileUrl.value,
            uploadFormName: "file", //上传时的文件表单名称
            uploadHeaders: {
                ...headers.value
            },
            uploaderEvent: {
                onUploadBefore: (file, uploadUrl, headers) => {
                    //监听图片上传之前，此方法可以不用回任何内容，但若返回 false，则终止上传
                    return handleBeforeUpload(file);
                },
                onSuccess: (file, response) => {
                    //监听图片上传成功
                    //注意：
                    // 1、如果此方法返回 false，则图片不会被插入到编辑器
                    // 2、可以在这里返回一个新的 json 给编辑器
                    if (response.code == 200) {
                        proxy?.$modal.closeLoading();
                        // 根据图片宽高设置默认显示大小
                        return {
                            "errorCode": 0,
                            "data": {
                                src: response.data.url,
                                alt: file.name,
                                loading: true,
                                "align": "left",
                                "width": "400px",
                                "height": "auto",
                                'data-src': response.data.url
                            }
                        }
                    }
                },
                onFailed: (file, response) => {
                    //监听图片上传失败，或者返回的 json 信息不正确
                    console.log('onFailed', file, response);

                },
                onError: (file, error) => {
                    //监听图片上传错误，比如网络超时等
                },
            },
            bubbleMenuItems: ["AlignLeft", "AlignCenter", "AlignRight", "delete"]
        },
        video: {
            uploadHeaders: {
                ...headers.value
            },
            uploadUrl: uploadFileUrl.value,
            uploadFormName: "file", //上传时的文件表单名称
            uploaderEvent: {
                onUploadBefore: (file, uploadUrl, headers) => {
                    console.log(file);

                    //监听视频上传之前，此方法可以不用回任何内容，但若返回 false，则终止上传
                    return handleBeforeUpload(file);
                },
                onSuccess: (file, response) => {
                    //监听视频上传成功
                    //注意：
                    // 1、如果此方法返回 false，则视频不会被插入到编辑器
                    // 2、可以在这里返回一个新的 json 给编辑器
                    if (response.code == 200) {
                        proxy?.$modal.closeLoading();
                        return {
                            "errorCode": 0,
                            "data": {
                                src: response.data.url,
                                poster: "",
                                "width": "480px",
                                "height": "320px",
                                controls: true,
                                'data-src': response.data.url
                            }
                        }
                    }
                },
                onFailed: (file, response) => {
                    //监听视频上传失败，或者返回的 json 信息不正确
                    console.log('onFailed', file, response);

                },
                onError: (file, error) => {
                    //监听视频上传错误，比如网络超时等
                },
            },
        },
        onChange: (aiEditor) => {
            // 监听到用编辑器内容发生变化了，控制台打印编辑器的 html 内容...
            emit('update:modelValue', aiEditor.getHtml());
        }
    })
}
onMounted(() => {
    // 等待1s,确保modelValue有值
    setTimeout(() => {
        initEditor();
    }, 1000);
})

// 图片上传前拦截
const handleBeforeUpload = (file: any) => {
    const type = ['image/jpeg', 'image/jpg', 'image/png', 'image/svg'];
    const isJPG = type.includes(file.type);
    //检验文件格式
    if (!isJPG) {
        proxy?.$modal.msgError(`图片格式错误!`);
        return false;
    }
    // 校检文件大小
    if (props.fileSize) {
        const isLt = file.size / 1024 / 1024 < props.fileSize;
        if (!isLt) {
            proxy?.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
            return false;
        }
    }
    proxy?.$modal.loading('正在上传文件，请稍候...');
    return true;
};

onUnmounted(() => {
    aiEditor.value && aiEditor.value.destroy();
})
</script>

<style>
.aie-content p {
    margin: 0;
}
</style>
