1、安装 wangEditor
npm 安装npm i wangeditor --save
注:wangeditor 全小写
package.json 文件
"wangeditor": "^4.7.11"
2-1、封装 wangEditor 组件(wangEditor.vue)
src / components / wangEditor / index.vue
<!-- 组件功能:wangEditor 富文本编辑器 -->
<template lang="html">
<div class="editor">
<div ref="toolbar" class="toolbar">
<div ref="editor" class="text">
import E from "wangeditor";
import fileMenu from "./fileMenu";
export default {
name:"editoritem",
data() {
return {
editor:"",
info_:null,
};
},
model: {
prop:"value",
event:"change",
},
props: {
value: {
type:String,
default:"",
},
isClear: {
type:Boolean,
default:false,
},
quTitle: {
type:String,
default:"",
},
},
watch: {
isClear(val) {
// 触发清除文本域内容
if (val) {
this.editor.txt.clear();
this.info_ =null;
}
},
value:function (value) {
if (value !==this.editor.txt.html()) {
this.editor.txt.html(this.value);
}
},
// value 为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
},
mounted() {
this.seteditor();
this.editor.txt.html(this.quTitle);
// this.editor.unFullScreen()
},
methods: {
seteditor() {
// http://192.168.2.125:8080/admin/storage/create
this.editor =new E(this.$refs.toolbar, this.$refs.editor);
this.editor.config.uploadImgShowBase64 =false; // base 64 存储图片
// this.editor.config.uploadImgServer = 'http://baidu.com' // 配置服务器地址, 这个是处理图片上传问题的
// this.editor.config.uploadImgServer = Settings.apiUrl + "/api/CoreService/File/UploadFile"; // 配置服务器端地址
this.editor.config.uploadImgHeaders = {}; // 自定义header
this.editor.config.uploadFileName ="file"; // 后端接受上传文件的参数名
this.editor.config.uploadImgMaxSize =6 *1024 *1024; // 将图片大小限制为6M
this.editor.config.uploadImgMaxLength =6; // 限制一次最多上传 6 张图片
this.editor.config.uploadImgTimeout =3 *60 *1000; // 设置超时时间
// 配置菜单
this.editor.config.menus = [
"head", // 标题
"bold", // 粗体
"fontSize", // 字号
"fontName", // 字体
"italic", // 斜体
"underline", // 下划线
"strikeThrough", // 删除线
"foreColor", // 文字颜色
"backColor", // 背景颜色
"link", // 插入链接
"list", // 列表
"justify", // 对齐方式
"quote", // 引用
"emoticon", // 表情
"image", // 插入图片
"emoticon", // 插入表情
"table", // 表格
"video", // 插入视频
"code", // 插入代码
"undo", // 撤销
"redo", // 重复
"fullscreen", // 全屏
// 附件 , 多图上传
];
// 加上以下代码, 上传视频的 tab 和图标显示出来
this.editor.config.uploadVideoServer ="/api/upload-video";
this.editor.config.showFullScreen =true;
this.editor.config.showLinkImg =false; // 隐藏网络图片的tab
this.editor.config.showLinkImgAlt =false; // 配置 alt 选项
this.editor.config.showLinkImgHref =false; // 配置超链接
// this.editor.fullScreen()
// this.editor.unFullScreen()
// 上传图片
this.editor.config.uploadImgHooks = {
fail: (xhr, editor, result) => {
// 插入图片失败回调
},
success: (xhr, editor, result) => {
// 图片上传成功回调
if (result.assertion) {
console.log(result.message);
}
},
timeout: (xhr, editor) => {
// 网络超时的回调
},
error: (xhr, editor) => {
// 图片上传错误的回调
},
customInsert: (insertImg, result, editor) => {
// 图片上传成功,插入图片的回调
// result: 上传图片成功时返回的数据,打印返回格式是: data:[{url:"路径的形式"},...]
// console.log(result.data[0].url)
// insertImg()为插入图片的函数
// 循环插入图片
const {code, data, msg } =result;
if (code ==0) {
insertImg("/CMMS" +data.image_url);
}else {
message.error(msg);
}
// let url = "http://otp.cdinfotech" + result.url;
// let url = Settings.apiUrl + ":1889/" + result.objectEntity;
// insertImg(url);
},
};
// 自己实现上传图片
this.editor.config.customUploadImg =function (files, insert) {
console.log(files, "files-----------");
// files 是 input 中选中的文件列表
// insert 是获取图片 url 后 , 插入到编辑器的方法
// let formData = new FormData()
// for (let i = 0; i < files.length; i++) {
// formData.append('file', files[i], files[i].name) // 多张图片放进一个formData
// }
// insert(imgUrl)
};
// 上传视频 server接口返回格式, 很重要!
// 接口返回 application/json 格式, 格式要求如下:
/*
{
// error 即错误代码, 0: 表示没有错误 // 如果有错误, error != 0, 可通过下文中的监听函数 fail 拿到该错误进行自定义处理"error": 0
// data 是一个对象, 返回视频的线上地址"data": {
"url": "视频1地址"
}
}
*/
this.editor.config.onchange = (html) => {
let data =this.editor.txt.getJSon;
console.log(data, "data---------");
this.info_ =html; // 绑定当前逐渐地值
this.$emit("change", this.info_); // 将内容同步到父组件中
};
this.editor.config.onchangeTimeout =500; // 修改为500ms
// 用户选取操作自动触发
this.editor.config.onSelectionChange = (newSelection) => {
console.log("onSelectionChange", newSelection);
};
// 创建富文本编辑器
this.editor.create();
fileMenu(this.editor, this.$refs.toolbar);
},
openFileAlert(value) {
this.showEnclosureAlert =value;
},
// 保存
advancedSave() {
console.log("附件保存");
},
},
};
<style lang="css">
.editor {
width:100%;
margin:0 auto;
position:relative;
z-index:0;
}
.toolbar {
border:1px solid #ccc;
}
.text {
border:1px solid #ccc;
min-height:500px;
}
</style>
this.editor.customConfig.uploadImgServer = Settings.apiUrl + ‘/api/CoreService/File/UploadFile’ // 配置服务器端地址,这个是处理图片上传问题的
2-2、封装 wangEditor 组件(wangEditor.vue)
src / components / wangEditor / fileMenu.js
/**
* editor: wangEditor 的实例
* editorSelector: wangEditor 挂载点的节点
* options: 一些配置
*/
import uploadFile from "./uploadFile";
import vue from "vue";
export default (editor, editorSelector, options) => {
editor.fileMenu = {
init: function (editor, editorSelector) {
const div = document.createElement("div");
div.className = "w-e-toolbar w-e-menu";
div.style.zIndex = 10001;
div.setAttribute("data-title", "附件");
const rdn = new Date().getTime();
div.onclick = function (e) {
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
// document.getElementById(`up-${rdn}`).click()
};
const input = document.createElement("input");
input.type = "file";
input.name = "file";
input.id = `up-${rdn}`;
input.className = "upload-file-input";
// <i class="el-icon-folder-add" style="margin-left:260px"></i> <span class="upload-file-span" style="margin-left:260px;">附件</span>
div.innerHTML = `<i class="el-icon-folder-add"></i>`;
div.appendChild(input);
editorSelector.getElementsByClassName("w-e-toolbar")[0].appendChild(div);
input.onchange = (e) => {
// console.log(e, 'change')
console.log(e.target.files[0], "files");
// 使用 uploadFile 上传文件
// uploadFile(e.target.files, {
// onOk: (data) => {
// console.log(data);
// // 可以使用 editor.txt.html(data) 进行更新
// },
// onFail: (err) => {
// console.log(err);
// },
// onprogress: (percent) => {
// console.log(percent);
// },
// });
};
},
};
// 创建完之后立即实例化
editor.fileMenu.init(editor, editorSelector);
};
2-3、封装 wangEditor 组件(wangEditor.vue)
src / components / wangEditor / uploadFile.js
import { message } from "element-ui";
function uploadFile(files, options) {
if (!files || !files.length) {
return;
}
let uploadFileServer = commonApi.imgUploadApi; // 文件上传地址
const maxSize = 100 * 1024 * 1024; // 100M
const maxSizeM = maxSize / 1000 / 1000;
const maxLength = 1;
const uploadFileName = "file";
const uploadFileParams = {};
const uploadFileParamsWithUrl = {};
const timeout = 5 * 60 * 1000; // 5 min
// ---------------------- 验证文件信息 ---------------------------
const resultFiles = [];
const errInfo = [];
for (let file of files) {
const name = file.name;
const size = file.size;
// chrome 低版本 name ===== undefined
if (!name || !size) return;
if (maxSize < size) {
// 上传附件过大
errInfo.push("\u3010" + name + "\u3011\u5927\u4E8E" + maxSizeM + "M");
return;
}
// 验证通过的加入结果列表
resultFiles.push(file);
}
// 抛出验证信息
if (errInfo.length) {
this._alert("附件验证未通过, \n" + errInfo.join("\n"));
return;
}
if (resultFiles.length > maxLength) {
this._alert("一次最多上传" + maxLength + "个文件");
return;
}
// ----------------------- 自定义上传 ----------------------
const formdata = new FormData();
for (let file of resultFiles) {
const name = uploadFileName || file.name;
formdata.append(name, file);
}
// ----------------------- 上传附件 -------------------------
if (uploadFileServer && typeof uploadFileServer === "string") {
for (key in uploadFileParams) {
val = encodeURIComponent(uploadFileParams[val]);
formdata.append(key, val);
}
}
// 定义 xhr
const xhr = new XMLHttpRequest();
xhr.open("POST", uploadFileServer);
// 设置超时
xhr.timeout = timeout;
xhr.ontimeout = function () {
if (options.timeout && typeof options.timeout === "function") {
options.timeout(xhr, editor);
}
message.error("上传附件超时");
};
// 监控 progress
if (xhr.upload) {
xhr.upload.onprogress = function (e) {
let percent = void 0;
// 进度条
if (e.lengthComputable) {
percent = e.loaded / e.total;
if (options.onprogress && typeof options.onprogress === "function") {
options.onprogress(percent);
}
}
};
}
// 返回数据
xhr.onreadystatechange = function () {
let result = void 0;
if (xhr.status < 200 || xhr.status >= 300) {
if (options.onFail && typeof options.onprogress === "function") {
options.onFail(xhr, editor);
}
return;
}
result = xhr.responseText;
if (
(typeof result === "undefined" ? "undefined" : typeof result) !== "object"
) {
try {
result = JSON.parse(result);
} catch (ex) {
if (options.onFail && typeof options.onFail === "function") {
options.onFail(xhr, editor, result);
}
return;
}
}
const data = result || [];
if (data.code == 0) {
options.onOk && options.onOk(data.data);
}
};
// 自定义 headers
for (let key in uploadFileHeaders) {
xhr.setRequestHeader(key, uploadFileHeaders[key]);
}
// 跨域传 token
xhr.widthCredentials = false;
// 发送请求
xhr.send(formdata);
}
export default uploadFile;
3、导入并引用组件
src / views / edit / components / parameter.vue
<template>
<div>
<editorBar
:isClear="isClear"
:quTitle="titleName"
@change="editorTitleChange"
></editorBar>
</div>
</template>
<script>
import editorBar from "../../../components/wangEditor/index.vue";
export default {
components: {
editorBar, // 注册 富文本编辑器 组件
},
data() {
return {
isClear: false,
titleName: "", // 标题
tempTitle: "",
};
},
methods: {
// 标题高级编辑器change事件
editorTitleChange(val) {
this.tempTitle = val;
},
},
};
</script>