| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- <template>
- <div class="richText">
- <div class="box" style="">
- <Toolbar
- class="boxToolbar"
- :editor="editorRef"
- :defaultConfig="toolbarConfig"
- :mode="mode"
- />
- <Editor
- class="boxEditor"
- v-model="valueHtml"
- :defaultConfig="editorConfig"
- :mode="mode"
- @onCreated="handleCreated"
- @onChange="handleChange"
- @onDestroyed="handleDestroyed"
- @onFocus="handleFocus"
- @onBlur="handleBlur"
- @customAlert="customAlert"
- @customPaste="customPaste"
- />
- </div>
- </div>
- </template>
- <script setup>
- import { useRouter } from "vue-router";
- import { ElMessage, ElMessageBox } from "element-plus";
- import { Calendar } from "@element-plus/icons-vue";
- import { dayjs } from "element-plus";
- import lodash, { reduce } from "lodash";
- import { uploadFile } from "@/api/uploadFile";
- import "@wangeditor/editor/dist/css/style.css"; // 引入 css
- import { onBeforeUnmount, nextTick, ref, shallowRef, onMounted } from "vue";
- import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
- import { DomEditor, createToolbar } from "@wangeditor/editor";
- // 编辑器实例,必须用 shallowRef
- const editorRef = shallowRef();
- const props = defineProps({
- fatherMessage: {},
- });
- const emit = defineEmits(["richtextClick"]);
- // 内容 HTML
- const valueHtml = ref();
- const toolbarConfig = {
- // JS 语法
- /* 工具栏配置 */
- excludeKeys: [
- "insertLink",
- "insertVideo",
- "insertTable",
- "fullScreen",
- "insertImage",
- // "group-image",
- "group-video",
- "todo",
- ],
- };
- const uploadImg = async (file, insertFn) => {
- // let imgData = new FormData();
- console.log(file);
- let srcImg = file;
- let data = new FormData();
- data.set("file", srcImg);
- let res = await uploadFile(data);
- console.log(res, "导入照片");
- if (res.code == 200) {
- let href = res.data.fileUrl;
- insertFn(href);
- ElMessage({
- type: "success",
- showClose: true,
- message: res.message,
- center: true,
- });
- } else {
- ElMessage({
- type: "error",
- showClose: true,
- message: res.message,
- center: true,
- });
- }
- };
- const editorConfig = {
- placeholder: "请输入内容......",
- MENU_CONF: {
- uploadImage: {
- // 自定义上传图片 方法
- customUpload: uploadImg,
- // 自定义插入图片 方法
- // customInsert: insertImg,
- //上传图片配置
- // server: "https:// jgy-1325577833.cos.ap-guangzhou.myqcloud.com", //上传接口地址
- fieldName: "file", //上传文件名
- methods: "post",
- metaWithUrl: false, // 参数拼接到 url 上
- // 单个文件上传成功之后
- // onSuccess(file, res) {
- // console.log(file, res);
- // },
- // 自定义插入图片
- customInsert(res, insertFn) {
- console.log(res);
- // insertFn(res.url)
- },
- },
- // insertImage: {
- // onInsertedImage(imageNode) {
- // if (imageNode == null) return;
- // const { src, alt, url, href } = imageNode;
- // console.log("inserted image", src, alt, url, href);
- // },
- // checkImage: customCheckImageFn, // 也支持 async 函数
- // parseImageSrc: customParseImageSrc, // 也支持 async 函数
- // },
- // editImage: {
- // onUpdatedImage(imageNode) {
- // if (imageNode == null) return;
- // const { src, alt, url } = imageNode;
- // console.log("updated image", src, alt, url);
- // },
- // checkImage: customCheckImageFn, // 也支持 async 函数
- // parseImageSrc: customParseImageSrc, // 也支持 async 函数
- // },
- },
- };
- const mode = ref("default"); // 默认模式
- // const mode = ref("simple"); // 简易模式
- const handleChange = (editor) => {
- // console.log("change:", editor);
- // console.log("change:", editor.getText());
- // console.log("change:", editor.getHtml());
- emit("richtextClick", {
- html: editor.getHtml(),
- text: editor.getText(),
- });
- };
- const handleDestroyed = (editor) => {
- console.log("destroyed", editor);
- };
- const handleFocus = (editor) => {
- console.log("focus", editor);
- const toolbar = DomEditor.getToolbar(editor);
- const curToolbarConfig = toolbar.getConfig();
- console.log(curToolbarConfig.toolbarKeys); // 当前菜单排序和分组
- };
- const handleBlur = (editor) => {
- console.log("blur", editor);
- };
- const customAlert = (info, type) => {
- alert(`【自定义提示】${type} - ${info}`);
- };
- // 粘贴事件对象
- const customPaste = (editor, event, callback) => {
- console.log("ClipboardEvent 粘贴事件对象", event);
- const html = event.clipboardData.getData("text/html"); // 获取粘贴的 html
- const text = event.clipboardData.getData("text/plain"); // 获取粘贴的纯文本
- const rtf = event.clipboardData.getData("text/rtf"); // 获取 rtf 数据(如从 word wsp 复制粘贴)
- // console.log(html);
- // 自定义插入内容
- // editor.insertText("自定义插入内容");
- // 返回 false ,阻止默认粘贴行为
- // event.preventDefault();
- // callback(false); // 返回值(注意,vue 事件的返回值,不能用 return)
- // 返回 true ,继续默认的粘贴行为
- callback(true);
- };
- // // 自定义图片上传
- // editorConfig.MENU_CONF["uploadImage"] = {
- // async customUpload(file, insertFn) {
- // let formData = new FormData();
- // formData.append("files", file);
- // try {
- // // 这里结合实际场景写自己上传图片的逻辑,此处代码仅为示例
- // const { data } = await upload(formData);
- // // 对图片进行处理,同样需要结合实际场景
- // data.forEach((item) => {
- // insertFn(item, "image", item);
- // });
- // } catch (error) {
- // console.log(error);
- // }
- // },
- // };
- const handleCreated = (editor) => {
- editorRef.value = editor; // 记录 editor 实例,重要!
- // console.log(props.fatherMessage);
- editor.setHtml(props.fatherMessage.data);
- if (props.fatherMessage.flag) {
- editor.enable();
- } else {
- editor.disable();
- }
- };
- // 模拟 ajax 异步获取内容
- onMounted(() => {
- // console.log(props.fatherMessage.data);
- });
- // 组件销毁时,也及时销毁编辑器
- onBeforeUnmount(() => {
- console.log("销毁组件");
- const editor = editorRef.value;
- if (editor == null) return;
- editor.destroy();
- });
- </script>
- <style scoped lang="scss">
- .richText {
- width: 100%;
- .box {
- .boxToolbar {
- border-top: 1px solid #ccc;
- border-left: 1px solid #ccc;
- border-right: 1px solid #ccc;
- }
- .boxEditor {
- min-height: 200px !important;
- max-height: 500px !important;
- overflow: auto;
- border: 1px solid #ccc;
- }
- }
- }
- </style>
|