Effect:
/** * File path:/src/tinymce/plugins/images/index.js */ import request from "@/utils/request"; tinymce.PluginManager.add('images', function (editor) {<!-- --> let pluginName = 'Multiple image upload' let bodyId = editor.getParam('body_id', '', 'hash') var imgList = [] //Configure popup layer let openDialog = function () {<!-- --> return editor.windowManager.open({<!-- --> title: pluginName, size: 'medium', body: {<!-- --> type: 'panel', items: [ {<!-- --> name: 'multifile', type: 'htmlpanel', html: ' <div style="min-height:200px"><div style="background: #3d97d4;color: #fff;border-radius: 3px;padding: 8px 16px;width: 120px;text-align: center ;cursor: pointer;" class="addfile " id="addfile"> + Add file</div> <ul id="file_list"></ul></div>', } ] }, buttons: [{<!-- --> type: 'cancel', text: 'Close' }, {<!-- --> type: 'custom', text: 'Save', name: 'save', primary: true }], onAction: function (api, details) {<!-- --> console.log(imgList,"What is obtained in it==========") switch (details.name) {<!-- --> case 'save': var html = ''; var imgs = imgList; var len = imgs.length; if (len>0) {<!-- --> for(let i=0;i<len;i + + ){<!-- --> if( imgs[i] ){<!-- --> html + = '<img src="' + imgs[i] + '" /> '; } } editor.insertContent(html) api.close() } \t\t\t\t\t break default: break } }, onChange(api, evt) {<!-- --> console.log('change') console.log(api) console.log(evt) } }) } //Add event listener let addEventListener = function (editor) {<!-- --> imgList = [] //add files document.querySelector('.addfile').addEventListener('click',()=>{<!-- --> var input = document.createElement('input'); const filetype=".png,.gif,.jpg,.jpeg" input.setAttribute('type', 'file'); input.setAttribute('multiple', 'multiple'); input.setAttribute('accept', filetype); input.click(); input.onchange = function(event) {<!-- --> var files = event.target.files; addList(files); } }); // let inputElement = document.getElementById('inputId'); // //Add event listener // if (inputElement) {<!-- --> // inputElement.addEventListener('change', function(event) {<!-- --> // // Code executed when file selection // console.log('File selected:', event.target.files); // const files = event.target.files // addList(files) // }); // } else {<!-- --> // console.log('The input element for image upload was not found!'); // } } let addList = function (files) {<!-- --> console.log(files, "What was obtained 222----------------"); var files_sum = files.length; var vDom = document.createDocumentFragment(); for (let i = 0; i < files_sum; i + + ) {<!-- --> let file = files[i]; let params = new FormData(); params.append("attachmentFile", file); let config = {<!-- --> headers: {<!-- --> "Content-Type": "multipart/form-data", }, }; request({<!-- --> url: "/attachment/upload", method: "post", headers: config.headers, data: params, onUploadProgress: (progressEvent) => {<!-- -->}, }) .then((resp) => {<!-- --> if (resp.code == 0) {<!-- --> imgList.push(resp.data.attachment.url); //Upload successful, fill in the image path in the success function } else {<!-- --> failure("Upload failed"); } }) .catch((error) => {<!-- --> failure("Upload error, the server is out of service"); }); let blobUrl = window.URL.createObjectURL(file); let li = document.createElement("li"); li.setAttribute("class", "up-no"); li.setAttribute("data-time", file.lastModified); li.innerHTML = '<div class="picbox"><img style="width:150px;height:150px;margin:20px" src="' + blobUrl + '"></div>' // < div class="namebox" > <span>' + // file.name + // '</span></div><div class="tools"><a class="remove"></a></div>'; vDom.appendChild(li); } document.querySelector("#file_list").appendChild(vDom); //reSort(); } //Add icon editor.ui.registry.getAll().icons.images || editor.ui.registry.addIcon('images', '<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org /2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0 ,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill=" #53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105. 4,105.4,0,0,0, 73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4 z" fill ="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6- 49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>') //Register toolbar button editor.ui.registry.addButton('images', { icon: 'images', tooltip: pluginName, onAction: function () { openDialog() addEventListener() } }) //Register menu options editor.ui.registry.addMenuItem('images', { icon: 'images', text: pluginName, onAction: function () {<!-- --> openDialog() addEventListener() } }) return {<!-- --> getMetadata: function () {<!-- --> return {<!-- --> name: pluginName, url: "https://dotatong.cn", } } } })
TEditor editor configuration
```bash <template> <div class="tinymce-box"> <Editor v-model="contentValue" :init="init" :disabled="disabled" @onClick="onClick" /> </div> </template> <script> // import api from '../api/api.js' //Introduce tinymce editor import Editor from "@tinymce/tinymce-vue"; //Introduce tinymce related files in node_modules import tinymce from "tinymce/tinymce"; //tinymce defaults to hidden. If it is not imported, the editor will not be displayed. import "tinymce/themes/silver"; //Editor theme, if not imported, an error will be reported import "tinymce/icons/default"; //Introduce the editor icon icon. If it is not introduced, the corresponding icon will not be displayed. //Introduce editor plug-ins (basic free plug-ins are here) import "tinymce/plugins/advlist"; //Advanced list import "tinymce/plugins/anchor"; //Anchor point import "tinymce/plugins/autolink"; //Auto link import "tinymce/plugins/autoresize"; //The editor is highly adaptive. Note: When this plug-in is introduced into plugins, the height set in Init will be invalid. import "tinymce/plugins/autosave"; //Automatically save manuscripts import "tinymce/plugins/charmap"; //Special characters import "tinymce/plugins/code"; //Edit source code import "tinymce/plugins/codesample"; //code sample import "tinymce/plugins/directionality"; //Text direction import "tinymce/plugins/emoticons"; //emoticons import "tinymce/plugins/fullpage"; //Document properties import "tinymce/plugins/fullscreen"; //full screen import "tinymce/plugins/help"; //Help import "tinymce/plugins/hr"; //Horizontal dividing line import "tinymce/plugins/image"; //Insert and edit pictures import "tinymce/plugins/importcss"; //Introduce css import "tinymce/plugins/insertdatetime"; //Insert date and time import "tinymce/plugins/link"; //Hyperlink import "tinymce/plugins/lists"; //list plugin import "tinymce/plugins/media"; //Insert editing media import "tinymce/plugins/nonbreaking"; //Insert nonbreaking spaces import "tinymce/plugins/pagebreak"; //Insert page break import "tinymce/plugins/paste"; //Paste plugin import "tinymce/plugins/preview"; //Preview import "tinymce/plugins/print"; //Print import "tinymce/plugins/quickbars"; //Quick Toolbar import "tinymce/plugins/save"; //Save import "tinymce/plugins/searchreplace"; //Search and replace //import 'tinymce/plugins/spellchecker' //Spellchecker has not yet been translated into Chinese and is not recommended for use. import "tinymce/plugins/tabfocus"; // Switch in and out, press the tab key to switch out of the editor, and switch into other input boxes on the page import "tinymce/plugins/table"; //Table import "tinymce/plugins/template"; //Content template import "tinymce/plugins/textcolor"; //Text color import "tinymce/plugins/textpattern"; //Quick typesetting import "tinymce/plugins/toc"; //Table of contents generator import "tinymce/plugins/visualblocks"; //Display element range import "tinymce/plugins/visualchars"; //Display invisible characters import "tinymce/plugins/wordcount"; import "/public/tinymce/plugins/images"; //Multiple image uploads import request from "@/utils/request"; //Word count export default {<!-- --> name: "TEditor", components: {<!-- --> Editor, }, props: {<!-- --> value: {<!-- --> type: String, default: "", }, disabled: {<!-- --> type: Boolean, default: false, }, plugins: {<!-- --> type: [String, Array], default: "print preview searchreplace autolink directionality visualblocks visualchars fullscreen image images link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists textpattern autosave ", }, toolbar: {<!-- --> type: [String, Array], default: " bold italic underline image images strikethrough alignment | forecolor backcolor outdent indent | \ formatselect fontsizeselect | bullist numlist blockquote link table code", // default: 'bold italic underline image alignment forecolor | outdent indent | \ // backcolor styleselect formatselect fontselect fontsizeselect | bullist numlist |strikethrough blockquote subscript superscript removeformat link| \ // table media charmap hr pagebreak insertdatetime preview | code selectall searchreplace visualblocks | indent2em lineheight formatpainter axupimgs' }, height: {<!-- --> type: Number, default: 300, }, isCustomStyle: {<!-- --> type: Boolean, default: false, }, }, data() {<!-- --> return {<!-- --> init: {<!-- --> force_br_newlines: false, force_p_newlines: false, //Do not use p tag for newlines forced_root_block: "", statusbar: false, language_url: "/tinymce/langs/zh_CN.js", //Introduce language pack file language: "zh_CN", //Language type skin_url: "/tinymce/skins/ui/oxide", //Skin: light color // skin_url: '/tinymce/skins/ui/oxide-dark', // skin: dark plugins: this.plugins, //Plug-in configuration toolbar: this.toolbar, //Toolbar configuration, set to false to hide toolbar_groups: {<!-- --> alignment: {<!-- --> icon: "align-left", tooltip: "Align", items: "alignleft aligncenter alignright alignjustify lineheight", }, }, menubar: false, //Menu bar configuration. If set to false, it will be hidden. If not configured, all menus will be displayed by default. You can also customize the configuration - see http://tinymce.ax-z.cn/configure/editor-appearance. php --Search for "custom menu" fontsize_formats: "12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px", //font size font_formats: "Microsoft YaHei=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif; Apple Pingfang=PingFang SC,Microsoft YaHei,sans-serif; Song Dynasty=simsun,serif;Simultaneous Song Dynasty=FangSong,serif;Helvetica=SimHei,sans -serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;", //Font style lineheight_formats: "0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5", //Line height configuration can also be configured in the form of "12px 14px 16px 20px" height: this.height, //Note: This attribute is invalid when the autoresize plug-in is introduced. placeholder: "Enter text here", branding: false, //Whether tiny technical support information is displayed resize: false, //Whether the width and height of the editor are variable, false-no, true-height is variable, 'both'-both width and height are acceptable, pay attention to the quotation marks // statusbar: false, //Whether the bottom element path and word count columns are displayed elementpath: false, //Whether the element path is displayed content_style: "img {max-width:100%;}", //Directly customize the css style of the editable area // content_css: '/tinycontent.css', // Customize the css style of the editable area in the form of css file. The css file needs to be created and imported by yourself. // images_upload_url: '/apib/api-upload/uploadimg', //The url of the backend handler. It is recommended to directly customize the upload function image_upload_handler. This can be omitted. // images_upload_base_path: '/demo', // Relative basic path - for suggestions on image uploading - http://tinymce.ax-z.cn/general/upload-images.php paste_data_images: true, //whether images can be pasted images_upload_handler: (blobInfo, success, failure) => {<!-- --> if (blobInfo.blob().size / 1024 / 1024 > 2) {<!-- --> failure("Upload failed, please control the image size within 2M"); } else {<!-- --> let params = new FormData(); params.append("attachmentFile", blobInfo.blob()); let config = {<!-- --> headers: {<!-- --> "Content-Type": "multipart/form-data", }, }; request({<!-- --> url: "/attachment/upload", method: "post", headers: config.headers, data: params, onUploadProgress: (progressEvent) => {<!-- -->}, }) .then((resp) => {<!-- --> if (resp.code == 0) {<!-- --> success(resp.data.attachment.url); //Upload successful, fill in the image path in the success function } else {<!-- --> failure("Upload failed"); } }) .catch((error) => {<!-- --> failure("Upload error, the server is out of service"); }); } }, setup: function (editor) {<!-- --> editor.on("init", function (e) {<!-- --> let isCustomStyle = localStorage.getItem("IsCustomStyle"); if (isCustomStyle == "true") {<!-- --> this.getBody().style.fontSize = "12px"; this.getBody().style.color = "#6b778c"; this.getBody().style.lineheight = "12px"; } }); }, }, contentValue: this.value, }; }, watch: {<!-- --> value(newValue) {<!-- --> this.contentValue = newValue; }, contentValue(newValue) {<!-- --> this.$emit("input", newValue); }, }, created() {<!-- -->}, mounted() {<!-- --> localStorage.setItem("IsCustomStyle", this.isCustomStyle); tinymce.init({<!-- -->}); }, methods: {<!-- --> //Add related events, refer to the documentation for available events => https://github.com/tinymce/tinymce-vue => All available events onClick(e) {<!-- --> this.$emit("onClick", e, tinymce); }, //clear content clear() {<!-- --> this.contentValue = ""; }, }, }; </script> <style lang="less"> .tox-tinymce {<!-- --> border: 1px solid#ebecf0 !important; border-radius: 4px !important; } .tox:not([dir="rtl"]) .tox-toolbar__group:not(:last-of-type) {<!-- --> border-right: 1px solid#ebecf0 !important; } .tox .tox-toolbar, .tox .tox-toolbar__overflow, .tox .tox-toolbar__primary {<!-- --> border-bottom: 1px solid#ebecf0 !important; background: #f2f6fc !important; } .tox .tox-tbtn svg {<!-- --> fill: #6b778c !important; } .tinymce-box .tox .tox-tbtn--bespoke .tox-tbtn__select-label {<!-- --> width: 60px; } .tox-tinymce-aux {<!-- --> z-index: 5000 !important; } #file_list {<!-- --> margin-left: -56px; margin-top: 20px; display: flex; flex-wrap: wrap; } .up-no {<!-- --> list-style: none; } </style>