UNPKG

jobsys-newbie

Version:

Enhanced component based on ant-design-vue

203 lines (176 loc) 4.61 kB
import { defineComponent, onBeforeUnmount, onMounted, ref, shallowRef, inject, watch } from "vue" import Editor from "./components/WangEditor.vue" import Toolbar from "./components/WangToolbar.vue" import { message, Form } from "ant-design-vue" import "./index.less" import { NEWBIE_EDITOR } from "../provider/NewbieProvider.jsx" import { useFetch, useProcessStatusSuccess, useT } from "../../hooks" /** * 富文本编辑器 * 基于 WangEditor * * @version 1.0.0 * @see https://www.wangeditor.com/v5/for-frame.html#vue3 */ export default defineComponent({ name: "NewbieEditor", props: { /** * 输入框的值 * @model */ value: { type: String, default: "" }, /** * 占位符 */ placeholder: { type: String, default: "" }, /** * 是否禁用 */ disabled: { type: Boolean, default: false }, /** * 是否只读 */ readonly: { type: Boolean, default: false }, /** * @param {Object} config.toolbarConfig [工具栏配置](https://www.wangeditor.com/v5/toolbar-config.html) * @param {Object} config.editorConfig [编辑器配置](https://www.wangeditor.com/v5/editor-config.html) */ config: { type: Object, default: () => ({ toolbarConfig: {}, editorConfig: {}, }), }, }, emits: ["update:value"], setup(props, { emit, expose }) { const formItemContext = Form.useInjectFormItemContext() // 编辑器实例,必须用 shallowRef,重要! const editorRef = shallowRef() // 内容 HTML const valueHtml = ref("") const toolbarConfig = ref({ excludeKeys: ["group-video", "emotion"], ...props.config?.toolbarConfig, }) const { uploadUrl } = inject(NEWBIE_EDITOR, () => ({})) const editorConfig = ref({ placeholder: props.placeholder || useT("form.please-input", { title: useT("common.content") }), readOnly: props.disabled || props.readonly, MENU_CONF: { uploadImage: { async customUpload(file, insertFn) { const formData = new FormData() formData.append("file", file) try { let res = await useFetch().post(uploadUrl, formData) useProcessStatusSuccess(res, () => { const { url, alt, href } = res.result insertFn(url, alt, href) }) } catch (e) { console.log(e) } }, }, }, ...props.config?.editorConfig, }) const setContent = (content) => { if (editorRef.value) { editorRef.value.setHtml(content) } } // 组件销毁时,也及时销毁编辑器,重要! onBeforeUnmount(() => { const editor = editorRef.value if (editor == null) return editor.destroy() }) watch( () => props.value, (val) => { if (val !== valueHtml.value && editorRef.value) { setContent(val) } }, ) // 编辑器回调函数 const handleCreated = (editor) => { editorRef.value = editor // 记录 editor 实例,重要! setContent(props.value) editor.on("fullScreen", () => { document.body.classList.add("fullscreen") }) editor.on("unFullScreen", () => { document.body.classList.remove("fullscreen") }) if (!props.disabled && !props.readonly) { toolbarElemRef.value = createToolbarElem() } } const handleChange = (editor) => { let html = editor.getHtml() if (editor.isEmpty()) { html = "" } if (html !== props.value) { emit("update:value", html) formItemContext.onFieldChange() } } const customAlert = async (info, type) => { switch (type) { case "success": message.success(info) break case "info": message.info(info) break case "warning": message.warning(info) break case "error": message.error(info) break default: message.info(info) break } } expose({ setContent, }) /********** render **********/ const toolbarElemRef = ref() const editorElemRef = ref() const createToolbarElem = () => { if (editorRef?.value?.destroy) { return <Toolbar editor={editorRef.value} defaultConfig={toolbarConfig.value} style="border-bottom: 1px solid #f0f0f0"></Toolbar> } else { return <div></div> } } const createEditorElem = () => ( <Editor v-model={valueHtml.value} defaultConfig={editorConfig.value} style="height: 400px; overflow-y: hidden" onOnChange={handleChange} onOnCreated={handleCreated} onCustomAlert={customAlert} /> ) onMounted(() => { editorElemRef.value = createEditorElem() }) return () => ( <div style="border: 1px solid #f0f0f0"> {toolbarElemRef.value} {editorElemRef.value} </div> ) }, })