vue2中quill、vue-quill-editor、quill-better-table案例

主文件

<template>
	<div style="width: 100%; height: 100%;">

<!--		回显-->
		<div style="width: 100%; height: 100%;" class="ql-editor" v-if="disabled" v-html="content">{{ content }}</div>

<!--		编辑-->
		<quill-editor
			v-else
			v-model="content"
			:options="options"
			ref="quillEditor"
			@blur="onEditorBlur($event)"
			@focus="onEditorFocus($event)"
			@ready="onEditorReady($event)"
			@change="onEditorChange($event)"
		/>

		<div style="float:right; margin: 10px 0;" v-if="!disabled">
			{{currentLength + ' / ' + max}}
		</div>

	</div>
</template>

<script>
import ResourcesService from "../../../util/ResourcesService";
const resourcesServer = new ResourcesService()

import {quillEditor} from "vue-quill-editor";
import Quill from "quill";
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

// 引入表格(必须是2.0.0的版本,现在还是dev版没有正式上线)
// 踩了很多坑,最后没显示出来,排查了半天,发现是z-index值太低了,wangEditor好用些
// npm install quill ^2.0.0-dev.4
// npm install quill-better-table
import QuillBetterTable from "quill-better-table"
import "quill-better-table/dist/quill-better-table.css"
Quill.register({'modules/better-table': QuillBetterTable}, true)


//  工具栏提示,参考博客https://www.cnblogs.com/meiyanstar/p/13346355.html
const titleConfig=[
	{Choice:'.ql-bold',title:'加粗'},
	{Choice:'.ql-italic',title:'斜体'},
	{Choice:'.ql-underline',title:'下划线'},
	{Choice:'.ql-header',title:'段落格式'},
	{Choice:'.ql-strike',title:'删除线'},
	{Choice:'.ql-blockquote',title:'块引用'},
	{Choice:'.ql-code',title:'插入代码'},
	{Choice:'.ql-code-block',title:'插入代码段'},
	{Choice:'.ql-font',title:'字体'},
	{Choice:'.ql-size',title:'字体大小'},
	{Choice:'.ql-list[value="ordered"]',title:'编号列表'},
	{Choice:'.ql-list[value="bullet"]',title:'项目列表'},
	{Choice:'.ql-direction',title:'文本方向'},
	{Choice:'.ql-header[value="1"]',title:'h1'},
	{Choice:'.ql-header[value="2"]',title:'h2'},
	{Choice:'.ql-align',title:'对齐方式'},
	{Choice:'.ql-color',title:'字体颜色'},
	{Choice:'.ql-background',title:'背景颜色'},
	{Choice:'.ql-image',title:'图像'},
	{Choice:'.ql-video',title:'视频'},
	{Choice:'.ql-link',title:'添加链接(请先选中文字)'},
	{Choice:'.ql-formula',title:'插入公式'},
	{Choice:'.ql-clean',title:'清除字体格式'},
	{Choice:'.ql-table',title:'表格'},
	{Choice:'.ql-script[value="sub"]',title:'下标'},
	{Choice:'.ql-script[value="super"]',title:'上标'},
	{Choice:'.ql-indent[value="-1"]',title:'向左缩进'},
	{Choice:'.ql-indent[value="+1"]',title:'向右缩进'},
	{Choice:'.ql-header .ql-picker-label',title:'标题大小'},
	{Choice:'.ql-header .ql-picker-item[data-value="1"]',title:'标题一'},
	{Choice:'.ql-header .ql-picker-item[data-value="2"]',title:'标题二'},
	{Choice:'.ql-header .ql-picker-item[data-value="3"]',title:'标题三'},
	{Choice:'.ql-header .ql-picker-item[data-value="4"]',title:'标题四'},
	{Choice:'.ql-header .ql-picker-item[data-value="5"]',title:'标题五'},
	{Choice:'.ql-header .ql-picker-item[data-value="6"]',title:'标题六'},
	{Choice:'.ql-header .ql-picker-item:last-child',title:'标准'},
	{Choice:'.ql-size .ql-picker-item[data-value="small"]',title:'小号'},
	{Choice:'.ql-size .ql-picker-item[data-value="large"]',title:'大号'},
	{Choice:'.ql-size .ql-picker-item[data-value="huge"]',title:'超大号'},
	{Choice:'.ql-size .ql-picker-item:nth-child(2)',title:'标准'},
	{Choice:'.ql-align .ql-picker-item:first-child',title:'居左对齐'},
	{Choice:'.ql-align .ql-picker-item[data-value="center"]',title:'居中对齐'},
	{Choice:'.ql-align .ql-picker-item[data-value="right"]',title:'居右对齐'},
	{Choice:'.ql-align .ql-picker-item[data-value="justify"]',title:'两端对齐'}
];

// 自定义字体(需要先全局引入css样式)
let fontFamily = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'pingfang'];
Quill.imports['formats/font'].whitelist = fontFamily;
Quill.register(Quill.imports['formats/font'])

// 自定义字体大小(需要先全局引入css样式)
let fontSize = ['10px', '12px', '14px', '16px', '20px', '24px', '26px', '30px', '36px']
Quill.imports['attributors/style/size'].whitelist = fontSize;
Quill.register(Quill.imports['attributors/style/size']);

// 上传图片的地址
import apiUrl from "../../../api/apiUrl";
const baseURL = apiUrl.baseAddr
/*富文本编辑图片上传配置*/
const uploadConfig = {
	action: '/api/files/v1/upEdit', // 必填参数 图片上传地址
	methods: 'POST', // 必填参数 图片上传方式
	token: sessionStorage.getItem('token'), // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
	name: 'file', // 必填参数 文件的参数名
	size: 10240, // 可选参数   图片大小,单位为Kb, 1M = 1024Kb
	accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon', // 可选 可上传的图片格式
}

// quill方法配置
const handlers = {
	// 图片
	image: function image() {
		var self = this
		var fileInput = this.container.querySelector(
			'input.ql-image[type=file]'
		)
		if (fileInput === null) {
			fileInput = document.createElement('input')
			fileInput.setAttribute('type', 'file')
			// 设置图片参数名
			if (uploadConfig.name) fileInput.setAttribute('name', uploadConfig.name)
			// 可设置上传图片的格式
			fileInput.setAttribute('accept', uploadConfig.accept)
			fileInput.classList.add('ql-image')
			// 监听选择文件
			fileInput.addEventListener('change', async function () {
				let res = await resourcesServer.uploadFile('med-main-svc', 'C006', 1,  fileInput.files[0])
				if (res.code === '0000') {
					let length = self.quill.getSelection(true).index
					//这里很重要,你图片上传成功后,img的src需要在这里添加,res.path就是你服务器返回的图片链接。
					const img = res.list[0]
					self.quill.insertEmbed(length, 'image', baseURL + '/res-svc/res/v3/download?fileId=' + img.fileId + '&applicationName=med-main-svc&businessTypeCode=C006&free=1')
					self.quill.setSelection(length + 1)
					fileInput.value = ''
				}
			})
			this.container.appendChild(fileInput)
		}
		fileInput.click()
	},
	// 表
	table: function () {
		this.quill.getModule('better-table').insertTable(3, 4)
	},
}
// quill工具栏展示工具配置
const container = [
	[{ 'font': fontFamily }],  //字体
	[{ 'size': fontSize }], 		// 字体大小
	['bold', 'italic', 'underline', 'strike'],    //加粗,斜体,下划线,删除线
	// ['blockquote', 'code-block'],     //引用,代码块
	// [{ 'header': 1 }, { 'header': 2 }],        // 标题,键值对的形式;1、2表示字体大小
	[{ 'list': 'ordered'}, { 'list': 'bullet' }], //列表
	[{ 'script': 'sub'}, { 'script': 'super' }],  // 上下标
	[{ 'indent': '-1'}, { 'indent': '+1' }],     	// 缩进
	// [{ 'direction': 'rtl' }],  // 文本方向
	[{ 'header': [1, 2, 3, 4, 5, 6, false] }],    //几级标题
	[{ 'color': [] }, { 'background': [] }],     // 字体颜色,字体背景颜色
	[{ 'align': [] }],    //对齐方式
	['clean'],   //清除字体样式
	['image'],   //上传图片、上传视频
	['table'] // 表格
]
// better-table配置
const betterTable = {
	// 右键菜单
	operationMenu: {
		items: {
			insertColumnRight: { text: '右边插入一列' },
			insertColumnLeft: { text: '左边插入一列' },
			insertRowUp: { text: '上边插入一行' },
			insertRowDown: { text: '下边插入一行' },
			mergeCells: { text: '合并单元格' },
			unmergeCells: { text: '拆分单元格' },
			deleteColumn: { text: '删除列' },
			deleteRow: { text: '删除行' },
			deleteTable: { text: '删除表格' },
		},
		background: {
			color: '#333'
		},
		color: {
			colors: ['green', 'red', 'yellow', 'blue', 'white', '#558ff2', '#595959', '#9fd9c5'],
			text: '背景色:'
		}
	}
}

export default {
	// quill-editor二次封装
	name: "quillEditorPackage",

	props: {
		// 禁用
		disabled: {
			type: Boolean,
   default: false
		},
		// 字数限制
		max: {
			type: Number | String,
   default: 10000
		}
	},

	data() {
  return {
   content: '',
   lastContent: '', // 用于限制字数
			currentLength: '0', // 当前字数

			// quill配置
			options: {
				placeholder: '请在这里输入',
				modules:{
					toolbar: {
						container: container,
						handlers: handlers,
					},
					table: false,
					'better-table': betterTable,
					keyboard: {
						bindings: QuillBetterTable.keyboardBindings
					}
				},
				theme:'snow'
			}
		}
	},
	components: { quillEditor },

	mounted(){
        // 调用函数出现工具栏提示(不调用则没有)
		this.autotip()
	},

	methods: {
		// 失去焦点
		onEditorBlur(e){
			// console.log('quill失去焦点', e)
		},
		// 获得焦点
		onEditorFocus(e){
			// console.log('quill获得焦点', e)
		},
		// 准备好
		onEditorReady(e){
			// console.log('quill准备好', e)
		},
		// 改变
		onEditorChange(e){
			const allText = e.text.replace('\n', "")
			this.currentLength = allText.length
			if(this.currentLength > Number(this.max)) {
				this.$nextTick(() => {
					this.content = this.lastContent
				})
				this.$message({
					type:'error',
     message: '超出最大字数'
				})
			} else {
				this.lastContent = this.content
			}
		},

	//	回显
		backShow(content) {
			if(this.disabled){
				this.content = content
				return
			}
			// 回显编辑 本来直接双向绑定改变this.content就可以了,增加了表格组件以后就报错 this.quill.pasteHTML(newVal) is not a function
			const editor = this.$refs.quillEditor.quill
			let delta = editor.clipboard.convert({html: content});
			editor.setContents(delta);
			this.content = content
		},
        autotip(){
			document.getElementsByClassName('ql-editor')[0].dataset.placeholder=''
			for(let item of titleConfig){
				let tip = document.querySelector('.quill-editor '+ item.Choice)
				if (!tip) continue
				tip.setAttribute('title',item.title)
			}
		}
	}
}
</script>

<style scoped lang="less">
</style>

css配置 -- QuillFont字体配置

/*
* quillEditor 字体配置
*/
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimSun"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimSun"]::before {
	content: "宋体";
	font-family: "SimSun";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="SimHei"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="SimHei"]::before {
	content: "黑体";
	font-family: "SimHei";
}

.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value="Microsoft-YaHei"]::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value="Microsoft-YaHei"]::before {
	content: "微软雅黑";
	font-family: "Microsoft YaHei";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="KaiTi"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="KaiTi"]::before {
	content: "楷体";
	font-family: "KaiTi";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="FangSong"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="FangSong"]::before {
	content: "仿宋";
	font-family: "FangSong";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="Arial"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="Arial"]::before {
	content: "Arial";
	font-family: "Arial";
}

.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value="Times-New-Roman"]::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value="Times-New-Roman"]::before {
	content: "Times New Roman";
	font-family: "Times New Roman";
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="sans-serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="sans-serif"]::before {
	content: "sans-serif";
	font-family: "sans-serif";
}

.ql-font-SimSun {
	font-family: "SimSun";
}

.ql-font-SimHei {
	font-family: "SimHei";
}

.ql-font-Microsoft-YaHei {
	font-family: "Microsoft YaHei";
}

.ql-font-KaiTi {
	font-family: "KaiTi";
}

.ql-font-FangSong {
	font-family: "FangSong";
}

.ql-font-Arial {
	font-family: "Arial";
}

.ql-font-Times-New-Roman {
	font-family: "Times New Roman";
}

.ql-font-sans-serif {
	font-family: "sans-serif";
}

css配置 -- QuillFontSize字体可选大小配置

/*
* quillEditor 字体大小配置
*/

/* 默认字号 */
.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="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
	content: "14px";
	font-size: 14px;
}
.ql-size-14px {
	font-size: 14px;
}


.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {
	content: "10px";
	font-size: 10px;
}
.ql-size-12px {
	font-size: 12px;
}


.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
	content: "12px";
	font-size: 12px;
}
.ql-size-12px {
	font-size: 12px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
	content: "16px";
	font-size: 16px;
}
.ql-size-16px {
	font-size: 16px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
	content: "18px";
	font-size: 18px;
}
.ql-size-18px {
	font-size: 18px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
	content: "20px";
	font-size: 20px;
}
.ql-size-20px {
	font-size: 20px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
	content: "22px";
	font-size: 22px;
}
.ql-size-22px {
	font-size: 22px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
	content: "24px";
	font-size: 24px;
}
.ql-size-24px {
	font-size: 24px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
	content: "26px";
	font-size: 26px;
}
.ql-size-26px {
	font-size: 26px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {
	content: "28px";
	font-size: 28px;
}
.ql-size-28px {
	font-size: 28px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="30px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="30px"]::before {
	content: "30px";
	font-size: 30px;
}
.ql-size-30px {
	font-size: 30px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="36px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36px"]::before {
	content: "36px";
	font-size: 36px;
}
.ql-size-36px {
	font-size: 36px;
}

css配置 -- QuillTitle标题配置

/*
* quillEditor 几级标题设置
*/
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
	content: "文本" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}
.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" !important;
}

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值