Step 1: Install TinyMCE
$npm install [email protected] -S $npm install @tinymce/[email protected] -S
Step 2: Find the tinymce folder in node_modules, move the internal files into the pubilc/tinymce folder, and introduce tinymce.min.js into the index.html file
Note: If you do not put the js file locally, the registration key prompt will be displayed when the rich text is displayed (you can also hide it with css yourself)
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"> <script src="./tinymce/tinymce.min.js"></script> </div> <!-- built files will be auto injected --> </body> </html>
Step Three: Chinese Language Pack
Create the file public/lang/zh_CN.js
Copy the following content directly into the file zh_CN.js
tinymce.addI18n('zh_CN',{ "Redo": "\重\做", "Undo": "\撤\销", "Cut": "\剪\切", "Copy": "\复\制", "Paste": "\粘\贴", "Select all": "\全\选", "New document": "\新\文\件", "Ok": "\确\定", "Cancel": "\取\消", "Visual aids": "\网\格\线", "Bold": "\粗\体", "Italic": "\斜\体", "Underline": "\下\划\线", "Strikethrough": "\删\除\线", "Superscript": "\上\标", "Subscript": "\下\标", "Clear formatting": "\清\除\格\式", "Align left": "\左\边\对\齐", "Align center": "\中\间\对\齐", "Align right": "\右\边\对\齐", "Justify": "\两\端\对\齐", "Bullet list": "\项\目\符\号", "Numbered list": "\编\号\列\表", "Decrease indent": "\减\少\缩\进", "Increase indent": "\增\加\缩\进", "Close": "\关\闭", "Formats": "\格\式", "Your browser doesn't support direct access to the clipboard. Please use the Ctrl + \开\剪\贴\板\,\请\使\用Ctrl + X\/C\/V\等\快\捷\键\。", "Headers": "\标\题", "Header 1": "\标\题1", "Header 2": "\标\题2", "Header 3": "\标\题3", "Header 4": "\标\题4", "Header 5": "\标\题5", "Header 6": "\标\题6", "Headings": "\标\题", "Heading 1": "\标\题1", "Heading 2": "\标\题2", "Heading 3": "\标\题3", "Heading 4": "\标\题4", "Heading 5": "\标\题5", "Heading 6": "\标\题6", "Preformatted": "\预\先\格\式\化\的", "Div": "Div", "Pre": "Pre", "Code": "\代\码", "Paragraph": "\段\落", "Blockquote": "\引\文\区\块", "Inline": "\文\本", "Blocks": "\基\块", "Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\当\前\为\纯\文\本\粘\贴\模\式\,\ u518d\次\点\击\可\以\回\到\普\通\粘\贴\模\式\。", "Fonts": "\字\体", "Font Sizes": "\字\号", "Class": "\类\型", "Browse for an image": "\浏\览\图\像", "OR": "\或", "Drop an image here": "\拖\放\一\张\图\像\至\此", "Upload": "\上\传", "Block": "\块", "Align": "\对\齐", "Default": "\默\认", "Circle": "\空\心\圆", "Disc": "\实\心\圆", "Square": "\方\块", "Lower Alpha": "\小\写\英\文\字\母", "Lower Greek": "\小\写\希\腊\字\母", "Lower Roman": "\小\写\罗\马\字\母", "Upper Alpha": "\大\写\英\文\字\母", "Upper Roman": "\大\写\罗\马\字\母", "Anchor...": "\锚\点...", "Name": "\名\称", "Id": "\标\识\符", "Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\标\识\符\应\该\以\字\母\开\头\,\后 ", "You have unsaved changes are you sure you want to navigate away?": "\你\还\有\文\档\尚\未\保\存\,\确\定\要\离\开\?" , "Restore last draft": "\恢\复\上\次\的\草\稿", "Special characters...": "\特\殊\字\符...", "Source code": "\源\代\码", "Insert\/Edit code sample": "\插\入\/\编\辑\代\码\示\例", "Language": "\语\言", "Code sample...": "\示\例\代\码...", "Color Picker": "\选\色\器", "R": "R", "G": "G", "B": "B", "Left to right": "\从\左\到\右", "Right to left": "\从\右\到\左", "Emoticons...": "\表\情\符\号...", "Metadata and Document Properties": "\元\数\据\和\文\档\属\性", "Title": "\标\题", "Keywords": "\关\键\词", "Description": "\描\述", "Robots": "\机\器\人", "Author": "\作\者", "Encoding": "\编\码", "Fullscreen": "\全\屏", "Action": "\操\作", "Shortcut": "\快\捷\键", "Help": "\帮\助", "Address": "\地\址", "Focus to menubar": "\移\动\焦\点\到\菜\单\栏", "Focus to toolbar": "\移\动\焦\点\到\工\具\栏", "Focus to element path": "\移\动\焦\点\到\元\素\路\径", "Focus to contextual toolbar": "\移\动\焦\点\到\上\下\文\菜\单", "Insert link (if link plugin activated)": "\插\入\链\接 (\如\果\链\接\插\件\已\激\活)", "Save (if save plugin activated)": "\保\存(\如\果\保\存\插\件\已\激\活)", "Find (if searchreplace plugin activated)": "\查\找(\如\果\查\找\替\换\插\件\已\激\活)", "Plugins installed ({0}):": "\已\安\装\插\件 ({0}):", "Premium plugins:": "\优\秀\插\件\:", "Learn more...": "\了\解\更\多...", "You are using {0}": "\你\正\在\使\用 {0}", "Plugins": "\插\件", "Handy Shortcuts": "\快\捷\键", "Horizontal line": "\水\平\分\割\线", "Insert\/edit image": "\插\入\/\编\辑\图\片", "Image description": "\图\片\描\述", "Source": "\地\址", "Dimensions": "\大\小", "Constrain proportions": "\保\持\纵\横\比", "General": "\普\通", "Advanced": "\高\级", "Style": "\样\式", "Vertical space": "\垂\直\边\距", "Horizontal space": "\水\平\边\距", "Border": "\边\框", "Insert image": "\插\入\图\片", "Image...": "\图\片...", "Image list": "\图\片\列\表", "Rotate counterclockwise": "\逆\时\针\旋\转", "Rotate clockwise": "\顺\时\针\旋\转", "Flip vertically": "\垂\直\翻\转", "Flip horizontally": "\水\平\翻\转", "Edit image": "\编\辑\图\片", "Image options": "\图\片\选\项", "Zoom in": "\放\大", "Zoom out": "\缩\小", "Crop": "\裁\剪", "Resize": "\调\整\大\小", "Orientation": "\方\向", "Brightness": "\亮\度", "Sharpen": "\锐\化", "Contrast": "\对\比\度", "Color levels": "\颜\色\层\次", "Gamma": "\伽\马\值", "Invert": "\反\转", "Apply": "\应\用", "Back": "\后\退", "Insert date\/time": "\插\入\日\期\/\时\间", "Date\/time": "\日\期\/\时\间", "Insert\/Edit Link": "\插\入\/\编\辑\链\接", "Insert\/edit link": "\插\入\/\编\辑\链\接", "Text to display": "\显\示\文\字", "Url": "\地\址", "Open link in...": "\链\接\打\开\位\置...", "Current window": "\当\前\窗\口", "None": "\无", "New window": "\在\新\窗\口\打\开", "Remove link": "\删\除\链\接", "Anchors": "\锚\点", "Link...": "\链\接...", "Paste or type a link": "\粘\贴\或\输\入\链\接", "The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\你\所\填\写\的URL\地\址\为\邮\件\地\址 \,\需\要\加\上mailto:\前\缀\吗\?", "The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\你\所\填\写\的URL\地\址\属\于\外 \部\链\接\,\需\要\加\上http:\/\/:\前\缀\吗\?", "Link list": "\链\接\列\表", "Insert video": "\插\入\视\频", "Insert\/edit video": "\插\入\/\编\辑\视\频", "Insert\/edit media": "\插\入\/\编\辑\媒\体", "Alternative source": "\镜\像", "Alternative source URL": "\替\代\来\源\网\址", "Media poster (Image URL)": "\封\面(\图\片\地\址)", "Paste your embed code below:": "\将\内\嵌\代\码\粘\贴\在\下\面:", "Embed": "\内\嵌", "Media...": "\多\媒\体...", "Nonbreaking space": "\不\间\断\空\格", "Page break": "\分\页\符", "Paste as text": "\粘\贴\为\文\本", "Preview": "\预\览", "Print...": "\打\印...", "Save": "\保\存", "Find": "\查\找", "Replace with": "\替\换\为", "Replace": "\替\换", "Replace all": "\全\部\替\换", "Previous": "\上\一\个", "Next": "\下\一\个", "Find and replace...": "\查\找\并\替\换...", "Could not find the specified string.": "\未\找\到\搜\索\内\容.", "Match case": "\区\分\大\小\写", "Find whole words only": "\全\字\匹\配", "Spell check": "\拼\写\检\查", "Ignore": "\忽\略", "Ignore all": "\全\部\忽\略", "Finish": "\完\成", "Add to Dictionary": "\添\加\到\字\典", "Insert table": "\插\入\表\格", "Table properties": "\表\格\属\性", "Delete table": "\删\除\表\格", "Cell": "\单\元\格", "Row": "\行", "Column": "\列", "Cell properties": "\单\元\格\属\性", "Merge cells": "\合\并\单\元\格", "Split cell": "\拆\分\单\元\格", "Insert row before": "\在\上\方\插\入", "Insert row after": "\在\下\方\插\入", "Delete row": "\删\除\行", "Row properties": "\行\属\性", "Cut row": "\剪\切\行", "Copy row": "\复\制\行", "Paste row before": "\粘\贴\到\上\方", "Paste row after": "\粘\贴\到\下\方", "Insert column before": "\在\左\侧\插\入", "Insert column after": "\在\右\侧\插\入", "Delete column": "\删\除\列", "Cols": "\列", "Rows": "\行", "Width": "\宽", "Height": "\高", "Cell spacing": "\单\元\格\外\间\距", "Cell padding": "\单\元\格\内\边\距", "Show caption": "\显\示\标\题", "Left": "\左\对\齐", "Center": "\居\中", "Right": "\右\对\齐", "Cell type": "\单\元\格\类\型", "Scope": "\范\围", "Alignment": "\对\齐\方\式", "H Align": "\水\平\对\齐", "V Align": "\垂\直\对\齐", "Top": "\顶\部\对\齐", "Middle": "\垂\直\居\中", "Bottom": "\底\部\对\齐", "Header cell": "\表\头\单\元\格", "Row group": "\行\组", "Column group": "\列\组", "Row type": "\行\类\型", "Header": "\表\头", "Body": "\表\体", "Footer": "\表\尾", "Border color": "\边\框\颜\色", "Insert template...": "\插\入\模\板...", "Templates": "\模\板", "Template": "\模\板", "Text color": "\文\字\颜\色", "Background color": "\背\景\色", "Custom...": "\自\定\义...", "Custom color": "\自\定\义\颜\色", "No color": "\无", "Remove color": "\移\除\颜\色", "Table of Contents": "\内\容\列\表", "Show blocks": "\显\示\区\块\边\框", "Show invisible characters": "\显\示\不\可\见\字\符", "Word count": "\字\数", "Words: {0}": "\字\数\:{0}", "{0} words": "{0} \字", "File": "\文\件", "Edit": "\编\辑", "Insert": "\插\入", "View": "\视\图", "Format": "\格\式", "Table": "\表\格", "Tools": "\工\具", "Powered by {0}": "\由{0}\驱\动", "Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\在\编\辑\区\按ALT-F9\打\开\菜\单\, \按ALT-F10\打\开\工\具\栏\,\按ALT-0\查\看\帮\助", "Image title": "\图\片\标\题", "Border width": "\边\框\宽\度", "Border style": "\边\框\样\式", "Error": "\错\误", "Warn": "\警\告", "Valid": "\有\效", "To open the popup, press Shift + Enter": "\按Shitf + Enter\键\打\开\对\话\框", "Rich Text Area. Press ALT-0 for help.": "\编\辑\区\。\按Alt + 0\键\打\开\帮\助\。", "System Font": "\系\统\字\体", "Failed to upload image: {0}": "\图\片\上\传\失\败: {0}", "Failed to load plugin: {0} from url {1}": "\插\件\加\载\失\败: {0} \来\自\链\接 {1}", "Failed to load plugin url: {0}": "\插\件\加\载\失\败 \链\接: {0}", "Failed to initialize plugin: {0}": "\插\件\初\始\化\失\败: {0}", "example": "\示\例", "Search": "\搜\索", "All": "\全\部", "Currency": "\货\币", "Text": "\文\字", "Quotations": "\引\用", "Mathematical": "\数\学", "Extended Latin": "\拉\丁\语\扩\充", "Symbols": "\符\号", "Arrows": "\箭\头", "User Defined": "\自\定\义", "dollar sign": "\美\元\符\号", "currency sign": "\货\币\符\号", "euro-currency sign": "\欧\元\符\号", "colon sign": "\冒\号", "cruzeiro sign": "\克\鲁\赛\罗\币\符\号", "french franc sign": "\法\郎\符\号", "lira sign": "\里\拉\符\号", "mill sign": "\密\尔\符\号", "naira sign": "\奈\拉\符\号", "peseta sign": "\比\塞\塔\符\号", "rupee sign": "\卢\比\符\号", "won sign": "\韩\元\符\号", "new sheqel sign": "\新\谢\克\尔\符\号", "dong sign": "\越\南\盾\符\号", "kip sign": "\老\挝\基\普\符\号", "tugrik sign": "\图\格\里\克\符\号", "drachma sign": "\德\拉\克\马\符\号", "german penny symbol": "\德\国\便\士\符\号", "peso sign": "\比\索\符\号", "guarani sign": "\瓜\拉\尼\符\号", "austral sign": "\澳\元\符\号", "hryvnia sign": "\格\里\夫\尼\亚\符\号", "cedi sign": "\塞\地\符\号", "livre tournois sign": "\里\弗\弗\尔\符\号", "spesmilo sign": "spesmilo\符\号", "tenge sign": "\坚\戈\符\号", "indian rupee sign": "\印\度\卢\比", "turkish lira sign": "\土\耳\其\里\拉", "nordic mark sign": "\北\欧\马\克", "manat sign": "\马\纳\特\符\号", "ruble sign": "\卢\布\符\号", "yen character": "\日\元\字\样", "yuan character": "\人\民\币\元\字\样", "yuan character, in hong kong and taiwan": "\元\字\样\(\港\台\地\区\)", "yen\/yuan character variant one": "\元\字\样\(\大\写\)", "Loading emoticons...": "\加\载\表\情\符\号...", "Could not load emoticons": "\不\能\加\载\表\情\符\号", "People": "\人\类", "Animals and Nature": "\动\物\和\自\然", "Food and Drink": "\食\物\和\饮\品", "Activity": "\活\动", "Travel and Places": "\旅\游\和\地\点", "Objects": "\物\件", "Flags": "\旗\帜", "Characters": "\字\符", "Characters (no spaces)": "\字\符(\无\空\格)", "Error: Form submit field collision.": "\错\误: \表\单\提\交\字\段\冲\突\。", "Error: No form element found.": "\错\误: \没\有\表\单\控\件\。", "Update": "\更\新", "Color swatch": "\颜\色\样\本", "Turquoise": "\青\绿\色", "Green": "\绿\色", "Blue": "\蓝\色", "Purple": "\紫\色", "Navy Blue": "\海\军\蓝", "Dark Turquoise": "\深\蓝\绿\色", "Dark Green": "\深\绿\色", "Medium Blue": "\中\蓝\色", "Medium Purple": "\中\紫\色", "Midnight Blue": "\深\蓝\色", "Yellow": "\黄\色", "Orange": "\橙\色", "Red": "\红\色", "Light Gray": "\浅\灰\色", "Gray": "\灰\色", "Dark Yellow": "\暗\黄\色", "Dark Orange": "\深\橙\色", "Dark Red": "\深\红\色", "Medium Gray": "\中\灰\色", "Dark Gray": "\深\灰\色", "Black": "\黑\色", "White": "\白\色", "Switch to or from fullscreen mode": "\切\换\全\屏\模\式", "Open help dialog": "\打\开\帮\助\对\话\框", "history": "\历\史", "styles": "\样\式", "formatting": "\格\式\化", "alignment": "\对\齐", "indentation": "\缩\进", "permanent pen": "\记\号\笔", "comments": "\备\注", "Anchor": "\锚\点", "Special character": "\特\殊\符\号", "Code sample": "\代\码\示\例", "Color": "\颜\色", "Emoticons": "\表\情", "Document properties": "\文\档\属\性", "Image": "\图\片", "Insert link": "\插\入\链\接", "Target": "\打\开\方\式", "Link": "\链\接", "Poster": "\封\面", "Media": "\媒\体", "Print": "\打\印", "Prev": "\上\一\个", "Find and replace": "\查\找\和\替\换", "Whole words": "\全\字\匹\配", "Spellcheck": "\拼\写\检\查", "Caption": "\标\题", "Insert template": "\插\入\模\板" });
Step 4: Encapsulate the editor component in the src/components folder
Paste the code directly here
Notice:
- Because we need to set the header when uploading images, we customized the image upload images_upload_handler.
- If you encounter the problem that the video cannot be displayed on the display page after being inserted and saved, use a custom method to solve it.
<template> <tiny-editor id="myEditor" ref="editorTools" v-model="content" :init="editorConfig"></tiny-editor> </template> <script> // import { rootPath } from "@/utils/globalParam"; import Editor from "@tinymce/tinymce-vue" import { uploadImg } from "@/api" export default { components: { 'tiny-editor': Editor }, props: { modelValue: { type: String, default: '' } }, data() { return { editorConfig: { // configuration selector: '#myEditor', branding: false, // inline: true, elementpath: false, height: 1100, menubar: 'my1', plugins: 'image link media table lists', // images_upload_url: rootPath + "/news/upload/file", // Image upload address images_upload_handler: function (blobInfo, succFun, failFun) { let fd = new FormData() fd.append('file', blobInfo.blob()) fd.append('fileType', 'news.contentImage') uploadImg(fd).then(res => { succFun(res.relativePath) }) }, media_url_resolver: function(data, resolve) { try { let embedHtml = '' let videoUri = encodeURI(data.url); if(data.url.indexOf('.mp4')>-1) { // Determine whether it is mp4, otherwise use ifarme nesting embedHtml = `<p> <video src=${ data.url } width="100%" height="auto" style="max-width: 100%;" allowfullscreen="false" controls="controls" controlslist="nodownload"> </video> </p>`; resolve({ html: embedHtml }); }else { embedHtml = `<p> <iframe frameborder="0" src=${ data.url } width="100%" height="100%" style="max-width: 100%;"> </iframe> </p>`; resolve({ html: embedHtml }); } } catch (e) { resolve({ html: "" }); } }, menu: { my1: { title: '', items: ''}, }, language_url: "/tinymce/langs/zh_CN.js", language: "zh_CN", toolbar: "h1 h2 h3 | bold italic underline strikethrough | forecolor backcolor | bullist numlist alignleft aligncenter alignright alignjustify | outdent indent blockquote | undo redo removeformat | table link image media", }, content: '', } }, watch: { content(newValue) { this.$emit("input", newValue); }, }, created() { this.initData() }, methods: { initData() { this.content = this.modelValue }, } } </script>
Step 5: Reference the component’s parent page
<template> <tinymce-editor v-if='content' :model-value='content' @input='contentChange' /> </template> <script> import tinymceEditor from '@/components/editor.vue' export default { components: { tinymceEditor: tinymceEditor }, data() { content: '' }, methods: { contentChange(data) { this.content = dats } } } </script>
Final display effect: