Editor.vue:
1 <template> 2 <div class="mavonEditor"> 3 <mavon-editor 4 ref="md" 5 @imgAdd="$imgAdd" 6 @imgDel="$imgDel" 7 :ishljs="true" 8 :html="openHtml" 9 :autofocus="false" 10 :toolbars="toolbars" 11 v-model="currentValue" 12 codeStyle="arduino-light" 13 @save="saveMavon" 14 > 15 <template v-slot:left-toolbar-after v-if="isAdminRole"> 16 <button 17 type="button" 18 :title="$t('m.Upload_file')" 19 class="op-icon fa markdown-upload" 20 aria-hidden="true" 21 @click="uploadFile" 22 > 23 <!-- 這裡用的是element-ui給出的圖示 --> 24 <i class="el-icon-upload" /> 25 </button> 26 </template> 27 <!-- <template slot="right-toolbar-after" v-if="isAdminRole"> 28 <button 29 type="button" 30 :title="$t('m.Upload_file')" 31 class="op-icon fa markdown-upload" 32 aria-hidden="true" 33 @click="uploadFile" 34 > 35 <i class="el-icon-upload" /> 36 插入數學公式 37 </button> 38 </template> --> 39 </mavon-editor> 40 <!-- 在這裡放一個隱藏的input,用來選擇檔案 --> 41 <input 42 ref="uploadInput" 43 style="display: none" 44 type="file" 45 @change="uploadFileChange" 46 /> 47 </div> 48 </template> 49 <script> 50 import { mapGetters } from "vuex"; 51 import { addCodeBtn } from "@/common/codeblock"; 52 export default { 53 name: "Editor", 54 props: { 55 value: { 56 type: String, 57 default: "", 58 }, 59 openHtml: { 60 type: Boolean, 61 default: true, 62 }, 63 }, 64 data() { 65 return { 66 currentValue: this.value, 67 img_file: {}, 68 toolbars: { 69 bold: true, // 粗體 70 italic: true, // 斜體 71 header: true, // 標題 72 underline: true, // 下劃線 73 strikethrough: true, // 中劃線 74 mark: true, // 標記 75 superscript: true, // 上角標 76 subscript: true, // 下角標 77 quote: true, // 引用 78 ol: true, // 有序列表 79 ul: true, // 無序列表 80 link: true, // 連結 81 imagelink: false, // 圖片連結 82 code: true, // code 83 table: true, // 表格 84 fullscreen: true, // 全屏編輯 85 readmodel: true, // 沉浸式閱讀 86 htmlcode: true, // 展示html原始碼 87 help: true, // 幫助 88 /* 1.3.5 */ 89 undo: true, // 上一步 90 redo: true, // 下一步 91 trash: true, // 清空 92 save: true, // 儲存(觸發events中的save事件) 93 /* 1.4.2 */ 94 navigation: true, // 導航目錄 95 /* 2.1.8 */ 96 alignleft: true, // 左對齊 97 aligncenter: true, // 居中 98 alignright: true, // 右對齊 99 /* 2.2.1 */ 100 subfield: true, // 單雙欄模式 101 preview: true, // 預覽 102 }, 103 s_external_link: { 104 katex_js: function () { 105 return "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.8.3/katex.min.js"; 106 }, 107 katex_css: function () { 108 return "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.8.3/katex.min.css"; 109 }, 110 }, 111 }; 112 }, 113 created() { 114 if (this.isAdminRole || this.isGroupAdmin) { 115 this.toolbars.imagelink = true; 116 } 117 }, 118 mounted() { 119 console.log("值1", this.openHtml); 120 console.log("值2", this.currentValue); 121 }, 122 methods: { 123 saveMavon(value, render) { 124 console.log("this is render" + render); 125 console.log("this is value" + value); 126 }, 127 loadExternalLink(name, type, callback) { 128 if (typeof this.p_external_link[name] !== "function") { 129 if (this.p_external_link[name] !== false) { 130 console.error( 131 "external_link." + name, 132 "is not a function, if you want to disabled this error log, set external_link." + 133 name, 134 "to function or false" 135 ); 136 } 137 return; 138 } 139 var _obj = { 140 css: loadLink, 141 js: loadScript, 142 }; 143 if (_obj.hasOwnProperty(type)) { 144 _obj[type](this.p_external_link[name](), callback); 145 } 146 }, 147 $paste($e) { 148 var clipboardData = $e.clipboardData; 149 if (clipboardData) { 150 var items = clipboardData.items; 151 if (!items) return; 152 var types = clipboardData.types || []; 153 var item = null; 154 for (var i = 0; i < types.length; i++) { 155 if (types[i] === "Files") { 156 item = items[i]; 157 break; 158 } 159 } 160 if (item && item.kind === "file") { 161 stopEvent($e); 162 var oFile = item.getAsFile(); 163 } 164 } 165 }, 166 initExternalFuc() { 167 var $vm = this; 168 var _external_ = [ 169 ]; 170 var _type_ = typeof $vm.externalLink; 171 var _is_object = _type_ === "object"; 172 var _is_boolean = _type_ === "boolean"; 173 for (var i = 0; i < _external_.length; i++) { 174 if ( 175 (_is_boolean && !$vm.externalLink) || 176 (_is_object && $vm.externalLink[_external_[i]] === false) 177 ) { 178 $vm.p_external_link[_external_[i]] = false; 179 } else if ( 180 _is_object && 181 typeof $vm.externalLink[_external_[i]] === "function" 182 ) { 183 $vm.p_external_link[_external_[i]] = $vm.externalLink[_external_[i]]; 184 } else { 185 $vm.p_external_link[_external_[i]] = 186 $vm.s_external_link[_external_[i]]; 187 } 188 } 189 }, 190 // 編輯開關 191 editableTextarea() { 192 let text_dom = this.$refs.vNoteTextarea.$refs.vTextarea; 193 if (this.editable) { 194 text_dom.removeAttribute("disabled"); 195 } else { 196 text_dom.setAttribute("disabled", "disabled"); 197 } 198 }, 199 // 將圖片上傳到伺服器,返回地址替換到md中 200 $imgAdd(pos, $file) { 201 if (!this.isAdminRole && !this.isGroupAdmin) { 202 return; 203 } 204 var formdata = new FormData(); 205 formdata.append("image", $file); 206 let gid = this.$route.params.groupID; 207 if (gid != null && gid != undefined) { 208 formdata.append("gid", gid); 209 } 210 //將下面上傳介面替換為你自己的伺服器介面 211 this.$http({ 212 url: "介面1", 213 method: "post", 214 data: formdata, 215 headers: { "Content-Type": "multipart/form-data" }, 216 }).then((res) => { 217 this.$refs.md.$img2Url(pos, res.data.data.link); 218 this.img_file[res.data.data.link] = res.data.data.fileId; 219 }); 220 }, 221 $imgDel(pos) { 222 // 刪除檔案 223 this.$http({ 224 url: "介面2", 225 method: "get", 226 params: { 227 fileId: this.img_file[pos[0]], 228 }, 229 }); 230 }, 231 uploadFile() { 232 // 透過ref找到隱藏的input標籤,觸發它的點選方法 233 this.$refs.uploadInput.click(); 234 }, 235 // 監聽input獲取檔案的狀態 236 uploadFileChange(e) { 237 // 獲取到input選取的檔案 238 const file = e.target.files[0]; 239 // 建立form格式的資料,將檔案放入form中 240 const formdata = new FormData(); 241 formdata.append("file", file); 242 let gid = this.$route.params.groupID; 243 if (gid != null && gid != undefined) { 244 formdata.append("gid", gid); 245 } 246 this.$http({ 247 url: "介面3", 248 method: "post", 249 data: formdata, 250 headers: { "Content-Type": "multipart/form-data" }, 251 }).then((res) => { 252 // 這裡獲取到的是mavon編輯器例項,上面掛載著很多方法 253 const $vm = this.$refs.md; 254 // 將檔名與檔案路徑插入當前游標位置,這是mavon-editor 內建的方法 255 $vm.insertText($vm.getTextareaDom(), { 256 prefix: `[${file.name}](${res.data.data.link})`, 257 subfix: "", 258 str: "", 259 }); 260 }); 261 }, 262 }, 263 computed: { 264 ...mapGetters(["isAdminRole", "isGroupAdmin"]), 265 }, 266 watch: { 267 value(val) { 268 if (this.currentValue !== val) { 269 this.currentValue = val; 270 } 271 }, 272 currentValue(newVal, oldVal) { 273 if (newVal !== oldVal) { 274 this.$emit("update:value", newVal); 275 this.$nextTick((_) => { 276 addCodeBtn(); 277 }); 278 } 279 }, 280 isAdminRole(val) { 281 if (!val) { 282 this.toolbars.imagelink = false; 283 } else { 284 this.toolbars.imagelink = true; 285 } 286 }, 287 editable: function () { 288 this.editableTextarea(); 289 }, 290 }, 291 }; 292 </script> 293 <style> 294 .auto-textarea-wrapper .auto-textarea-block { 295 white-space: pre-wrap !important; 296 } 297 </style>