vue 后台管理系统富文本组件(四)UEditor(集成 135 编辑器插件)
简介
135 编辑器应用于微信文章、企业网站、以及论坛等多种平台,支持秒刷、一键排版、全文配色、公众号管理、微信变量回复、48 小时群发、定时群发、云端草稿、文本校对等 40 多项功能与服务, 像拼积木一样组合排版的文章。 135 编辑器因其简单的操作,强大的功能和美观的排版深受广大用户喜爱。135 编辑器本质是基于百度 UEditor 二次开发的,因公司业务需求开发了本文组件。
准备工作
-
下载 UEditor
UEditor 官网下载链接 如图下载开发版 1.4.3.3 完整源码-点击下载
下载完成后的目录如下
其中好多文件目录我们并不需要,如下只保留这些文件。editor_api.js
文件来自_examples
文件夹,_examples
文件夹删除前把这个文件提取出来。
-
基于
vue-cli 3
搭建项目,主要依赖说明 (先安装,scss和element-ui先配置,步骤略){ "axios": "^0.19.0", "core-js": "^3.4.4", "element-ui": "^2.13.0", "vue": "^2.6.10", "vue-router": "^3.1.3", "vuex": "^3.1.2" }
-
vue.config.js
配置如下,(assetsDir
是static
,publicPath
是"./"
)module.exports = { publicPath: "./", outputDir: "dist", assetsDir: "static", productionSourceMap: false, lintOnSave: true, devServer: { port: 8080, open: true, overlay: { warnings: true, errors: true } } };
VueRouter
的模式改成hash
模式const router = new VueRouter({ mode: 'hash', base: process.env.BASE_URL, routes })
-
然后在
public
里新建文件夹static
把下载的ueditor
文件夹整个拿过来,放到static
目录下 -
修改
editor_api.js
文件里的baseURL
变量baseURL = '../_src/'
改为baseURL = 'static/ueditor/_src/'
-
添加 135 插件,添加 135 插件文档
a. 下载
http://www.135editor.com/js/ueditor/plugins/135editor.jshttp://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 菜单项toolbars: [ ['135editor', 'fullscreen', 'source', '|', 'undo', redo', .... ]]
d.添加 css (在后文 src/components/UEditor/index.vue 文件里添加)
.edui-button.edui-for-135editor .edui-button-wrap .edui-button-body .edui-icon { background-image: url("http://static.135editor.com/img/icons/editor-135-icon.png") !important; background-size: 85%; background-position: center; background-repeat: no-repeat; }
-
public/index.html 里添加文件 ueditor.config.js,editor_api.js,zh-cn.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width,initial-scale=1.0" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico" /> <title>135</title> </head> <body> <noscript> <strong >We're sorry but 135 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong > </noscript> <div id="app"></div> <!-- built files will be auto injected --> <!-- ueditor --> <script type="text/javascript" src="static/ueditor/ueditor.config.js" ></script> <script type="text/javascript" src="static/ueditor/editor_api.js" ></script> <script type="text/javascript" src="static/ueditor/lang/zh-cn/zh-cn.js" ></script> </body> </html>
组件
-
文件目录
-
核心代码
src/components/UEditor/index.vue<template> <div class="custom-ueditor-container"> <div :id="id" :style="{ width: width + 'px', height: height + 'px' }" ></div> <multiple-upload class="custom-upload-button" :button-style="buttonStyle" @success="imageSuccess" /> </div> </template> <script> /* eslint-disable eqeqeq */ /* eslint-disable no-undef */ /* eslint-disable no-unused-vars */ /* eslint-disable space-in-parens */ import axios from "axios"; import config from "./config"; // 配置文件见下文 import MultipleUpload from "../MultipleUpload"; // MultipleUpload组件参考 https://blog.csdn.net/qq_39953537/article/details/100039094 import { uploadHtml } from "@/api/upload"; // 接口根据自己后端提供的写 const UE = window.UE; // 设置 UEDITOR_HOME_URL window.UEDITOR_HOME_URL = "static/ueditor"; export default { components: { MultipleUpload }, props: { width: { type: Number, default: 750 }, height: { type: Number, default: 400 }, html: { type: String, default: "" } }, data() { return { ueditor: null, buttonStyle: { padding: "3px 6px" } }; }, computed: { // 生成唯一id id() { const id = Math.random() .toString(36) .substring(2, 15) + "-ueditor-" + +new Date(); return id; } }, watch: { html(val) { this.loadUrl(val); } }, mounted() { this.init(); }, beforeDestroy() { this.destroyEditor(); }, methods: { // 编辑器初始化 init() { this.ueditor = UE.getEditor(this.id, { ...config }); if (this.html) { this.loadUrl(this.html); } }, // 加载html内容 async loadUrl(url) { try { const { data } = await axios.get(url); this.setContent(data); } catch (error) { this.setContent("服务器数据加载失败,请重试!"); } }, // 图片上传成功添加到编辑器 async imageSuccess(urlList) { try { let imageTemplateList = ""; urlList.forEach(item => { const image = `<img style="max-width:100%;" src="${item}">`; imageTemplateList = imageTemplateList + image; }); this.inserthtml(imageTemplateList, true); this.$message.success("上传成功!"); } catch (error) { console.log(error); this.$message.error(error); } }, // 编辑器内容上传到cos,调用返回url async content2Url() { try { if (!this.hasContent()) { throw new Error("未输入内容"); } const content = this.getContent(); const res = await uploadHtml(content); return res; } catch (error) { throw new Error(error); } }, // 设置编辑器内容 isAppendTo为true时是追加内容到编辑器,false是覆盖 setContent(content, isAppendTo) { if (!content) return; this.ueditor.ready(() => { this.ueditor.setContent(content, isAppendTo); }); }, // 在当前光标位置插入html内容 inserthtml(content) { if (!content) return; this.ueditor.execCommand("inserthtml", content); }, // 获取编辑器内容 getContent() { return this.ueditor.getContent(); }, // 设置编辑器聚焦 setFocus() { this.ueditor.focus(); }, // 判断编辑器是否有内容 hasContent() { return this.ueditor.hasContents(); }, // 销毁编辑器 destroyEditor() { this.ueditor.destroy(); } } }; </script> <style lang="scss" scoped> .custom-ueditor-container { position: relative; color: #373737; line-height: 22px; .custom-upload-button { position: absolute; left: 650px; top: 32px; z-index: 99; } } </style> <style> /* 添加135编辑器插件样式 */ .edui-button.edui-for-135editor .edui-button-wrap .edui-button-body .edui-icon { background-image: url("http://static.135editor.com/img/icons/editor-135-icon.png") !important; background-size: 85%; background-position: center; background-repeat: no-repeat; } </style>
src/components/UEditor/config/index.js
import toolbars from "./toolbars"; const config = { toolbars, zIndex: 99, // 编辑器层级的基数,默认是900 wordCount: false, // 是否开启字数统计 wordCountMsg: "", // 输入提示 maximumWords: Number.MAX_VALUE, // 允许的最大字符数 serverUrl: "", // 服务器统一请求接口路径 enableAutoSave: false, // 不自动保存 enableContextMenu: false, // 禁用右键 autoHeightEnabled: false, // 不自动扩展编辑器高度 elementPathEnabled: false // 不显示html元素路径 }; export default config;
src/components/UEditor/config/toolbars.js
const toolbars = [ [ // 'fullscreen', // 全屏 // 'source', // 源代码 // '|', // 'undo', // 'redo', // '|', "bold", "italic", "underline", "fontborder", "strikethrough", "superscript", "subscript", "removeformat", "formatmatch", "autotypeset", "blockquote", "pasteplain", "|", "forecolor", "backcolor", // 'insertorderedlist', // 有序 // 'insertunorderedlist', // 无序 "selectall", "cleardoc", "|", "rowspacingtop", "rowspacingbottom", "lineheight", "|", // 'customstyle', "paragraph", // 'fontfamily', "fontsize", "|", // 'directionalityltr', // 文字方向 // 'directionalityrtl', // 文字方向 "indent", "|", "justifyleft", "justifycenter", "justifyright", "justifyjustify", "|", "touppercase", "tolowercase", // '|', // 'link', // 'unlink', // 'anchor', "|", "imagenone", "imageleft", "imageright", "imagecenter", "|", // 'simpleupload', // 'insertimage', "emotion", // 'scrawl', // 涂鸦 // 'insertvideo', // 'music', // 'attachment', // 附件 // 'map', // 'gmap', // 'insertframe', // 'insertcode', // 'webapp', // 'pagebreak', // 分页 "template", // 'background', // 编辑器背景 "|", "horizontal", "date", "time", "spechars", // 'snapscreen', // 截图 // 'wordimage', // '|', // 'inserttable', // 'deletetable', // 'insertparagraphbeforetable', // 'insertrow', // 'deleterow', // 'insertcol', // 'deletecol', // 'mergecells', // 'mergeright', // 'mergedown', // 'splittocells', // 'splittorows', // 'splittocols', // 'charts', "|", // 'print', // 'preview', "searchreplace" // 'help', // 'drafts' ] ]; export default toolbars;
-
使用
<template> <div class="demo"> <u-editor ref="editor" :height="500" :html="html" @input="getContent" /> <div class="get-url-btn-warpper"> <el-button type="primary" size="small" @click="getContentUrl"> 获取上传后的链接 </el-button> </div> </div> </template> <script> import UEditor from '@/components/UEditor' export default { name: 'UEditorDemo', components: { UEditor }, data() { return { html: '', content: '' } }, methods: { // 获取商品详情编辑器内容 getContent(content) { this.content = content }, // 获取上传后的链接 async getContentUrl() { try { const url = await this.$refs.editor.content2Url() console.log(url) } catch (error) { this.$message.warning(error.message) } } } } </script> <style lang="scss"> .demo { margin: 50px; } .get-url-btn-warpper { margin-top: 10px; } </style>
-
使用效果
参考链接