Bläddra i källkod

封装富文本组件

bihuisong 5 månader sedan
förälder
incheckning
c0e87314f1

+ 3 - 0
zhjq-ui/package.json

@@ -37,6 +37,9 @@
   },
   "dependencies": {
     "@riophae/vue-treeselect": "0.4.0",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^1.0.2",
+    "@wangeditor/plugin-upload-attachment": "^1.1.0",
     "axios": "0.28.1",
     "clipboard": "2.0.8",
     "core-js": "3.37.1",

+ 200 - 0
zhjq-ui/src/components/MyEditor/index.vue

@@ -0,0 +1,200 @@
+<template>
+  <div>
+    <div>
+      <Toolbar style="border: 1px solid black; border-bottom: 1px solid #ccc;" :editor="editor"
+               :defaultConfig="toolbarConfig" :mode="mode"/>
+    </div>
+    <div class="editor">
+      <Editor
+        :style="height"
+        v-model="html"
+        :defaultConfig="editorConfig"
+        :mode="mode"
+        @onCreated="onCreated"
+        @onChange="onChange"
+      />
+    </div>
+  </div>
+
+</template>
+<script>
+import {Boot} from "@wangeditor/editor";
+import attachmentModule from "@wangeditor/plugin-upload-attachment";
+import {Editor, Toolbar} from "@wangeditor/editor-for-vue";
+import "@wangeditor/editor/dist/css/style.css";
+import axios from "axios";
+import {getToken} from "@/utils/auth";
+
+Boot.registerModule(attachmentModule);
+
+export default {
+  components: {Editor, Toolbar},
+  name: "MyEditor",
+  props: {
+    //border
+    border: {
+      type: Boolean,
+      default: false,
+    },
+    /* 编辑器的内容 */
+    value: {
+      type: String,
+      default: "",
+    },
+    // 高度
+    height: {
+      type: String,
+      default: () => "500px",
+    },
+  },
+  data() {
+    return {
+      token: "Bearer " + getToken(),
+      editor: null,
+      html: "",
+      toolbarConfig: {
+        // excludeKeys: ["fullScreen","insertVideo","group-video"],
+        excludeKeys: ["fullScreen"],
+        insertKeys: {
+          index: 24,
+          keys: ["uploadAttachment"],
+        },
+      },
+      editorConfig: {
+        placeholder: "请输入内容...",
+        scroll: false,
+        MENU_CONF: {
+          uploadImage: {
+            // 自定义上传图片 方法
+            customUpload: this.uploadImg,
+            // 上传接口设置文件名
+            fieldName: "file",
+            meta: {
+              token: this.token,
+            },
+          },
+          uploadVideo: {
+            customUpload: this.uploadVideo,
+            fieldName: "file",
+            meta: {
+              token: this.token,
+            },
+          },
+          uploadAttachment: {
+            customUpload: this.uploadFile,
+            fieldName: "file",
+            meta: {
+              token: this.token,
+            },
+          },
+        },
+        hoverbarKeys: {
+          attachment: {
+            menuKeys: ["downloadAttachment"],
+          },
+        },
+      },
+      uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址 一定要写ip+端口 不要写localhost
+      mode: "default", //default or 'simple'
+    };
+  },
+  watch: {
+    value: {
+      handler(val) {
+        this.html = val;
+      },
+      immediate: true,
+    },
+  },
+  mounted() {
+    // 模拟 ajax 请求,异步渲染编辑器
+  },
+  beforeDestroy() {
+    const editor = this.editor;
+    if (editor == null) return;
+    editor.destroy(); // 组件销毁时,及时销毁编辑器
+  },
+  methods: {
+    onChange(editor) {
+      this.$emit("input", this.html);
+    },
+    onCreated(editor) {
+      this.editor = Object.seal(editor); // 一定要用 Object.seal() ,否则会报错
+    },
+    uploadImg(file, insertFn) {
+      let imgData = new FormData();
+      imgData.append("file", file);
+      axios.post(this.uploadUrl,
+        imgData,
+        {
+          headers: {
+            'content-Type': 'multipart/form-data',
+            "Authorization": this.token,
+          },
+        }).then((res) => {
+        if (res.data.code == 200) {
+          insertFn(res.data.url);
+        } else {
+          this.$message.warning(res.msg);
+        }
+      });
+    },
+    uploadVideo(file, insertFn) {
+      let imgData = new FormData();
+      imgData.append("file", file);
+      axios.post(this.uploadUrl,
+        imgData,
+        {
+          headers: {
+            'content-Type': 'multipart/form-data',
+            "Authorization": this.token,
+          },
+        }).then((res) => {
+        if (res.data.code == 200) {
+          // insertFn(`<video src="${res.data.url}" style="width: 100px; height: 100px;"></video>`);
+          insertFn(res.data.url);
+          console.log("insertFn",insertFn)
+        } else {
+          this.$message.warning(res.msg);
+        }
+      });
+    },
+    uploadFile(file, insertFn) {
+      let imgData = new FormData();
+      imgData.append("file", file);
+      axios.post(this.uploadUrl,
+        imgData,
+        {
+          headers: {
+            'content-Type': 'multipart/form-data',
+            "Authorization": this.token,
+          },
+        }).then((res) => {
+        if (res.data.code == 200) {
+          insertFn(
+            `附件:${res.data.originalFilename}`, res.data.url);
+        } else {
+          this.$message.warning(res.msg);
+        }
+      });
+    },
+  },
+};
+</script>
+<style scoped>
+.editor, .ql-toolbar {
+  white-space: pre-wrap !important;
+  line-height: normal !important;
+  height: 300px;
+  overflow-y: auto;
+  border: 1px solid black;
+}
+
+.border-line {
+  border: 1px solid #d6d6d6;
+}
+.w-e-scroll > div:first-child {
+  height: 100%;
+  overflow-y: auto;
+}
+</style>

+ 3 - 0
zhjq-ui/src/main.js

@@ -39,6 +39,8 @@ import DictTag from '@/components/DictTag'
 import VueMeta from 'vue-meta'
 // 字典数据组件
 import DictData from '@/components/DictData'
+// 音频上传组件
+import MyEditor from "@/components/MyEditor"
 
 // 全局方法挂载
 Vue.prototype.getDicts = getDicts
@@ -60,6 +62,7 @@ Vue.component('FileUpload', FileUpload)
 Vue.component('VoiceUpload', VoiceUpload)
 Vue.component('ImageUpload', ImageUpload)
 Vue.component('ImagePreview', ImagePreview)
+Vue.component('MyEditor', MyEditor)
 
 Vue.use(directive)
 Vue.use(plugins)

+ 2 - 1
zhjq-ui/src/views/system/article/index.vue

@@ -173,7 +173,8 @@
           <file-upload v-model="form.img" :limit="1" :file-type="['png','jpg','jpeg']" :file-size="10"/>
         </el-form-item>
         <el-form-item label="内容" prop="journalismContent">
-          <editor style="height: 300px" label="富文本控件" v-model="form.journalismContent" maxlength="4000" show-word-limit/>
+<!--          <editor style="height: 300px" label="富文本控件" v-model="form.journalismContent" maxlength="4000" show-word-limit/>-->
+          <MyEditor v-model="form.journalismContent"/>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">

+ 27 - 26
zhjq-ui/src/views/system/notice/index.vue

@@ -124,24 +124,28 @@
     <el-dialog :title="title" :visible.sync="open" append-to-body width="780px">
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-row>
-          <el-col :span="12">
+          <el-col :span="24">
             <el-form-item label="公告标题" prop="noticeTitle">
               <el-input v-model="form.noticeTitle" placeholder="请输入公告标题"/>
             </el-form-item>
           </el-col>
-          <el-col :span="24">
-            <el-form-item label="状态">
-              <el-radio-group v-model="form.status">
-                <el-radio
-                  v-for="dict in dict.type.sys_notice_status"
-                  :key="dict.value"
-                  :label="dict.value"
-                >{{ dict.label }}
-                </el-radio>
-              </el-radio-group>
+          <el-col :span="12">
+            <el-form-item label="发布人" prop="author">
+              <el-input v-model="form.author" placeholder="请输入发布人"/>
             </el-form-item>
           </el-col>
-          <el-col :span="24">
+          <el-col :span="12">
+            <el-form-item label="发布时间" prop="releaseTime">
+              <el-date-picker
+                style="width: 290px"
+                v-model="form.releaseTime"
+                type="date"
+                placeholder="请选择发布时间"
+                value-format="yyyy-MM-dd"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
             <el-form-item label="是否置顶">
               <el-radio-group v-model="form.isTop">
                 <el-radio
@@ -154,24 +158,21 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="发布人" prop="author">
-              <el-input v-model="form.author" placeholder="请输入发布人"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="24">
-            <el-form-item label="发布时间" prop="releaseTime">
-              <el-date-picker
-                style="width: 290px"
-                v-model="form.releaseTime"
-                type="date"
-                placeholder="请选择发布时间"
-                value-format="yyyy-MM-dd"
-              />
+            <el-form-item label="状态">
+              <el-radio-group v-model="form.status">
+                <el-radio
+                  v-for="dict in dict.type.sys_notice_status"
+                  :key="dict.value"
+                  :label="dict.value"
+                >{{ dict.label }}
+                </el-radio>
+              </el-radio-group>
             </el-form-item>
           </el-col>
           <el-col :span="24">
             <el-form-item label="内容" prop="noticeContent">
-              <editor v-model="form.noticeContent" :min-height="192"/>
+<!--              <editor v-model="form.noticeContent" :min-height="192"/>-->
+              <MyEditor v-model="form.noticeContent"/>
             </el-form-item>
           </el-col>
         </el-row>

+ 5 - 1
zhjq-ui/src/views/system/voice/details/details.vue

@@ -84,10 +84,14 @@ img {
   display: block; /* 使图片成为块级元素 */
   margin: 16px 0; /* 上下外边距 */
 }
+video {
+  width: 100%;
+  height: auto; /* 固定高度 */
+}
 </style>
 <style scoped>
 .attraction-page {
-  width: 1000rpx;
+  width: 100%;
   margin: auto;
   padding: 16px; /* 添加内边距 */
 }

+ 2 - 1
zhjq-ui/src/views/system/voice/index.vue

@@ -150,7 +150,8 @@
           </el-col>
           <el-col :span="24">
             <el-form-item label="内容" prop="content">
-              <editor style="height: 280px" label="富文本控件" v-model="form.content"/>
+<!--              <editor style="height: 280px" label="富文本控件" v-model="form.content"/>-->
+              <MyEditor v-model="form.content"/>
             </el-form-item>
           </el-col>
         </el-row>