1.安装
安装依赖包,包含编辑器包,拖拽包,缩放包 (拖拽包因为无法和element ui 配合且上传的是Base 64 格式的这里就看个人需求)
npm i vue-quill-editor quill quill-image-drop-module quill-image-resize-module --save
2.main.js 引用
import VueQuillEditor from 'vue-quill-editor'
import * as Quill from 'quill'; // 富文本基于quill
import imageResize from 'quill-image-resize-module' // 图片缩放组件。
import { ImageDrop } from 'quill-image-drop-module'; // 图片拖动组件。
Quill.register('modules/imageDrop', ImageDrop);
Quill.register('modules/imageResize', imageResize)
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor);
3.配置文件
webpack.base.conf.js配置
const webpack = require('webpack'); //加入
module.exports里面加
plugins: [
new webpack.ProvidePlugin({
'window.Quill': 'quill/dist/quill.js',
'Quill': 'quill/dist/quill.js'
})
],
rules 里面加
{
test: /\.js$/,
exclude: /node_modules(?!\/quill-image-drop-module|quill-image-resize-module)/,
loader: 'babel-loader'
}
4.修改原版部分样式(复制到App.vue)
.editor {
line-height: normal !important;
height: 800px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: '保存';
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode=video]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
content: '32px';
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: '标题6';
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
content: '等宽字体';
}
5.页面中使用:
<template>
<div class="GzGl BaW">
<div class="f-14 b_botm GzGlTit">
<div class="fonW">新手帮助</div>
</div>
<div>
<el-upload
class="avatar-uploader"
:action="uploadUrl()"
name="img"
:headers="myHeader"
:show-file-list="false"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload">
</el-upload>
<quill-editor
style="height: 690px;"
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@change="onEditorChange($event)"
>
</quill-editor>
</div>
<div class="M-T-50 disCen">
<el-button @click="Baocun" type="primary">保存</el-button>
</div>
</div>
</template>
<script>
import { showLoading, hideLoading } from '../../../../utils/loading' //elemnt 提示函数
const toolbarOptions = [ //配置功能栏
['bold', 'italic', 'underline', 'strike'],
[{'header': 1}, {'header': 2}],
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'indent': '-1'}, {'indent': '+1'}],
[{'direction': 'rtl'}],
[{'size': ['small', false, 'large', 'huge']}],
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}],
[{'font': []}],
[{'align': []}],
['link', 'image'], //图片,超链接
['clean']
]
export default {
data() {
return {
quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
content: '',
editorOption: {
placeholder: '',
theme: 'snow',
modules: {
imageResize: { //配置图片缩放
displayStyles: {
backgroundColor: 'black',
border: 'none',
color: 'white'
},
modules: ['Resize', 'DisplaySize', 'Toolbar']
},
toolbar: {
container: toolbarOptions,
handlers: {
'image': function (value) {
if (value) {
// 触发input框选择图片文件
document.querySelector('.avatar-uploader input').click()
} else {
this.quill.format('image', false);
}
}
}
}
}
}
}
},
computed: { //在此配置 Token
myHeader(){
return {
"Authorization":"Bearer " + window.sessionStorage.getItem('Token')
}
},
},
created () {
this.WendanHuix()
},
methods: {
onEditorChange({editor, html, text}) { //内容改变事件
console.log("---内容改变事件---")
this.content = html
console.log(html)
},
uploadUrl(){ //图片上传路径
return window.g.Url + '/basic/api/file/uploadimage'
},
// 富文本图片上传前
beforeUpload() {
// 显示loading动画
this.quillUpdateImg = true
},
uploadSuccess(res, file) {
// res为图片服务器返回的数据
// 获取富文本组件实例
console.log(res);
let quill = this.$refs.myQuillEditor.quill
// 如果上传成功
if (res.Msg == '成功' ) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, 'image',window.g.Url + res.Content.Items[0]) //拼接完整图片路径并放入富文本
// 调整光标到最后
quill.setSelection(length + 1)
} else {
this.$message.error('图片插入失败')
}
// loading动画消失
this.quillUpdateImg = false
},
// 富文本图片上传失败
uploadError() {
// loading动画消失
this.quillUpdateImg = false
this.$message.error('图片插入失败')
},
WendanHuix(){ //文档回显
let that = this
this.$axios.get('url',{
params: {
'agreementType':5
}
})
.then(res => {
if(!res.data.Code) {
if(res.data.Content){
this.content = res.data.Content
console.log(this.content)
}
// console.log(res.data.Content)
} else {
that.$alert(res.data.Msg, '错误提醒', {
confirmButtonText: '确定',
callback: action => {
}
});
}
})
},
Baocun(){ //保存
console.log(this.content)
if(!this.content){
this.$message.error('亲!请填写协议内容');
return
}
showLoading()
this.$axios.post('url', {
"AgreementType": 5,
"Content": this.content
}, )
.then(res => {
setTimeout(function() {
hideLoading()
}, 200)
if(!res.data.Code) {
this.$message({
message: '恭喜你,这是一条成功消息',
type: 'success'
});
console.log(res.data.Content)
} else {
this.$alert(res.data.Msg, '错误提醒', {
confirmButtonText: '确定',
callback: action => {
}
});
}
})
}
}
}
</script>
<style scoped>
.GzGl{
padding: 5px 10px;
}
.GzGlTit{
padding-top: 7px;
padding-bottom: 15px;
margin-bottom: 20px;
}
</style>