Browse Source

富文本添加自定义按钮

DESKTOP-SVI9JE1\muzen 1 year ago
parent
commit
78a7b94156
1 changed files with 80 additions and 236 deletions
  1. 80 236
      src/components/Editor/index.vue

+ 80 - 236
src/components/Editor/index.vue

@@ -2,77 +2,26 @@
   <div ref="body">
     <el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess"
       :on-error="handleUploadError" :data="data" name="file" :show-file-list="false" :headers="headers"
-      style="display: none" ref="upload" v-if="isShow()">
+      style="display: none" ref="upload" v-if="type == 'url'">
     </el-upload>
-    <el-upload :action="audioUrl" :before-upload="handleBeforeAudio" :on-success="handleAudioSuccess"
-      :on-error="handleAudioError" :data="audioData" :show-file-list="false" :headers="headers" style="display: none"
-      ref="audio" v-if="isShow()" v-loading.fullscreen.lock="fullScreenLoading">
-    </el-upload>
-    <div class="editor" ref="editor" :style="styles"></div>
-
-    <!-- 弹窗 -->
-    <el-dialog :visible.sync="dialogVisible" title="选择音频" width="1000px">
-      <el-form inline size="mini">
-        <el-form-item label="音频类型:">
-          <el-select v-model="dialogForm.audioType" placeholder="请选择音频类型">
-            <el-option v-for="item in audioTypeOptions" :key="item.value" :value="item.value" :label="item.label" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="资源平台:">
-          <el-select v-model="dialogForm.platformId" placeholder="请选择资源平台" clearable>
-            <el-option v-for="item in platformOptions" :key="item.value" :value="item.value" :label="item.label" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="付费状态:">
-          <el-select v-model="dialogForm.isFree" placeholder="请选择付费类型" clearable>
-            <el-option v-for="item in freeOptions" :key="item.value" :label="item.label" :value="item.value" />
-          </el-select>
+    <div class="editor" ref="editor" :style="styles" />
+
+    <!-- 视频弹出框 -->
+    <el-popover popper-class="ql-popover" width="398" ref="popover">
+      <el-form>
+        <el-form-item label="视频链接">
+          <el-input v-model="videoForm.src" placeholder="请输入视频链接">
+            <template slot="append">
+              <Upload @upload="upload" />
+            </template>
+          </el-input>
         </el-form-item>
-        <el-form-item label="内容名称:">
-          <el-input v-model="dialogForm.keyword" placeholder="请输入内容名称" clearable />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" icon="el-icon-search" @click="getSearch">搜索</el-button>
-          <el-button icon="el-icon-refresh" @click="getRefresh">重置</el-button>
-          <el-button type="primary" icon="el-icon-upload2"
-            @click="$refs.audio.$children[0].$refs.input.click();">上传音频</el-button>
+        <el-form-item style="margin-top: 15px;">
+          <el-button @click="closeVideo">取消</el-button>
+          <el-button type="primary" @click="handleUploadSuccess()" :disabled="videoForm.src == ''">确定</el-button>
         </el-form-item>
       </el-form>
-      <el-table :data="tableData" v-loading="loading">
-        <el-table-column label="音频ID" prop="audioId" align="center" show-overflow-tooltip />
-        <el-table-column label="音频名称" prop="audioName" align="center" show-overflow-tooltip />
-        <el-table-column label="音频封面" align="center" width="100px">
-          <template slot-scope="scope">
-            <el-image v-if="scope.row.audioPic" :src="scope.row.audioPic" />
-          </template>
-        </el-table-column>
-        <el-table-column label="音频作者" align="center" show-overflow-tooltip>
-          <template slot-scope="scope">
-            <span>
-              {{ scope.row.singerName ? scope.row.singerName : '-' }}
-            </span>
-          </template>
-        </el-table-column>
-        <el-table-column label="专辑名称" prop="songName" align="center" show-overflow-tooltip>
-          <template slot-scope="scope">
-            <span>
-              {{ scope.row.songName ? scope.row.songName : '-' }}
-            </span>
-          </template>
-        </el-table-column>
-        <el-table-column label="付费类型" prop="isFree" align="center" :formatter="freeFormatter" />
-        <el-table-column label="资源平台" align="center" :formatter="platfromFormatter" />
-        <el-table-column label="操作" align="center">
-          <template slot-scope="scope">
-            <el-button type="text" @click="handleChecked(scope.row)">选择</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <div slot="footer">
-        <pagination v-show="total > 0" :total="total" :page.sync="dialogForm.pageNum" :limit.sync="dialogForm.pageSize"
-          @pagination="getList" />
-      </div>
-    </el-dialog>
+    </el-popover>
   </div>
 </template>
 
@@ -81,14 +30,13 @@ import Quill from "quill";
 import "quill/dist/quill.core.css";
 import "quill/dist/quill.snow.css";
 import "quill/dist/quill.bubble.css";
+import Upload from '../Upload/index.vue';
 import { getToken } from "@/utils/auth";
-import Audio from "@/store/modules/editor";
-Quill.register(Audio, true);
+import { View } from "@/store/modules/editor";
+Quill.register(View, true);
 
-import { list } from '@/api/operation/channel'
-import { platformMixin, isFreeMixin, channelMixin } from '@/mixin/index'
 export default {
-  mixins: [platformMixin, isFreeMixin, channelMixin],
+  components: { Upload },
   name: "Editor",
   props: {
     /* 编辑器的内容 */
@@ -111,11 +59,6 @@ export default {
       type: Boolean,
       default: false,
     },
-    // 上传文件大小限制(MB)
-    fileSize: {
-      type: Number,
-      default: 5,
-    },
     /* 类型(base64格式、url格式) */
     type: {
       type: String,
@@ -128,7 +71,6 @@ export default {
       fullScreenLoading: false,
       loading: false,
       uploadUrl: process.env.VUE_APP_BASE_API + "/system/file/picture/upload", // 上传的图片服务器地址
-      audioUrl: process.env.VUE_APP_BASE_API + "/system/file/mp3/upload", // 上传的音频服务器地址
       headers: {
         Authorization: "Bearer " + getToken()
       },
@@ -147,47 +89,29 @@ export default {
               ["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线
               ["blockquote", "code-block"],                    // 引用  代码块
               [{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表
-              // [{ indent: "-1" }, { indent: "+1" }],            // 缩进
+              // [{ indent: "-1" }, { indent: "+1" }],         // 缩进
               [{ size: ["small", false, "large", "huge"] }],   // 字体大小
               [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题
               [{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色
               [{ align: [] }],                                 // 对齐方式
               ["clean"],                                       // 清除文本格式
-              ["link", "image", "video", "audio"]              // 链接、图片、视频
+              ["link", "image", "view"], // "audio"            // 链接、图片、视频
             ]
           }
         },
-        initAudioButton: function () {
-          const AudioButton = document.querySelector('.ql-audio')
-          AudioButton.classList.add('el-icon-headset')
-          AudioButton.style.cssText = "font-size: 16px; font-weight: bold"
+        // 自定义按钮
+        customButton: function (className, icon) {
+          const btn = document.querySelector(className)
+          btn.classList.add(icon)
+          btn.style.cssText = 'font-size: 16px; font-weight: bold'
         },
         placeholder: "请输入内容",
         readOnly: this.readOnly,
       },
-
-      // 弹窗
-      dialogVisible: false,
-      dialogForm: {
-        pageNum: 1,
-        pageSize: 10,
-        status: 1,
-        audioType: 2
-      },
-      // 列表
-      tableData: [],
-      total: 0,
-      // 音频类型
-      audioTypeOptions: [{
-        value: 2,
-        label: '广播电台'
-      }, {
-        value: 6,
-        label: '节目'
-      }, {
-        value: 11,
-        label: '歌曲'
-      }]
+      // 视频表单
+      videoForm: {
+        src: ''
+      }
     };
   },
   computed: {
@@ -213,14 +137,6 @@ export default {
         }
       },
       immediate: true,
-    },
-    'dialogForm.audioType'(val) {
-      if (val) {
-        this.getPlatform({
-          audioType: val
-        })
-        this.getList()
-      }
     }
   },
   mounted() {
@@ -233,9 +149,10 @@ export default {
     init() {
       const editor = this.$refs.editor;
       this.Quill = new Quill(editor, this.options);
-      this.editorImage()
-      this.editorAudio()
-      this.options.initAudioButton()
+      // 自定义按钮
+      this.customEditor('image')
+      this.customEditor('view')
+      this.options.customButton('.ql-view', 'el-icon-video-camera')
       this.Quill.pasteHTML(this.currentValue);
       this.Quill.on("text-change", (delta, oldDelta, source) => {
         const html = this.$refs.editor.children[0].innerHTML;
@@ -255,147 +172,62 @@ export default {
         this.$emit("on-editor-change", eventName, ...args);
       });
     },
-    editorImage() {
-      // 如果设置了上传地址则自定义图片上传事件
-      if (this.type == 'url') {
-        let toolbar = this.Quill.getModule("toolbar");
-        toolbar.addHandler("image", (value) => {
-          this.uploadType = "image";
-          if (value) {
-            this.$refs.upload.$children[0].$refs.input.click();
-          } else {
-            this.quill.format("image", false);
-          }
-        });
-      }
-    },
-    handleBeforeUpload(file) {
-      this.data.multipartFile = file
-    },
-    handleUploadSuccess(res, file) {
-      // 获取富文本组件实例
-      let quill = this.Quill;
-      // 如果上传成功
-      if (res.code == 0) {
-        // 获取光标所在位置
-        let length = quill.getSelection().index;
-        // 插入图片  res.url为服务器返回的图片地址
-        quill.insertEmbed(length, "image", res.data);
-        // 调整光标到最后
-        quill.setSelection(length + 1);
-      } else {
-        this.$message.error("图片插入失败");
-      }
-    },
-    handleUploadError() {
-      this.$message.error("图片插入失败");
-    },
-    isShow() {
-      if (!this.readOnly) {
-        return this.type == 'url'
-      }
-    },
 
-    // 音频
-    editorAudio() {
+    // 自定义按钮
+    customEditor(key) {
       let toolbar = this.Quill.getModule("toolbar");
-      toolbar.addHandler("audio", (value) => {
+      toolbar.addHandler(key, (value) => {
         if (value) {
-          this.dialogVisible = true
-          this.getPlatform({
-            audioType: 2
-          })
-          this.getList()
+          if (key === 'image') { this.$refs.upload.$children[0].$refs.input.click() }
+          if (key === 'view') { this.$refs.popover.showPopper = true }
         } else {
-          this.quill.format("audio", false);
+          this.quill.format(key, false);
         }
       });
     },
 
-    handleBeforeAudio(file) {
-      this.fullScreenLoading = true
-      this.audioData.multipartFile = file
-    },
-
-    handleAudioSuccess(res) {
-      this.fullScreenLoading = false
-      let quill = this.Quill
-      if (res.code == 0) {
-        let length = quill.getSelection().index;
-        quill.insertEmbed(
-          length + 1,
-          'audio',
-          { src: res.data.url, name: res.data.realName },
-          "api"
-        );
-        quill.insertText(length + 2, "");
-        quill.setSelection(length + 2);
-      } else {
-        this.$message.error(res.message)
-      }
-    },
-
-    handleAudioError() {
-      this.fullScreenLoading = false
-      this.$message.error('插入失败')
+    // 上传视频
+    upload(e) {
+      this.videoForm.src = e.file
     },
 
-    // 列表
-    getList() {
-      this.loading = true
-      list(this.dialogForm).then(res => {
-        if (res.code === 0) {
-          this.tableData = res.data.records
-          this.total = res.data.total
-          this.loading = false
-        }
-      })
+    // 上传图片之前
+    handleBeforeUpload(file) {
+      this.data.multipartFile = file
     },
 
-    // 搜索
-    getSearch() {
-      this.dialogForm.pageNum = 1
-      this.getList()
+    // 图片上传失败
+    handleUploadError() {
+      this.$message.error("图片插入失败");
     },
 
-    // 重置
-    getRefresh() {
-      this.dialogForm = {
-        pageNum: 1,
-        pageSize: 10,
-        status: 1,
-        audioType: 2
+    // 成功添加
+    handleUploadSuccess(res) {
+      // 获取富文本组件实例
+      let quill = this.Quill;
+      // 如果上传成功
+      if (quill.getSelection()) {
+        let length = quill.getSelection().index
+        let key = res ? "image" : "view"
+        let form = res ? res.data : this.videoForm
+        quill.insertEmbed(length, key, form)
+        quill.setSelection(length + 1)
+      } else {
+        this.$message.error("请先聚焦于富文本输入框,再插入视频")
       }
-      this.getList()
     },
 
-    // 选择音频
-    handleChecked(row) {
-      let quill = this.Quill
-      let length = quill.getSelection().index;
-      quill.insertEmbed(
-        length + 1,
-        'audio',
-        { src: '', name: row.audioName, poster: row.audioPic, id: row.audioId },
-        "api"
-      );
-      quill.insertText(length + 2, "");
-      quill.setSelection(length + 2);
-      this.$message.success('选择成功!')
+    // 关闭视频弹框
+    closeVideo() {
+      this.$refs.popover.showPopper = false
+      this.videoForm = {}
     },
 
-    // 字典翻译
-    freeFormatter(row) {
-      return this.selectDictLabel(this.freeOptions, row.isFree)
-    },
-    platfromFormatter(row) {
-      return this.selectDictLabel(this.platformOptions, row.platformId)
-    },
   },
 };
 </script>
 
-<style>
+<style lang="scss">
 .editor,
 .ql-toolbar {
   white-space: pre-wrap !important;
@@ -489,4 +321,16 @@ export default {
 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
   content: '等宽字体';
 }
+
+.ql-popover {
+  top: 66px;
+  right: 1px;
+
+  .el-input-group__append,
+  .el-input-group__prepend {
+    color: #FFFFFF;
+    background-color: #1890ff;
+    border-color: #1890ff;
+  }
+}
 </style>