vue-quill-editor 富文本图片、视频上传设置

<template>
  <div class="card" style="overflow: hidden; padding-bottom: 10px">
    <div class="box">
      <div>
        <div class="box_count">
          <div class="box_l">
            <FlexLinePI :title="'图文标题'" :dropshow="true">
              <el-input
                v-model="ruleForm.title"
                maxlength="50"
                type="text"
                placeholder="请输入标题"
              >el-input>
            FlexLinePI>
            <FlexLinePI :title="'图文摘要'" :dropshow="true"
              ><el-input
                v-model="ruleForm.note"
                type="textarea"
                maxlength="200"
                show-word-limit
                rows="5"
                placeholder="请输入正文详情"
              >el-input>
            FlexLinePI>
            <FlexLinePI :title="'封面图片'" :dropshow="true">
              <el-upload
                class="avatar-uploader"
                :action="upload"
                :show-file-list="false"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload"
              >
                <img
                  v-if="ruleForm.cover"
                  :src="ruleForm.cover"
                  class="avatar"
                />
                <i v-else class="el-icon-plus avatar-uploader-icon">i>
                <div slot="tip" class="el-upload__tip">
                  建议上传图片尺寸800*800px,大小不超过5M
                div>
              el-upload>
            FlexLinePI>
            <FlexLinePI :title="''" :dropshow="false">
              <div>
                <div class="rich-uploader">
                  
                  <el-upload
                    class="rich-uploader2"
                    name="pic"
                    action=""
                    :show-file-list="false"
                    :http-request="httpRequest"
                  >
                  el-upload>
                  <el-upload
                    class="rich-uploader3"
                    name="pic"
                    action=""
                    :show-file-list="false"
                    :http-request="httpRequestvideo"
                  >
                  el-upload>
                div>
                <quill-editor
                  v-model="ruleForm.content"
                  ref="quillEditor"
                  :options="editorOption"
                >
                quill-editor>
              div>
            FlexLinePI>
            <div class="buttom">
              <el-button type="primary" @click="addandedit(0)">保存el-button>
              <el-button type="primary" @click="addandedit(1)"
                >保存并发布el-button
              >
              
            div>
          div>
          <div
            class="box_r"
            :style="{
              'background-image': `url(${require('../../../assets/images/phone.png')}`,
            }"
          >
            <div class="box_r_informationurl">
              <div class="box_r_inImg">
                <img
                  src="../../../assets/images/authorlogo.png"
                  alt=""
                  srcset=""
                  style="width: 100%; height: 100%"
                />
              div>
              <div class="box_r_inlanguage">
                <p
                  style="-webkit-line-clamp: 1; font-size: 18px"
                  class="ellipsis"
                >
                  {{ ruleForm.title != "" ? ruleForm.title : "请输入标题" }}
                p>
                <div style="display: flex; margin-top: 5px; height: 90px">
                  <div style="flex: 1; -webkit-line-clamp: 5" class="ellipsis">
                    {{ ruleForm.note != "" ? ruleForm.note : "请输入正文详情" }}
                  div>
                  <div class="box_r_inlanguageimg">
                    <img
                      :src="ruleForm.cover != '' ? ruleForm.cover : urlimg"
                      alt=""
                      srcset=""
                      style="width: 100%; height: 100%"
                    />
                  div>
                div>
              div>
            div>
          div>
        div>
      div>
    div>
  div>
template>
<script>
import step from "@/components/EchartsChart/nextstep.vue";
import { upload, uploadvideo } from "@/api/common.js";
import { quillEditor, Quill } from "vue-quill-editor";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import axios from "axios";
import {
  detailGraphic,
  addGraphic,
  updateGraphic,
} from "@/api/material/index.js";
// 引入修改video模块并注册
import video from "@/assets/js/quillVideo.js";
Quill.register(video);
export default {
  name: "AddImageText",
  components: { quillEditor, step },
  computed: {
    quill() {
      const { quill } =  this.$refs.quillEditor || {} 
      return quill;
    },
  },
  data() {
    const toolbarOptions = [
      ["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"] }], // 字体大小
      [{ header: [1, 2, 3, 4, 5, 6, false] }], //几级标题

      [{ color: [] }, { background: [] }], // 字体颜色,字体背景颜色
      [{ font: [] }], //字体
      [{ align: [] }], //对齐方式

      ["clean"], //清除字体样式
      ["image"], //上传图片
      ["video"], // 视频
    ];
    return {
      upload: upload,
      uploadvideo: uploadvideo,
      ruleForm: {
        id: "",
        title: "",
        note: "",
        cover: "",
        content: "",
      },
      // 视频
      progress: 0,
      // 富文本
      editorOption: {
        placeholder: "请输入内容",
        theme: "snow",
        modules: {
          toolbar: {
            container: toolbarOptions, // 工具栏
            handlers: {
              image: function (value) {
                if (value) {
                  console.log(value);
                  // 触发input框选择图片文件
                  document.querySelector(".rich-uploader2 input").click();
                } else {
                  this.quill.format("image", false);
                }
              },
              video: function (value) {
                if (value) {
                  console.log(value);
                  // 触发input框选择图片文件
                  document.querySelector(".rich-uploader3 input").click();
                } else {
                  this.quill.format("video", false);
                }
              },
            },
          },
        },
      },
      // 上传图片
      urlimg: require("../../../assets/images/gift.png"),

      // 当前id
      updateId: sessionStorage.getItem("updateId")
        ? sessionStorage.getItem("updateId")
        : "",
    };
  },
  mounted() {
    if (this.updateId == "" || this.updateId == null) {
      this.ruleForm = {
        id: "",
        title: "",
        note: "",
        cover: "",
        content: "",
      };
    } else {
      // 详情
      this.getdetail(this.updateId);
    }
  },
  computed: {},
  methods: {
    //
    handleAvatarSuccess(res, file) {
      if (res.status == 1) {
        this.ruleForm.cover = res.data.real_path;
      }
    },
    beforeAvatarUpload(file) {
      const isLt2M = file.size / 1024 / 1024 < 5;
      if (!isLt2M) {
        this.$message.error("上传头像图片大小不能超过 5MB!");
      }
      return isLt2M;
    },
    // 详情
    getdetail(id) {
      detailGraphic({
        id: id,
      })
        .then((res) => {
          if (res.status == 1) {
            this.ruleForm = {
              id: res.data.id,
              title: res.data.title,
              note: res.data.note,
              cover: res.data.cover,
              content: res.data.content,
            };
          } else {
            this.$message.warning(res.msg || "数据响应过慢,请稍后再试");
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    //  步骤 2 =====================================================
    httpRequest(item) {
      let quill = this.$refs.quillEditor.quill;
      let formdata = new FormData();
      formdata.append("file", item.file, item.file.name);
      formdata.append("type", "1");
      let length = quill.getSelection().index;
      quill.insertEmbed(length, "image", item.file);
      axios
        .post(upload, formdata, {
          header: { "Content-Type": "multipart/form-data" },
        })
        .then((res) => {
          if (res.data.status == 1) {
            let length = quill.getSelection().index;
            // 插入图片  服务器返回的图片地址
            quill.insertEmbed(length, "image", res.data.data.real_path);
            //       // 调整光标到最后
            quill.setSelection(length + 1);
          } else {
            this.$message.warning(res.msg || "数据响应过慢,请稍后再试");
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },

    // ==============================================================
    // 保存编辑
    addandedit(val) {
      if (this.updateId == "" || this.updateId == null) {
        let tmpParams = {
          id: "",
          title: this.ruleForm.title, // 时间
          note: this.ruleForm.note, // 时间
          cover: this.ruleForm.cover,
          content: this.ruleForm.content,
          is_publish: val,
        };
        this.sever(tmpParams);
      } else {
        let tmpParams = {
          id: this.updateId,
          title: this.ruleForm.title, // 时间
          note: this.ruleForm.note, // 时间
          cover: this.ruleForm.cover,
          content: this.ruleForm.content,
          is_publish: val,
        };
        this.edit(tmpParams);
      }
    },
    // 保存
    sever(val) {
      addGraphic(val)
        .then((res) => {
          if (res.status == 1) {
            this.dialogVisible = false;
            this.$router.push({
              name: "ImageText",
            });
          } else {
            this.$message.warning(res.msg || "数据响应过慢,请稍后再试");
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 编辑
    edit(val) {
      updateGraphic(val)
        .then((res) => {
          if (res.status == 1) {
            this.dialogVisible = false;
            this.$router.push({
              name: "ImageText",
            });
          } else {
            this.$message.warning(res.msg || "数据响应过慢,请稍后再试");
          }
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 视频上传 =================
    httpRequestvideo(item) {
      let chunkSize = 1024 * 1024 * 5; // 每个切片的大小(这里设置为1MB)
      let totalChunks = Math.ceil(item.file.size / chunkSize); // 总切片数
      let currentChunk = 1; // 当前切片索引
      const uploadNextChunk = () => {
        const formData = new FormData();
        formData.append("name", item.file.name);
        formData.append("data", item.file);
        formData.append("total", totalChunks);
        formData.append("index", currentChunk);
        formData.append("filename", item.file.name);
        axios
          .post(uploadvideo + "?act=upload", formData, {
            headers: { "Content-Type": "multipart/form-data" },
            onUploadProgress: (progressEvent) => {
              this.progress = Math.round(
                (currentChunk * 100 +
                  progressEvent.loaded / progressEvent.total) /
                  totalChunks
              );
            },
          })
          .then((res) => {
            currentChunk++;
            if (currentChunk < totalChunks + 1) {
              uploadNextChunk();
            } else {
              this.progress = 0; // 上传完成后重置进度
              let date = {
                name: item.file.name,
                data: item.file,
                total: totalChunks,
                index: currentChunk,
                filename: item.file.name,
              };
              this.uploadok(date);
            }
          })
          .catch((error) => {
            console.error("Error uploading file:", error);
          });
      };
      uploadNextChunk();
    },
    uploadok(val) {
      let quill = this.$refs.quillEditor.quill;
      let formdata = new FormData();
      formdata.append("name", val.name);
      formdata.append("data", val.data);
      formdata.append("total", val.total);
      formdata.append("index", val.index);
      formdata.append("filename", val.filename);
      // let length = quill.getSelection().index;
      // quill.insertEmbed(length, "video", val.data);
      axios
        .post(uploadvideo + "?act=join", formdata, {
          headers: { "Content-Type": "multipart/form-data" },
        })
        .then((res) => {
          if (res.data.status == 1) {
            let length = quill.getSelection().index;
            // 插入图片  服务器返回的图片地址
            quill.insertEmbed(length, "video", res.data.path);
            // 调整光标到最后
            quill.setSelection(length + 1);
          } else {
            this.$message.warning(res.msg || "数据响应过慢,请稍后再试");
          }
        })
        .catch((error) => {
          console.error("Error uploading file:", error);
        });
    },
  },
};
script>
<style scoped lang='less'>
p {
  margin: 0;
  padding: 0;
}
.box {
  width: 90%;
  margin: 0 auto;
  padding: 10px 0;
  .box_count {
    display: flex;
    // justify-content: center;
    .box_l {
      width: 50%;
    }
    .box_r {
      width: 320px;
      height: 580px;
      margin: 10px 10px 10px 100px;
      background-size: 100% 100%;
      // box-shadow: 0 0 10px 0 #ccc;
      border-radius: 25px;
      position: relative;
      .box_r_informationurl {
        width: 100%;
        margin-top: 60px;
        display: flex;
        padding: 30px;
        .box_r_inImg {
          width: 50px;
          height: 50px;
          margin-left: 10px;
        }
        .box_r_inlanguage {
          flex: 1;
          margin: 0 10px;
          background: #ffffff;
          padding: 10px;
          border-radius: 5px;
          .box_r_inlanguageimg {
            width: 50px;
            height: 50px;
          }
        }
      }
    }
  }
  .buttom {
    display: flex;
    justify-content: center;
    margin: 10px 0;
  }
}
/deep/ .ql-container {
  height: 600px;
}
/deep/ .avatar {
  border-radius: 0;
}
style>

// 文件主要是使视频video替换ifrom标签的文档进行使用


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);
  }

  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 `${video}`;
  }
}
Video.blotName = "video"; // 这里不用改,楼主不用iframe,直接替换掉原来,如果需要也可以保留原来的,这里用个新的blot
Video.className = "ql-video";
Video.tagName = "video"; // 用video标签替换iframe

export default Video;

你可能感兴趣的:(vue.js,音视频)