| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 | <template>  <div class="editor">    <quill-editor      class="ql-editor"      v-model="form"      ref="myAlias"      :options="editorOption"      @blur="onEditorBlur($event)"      @focus="onEditorFocus($event)"      @change="onEditorChange($event)"    ></quill-editor>    <el-upload      ref="ivuUpload"      class="ivu-upload"      style="height: 1px"      :show-file-list="false"      :on-success="handleSuccess"      accept=".jpg, .jpeg, .png"      :before-upload="beforeImgUpload"      :max-size="2048"      multiple      :action="ossUploadUrl"      :data="dataObj"    >      <p></p>    </el-upload>    <el-dialog      title="插入视频"      width="500px"      :visible.sync="dialogFormVisible"      append-to-body    >      <el-form :model="dialogForm" ref="diologForm" :rules="dialogFormRules">        <el-form-item label="封面图地址" label-width="90px">          <!--        v-loading="uploadImgLoading" -->          <el-upload            class="avatar-uploader"            style="line-height: 0; display: inline-block"            :show-file-list="false"            accept=".jpg, .jpeg, .png"            :on-success="handleImgSuccess"            :on-error="handleUploadImgError"            :before-upload="beforeImgUpload"            :action="ossUploadUrl"            :data="dataObj"          >            <img              width="300px"              v-if="dialogForm.poster"              :src="dialogForm.poster"              class="avatar"            />            <i v-else class="el-icon-plus avatar-uploader-icon"></i>          </el-upload>        </el-form-item>        <el-form-item label="视频类型" label-width="90px">          <el-radio-group v-model="formRadio">            <el-radio :label="1">外部链接</el-radio>            <el-radio :label="2">上传</el-radio>          </el-radio-group>        </el-form-item>        <el-form-item          v-if="formRadio == 1"          label="视频地址"          label-width="90px"          prop="url"        >          <el-input            v-model="dialogForm.url"            style="width: 100%"            autocomplete="off"          ></el-input>        </el-form-item>        <el-form-item          v-if="formRadio == 2"          label="上传视频"          label-width="90px"          prop="videoUrl"        >          <el-upload            class="upload-demo"            style="display: inline-block"            v-loading="uploadLoading"            :before-upload="beforeUpload"            :on-success="handleUploadSuccess"            :on-error="handleUploadError"            :show-file-list="false"            accept=".mp4"            :file-list="fileList"            :on-exceed="handleExceed"            :action="ossUploadUrl"            :data="dataObj"          >            <video              style="width: 120px; height: 120px"              v-if="dialogForm.videoUrl"              type="video/mp4"              preload="auto"              :src="dialogForm.videoUrl"            ></video>            <i v-else class="el-icon-plus avatar-uploader-icon"></i>          </el-upload>          <p class="imageSize">只能上传mp4文件, 且不超过100M</p>        </el-form-item>      </el-form>      <div slot="footer" class="dialog-footer">        <el-button @click="dialogFormVisible = false">取 消</el-button>        <el-button type="primary" @click="onVideoComfirm('diologForm')"          >确 定</el-button        >      </div>    </el-dialog>  </div></template><script>import { getToken } from "@/utils/auth";import "quill/dist/quill.core.css";import "quill/dist/quill.snow.css";import "quill/dist/quill.bubble.css";import Quill from "quill";import { quillEditor } from "vue-quill-editor";import { policy } from "@/api/appTenant";// 工具栏配置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", "middle", "large", "huge"] }], // 字体大小  [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色  [{ font: [] }], // 字体种类  [{ align: [] }], // 对齐方式  ["clean"], // 清除文本格式 // 链接、图片、视频 , "video"  ["link", "image", "video"] // 链接、图片、视频];// 标题const titleConfig = {  "ql-bold": "加粗",  "ql-color": "颜色",  "ql-font": "字体",  "ql-code": "插入代码",  "ql-italic": "斜体",  // 'ql-link': '添加链接',  "ql-background": "背景颜色",  "ql-size": "字体大小",  "ql-strike": "删除线",  "ql-script": "上标/下标",  "ql-underline": "下划线",  "ql-blockquote": "引用",  "ql-header": "标题",  "ql-indent": "缩进",  "ql-list": "列表",  "ql-align": "文本对齐",  "ql-direction": "文本方向",  "ql-code-block": "代码块",  "ql-formula": "公式",  "ql-image": "图片",  "ql-video": "视频",  "ql-clean": "清除字体样式",  "ql-upload": "文件"};// 这里引入修改过的video模块并注册import Video from "@/views/quill/video.js";import dayjs from "dayjs";Quill.register(Video, true);let that;export default {  // props: ["form",'key'],  props: {    id: "",    keyWord: {      type: String,      default: "content"    },    form: {      type: String    },    alias: {      type: String,      default: "myQuillEditor"    },    bucket_name: {      type: String,      default: "daya"    }  },  name: "editor",  components: { quillEditor },  data() {    return {      content: null,      headers: {        Authorization: getToken()      },      dialogFormVisible: false,      dialogForm: {        poster: null,        url: null,        videoUrl: null      },      uploadLoading: false,      uploadImgLoading: false,      fileList: [],      dialogFormRules: {        url: [{ required: true, message: "请输入视频地址", trigger: "blur" }],        videoUrl: [{ required: true, message: "请上传视频", trigger: "blur" }]      },      formRadio: 1,      editorOption: {        placeholder: "请输入内容",        modules: {          toolbar: {            container: toolbarOptions,            handlers: {              image: value => {                if (value) {                  // 调用iview图片上传                  let editor = this.editor;                  // this.ActiveEditor = this.editor                  this.editorIndex = editor.getSelection()?.index || 0;                  this.$refs.ivuUpload.$children[0].$refs.input.click();                } else {                  this.quill.format("image", false);                }              },              video: value => {                if (value) {                  this.dialogFormVisible = true;                  let editor = this.editor;                  // this.ActiveEditor = this.editor                  // 光标所在位置                  this.editorIndex = editor.getSelection()?.index || 0;                } else {                  this.quill.format("image", false);                }              }            }          }        }      },      ActiveEditor: null,      dataObj: {        policy: "",        signature: "",        key: "",        KSSAccessKeyId: "",        // dir: "",        acl: "public-read",        name: ""      },      // ossUploadUrl: "https://ks3-cn-beijing.ksyuncs.com/" + this.bucket_name,      ossUploadUrl: `https://${this.bucket_name}.ks3-cn-beijing.ksyuncs.com`    };  },  created() {},  mounted() {    that = this;    // console.log(this.form);\  },  methods: {    onEditorBlur({ quill, html, text }) {      //失去焦点事件      // console.log('失去焦点');    },    onEditorFocus($event) {      console.log($event, this.id);      this.ActiveEditor = $event;      //获得焦点事件      // console.log('获得焦点事件');    },    onEditorChange({ quill, html, text }) {      this.$emit("onEditorChange", html);      // this.form = html;    },    onVideoComfirm(formName) {      this.$refs[formName].validate(valid => {        if (valid) {          let dialogForm = this.dialogForm;          // 获取富文本组件实例          let quill = this.editor;          console.log(quill, this.keyWord);          // 插入图片,res为服务器返回的图片链接地址          const params = {            poster: dialogForm.poster,            url: this.formRadio == 1 ? dialogForm.url : dialogForm.videoUrl          };          quill.insertEmbed(this.editorIndex, "video", params);          // 调整光标到最后          quill.setSelection(this.editorIndex + 1, { preload: false });          this.dialogFormVisible = false;          this.dialogForm = {            poster: null,            url: null,            videoUrl: null          };        } else {          return false;        }      });    },    handleSuccess(res) {      // 获取富文本组件实例      let quill = this.ActiveEditor;      // 光标所在位置      // 如果上传成功      // return;      let url = this.ossUploadUrl + "/" + this.dataObj.key;      if (url) {        // 获取光标所在位置        let length = quill.getSelection().index || 0;        // 插入图片,res为服务器返回的图片链接地址        quill.insertEmbed(length, "image", url);        // 调整光标到最后        quill.setSelection(length + 1);      } else {        // 提示信息,需引入Message        this.$message.error("图片插入失败");      }    },    addQuillTitle() {      const oToolBar = document.querySelector(".ql-toolbar"),        aButton = oToolBar.querySelectorAll("button"),        aSelect = oToolBar.querySelectorAll("select");      aButton.forEach(function(item) {        if (item.className === "ql-script") {          item.value === "sub" ? (item.title = "下标") : (item.title = "上标");        } else if (item.className === "ql-indent") {          item.value === "+1"            ? (item.title = "向右缩进")            : (item.title = "向左缩进");        } else {          item.title = titleConfig[item.classList[0]];        }      });      aSelect.forEach(function(item) {        item.parentNode.title = titleConfig[item.classList[0]];      });    },    handleUploadImgError(file) {      this.uploadImgLoading = false;      this.$message.error("上传失败");    },    handleImgSuccess(res, file) {      this.uploadImgLoading = false;      let url = this.ossUploadUrl + "/" + this.dataObj.key;      this.dialogForm.poster = url;    },    async beforeImgUpload(file) {      const imageType = {        "image/png": true,        "image/jpeg": true      };      const isImage = imageType[file.type];      const isLt2M = file.size / 1024 / 1024 < 2;      isImage, isLt2M;      if (!isImage) {        this.$message.error("只能上传图片格式!");      }      if (!isLt2M) {        this.$message.error("上传图片大小不能超过 2MB!");      }      if (isImage && isLt2M) {        this.uploadImgLoading = true;      }      try {        let fileName = file.name.replaceAll(" ", "_");        let key = new Date().getTime() + fileName;        let obj = {          filename: fileName,          bucketName: this.bucket_name,          postData: {            filename: fileName,            acl: "public-read",            key: key,            unknowValueField: []          }        };        const res = await policy(obj);        this.dataObj = {          policy: res.data.policy,          signature: res.data.signature,          key: key,          KSSAccessKeyId: res.data.kssAccessKeyId,          // dir: "",          acl: "public-read",          name: fileName          // bucket_name: props.bucket_name        };      } catch (e) {        console.log(e);        return false;      }      return isImage && isLt2M;    },    // handleAvatarSuccess(res, file) {    //   this.form.coverImage = res.data.url;    // },    beforeAvatarUpload(file) {      const imageType = {        "image/png": true,        "image/jpeg": true      };      const isImage = imageType[file.type];      const isLt2M = file.size / 1024 / 1024 < 2;      if (!isImage) {        this.$message.error("只能上传图片格式!");      }      if (!isLt2M) {        this.$message.error("上传图片大小不能超过 2M!");      }      return isImage && isLt2M;    },    async beforeUpload(file) {      // const isJPG = file.type === 'image/jpeg';      const isLt2M = file.size / 1024 / 1024 < 100;      //   if (!isJPG) {      //     this.$message.error('上传头像图片只能是 JPG 格式!');      //   }      if (!isLt2M) {        this.$message.error("上传视频大小不能超过 100MB!");      }      this.uploadLoading = true;      try {        let fileName = file.name.replaceAll(" ", "_");        let key = new Date().getTime() + fileName;        let obj = {          filename: fileName,          bucketName: this.bucket_name,          postData: {            filename: fileName,            acl: "public-read",            key: key,            unknowValueField: []          }        };        const res = await policy(obj);        this.dataObj = {          policy: res.data.policy,          signature: res.data.signature,          key: key,          KSSAccessKeyId: res.data.kssAccessKeyId,          // dir: "",          acl: "public-read",          name: fileName          // bucket_name: props.bucket_name        };      } catch (e) {        console.log(e);        return false;      }      return isLt2M;    },    handleUploadError(file) {      this.uploadLoading = false;      this.$message.error("上传视频失败");    },    handleUploadSuccess(file, fileList) {      this.uploadLoading = false;      let url = this.ossUploadUrl + "/" + this.dataObj.key;      this.dialogForm.videoUrl = url;    },    handleExceed(files, fileList) {      this.$message.error("您已上传过视频");    }  },  computed: {    editor() {      return this.$refs.myAlias.quill;    },    ActiveEditors() {      console.log(this.id);      return this.ActiveEditor;    }  }};</script><style lang="scss" scoped>::v-deep .ql-editor {  min-height: 250px;  padding: 0;}::v-deep .ql-container .ql-editor {  max-height: 500px;}::v-deep .ql-snow .ql-editor img {  max-width: 95%;}</style>
 |