<template>
	<div class="editor-container">
		<Toolbar :editor="editorRef" :mode="mode" :defaultConfig="toolConfig" />
		<Editor
			:mode="mode"
			:defaultConfig="state.editorConfig"
			:style="{ height }"
			v-model="state.editorVal"
			@onCreated="handleCreated"
			@onChange="handleChange"
			@onBlur="handleBlur"
			:defaultContent="defaultContent"
		/>
	</div>
</template>
<script lang="ts" setup name="wngEditor">
import '@wangeditor-next/editor/dist/css/style.css' // 引入 css
import { onBeforeUnmount, reactive, shallowRef, watch, nextTick, ref } from 'vue';
import { IDomEditor } from '@wangeditor-next/editor'
import { Editor, Toolbar } from '@wangeditor-next/editor-for-vue'
import { Cookie } from '@/utils/storage';
import { uploadFile } from '@/api/public/upload';
import { ElMessage } from 'element-plus';
//  全局配置
// 定义父组件传过来的值
const props = defineProps({
	// 是否禁用
	disable: {
		type: Boolean,
		default: () => false,
	},
	// 内容框默认 placeholder
	placeholder: {
		type: String,
		default: () => '请填写内容...',
	},
	// https://www.wangeditor.com/v5/getting-started.html#mode-%E6%A8%A1%E5%BC%8F
	// 模式，可选 <default|simple>，默认 default
	mode: {
		type: String,
		default: () => 'default',
	},
	// 高度
	height: {
		type: String,
		default: () => '310px',
	},
	// 双向绑定，用于获取 editor.getHtml()
	getHtml: String,
	// 双向绑定，用于获取 editor.getText()
	getText: String,
	defaultContent: {
		type: Array,
		default: () => [],
	},
});
// 定义子组件向父组件传值/事件
const emit = defineEmits(['update:getHtml', 'update:getText', 'blur']);

const editorRef = shallowRef<RefType>();
const state = reactive<any>({
	editorConfig: {
		placeholder: props.placeholder,
		MENU_CONF: {},
		hoverbarKeys:{

		},
	},
	editorVal: props.getHtml,

});
const toolConfig = ref({
	excludeKeys: [
		// 排除掉视频上传
		'group-video',
	],
});
type InsertFnType = (url: string, alt: string, href: string) => void;
// 图片上传
state.editorConfig.MENU_CONF['uploadImage'] = {
	// 自定义上传
	async customUpload(file: File, insertFn: InsertFnType) {
		// 限制文件不能大于100M
		if (file.size > 10 * 1024 * 1024) {
			ElMessage.error('上传图片不能大于10M');
			return;
		}
		const formData = new FormData();
		formData.append('fileData', file);
		uploadFile(formData)
			.then((res) => {
				insertFn(import.meta.env.VITE_API_UPLOAD_URL + res.result.path, '加载失败', '');
			})
			.catch((err) => {
				ElMessage.error(err);
			});
	},
};

// //上传视频
state.editorConfig.MENU_CONF['uploadVideo'] = {
	server: import.meta.env.VITE_API_UPLOAD_URL,
	// form-data fieldName ，默认值 'wangeditor-uploaded-video'
	fieldName: 'file',

	// 单个文件的最大体积限制，默认为 10M
	maxFileSize: 5 * 1024 * 1024, // 5M

	// 最多可上传几个文件，默认为 5
	maxNumberOfFiles: 3,

	// 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
	allowedFileTypes: ['video/*'],

	// 将 meta 拼接到 url 参数中，默认 false
	metaWithUrl: false,

	// 自定义增加 http  header
	headers: {
		Authorization: 'Bearer ' + Cookie.get('token'),
		userid: '',
	},

	// 跨域是否传递 cookie ，默认为 false
	withCredentials: true,
	// 超时时间，默认为 30 秒
	timeout: 15 * 1000, // 15 秒
	// 自定义插入视频
	customInsert(res: any, insertFn: any) {
		// 从 res 中找到 url alt href ，然后插图图片
		insertFn(res.data.url);
	},
};
// 行高
/*state.editorConfig.MENU_CONF['lineHeight'] = {
	lineHeightList: ['1', '1.5', '2', '2.5'],
};*/
// 字体大小
state.editorConfig.MENU_CONF['fontSize'] = {
	fontSizeList: [
		// 元素支持两种形式
		//   1. 字符串；
		//   2. { name: 'xxx', value: 'xxx' }

		'12px',
		'14px',
		'16px',
		'20px',
		'24px',
		'32px',
		'40px',
		'48px',
	],
};
// 默认字体
/*const defaultContent =ref([
	{
		type: "paragraph",
		children: [{ text: "" }],
		fontSize: "20px",
		fontFamily: "仿宋",
	},
],)*/
// 编辑器回调函数
const handleCreated = (editor: IDomEditor) => {
	editorRef.value = editor;
};
// 编辑器内容改变时
const handleChange = (editor: IDomEditor) => {
	emit('update:getHtml', editor.getHtml());
	emit('update:getText', editor.getText());
};
// 页面销毁时
onBeforeUnmount(() => {
	const editor = editorRef.value;
	if (editor == null) return;
	editor?.destroy();
});
nextTick(() => {
	// 监听双向绑定值改变，用于回显
	watch(
		() => props.getHtml,
		(val) => {
			state.editorVal = val;
		},
		{
			deep: true,
		}
	);
	// 监听是否禁用改变
	// https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I
	watch(
		() => props.disable,
		(bool) => {
			const editor = editorRef.value;
			if (editor == null) return;

			bool ? editor.disable() : editor.enable();
		},
		{
			deep: true,
			immediate: true,
		}
	);
});
const handleBlur = (editor: IDomEditor) => {
	emit('blur', editor);
};
// 暴露变量
defineExpose({
	editorRef,
});
</script>
<style scoped lang="scss">
.editor-container {
	z-index: 99;
	border-radius: 5px;
	width: 100%;
	height: 100%;
}
</style>
