vue 后台管理系统富文本组件(四)UEditor(集成 135 编辑器插件)

简介

135 编辑器应用于微信文章、企业网站、以及论坛等多种平台,支持秒刷、一键排版、全文配色、公众号管理、微信变量回复、48 小时群发、定时群发、云端草稿、文本校对等 40 多项功能与服务, 像拼积木一样组合排版的文章。 135 编辑器因其简单的操作,强大的功能和美观的排版深受广大用户喜爱。135 编辑器本质是基于百度 UEditor 二次开发的,因公司业务需求开发了本文组件。

本文章源码-GitHub 仓库地址

准备工作

  1. 下载 UEditor

    UEditor 官网下载链接 如图下载开发版 1.4.3.3 完整源码-点击下载
    在这里插入图片描述

    下载完成后的目录如下
    在这里插入图片描述
    其中好多文件目录我们并不需要,如下只保留这些文件。editor_api.js文件来自 _examples文件夹,_examples文件夹删除前把这个文件提取出来。
    在这里插入图片描述

  2. 基于vue-cli 3 搭建项目,主要依赖说明 (先安装,scss 和 element-ui 先配置,步骤略)

    1
    {
    2
      "axios": "^0.19.0",
    3
      "core-js": "^3.4.4",
    4
      "element-ui": "^2.13.0",
    5
      "vue": "^2.6.10",
    6
      "vue-router": "^3.1.3",
    7
      "vuex": "^3.1.2"
    8
    }
  3. vue.config.js 配置如下,( assetsDirstaticpublicPath"./"

    1
    module.exports = {
    2
      publicPath: './',
    3
      outputDir: 'dist',
    4
      assetsDir: 'static',
    5
      productionSourceMap: false,
    6
      lintOnSave: true,
    7
      devServer: {
    8
        port: 8080,
    9
        open: true,
    10
        overlay: {
    11
          warnings: true,
    12
          errors: true
    13
        }
    14
      }
    15
    }

    VueRouter 的模式改成hash模式

    1
    const router = new VueRouter({
    2
      mode: 'hash',
    3
      base: process.env.BASE_URL,
    4
      routes
    5
    })
  4. 然后在public 里新建文件夹static 把下载的ueditor文件夹整个拿过来,放到static目录下

    在这里插入图片描述

  5. 修改editor_api.js文件里的 baseURL变量

    baseURL = '../_src/' 改为 baseURL = 'static/ueditor/_src/'

  6. 添加 135 插件,添加 135 插件文档

    a. 下载
    http://www.135editor.com/js/ueditor/plugins/135editor.js

    http://www.135editor.com/js/ueditor/dialogs/135editor/135EditorDialogPage.html

    b.放置文件
    135editor.js文件放到 public/static/ueditor/_src/plugins 文件夹下

    135EditorDialogPage.html文件放到public/static/ueditor/dialogs/135editor 文件夹下 没有135editor文件夹需要新建)

    c. 修改配置文件
    在 ueditor.config.js 中 toolbars 项里增加一个 135editor 菜单项

    1
    toolbars: [ ['135editor', 'fullscreen', 'source', '|',  'undo', redo', .... ]]

    d.添加 css (在后文 src/components/UEditor/index.vue 文件里添加)

    1
    .edui-button.edui-for-135editor
    2
      .edui-button-wrap
    3
      .edui-button-body
    4
      .edui-icon {
    5
      background-image: url('http://static.135editor.com/img/icons/editor-135-icon.png') !important;
    6
      background-size: 85%;
    7
      background-position: center;
    8
      background-repeat: no-repeat;
    9
    }
  7. public/index.html 里添加文件 ueditor.config.js,editor_api.js,zh-cn.js

    1
    <!DOCTYPE html>
    2
    <html lang="en">
    3
      <head>
    4
        <meta charset="utf-8" />
    5
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    6
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    7
        <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    8
        <title>135</title>
    9
      </head>
    10
      <body>
    11
        <noscript>
    12
          <strong
    13
            >We're sorry but 135 doesn't work properly without JavaScript
    14
            enabled. Please enable it to continue.</strong
    15
          >
    16
        </noscript>
    17
        <div id="app"></div>
    18
        <!-- built files will be auto injected -->
    19
    20
        <!-- ueditor -->
    21
        <script
    22
          type="text/javascript"
    23
          src="static/ueditor/ueditor.config.js"
    24
        ></script>
    25
        <script
    26
          type="text/javascript"
    27
          src="static/ueditor/editor_api.js"
    28
        ></script>
    29
        <script
    30
          type="text/javascript"
    31
          src="static/ueditor/lang/zh-cn/zh-cn.js"
    32
        ></script>
    33
      </body>
    34
    </html>

组件

  1. 文件目录
    在这里插入图片描述

  2. 核心代码
    src/components/UEditor/index.vue

    1
    <template>
    2
      <div class="custom-ueditor-container">
    3
        <div
    4
          :id="id"
    5
          :style="{ width: width + 'px', height: height + 'px' }"
    6
        ></div>
    7
        <multiple-upload
    8
          class="custom-upload-button"
    9
          :button-style="buttonStyle"
    10
          @success="imageSuccess"
    11
        />
    12
      </div>
    13
    </template>
    14
    <script>
    15
      /* eslint-disable eqeqeq */
    16
      /* eslint-disable no-undef */
    17
      /* eslint-disable no-unused-vars */
    18
      /* eslint-disable space-in-parens */
    19
      import axios from 'axios'
    20
      import config from './config' // 配置文件见下文
    21
      import MultipleUpload from '../MultipleUpload' // MultipleUpload组件参考 https://blog.csdn.net/qq_39953537/article/details/100039094
    22
      import { uploadHtml } from '@/api/upload' // 接口根据自己后端提供的写
    23
    24
      const UE = window.UE
    25
    26
      // 设置 UEDITOR_HOME_URL
    27
      window.UEDITOR_HOME_URL = 'static/ueditor'
    28
      export default {
    29
        components: {
    30
          MultipleUpload
    31
        },
    32
        props: {
    33
          width: {
    34
            type: Number,
    35
            default: 750
    36
          },
    37
          height: {
    38
            type: Number,
    39
            default: 400
    40
          },
    41
          html: {
    42
            type: String,
    43
            default: ''
    44
          }
    45
        },
    46
        data() {
    47
          return {
    48
            ueditor: null,
    49
            buttonStyle: {
    50
              padding: '3px 6px'
    51
            }
    52
          }
    53
        },
    54
        computed: {
    55
          // 生成唯一id
    56
          id() {
    57
            const id =
    58
              Math.random().toString(36).substring(2, 15) +
    59
              '-ueditor-' +
    60
              +new Date()
    61
            return id
    62
          }
    63
        },
    64
        watch: {
    65
          html(val) {
    66
            this.loadUrl(val)
    67
          }
    68
        },
    69
        mounted() {
    70
          this.init()
    71
        },
    72
        beforeDestroy() {
    73
          this.destroyEditor()
    74
        },
    75
    76
        methods: {
    77
          // 编辑器初始化
    78
          init() {
    79
            this.ueditor = UE.getEditor(this.id, { ...config })
    80
            if (this.html) {
    81
              this.loadUrl(this.html)
    82
            }
    83
          },
    84
    85
          // 加载html内容
    86
          async loadUrl(url) {
    87
            try {
    88
              const { data } = await axios.get(url)
    89
              this.setContent(data)
    90
            } catch (error) {
    91
              this.setContent('服务器数据加载失败,请重试!')
    92
            }
    93
          },
    94
    95
          // 图片上传成功添加到编辑器
    96
          async imageSuccess(urlList) {
    97
            try {
    98
              let imageTemplateList = ''
    99
              urlList.forEach(item => {
    100
                const image = `<img style="max-width:100%;" src="${item}">`
    101
                imageTemplateList = imageTemplateList + image
    102
              })
    103
              this.inserthtml(imageTemplateList, true)
    104
              this.$message.success('上传成功!')
    105
            } catch (error) {
    106
              console.log(error)
    107
              this.$message.error(error)
    108
            }
    109
          },
    110
    111
          // 编辑器内容上传到cos,调用返回url
    112
          async content2Url() {
    113
            try {
    114
              if (!this.hasContent()) {
    115
                throw new Error('未输入内容')
    116
              }
    117
              const content = this.getContent()
    118
              const res = await uploadHtml(content)
    119
              return res
    120
            } catch (error) {
    121
              throw new Error(error)
    122
            }
    123
          },
    124
    125
          // 设置编辑器内容  isAppendTo为true时是追加内容到编辑器,false是覆盖
    126
          setContent(content, isAppendTo) {
    127
            if (!content) return
    128
            this.ueditor.ready(() => {
    129
              this.ueditor.setContent(content, isAppendTo)
    130
            })
    131
          },
    132
    133
          // 在当前光标位置插入html内容
    134
          inserthtml(content) {
    135
            if (!content) return
    136
            this.ueditor.execCommand('inserthtml', content)
    137
          },
    138
    139
          // 获取编辑器内容
    140
          getContent() {
    141
            return this.ueditor.getContent()
    142
          },
    143
    144
          // 设置编辑器聚焦
    145
          setFocus() {
    146
            this.ueditor.focus()
    147
          },
    148
    149
          // 判断编辑器是否有内容
    150
          hasContent() {
    151
            return this.ueditor.hasContents()
    152
          },
    153
    154
          // 销毁编辑器
    155
          destroyEditor() {
    156
            this.ueditor.destroy()
    157
          }
    158
        }
    159
      }
    160
    </script>
    161
    <style lang="scss" scoped>
    162
      .custom-ueditor-container {
    163
        position: relative;
    164
        color: #373737;
    165
        line-height: 22px;
    166
        .custom-upload-button {
    167
          position: absolute;
    168
          left: 650px;
    169
          top: 32px;
    170
          z-index: 99;
    171
        }
    172
      }
    173
    </style>
    174
    175
    <style>
    176
      /* 添加135编辑器插件样式 */
    177
      .edui-button.edui-for-135editor
    178
        .edui-button-wrap
    179
        .edui-button-body
    180
        .edui-icon {
    181
        background-image: url('http://static.135editor.com/img/icons/editor-135-icon.png') !important;
    182
        background-size: 85%;
    183
        background-position: center;
    184
        background-repeat: no-repeat;
    185
      }
    186
    </style>

    src/components/UEditor/config/index.js

    1
    import toolbars from './toolbars'
    2
    const config = {
    3
      toolbars,
    4
      zIndex: 99, // 编辑器层级的基数,默认是900
    5
      wordCount: false, // 是否开启字数统计
    6
      wordCountMsg: '', // 输入提示
    7
      maximumWords: Number.MAX_VALUE, // 允许的最大字符数
    8
      serverUrl: '', // 服务器统一请求接口路径
    9
      enableAutoSave: false, // 不自动保存
    10
      enableContextMenu: false, // 禁用右键
    11
      autoHeightEnabled: false, // 不自动扩展编辑器高度
    12
      elementPathEnabled: false // 不显示html元素路径
    13
    }
    14
    15
    export default config

    src/components/UEditor/config/toolbars.js

    1
    const toolbars = [
    2
      [
    3
        // 'fullscreen', // 全屏
    4
        // 'source',  // 源代码
    5
        // '|',
    6
        // 'undo',
    7
        // 'redo',
    8
        // '|',
    9
        'bold',
    10
        'italic',
    11
        'underline',
    12
        'fontborder',
    13
        'strikethrough',
    14
        'superscript',
    15
        'subscript',
    16
        'removeformat',
    17
        'formatmatch',
    18
        'autotypeset',
    19
        'blockquote',
    20
        'pasteplain',
    21
        '|',
    22
        'forecolor',
    23
        'backcolor',
    24
        // 'insertorderedlist',  // 有序
    25
        // 'insertunorderedlist', // 无序
    26
        'selectall',
    27
        'cleardoc',
    28
        '|',
    29
        'rowspacingtop',
    30
        'rowspacingbottom',
    31
        'lineheight',
    32
        '|',
    33
        // 'customstyle',
    34
        'paragraph',
    35
        // 'fontfamily',
    36
        'fontsize',
    37
        '|',
    38
        // 'directionalityltr',  // 文字方向
    39
        // 'directionalityrtl', // 文字方向
    40
        'indent',
    41
        '|',
    42
        'justifyleft',
    43
        'justifycenter',
    44
        'justifyright',
    45
        'justifyjustify',
    46
        '|',
    47
        'touppercase',
    48
        'tolowercase',
    49
        // '|',
    50
        // 'link',
    51
        // 'unlink',
    52
        // 'anchor',
    53
        '|',
    54
        'imagenone',
    55
        'imageleft',
    56
        'imageright',
    57
        'imagecenter',
    58
        '|',
    59
        // 'simpleupload',
    60
        // 'insertimage',
    61
        'emotion',
    62
        // 'scrawl', // 涂鸦
    63
        // 'insertvideo',
    64
        // 'music',
    65
        // 'attachment', // 附件
    66
        // 'map',
    67
        // 'gmap',
    68
        // 'insertframe',
    69
        // 'insertcode',
    70
        // 'webapp',
    71
        // 'pagebreak', // 分页
    72
        'template',
    73
        // 'background', // 编辑器背景
    74
        '|',
    75
        'horizontal',
    76
        'date',
    77
        'time',
    78
        'spechars',
    79
        // 'snapscreen', // 截图
    80
        // 'wordimage',
    81
        // '|',
    82
        // 'inserttable',
    83
        // 'deletetable',
    84
        // 'insertparagraphbeforetable',
    85
        // 'insertrow',
    86
        // 'deleterow',
    87
        // 'insertcol',
    88
        // 'deletecol',
    89
        // 'mergecells',
    90
        // 'mergeright',
    91
        // 'mergedown',
    92
        // 'splittocells',
    93
        // 'splittorows',
    94
        // 'splittocols',
    95
        // 'charts',
    96
        '|',
    97
        // 'print',
    98
        // 'preview',
    99
        'searchreplace'
    100
        // 'help',
    101
        // 'drafts'
    102
      ]
    103
    ]
    104
    105
    export default toolbars
  3. 使用

    1
    <template>
    2
      <div class="demo">
    3
        <u-editor ref="editor" :height="500" :html="html" @input="getContent" />
    4
        <div class="get-url-btn-warpper">
    5
          <el-button type="primary" size="small" @click="getContentUrl">
    6
            获取上传后的链接
    7
          </el-button>
    8
        </div>
    9
      </div>
    10
    </template>
    11
    12
    <script>
    13
      import UEditor from '@/components/UEditor'
    14
      export default {
    15
        name: 'UEditorDemo',
    16
        components: {
    17
          UEditor
    18
        },
    19
        data() {
    20
          return {
    21
            html: '',
    22
            content: ''
    23
          }
    24
        },
    25
        methods: {
    26
          // 获取商品详情编辑器内容
    27
          getContent(content) {
    28
            this.content = content
    29
          },
    30
          // 获取上传后的链接
    31
          async getContentUrl() {
    32
            try {
    33
              const url = await this.$refs.editor.content2Url()
    34
              console.log(url)
    35
            } catch (error) {
    36
              this.$message.warning(error.message)
    37
            }
    38
          }
    39
        }
    40
      }
    41
    </script>
    42
    43
    <style lang="scss">
    44
      .demo {
    45
        margin: 50px;
    46
      }
    47
      .get-url-btn-warpper {
    48
        margin-top: 10px;
    49
      }
    50
    </style>
  4. 使用效果
    在这里插入图片描述
    在这里插入图片描述

    参考链接

    1. http://www.135plat.com/135_ueditor_plugin.html
    2. http://fex.baidu.com/ueditor/
    3. http://ueditor.baidu.com/doc/