|
|
@@ -1,284 +0,0 @@
|
|
|
-<template>
|
|
|
- <div
|
|
|
- class="rich-text-editor"
|
|
|
- :style="{ border: border ? '1px solid #ccc' : '0px solid #ccc' }"
|
|
|
- :key="JSON.stringify(readOnly)"
|
|
|
- >
|
|
|
- <Toolbar
|
|
|
- v-show="showToolbar"
|
|
|
- ref="toolbarRef"
|
|
|
- class="rich-text-editor-toolbar"
|
|
|
- :editor="editor"
|
|
|
- :defaultConfig="toolbarConfig"
|
|
|
- :mode="mode"
|
|
|
- :style="toolbarConfig.style"
|
|
|
- />
|
|
|
- <Editor
|
|
|
- ref="editorRef"
|
|
|
- class="rich-text-editor-editor"
|
|
|
- v-model="html"
|
|
|
- :defaultConfig="editorConfig"
|
|
|
- :mode="mode"
|
|
|
- style="overflow-y: auto"
|
|
|
- :style="editorConfig.style"
|
|
|
- @onCreated="onCreated"
|
|
|
- @onMaxLength="onMaxLength"
|
|
|
- @onChange="onChange"
|
|
|
- @customPaste="customPaste"
|
|
|
- @customAlert="customAlert"
|
|
|
- />
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import { Editor, Toolbar } from "@wangeditor-next/editor-for-vue2";
|
|
|
-
|
|
|
-import {
|
|
|
- initEditorConfig,
|
|
|
- initToolbarConfig,
|
|
|
- initUploadImage,
|
|
|
-} from "./initData";
|
|
|
-
|
|
|
-import "@wangeditor-next/editor/dist/css/style.css";
|
|
|
-
|
|
|
-export default {
|
|
|
- components: { Editor, Toolbar },
|
|
|
- props: {
|
|
|
- value: {
|
|
|
- type: String,
|
|
|
- default: "",
|
|
|
- },
|
|
|
-
|
|
|
- /**
|
|
|
- * 主题
|
|
|
- * default 默认 | simple 简约
|
|
|
- * 工具栏的配置也会有所不同
|
|
|
- */
|
|
|
- mode: {
|
|
|
- type: String,
|
|
|
- default: "simple",
|
|
|
- },
|
|
|
-
|
|
|
- /** 是否显示边框 */
|
|
|
- border: {
|
|
|
- type: Boolean,
|
|
|
- default: true,
|
|
|
- },
|
|
|
-
|
|
|
- /** 是否只读 */
|
|
|
- readOnly: {
|
|
|
- type: Boolean,
|
|
|
- default: initToolbarConfig.readOnly,
|
|
|
- },
|
|
|
-
|
|
|
- placeholder: {
|
|
|
- type: String,
|
|
|
- default: "请输入内容...",
|
|
|
- },
|
|
|
-
|
|
|
- /** 是否显示工具栏 */
|
|
|
- showToolbar: {
|
|
|
- type: Boolean,
|
|
|
- default: true,
|
|
|
- },
|
|
|
-
|
|
|
- /** 工具栏配置 */
|
|
|
- toolbarConfig: {
|
|
|
- type: Object,
|
|
|
- default: () => initToolbarConfig,
|
|
|
- },
|
|
|
-
|
|
|
- /** 编辑器配置 */
|
|
|
- defaultEditorConfig: {
|
|
|
- type: Object,
|
|
|
- default: () => initEditorConfig,
|
|
|
- },
|
|
|
- /** 自定义粘贴事件。可阻止编辑器的默认粘贴,实现自己的粘贴逻辑 */
|
|
|
- customPaste: {
|
|
|
- type: Function,
|
|
|
- default(editor, event, callback) {
|
|
|
- // console.log(editor.getConfig());
|
|
|
- // console.log(editor.getConfig().MENU_CONF.uploadImage);
|
|
|
- // // 阻止默认粘贴行为
|
|
|
- // event.preventDefault()
|
|
|
- // // 获取粘贴的HTML数据
|
|
|
- // let clipboardData = event.clipboardData || window.clipboardData
|
|
|
- // let pastedHtml = clipboardData.getData('text/html')
|
|
|
- // if (pastedHtml) {
|
|
|
- // // 处理粘贴内容,移除 <p><br></p> 标签
|
|
|
- // pastedHtml = pastedHtml.replace(/<p><br><\/p>/g, '')
|
|
|
- // // 插入处理后的内容到编辑器中
|
|
|
- // editor.dangerouslyInsertHtml(pastedHtml)
|
|
|
- // }
|
|
|
- // callback(false)
|
|
|
- },
|
|
|
- },
|
|
|
- /** 自定义编辑器 alert */
|
|
|
- customAlert: {
|
|
|
- type: Function,
|
|
|
- default: (s, t) => {},
|
|
|
- },
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- editor: null,
|
|
|
- html: "",
|
|
|
- };
|
|
|
- },
|
|
|
- computed: {
|
|
|
- editorConfig() {
|
|
|
- // console.log(this.$props);
|
|
|
- const config = this.$props.defaultEditorConfig;
|
|
|
- const MENU_CONF = config.MENU_CONF;
|
|
|
- const that = this;
|
|
|
- // console.log({
|
|
|
- // ...config,
|
|
|
- // readOnly: Boolean(this.$props.readOnly),
|
|
|
- // placeholder: this.$props.placeholder,
|
|
|
- // MENU_CONF: {
|
|
|
- // ...MENU_CONF,
|
|
|
- // uploadImage: {
|
|
|
- // onBeforeUpload(file) {
|
|
|
- // const f = Object.values(file)[0];
|
|
|
- // if (f.size > initUploadImage.base64LimitSize) {
|
|
|
- // that.$message.error(initUploadImage.overflowErrMsg);
|
|
|
- // }
|
|
|
- // return false;
|
|
|
- // },
|
|
|
- // onError(file, err, res) {
|
|
|
- // if (file.size > initUploadImage.base64LimitSize) {
|
|
|
- // that.$message.error(initUploadImage.overflowErrMsg);
|
|
|
- // }
|
|
|
- // },
|
|
|
- // ...MENU_CONF.uploadImage,
|
|
|
- // },
|
|
|
- // },
|
|
|
- // });
|
|
|
- return {
|
|
|
- ...config,
|
|
|
- readOnly: Boolean(this.$props.readOnly),
|
|
|
- placeholder: this.$props.placeholder,
|
|
|
- MENU_CONF: {
|
|
|
- ...MENU_CONF,
|
|
|
- uploadImage: {
|
|
|
- /** 上传之前触发 */
|
|
|
- onBeforeUpload(file) {
|
|
|
- const f = Object.values(file)[0];
|
|
|
- if (f.size > initUploadImage.maxFileSize) {
|
|
|
- that.$message.error(initUploadImage.overflowErrMsg);
|
|
|
- return false;
|
|
|
- }
|
|
|
- },
|
|
|
- /** 上传错误,或者触发 timeout 超时 */
|
|
|
- onError(file, err, res) {
|
|
|
- const f = file;
|
|
|
- if (f.size > initUploadImage.maxFileSize) {
|
|
|
- that.$message.error(initUploadImage.overflowErrMsg);
|
|
|
- }
|
|
|
- },
|
|
|
- /** 上传失败 */
|
|
|
- onFailed(file, res) {
|
|
|
- that.$message.error(`${file.name} 上传失败`);
|
|
|
- },
|
|
|
- ...MENU_CONF.uploadImage,
|
|
|
- },
|
|
|
- },
|
|
|
- };
|
|
|
- },
|
|
|
- },
|
|
|
- watch: {
|
|
|
- html: {
|
|
|
- handler(v) {
|
|
|
- // console.log(this.$props);
|
|
|
- // console.log("v", v);
|
|
|
- // doSomething
|
|
|
- this.pasteTableLineBreaker();
|
|
|
- },
|
|
|
- deep: true,
|
|
|
- },
|
|
|
- value: {
|
|
|
- handler(v) {
|
|
|
- if (v != this.html) {
|
|
|
- this.html = v || "";
|
|
|
- }
|
|
|
- },
|
|
|
- deep: true,
|
|
|
- immediate: true,
|
|
|
- },
|
|
|
- },
|
|
|
- methods: {
|
|
|
- /** 编辑器创建完毕时的回调函数 */
|
|
|
- onCreated(editor) {
|
|
|
- this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
|
|
|
- this.$nextTick(() => {
|
|
|
- // console.log(editor.getConfig())
|
|
|
- // const toolbar = DomEditor.getToolbar(this.editor)
|
|
|
- // const curToolbarConfig = toolbar.getConfig()
|
|
|
- // console.log('【 curToolbarConfig 】-39', curToolbarConfig)
|
|
|
- });
|
|
|
- },
|
|
|
- /** 编辑器内容、选区变化时的回调函数 */
|
|
|
- onChange(editor) {
|
|
|
- if (this.html != this.$props.value) {
|
|
|
- // console.log(this.html);
|
|
|
- this.$emit("input", this.html == "<p><br></p>" ? "" : this.html);
|
|
|
- this.$emit("onChange", editor);
|
|
|
- }
|
|
|
- },
|
|
|
- /**
|
|
|
- * 编辑器销毁时的回调函数
|
|
|
- * 调用 editor.destroy() 即可销毁编辑器,详见 API
|
|
|
- */
|
|
|
- onDestroyed(editor) {
|
|
|
- this.$emit("onDestroy", editor);
|
|
|
- },
|
|
|
- /** 编辑器 focus 时的回调函数 */
|
|
|
- onFocus(editor) {
|
|
|
- this.$emit("onFocus", editor);
|
|
|
- },
|
|
|
- /** 编辑器 blur 时的回调函数 */
|
|
|
- onBlur(editor) {
|
|
|
- this.$emit("onBlur", editor);
|
|
|
- },
|
|
|
- /** 文本长度达到指定长度 */
|
|
|
- onMaxLength(editor) {
|
|
|
- this.$emit("onMaxLength", editor);
|
|
|
- },
|
|
|
-
|
|
|
- /** 处理粘贴表格的时候生成一个换行 */
|
|
|
- pasteTableLineBreaker() {
|
|
|
- if (/<p><br><\/p><table/g.test(this.html)) {
|
|
|
- let filteredHtml = this.html.replace(/<p><br><\/p><table/g, "<table");
|
|
|
- filteredHtml = filteredHtml.replace(
|
|
|
- /<\/table><p><br><\/p>/g,
|
|
|
- "</table>"
|
|
|
- );
|
|
|
- this.editor.clear();
|
|
|
- this.editor.dangerouslyInsertHtml(filteredHtml);
|
|
|
- this.onChange(this.editor);
|
|
|
- }
|
|
|
- },
|
|
|
- },
|
|
|
- beforeDestroy() {
|
|
|
- const editor = this.editor;
|
|
|
- if (editor == null) return;
|
|
|
- editor.destroy(); // 组件销毁时,及时销毁编辑器
|
|
|
- },
|
|
|
-};
|
|
|
-</script>
|
|
|
-<style lang="scss">
|
|
|
-.rich-text-editor {
|
|
|
- display: flex;
|
|
|
- width: 100%;
|
|
|
- height: 400px;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
-
|
|
|
-.rich-text-editor .rich-text-editor-toolbar {
|
|
|
- border-bottom: 1px solid #ccc;
|
|
|
-}
|
|
|
-
|
|
|
-.rich-text-editor .rich-text-editor-editor {
|
|
|
- flex: 1;
|
|
|
-}
|
|
|
-</style>
|