5 changed files with 835 additions and 52 deletions
-
1package.json
-
206src/components/quillEditor/index.vue
-
374src/components/quillEditor/index2.vue
-
296src/components/quillEditor/indexlast.vue
-
10src/views/inquiryMachine/content.vue
@ -0,0 +1,374 @@ |
|||
<template> |
|||
<div> |
|||
<div ref="editorContainer" class="editor" style="height: 450px; overflow-y: scroll;" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { upload } from '@/utils/upload' |
|||
import Quill from 'quill' |
|||
import 'quill/dist/quill.snow.css' |
|||
import '@/assets/styles/quillEditor.css' |
|||
|
|||
import QuillBetterTable from 'quill-better-table' |
|||
import 'quill-better-table/dist/quill-better-table.css' |
|||
Quill.register({ 'modules/better-table': QuillBetterTable }, true) |
|||
|
|||
// 自定义字体 |
|||
var fonts = [ |
|||
'SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'sans-serif' |
|||
] |
|||
|
|||
// 自定义字号 |
|||
var sizes = [false, '14px', '16px', '18px', '20px', '22px', '26px', '28px', '30px'] |
|||
|
|||
// 注册自定义格式 |
|||
var Size = Quill.import('formats/size') |
|||
Size.whitelist = sizes |
|||
var Font = Quill.import('formats/font') |
|||
Font.whitelist = fonts |
|||
Quill.register(Font, true) |
|||
|
|||
// 工具栏提示文字配置 |
|||
const titleConfig = { |
|||
'ql-bold': '加粗', |
|||
'ql-color': '颜色', |
|||
'ql-font': '字体', |
|||
'ql-code': '插入代码', |
|||
'ql-italic': '斜体', |
|||
'ql-link': '添加链接', |
|||
'ql-background': '背景色', |
|||
'ql-size': '字体大小', |
|||
'ql-strike': '删除线', |
|||
'ql-script': '上标/下标', |
|||
'ql-underline': '下划线', |
|||
'ql-blockquote': '引用', |
|||
'ql-header': '标题', |
|||
'ql-indent': '缩进', |
|||
'ql-list': '列表', |
|||
'ql-align': '文本对齐', |
|||
'ql-direction': '文本方向', |
|||
'ql-code-block': '代码块', |
|||
'ql-formula': '公式', |
|||
'ql-image': '图片', |
|||
'ql-video': '视频', |
|||
'ql-clean': '清除字体样式', |
|||
'ql-upload': '文件', |
|||
'ql-table': '插入表格', |
|||
'ql-table-insert-row': '插入行', |
|||
'ql-table-insert-column': '插入列', |
|||
'ql-table-delete-row': '删除行', |
|||
'ql-table-delete-column': '删除列' |
|||
} |
|||
|
|||
// 表格右键菜单配置 |
|||
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 { |
|||
name: 'Editor', |
|||
props: { |
|||
value: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
quill: null, |
|||
file: null, |
|||
options: { |
|||
theme: 'snow', |
|||
modules: { |
|||
toolbar: { |
|||
container: [ |
|||
['bold', 'italic', 'underline', 'strike'], |
|||
[{ header: 1 }, { header: 2 }], |
|||
[{ list: 'ordered' }, { list: 'bullet' }], |
|||
[{ script: 'sub' }, { script: 'super' }], |
|||
[{ indent: '-1' }, { indent: '+1' }], |
|||
[{ color: [] }, { background: [] }], |
|||
[{ size: sizes }], |
|||
[{ font: fonts }], |
|||
[{ align: [] }], |
|||
['link', 'image'], |
|||
['clean'], |
|||
['table'] |
|||
], |
|||
handlers: { |
|||
image: function(value) { |
|||
if (value) { |
|||
const input = document.createElement('input') |
|||
input.setAttribute('type', 'file') |
|||
input.setAttribute('accept', 'image/*') |
|||
|
|||
input.addEventListener('change', (e) => { |
|||
const file = e.target.files[0] |
|||
if (file) { |
|||
this.file = file |
|||
// 执行上传逻辑 |
|||
const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
|
|||
upload(linkSrc + '/api/fileRelevant/uploadOtherImg', this.file).then(res => { |
|||
if (res.data.code === 200) { |
|||
const imageUrl = linkSrc + '/api/fileRelevant/getImg?imgType=1&imgId=' + res.data.data |
|||
const range = this.quill.getSelection() |
|||
if (range) { |
|||
// 在光标位置插入图片 |
|||
this.quill.insertEmbed(range.index, 'image', imageUrl) |
|||
// 移动光标到图片后面 |
|||
this.quill.setSelection(range.index + 1) |
|||
} else { |
|||
this.quill.insertEmbed(this.quill.getLength(), 'image', imageUrl) |
|||
} |
|||
} |
|||
}).catch(err => { |
|||
console.error('上传失败:', err) |
|||
}) |
|||
} |
|||
}) |
|||
input.click() |
|||
} else { |
|||
this.quill.format('image', false) |
|||
} |
|||
}, |
|||
table: function() { |
|||
this.quill.getModule('better-table').insertTable(3, 4) |
|||
} |
|||
} |
|||
}, |
|||
table: false, |
|||
'better-table': betterTable, |
|||
keyboard: { |
|||
bindings: QuillBetterTable.keyboardBindings |
|||
} |
|||
}, |
|||
placeholder: '' |
|||
}, |
|||
titleConfig |
|||
} |
|||
}, |
|||
watch: { |
|||
value(newVal) { |
|||
if (newVal === this.quill.root.innerHTML) return |
|||
this.quill.setContents([]) |
|||
this.quill.clipboard.dangerouslyPasteHTML(0, newVal) |
|||
} |
|||
}, |
|||
mounted() { |
|||
const dom = this.$refs.editorContainer |
|||
this.quill = new Quill(dom, this.options) |
|||
|
|||
if (this.value) { |
|||
this.quill.clipboard.dangerouslyPasteHTML(this.value) |
|||
} |
|||
|
|||
this.addQuillTitle() |
|||
|
|||
// 初始化表格列宽拖动功能 |
|||
this.initTableResize() |
|||
|
|||
// 监听内容变化,为新添加的表格初始化拖动功能 |
|||
this.quill.on('text-change', (delta, oldDelta, source) => { |
|||
if (source === 'user') { |
|||
this.initTableResize() |
|||
} |
|||
}) |
|||
}, |
|||
methods: { |
|||
// 添加工具栏提示文字 |
|||
addQuillTitle() { |
|||
const oToolBar = document.querySelector('.ql-toolbar') |
|||
const aButton = oToolBar.querySelectorAll('button') |
|||
const aSelect = oToolBar.querySelectorAll('select') |
|||
|
|||
aButton.forEach(function(item) { |
|||
if (item.className === 'ql-script') { |
|||
item.value === 'sub' ? (item.title = '下标') : (item.title = '上标') |
|||
} else if (item.className === 'ql-indent') { |
|||
item.value === '+1' ? (item.title = '向右缩进') : (item.title = '向左缩进') |
|||
} else { |
|||
item.title = titleConfig[item.classList[0]] |
|||
} |
|||
}) |
|||
|
|||
aSelect.forEach(function(item) { |
|||
item.parentNode.title = titleConfig[item.classList[0]] |
|||
}) |
|||
}, |
|||
|
|||
// 获取HTML内容 |
|||
getHtmlContent() { |
|||
return this.quill.root.innerHTML |
|||
}, |
|||
|
|||
// 获取Delta格式内容 |
|||
getDeltaContent() { |
|||
return this.quill.getContents() |
|||
}, |
|||
|
|||
/** |
|||
* 初始化表格列宽拖动功能 |
|||
*/ |
|||
initTableResize() { |
|||
// 获取编辑器中所有表格 |
|||
const tables = this.quill.root.querySelectorAll('.ql-editor table') |
|||
tables.forEach(table => { |
|||
// 确保表格使用固定布局 |
|||
table.style.tableLayout = 'fixed' |
|||
table.style.width = '100%' |
|||
|
|||
// // 为所有列头添加拖动功能 |
|||
// const headers = table.querySelectorAll('th') |
|||
// headers.forEach((header, colIndex) => { |
|||
// // 避免重复添加手柄 |
|||
// if (!header.querySelector('.table-resize-handle')) { |
|||
// this.addResizeHandle(header, table, colIndex) |
|||
// } |
|||
// }) |
|||
|
|||
// // 如果表格没有表头(th),则为第一行单元格添加拖动功能 |
|||
// if (headers.length === 0) { |
|||
// const firstRowCells = table.querySelectorAll('tr:first-child td') |
|||
// firstRowCells.forEach((cell, colIndex) => { |
|||
// if (!cell.querySelector('.table-resize-handle')) { |
|||
// this.addResizeHandle(cell, table, colIndex) |
|||
// } |
|||
// }) |
|||
// } |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 为单元格添加拖动手柄和事件监听 |
|||
* @param {HTMLElement} cell - 单元格元素 |
|||
* @param {HTMLElement} table - 表格元素 |
|||
* @param {number} colIndex - 列索引 |
|||
*/ |
|||
addResizeHandle(cell, table, colIndex) { |
|||
// 创建拖动手柄 |
|||
const handle = document.createElement('div') |
|||
handle.className = 'table-resize-handle' |
|||
cell.appendChild(handle) |
|||
|
|||
// 拖动状态变量 |
|||
let isResizing = false |
|||
let startX = 0 |
|||
let startWidth = 0 |
|||
|
|||
// 鼠标按下事件 - 开始拖动 |
|||
handle.addEventListener('mousedown', (e) => { |
|||
isResizing = true |
|||
startX = e.clientX |
|||
// 获取当前列的初始宽度 |
|||
const columnCells = table.querySelectorAll(`tr td:nth-child(${colIndex + 1}), tr th:nth-child(${colIndex + 1})`) |
|||
startWidth = columnCells[0].offsetWidth |
|||
handle.classList.add('active') |
|||
|
|||
// 阻止事件冒泡,避免影响编辑器其他操作 |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
}) |
|||
|
|||
// 鼠标移动事件 - 处理拖动 |
|||
document.addEventListener('mousemove', (e) => { |
|||
if (!isResizing) return |
|||
|
|||
// 计算新宽度,限制最小宽度为50px |
|||
const widthDiff = e.clientX - startX |
|||
const newWidth = Math.max(50, startWidth + widthDiff) |
|||
|
|||
// 更新当前列所有单元格的宽度 |
|||
const columnCells = table.querySelectorAll(`tr td:nth-child(${colIndex + 1}), tr th:nth-child(${colIndex + 1})`) |
|||
columnCells.forEach(cell => { |
|||
cell.style.width = `${newWidth}px` |
|||
cell.style.minWidth = `${newWidth}px` |
|||
cell.style.maxWidth = `${newWidth}px` |
|||
}) |
|||
|
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
}) |
|||
|
|||
// 鼠标释放事件 - 结束拖动 |
|||
document.addEventListener('mouseup', () => { |
|||
if (isResizing) { |
|||
isResizing = false |
|||
handle.classList.remove('active') |
|||
} |
|||
}) |
|||
|
|||
// 鼠标离开窗口事件 - 结束拖动 |
|||
document.addEventListener('mouseleave', () => { |
|||
if (isResizing) { |
|||
isResizing = false |
|||
handle.classList.remove('active') |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
/* 表格列宽拖动相关样式 */ |
|||
.ql-editor table { |
|||
table-layout: fixed !important; |
|||
width: 100% !important; |
|||
border-collapse: collapse; |
|||
} |
|||
|
|||
.ql-editor table td, |
|||
.ql-editor table th { |
|||
border: 1px solid #ccc; |
|||
padding: 8px; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
.table-resize-handle { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
width: 6px; |
|||
height: 100%; |
|||
cursor: col-resize; |
|||
background-color: transparent; |
|||
z-index: 10; |
|||
} |
|||
|
|||
.table-resize-handle:hover, |
|||
.table-resize-handle.active { |
|||
background-color: #558ff2; |
|||
} |
|||
|
|||
.ql-editor table th, |
|||
.ql-editor table tr:first-child td { |
|||
position: relative; |
|||
} |
|||
|
|||
/* 右键菜单层级 */ |
|||
.qlbt-operation-menu{ |
|||
z-index: 99999 !important; |
|||
} |
|||
</style> |
@ -0,0 +1,296 @@ |
|||
<template> |
|||
<div style="width: 100%; height: 100%;"> |
|||
<!-- 回显--> |
|||
<div v-if="disabled" style="width: 100%; height: 100%;" class="ql-editor" v-html="content" /> |
|||
<!-- 编辑--> |
|||
<quill-editor |
|||
v-else |
|||
ref="quillEditor" |
|||
v-model="content" |
|||
:options="options" |
|||
@blur="onEditorBlur($event)" |
|||
@focus="onEditorFocus($event)" |
|||
@ready="onEditorReady($event)" |
|||
@change="onEditorChange($event)" |
|||
/> |
|||
|
|||
<div v-if="!disabled" style="float:right; margin: 10px 0;"> |
|||
{{ 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样式) |
|||
const fontFamily = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'pingfang'] |
|||
Quill.imports['formats/font'].whitelist = fontFamily |
|||
Quill.register(Quill.imports['formats/font']) |
|||
|
|||
// 自定义字体大小(需要先全局引入css样式) |
|||
const 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() { |
|||
const res = await resourcesServer.uploadFile('med-main-svc', 'C006', 1, fileInput.files[0]) |
|||
if (res.code === '0000') { |
|||
const 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', |
|||
components: { quillEditor }, |
|||
|
|||
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' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
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 |
|||
const delta = editor.clipboard.convert({ html: content }) |
|||
editor.setContents(delta) |
|||
this.content = content |
|||
}, |
|||
autotip() { |
|||
document.getElementsByClassName('ql-editor')[0].dataset.placeholder = '' |
|||
for (const item of titleConfig) { |
|||
const tip = document.querySelector('.quill-editor ' + item.Choice) |
|||
if (!tip) continue |
|||
tip.setAttribute('title', item.title) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="less"> |
|||
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue