2021-05-13 10:56:04 +08:00
|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<div style="position:relative">
|
|
|
|
<div :id="id" style="text-align: left;width:850px"></div>
|
|
|
|
<div v-if="showExpand">
|
|
|
|
<div class="e-menu e-code" @click="editHTML">
|
|
|
|
<Icon type="md-code-working" size="22" />
|
|
|
|
</div>
|
|
|
|
<div class="e-menu e-preview" @click="fullscreenModal=true">
|
|
|
|
<Icon type="ios-eye" size="24" />
|
|
|
|
</div>
|
|
|
|
<div class="e-menu e-trash" @click="clear">
|
|
|
|
<Icon type="md-trash" size="18" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2021-06-10 18:31:54 +08:00
|
|
|
<Modal title="编辑html代码" v-model="showHTMLModal" :mask-closable="false" :width="900" :fullscreen="full">
|
|
|
|
<Input v-if="!full" v-model="dataEdit" :rows="15" type="textarea" style="max-height:60vh;overflow:auto;" />
|
2021-05-13 10:56:04 +08:00
|
|
|
<Input v-if="full" v-model="dataEdit" :rows="32" type="textarea" />
|
|
|
|
<div slot="footer">
|
|
|
|
<Button @click="full=!full" icon="md-expand">全屏开/关</Button>
|
|
|
|
<Button @click="editHTMLOk" type="primary" icon="md-checkmark-circle-outline">确定保存</Button>
|
|
|
|
</div>
|
|
|
|
</Modal>
|
|
|
|
<Modal title="预览" v-model="fullscreenModal" fullscreen>
|
|
|
|
<div v-html="data">{{data}}</div>
|
|
|
|
<div slot="footer">
|
|
|
|
<Button @click="fullscreenModal=false">关闭</Button>
|
|
|
|
</div>
|
|
|
|
</Modal>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import { uploadFile } from "@/api/index";
|
|
|
|
import E from "wangeditor";
|
|
|
|
import xss from "xss";
|
|
|
|
// 表情包配置 自定义表情可在该js文件中统一修改
|
|
|
|
import { sina } from "@/libs/emoji";
|
|
|
|
var editor = null;
|
|
|
|
export default {
|
|
|
|
name: "editor",
|
|
|
|
props: {
|
|
|
|
id: {
|
|
|
|
type: String,
|
2021-06-10 18:31:54 +08:00
|
|
|
default: "editor",
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
value: String,
|
|
|
|
base64: {
|
|
|
|
type: Boolean,
|
2021-06-10 18:31:54 +08:00
|
|
|
default: false,
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
showExpand: {
|
|
|
|
type: Boolean,
|
2021-06-10 18:31:54 +08:00
|
|
|
default: true,
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
openXss: {
|
|
|
|
type: Boolean,
|
2021-06-10 18:31:54 +08:00
|
|
|
default: false,
|
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
2021-05-13 18:09:36 +08:00
|
|
|
editor: null, // 富文本编辑器初始化
|
2021-05-13 10:56:04 +08:00
|
|
|
data: this.value, // 富文本数据
|
|
|
|
dataEdit: "", // 编辑数据
|
|
|
|
showHTMLModal: false, // 显示html
|
|
|
|
full: false, // html全屏开关
|
2021-06-10 18:31:54 +08:00
|
|
|
fullscreenModal: false, // 显示全屏预览
|
2021-05-13 10:56:04 +08:00
|
|
|
};
|
|
|
|
},
|
|
|
|
methods: {
|
2021-06-10 18:31:54 +08:00
|
|
|
|
2021-05-13 10:56:04 +08:00
|
|
|
initEditor() {
|
|
|
|
let that = this;
|
|
|
|
// 详见wangeditor3官网文档 https://www.kancloud.cn/wangfupeng/wangeditor3/332599
|
|
|
|
editor = new E(`#${this.id}`);
|
|
|
|
// 编辑内容绑定数据
|
2021-06-10 18:31:54 +08:00
|
|
|
editor.config.onchange = (html) => {
|
2021-05-13 10:56:04 +08:00
|
|
|
if (this.openXss) {
|
|
|
|
this.data = xss(html);
|
|
|
|
} else {
|
|
|
|
this.data = html;
|
|
|
|
}
|
|
|
|
this.$emit("input", this.data);
|
|
|
|
this.$emit("on-change", this.data);
|
|
|
|
};
|
|
|
|
editor.config.showFullScreen = false;
|
|
|
|
// z-index
|
|
|
|
editor.config.zIndex = 100;
|
|
|
|
if (this.base64) {
|
|
|
|
// 使用 base64 保存图片
|
|
|
|
editor.config.uploadImgShowBase64 = true;
|
|
|
|
} else {
|
|
|
|
// 配置上传图片服务器端地址
|
|
|
|
editor.config.uploadImgServer = uploadFile;
|
|
|
|
// lili如要header中传入token鉴权
|
|
|
|
editor.config.uploadImgHeaders = {
|
2021-06-10 18:31:54 +08:00
|
|
|
accessToken: that.getStore("accessToken"),
|
2021-05-13 10:56:04 +08:00
|
|
|
};
|
|
|
|
editor.config.uploadFileName = "file";
|
|
|
|
editor.config.uploadImgHooks = {
|
2021-06-10 18:31:54 +08:00
|
|
|
before: function (xhr, editor, files) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// 图片上传之前触发
|
|
|
|
},
|
2021-06-10 18:31:54 +08:00
|
|
|
success: function (xhr, editor, result) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// 图片上传并返回结果,图片插入成功之后触发
|
|
|
|
},
|
2021-06-10 18:31:54 +08:00
|
|
|
fail: function (xhr, editor, result) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// 图片上传并返回结果,但图片插入错误时触发
|
|
|
|
that.$Message.error("上传图片失败");
|
|
|
|
},
|
2021-06-10 18:31:54 +08:00
|
|
|
error: function (xhr, editor) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// 图片上传出错时触发
|
|
|
|
that.$Message.error("上传图片出错");
|
|
|
|
},
|
2021-06-10 18:31:54 +08:00
|
|
|
timeout: function (xhr, editor) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// 图片上传超时时触发
|
|
|
|
that.$Message.error("上传图片超时");
|
|
|
|
},
|
|
|
|
// 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
|
2021-06-10 18:31:54 +08:00
|
|
|
customInsert: function (insertImg, result, editor) {
|
2021-05-13 10:56:04 +08:00
|
|
|
if (result.success == true) {
|
2021-07-02 14:26:01 +08:00
|
|
|
console.log(insertImg,result,editor);
|
2021-05-13 10:56:04 +08:00
|
|
|
let url = result.result;
|
|
|
|
insertImg(url);
|
|
|
|
that.$Message.success("上传图片成功");
|
|
|
|
} else {
|
|
|
|
that.$Message.error(result.message);
|
|
|
|
}
|
2021-06-10 18:31:54 +08:00
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
};
|
|
|
|
}
|
2021-06-10 18:31:54 +08:00
|
|
|
|
|
|
|
editor.config.customAlert = function (info) {
|
2021-05-13 10:56:04 +08:00
|
|
|
// info 是需要提示的内容
|
|
|
|
// that.$Message.info(info);
|
|
|
|
};
|
|
|
|
// 字体
|
|
|
|
editor.config.fontNames = ["微软雅黑", "宋体", "黑体", "Arial"];
|
|
|
|
// 表情面板可以有多个 tab ,因此要配置成一个数组。数组每个元素代表一个 tab 的配置
|
|
|
|
editor.config.emotions = [
|
|
|
|
{
|
|
|
|
// tab 的标题
|
|
|
|
title: "新浪",
|
|
|
|
// type -> 'emoji' / 'image'
|
|
|
|
type: "image",
|
|
|
|
// content -> 数组
|
2021-06-10 18:31:54 +08:00
|
|
|
content: sina,
|
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
];
|
|
|
|
editor.create();
|
|
|
|
if (this.value) {
|
|
|
|
if (this.openXss) {
|
|
|
|
editor.txt.html(xss(this.value));
|
|
|
|
} else {
|
|
|
|
editor.txt.html(this.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
editHTML() {
|
|
|
|
this.dataEdit = this.data;
|
|
|
|
this.showHTMLModal = true;
|
|
|
|
},
|
|
|
|
editHTMLOk() {
|
|
|
|
editor.txt.html(this.dataEdit);
|
|
|
|
this.$emit("input", this.data);
|
|
|
|
this.$emit("on-change", this.data);
|
|
|
|
this.showHTMLModal = false;
|
|
|
|
},
|
|
|
|
clear() {
|
|
|
|
this.$Modal.confirm({
|
|
|
|
title: "确认清空",
|
|
|
|
content: "确认要清空编辑器内容?清空后不能撤回",
|
|
|
|
onOk: () => {
|
|
|
|
this.data = "";
|
|
|
|
editor.txt.html(this.data);
|
|
|
|
this.$emit("input", this.data);
|
|
|
|
this.$emit("on-change", this.data);
|
2021-06-10 18:31:54 +08:00
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
});
|
|
|
|
},
|
|
|
|
setData(value) {
|
|
|
|
if (!editor) {
|
|
|
|
this.initEditor();
|
|
|
|
}
|
|
|
|
if (value && value != this.data) {
|
|
|
|
this.data = value;
|
|
|
|
editor.txt.html(this.data);
|
|
|
|
this.$emit("input", this.data);
|
|
|
|
this.$emit("on-change", this.data);
|
|
|
|
}
|
2021-06-10 18:31:54 +08:00
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
value(val) {
|
|
|
|
this.setData(val);
|
2021-06-10 18:31:54 +08:00
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
this.initEditor();
|
2021-06-10 18:31:54 +08:00
|
|
|
},
|
2021-05-13 10:56:04 +08:00
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.e-menu {
|
|
|
|
z-index: 101;
|
|
|
|
position: absolute;
|
|
|
|
cursor: pointer;
|
|
|
|
color: #999;
|
|
|
|
:hover {
|
|
|
|
color: #333;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.e-code {
|
|
|
|
top: 6px;
|
|
|
|
left: 818px;
|
|
|
|
}
|
|
|
|
.e-preview {
|
|
|
|
top: 46px;
|
|
|
|
left: 174px;
|
|
|
|
}
|
|
|
|
.e-trash {
|
|
|
|
top: 46px;
|
|
|
|
left: 215px;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|