1、需求:商家可上传平台规则(规则内容包含图片且可以放大伸缩、文件上传至服务器、可插入表格、插入代码等数据、数据不保存时可以直接预览、预览后直接发布也可以保存富文本编辑器中的内容,保存后数据展示在列表中再进行发布)
2、难点:
(1)因为上传图片时是base64位的,这样会导致数据量大,上传图片超过5张并且W数过大的话会导致服务器承受不住压力从而造成页面卡顿。
(2)插入表格后富文本编辑器中表格样式显示正常,但是预览时表格样式会失效。此时需要自定义表格样式。
(3)因为预览时数据还没有保存,此时需要先把富文本中输入的数据本地保存缓存下来。在预览页面再去取。
3、解决方式
(1)将图片上传至服务器,拿到图片的oss返回给后端,这样上传的数据量会小很多从而减轻服务器的压力。
(2)预览时表格的样式丢失,此时需要用深度选择器去修改。具体可以看以下代码。
(3)将富文本中的数据在点击预览按钮时用localStorage缓存下来,然后在预览的页面去取。
4、完整代码
!!! 力荐wangEditor 5编辑器
轻量级框架,容易修改,附上链接 wangEditor
编辑富文本页面
<template>
<div class="rolseList">
<div class="rules-content">
<el-form-item label="规则内容" prop="content" required>
<div style="border: 1px solid #ccc;">
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode"/>
<Editor style="height: 460px; overflow-y: hidden;" v-model="formData.content" :defaultConfig="editorConfig" :mode="mode"
@onCreated="onCreated" @onChange="onChange"/>
</div>
</el-form-item>
<el-form-item class="oprition-btn">
<el-button type="primary" @click="submitForm(formData)">保存</el-button>
<el-button @click="preview(formData.content)">预览</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import '@wangeditor/editor/dist/css/style.css'
export default {
components: {
Editor, Toolbar
},
data() {
return {
//富文本编辑器相关配置
editor: null,
toolbarConfig: {
excludeKeys : [
'group-video', //禁止上传视频,此时将上传视频的图标隐藏掉
'fullScreen',//隐藏全屏
// 'group-indent', //隐藏缩进按钮
// 'indent',//向前缩进
'codeBlock',//隐藏代码块
// 'viewImageLink',//隐藏上传网图
'delIndent' //减少缩进
]
},
editorConfig: {
placeholder: '请输入内容...',
// 所有的菜单配置,都要在 MENU_CONF 属性下
MENU_CONF: {
// 配置上传图片
uploadImage: {
timeout: 5 * 1000, // 5s
maxFileSize: 3 * 1024 * 1024, // 3M
// base64LimitSize: 5 * 1024, // 5kb 以下插入 base64
onBeforeUpload(files) {
return files; // 返回哪些文件可以上传
// return false 会阻止上传
},
// 用户自定义上传图片
customUpload(file, insertFn) {
requestServer(file, "rules").then((res) => {
insertFn(res); //插入图片
});
}
}
}
},
mode: 'default', // or 'simple'
};
},
created() {
this.getPlanList();
},
beforeDestroy() {
const editor = this.editor
if (editor == null) return
editor.destroy() // 组件销毁时,及时销毁编辑器
},
methods: {
onCreated(editor) {
this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错
},
onChange(editor) {
this.$emit('change', JSON.stringify(editor.children), editor.getHtml())
},
submitForm(formData) {
if (this.formData.content.length <= 11) {
this.$message.info('请输入规则内容')
return
}
},
preview(formData) {
if (this.formData.content.length <= 11) {
this.$message.info('请输入规则内容')
return
}
localStorage.setItem('quillContent',formData)
const { href } = this.$router.resolve({
//path是要跳转到的页面路径
path: "preview",
query: {
type:4
},
});
window.open(href, "_blank");
},
},
};
</script>
<style scoped lang='scss'>
.rolseList {
padding: 10px 20px;
}
.rules-content{
margin-top: 16px;
}
.span_type_detail {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #1692FF;
margin-left: 16px;
cursor:pointer;
}
.oprition-btn{
margin-top: 40px;
}
</style>
预览富文本页面
<template>
<div class="release">
<div class="release-top" v-if="isRelease == 0 || isRelease == 2">
<el-button type="primary" @click="release">一键发布</el-button>
</div>
<div
style="margin-left: 76px; margin-right: 76px"
class="ql-editor"
v-html="quillContent"
></div>
</div>
</template>
<script>
export default {
data() {
return {
quillContent: "", //接收的富文本框的预览内容
isRelease:null,
type:null,//接收的规则内容 列表跳转过来的编辑为 3 ,新增时的编辑为 4
};
},
created() {
this.type = this.$route.query.type
if (this.type == 3) {
this.quillContent = this.$route.query.content
this.isRelease = this.$route.query.isRelease
}else if (this.type == 4) {
this.quillContent = localStorage.getItem("quillContent");
this.isRelease = 2
}
},
methods: {
release(){
console.log('一键发布');
//判断是新增发布,还是预览并发布,需要添加一个入参判断是在列表中发布还是预览时发布,列表需要+id,预览不需要
// let msg = {
// rulesId:''
// }
// releaseRules(msg).then((res) => {
// if (res.status == 200) {
// this.$message({
// type: "success",
// message: "发布成功!",
// });
// this.$router.push('platformList')
// }
// });
}
},
};
</script>
<style scoped lang='scss'>
.release-top{
padding: 16px 80px;
border-bottom: 1px solid #ccc;
text-align: right;
}
.ql-editor{
::v-deep table {
border: none;
border-collapse: collapse;
}
::v-deep table td,
::v-deep table th {
border: 1px solid #ccc;
padding: 3px 5px;
min-width: 50px;
height: 20px;
}
::v-deep table th {
border-right: 1px solid #ccc;
border-bottom: 2px solid #ccc;
text-align: center;
background-color: #f1f1f1;
}
::v-deep ul,
ol {
margin: 10px 0 10px 20px;
}
::v-deep pre {
border: 1px solid #ccc;
background-color: #f8f8f8;
padding: 10px;
margin: 5px 0px;
font-size: 0.8em;
border-radius: 3px;
}
::v-deep .ql-editor ul li {
list-style-type: disc; // 解决序列li前面的.不展示问题
}
::v-deep .ql-editor ol li {
list-style-type: decimal; // 解决序列li前面的数字不展示问题
}
}
</style>