Vue中实现富文本功能,适配小程序端,uniapp也可实现,vue-quill-editor适配小程序,将vue-quill-editor插件中的class样式换为style内联样式达到适配目的

小程序 0

1、Vue中实现富文本功能

1.1 拓展功能,上传图片从系统图片素材库中拉取图片,黏贴图片时,图片也存入图片素材库中

2、将自带的class样式换为style内联样式

3、适配小程序端(仅展示,不需要编辑)

4、小程序端新增编辑富文本

1、Vue中实现富文本功能

  1. 使用插件 vue-quill-editor ,先下载插件
npm insatll --save vue-quill-editor
  1. 在main.js 中引入
import VueQuillEditor from 'vue-quill-editor' //富文本import * as Quill from 'quill'import 'quill/dist/quill.core.css'import 'quill/dist/quill.snow.css'import 'quill/dist/quill.bubble.css'Vue.use(VueQuillEditor);
  1. 封装富文本组件 textEditor
    uploadPictures 为图片素材库 ,引入自己的素材库,
    vxe-model 是vxe 插件的弹框组件
    diyConfig 为组件传参,默认file,调用本地电脑上的图片,libImgStore为使用素材库中的图片
    imgData 为调用图片素材库时必要的传参
    getContent 为编辑时富文本Html传参

函数
editorFn 回调函数 返回值进行下一步处理

// 组件 textEditor.vue<template>  <div>    <quill-editor class="editor" ref="myTextEditor" v-model="content" :options="editorOption" @blur="onEditorBlur($event)"      @focus="onEditorFocus($event)" @ready="onEditorReady($event)" @change="(e)=>onEditorChange(e)" >    </quill-editor>    <vxe-modal  v-model="modalPic" width="1200" height="720" min-width="860"  id="imgUpdata" min-height="420" resize remember storage transfer   :esc-closable="true">      <template v-slot:title>        <span >素材库</span>      </template>      <uploadPictures :isChoice="imageData.isChoice" @getPic="getPic" @getPicD="getPicD" v-if="modalPic" :storeId.sync="imageData.storeId"></uploadPictures>    </vxe-modal>  </div></template><script>// 图片素材库引入 uploadPictures import uploadPictures from '@/components/uploadPictures';import axios from "axios";  export default {    props: {      getContent:{        type: String,        default:""      },      diyConfig:{//自定义配置        type: Object,        default:()=>{          return {            image:'file',//file 上传图片从电脑文件中选择,libImgStore 微商城素材库          }        }      },      imageData:{        type: Object,        default:()=>{          return {}// storeId 店号,isChoice:多选单选        }      }    },    components: {      uploadPictures,    },    mounted() {      this.$nextTick(() => {        const quill = this.$refs.myTextEditor.quill        quill.root.addEventListener('paste', this.handlePaste)        //获取图片库中的分类        if(this.diyConfig.image == 'libImgStore'){          this.getClassList()        }      })    },    data() {      return {        content: null,        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: ["small", false, "large", "huge"]                  size: ['14px', '16px', '18px', '20px', '24px', '28px', '32px']                }], // 字体大小                [{                  header: [1, 2, 3, 4, 5, 6, false]                }], // 标题                [{                  color: []                }, {                  background: []                }], // 字体颜色、字体背景颜色                [{                  font: ['SimSun',                    'SimHei',                    'Microsoft-YaHei',                    'KaiTi',                    'FangSong']                }], // 字体种类                [{                  align: []                }], // 对齐方式                ["clean"], // 清除文本格式                ["link", "image", "video"] // 链接、图片、视频              ],//工具菜单栏配置              handlers: {                'image': (e)=>this.imageHandle(e,this.quill)              }            }           },          placeholder: '添加内容...', //提示          readyOnly: false, //是否只读          theme: 'snow', //主题 snow/bubble          syntax: true, //语法检测        },        modalPic: false,        isHandlingImage: false,      }    },    directives: {      quillImageAdded: {        bind(el, binding) {          el.addEventListener('paste', (event) => {            console.log(event,"paste")            if (event.target.tagName === 'IMG') {              binding.value(event.target.src);            }          });        }      }    },    methods: {      // 失去焦点      onEditorBlur() {        // console.log(editor)      },      // 获得焦点      onEditorFocus() {        // console.log(editor)      },      // 开始      onEditorReady() {        // console.log(editor)      },      // 值发生变化      onEditorChange(editor) {        this.content = editor.html;        this.$emit('update:editor', this.content)        this.$emit('editorFn', this.content)      },      clearContent() {        this.content = ''      },      getClassList(){        this.$http.GET('/MA/mallPsdClassify/psdClassList').then(data => {        this.classList = data.data        this.formDatas[1].options = data.data.map(item => {          item.value = item.classifyId;          item.name = item.classifyId + '--' + item.classifyName;          return item;        });      })      },      imageHandle(e,quill){        if(this.diyConfig && this.diyConfig.image == 'libImgStore'){          if (e) {            alert('点击了上传图片')          } else {            quill.format('image', false);          }        }else{          quill.format('image', '');        }      },      // 获取图片信息      getPic(pc) {        let quill = this.$refs.myTextEditor.quill;        const range = quill.getSelection(true);        console.log(pc,"pc",range)        if (!range) return;        quill.insertEmbed(range.index, "image", pc.picUrl);        this.modalPic = false;      },      getPicD(pc) {        let quill = this.$refs.myTextEditor.quill;        const range = quill.getSelection(true);        if (!range) return;          // 将图片插入到富文本编辑器中        pc.reverse()        pc.forEach(element => {          quill.insertEmbed(range.index, "image", element.picUrl);        });        this.modalPic = false;      },      handlePaste(event) {        const clipboardData = event.clipboardData || window.clipboardData        if (!clipboardData) return        const items = clipboardData.items        if (!items) return        for (let i = 0; i < items.length; i++) {          const item = items[i]          if (item.type.indexOf('image') !== -1) {            const file = item.getAsFile()            // 处理粘贴的图片文件            this.handleImageUpload(file)          }        }      },      async handleImageUpload(file) {        this.isHandlingImage = false;        if(!this.isHandlingImage && this.diyConfig.image && this.diyConfig.image == 'libImgStore'){          this.isHandlingImage = true;          console.log(this.modalPic,"image.png",this.isHandlingImage)          if(this.modalPic){            this.isHandlingImage = false;            return           }          const formData = new FormData()          formData.append('file', file); // 有的后台需要传文件名,不然会报错          formData.append("type", 'image');          formData.append("storeId", this.imageData.storeId);          // 发送图片到服务器上传          axios ({            method: "post",            url: "/manager/crm-wx/wechat/media/uploadMedia",            data: formData,            headers: {              "Content-Type": "multipart/form-data"            }          }).then(res=>{            if (res.data.code==200 && res.data.data.url!=null) {                // 上传成功将照片传回父组件                const imageUrl =  res.data.data.url;                let obj = {                  classifyId:this.classList[0].classifyId,                  classifyName: this.classList[0].classifyName,                  media_id: res.data.data.media_id,                  picUrl: imageUrl,                  picName: file.name,                }                //图片上传成功后添加到图片素材库分类中                this.$http.POSTJSON("/MA/mallPsdClassifyRef/merge", [obj])                .then(data => {                  if (data.code == 200) {                    this.delDiyImg()                    // // 上传成功后,在富文本框中插入图片                    const quill = this.$refs.myTextEditor.quill                    const range = quill.getSelection(true)                    quill.insertEmbed(range.index, 'image', imageUrl)                    quill.setSelection(range.index + 1)                    // this.onEditorChange({html:this.content})                    // 在富文本框中展示图片                    // 如果你不想展示上传失败的图片,则可以省略这一步                    // quill.format('image', imageUrl)                  }else{                    this.$message.warning("图片上传失败1!")                    this.delDiyImg()                  }                });            }else{              this.$message.warning("图片上传失败2!")              this.delDiyImg()            }            this.isHandlingImage = false;          }).catch(err=>{            console.log(err,"err")            this.$message.warning("图片上传失败3!")            this.delDiyImg()            this.isHandlingImage = false;          })        }      },      delDiyImg(){        const quill = this.$refs.myTextEditor.quill        const index = quill.getSelection().index        quill.deleteText(index-1, 1)      }    },    computed: {      editor() {        return this.$refs.myTextEditor.quillEditor;      }    },    watch: {      getContent: {        handler(newVal) {          console.log(newVal,"newVal")          this.content = newVal;        },        immediate: true      },      diyConfig: {        handler(newVal) {          if(newVal && newVal.image == 'libImgStore'){            let that = this            this.editorOption.modules.toolbar.handlers.image = function(val){              if (val) {                that.modalPic = true;              } else {                this.quill.format('image', false);              }            }          }else{            delete this.editorOption.modules.toolbar.handlers.image          }        },        immediate: true      }    }  }</script><style lang="scss">.ql-editor u ,.ql-snow u{  text-decoration: underline;}.ql-editor s,del , .ql-snow s,del{  text-decoration: line-through;}.ql-editor i,em , .ql-snow i,em{  font-style: italic;}.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="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="32px"]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {  content: "32px";  font-size: 32px;}.ql-size-32px {  font-size: 32px;}  .editor {    line-height: normal !important;  }  .ql-snow .ql-tooltip[data-mode=link]::before {    content: "请输入链接地址:" !important;  }  .ql-snow .ql-tooltip.ql-editing a.ql-action::after {    border-right: 0px;    content: '保存' !important;    padding-right: 0px;  }  .ql-snow .ql-tooltip[data-mode=video]::before {    content: "请输入视频地址:" !important;  }  .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;  }  .quill-editor .ql-editor .ql-container img{    max-width: 400px;  }</style>

在页面中使用

<textEditor ref="editor" :editor.sync="content" :getContent="getContent" :diyConfig="{image:'libImgStore'}" :imageData="{storeId: form.storeId,isChoice:'多选'}"  style="width:340px;"  @editorFn="editorFn"></textEditor>

此时富文本已经可以使用了

2、 将自带的class样式换为style内联样式

可以参考文档 https://www.kancloud.cn/liuwave/quill/1409946#_61

将main.js 中引入的文件换为 下面文件

import VueQuillEditor from 'vue-quill-editor' //富文本import * as Quill from 'quill'import 'quill/dist/quill.core.css'import 'quill/dist/quill.snow.css'import 'quill/dist/quill.bubble.css'// 设置字体大小const fontSizeStyle = Quill.import('attributors/style/size') // 引入这个后会把样式写在style上fontSizeStyle.whitelist = [ '14px', '16px', '18px', '20px', '24px', '28px', '32px']Quill.register(fontSizeStyle, true)const Font = Quill.import('attributors/style/font') // 引入这个后会把样式写在style上const fonts = [  'SimSun',  'SimHei',  'Microsoft-YaHei',  'KaiTi',  'FangSong']Font.whitelist = fonts // 将字体加入到白名单Quill.register(Font, true)var Align = Quill.import('attributors/style/align')Quill.register(Align, true)var Direction = Quill.import('attributors/style/direction')Quill.register(Direction, true)Vue.use(VueQuillEditor);

在这里插入图片描述
中间这个部分 会在写入样式时,写入style样式,达到目的
其中的 whitelist 、fonts、这两个数组赋值,是将富文本自带的数组换为自定义的数组了

查看原本数据 可以 console.log(Quill.imports) 单独打印出来看

3、 小程序中展示(仅展示,不编辑)

使用uview 中自带的富文本功能,Parse只需把富文本传值传入即可展示,对应的样式查看官方文档
https://v1.uviewui.com/components/parse.html
基本使用,长按复制,样式设置 等功能都能满足 (注意有1.0版本和2.0 版本)根据下载的插件看不同版本的文档

4、小程序中新增、编辑管理端中存入的富文本

1、下载插件

https://ext.dcloud.net.cn/plugin?id=12013 富文本插件
下载到自己项目中

2、把不需要的功能屏蔽,或者如果有满足不了的可以自己开发。

在这里插入图片描述

源码中 上传图片代码有两处,根据平台不同,找到对应代码,图片我默认给宽度100%了,所以我控制了不让调整大小,更剧自己需求具体适配
在微信小程序中适配是 // #ifdef MP 从这以下的代码
在这里插入图片描述

在这里插入图片描述
添加一个参数用来控制富文本的样式 ,我主要是用来更改他的高度
在这里插入图片描述

下载插件后的代码 piaoyi-editor 更改完后的代码,可直接复制替换

<template>	<view class="container-editor">		<view class="textarea">			<view class="page-body">				<view class='wrapper ql-editor'>					<PickerColor ref="colorPicker" :color="{r: 255,g: 0,b: 0,a: 0.6}" @confirm="confirm"></PickerColor>					<view class='toolbar' @tap="format">						<view :class="formats.fontSize === '24px' ? 'ql-active' : ''" class="iconfont icon-font-size"							data-name="fontSize" data-value="24px"></view>						<view :class="formats.color? 'ql-active' : ''" class="iconfont icon-zitiyanse" data-name="color" :data-value="formats.color">						</view>						<view :class="formats.header === 1 ? 'ql-active' : ''" class="iconfont icon-formatheader1"							data-name="header" :data-value="1"></view>						<view :class="formats.header === 2 ? 'ql-active' : ''" class="iconfont icon-formatheader2"							data-name="header" :data-value="2"></view>						<view :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" data-name="bold">						</view>						<view :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti"							data-name="italic"></view>						<view :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian"							data-name="underline"></view>						<view :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-shanchuxian"							data-name="strike"></view>						<view :class="formats.align === 'left' ? 'ql-active' : ''" class="iconfont icon-zuoduiqi"							data-name="align" data-value="left"></view>						<view :class="formats.align === 'center' ? 'ql-active' : ''" class="iconfont icon-juzhongduiqi"							data-name="align" data-value="center"></view>						<view :class="formats.align === 'right' ? 'ql-active' : ''" class="iconfont icon-youduiqi"							data-name="align" data-value="right"></view>						<view :class="formats.align === 'justify' ? 'ql-active' : ''" class="iconfont icon-zuoyouduiqi"							data-name="align" data-value="justify"></view>						<!-- <view :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-LineHeight"							data-name="lineHeight" data-value="2"></view>						<view :class="formats.letterSpacing ? 'ql-active' : ''" class="iconfont icon-Character-Spacing"							data-name="letterSpacing" data-value="2em">						</view> -->						<!-- <view :class="formats.marginTop ? 'ql-active' : ''" class="iconfont icon-duanqianju"							data-name="marginTop" data-value="10px"></view>						<view :class="formats.previewarginBottom ? 'ql-active' : ''" class="iconfont icon-duanhouju"							data-name="marginBottom" data-value="10px"></view> -->						<!-- <view class="iconfont icon-rili4" @tap="insertDate"></view> -->						<!-- <view class="iconfont icon-checklist" data-name="list" data-value="check"></view> -->						<view :class="formats.list === 'ordered' ? 'ql-active' : ''" class="iconfont icon-youxupailie"							data-name="list" data-value="ordered"></view>						<view :class="formats.list === 'bullet' ? 'ql-active' : ''" class="iconfont icon-wuxupailie"							data-name="list" data-value="bullet"></view>					<!-- 	<view class="iconfont icon-outdent" data-name="indent" data-value="-1"></view>						<view class="iconfont icon-indent" data-name="indent" data-value="+1"></view> -->						<!-- <view class="iconfont icon-fengexian" @tap="insertDivider"></view> -->						<view class="iconfont icon-charutupian" @tap="insertImage"></view>						<view class="iconfont icon-undo" @tap="undo"></view>						<view class="iconfont icon-redo" @tap="redo"></view>						<view class="iconfont icon-format" @tap="clear"></view>					</view>					<!-- showImgResize -->					<editor id="editor" class="editor" placeholder="开始输入..." showImgSize showImgToolbar 						@statuschange="onStatusChange" :read-only="readOnly" @ready="onEditorReady" :style="[editStyle]"						@input="saveContens">					</editor>				</view>			</view>		</view>	</view></template><script>	import PickerColor from "./color-picker.vue"	export default {		components: {			PickerColor		},		props: {			api: {				type: String,				default: ''			},			photoUrl: {				type: String,				default: ''			},			values: {				type: String,				default: ''			},			readOnly: {				type: Boolean,				default: false			},			maxlength: {				type: Number,				default: 300			},			name: {				type: String,				default: 'file'			},			editStyle: {				type: Object,				default: ()=>{}			},		},		data() {			return {				currentTab: 0,				curColor: '#000000',				show: true,				hdid: "",				myHtml: "",				formats: {}			}		},		methods: {			showPicker() {				this.$refs.colorPicker.open()			},			confirm(e) {				this.editorCtx.format('color', e.hex)			},			saveContens() {				let that = this;				let maxlength = parseInt(that.maxlength);				that.editorCtx.getContents({					success: function(res) {						let html_text = res.html;						let html_length = html_text.length;						if (html_length > maxlength) {							uni.showModal({								title: '最多只能输入' + maxlength + '字',								confirmText: '确定',								showCancel: false,								success(res) {									that.$emit("changes", {										html: res.html,										length: html_length									});								}							});						} else {							that.$emit("changes", {								html: res.html=='<p><br></p>'?'':res.html,								length: html_length							});						}					},				})			},			update() {				//获取一下是否有数据				let that = this;				setTimeout(() => {					that.editorCtx.setContents({						"html": that.values					});				}, 1000)			},			onEditorReady() {				let that = this;				uni.createSelectorQuery().in(this).select('#editor').context((res) => {					that.editorCtx = res.context;					that.update();				}).exec((result) => {});			},			undo() {				this.editorCtx.undo()			},			redo() {				this.editorCtx.redo()			},			format(e) {				let {					name,					value				} = e.target.dataset				if (!name) return				if (name == 'color') {					this.showPicker()				} else {					this.editorCtx.format(name, value)				}			},			onStatusChange(e) {				const formats = e.detail				this.formats = formats			},			insertDivider() {				this.editorCtx.insertDivider();			},			clear() {				let that = this				this.editorCtx.clear({					success: res=>{						this.$emit("changes",{html:""})					}				});			},			insertDate() {				const date = new Date()				const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`				this.editorCtx.insertText({					text: formatDate				})			},			insertImage() {				let that = this;				// #ifdef APP-PLUS || H5				uni.chooseImage({					count: 1, //默认9					sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有					sourceType: ['album'], //从相册或者相机选择					success: (res) => {						const tempFilePaths = res.tempFilePaths[0]						if (!this.api || !this.photoUrl) {							that.editorCtx.insertImage({								src: tempFilePaths,								alt: '图像',								success: function() {}							})							uni.showToast({								title: '未传入api字段或者photoUrl字段,此为临时图片路径',								duration: 3000,								icon: 'none'							})						} else {							uni.uploadFile({								url: this.photoUrl + this.api,								filePath: tempFilePaths,								name: this.name,								formData: {},								success: (uploadFileRes) => {									var obj = JSON.parse(uploadFileRes.data)									if (obj.code == 200) {										this.img = this.photoUrl + '/' + obj.data										wx.showToast({											title: obj.msg,											icon: 'none'										})										this.editorCtx.insertImage({											src: this.img,											alt: '图像',											width: "100%",											success: function() {												const imageElement = document.querySelector('.custom-image-class');												console.log(imageElement,"imageElement")												if (imageElement) {													imageElement.style.width = '100%'; // 设置宽度为20px												}											}										})									} else {										wx.showToast({											title: obj.msg,											icon: 'none'										})									}								}							});						}					},					fail() {						uni.showToast({							title: '未授权访问相册权限,请授权后使用',							icon: 'none'						})					}				});				// #endif				// #ifdef MP				uni.chooseMedia({					count: 1,					mediaType: ['image'],					sourceType: ['album'],					sizeType: 'compressed',					success: (chooseImageRes) => {						const tempFilePaths = chooseImageRes.tempFiles[0].tempFilePath;						console.log(tempFilePaths)						if (!this.api || !this.photoUrl) {							that.editorCtx.insertImage({								src: tempFilePaths,								alt: '图像',								success: function() {}							})							uni.showToast({								title: '未传入api字段或者photoUrl字段,此为临时图片路径',								duration: 3000,								icon: 'none'							})						} else {							uni.uploadFile({								url: this.photoUrl + this.api,								filePath: tempFilePaths,								name: this.name,								formData: {},								success: (uploadFileRes) => {									var obj = JSON.parse(uploadFileRes.data)									console.log(obj,"uploadFileRes")									if (obj.code == 200) {										// this.img = path + '/' + obj.data										this.img =  obj.data.url										wx.showToast({											title: obj.msg,											icon: 'none'										})										this.editorCtx.insertImage({											src: this.img,											alt: '图像',											width: "100%",											success: function() {}										})									} else {										wx.showToast({											title: obj.msg,											icon: 'none'										})									}								},								fail(err) {									console.log(err)									uni.showToast({										title: err.errMsg,										icon: 'none'									})								}							});						}					}				})				// #endif			}		}	}</script><style>	@import url('iconfont.css');	.tabs {		display: flex;		justify-content: space-around;		background-color: #FFFFFF;	}	.tabs .current {		border-bottom: 2px solid #0369D6;	}	.tabs .tab {		font-size: 32upx;	}	.main {		padding: 20upx;		background-color: #FFFFFF;	}	.main .item {		display: flex;		justify-content: space-between;		line-height: 80upx;		border-bottom: 1px solid #F2F2F2;	}	.main .item .left {		min-width: 200upx;	}	.main .title {		padding-bottom: 20upx;		font-weight: bold;		border-bottom: 1px solid #F2F2F2;	}	.main .textarea {		border: 1px solid #F2F2F2;	}	.wrapper {		padding: 0 10upx;	}	.iconfont {		display: inline-block;		width: 9%;		cursor: pointer;		font-size: 40upx !important;		text-align: center;		padding: 10upx 0;	}	.icon-rili4 {		font-size: 48upx !important;	}	.icon-duanqianju,	.icon-duanhouju,	.icon-zitijiacu,	.icon-zitixieti,	.icon-zitixiahuaxian,	.icon-shanchuxian {		font-size: 36upx !important;	}	.toolbar {		box-sizing: border-box;		border-bottom: 0;		margin-bottom: 10upx;			}	.ql-container {		box-sizing: border-box;		width: 100%;		min-height: 600upx;		height: auto;		background: #fff;		font-size: 32upx;		line-height: 1;		padding-bottom: 60upx;	}	/deep/ .ql-editor.ql-blank:before {		font-size: 28upx;		font-style: inherit;	}	.ql-active {		color: #ff0000;	}	button {		width: 150upx;		font-size: 30upx;	}	.editor {		color: #333;	}</style>

插件已经修改为成后,就可以在页面中使用了

3、在页面中使用

注意下面部分需要换成自己的接口
在这里插入图片描述
完整代码 如下

<template>	<view class="richtext">		<piaoyiEditor :values="desc" :maxlength="3000" @changes="saveContens" :readOnly="readOnly" :photoUrl="photoUrl"			:api="api" :name="name" :editStyle="editStyle"/>		<view class="q-flex-center q-position-fixed-Bottom q-borderBox u-p-b-20 u-p-t-20 q-shadow  bottomBar">			<view class="buttonSTY" @click="submit">				确认			</view>		</view>	</view></template><script>	import piaoyiEditor from '@/uni_modules/piaoyi-editor/components/piaoyi-editor/piaoyi-editor.vue';	export default {		data() {			return {				readOnly: false, //是否只读				photoUrl: '', //服务器图片域名或者ip				api: '/wechat/media/uploadMedia', //上传图片接口地址				txt: '',				name: 'file',				desc: '<div>11111222</div>',				editStyle: {					height: "calc(100vh - 130px)",				}			};		},		components: {			piaoyiEditor		},		onLoad(option){			this.desc = decodeURIComponent(option.desc);			this.txt = this.desc;		},		onShow() {			this.photoUrl = this.$common.api_url+this.$common.fileserver;			this.api = `/wechat/media/uploadMedia?type=image&storeId=${uni.getStorageSync('shopNo')}`;		}, 		methods: {			saveContens(e) {				console.log(e,"e")				this.txt = e.html			},			submit(){				let that = this;				let pages = getCurrentPages()				let prevPage = pages[pages.length - 2];				uni.navigateBack({					delta: 1,					success() {						prevPage.$vm.richTextSubmit(encodeURIComponent(that.txt));					},				})			},		},	}</script><style scoped>	.bottomBar{		background: #fff;	}	.buttonSTY{		width: 600rpx;		text-align: center;		background: #FC6B3A;		height: 80rpx;		font-size: 30rpx;		line-height: 80rpx;		color: #f3f3f3;		border-radius: 40rpx;	}</style>

也许您对下面的内容还感兴趣: