安装

npm install vue-quill-editor --save

在main.js  引入

import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

在页面中引入

// 页面引入
import { quillEditor,Quill } from 'vue-quill-editor'
import Video from '../../../utils/video'
Quill.register(Video, true)

// 配置项
  editorOption: {
         modules:{
             toolbar:{
                container: [
                    ['bold', 'italic', 'underline', 'strike'], //加粗,斜体,下划线,删除线
                    [{ 'header': 1 }, { 'header': 2}], // 标题,键值对的形式;1、2表示字体大小
                    [{'list': 'ordered'}, {'list': 'bullet'}], //列表
                    [{ 'script': 'sub'}, {'script': 'super' }], // 上下标
                    [{ 'indent': '-1'}, {'indent': '+1'}], // 缩进
                    [{'direction': 'rtl' }], // 文本方向
                    ['clean'], //清除字体样式
                    ['image', 'video'] //上传图片、上传视频
                ],
                handlers: {
                  'video':(val)=>{
                    // 覆盖默认的上传视频
            this.onVideo();
                  },
                  'image':(value)=>{
            // 覆盖默认的图片上传
            // 获取光标所在的位置
                    var range = this.$refs.myQuillEditor.quill.getSelection();
                    if (range == null) {
                      this.indexVideo = 0;
                    } else {
                      this.indexVideo = range.index;
                    }
            // 点击隐藏的上传表单
                    if (value) {
                       document.querySelector('.avataruploaderTip input').click()
                    } else {
                      this.quill.format('image', false)
                    }
                  }
                }
             }
         },
         placeholder:'请输入'
    },
   // 相关变量

   indexVideo:0,
   videoUrl:'',
   videoTab:{
     tabUrl:true,
     tabUpd:false
   },
   videoProgress:false,
 
  // 声明组件
  components: {
     quillEditor
  },
// 富文本相关
    onVideo(){
        this.videoFlag = true;
         //当编辑器中没有输入文本时,这里获取到的 range 为 null   获取光标位置
        var range = this.$refs.myQuillEditor.quill.getSelection();
        if (range == null) {
          this.indexVideo = 0;
        } else {
          this.indexVideo = range.index;
        }
    },
    onVideoTab(val){  // 链接与视频上传 tab切换
      if(val == 1){
        this.videoTab.tabUrl = true;
        this.videoTab.tabUpd = false;
      }else{
        this.videoTab.tabUpd = true;
        this.videoTab.tabUrl = false;
      }
    },
    //上传视频
    uploadVideoTip(param){
       const formData = new FormData()
       formData.append('file', param.file)
       this.videoProgress = true;
       fetchUploadVideo(formData).then(response => {
            this.videoForm.showVideoPath = response.videoUrl;
       // 获取富文本
            let quill = this.$refs.myQuillEditor.quill
       // 在光标所在位置 插入视频
            quill.insertEmbed(this.indexVideo,'video', this.videoForm.showVideoPath)
            quill.setSelection(this.indexVideo + 1)
            this.videoProgress = false;
            this.videoFlag = false;
        });
    },
    // 上传图片链接
    upVideoUrl(){
      if(this.videoUrl){
         let quill = this.$refs.myQuillEditor.quill
         quill.insertEmbed(this.indexVideo,'video', this.videoUrl)
         quill.setSelection(this.indexVideo + 1)
         this.videoFlag = false;
      }else{
        this.$message({
            message: '请填写视频链接',
            type: 'warning'
        });
      }
    },
  // 图片上传
    uploadImgTip(param){
       const formData = new FormData()
       formData.append('file', param.file)
       fetchImg(formData).then(response => {
          let url = response.imgUrl
           let quill = this.$refs.myQuillEditor.quill
      // 插入图片链接
           quill.insertEmbed(this.indexVideo, 'image', url)
           quill.setSelection(this.indexVideo + 1)
        });
    },
  }
 
// 隐藏图片上传表单
     <el-upload  
        class="avataruploaderTip"
        ref="uploadtip"
        :limit="999"
        action="#"
        :show-file-list="false"
        :http-request="uploadImgTip"
        >
      </el-upload>
// 视频上传弹出框
  <el-dialog
      title="视频上传"
      :visible.sync="videoFlag"
      :close-on-click-modal="false"
      class="editerV"
      width="500px">
      <div class="editerVideo">
         <div class="editerVideo_title">
           <div :class="['editerVideo_title_item',videoTab.tabUrl?'editerVideo_title_act':''] " @click="onVideoTab(1)">添加链接</div>
           <div :class="['editerVideo_title_item',videoTab.tabUpd?'editerVideo_title_act':''] " @click="onVideoTab(2)">上传视频</div>
         </div>
         <div class="editerVideo_main">
            <div class="editerVideo_main_url" v-if="videoTab.tabUrl">
              <div>视频地址:</div>
              <el-input size="small" v-model="videoUrl" style="width:300px"></el-input>
              <el-button  type="primary"  style=" margin-left:10px;  height:30px" @click="upVideoUrl" size="small" >添加</el-button>
            </div>
            <div v-if="videoTab.tabUpd">
                <div v-if="videoProgress" class="videoProgress">视频上传中,请耐心等待!</div>
                <el-upload
                  v-else
                  class="avatar-uploader_video"
                  :limit=1
                  action="#"
                  :show-file-list="false"
                  :http-request="uploadVideoTip"
                >
                  <i class="el-icon-plus avatar-uploader-videoiocn"></i>
                </el-upload>
               
            </div>
         </div>
      </div>
  </el-dialog>
// 视频上传组件
.editerV /deep/ .el-dialog__body{
  padding: 0px 20px 20px 20px;
}
.editerVideo{
  width: 100%;
}
.editerVideo_title{
  display: flex;
  height: 30px;
  line-height: 30px;
  width: 100%;
  color: #1f2f3d;
  font-weight: bold;
  justify-content: flex-start;
  border-bottom: 2px solid #DCDFE6;
}
.editerVideo_title_act{
  color: #409eff;
  border-bottom: 2px solid #409eff;
  margin-bottom: -2px;
}
.editerVideo_title_item{
  margin-right: 10px;
}
.editerVideo_main{
  width: 100%;
  height: 120px;
}
.editerVideo_main_url{
  width: 100%;
  height: 200px;
  line-height: 30px;
  display: flex;
  flex-direction: row;
  justify-content:flex-start;
  margin-top: 35px;
}
.avatar-uploader_video{
  width: 100px;
  height: 100px;
  border: 1px solid #D9D9D9;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 30px;
}
.avatar-uploader-videoiocn {
  font-size: 28px;
  color: #D9D9D9;
  line-height: 90px;
  text-align: center;
}
.videoProgress{
  margin-top: 30px;
}
.quillWidthmain{
  width: 800px;
  height:320px;
}
.quillWidth{
  width:800px;
  height:270px;
}
 

video.js

import { Quill } from 'vue-quill-editor'
// 源码中是import直接倒入,这里要用Quill.import引入
const BlockEmbed = Quill.import('blots/block/embed')
const Link = Quill.import('formats/link') const ATTRIBUTES = ['height', 'width'] class Video extends BlockEmbed {
static create (value) {
const node = super.create(value)
// 添加video标签所需的属性
node.setAttribute('controls', 'controls')
node.setAttribute('type', 'video/mp4')
node.setAttribute('src', this.sanitize(value))
return node
}
static formats (domNode) {
return ATTRIBUTES.reduce((formats, attribute) => {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute)
}
return formats
}, {})
} static sanitize (url) {
return Link.sanitize(url) // eslint-disable-line import/no-named-as-default-member
} static value (domNode) {
return domNode.getAttribute('src')
} format (name, value) {
if (ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value)
} else {
this.domNode.removeAttribute(name)
}
} else {
super.format(name, value)
}
}
html () {
const { video } = this.value()
return `<a href="${video}">${video}</a>`
}
}
Video.blotName = 'video' //不用iframe,直接替换掉原来,如果需要也可以保留原来的,这里用个新的blot
Video.className = 'ql-video'
Video.tagName = 'video' // 用video标签替换iframe
export default Video

  

vue-quill-editor 自定义图片上传和视频上传的更多相关文章

  1. vue quill editor输入文字出现首字母的问题

    当使用vue quill editor输入中文时,第一个中文的汉语拼音第一个字母会显示如图. 解决的办法就是升级vue quill editor js文件的版本,目前的我升级之后ok的版本是 < ...

  2. 大文件上传-大视频上传,T级别的,求解决方案

    第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname =  ...

  3. Vue+Element UI 实现视频上传

    一.前言 项目中需要提供一个视频介绍,使用户能够快速.方便的了解如何使用产品以及注意事项. 前台使用Vue+Element UI中的el-upload组件实现视频上传及进度条展示,后台提供视频上传AP ...

  4. SpringBoot 整合文件上传 elment Ui 上传组件

    SpringBoot 整合文件上传 elment Ui 上传组件 本文章记录 自己学习使用 侵权必删! 前端代码 博主最近在学 elment Ui 所以 前端使用 elmentUi 的 upload ...

  5. vue项目富文本编辑器vue-quill-editor之自定义图片上传

    使用富文本编辑器的第一步肯定是先安装依赖 npm i vue-quill-editor 1.如果按照官网富文本编辑器中的图片上传是将图片转为base64格式的,如果需要上传图片到自己的服务器,需要修改 ...

  6. CKEditor5 + vue2.0 自定义图片上传、highlight、字体等用法

    因业务需求,要在 vue2.0 的项目里使用富文本编辑器,经过调研多个编辑器,CKEditor5 支持 vue,遂采用.因 CKEditor5 文档比较少,此处记录下引用和一些基本用法. CKEdit ...

  7. rails使用bootstrap3-wysiwyg可视化编辑器并实现自定义图片上传插入功能

    之前在rails开发中使用了ckeditor作为可视化编辑器,不过感觉ckeditor过于庞大,有很多不需要的功能,而且图片上传功能不好控制不同用户可以互相删除图片,感觉很不好.于是考虑更改可视化编辑 ...

  8. ueditor 百度编辑器 自定义图片上传路径和格式化上传文件名

    今天项目中需要自定义图片上传的保存路径,并且不需要按照日期自动创建存储文件夹和文件名,我的ueditor版本是1.3.6.下面记录一下我配置成功的方法,如果有什么不对的地方欢迎指出,共同学习: 1:我 ...

  9. vue+element-ui中的图片获取与上传

    vue+element-ui中的图片获取与上传 工作上接触了一下图片的处理,图片的格式是文件流, 记录如下. 请求图片 请求图片的时候,带上{ responseType: 'blob' }, 否则图片 ...

  10. vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式

    进入正题 1. PC端调用摄像头拍照上传base64格式到后台,这个没什么花里胡哨的骚操作,直接看代码 (canvas + video) <template> <div> &l ...

随机推荐

  1. Parallels Desktop 虚拟机网络地址

    bridge100 是宿主机在共享网络中的地址 bridge101 是宿主机在 Host-Only 网络中的地址 查询宿主机 IP 地址 $ ip addr show # 共享网络(默认) bridg ...

  2. 淘宝订单信息获取接口,淘宝开放平台R2权限,淘宝开放平台订单获取接口

    目前淘宝开放平台是关闭了订单权限申请的,有这方便的需求的人,除非是天猫用户才能申请(天猫用户申请到只能给自己天猫店授权),否则是申请不到这个订单接口了,如果有这方面需要的人可以联系我,站内信留下QQ或 ...

  3. 填坑 Plugin 'mysql_native_password' is not loaded

    数据库从 mysql5.7 升级到 mysql8.4,部分场景出现以下错误提示:Plugin 'mysql_native_password' is not loaded 原因是:mysql_nativ ...

  4. (零) React Native 项目开发拾遗

    一位离职的前端同事,最近接了个 React Native 的活儿,遇到许多搞不定的问题,于是找到我帮忙"补课"(没有系统的学习 React Native,也不具备原生 Androi ...

  5. 使用 `Roslyn` 分析器和修复器 对异步方法规范化返回Async结尾

    之前写过一篇使用修复器帮助添加头部注释文本的功能,今天使用Roslyn的代码修复器对异步返回方法规范化的功能 实现分析器 首先需要实现分析器,使用RegisterSyntaxNodeAction,分析 ...

  6. Blazor静态服务端呈现(静态SSR)身份认证

    本文介绍 Blazor 静态服务端呈现(静态 SSR)模式下,用户登录身份认证是如何实现的. 1. SSR 简介 SSR 是服务器侧呈现,HTML 是由服务器上的 ASP.NET Core 运行时生成 ...

  7. C#|.net core 基础 - 深拷贝的五大类N种实现方式

    在实际应用中经常会有这样的需求:获取一个与原对象数据相同但是独立于原对象的精准副本,简单来说就是克隆一份,拷贝一份,复制一份和原对象一样的对象,但是两者各种修改不能互相影响.这一行为也叫深克隆,深拷贝 ...

  8. ASP 封装基本身份认证( HTTP Basic Authenticate)辅助类

    最近修改一个古老的asp程序,需要为单独几个页面进行基本身份认证.由于IIS自带的设置基本身份认证是针对文件夹的,而这几个页面又不方便挪动位置,幸好在网上找到一个asp实现WWW-Authentica ...

  9. 高通USB overview

    一,Dedicated Connectivity Ports (USB) 1,USB 3.1 Type-C with DisplayPort 2,Support USB3-DisplayPort Co ...

  10. iOS关于屏蔽暗黑模式小结

    不想适配暗黑模式可以关闭暗黑模式:在xcode12之前的版本Info.plist文件中添加Key:User Interface Style,值类型设置为String,值为Light,就可以不管在什么模 ...