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