2025-04-23 17:15:41 +08:00

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>