vue-quill-editor
安装
npm install vue-quill-editor -S
使用
.....<quill-editorstyle="padding-left: 0;padding-top: .0px;margin-top: 30px;"ref="editorRef" v-model="params.content" class="ql-editor" :options="editorOption"@blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @change="onEditorChange($event)" />
......import { quillEditor } from 'vue-quill-editor'
// 上传至oss
import { uploadOss } from '@/api/uploadOss'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
var sizes = [false, "16px", "18px", "20px", "22px", "26px", "28px", "30px"];......
components: {quillEditor},
data(){
return{editorOption: {modules: {toolbar: {container: [['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' }], // 文本方向[{ size: sizes }], // 字体大小[{ header: [1, 2, 3, 4, 5, 6,false] }], // 标题[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色// [{ font: ['songti'] }], // 字体种类[{ align: [] }], // 对齐方式['clean'], // 清除文本格式['image', 'video'] // 链接、图片、视频],handlers: {image: this.imageUploadOss}},placeholder: '请输入正文'},
}
}
....
methods:{
// 失去焦点事件onEditorBlur(quill) {},// 获得焦点事件onEditorFocus(quill) {},// 准备富文本编辑器onEditorReady(quill) {},// 内容改变事件onEditorChange({ quill, html, text }) {this.params.content = html},
}
图片拖拽及图片缩放
安装
npm i quill-image-drop-module -S
npm i quill-image-resize-module -S
使用
1. 新增样式文件.css
目录: assets/styles/quillEditor.css
.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";
}/* 字号设置 */
/* 默认字号 */
.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="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="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;
}
2.配置及使用
// vue.config.js 中增加
const webpack = require('webpack');
new webpack.ProvidePlugin({'window.Quill': 'quill/dist/quill.js','Quill': 'quill/dist/quill.js'})
// 新建的css文件的保存位置,如不同,需要修改
import "@/assets/styles/quillEditor.css";
import imageResize from 'quill-image-resize-module'
Quill.register('modules/imageResize', imageResize )
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop)// 调整字体大小选项
var sizes = [false, "16px", "18px", "20px", "22px", "26px", "28px", "30px"];
var Size = Quill.import("formats/size");
Size.whitelist = sizes;
Quill.register(Size, true)// toobar同级增加,如下图
imageDrop: true, // 拖动加载图片组件。
imageResize: { //调整大小组件。displayStyles: {backgroundColor: 'black',border: 'none',color: 'white'},modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
}
视图效果
完整代码
<template><div class="app-container" style="min-height: calc(100vh - 50px);"><el-tabs v-model="params.type" @tab-click="tabClick"><el-tab-pane label="医院简介" name="BRIEF" /><el-tab-pane label="楼宇分布" name="BUILDING" /><el-tab-pane label="科室分布" name="DEPARTMENT" /></el-tabs><div style="position: relative;margin-top: 10px;"><span style="display: block;position: absolute;top: 10px;padding-left: 18px;box-sizing: border-box;"><a style="font-size: 40px;color: red;position: absolute;left: 0;top: -5px;">*</a>介绍内容</span></div><quill-editorstyle="padding-left: 0;padding-top: .0px;margin-top: 30px;"ref="editorRef" v-model="params.content" class="ql-editor" :options="editorOption"@blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @change="onEditorChange($event)" /><div style="width: 100%;text-align: center;"><el-button style="width: 100px;" icon="el-icon-delete" @click="() => params.content = ''">清空</el-button><el-button style="width: 100px;" icon="el-icon-tickets" :loading="loading" type="primary" @click="saveContent()"v-if="checkPer(['admin', 'unicameral:introduce:edit'])" >保存</el-button></div></div>
</template><script>
import { Notification, Loading } from 'element-ui'
import { quillEditor } from 'vue-quill-editor'
import { uploadOss } from '@/api/uploadOss'
import * as introduceService from '@/api/unicameral/introduceService'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
// 新建的css文件的保存位置,如不同,需要修改
import "@/assets/styles/quillEditor.css";
import imageResize from 'quill-image-resize-module'
Quill.register('modules/imageResize', imageResize )
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop)var sizes = [false, "16px", "18px", "20px", "22px", "26px", "28px", "30px"];
var Size = Quill.import("formats/size");
Size.whitelist = sizes;
Quill.register(Size, true)export default {name: 'UnicameralIntroduce',components: {quillEditor},data() {return {params: {hosId: '',type: 'BRIEF',content: ''},loading: false,editorOption: {modules: {toolbar: {container: [['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' }], // 文本方向[{ size: sizes }], // 字体大小[{ header: [1, 2, 3, 4, 5, 6,false] }], // 标题[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色// [{ font: ['songti'] }], // 字体种类[{ align: [] }], // 对齐方式['clean'], // 清除文本格式['image', 'video'] // 链接、图片、视频],handlers: {image: this.imageUploadOss}},imageDrop: true, // 拖动加载图片组件。imageResize: { //调整大小组件。displayStyles: {backgroundColor: 'black',border: 'none',color: 'white'},modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]}},placeholder: '请输入正文'},}},mounted() {this.getContent()},methods: {tabClick() {// 清空内容this.params.content = ''this.getContent()},// 失去焦点事件onEditorBlur(quill) {},// 获得焦点事件onEditorFocus(quill) {},// 准备富文本编辑器onEditorReady(quill) {},// 内容改变事件onEditorChange({ quill, html, text }) {this.params.content = html},getContent() {const options = {fullscreen: false,target: document.querySelector('.platform-wrap')}const loadingInstance = Loading.service(options)this.params.content = ""introduceService.getIntroduce(this.params).then(res => {if(res.status == '200'){this.params.content = res.result}}).finally(() => loadingInstance.close())},saveContent() {this.loading = true;introduceService.saveIntroduce(this.params).then(res => {if(res.status == '200'){Notification.success('操作成功')}else {Notification.error('操作成功')}}).finally(() => this.loading = false)},imageUploadOss() {const { quill } = this.$refs.editorReflet fileInput = quill.container.querySelector('input.ql-image[type=file]')if (fileInput === null) {fileInput = document.createElement('input')fileInput.setAttribute('type', 'file')// 设置图片参数名fileInput.setAttribute('name', 'file')// 可设置上传图片的格式fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon')fileInput.classList.add('ql-image')// 监听选择文件fileInput.addEventListener('change', function() {const formData = new FormData()formData.append('file', fileInput.files[0])formData.append('imageUrl', 'hos/unicameral-introduce/')uploadOss(formData).then(res => {if (res.status === '200') {const length = quill.getSelection(true).indexquill.insertEmbed(length, 'image', process.env.VUE_APP_DOMAIN_STATIC + res.result)quill.setSelection(length + 1)}}).catch(err => {console.log(err)Notification.error('图片上传失败')})})}fileInput.click()},imageUpload() {// var self = thisconst { quill } = this.$refs.editorReflet fileInput = quill.container.querySelector('input.ql-image[type=file]')if (fileInput === null) {fileInput = document.createElement('input')fileInput.setAttribute('type', 'file')// 设置图片参数名fileInput.setAttribute('name', 'file')// 可设置上传图片的格式fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon')fileInput.classList.add('ql-image')// 监听选择文件fileInput.addEventListener('change', () => {const formData = new FormData()formData.append('file', fileInput.files[0])// let length = self.quill.getSelection(true).index;// quill.insertEmbed(length, 'image', data.data.data.url);// quill.insertEmbed(length, 'title', data.data.data.fileName);// quill.setSelection(length + 1)})quill.container.appendChild(fileInput)}fileInput.click()}}
}
</script>
<style scoped lang="scss">
.codeJs {font-size: 11pt;font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
}
::v-deep .el-tabs {margin-bottom: 0px;
}
// ::v-deep .ql-editor{
// height:260px;
// }
</style>
<style>
.CodeMirror-hints{z-index: 8888!important;
}
</style>