| | |
| | | <template> |
| | | <div :style="styleEditor"> |
| | | <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" /> |
| | | <Editor :style="style" class="declass" v-model="html" :defaultConfig="editorConfig" :mode="mode" |
| | | <Editor style="min-height: 80px; overflow-y: hidden;" v-model="html" :defaultConfig="editorConfig" :mode="mode" |
| | | @onCreated="onCreated" @onChange="onChange" /> |
| | | </div> |
| | | </template> |
| | |
| | | <script> |
| | | import Vue from 'vue' |
| | | import { Editor, Toolbar } from '@wangeditor/editor-for-vue' |
| | | import { Loading } from 'element-ui' |
| | | import { Loading } from 'element-ui'; |
| | | let loadingInstance = null |
| | | export default Vue.extend({ |
| | | props: { |
| | |
| | | default: '' |
| | | }, |
| | | styleEditor: '', |
| | | style:'', |
| | | readonly: false // 是否可以输入 |
| | | readonly: false, // 是否可以输入 |
| | | }, |
| | | name: 'RichEditor', |
| | | name:'RichEditor', |
| | | components: { Editor, Toolbar }, |
| | | data () { |
| | | data() { |
| | | return { |
| | | editor: null, |
| | | html: '', |
| | | toolbarConfig: { // 工具栏配置 |
| | | toolbarKeys: this.readonly ? ['fullScreen'] : [ // 显示指定的菜单项 |
| | | 'bold', // 粗体 |
| | | 'underline', // 下划线 |
| | | 'italic', // 斜体 |
| | | 'through', // 删除线 |
| | | 'code', // 行内代码 |
| | | 'sub', // 下标 |
| | | 'sup', // 上标 |
| | | 'clearStyle', // 清除格式 |
| | | 'color', // 字体颜色 |
| | | 'bgColor', // 背景色 |
| | | 'fontSize', // 字号 |
| | | 'fontFamily', // 字体 |
| | | 'indent', // 增加缩进 |
| | | 'delIndent', // 减少缩进 |
| | | 'justifyLeft', // 左对齐 |
| | | 'justifyRight', // 右对齐 |
| | | 'justifyCenter', // 居中对齐 |
| | | 'justifyJustify', // 两端对齐 |
| | | 'lineHeight', // 行高 |
| | | toolbarKeys: this.readonly ? ["fullScreen"]: [ // 显示指定的菜单项 |
| | | "bold", // 粗体 |
| | | "underline", // 下划线 |
| | | "italic", // 斜体 |
| | | "through", // 删除线 |
| | | "code", // 行内代码 |
| | | "sub", // 下标 |
| | | "sup", // 上标 |
| | | "clearStyle", // 清除格式 |
| | | "color", // 字体颜色 |
| | | "bgColor", // 背景色 |
| | | "fontSize", // 字号 |
| | | "fontFamily", // 字体 |
| | | "indent", // 增加缩进 |
| | | "delIndent", // 减少缩进 |
| | | "justifyLeft", // 左对齐 |
| | | "justifyRight", // 右对齐 |
| | | "justifyCenter", // 居中对齐 |
| | | "justifyJustify", // 两端对齐 |
| | | "lineHeight", // 行高 |
| | | // "viewImageLink", // 查看链接 |
| | | 'divider', // 分割线 |
| | | 'emotion', // 表情 |
| | | 'insertLink', // 插入链接 |
| | | "divider", // 分割线 |
| | | "emotion", // 表情 |
| | | "insertLink", // 插入链接 |
| | | // "editLink", // 修改链接 |
| | | // "unLink", // 取消链接 |
| | | // "viewLink", // 查看链接 |
| | | 'codeBlock', // 代码块 |
| | | 'blockquote', // 引用 |
| | | 'headerSelect', // 标题 |
| | | "codeBlock", // 代码块 |
| | | "blockquote", // 引用 |
| | | "headerSelect", // 标题 |
| | | // "header1", // 标题1 |
| | | // "header2", // 标题2 |
| | | // "header3", // 标题3 |
| | | // "header4", // 标题4 |
| | | // "header5", // 标题5 |
| | | // "todo", // 待办 |
| | | 'redo', // 重做 |
| | | 'undo', // 撤销 |
| | | "redo", // 重做 |
| | | "undo", // 撤销 |
| | | // "enter", // 回车 |
| | | // "bulletedList", // 无序列表 |
| | | // "numberedList", // 有序列表 |
| | |
| | | "tableHeader", // 表头 |
| | | "tableFullWidth", // 宽度自适应 |
| | | ] // 下级菜单 key ,必填 |
| | | }, */ |
| | | },*/ |
| | | // 上传图片分组 |
| | | { |
| | | key: 'img-style', // 必填,要以 group 开头 |
| | | title: '图片', // 必填 |
| | | // iconSvg: '<svg>....</svg>', // 可选 |
| | | menuKeys: [ |
| | | 'uploadImage', // 上传图片 |
| | | 'insertImage', // 网络图片 |
| | | 'deleteImage', // 删除图片 |
| | | 'editImage', // 编辑图片 |
| | | 'imageWidth30', // 图片宽度相对于编辑器宽度的百分比30 |
| | | 'imageWidth50', // 图片宽度相对于编辑器宽度的百分比50 |
| | | 'imageWidth100' // 图片宽度相对于编辑器宽度的百分比100 |
| | | "uploadImage", // 上传图片 |
| | | "insertImage", // 网络图片 |
| | | "deleteImage", // 删除图片 |
| | | "editImage", // 编辑图片 |
| | | "imageWidth30", // 图片宽度相对于编辑器宽度的百分比30 |
| | | "imageWidth50", // 图片宽度相对于编辑器宽度的百分比50 |
| | | "imageWidth100", // 图片宽度相对于编辑器宽度的百分比100 |
| | | ] // 下级菜单 key ,必填 |
| | | }, |
| | | // 视频分组 |
| | |
| | | title: '视频', // 必填 |
| | | // iconSvg: '<svg>....</svg>', // 可选 |
| | | menuKeys: [ |
| | | 'insertVideo', // 插入网络视频 |
| | | 'uploadVideo', // 上传视频 |
| | | 'editVideoSize' // 修改视频尺寸 |
| | | "insertVideo", // 插入网络视频 |
| | | "uploadVideo", // 上传视频 |
| | | "editVideoSize", // 修改视频尺寸 |
| | | ] // 下级菜单 key ,必填 |
| | | }, |
| | | 'fullScreen' // 全屏 |
| | | "fullScreen", // 全屏 |
| | | ], |
| | | excludeKeys: [ // 隐藏指定的菜单项 |
| | | // 'headerSelect', |
| | | // 'video-style' |
| | | // 排除菜单组,写菜单组 key 的值即可 |
| | | ] |
| | | ], |
| | | |
| | | }, |
| | | editorConfig: { // 编辑器配置 |
| | |
| | | MENU_CONF: { |
| | | // 图片上传 |
| | | uploadImage: { |
| | | server: process.env.VUE_APP_API_PREFIX + '/web/public/uploadLocal?folder=', |
| | | server: process.env.VUE_APP_API_PREFIX + '/public/uploadLocal?folder=', |
| | | fieldName: 'file', |
| | | // 单个文件的最大体积限制,默认为 2M |
| | | maxFileSize: 20 * 1024 * 1024, // 10M |
| | | maxFileSize: 10 * 1024 * 1024, // 10M |
| | | // 最多可上传几个文件,默认为 100 |
| | | maxNumberOfFiles: 10, |
| | | // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 [] |
| | |
| | | // 跨域是否传递 cookie ,默认为 false |
| | | withCredentials: true, |
| | | // 超时时间,默认为 10 秒 |
| | | timeout: 10 * 1000, // 10 秒 |
| | | timeout: 10 * 1000, //10 秒 |
| | | // 上传前 |
| | | onBeforeUpload (files) { |
| | | onBeforeUpload(files) { |
| | | loadingInstance = Loading.service({ |
| | | lock: true, |
| | | text: '上传中...', |
| | | spinner: 'el-icon-loading', |
| | | background: 'rgba(0, 0, 0, 0.7)' |
| | | }) |
| | | return files |
| | | }); |
| | | return files; |
| | | }, |
| | | // 自定义插入图片 |
| | | customInsert (res, insertFn) { |
| | | console.log(res) |
| | | customInsert(res, insertFn) { |
| | | console.log(res); |
| | | // 因为自定义插入导致onSuccess与onFailed回调函数不起作用,自己手动处理 |
| | | // 先关闭等待的Message |
| | | loadingInstance = Loading.service({ |
| | |
| | | text: '上传中...', |
| | | spinner: 'el-icon-loading', |
| | | background: 'rgba(0, 0, 0, 0.7)' |
| | | }).close() |
| | | }).close(); |
| | | if (res.code === 200) { |
| | | // Message.success({ |
| | | // message: `${res.data.originalName} 上传成功` |
| | |
| | | // message: `${res.data.originalName} 上传失败,请重新尝试` |
| | | // }); |
| | | } |
| | | insertFn(res.data.url, res.data.originname, res.data.imgname) |
| | | insertFn(res.data.url, res.data.originname, res.data.imgname); |
| | | }, |
| | | |
| | | // 单个文件上传成功之后 |
| | | onSuccess (file, res) { |
| | | console.log(`${file.originalFilename} 上传成功`, res) |
| | | onSuccess(file, res) { |
| | | console.log(`${file.originalFilename} 上传成功`, res); |
| | | }, |
| | | // 单个文件上传失败 |
| | | onFailed (file, res) { |
| | | console.log(`${file.originalFilename} 上传失败`, res) |
| | | loadingInstance.close() |
| | | onFailed(file, res) { |
| | | console.log(`${file.originalFilename} 上传失败`, res); |
| | | loadingInstance.close(); |
| | | }, |
| | | // 上传进度的回调函数 |
| | | onProgress (progress) { |
| | | console.log('progress', progress) |
| | | onProgress(progress) { |
| | | console.log('progress', progress); |
| | | // progress 是 0-100 的数字 |
| | | }, |
| | | // 上传错误,或者触发 timeout 超时 |
| | | onError (file, err, res) { |
| | | loadingInstance.close() |
| | | console.log(`${file.originalFilename} 上传出错`, err, res) |
| | | onError(file, err, res) { |
| | | loadingInstance.close(); |
| | | console.log(`${file.originalFilename} 上传出错`, err, res); |
| | | } |
| | | }, |
| | | // 视频上传 |
| | |
| | | // 超时时间,默认为 30 秒 |
| | | timeout: 1000 * 1000, // 1000 秒, |
| | | // 上传之前触发 |
| | | onBeforeUpload (file) { |
| | | return file |
| | | onBeforeUpload(file) { |
| | | return file; |
| | | }, |
| | | // 自定义插入视频 |
| | | customInsert (res, insertFn) { |
| | | customInsert(res, insertFn) { |
| | | // 因为自定义插入导致onSuccess与onFailed回调函数不起作用,自己手动处理 |
| | | // 先关闭等待的Message |
| | | // Message.closeAll(); |
| | |
| | | // message: `${res.data.originalName} 上传失败,请重新尝试` |
| | | // }); |
| | | } |
| | | insertFn(res.data.url, res.data.url) |
| | | insertFn(res.data.url, res.data.url); |
| | | }, |
| | | // 上传进度的回调函数 |
| | | onProgress (progress) { |
| | | console.log(progress) |
| | | onProgress(progress) { |
| | | console.log(progress); |
| | | // onProgress(progress) { // JS 语法 |
| | | // progress 是 0-100 的数字 |
| | | }, |
| | |
| | | // this.errorMsg(file); |
| | | // }, |
| | | // 上传错误,或者触发 timeout 超时 |
| | | onError (file, err, res) { |
| | | console.log(`${file.name} 上传出错`, err, res) |
| | | onError(file, err, res) { |
| | | console.log(`${file.name} 上传出错`, err, res); |
| | | // Notification.error({ |
| | | // title: '错误', |
| | | // message: `${file.name} 上传失败,请重新尝试` |
| | |
| | | } |
| | | } |
| | | }, |
| | | mode: 'default' // or 'simple' |
| | | mode: 'default', // or 'simple' |
| | | } |
| | | }, |
| | | watch: { |
| | | richData: function (value) { |
| | | this.html = value |
| | | console.log("onChange123", value); // onChange 时获取编辑器最新内容 |
| | | this.$nextTick(()=>{ |
| | | this.html = value |
| | | }) |
| | | }, |
| | | readonly: function (value) { |
| | | this.readonly = value |
| | | }, |
| | | styleEditor: function (value) { |
| | | this.styleEditor = value |
| | | } |
| | | }, |
| | | }, |
| | | mounted () { |
| | | mounted() { |
| | | // 需要在编辑器创建完毕后在赋值 |
| | | this.$nextTick(() => { |
| | | this.$nextTick(()=>{ |
| | | this.html = this.richData |
| | | }) |
| | | }, |
| | | methods: { |
| | | // 编辑器创建完毕时的回调函数 |
| | | onCreated (editor) { |
| | | onCreated(editor) { |
| | | var that =this |
| | | this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错 |
| | | setTimeout(function (){ |
| | | that.html = that.richData |
| | | // alert(that.html) |
| | | },15000) |
| | | }, |
| | | // 编辑器内容、选区变化时的回调函数 |
| | | onChange (editor) { |
| | | onChange(editor) { |
| | | this.$emit('getWangedditor', editor.getHtml()) |
| | | console.log('onChange', editor.getHtml()) // onChange 时获取编辑器最新内容 |
| | | } |
| | | console.log("onChange", editor.getHtml()); // onChange 时获取编辑器最新内容 |
| | | }, |
| | | }, |
| | | beforeDestroy () { |
| | | beforeDestroy() { |
| | | // 编辑器销毁时的回调函数。调用 editor.destroy() 即可销毁编辑器 |
| | | const editor = this.editor |
| | | if (editor == null) return |
| | |
| | | } |
| | | }) |
| | | </script> |
| | | <style lang="scss"> |
| | | .declass{ |
| | | min-height: 80px; overflow-y: hidden; |
| | | <style> |
| | | ::v-deep .w-e-text-container { |
| | | height: 420px !important; |
| | | } |
| | | </style>> |
| | | .w-e-text-container .w-e-scroll { |
| | | height: 500px !important; |
| | | -webkit-overflow-scrolling: touch; |
| | | } |
| | | </style> |
| | | |