vue3 tinymce7版本 完美适配基本需求(特殊需求外)

devtools/2024/11/29 15:21:33/

直接上代码 然后根据自己需求来调整代码内的toolbar功能设置
另外添加两个没有plugin的插件 首行缩进 以及调整段落大小 (目前没有太细看文档 不入门也不太好看懂~) 我这是从版本4升级到6的
已解决弹窗上使用问题
后面会出个相关配置文档的

代码

<template><div class="tinymce-boxz"><Editor v-model="content" :api-key="apiKey" :init="init" /></div>
</template><script>
import Editor from '@tinymce/tinymce-vue';
import { reactive, ref, toRefs, watchEffect } from 'vue';
import axios from 'axios';
export default {name: 'Tinymce',components: {Editor,},props: {//默认值modelValue: {type: String,default: '',},},setup(props, context) {const content = ref(props.modelValue);// 监听 props.modelValue,确保父组件数据变化时同步到本地watch(() => props.modelValue,(newValue) => {content.value = newValue;});// 监听本地 content 值的变化,向父组件发出更新事件watchEffect(() => {context.emit('update:modelValue', content.value);});const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/common/uploadOneFileToQiniu');const tiny = reactive({apiKey: '9i8khq1jzwwj7hda35fpc0q1e14zsb4ev23vaif34nqif0fw', //https://github.com/tinymce/tinymce-vue/blob/main/src/demo/views/Iframe.vueinit: {language: 'zh_CN', //语言类型placeholder: '在这里输入文字', //textarea中的提示信息min_width: 320,min_height: 220,height: 500, //注:引入autoresize插件时,此属性失效resize: 'both', //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号branding: false, //tiny技术支持信息是否显示// statusbar: false,  //最下方的元素路径和字数统计那一栏是否显示// elementpath: false, //元素路径是否显示font_size_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px',font_formats:'微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;', //字体样式plugins:' preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave emoticons  paragraphspacing', //插件配置 axupimgs indent2emtoolbar: ['fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ','styleselect formatselect fontselect fontsizeselect |  table image axupimgs media emoticons charmap hr pagebreak insertdatetime  selectall visualblocks searchreplace | code print preview |  lineheight formatpainter|fontsize | indent2em  | paragraphspacing  ',], //工具栏配置,设为false则隐藏external_plugins: {indent2em: '/plugins/tinymce/indent2em.js', // 本地插件路径(相对路径)},indent2em_val: '2em', // 插件的默认缩进值setup: function (editor) {// 段落间距插件editor.ui.registry.addMenuButton('paragraphspacing', {text: '段落间距',tooltip: '设置段落间距',fetch: function (callback) {const paragraphspacing = ['4px','6px','8px','10px','12px','14px','16px','18px','22px','24px','26px','28px','30px','32px',];let selectedItem = '0px';const items = paragraphspacing.map(function (item) {return {type: 'togglemenuitem',text: item,onAction: function () {selectedItem = item;editor.undoManager.transact(function () {editor.focus();editor.formatter.register({paragraphspacing: {block: 'p',styles: { margin: `${item} 0` },},});editor.formatter.apply('paragraphspacing', {value: item,});});},onSetup: function (api) {api.setActive(selectedItem === item);},};});callback(items);},});},// menubar: "file edit my1", //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”// images_upload_url: '/apib/api-upload/uploadimg',  //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了// images_upload_base_path: '/demo',  //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.phppaste_data_images: true, //图片是否可粘贴//此处为图片上传处理函数images_upload_handler: (blobInfo, success, failure) => {// 这里用base64的图片形式上传图片,let reader = new FileReader(); //本地预览reader.readAsDataURL(blobInfo.blob());reader.onloadend = function () {const imgbase64 = reader.result;success(imgbase64);console.log(imgbase64, '图片地址');};},file_picker_types: 'file image media', //file image media分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数// 文件上传处理函数file_picker_callback: function (callback, value, meta) {// meta.filetype  //根据这个判断点击的是什么file image medialet filetype; //限制文件的上传类型,需要什么就添加什么的后缀if (meta.filetype == 'image') {filetype = '.jpg, .jpeg, .png, .gif, .ico, .svg';} else if (meta.filetype == 'media') {filetype = '.mp3, .mp4, .avi, .mov';} else {filetype ='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4, .jpg, .jpeg, .png, .gif, .ico, .svg';}console.log(filetype, '类型', value, 'value');let inputElem = document.createElement('input'); //创建文件选择inputElem.setAttribute('type', 'file');inputElem.setAttribute('accept', filetype);inputElem.click();inputElem.onchange = () => {let file = inputElem.files[0]; // 获取文件对象if (!file) return; // 如果未选择文件,直接返回// 使用 FormData 上传文件let formData = new FormData();formData.append('file', file); // 假设服务端要求的字段名是 'file'// 上传到服务器axios.post(uploadUrl.value, formData, {headers: {'Content-Type': 'multipart/form-data',},}).then((res) => {console.log(res, '上传成功返回的文件 URL');// 成功后回调,将文件 URL 插入编辑器callback(res.data.url, { title: res.data.fileName });});};},},});//内容有变化,就更新内容,将值返回给父组件watchEffect(() => {context.emit('update:value', content.value);});return {content,...toRefs(tiny),};},
};
</script><style scoped>
.tinymce-boxz > textarea {display: none;
}
</style>
<style>
/* 隐藏apikey没有绑定这个域名的提示 */
.tox-notifications-container .tox-notification--warning {display: none !important;
}.tox.tox-tinymce {max-width: 100%;
}/* 在el-dialog中tinymce z-index 被太小而被遮挡时要加这两句 */
.tox-tinymce-aux {z-index: 99999 !important;
}.tinymce.ui.FloatPanel {z-index: 99;
}
</style>

插件文件indent2em

tinymce.PluginManager.add('indent2em', function(editor, url) {var pluginName='首行缩进';var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');var indent2em_val = editor.getParam('indent2em_val', '2em');var doAct = function () {var dom = editor.dom;var blocks = editor.selection.getSelectedBlocks();var act = '';global$1.each(blocks, function (block) {if(act==''){act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add';}if( act=='add' ){dom.setStyle(block, 'text-indent', indent2em_val);}else{var style=dom.getAttrib(block,'style');var reg = new RegExp('text-indent:[\\s]*' + indent2em_val + ';', 'ig');style = style.replace(reg, '');dom.setAttrib(block,'style',style);}});};editor.ui.registry.getAll().icons.indent2em || editor.ui.registry.addIcon('indent2em','<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M170.666667 563.2v-102.4H887.466667v102.4zM170.666667 836.266667v-102.4H887.466667v102.4zM512 290.133333v-102.4H887.466667v102.4zM238.933333 341.333333V136.533333l204.8 102.4z" fill="#2c2c2c" p-id="5210"></path></svg>');var stateSelectorAdapter = function (editor, selector) {return function (buttonApi) {return editor.selection.selectorChangedWithUnbind(selector.join(','), buttonApi.setActive).unbind;};};editor.ui.registry.addToggleButton('indent2em', {icon: 'indent2em',tooltip: pluginName,onAction: function () {doAct();},onSetup: stateSelectorAdapter(editor, ['*[style*="text-indent"]','*[data-mce-style*="text-indent"]',])});editor.ui.registry.addMenuItem('indent2em', {text: pluginName,onAction: function() {doAct();}});editor.addCommand('indent2em', doAct  );return {getMetadata: function () {return  {name: pluginName,url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php",};}};
});

依赖

在这里插入图片描述


http://www.ppmy.cn/devtools/137949.html

相关文章

质数——acwing

素数几种方法&#xff08;区间筛&#xff09;-CSDN博客 之前做的笔记&#x1f446;&#x1f446;&#x1f446; 题目一&#xff1a;试除法判定质数 866. 试除法判定质数 - AcWing题库 代码 #include<bits/stdc.h> using namespace std;bool isprime(int x) {if(x 1…

C++学习日记---第13天(类和对象---封装)

笔记复习 1.类和对象 c面向对象的三大特性为&#xff1a;封装&#xff0c;继承&#xff0c;多态 c认为万事万物都皆为对象&#xff0c;对象上有其属性和行为 具有相同性质的对象&#xff0c;我们可以抽象为称为类 2.封装 作用&#xff1a;将属性和行为作为一个整体&#xf…

arm Rk1126 编译Qt工程报错: Could not find qmake spec

首先修改qmake.conf文件&#xff0c;配置好正确的交叉编译工具&#xff1a; 然后执行编译&#xff1a; /opt/Rv1126/Rv1126-盒子代码/rv1126-qt5-sdk/bin/qmake untitled.pro 报错。 原因&#xff1a;中文路径。修改路径为英文路径即可

【R库包安装】R库包安装总结:conda、CRAN等

【R库包安装】R库包安装总结&#xff1a;conda、CRAN等 方法1&#xff1a;基于 R 的 CRAN 仓库安装CRAN库包查询从 CRAN 安装 方法2&#xff1a;使用conda安装库包确保已安装 R 和 Conda 环境使用 Conda 官网浏览是否存在相应库包Conda 安装 R 库 方法3&#xff1a;从 GitHub 安…

Linux进程基础

前言&#xff1a;并行和并发 1.并发&#xff1a;在操作系统中是指一个时间段中有几个进程都处于正在运行到运行完毕之间&#xff0c;且它们都是在同一个处理器上运行的&#xff0c;抢占了共享的这个CPU资源 在用户的视角上&#xff0c;这些进程看似同时进行&#xff0c;但不是…

QT6学习第四天 感受QT的文件编译

QT6学习第四天 感受QT的文件编译 使用纯代码编写程序新建工程 使用其他编辑器纯代码编写程序并在命令行运行使用 .ui 表单文件生成界面使用自定义 C 窗口类使用现成的QT Designer界面类 使用纯代码编写程序 我们知道QT Creator中可以用拖拽的方式在 .ui 文件上布局&#xff0c…

【计算机网络】计算机网络概述

当我们决定要谈谈网络的时候&#xff0c;我想在谈之前&#xff0c;有必要了解一下“协议”这个词。协议&#xff0c;定义了在俩个或者多个通信实体之间交换报文的格式和次序&#xff0c;以及报文发送、接收报文或者其他的事件所采取的动作。定义都比较晦涩&#xff0c;那就让我…

QML学习 —— 33、弹出式菜单(附源码)

效果 说明 Menu菜单类型为本机平台菜单弹出式菜单提供QML API。 代码 import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.12Window {id: rootvisible: