精华内容
下载资源
问答
  • tinymce富文本
    2022-08-11 18:35:57

    这篇博客的目的是记录一下Vue 中使用 tinymce 富文本编辑器,其中参考了一下 https://www.cnblogs.com/wisewrong/p/8985471.html 这篇博客,但原博客只兼容 Tinymce 4.x 不支持最新版本,所以在此做了更新。

    特别说明,此博客适用于 tinymce 6.x

    版本说明

    "vue": "^2.6.14""@tinymce/tinymce-vue": "^3.2.8",
    "tinymce": "^6.1.2",
    
    • 如果有购买 tinymce 的服务,可以参考 tinymce-vue 的说明,通过 api-key 直接使用 tinymce。
    • 安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 public 目录下

    初始化

    引入以下文件

    import tinymce from 'tinymce/tinymce'
    import Editor from '@tinymce/tinymce-vue'
    import 'tinymce/themes/silver/theme'
    import 'tinymce/models/dom';
    import 'tinymce/icons/default';
    

    tinymce-vue 是一个组件,需要在 components 中注册,然后直接使用

    <Editor v-model="tinymceHtml" :init="editorInit"></Editor>
    

    编辑器需要一个 skin 才能正常工作,所以要设置一个 skin_url 指向之前复制出来的 skins 文件,content_css 指向 content.css
    注意,需要使用哪套theme,就将目录指到对应文件。如下面的黑暗模式

    editorInit: {
      skin_url: '/skins/ui/oxide',
      content_css: '/skins/content/default/content.css',
      // 黑暗模式
      // skin_url: '/skins-2/ui/oxide-dark',
      // content_css: '/skins-2/content/dark/content.css',
      height: 300,
    }
    

    同时在 mounted 中也需要初始化一次:
    如果在这里传入上面的 init 对象,并不能生效,但什么参数都不传也会报错,所以这里传入一个空对象。

    mounted () {
      tinymce.init({})
    }
    

    扩展插件

    完成了上面的初始化之后,就已经能正常运行编辑器了,但只有一些基本功能

    tinymce 通过添加插件 plugins 的方式来添加功能

    比如要添加一个上传图片的功能,就需要用到 image 插件,添加超链接需要用到 link 插件。

    import 'tinymce/plugins/image';
    import 'tinymce/plugins/link';
    

    添加plugin:

    plugins: 'link image',
    

    添加 toolbar:

    toolbar: 'link image',
    

    最后贴一下完整代码:

    <template>
      <div class='tinymce'>
        <h1>tinymce</h1>
        <Editor v-model='tinymceHtml' :init='editorInit'></Editor>
        <div v-html='tinymceHtml'></div>
      </div>
    </template>
    
    <script>
    import tinymce from 'tinymce/tinymce'
    import Editor from '@tinymce/tinymce-vue'
    import 'tinymce/themes/silver/theme'
    import 'tinymce/models/dom';
    import 'tinymce/icons/default';
    
    // plugin, 更多plugin,请参考官方文档
    import 'tinymce/plugins/image'
    import 'tinymce/plugins/link'
    import 'tinymce/plugins/code'
    import 'tinymce/plugins/table'
    import 'tinymce/plugins/lists'
    import 'tinymce/plugins/wordcount'
    import 'tinymce/plugins/media'
    
    export default {
      // eslint-disable-next-line vue/multi-word-component-names
      name: 'tinymce',
      data () {
        return {
          tinymceHtml: '请输入内容',
          editorInit: {
            skin_url: '/skins/ui/oxide',
            content_css: '/skins/content/default/content.css',
            height: 300,
            plugins: 'link lists image code table wordcount media',
            toolbar: 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat',
            branding: false
          }
        }
      },
      mounted () {
        // 如果在这里传入上面的 init 对象,并不能生效,但什么参数都不传也会报错,所以这里传入一个空对象。
        tinymce.init({})
      },
      components: {Editor}
    }
    </script>
    

    上传图片

    默认配置是不支持上传图片的,需要上传图片需要按照文档添加相应配置,才会出现上传操作按钮。

    多语言

    默认显示英文,如果需要其他语言,需要自行下载对应的语言包,通过language_urllanguage 设置。
    language_url 和语言包设置方法,同 skin_url

    editorInit: {
      // ...
      language_url: '/static/tinymce/zh_CN.js',
      language: 'zh_CN',
    }
    

    更多配置请参考官方文档

    更多相关内容
  • vue-tinymce 封装了el-upload 控件,支持富文本编辑器自定义图片上传整合。 复制到vue的src/components文件夹下 详情博文介绍见:https://xingyun.blog.csdn.net/article/details/102492921
  • tinymce中文语言包,在项目中引入后,需要设置初始化参数:language: 'zh_CN'即可。
  • 应用JS实现,TinyMCE富文本编辑器导出为word文档,可解决图片,表格的导出,这是实现的demo,可以直接取用
  • tinymce富文本4.7.5资源

    2019-03-21 19:18:35
    tinymce富文本4.7.5资源,整合vue做的.....
  • Django原生的TextField并不友好,集成TinyMCE富文本编辑器 Django版本:1.11.5 TinyMCE版本:4.6.7 第一步:从官网下载TinyMCE https://www.tinymce.com/download/ 注意下载的是下面那个开发包,Dev Package。此包包...
  • tinyMCE富文本编辑器line-height行高插件,下载后放在tinyMCE插件的plugins文件夹中,之后初始化中引入plugins,即可在toolbar中展示
  • tinymce富文本编辑器集成demo,添加powerpaste插件,支持word、excel带格式粘贴.rar
  • tinymce富文本编辑器

    2018-12-14 10:41:23
    tinymce富文本编辑器集成demo,添加powerpaste插件,支持word、excel带格式粘贴。 演示案例 demo.html
  • 【超详细】Tinymce富文本使用教程

    千次阅读 2022-06-10 15:18:25
    官网文档:www.tiny.cloud/docs/ 社区版及开发版官方最新打包地址:... 获取内容:tinyMCE.activeEditor.getContent() 设置内容:tinyMCE.activeEditor.setContent("需要设置的编辑器内容") 获取内容:tinyMCE.

    Tinymce基础使用手册

    1. 开始

    官网文档:www.tiny.cloud/docs/ 

    社区版及开发版官方最新打包地址:www.tiny.cloud/get-tiny/self-hosted/ 

    汉化包:tinymce.ax-z.cn/static/tiny/langs/zh_CN.js

    2. 快速使用

    • 引入tinymce脚本

    • 将tinymce初始化为页面的一部分

    我们需要使用tinymce.init()来进行初始化;tinymce.init()内的初始化对象包含众多参数,但都是可省略的,唯一必须的参数就是selector(允许通过css选择器指定tinymce要绑定的内容容器,div和textarea都是可以的)

    例如:

    <div id = "tinydemo"></div>
    <script >
        tinymce.init({
            selector: '#tinydemo'
        }); 
    </script>
    

    • 获取tinymce富文本框内容的几种方式:

     如果当前页面只有一个编辑器

            获取内容:tinyMCE.activeEditor.getContent()

            设置内容:tinyMCE.activeEditor.setContent("需要设置的编辑器内容")

    如果当前页面有多个编辑器(下面的“[0]”表示第一个编辑器,以此类推)

            获取内容:tinyMCE.editors[0].getContent()

            设置内容:tinyMCE.editors[0].setContent("需要设置的编辑器内容")

    获取不带HTML标记的纯文本内容

    var activeEditor = tinymce.activeEditor;
    var editBody = activeEditor.getBody();
    activeEditor.selection.select(editBody);
    //纯文本内容
    var text = activeEditor.selection.getContent({
        'format': 'text'
    });
    

    textarea可通过表单提交

    <h1>TinyMCE Quick Start Guide</h1>
    <form method="post">
          <textarea id="mytextarea">Hello, World!</textarea>
    </form>
    <script>
          tinymce.init({
            selector: '#mytextarea'
          });
    </script>
    

    3. 常用配置

    selector

    渲染DOM,必填,String值,使用CSS选择器。

    language

    指定语言,String,值区分大小写。

    language_url

    汉化包路径

    height

    设置整个编辑器的高度,包括菜单栏、工具栏和状态栏,如果提供了数字,TinyMCE 以像素为单位设置高度。如果提供了字符串,TinyMCE 假定该值是有效的 CSS,并将编辑器的高度设置为字符串值。这允许备用单元,例如%,em,和vh。(测试%不起作用)

    readonly

    只读,Boolean,将编辑器设置成只读模式,不可编辑。

    plugins

    指定需加载的插件,String或Array,此插件必须已存在plugins目录内;若使用String值,多个插件用空格分隔;默认不会加载任何插件,支持自写插件。

    可选插件配置:www.tiny.cloud/docs/plugins/opensource/advlist/

    toolbar

    自定义工具栏,Boolean或String或Array;为false时将关闭工具栏;String值时用于自定义工具栏,例:toolbar:"link | preview",值中可插入“|”分组;支持多级工具栏,例:toolbar1:"",toolbar2:"";官网:www.tiny.cloud/docs/configure/editor-appearance/#toolbar

    menu

    自定义菜单。例:

    tinymce.init({
        selector: '#tinydemo',
        menu: {
            file: {title: '文件', items: 'newdocument'},
            edit: {title: '编辑', items: 'undo redo | cut copy paste pastetext | selectall'},
            insert: {title: '插入', items: 'link media | template hr'},
            view: {title: '查看', items: 'visualaid'},
            format: {title: '格式', items: 'bold italic underline strikethrough superscript subscript | formats | removeformat'},
            table: {title: '表格', items: 'inserttable tableprops deletetable | cell row column'},
            tools: {title: '工具', items: 'spellchecker code'}
        }
    });
    

    当有多级菜单时:

    tinymce.init({
        selector: '#tinydemo',
        menubar: 'my1',
        menu: {
            my1: {title: '我的菜单', items: 'copy paste' }
        }
    });
    

    menubar

    1级菜单,Boolean或String;为false时将关闭菜单栏;String时用于自定义1级菜单,例:menubar:"file edit";官网:www.tiny.cloud/docs/configure/editor-appearance/#menubar

    placeholder

    内容预展示文本,String值。

    resize

    调整编辑器大小工具,编辑器右下角有一个可以拖动的标记,鼠标按住它可以改变编辑器的大小。默认resize: true;可选值为:true(仅允许改变高度), false(完全不让你动), 'both'(宽高都能改变,注意引号)。

    4. 高级功能 

         图片上传 

    tinymce.init({
        selector: '#tinydemo',
        language: 'zh_CN',
        plugins: 'image', //使用image插件
        toolbar: 'image', //工具栏显示
        images_upload_url: '/api/controller/action', //用于指定一个接收上传文件的后端处理程序地址
        images_upload_base_path: '/demo', //如果返回的地址是相对路径,此参数可以给相对路径指定它所相对的基本路径
    });
    

    跨域问题:如果TinyMCE和接受上传图片程序未在同一域名下,浏览器会因跨域问题而拒绝操作,后端程序返回结果时,需给浏览器一个允许跨域的指令。

    图片上传扩展参数

    名称描述
    images_upload_credentials对images_upload_url中指定的地址调用时是否传递cookie等跨域的凭据。值为布尔值,默认false。
    images_upload_handler(图片上传自定义实现)此选项允许你使用自定义函数代替TinyMCE来处理上传操作。该自定义函数需提供4个参数:blobInfo、成功回调和失败回调、上传进度(取值1-100)。

    images_upload_handler函数将完全接管编辑器的图片上传,你需要在上传成功后执行成功回调函数,参数则为图片URL,也可以在第二个参数加入对话框填充数据对象。

    //以下为自定义上传实现的一个代码示例
    tinymce.init({
        selector: '#tinydemo',
        images_upload_handler: function(blobInfo, success, failure, progress) {
            var xhr, formData;
            xhr = new XMLHttpRequest();
            xhr.withCredentials = false;
            xhr.open('POST', 'action');
    
            xhr.upload.onprogress = function(e) {
                progress(e.loaded / e.total * 100);
            }
    
            xhr.onload = function() {
                var json;
                if (xhr.status == 403) {
                    failure('HTTP Error: ' + xhr.status, {
                        remove: true
                    });
                    return;
                }
                if (xhr.status < 200 || xhr.status >= 300) {
                    failure('HTTP Error: ' + xhr.status);
                    return;
                }
                json = JSON.parse(xhr.responseText);
                if (!json || typeof json.location != 'string') {
                    failure('Invalid JSON: ' + xhr.responseText);
                    return;
                }
                success(json.location);
            };
    
            xhr.onerror = function() {
                failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
            }
    
            formData = new FormData();
            formData.append('file', blobInfo.blob(), blobInfo.filename());
    
            xhr.send(formData);
        }
    });
    

    文件上传

    原文里只涉及了图片上传,文件上传没有说明,只能使用 file_picker_callback 写回调。
    更多参数请移步官网:www.tiny.cloud/docs/configure/file-image-upload/#automatic_uploads

    简单例子:

    tinymce.init({
        selector: '#tinydemo',
        language: 'zh_CN',
        plugins: 'link',        
        toolbar: 'link',            
        file_picker_callback: function(callback, value, meta) {
        //文件分类
        var filetype = '.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4';
        var upurl = '/api/controller/';
        //为不同插件指定文件类型及后端地址
        switch (meta.filetype) {
            case 'image':
                filetype = '.jpg, .jpeg, .png, .gif';
                upurl += 'action1';
                break;
            case 'media':
                filetype = '.mp3, .mp4';
                upurl += 'action2';
                break;
                case 'file':
                    break;
        };
        //模拟出一个input用于添加本地文件
        var input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.setAttribute('accept', filetype);
        input.click();
        input.onchange = function() {
            var file = this.files[0];
            var xhr, formData;
            console.log(file.name);
            //TODO:这里写请求
            };
        },            
    });                
    

    自定义插件

    第一,在目录tinymce/plugins下新建一个目录,与自己要取的插件名称相同,在到插件目录下新建plugin.min.js,如下:

    • upfile/plugin.min.js

    upfile是我自定义插件名称,位置tinymce/plugins/upfile

    第二,理解下面代码,参阅官网:www.tiny.cloud/docs/api/tinymce/tinymce.addonmanager/

    /**
     * 上传文件插件
     */
    
    tinymce.PluginManager.add('upfile', function (editor, url) {
        var openDialog = function () {
            return editor.windowManager.open({
                title: '上传文件',
                body: {
                    type: 'panel',
                    items: [
                        {
                            type: 'htmlpanel', // component type
                            html: '<div><input id="TinymcefileToUpload" type="file"  name="TinymcefileToUpload" class="input"></div>'
                        }
                    ]
                },
                buttons: [
                    {
                        type: 'cancel',
                        text: 'Close'
                    },
                    {
                        type: 'submit',
                        text: 'Upload',
                        primary: true
                    }
                ],
                onSubmit: function (api) {
                    let input = document.getElementById("TinymcefileToUpload");
                    console.log("进来了");
                    if (input.files.length > 0) {
                        let file = input.files[0];
                        let formData = new FormData();
                        formData.append("formFile", file);
                        axios.post("https://192.168.0.174:7183/api/Test/UploadFile", formData).then(res => {
                            if (res.data?.path != "") {
                                editor.insertContent(res.data.fileName + ":" + res.data?.path);
                                alert("文件上传成功");
                            }
                            else {
                                alert("上传失败");
                            }
                        }).catch(err => console.log(err));
                    }
                    api.close();
                }
            });
        };
    
        // Add a button that opens a window
        editor.ui.registry.addButton('upfile', {
            text: `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" class="bi bi-box-arrow-in-up" viewBox="0 0 16 16">
                < path fill- rule="evenodd" d = "M3.5 10a.5.5 0 0 1-.5-.5v-8a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 0 0 1h2A1.5 1.5 0 0 0 14 9.5v-8A1.5 1.5 0 0 0 12.5 0h-9A1.5 1.5 0 0 0 2 1.5v8A1.5 1.5 0 0 0 3.5 11h2a.5.5 0 0 0 0-1h-2z" />
                <path fill-rule="evenodd" d="M7.646 4.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 5.707V14.5a.5.5 0 0 1-1 0V5.707L5.354 7.854a.5.5 0 1 1-.708-.708l3-3z" />
          </svg> `,
            onAction: function () {
                // Open window
                openDialog();
            }
        });
    
        // Adds a menu item, which can then be included in any menu via the menu/menubar configuration
        editor.ui.registry.addMenuItem('upfile', {
            text: 'Example plugin',
            onAction: function () {
                // Open window
                openDialog();
            }
        });
    
        return {
            getMetadata: function () {
                return {
                    name: "Example plugin",
                    url: "http://exampleplugindocsurl.com"
                };
            }
        };
    });
    

    第三,笔者理解 不难看出,这是一个自写文件上传插件,需要注意的是该插件基于tinymce5.x,5.x以下会报错; 回到代码,其中upfile是插件名; openDialog()是用于打开弹窗; editor.windowManager.open用于自定义弹窗主题内容以及按钮回调; title是弹窗标题; body是弹窗中间内容; 上述插件使用的是一个容器包含很多子项,子项其中用了html容器,该容器支持html输出; buttons弹窗按钮集合;onSubmit是提交按钮触发事件; editor.ui.registry用于添加自定义项,具体参考:www.tiny.cloud/docs/api/tinymce.editor.ui/tinymce.editor.ui.registry/#methods

    5.使用typo排版

    引入typo.css,给div加上"class='typo'"即可自动排版,详情参阅:typo.sofi.sh

    typo.css局域网地址:file://desktop-b9prpkg/enjoy/typo.css

    6.tinymce-vue(不推荐)

    a.快速使用

    本节基于vue2演示 首先,使用vuecli创建项目

    vue create vue-demo

    进入项目目录后,安装tinymce-vue

    npm install --save "@tinymce/tinymce-vue@^3"

    完整使用:

    <template>
      <div id="app">
        <img alt="Vue logo" src="./assets/logo.png" />
        <HelloWorld msg="Welcome to Your Vue.js App" />
        <editor api-key="no-api-key" :init="initME" />
      </div>
    </template>
    
    <script src="http://tinymce.ax-z.cn/static/tiny/langs/zh_CN.js"></script>
    <script>
    import HelloWorld from "./components/HelloWorld.vue";
    import Editor from "@tinymce/tinymce-vue";
    
    export default {
      name: "App",
      components: {
        HelloWorld,
        Editor,
      },
      data() {
        return {
          initME: {
            height: 500,
            language: "zh_CN",
            plugins: [
              "advlist autolink lists link image charmap print preview anchor",
              "searchreplace visualblocks code fullscreen",
              "insertdatetime media table paste code help wordcount",
            ],
            toolbar:
              "undo redo | formatselect | bold italic backcolor | \
               alignleft aligncenter alignright alignjustify | \
               bullist numlist outdent indent | removeformat | help",
          },
        };
      },
      mounted() {
        tinymce.init({});
    },
    };
    </script>
    

     

    b.组件配置项

    api-key

    Tiny Cloud API 密钥。使用 Tiny Cloud 进行部署时需要提供 TinyMCE 编辑器。 默认值: no-api-key,类型:String.

    cloud-channel

    不详

    disabled

    该disabled属性可以在“禁用”(只读)模式 ( true) 和标准可编辑模式 ( false)之间动态切换编辑器。

    id

    编辑器的id.用于使用该tinymce.get('id')方法检索编辑器实例。默认为自动生成的UUID.

    init

    对象发送到tinymce.init用于初始化编辑器的方法,同配置

    initial-value

    编辑器初始化时编辑器的初始内容,与原生placeholder用法一致。

    inline

    是否开启内联模式,默认false.

    model-events

    更改要触发v-model事件的事件,默认为'change keyup'

    output-format

    用于指定通过input事件发出的内容的格式。这会影响与数据绑定一起使用的内容的格式。 默认值:html.可选择:html,text.

    plugins

    插件,同plugins.

    tag-name

    仅当inline=true时有效,用于为内联模式的编辑器定义HTML元素。

    toolbar

    工具栏,同toolbar.

    tinymce-script-src

    使用tinymce-script-srcprop 指定 TinyMCE 的外部版本以进行延迟加载,String值,例:

    <editor
      tinymce-script-src="/path/to/tinymce.min.js"
    />
    

    v-model

    指令可用于创建双向数据绑定。

    selectionChange

    事件绑定,详细请参阅:www.tiny.cloud/docs/integrations/vue/#eventbinding

    7.自定义在vue中使用(推荐)

    第一,引入,例:

    <script src="../tinymce/tinymce.min.js"></script>
    

    第二,创建div或textarea,例:

    <div id="tinymcedemo"></div>
    

    第三,tinymce初始化方法写入vue实例的methods属性,例:

    methods:{
        init(){
            window.tinymce.init({
                selector:"#tinymcedemo"
            })
        }
    }
    

    第四,挂载,例:

    mounted(){
        this.init();
    }
    

    挂载完成后,就可以使用了

     

    作者:永远十八
    链接:https://juejin.cn/post/7103019617194344485

     

    展开全文
  • tinyMCE 富文本编辑器 line-height 行高插件。 tinyMCE富文本编辑器line-height行高插件,下载后放在tinyMCE插件的plugins文件夹中,之后初始化中引入plugins,即可在toolbar中展示 tinyMCE line-height 行高插件
  • tinymce富文本使用详解

    千次阅读 2021-08-27 15:58:12
    1、不要去看tinymce的中文翻译的,可能是低版本的使用方式,最新的tinymce.init和中文班上面的存在不太一样的情况。下面介绍最简单的使用方面及遇到问题的解法。 2、在tinymce上面注册一个账号。会有这样的快速生成...

    1、不要去看tinymce的中文翻译的,可能是低版本的使用方式,最新的tinymce.init和中文班上面的存在不太一样的情况。下面介绍最简单的使用方面及遇到问题的解法。

    2、在tinymce上面注册一个账号。会有这样的快速生成的案例。

    3、直接把上面的代码copy到你的项目中就可以直接的查看效果的。

    <textarea id="tinydemo" name="content" v-model="content">
    </textarea> 

       v-model="content" 就可以回显获取的编辑器的内容

     4、获取文档编辑的内容

    const content = tinymce.activeEditor.getContent();

    5、虽然上面的已经可以很好的展示了,但是会提示一些信息。

       this domain is not registered with Tiny Cloud . Please review your approved domains

    那我们之需要到

    添加上对应的域名即可。

    除了上面的方式外我们还可以通过本地的引用js就可以了。下面是下载的方法:

     打开连接 https://www.tiny.cloud/get-tiny/self-hosted/ 出现下载的界面

     点击下载即可。

    到现在就可以去使用了

    补充:

    1、出现系统可能不会保存您所作的更改

    解决方案是把  plugins 下面的 autosave去掉

    添加汉化 

    1、此次的解决方法是参看tiny 的中文文档 

      此处添加tiny 的中文文档的截图和链接

    tiny 的中文文档

    并附上汉化包

       

    展开全文
  • TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成。它对IE6+和Firefox1.5+都有着非常良好的支持。

    相关链接tinymce (v6.0.2) - TinyMCE 是一个采用 JavaScript 编写的、轻量级的、基于浏览器的、所见即所得编辑器。 | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务TinyMCE 是一个采用 JavaScript 编写的、轻量级的、基于浏览器的、所见即所得编辑器。https://www.bootcdn.cn/tinymce/

    安装tinymce-vue

    npm install @tinymce/tinymce-vue -S

    下载tinymce

    npm install tinymce -S

    下载tinymce完成后在node_modules 中找到 tinymce目录,复制文件夹到components下面,

     

     Tinymce文件夹里index.vue里的代码如下

    <template>
      <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
        <textarea :id="tinymceId" class="tinymce-textarea" />
      </div>
    </template>
    
    <script>
    import editorImage from "./components/EditorImage";
    import plugins from "./plugins";
    import toolbar from "./toolbar";
    import load from "./dynamicLoadScript";
    
    
    // tinymceCDN地址如果请求失败可以去tinymceCDN官网上面换换其他的地址
    const tinymceCDN =
      "https://cdn.bootcdn.net/ajax/libs/tinymce/4.9.2/tinymce.min.js";
    
    export default {
      name: "Tinymce",
      components: { editorImage },
      props: {
        id: {
          type: String,
          default: function() {
            return (
              "vue-tinymce-" +
              +new Date() +
              ((Math.random() * 1000).toFixed(0) + "")
            );
          }
        },
        value: {
          type: String,
          default: ""
        },
        toolbar: {
          type: Array,
          required: false,
          default() {
            return [];
          }
        },
        menubar: {
          type: String,
          default: "file edit insert view format table"
        },
        height: {
          type: [Number, String],
          required: false,
          default: 360
        },
        width: {
          type: [Number, String],
          required: false,
          default: "auto"
        }
      },
      data() {
        return {
          hasChange: false,
          hasInit: false,
          tinymceId: this.id,
          fullscreen: false,
          languageTypeList: {
            en: "en",
            zh: "zh_CN",
            es: "es_MX",
            ja: "ja"
          }
        };
      },
      computed: {
        containerWidth() {
          const width = this.width;
          if (/^[\d]+(\.[\d]+)?$/.test(width)) {
            // matches `100`, `'100'`
            return `${width}px`;
          }
          return width;
        }
      },
      watch: {
        value(val) {
          if (!this.hasChange && this.hasInit) {
            this.$nextTick(() =>
              window.tinymce.get(this.tinymceId).setContent(val || "")
            );
          }
        }
      },
      mounted() {
        this.init();
      },
      activated() {
        if (window.tinymce) {
          this.initTinymce();
        }
      },
      deactivated() {
        this.destroyTinymce();
      },
      destroyed() {
        this.destroyTinymce();
      },
      methods: {
        init() {
          // dynamic load tinymce from cdn
          load(tinymceCDN, err => {
            if (err) {
              this.$message.error(err.message);
              return;
            }
            this.initTinymce();
          });
        },
        initTinymce() {
          const _this = this;
          window.tinymce.init({
            selector: `#${this.tinymceId}`,
            // images_upload_url: 'http://120.26.9.215:36223/api/admin/article/uploadimg',
            // en对应英文
            language: this.languageTypeList["zh"],
            height: this.height,
            body_class: "panel-body ",
            object_resizing: false,
            toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
            menubar: this.menubar,
            plugins: plugins,
            end_container_on_empty_block: true,
            powerpaste_word_import: "clean",
            code_dialog_height: 450,
            code_dialog_width: 1000,
            advlist_bullet_styles: "square",
            advlist_number_styles: "default",
            imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
            default_link_target: "_blank",
            link_title: false,
            nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
            init_instance_callback: editor => {
              if (_this.value) {
                editor.setContent(_this.value);
              }
              _this.hasInit = true;
              editor.on("NodeChange Change KeyUp SetContent", () => {
                this.hasChange = true;
                this.$emit("input", editor.getContent());
              });
            },
            setup(editor) {
              editor.on("FullscreenStateChanged", e => {
                _this.fullscreen = e.state;
              });
            },
            convert_urls: false,
            images_upload_handler: function(blobInfo, success, failure, progress) {
              var xhr, formData;
              xhr = new XMLHttpRequest();
              xhr.withCredentials = false;
    
              xhr.open(
                "POST",
                "https://www.yytlms.com:36223/api/admin/article/uploadimg"
              );
              xhr.upload.onprogress = function(e) {
                progress(e.loaded / e.total * 100);
              };
              xhr.setRequestHeader("source", 0);
              console.log(blobInfo.blob());
              xhr.onload = function() {
                var json;
                if (xhr.status === 403) {
                  failure("HTTP Error: " + xhr.status, { remove: true });
                  return;
                }
                if (xhr.status < 200 || xhr.status >= 300) {
                  failure("HTTP Error: " + xhr.status);
                  return;
                }
                json = JSON.parse(xhr.responseText);
                if (!json || typeof json.data !== "string") {
                  failure("Invalid JSON: " + xhr.responseText);
                  return;
                }
                var path_arr = json.data.split("/");
                // console.log(path_arr[path_arr.length - 1])
                success("https://www.yytlms.com/images/" + path_arr[path_arr.length - 1]);
              };
    
              xhr.onerror = function() {
                failure(
                  "Image upload failed due to a XHR Transport error. Code: " +
                    xhr.status
                );
              };
    
              formData = new FormData();
              formData.append("upload", blobInfo.blob(), blobInfo.filename());
    
              xhr.send(formData);
            }
          });
        },
        destroyTinymce() {
          const tinymce = window.tinymce.get(this.tinymceId);
          if (this.fullscreen) {
            tinymce.execCommand("mceFullScreen");
          }
    
          if (tinymce) {
            tinymce.destroy();
          }
        },
        setContent(value) {
          window.tinymce.get(this.tinymceId).setContent(value);
        },
        getContent() {
          window.tinymce.get(this.tinymceId).getContent();
        },
        imageSuccessCBK(arr) {
          arr.forEach(v =>
            window.tinymce
              .get(this.tinymceId)
              .insertContent(`<img class="wscnph" src="${v.url}" >`)
          );
        }
      }
    };
    </script>
    
    <style lang="scss" scoped>
    .tinymce-container {
      position: relative;
      line-height: normal;
    }
    
    .tinymce-container {
      ::v-deep {
        .mce-fullscreen {
          z-index: 10000;
        }
      }
    }
    
    .tinymce-textarea {
      visibility: hidden;
      z-index: -1;
    }
    
    .editor-custom-btn-container {
      position: absolute;
      right: 4px;
      top: 4px;
    }
    
    .fullscreen .editor-custom-btn-container {
      z-index: 10000;
      position: fixed;
    }
    
    .editor-upload-btn {
      display: inline-block;
    }
    </style>
    

    Tinymce文件夹下面components文件夹下方的Editorlmage.vue代码如下

    <template>
      <div class="upload-container">
        <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
          upload
        </el-button>
        <el-dialog :visible.sync="dialogVisible">
          <el-upload
            :multiple="true"
            :file-list="fileList"
            :show-file-list="true"
            :on-remove="handleRemove"
            :on-success="handleSuccess"
            :before-upload="beforeUpload"
            class="editor-slide-upload"
            action="https://httpbin.org/post"
            list-type="picture-card"
          >
            <el-button size="small" type="primary">
              Click upload
            </el-button>
          </el-upload>
          <el-button @click="dialogVisible = false">
            Cancel
          </el-button>
          <el-button type="primary" @click="handleSubmit">
            Confirm
          </el-button>
        </el-dialog>
      </div>
    </template>
    
    <script>
    
    export default {
      name: 'EditorSlideUpload',
      props: {
        color: {
          type: String,
          default: '#1890ff'
        }
      },
      data() {
        return {
          dialogVisible: false,
          listObj: {},
          fileList: []
        }
      },
      methods: {
        checkAllSuccess() {
          return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
        },
        handleSubmit() {
          const arr = Object.keys(this.listObj).map(v => this.listObj[v])
          if (!this.checkAllSuccess()) {
            this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
            return
          }
          this.$emit('successCBK', arr)
          this.listObj = {}
          this.fileList = []
          this.dialogVisible = false
        },
        handleSuccess(response, file) {
          const uid = file.uid
          const objKeyArr = Object.keys(this.listObj)
          for (let i = 0, len = objKeyArr.length; i < len; i++) {
            if (this.listObj[objKeyArr[i]].uid === uid) {
              this.listObj[objKeyArr[i]].url = response.files.file
              this.listObj[objKeyArr[i]].hasSuccess = true
              return
            }
          }
        },
        handleRemove(file) {
          const uid = file.uid
          const objKeyArr = Object.keys(this.listObj)
          for (let i = 0, len = objKeyArr.length; i < len; i++) {
            if (this.listObj[objKeyArr[i]].uid === uid) {
              delete this.listObj[objKeyArr[i]]
              return
            }
          }
        },
        beforeUpload(file) {
          const _self = this
          const _URL = window.URL || window.webkitURL
          const fileName = file.uid
          this.listObj[fileName] = {}
          return new Promise((resolve, reject) => {
            const img = new Image()
            img.src = _URL.createObjectURL(file)
            img.onload = function() {
              _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
            }
            resolve(true)
          })
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .editor-slide-upload {
      margin-bottom: 20px;
      ::v-deep .el-upload--picture-card {
        width: 100%;
      }
    }
    </style>
    

    Tinymce文件夹下方的dynamicLoadScipt.js代码如下

    let callbacks = []
    
    function loadedTinymce() {
      return window.tinymce
    }
    
    const dynamicLoadScript = (src, callback) => {
      const existingScript = document.getElementById(src)
      const cb = callback || function() {}
    
      if (!existingScript) {
        const script = document.createElement('script')
        script.src = src // src url for the third-party library being loaded.
        script.id = src
        document.body.appendChild(script)
        callbacks.push(cb)
        const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
        onEnd(script)
      }
    
      if (existingScript && cb) {
        if (loadedTinymce()) {
          cb(null, existingScript)
        } else {
          callbacks.push(cb)
        }
      }
    
      function stdOnEnd(script) {
        script.onload = function() {
          this.onerror = this.onload = null
          for (const cb of callbacks) {
            cb(null, script)
          }
          callbacks = null
        }
        script.onerror = function() {
          this.onerror = this.onload = null
          cb(new Error('Failed to load ' + src), script)
        }
      }
    
      function ieOnEnd(script) {
        script.onreadystatechange = function() {
          if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
          this.onreadystatechange = null
          for (const cb of callbacks) {
            cb(null, script) // there is no way to catch loading errors in IE8
          }
          callbacks = null
        }
      }
    }
    
    export default dynamicLoadScript
    

    Tinymce文件夹下面plugins.js代码如下

    
    
    const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
    
    export default plugins
    

    Tinymce文件夹下面toolbar.js代码如下

    
    
    const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
    
    export default toolbar
    

    在其他页面上面引用

    import Tinymce from '@/components/Tinymce'
     components: {
        Tinymce
      },
     <tinymce/>

    展开全文
  • vue中使用tinymce 其中最大的问题就是二次进入页面 富文本不会更新内容
  • tinyMCE 富文本编辑器 line-height 行高插件。...tinyMCE富文本编辑器line-height行高插件,下载后放在tinyMCE插件的plugins文件夹中,之后初始化中引入plugins,即可在toolbar中展示 tinyMCE line-height 行高插件
  • 一、Tinymce可视化编辑器 参考 https://panjiachen.gitee.io/vue-element-admin/#/components/tinymce https://panjiachen.gitee.io/vue-element-admin/#/example/create 二、组件初始化 Tinymce是一个传统...
  • 要实现根据条件判断这个富文本是否可以编辑 这里我们最开始尝试了一下:disabled=“true” 和readonly都没有用 ,刷新以后全部失效 然后google一番,并且看了官方文档都没有用哈哈哈哈哈 <div class=...
  • tinymce 富文本编辑器

    2022-03-14 15:10:33
    tinymce 富文本编辑器 简单使用,图片上传
  • tinymce富文本编辑器(vue)

    万次阅读 热门讨论 2021-08-10 09:26:54
    TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。跟其他富文本编辑器相比,有着丰富的插件,支持多种语言,能够满足日常的业务需求并且免费。 TinyMCE的优势: 开源可商用,基于LGPL2.1 插件丰富,自带...
  • vue+tinymce 富文本不显示
  • vue-tinymce富文本:在vue中使用tinymce富文本编辑器,tinymce富文本编辑器插入图片,自定义菜单按钮封装
  • tinymce富文本编辑器 安装 npm i tinymce npm install @tinymce/tinymce-vue 安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 static 或plugins 目录下 如果要使用中文版记得下载...
  • 2. 在template中添加富文本组件 <tinymce v-model="noticeForm.content" :toolbar="[ 'bold italic underline strikethrough alignleft aligncenter alignright alignjustify bullist numlist styleselect ...
  • vue使用tinymce富文本编辑器

    千次阅读 2022-02-21 14:36:36
    vue使用tinymce富文本编辑器
  • 自定义inymce富文本编辑器列表,可以通过以下几个步骤实现: 1、配置中,加入lists和advlist插件,toolbar加入有序列表numlist或者无序列表bullist。 plugins: 'lists, advlist', toolbar: 'bullist numlist' 2...
  • npm install tinymce -S npm install @packy-tang/vue-tinymce 2.把node_modules\tinymce里面的tinymce文件夹复制到public文件夹下面,并在html中引入tinymce.min.js,如下图 3.在mian.js中引入@packy-tang/...
  • Vue 项目中引入 tinymce 富文本编辑器

    千次阅读 2022-02-21 10:38:13
    在 Vue 项目中引入 tinymce 富文本编辑器 项目中原本使用的富文本编辑器是wangEditor,这是一个很轻量、简洁编辑器 但是公司的业务升级,想要一个功能更全面的编辑器,我找了好久,目前常见的编辑器有这些: ...
  • tinymce富文本框架

    2019-04-22 20:51:22
    TinyMCE-5.0.3 js引用,TinyMCE 5.0是一个功能强大且灵活的富文本编辑器,可以嵌入到用户的Web应用程序中。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,564
精华内容 1,825
关键字:

tinymce富文本

友情链接: TNMUDPEX.rar