|
@@ -1,523 +0,0 @@
|
|
|
-<template>
|
|
|
- <div>
|
|
|
- <!-- 图片上传组件辅助-->
|
|
|
- <el-upload
|
|
|
- class="avatar-uploader"
|
|
|
- action="notnull"
|
|
|
- :http-request="uploadFileFun"
|
|
|
- name="img"
|
|
|
- :headers="header"
|
|
|
- :show-file-list="false"
|
|
|
- :on-success="uploadSuccess"
|
|
|
- :on-error="uploadError"
|
|
|
- :before-upload="beforeUpload"
|
|
|
- v-show="false">
|
|
|
- <el-button class="stBtnUpload" size="small" type="primary">点击上传</el-button>
|
|
|
- </el-upload>
|
|
|
- <el-button style="display: none" @click="richtext()" size="small" type="primary">返回</el-button>
|
|
|
- <quill-editor
|
|
|
- class="editor"
|
|
|
- v-model="content"
|
|
|
- :ref="quillEditorRef"
|
|
|
- :options="editorOption"
|
|
|
- @blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
|
|
|
- @change="onEditorChange($event)">
|
|
|
- </quill-editor>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-<script>
|
|
|
- let cusSpecial = ['α', 'β', 'γ'];
|
|
|
- // 工具栏配置
|
|
|
- const toolbarOptions = [
|
|
|
- ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
|
|
|
- ['blockquote', 'code-block', 'formula'], // 引用 代码块
|
|
|
- [{ header: 1 }, { header: 2 }], // 1、2 级标题
|
|
|
- [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
|
|
|
- [{ script: 'sub' }, { script: 'super' }], // 上标/下标
|
|
|
- [{ indent: '-1' }, { indent: '+1' }], // 缩进
|
|
|
- // [{'direction': 'rtl'}], // 文本方向
|
|
|
- [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
|
|
|
- [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
|
|
|
- [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
|
|
|
- [{ font: [] }], // 字体种类
|
|
|
- [{ align: [] }], // 对齐方式
|
|
|
- ['clean'], // 清除文本格式
|
|
|
- ['link', 'image', 'video'], // 链接、图片、视频
|
|
|
- cusSpecial, // 特殊符号
|
|
|
- ];
|
|
|
-
|
|
|
- import { quillEditor } from 'vue-quill-editor';
|
|
|
- import * as Quill from 'quill';
|
|
|
- import * as Delta from 'quill-delta';
|
|
|
- import ImageResize from 'quill-image-resize-module';
|
|
|
- import StImage from './QuillEditorStBlockEmbed';
|
|
|
-
|
|
|
- Quill.register('modules/imageResize', ImageResize);
|
|
|
- Quill.register('formats/stImage', StImage);
|
|
|
-
|
|
|
- import 'quill/dist/quill.core.css';
|
|
|
- import 'quill/dist/quill.snow.css';
|
|
|
- import 'quill/dist/quill.bubble.css';
|
|
|
-
|
|
|
- import { getUploadImg } from '@/api/AlCloud';
|
|
|
- import { getUploadConfig } from '@/api/base64';
|
|
|
- import axios from 'axios';
|
|
|
- import store from '@/store';
|
|
|
-
|
|
|
- export default {
|
|
|
- props: {
|
|
|
- /*编辑器的内容*/
|
|
|
- value: {
|
|
|
- type: String,
|
|
|
- },
|
|
|
- flg: {
|
|
|
- type: String,
|
|
|
- },
|
|
|
- quillEditorRef: {
|
|
|
- type: String,
|
|
|
- },
|
|
|
- /*图片大小*/
|
|
|
- maxSize: {
|
|
|
- type: Number,
|
|
|
- default: 4000, //kb
|
|
|
- },
|
|
|
- },
|
|
|
- components: {
|
|
|
- quillEditor,
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- curLength: 0,
|
|
|
- uploadfileParam: {},
|
|
|
- content: this.value,
|
|
|
- quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
|
|
|
- editorOption: {
|
|
|
- theme: 'snow', // or 'bubble'
|
|
|
- placeholder: '请输入内容...',
|
|
|
- modules: {
|
|
|
- toolbar: {
|
|
|
- container: toolbarOptions,
|
|
|
- handlers: {
|
|
|
- image: function (value) {
|
|
|
- if (value) {
|
|
|
- // 触发input框选择图片文件
|
|
|
- // this.$refs[this.btnRef].click();
|
|
|
- this.container.parentElement.parentElement.children[0].children[0].children[0].click();
|
|
|
- this.container.parentElement.parentElement.children[1].click();
|
|
|
- } else {
|
|
|
- this.quill.format('image', false);
|
|
|
- }
|
|
|
- },
|
|
|
- 'formula': (value) => {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- this.curLength = quill.getSelection() ? quill.getSelection().index : 0;
|
|
|
- let chuck = this.getSelectionLatex();
|
|
|
- if (chuck) {
|
|
|
- this.formula.latex = chuck.latex;
|
|
|
- this.formula.type = chuck.type;
|
|
|
- } else {
|
|
|
- this.formula.latex = '';
|
|
|
- this.formula.type = '';
|
|
|
- }
|
|
|
-
|
|
|
- this.formula.dialogVisible = true;
|
|
|
- this.formula.quillEditorRef = this.quillEditorRef;
|
|
|
-
|
|
|
- store.commit({
|
|
|
- type: 'setFormula'
|
|
|
- , formula: this.formula,
|
|
|
- });
|
|
|
- },
|
|
|
- 'α': (value) => {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- /*quill.insertEmbed(length, 'image', `${multipartParams.url}/${multipartParams.key}`);
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + 1);*/
|
|
|
- quill.insertText(length, 'α');
|
|
|
- quill.setSelection(length + 1);
|
|
|
- },
|
|
|
- 'β': (value) => {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- /*quill.insertEmbed(length, 'image', `${multipartParams.url}/${multipartParams.key}`);
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + 1);*/
|
|
|
- quill.insertText(length, 'β');
|
|
|
- quill.setSelection(length + 1);
|
|
|
- },
|
|
|
- 'γ': (value) => {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- /*quill.insertEmbed(length, 'image', `${multipartParams.url}/${multipartParams.key}`);
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + 1);*/
|
|
|
- quill.insertText(length, 'γ');
|
|
|
- quill.setSelection(length + 1);
|
|
|
- },
|
|
|
- },
|
|
|
- },
|
|
|
- imageResize: {},
|
|
|
- },
|
|
|
- },
|
|
|
- // serverUrl: "/v1/blog/imgUpload", // 这里写你要上传的图片服务器地址
|
|
|
- header: {
|
|
|
- // token: sessionStorage.token
|
|
|
- }, // 有的图片服务器要求请求头需要有token
|
|
|
- currentImgSrc: '',
|
|
|
- sttipinputw: 0,
|
|
|
- sttipinputh: 0,
|
|
|
- formula: {
|
|
|
- dialogVisible: false,
|
|
|
- imgsrc: '',
|
|
|
- latex: '',
|
|
|
- type: '',
|
|
|
- quillEditorRef: '',
|
|
|
- },
|
|
|
- };
|
|
|
- },
|
|
|
-
|
|
|
- methods: {
|
|
|
-
|
|
|
- // describe: 此功能用户放切屏点击图片失去焦点 author: Wgy date:2020-07-07
|
|
|
- richtext(){
|
|
|
- window.onblur = null;
|
|
|
- this.$emit('richText','richtext');
|
|
|
- },
|
|
|
- onEditorBlur() {
|
|
|
- //失去焦点事件
|
|
|
- },
|
|
|
- onEditorFocus() {
|
|
|
- //获得焦点事件
|
|
|
- },
|
|
|
- onEditorChange() {
|
|
|
- //内容改变事件
|
|
|
- this.$emit('syncValue', this.flg, this.content);
|
|
|
- },
|
|
|
-
|
|
|
- // 富文本图片上传前
|
|
|
- beforeUpload() {
|
|
|
- // 显示loading动画
|
|
|
- this.quillUpdateImg = true;
|
|
|
- },
|
|
|
-
|
|
|
- uploadSuccess(res, file) {
|
|
|
- },
|
|
|
- // 富文本图片上传失败
|
|
|
- uploadError() {
|
|
|
- // loading动画消失
|
|
|
- this.quillUpdateImg = false;
|
|
|
- },
|
|
|
- uploadFileFun(truck) {
|
|
|
- var file = truck.file;
|
|
|
- const suffix = file.name.split('.').pop();
|
|
|
- var dd = new Date();
|
|
|
- var y = dd.getFullYear();
|
|
|
- var m = dd.getMonth() + 1;//获取当前月份的日期
|
|
|
- const options = {
|
|
|
- prefix: 'resource/QuillEditor/' + y + m + '/',
|
|
|
- suffix: suffix,
|
|
|
- };
|
|
|
-
|
|
|
- getUploadImg(options).then((res) => {
|
|
|
- if (res.code === 0) {
|
|
|
- // 二进制文件通过forData对象进行传递
|
|
|
- const FormDataForAl = new FormData();
|
|
|
- const multipartParams = Object.assign({}, res.data, {
|
|
|
- Filename: `images/${file.name}`,
|
|
|
- success_action_status: '200',
|
|
|
- });
|
|
|
- // 参数数据
|
|
|
- FormDataForAl.append('key', multipartParams.key);
|
|
|
- FormDataForAl.append('policy', multipartParams.policy);
|
|
|
- FormDataForAl.append('signature', multipartParams.signature);
|
|
|
- FormDataForAl.append('OSSAccessKeyId', multipartParams.accessid);
|
|
|
- FormDataForAl.append('success_action_status', multipartParams.success_action_status);
|
|
|
- // OSS要求, file放到最后
|
|
|
- FormDataForAl.append('file', file);
|
|
|
-
|
|
|
- axios.post(multipartParams.uploadUrl, FormDataForAl).then(alRes => {
|
|
|
- if (alRes.status === 200) {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- quill.insertEmbed(length, 'image', `${multipartParams.downloadUrl}/${multipartParams.key}`);
|
|
|
-
|
|
|
-
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + 1);
|
|
|
- }
|
|
|
- }).catch(alerr => {
|
|
|
- this.$message.error('图片插入失败');
|
|
|
- console.error('阿里云错误', alerr);
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
-
|
|
|
- },
|
|
|
- clearContent() {
|
|
|
- this.content = '';
|
|
|
- },
|
|
|
- setContent(val) {
|
|
|
- this.content = val;
|
|
|
- },
|
|
|
- quillEditorAddEventListener() {
|
|
|
- let dom = this.$refs[this.quillEditorRef].$el.children[1].children[0];
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- let that = this;
|
|
|
- var pasteFun = function (e) {
|
|
|
- var clipboardData = e.clipboardData;
|
|
|
- if (!(clipboardData && clipboardData.items)) {//是否有粘贴内容
|
|
|
- return;
|
|
|
- }
|
|
|
- for (var i = 0; i < clipboardData.items.length; i++) {
|
|
|
- var item = clipboardData.items[i];
|
|
|
- if (item.kind === 'string' && item.type === 'text/plain') {
|
|
|
- item.getAsString((str) => {
|
|
|
- // str 是获取到的字符串,创建文本框
|
|
|
- //处理粘贴的文字内容
|
|
|
- setTimeout(() => {
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入
|
|
|
- quill.insertText(length, str);
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + str.length);
|
|
|
- }, 50);
|
|
|
- });
|
|
|
- } else if (item.kind === 'file') {//file 一般是各种截图base64数据
|
|
|
- var pasteFile = item.getAsFile();
|
|
|
- // pasteFile就是获取到的文件
|
|
|
- var reader = new FileReader();
|
|
|
- reader.onload = function (event) {
|
|
|
- var base64Img = event.target.result;
|
|
|
- // image/png;base64,
|
|
|
- let base64ImgPrefix = base64Img.substring(0, base64Img.indexOf(',') + 1);
|
|
|
- let base64ImgData = base64Img.substring(base64Img.indexOf(',') + 1);
|
|
|
- let opt = {
|
|
|
- 'data': base64ImgData,
|
|
|
- 'prefix': 'resource/',
|
|
|
- 'suffix': base64ImgPrefix.substring(base64ImgPrefix.indexOf('/') + 1, base64ImgPrefix.indexOf(';')),
|
|
|
- };
|
|
|
- getUploadConfig(opt).then(res => {
|
|
|
- if (res.code === 0) {
|
|
|
- let uri = res.data;
|
|
|
-
|
|
|
- // 获取光标所在位置
|
|
|
- let length = quill.getSelection().index;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- quill.insertEmbed(length, 'image', uri);
|
|
|
- // 调整光标到最后
|
|
|
- quill.setSelection(length + 1);
|
|
|
- } else {
|
|
|
- that.$message.error('图片插入失败');
|
|
|
- }
|
|
|
-
|
|
|
- });
|
|
|
- }; // data url
|
|
|
- reader.readAsDataURL(pasteFile);
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- dom.removeEventListener('paste', pasteFun);
|
|
|
- dom.addEventListener('paste', pasteFun);
|
|
|
- },
|
|
|
-
|
|
|
- getSelectionLatex() {
|
|
|
- let type = '';
|
|
|
- let leaf = null;
|
|
|
- // 如果光标前一个是公式 取得公式的latex
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- let selection = quill.getSelection();
|
|
|
- if (!selection) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- if (selection.length === 0) {
|
|
|
- type = 'rightSingle';
|
|
|
- leaf = quill.getLeaf(selection.index);
|
|
|
- } else {
|
|
|
- type = 'selected';
|
|
|
- leaf = quill.getLeaf(selection.index + 1);
|
|
|
- }
|
|
|
- // let contents = quill.getContents();
|
|
|
-
|
|
|
- // let line = quill.getLine(selection.index);
|
|
|
- // let bounds = quill.getBounds(selection.index);
|
|
|
- // console.log(selection, leaf);
|
|
|
-
|
|
|
- if (leaf[0] instanceof StImage) {
|
|
|
- // console.log(leaf[0].domNode.dataset.latex);
|
|
|
- return {
|
|
|
- type: type,
|
|
|
- latex: leaf[0].domNode.dataset.latex,
|
|
|
- };
|
|
|
- }
|
|
|
- return null;
|
|
|
- },
|
|
|
- // Delta operation
|
|
|
- delQuillContent(index) {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- /*console.dir(quill);
|
|
|
- console.dir(quill.getSelection());
|
|
|
- console.dir(quill.getContents());*/
|
|
|
-
|
|
|
- // .insert('White', { color: '#fff' })
|
|
|
- var stDelta = new Delta().retain(index).delete(1);
|
|
|
- let quillContents = quill.getContents().compose(stDelta);
|
|
|
- quill.setContents(quillContents);
|
|
|
- },
|
|
|
- passValue() {
|
|
|
- // console.log('do passValue!!');
|
|
|
- let latex = this.formula.latex;
|
|
|
- if (latex.indexOf('placeholder') > -1) {
|
|
|
- this.formula.dialogVisible = false;
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- quill.setSelection(this.curLength);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (latex && latex !== '') {
|
|
|
-
|
|
|
- if (this.formula.type === 'rightSingle') {
|
|
|
- // del formula
|
|
|
- this.delQuillContent(this.curLength - 1);
|
|
|
-
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- // let length = quill.getSelection() ? quill.getSelection().index : 0;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- quill.insertEmbed(this.curLength - 1, 'stimage', {
|
|
|
- src: this.formula.imgsrc,
|
|
|
- 'data-latex': latex,
|
|
|
- });
|
|
|
- // quill.formatText(length, 1, { 'data-latex': latex });
|
|
|
- /*var delta = quill.getContents();
|
|
|
- console.log(delta);*/
|
|
|
- // 调整光标到最后
|
|
|
- // quill.insertText(length, img);
|
|
|
- quill.setSelection(this.curLength);
|
|
|
- } else if (this.formula.type === 'selected') {
|
|
|
- // del formula
|
|
|
- this.delQuillContent(this.curLength);
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- // let length = quill.getSelection() ? quill.getSelection().index : 0;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- quill.insertEmbed(this.curLength, 'stimage', {
|
|
|
- src: this.formula.imgsrc,
|
|
|
- 'data-latex': latex,
|
|
|
- });
|
|
|
- // quill.formatText(length, 1, { 'data-latex': latex });
|
|
|
- /*var delta = quill.getContents();
|
|
|
- console.log(delta);*/
|
|
|
- // 调整光标到最后
|
|
|
- // quill.insertText(length, img);
|
|
|
- quill.setSelection(this.curLength + 1);
|
|
|
- } else {
|
|
|
- let quill = this.$refs[this.quillEditorRef].quill;
|
|
|
- // 获取光标所在位置
|
|
|
- // let length = quill.getSelection() ? quill.getSelection().index : 0;
|
|
|
- // 插入图片 res.url为服务器返回的图片地址
|
|
|
- quill.insertEmbed(this.curLength, 'stimage', {
|
|
|
- src: this.formula.imgsrc,
|
|
|
- 'data-latex': latex,
|
|
|
- });
|
|
|
- // quill.formatText(length, 1, { 'data-latex': latex });
|
|
|
- /*var delta = quill.getContents();
|
|
|
- console.log(delta);*/
|
|
|
- // 调整光标到最后
|
|
|
- // quill.insertText(length, img);
|
|
|
- quill.setSelection(this.curLength + 1);
|
|
|
- this.formula.dialogVisible = false;
|
|
|
- }
|
|
|
-
|
|
|
- this.formula.dialogVisible = false;
|
|
|
- }
|
|
|
- },
|
|
|
- },
|
|
|
- mounted() {
|
|
|
-
|
|
|
- let checkCount = 0;
|
|
|
- let checkCountMax = 100;
|
|
|
- let stInterval = setInterval(() => {
|
|
|
- if (this.quillEditorRef) {
|
|
|
- clearInterval(stInterval);
|
|
|
- this.$nextTick(function () {
|
|
|
- this.quillEditorAddEventListener();
|
|
|
- });
|
|
|
- /*let dom = this.$refs[this.quillEditorRef].$el.children[1].children[0];
|
|
|
- const specialSignals = document.querySelectorAll('.ql-special-signal');
|
|
|
- for (const specialSignal of specialSignals) {
|
|
|
- // specialSignal.style.cssText = "width:80px; border:1px solid #ccc; border-radius:5px;";
|
|
|
- // specialSignal.style.cssText = "width:50px;";
|
|
|
- // specialSignal.innerText="特殊符号";
|
|
|
-
|
|
|
- specialSignal.classList.add('el-icon-edit-outline');
|
|
|
- specialSignal.title = "特殊符号";
|
|
|
- }*/
|
|
|
-
|
|
|
- for (const special of cusSpecial) {
|
|
|
- const specialSignals = document.querySelectorAll('.ql-' + special);
|
|
|
- for (const specialSignal of specialSignals) {
|
|
|
- // specialSignal.style.cssText = "width:80px; border:1px solid #ccc; border-radius:5px;";
|
|
|
- // specialSignal.style.cssText = "width:50px;";
|
|
|
- specialSignal.innerText = special;
|
|
|
-
|
|
|
- // specialSignal.classList.add('el-icon-edit-outline');
|
|
|
- specialSignal.title = special;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- } else {
|
|
|
- if (checkCount > checkCountMax) {
|
|
|
- clearInterval(stInterval);
|
|
|
- }
|
|
|
- }
|
|
|
- checkCount++;
|
|
|
- }, 100);
|
|
|
- /*监听富文本复制粘贴*/
|
|
|
- document.onpaste = function (e) {
|
|
|
- let arrPath = e.path;
|
|
|
- let has = false;
|
|
|
- if (arrPath) {
|
|
|
- for (const path of arrPath) {
|
|
|
- if (path.className && path.className.indexOf('ql-editor') > -1) {
|
|
|
- has = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (has) {
|
|
|
- e.preventDefault();
|
|
|
- }
|
|
|
- };
|
|
|
- },
|
|
|
- watch: {
|
|
|
- '$store.state.formula': {
|
|
|
- handler(newVal, oldVal) {
|
|
|
- // console.log('in store.state.formula');
|
|
|
- // console.log(newVal);
|
|
|
- this.formula = newVal;
|
|
|
- /*console.dir('======start=======');
|
|
|
- console.dir(this.formula.quillEditorRef);
|
|
|
- console.dir(this.quillEditorRef);
|
|
|
- console.dir('======end=======');*/
|
|
|
- if (this.formula.dialogVisible === false && this.formula.quillEditorRef === this.quillEditorRef) {
|
|
|
- this.passValue();
|
|
|
- }
|
|
|
- },
|
|
|
- deep: true,
|
|
|
- },
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
-</script>
|