174 lines
3.9 KiB
Vue
174 lines
3.9 KiB
Vue
<!--
|
|
* @Description:
|
|
* @Author: zenghua.wang
|
|
* @Date: 2024-03-24 11:04:52
|
|
* @LastEditors: zenghua.wang “1048523306@qq.com”
|
|
* @LastEditTime: 2025-01-20 09:34:23
|
|
-->
|
|
<template>
|
|
<section class="rich-editor">
|
|
<Toolbar v-show="toolbarShow" class="rich-editor-toolbar" :editor="refEditor" :default-config="options.toolbarConfig" :mode="mode" />
|
|
<Editor
|
|
v-model="valueHtml"
|
|
class="rich-editor-toolbar"
|
|
:style="styleEditor"
|
|
:default-config="options.editorConfig"
|
|
:mode="mode"
|
|
@on-created="handleCreated"
|
|
@on-change="handleChange"
|
|
@on-destroyed="handleDestroyed"
|
|
@on-focus="handleFocus"
|
|
@on-blur="handleBlur"
|
|
/>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
|
|
import { shallowRef, ref, computed, nextTick, onBeforeUnmount, onMounted } from 'vue';
|
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
|
import { isEmpty } from '@/utils';
|
|
// import { CommonUpload, UploadImageFromEditor } from '@/apis/common';
|
|
import { imageUpload } from './upFile';
|
|
|
|
const { VITE_APP_OSS_URL } = import.meta.env;
|
|
|
|
export default {
|
|
name: 'CustomRichEditor',
|
|
components: { Editor, Toolbar },
|
|
props: {
|
|
value: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
mode: {
|
|
type: String,
|
|
default: 'default', //'default' 或 'simple'
|
|
},
|
|
readOnly: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
options: {
|
|
type: Object,
|
|
default: () => {
|
|
return {
|
|
toolbarConfig: {},
|
|
editorConfig: {
|
|
placeholder: '请输入内容...',
|
|
readOnly: false,
|
|
MENU_CONF: {
|
|
uploadImage: {
|
|
server: '',
|
|
base64LimitSize: 10 * 1024, //10kb
|
|
maxFileSize: 10 * 1024 * 1024, //10M
|
|
maxNumberOfFiles: 10,
|
|
allowedFileTypes: ['image/*'],
|
|
customUpload: imageUpload,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
},
|
|
},
|
|
toolbarShow: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
},
|
|
emits: ['focus', 'blur', 'change', 'update:value'],
|
|
setup(props, cxt) {
|
|
const refEditor = shallowRef();
|
|
const valueHtml = ref('');
|
|
|
|
const styleEditor = computed(() => {
|
|
return {
|
|
height: props.options.contentHeight || '300px',
|
|
};
|
|
});
|
|
|
|
/**
|
|
* 创建
|
|
* @param {*} editor
|
|
*/
|
|
const handleCreated = (editor) => {
|
|
refEditor.value = editor;
|
|
props.readOnly ? editor.disable() : editor.enable();
|
|
};
|
|
/**
|
|
* 组件内容变化
|
|
* @param {*} editor
|
|
*/
|
|
const handleChange = (editor) => {
|
|
cxt.emit('change', editor);
|
|
cxt.emit('update:value', valueHtml.value);
|
|
};
|
|
/**
|
|
* 组件销毁
|
|
* @param {*} editor
|
|
*/
|
|
const handleDestroyed = (editor) => {
|
|
valueHtml.value = '';
|
|
};
|
|
/**
|
|
* 光标处于编辑区
|
|
* @param {*} editor
|
|
*/
|
|
const handleFocus = (editor) => {
|
|
cxt.emit('focus', editor);
|
|
};
|
|
/**
|
|
* 光标离开编辑区
|
|
* @param {*} editor
|
|
*/
|
|
const handleBlur = (editor) => {
|
|
cxt.emit('blur', editor);
|
|
};
|
|
/**
|
|
* 挂载
|
|
*/
|
|
onMounted(() => {
|
|
nextTick(() => {
|
|
if (props?.value) {
|
|
valueHtml.value = props.value;
|
|
}
|
|
});
|
|
});
|
|
/**
|
|
* 组件销毁时,也及时销毁编辑器
|
|
*/
|
|
onBeforeUnmount(() => {
|
|
if (!refEditor?.value) return;
|
|
refEditor.value.destroy();
|
|
});
|
|
|
|
return {
|
|
refEditor,
|
|
valueHtml,
|
|
styleEditor,
|
|
handleCreated,
|
|
handleChange,
|
|
handleDestroyed,
|
|
handleFocus,
|
|
handleBlur,
|
|
};
|
|
},
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.rich-editor {
|
|
z-index: 9999;
|
|
border: 1px solid $color-border;
|
|
&-toolbar {
|
|
border-bottom: 1px solid $color-border;
|
|
:deep(.w-e-bar-divider) {
|
|
width: 0;
|
|
}
|
|
}
|
|
&-editor {
|
|
overflow-y: hidden;
|
|
height: 200px;
|
|
}
|
|
}
|
|
</style>
|