mirror of
https://github.com/vbenjs/vben-admin-thin-next.git
synced 2025-01-23 01:30:23 +08:00
feat(tinymce): add rich editor
This commit is contained in:
parent
d8b25b488b
commit
c0e4c9e5a5
@ -5,3 +5,5 @@
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
/public/*
|
||||
|
2
.stylelintignore
Normal file
2
.stylelintignore
Normal file
@ -0,0 +1,2 @@
|
||||
/dist/*
|
||||
/public/*
|
389
public/resource/tinymce/langs/zh_CN.js
Executable file
389
public/resource/tinymce/langs/zh_CN.js
Executable file
@ -0,0 +1,389 @@
|
||||
tinymce.addI18n('zh_CN',{
|
||||
"Redo": "\u91cd\u505a",
|
||||
"Undo": "\u64a4\u9500",
|
||||
"Cut": "\u526a\u5207",
|
||||
"Copy": "\u590d\u5236",
|
||||
"Paste": "\u7c98\u8d34",
|
||||
"Select all": "\u5168\u9009",
|
||||
"New document": "\u65b0\u6587\u4ef6",
|
||||
"Ok": "\u786e\u5b9a",
|
||||
"Cancel": "\u53d6\u6d88",
|
||||
"Visual aids": "\u7f51\u683c\u7ebf",
|
||||
"Bold": "\u7c97\u4f53",
|
||||
"Italic": "\u659c\u4f53",
|
||||
"Underline": "\u4e0b\u5212\u7ebf",
|
||||
"Strikethrough": "\u5220\u9664\u7ebf",
|
||||
"Superscript": "\u4e0a\u6807",
|
||||
"Subscript": "\u4e0b\u6807",
|
||||
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
|
||||
"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
|
||||
"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
|
||||
"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
|
||||
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
|
||||
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
|
||||
"Numbered list": "\u7f16\u53f7\u5217\u8868",
|
||||
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
|
||||
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
|
||||
"Close": "\u5173\u95ed",
|
||||
"Formats": "\u683c\u5f0f",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
|
||||
"Headers": "\u6807\u9898",
|
||||
"Header 1": "\u6807\u98981",
|
||||
"Header 2": "\u6807\u98982",
|
||||
"Header 3": "\u6807\u98983",
|
||||
"Header 4": "\u6807\u98984",
|
||||
"Header 5": "\u6807\u98985",
|
||||
"Header 6": "\u6807\u98986",
|
||||
"Headings": "\u6807\u9898",
|
||||
"Heading 1": "\u6807\u98981",
|
||||
"Heading 2": "\u6807\u98982",
|
||||
"Heading 3": "\u6807\u98983",
|
||||
"Heading 4": "\u6807\u98984",
|
||||
"Heading 5": "\u6807\u98985",
|
||||
"Heading 6": "\u6807\u98986",
|
||||
"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
|
||||
"Div": "Div",
|
||||
"Pre": "Pre",
|
||||
"Code": "\u4ee3\u7801",
|
||||
"Paragraph": "\u6bb5\u843d",
|
||||
"Blockquote": "\u5f15\u6587\u533a\u5757",
|
||||
"Inline": "\u6587\u672c",
|
||||
"Blocks": "\u57fa\u5757",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
|
||||
"Fonts": "\u5b57\u4f53",
|
||||
"Font Sizes": "\u5b57\u53f7",
|
||||
"Class": "\u7c7b\u578b",
|
||||
"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
|
||||
"OR": "\u6216",
|
||||
"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
|
||||
"Upload": "\u4e0a\u4f20",
|
||||
"Block": "\u5757",
|
||||
"Align": "\u5bf9\u9f50",
|
||||
"Default": "\u9ed8\u8ba4",
|
||||
"Circle": "\u7a7a\u5fc3\u5706",
|
||||
"Disc": "\u5b9e\u5fc3\u5706",
|
||||
"Square": "\u65b9\u5757",
|
||||
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
|
||||
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
|
||||
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
|
||||
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
|
||||
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
|
||||
"Anchor...": "\u951a\u70b9...",
|
||||
"Name": "\u540d\u79f0",
|
||||
"Id": "\u6807\u8bc6\u7b26",
|
||||
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
|
||||
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
|
||||
"Special characters...": "\u7279\u6b8a\u5b57\u7b26...",
|
||||
"Source code": "\u6e90\u4ee3\u7801",
|
||||
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
|
||||
"Language": "\u8bed\u8a00",
|
||||
"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
|
||||
"Color Picker": "\u9009\u8272\u5668",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"B": "B",
|
||||
"Left to right": "\u4ece\u5de6\u5230\u53f3",
|
||||
"Right to left": "\u4ece\u53f3\u5230\u5de6",
|
||||
"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
|
||||
"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
|
||||
"Title": "\u6807\u9898",
|
||||
"Keywords": "\u5173\u952e\u8bcd",
|
||||
"Description": "\u63cf\u8ff0",
|
||||
"Robots": "\u673a\u5668\u4eba",
|
||||
"Author": "\u4f5c\u8005",
|
||||
"Encoding": "\u7f16\u7801",
|
||||
"Fullscreen": "\u5168\u5c4f",
|
||||
"Action": "\u64cd\u4f5c",
|
||||
"Shortcut": "\u5feb\u6377\u952e",
|
||||
"Help": "\u5e2e\u52a9",
|
||||
"Address": "\u5730\u5740",
|
||||
"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
|
||||
"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
|
||||
"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
|
||||
"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
|
||||
"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
|
||||
"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
|
||||
"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
|
||||
"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
|
||||
"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
|
||||
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
|
||||
"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
|
||||
"Plugins": "\u63d2\u4ef6",
|
||||
"Handy Shortcuts": "\u5feb\u6377\u952e",
|
||||
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
|
||||
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
|
||||
"Image description": "\u56fe\u7247\u63cf\u8ff0",
|
||||
"Source": "\u5730\u5740",
|
||||
"Dimensions": "\u5927\u5c0f",
|
||||
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
|
||||
"General": "\u666e\u901a",
|
||||
"Advanced": "\u9ad8\u7ea7",
|
||||
"Style": "\u6837\u5f0f",
|
||||
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
|
||||
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
|
||||
"Border": "\u8fb9\u6846",
|
||||
"Insert image": "\u63d2\u5165\u56fe\u7247",
|
||||
"Image...": "\u56fe\u7247...",
|
||||
"Image list": "\u56fe\u7247\u5217\u8868",
|
||||
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
|
||||
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
|
||||
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
|
||||
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
|
||||
"Edit image": "\u7f16\u8f91\u56fe\u7247",
|
||||
"Image options": "\u56fe\u7247\u9009\u9879",
|
||||
"Zoom in": "\u653e\u5927",
|
||||
"Zoom out": "\u7f29\u5c0f",
|
||||
"Crop": "\u88c1\u526a",
|
||||
"Resize": "\u8c03\u6574\u5927\u5c0f",
|
||||
"Orientation": "\u65b9\u5411",
|
||||
"Brightness": "\u4eae\u5ea6",
|
||||
"Sharpen": "\u9510\u5316",
|
||||
"Contrast": "\u5bf9\u6bd4\u5ea6",
|
||||
"Color levels": "\u989c\u8272\u5c42\u6b21",
|
||||
"Gamma": "\u4f3d\u9a6c\u503c",
|
||||
"Invert": "\u53cd\u8f6c",
|
||||
"Apply": "\u5e94\u7528",
|
||||
"Back": "\u540e\u9000",
|
||||
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
|
||||
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
|
||||
"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
|
||||
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
|
||||
"Text to display": "\u663e\u793a\u6587\u5b57",
|
||||
"Url": "\u5730\u5740",
|
||||
"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
|
||||
"Current window": "\u5f53\u524d\u7a97\u53e3",
|
||||
"None": "\u65e0",
|
||||
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
|
||||
"Remove link": "\u5220\u9664\u94fe\u63a5",
|
||||
"Anchors": "\u951a\u70b9",
|
||||
"Link...": "\u94fe\u63a5...",
|
||||
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
|
||||
"Link list": "\u94fe\u63a5\u5217\u8868",
|
||||
"Insert video": "\u63d2\u5165\u89c6\u9891",
|
||||
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
|
||||
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
|
||||
"Alternative source": "\u955c\u50cf",
|
||||
"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
|
||||
"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
|
||||
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
|
||||
"Embed": "\u5185\u5d4c",
|
||||
"Media...": "\u591a\u5a92\u4f53...",
|
||||
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
|
||||
"Page break": "\u5206\u9875\u7b26",
|
||||
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
|
||||
"Preview": "\u9884\u89c8",
|
||||
"Print...": "\u6253\u5370...",
|
||||
"Save": "\u4fdd\u5b58",
|
||||
"Find": "\u67e5\u627e",
|
||||
"Replace with": "\u66ff\u6362\u4e3a",
|
||||
"Replace": "\u66ff\u6362",
|
||||
"Replace all": "\u5168\u90e8\u66ff\u6362",
|
||||
"Previous": "\u4e0a\u4e00\u4e2a",
|
||||
"Next": "\u4e0b\u4e00\u4e2a",
|
||||
"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
|
||||
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
|
||||
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
|
||||
"Find whole words only": "\u5168\u5b57\u5339\u914d",
|
||||
"Spell check": "\u62fc\u5199\u68c0\u67e5",
|
||||
"Ignore": "\u5ffd\u7565",
|
||||
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
|
||||
"Finish": "\u5b8c\u6210",
|
||||
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
|
||||
"Insert table": "\u63d2\u5165\u8868\u683c",
|
||||
"Table properties": "\u8868\u683c\u5c5e\u6027",
|
||||
"Delete table": "\u5220\u9664\u8868\u683c",
|
||||
"Cell": "\u5355\u5143\u683c",
|
||||
"Row": "\u884c",
|
||||
"Column": "\u5217",
|
||||
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
|
||||
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
|
||||
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
|
||||
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
|
||||
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
|
||||
"Delete row": "\u5220\u9664\u884c",
|
||||
"Row properties": "\u884c\u5c5e\u6027",
|
||||
"Cut row": "\u526a\u5207\u884c",
|
||||
"Copy row": "\u590d\u5236\u884c",
|
||||
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
|
||||
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
|
||||
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
|
||||
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
|
||||
"Delete column": "\u5220\u9664\u5217",
|
||||
"Cols": "\u5217",
|
||||
"Rows": "\u884c",
|
||||
"Width": "\u5bbd",
|
||||
"Height": "\u9ad8",
|
||||
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
|
||||
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
|
||||
"Show caption": "\u663e\u793a\u6807\u9898",
|
||||
"Left": "\u5de6\u5bf9\u9f50",
|
||||
"Center": "\u5c45\u4e2d",
|
||||
"Right": "\u53f3\u5bf9\u9f50",
|
||||
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
|
||||
"Scope": "\u8303\u56f4",
|
||||
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
|
||||
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
|
||||
"V Align": "\u5782\u76f4\u5bf9\u9f50",
|
||||
"Top": "\u9876\u90e8\u5bf9\u9f50",
|
||||
"Middle": "\u5782\u76f4\u5c45\u4e2d",
|
||||
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
|
||||
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
|
||||
"Row group": "\u884c\u7ec4",
|
||||
"Column group": "\u5217\u7ec4",
|
||||
"Row type": "\u884c\u7c7b\u578b",
|
||||
"Header": "\u8868\u5934",
|
||||
"Body": "\u8868\u4f53",
|
||||
"Footer": "\u8868\u5c3e",
|
||||
"Border color": "\u8fb9\u6846\u989c\u8272",
|
||||
"Insert template...": "\u63d2\u5165\u6a21\u677f...",
|
||||
"Templates": "\u6a21\u677f",
|
||||
"Template": "\u6a21\u677f",
|
||||
"Text color": "\u6587\u5b57\u989c\u8272",
|
||||
"Background color": "\u80cc\u666f\u8272",
|
||||
"Custom...": "\u81ea\u5b9a\u4e49...",
|
||||
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
|
||||
"No color": "\u65e0",
|
||||
"Remove color": "\u79fb\u9664\u989c\u8272",
|
||||
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
|
||||
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
|
||||
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
|
||||
"Word count": "\u5b57\u6570",
|
||||
"Words: {0}": "\u5b57\u6570\uff1a{0}",
|
||||
"{0} words": "{0} \u5b57",
|
||||
"File": "\u6587\u4ef6",
|
||||
"Edit": "\u7f16\u8f91",
|
||||
"Insert": "\u63d2\u5165",
|
||||
"View": "\u89c6\u56fe",
|
||||
"Format": "\u683c\u5f0f",
|
||||
"Table": "\u8868\u683c",
|
||||
"Tools": "\u5de5\u5177",
|
||||
"Powered by {0}": "\u7531{0}\u9a71\u52a8",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
|
||||
"Image title": "\u56fe\u7247\u6807\u9898",
|
||||
"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
|
||||
"Border style": "\u8fb9\u6846\u6837\u5f0f",
|
||||
"Error": "\u9519\u8bef",
|
||||
"Warn": "\u8b66\u544a",
|
||||
"Valid": "\u6709\u6548",
|
||||
"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
|
||||
"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
|
||||
"System Font": "\u7cfb\u7edf\u5b57\u4f53",
|
||||
"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
|
||||
"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
|
||||
"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
|
||||
"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
|
||||
"example": "\u793a\u4f8b",
|
||||
"Search": "\u641c\u7d22",
|
||||
"All": "\u5168\u90e8",
|
||||
"Currency": "\u8d27\u5e01",
|
||||
"Text": "\u6587\u5b57",
|
||||
"Quotations": "\u5f15\u7528",
|
||||
"Mathematical": "\u6570\u5b66",
|
||||
"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
|
||||
"Symbols": "\u7b26\u53f7",
|
||||
"Arrows": "\u7bad\u5934",
|
||||
"User Defined": "\u81ea\u5b9a\u4e49",
|
||||
"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
|
||||
"currency sign": "\u8d27\u5e01\u7b26\u53f7",
|
||||
"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
|
||||
"colon sign": "\u5192\u53f7",
|
||||
"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
|
||||
"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
|
||||
"lira sign": "\u91cc\u62c9\u7b26\u53f7",
|
||||
"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
|
||||
"naira sign": "\u5948\u62c9\u7b26\u53f7",
|
||||
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
|
||||
"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
|
||||
"won sign": "\u97e9\u5143\u7b26\u53f7",
|
||||
"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
|
||||
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
|
||||
"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
|
||||
"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
|
||||
"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
|
||||
"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
|
||||
"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
|
||||
"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
|
||||
"austral sign": "\u6fb3\u5143\u7b26\u53f7",
|
||||
"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
|
||||
"cedi sign": "\u585e\u5730\u7b26\u53f7",
|
||||
"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
|
||||
"spesmilo sign": "spesmilo\u7b26\u53f7",
|
||||
"tenge sign": "\u575a\u6208\u7b26\u53f7",
|
||||
"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
|
||||
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
|
||||
"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
|
||||
"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
|
||||
"ruble sign": "\u5362\u5e03\u7b26\u53f7",
|
||||
"yen character": "\u65e5\u5143\u5b57\u6837",
|
||||
"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
|
||||
"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
|
||||
"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
|
||||
"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
|
||||
"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
|
||||
"People": "\u4eba\u7c7b",
|
||||
"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
|
||||
"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
|
||||
"Activity": "\u6d3b\u52a8",
|
||||
"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
|
||||
"Objects": "\u7269\u4ef6",
|
||||
"Flags": "\u65d7\u5e1c",
|
||||
"Characters": "\u5b57\u7b26",
|
||||
"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
|
||||
"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
|
||||
"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
|
||||
"Update": "\u66f4\u65b0",
|
||||
"Color swatch": "\u989c\u8272\u6837\u672c",
|
||||
"Turquoise": "\u9752\u7eff\u8272",
|
||||
"Green": "\u7eff\u8272",
|
||||
"Blue": "\u84dd\u8272",
|
||||
"Purple": "\u7d2b\u8272",
|
||||
"Navy Blue": "\u6d77\u519b\u84dd",
|
||||
"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
|
||||
"Dark Green": "\u6df1\u7eff\u8272",
|
||||
"Medium Blue": "\u4e2d\u84dd\u8272",
|
||||
"Medium Purple": "\u4e2d\u7d2b\u8272",
|
||||
"Midnight Blue": "\u6df1\u84dd\u8272",
|
||||
"Yellow": "\u9ec4\u8272",
|
||||
"Orange": "\u6a59\u8272",
|
||||
"Red": "\u7ea2\u8272",
|
||||
"Light Gray": "\u6d45\u7070\u8272",
|
||||
"Gray": "\u7070\u8272",
|
||||
"Dark Yellow": "\u6697\u9ec4\u8272",
|
||||
"Dark Orange": "\u6df1\u6a59\u8272",
|
||||
"Dark Red": "\u6df1\u7ea2\u8272",
|
||||
"Medium Gray": "\u4e2d\u7070\u8272",
|
||||
"Dark Gray": "\u6df1\u7070\u8272",
|
||||
"Black": "\u9ed1\u8272",
|
||||
"White": "\u767d\u8272",
|
||||
"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
|
||||
"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
|
||||
"history": "\u5386\u53f2",
|
||||
"styles": "\u6837\u5f0f",
|
||||
"formatting": "\u683c\u5f0f\u5316",
|
||||
"alignment": "\u5bf9\u9f50",
|
||||
"indentation": "\u7f29\u8fdb",
|
||||
"permanent pen": "\u8bb0\u53f7\u7b14",
|
||||
"comments": "\u5907\u6ce8",
|
||||
"Anchor": "\u951a\u70b9",
|
||||
"Special character": "\u7279\u6b8a\u7b26\u53f7",
|
||||
"Code sample": "\u4ee3\u7801\u793a\u4f8b",
|
||||
"Color": "\u989c\u8272",
|
||||
"Emoticons": "\u8868\u60c5",
|
||||
"Document properties": "\u6587\u6863\u5c5e\u6027",
|
||||
"Image": "\u56fe\u7247",
|
||||
"Insert link": "\u63d2\u5165\u94fe\u63a5",
|
||||
"Target": "\u6253\u5f00\u65b9\u5f0f",
|
||||
"Link": "\u94fe\u63a5",
|
||||
"Poster": "\u5c01\u9762",
|
||||
"Media": "\u5a92\u4f53",
|
||||
"Print": "\u6253\u5370",
|
||||
"Prev": "\u4e0a\u4e00\u4e2a",
|
||||
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
|
||||
"Whole words": "\u5168\u5b57\u5339\u914d",
|
||||
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
|
||||
"Caption": "\u6807\u9898",
|
||||
"Insert template": "\u63d2\u5165\u6a21\u677f"
|
||||
});
|
1
src/components/Tinymce/index.ts
Normal file
1
src/components/Tinymce/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as Tinymce } from './src/Editor.vue';
|
90
src/components/Tinymce/src/Editor.vue
Normal file
90
src/components/Tinymce/src/Editor.vue
Normal file
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="tinymce-container" :style="{ width: containerWidth }">
|
||||
<tinymce-editor
|
||||
:id="id"
|
||||
:init="initOptions"
|
||||
:modelValue="tinymceContent"
|
||||
@update:modelValue="handleChange"
|
||||
:tinymceScriptSrc="tinymceScriptSrc"
|
||||
></tinymce-editor>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import TinymceEditor from './lib'; // TinyMCE vue wrapper
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { basicProps } from './props';
|
||||
import toolbar from './toolbar';
|
||||
import plugins from './plugins';
|
||||
|
||||
const CDN_URL = 'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1';
|
||||
const tinymceScriptSrc = `${CDN_URL}/tinymce.min.js`;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Tinymce',
|
||||
components: { TinymceEditor },
|
||||
props: basicProps,
|
||||
setup(props, { emit }) {
|
||||
const tinymceContent = computed(() => {
|
||||
return props.value;
|
||||
});
|
||||
function handleChange(value: string) {
|
||||
emit('change', value);
|
||||
}
|
||||
const containerWidth = computed(() => {
|
||||
const width = props.width;
|
||||
// Test matches `100`, `'100'`
|
||||
if (/^[\d]+(\.[\d]+)?$/.test(width.toString())) {
|
||||
return `${width}px`;
|
||||
}
|
||||
return width;
|
||||
});
|
||||
const initOptions = computed(() => {
|
||||
const { id, height, menubar } = props;
|
||||
return {
|
||||
selector: `#${id}`,
|
||||
height: height,
|
||||
toolbar: toolbar,
|
||||
menubar: menubar,
|
||||
plugins: plugins,
|
||||
// 语言包
|
||||
language_url: 'resource/tinymce/langs/zh_CN.js',
|
||||
// 中文
|
||||
language: 'zh_CN',
|
||||
};
|
||||
});
|
||||
return { containerWidth, initOptions, tinymceContent, handleChange, tinymceScriptSrc };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tinymce-container {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
|
||||
.mce-fullscreen {
|
||||
z-index: 10000;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-custom-btn-container {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
|
||||
&.fullscreen {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-upload-btn {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
textarea {
|
||||
z-index: -1;
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
72
src/components/Tinymce/src/lib/ScriptLoader.ts
Normal file
72
src/components/Tinymce/src/lib/ScriptLoader.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { uuid } from './Utils';
|
||||
|
||||
export type callbackFn = () => void;
|
||||
export interface IStateObj {
|
||||
listeners: callbackFn[];
|
||||
scriptId: string;
|
||||
scriptLoaded: boolean;
|
||||
}
|
||||
|
||||
const createState = (): IStateObj => {
|
||||
return {
|
||||
listeners: [],
|
||||
scriptId: uuid('tiny-script'),
|
||||
scriptLoaded: false
|
||||
};
|
||||
};
|
||||
|
||||
interface ScriptLoader {
|
||||
load: (doc: Document, url: string, callback: callbackFn) => void;
|
||||
reinitialize: () => void;
|
||||
}
|
||||
|
||||
const CreateScriptLoader = (): ScriptLoader => {
|
||||
let state: IStateObj = createState();
|
||||
|
||||
const injectScriptTag = (scriptId: string, doc: Document, url: string, callback: callbackFn) => {
|
||||
const scriptTag = doc.createElement('script');
|
||||
scriptTag.referrerPolicy = 'origin';
|
||||
scriptTag.type = 'application/javascript';
|
||||
scriptTag.id = scriptId;
|
||||
scriptTag.src = url;
|
||||
|
||||
const handler = () => {
|
||||
scriptTag.removeEventListener('load', handler);
|
||||
callback();
|
||||
};
|
||||
scriptTag.addEventListener('load', handler);
|
||||
if (doc.head) {
|
||||
doc.head.appendChild(scriptTag);
|
||||
}
|
||||
};
|
||||
|
||||
const load = (doc: Document, url: string, callback: callbackFn) => {
|
||||
if (state.scriptLoaded) {
|
||||
callback();
|
||||
} else {
|
||||
state.listeners.push(callback);
|
||||
if (!doc.getElementById(state.scriptId)) {
|
||||
injectScriptTag(state.scriptId, doc, url, () => {
|
||||
state.listeners.forEach((fn) => fn());
|
||||
state.scriptLoaded = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Only to be used by tests.
|
||||
const reinitialize = () => {
|
||||
state = createState();
|
||||
};
|
||||
|
||||
return {
|
||||
load,
|
||||
reinitialize
|
||||
};
|
||||
};
|
||||
|
||||
const ScriptLoader = CreateScriptLoader();
|
||||
|
||||
export {
|
||||
ScriptLoader
|
||||
};
|
9
src/components/Tinymce/src/lib/TinyMCE.ts
Normal file
9
src/components/Tinymce/src/lib/TinyMCE.ts
Normal file
@ -0,0 +1,9 @@
|
||||
const getGlobal = (): any => (typeof window !== 'undefined' ? window : global);
|
||||
|
||||
const getTinymce = () => {
|
||||
const global = getGlobal();
|
||||
|
||||
return global && global.tinymce ? global.tinymce : null;
|
||||
};
|
||||
|
||||
export { getTinymce };
|
151
src/components/Tinymce/src/lib/Utils.ts
Normal file
151
src/components/Tinymce/src/lib/Utils.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import { ComponentPublicInstance } from 'vue';
|
||||
|
||||
const validEvents = [
|
||||
'onActivate',
|
||||
'onAddUndo',
|
||||
'onBeforeAddUndo',
|
||||
'onBeforeExecCommand',
|
||||
'onBeforeGetContent',
|
||||
'onBeforeRenderUI',
|
||||
'onBeforeSetContent',
|
||||
'onBeforePaste',
|
||||
'onBlur',
|
||||
'onChange',
|
||||
'onClearUndos',
|
||||
'onClick',
|
||||
'onContextMenu',
|
||||
'onCopy',
|
||||
'onCut',
|
||||
'onDblclick',
|
||||
'onDeactivate',
|
||||
'onDirty',
|
||||
'onDrag',
|
||||
'onDragDrop',
|
||||
'onDragEnd',
|
||||
'onDragGesture',
|
||||
'onDragOver',
|
||||
'onDrop',
|
||||
'onExecCommand',
|
||||
'onFocus',
|
||||
'onFocusIn',
|
||||
'onFocusOut',
|
||||
'onGetContent',
|
||||
'onHide',
|
||||
'onInit',
|
||||
'onKeyDown',
|
||||
'onKeyPress',
|
||||
'onKeyUp',
|
||||
'onLoadContent',
|
||||
'onMouseDown',
|
||||
'onMouseEnter',
|
||||
'onMouseLeave',
|
||||
'onMouseMove',
|
||||
'onMouseOut',
|
||||
'onMouseOver',
|
||||
'onMouseUp',
|
||||
'onNodeChange',
|
||||
'onObjectResizeStart',
|
||||
'onObjectResized',
|
||||
'onObjectSelected',
|
||||
'onPaste',
|
||||
'onPostProcess',
|
||||
'onPostRender',
|
||||
'onPreProcess',
|
||||
'onProgressState',
|
||||
'onRedo',
|
||||
'onRemove',
|
||||
'onReset',
|
||||
'onSaveContent',
|
||||
'onSelectionChange',
|
||||
'onSetAttrib',
|
||||
'onSetContent',
|
||||
'onShow',
|
||||
'onSubmit',
|
||||
'onUndo',
|
||||
'onVisualAid'
|
||||
];
|
||||
|
||||
const isValidKey = (key: string) => validEvents.indexOf(key) !== -1;
|
||||
|
||||
const bindHandlers = (initEvent: Event, listeners: any, editor: any): void => {
|
||||
Object.keys(listeners)
|
||||
.filter(isValidKey)
|
||||
.forEach((key: string) => {
|
||||
const handler = listeners[key];
|
||||
if (typeof handler === 'function') {
|
||||
if (key === 'onInit') {
|
||||
handler(initEvent, editor);
|
||||
} else {
|
||||
editor.on(key.substring(2), (e: any) => handler(e, editor));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const bindModelHandlers = (ctx: ComponentPublicInstance, editor: any) => {
|
||||
const modelEvents = ctx.$props.modelEvents ? ctx.$props.modelEvents : null;
|
||||
const normalizedEvents = Array.isArray(modelEvents) ? modelEvents.join(' ') : modelEvents;
|
||||
// @ts-ignore
|
||||
ctx.$watch('modelValue', (val: string, prevVal: string) => {
|
||||
if (editor && typeof val === 'string' && val !== prevVal && val !== editor.getContent({ format: ctx.$props.outputFormat })) {
|
||||
editor.setContent(val);
|
||||
}
|
||||
});
|
||||
|
||||
editor.on(normalizedEvents ? normalizedEvents : 'change keyup undo redo', () => {
|
||||
ctx.$emit('update:modelValue', editor.getContent({ format: ctx.$props.outputFormat }));
|
||||
});
|
||||
};
|
||||
|
||||
const initEditor = (initEvent: Event, ctx: ComponentPublicInstance, editor: any) => {
|
||||
const value = ctx.$props.modelValue ? ctx.$props.modelValue : '';
|
||||
const initialValue = ctx.$props.initialValue ? ctx.$props.initialValue : '';
|
||||
|
||||
editor.setContent(value || initialValue);
|
||||
|
||||
// checks if the v-model shorthand is used (which sets an v-on:input listener) and then binds either
|
||||
// specified the events or defaults to "change keyup" event and emits the editor content on that event
|
||||
if (ctx.$attrs['onUpdate:modelValue']) {
|
||||
bindModelHandlers(ctx, editor);
|
||||
}
|
||||
|
||||
bindHandlers(initEvent, ctx.$attrs, editor);
|
||||
};
|
||||
|
||||
let unique = 0;
|
||||
|
||||
const uuid = (prefix: string): string => {
|
||||
const time = Date.now();
|
||||
const random = Math.floor(Math.random() * 1000000000);
|
||||
|
||||
unique++;
|
||||
|
||||
return prefix + '_' + random + unique + String(time);
|
||||
};
|
||||
|
||||
const isTextarea = (element: Element | null): element is HTMLTextAreaElement => {
|
||||
return element !== null && element.tagName.toLowerCase() === 'textarea';
|
||||
};
|
||||
|
||||
const normalizePluginArray = (plugins?: string | string[]): string[] => {
|
||||
if (typeof plugins === 'undefined' || plugins === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.isArray(plugins) ? plugins : plugins.split(' ');
|
||||
};
|
||||
|
||||
const mergePlugins = (initPlugins: string | string[], inputPlugins?: string | string[]) =>
|
||||
normalizePluginArray(initPlugins).concat(normalizePluginArray(inputPlugins));
|
||||
|
||||
const isNullOrUndefined = (value: any): value is null | undefined => value === null || value === undefined;
|
||||
|
||||
export {
|
||||
bindHandlers,
|
||||
bindModelHandlers,
|
||||
initEditor,
|
||||
uuid,
|
||||
isTextarea,
|
||||
mergePlugins,
|
||||
isNullOrUndefined
|
||||
};
|
111
src/components/Tinymce/src/lib/components/Editor.ts
Normal file
111
src/components/Tinymce/src/lib/components/Editor.ts
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2018-present, Ephox, Inc.
|
||||
*
|
||||
* This source code is licensed under the Apache 2 license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
// import { ThisTypedComponentOptionsWithRecordProps } from 'vue/types/options';
|
||||
// import { CreateElement, Vue } from 'vue/types/vue';
|
||||
|
||||
import { ScriptLoader } from '../ScriptLoader';
|
||||
import { getTinymce } from '../TinyMCE';
|
||||
import { initEditor, isTextarea, mergePlugins, uuid, isNullOrUndefined } from '../Utils';
|
||||
import { editorProps, IPropTypes } from './EditorPropTypes';
|
||||
import { h, defineComponent, ComponentPublicInstance } from 'vue'
|
||||
|
||||
|
||||
export interface IEditor {
|
||||
$props: Partial<IPropTypes>
|
||||
}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
elementId: string;
|
||||
element: Element | null;
|
||||
editor: any;
|
||||
inlineEditor: boolean;
|
||||
$props: Partial<IPropTypes>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const renderInline = (id: string, tagName?: string) => {
|
||||
return h(tagName ? tagName : 'div', {
|
||||
id
|
||||
});
|
||||
};
|
||||
|
||||
const renderIframe = (id: string) => {
|
||||
return h('textarea', {
|
||||
id,
|
||||
visibility: 'hidden'
|
||||
});
|
||||
};
|
||||
|
||||
const initialise = (ctx: ComponentPublicInstance) => () => {
|
||||
const finalInit = {
|
||||
...ctx.$props.init,
|
||||
readonly: ctx.$props.disabled,
|
||||
selector: `#${ctx.elementId}`,
|
||||
plugins: mergePlugins(ctx.$props.init && ctx.$props.init.plugins, ctx.$props.plugins),
|
||||
toolbar: ctx.$props.toolbar || (ctx.$props.init && ctx.$props.init.toolbar),
|
||||
inline: ctx.inlineEditor,
|
||||
setup: (editor: any) => {
|
||||
ctx.editor = editor;
|
||||
editor.on('init', (e: Event) => initEditor(e, ctx, editor));
|
||||
|
||||
if (ctx.$props.init && typeof ctx.$props.init.setup === 'function') {
|
||||
ctx.$props.init.setup(editor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isTextarea(ctx.element)) {
|
||||
ctx.element.style.visibility = '';
|
||||
}
|
||||
|
||||
getTinymce().init(finalInit);
|
||||
};
|
||||
|
||||
export const Editor = defineComponent({
|
||||
props: editorProps,
|
||||
created() {
|
||||
this.elementId = this.$props.id || uuid('tiny-vue');
|
||||
this.inlineEditor = (this.$props.init && this.$props.init.inline) || this.$props.inline;
|
||||
},
|
||||
watch: {
|
||||
disabled() {
|
||||
(this as any).editor.setMode(this.disabled ? 'readonly' : 'design');
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.element = this.$el;
|
||||
|
||||
if (getTinymce() !== null) {
|
||||
initialise(this)();
|
||||
} else if (this.element && this.element.ownerDocument) {
|
||||
const channel = this.$props.cloudChannel ? this.$props.cloudChannel : '5';
|
||||
const apiKey = this.$props.apiKey ? this.$props.apiKey : 'no-api-key';
|
||||
|
||||
const scriptSrc = isNullOrUndefined(this.$props.tinymceScriptSrc) ?
|
||||
`https://cdn.tiny.cloud/1/${apiKey}/tinymce/${channel}/tinymce.min.js` :
|
||||
this.$props.tinymceScriptSrc;
|
||||
|
||||
ScriptLoader.load(
|
||||
this.element.ownerDocument,
|
||||
scriptSrc,
|
||||
initialise(this)
|
||||
);
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
if (getTinymce() !== null) {
|
||||
getTinymce().remove(this.editor);
|
||||
}
|
||||
},
|
||||
render() {
|
||||
return this.inlineEditor ? renderInline(this.elementId, this.$props.tagName) : renderIframe(this.elementId);
|
||||
}
|
||||
})
|
46
src/components/Tinymce/src/lib/components/EditorPropTypes.ts
Normal file
46
src/components/Tinymce/src/lib/components/EditorPropTypes.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2018-present, Ephox, Inc.
|
||||
*
|
||||
* This source code is licensed under the Apache 2 license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
export type CopyProps<T> = { [P in keyof T]: any };
|
||||
|
||||
export interface IPropTypes {
|
||||
apiKey: string;
|
||||
cloudChannel: string;
|
||||
id: string;
|
||||
init: any;
|
||||
initialValue: string;
|
||||
outputFormat: 'html' | 'text';
|
||||
inline: boolean;
|
||||
modelEvents: string[] | string;
|
||||
plugins: string[] | string;
|
||||
tagName: string;
|
||||
toolbar: string[] | string;
|
||||
modelValue: string;
|
||||
disabled: boolean;
|
||||
tinymceScriptSrc: string;
|
||||
}
|
||||
|
||||
export const editorProps: CopyProps<IPropTypes> = {
|
||||
apiKey: String,
|
||||
cloudChannel: String,
|
||||
id: String,
|
||||
init: Object,
|
||||
initialValue: String,
|
||||
inline: Boolean,
|
||||
modelEvents: [String, Array],
|
||||
plugins: [String, Array],
|
||||
tagName: String,
|
||||
toolbar: [String, Array],
|
||||
modelValue: String,
|
||||
disabled: Boolean,
|
||||
tinymceScriptSrc: String,
|
||||
outputFormat: {
|
||||
type: String,
|
||||
validator: (prop: string) => prop === 'html' || prop === 'text'
|
||||
},
|
||||
};
|
4
src/components/Tinymce/src/lib/global.d.ts
vendored
Normal file
4
src/components/Tinymce/src/lib/global.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// Global compile-time constants
|
||||
declare var __DEV__: boolean
|
||||
declare var __BROWSER__: boolean
|
||||
declare var __CI__: boolean
|
3
src/components/Tinymce/src/lib/index.ts
Normal file
3
src/components/Tinymce/src/lib/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Editor } from './components/Editor';
|
||||
|
||||
export default Editor;
|
10
src/components/Tinymce/src/plugins.ts
Normal file
10
src/components/Tinymce/src/plugins.ts
Normal file
@ -0,0 +1,10 @@
|
||||
// Any plugins you want to use has to be imported
|
||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
||||
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
||||
// colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration
|
||||
|
||||
const plugins = [
|
||||
'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount',
|
||||
];
|
||||
|
||||
export default plugins;
|
31
src/components/Tinymce/src/props.ts
Normal file
31
src/components/Tinymce/src/props.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { PropType } from 'vue';
|
||||
|
||||
export const basicProps = {
|
||||
id: {
|
||||
type: String as PropType<string>,
|
||||
default: () => {
|
||||
return `tinymce-${new Date().getTime()}${(Math.random() * 1000).toFixed(0)}`;
|
||||
},
|
||||
},
|
||||
menubar: {
|
||||
type: String as PropType<string>,
|
||||
default: 'file edit insert view format table',
|
||||
},
|
||||
value: {
|
||||
type: String as PropType<string>,
|
||||
// default: ''
|
||||
},
|
||||
// 高度
|
||||
height: {
|
||||
type: [Number, String] as PropType<string | number>,
|
||||
required: false,
|
||||
default: 400,
|
||||
},
|
||||
|
||||
// 宽度
|
||||
width: {
|
||||
type: [Number, String] as PropType<string | number>,
|
||||
required: false,
|
||||
default: 'auto',
|
||||
},
|
||||
};
|
9
src/components/Tinymce/src/toolbar.ts
Normal file
9
src/components/Tinymce/src/toolbar.ts
Normal file
@ -0,0 +1,9 @@
|
||||
// Here is a list of the toolbar
|
||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||
|
||||
const toolbar = [
|
||||
'searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample',
|
||||
'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen',
|
||||
];
|
||||
|
||||
export default toolbar;
|
@ -66,6 +66,20 @@ const menu: MenuModule = {
|
||||
path: '/strength-meter',
|
||||
name: '密码强度组件',
|
||||
},
|
||||
{
|
||||
path: '/tinymce',
|
||||
name: '富文本',
|
||||
children: [
|
||||
{
|
||||
path: '/index',
|
||||
name: '基础使用',
|
||||
},
|
||||
{
|
||||
path: '/editor',
|
||||
name: '嵌入form使用',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
@ -136,5 +136,31 @@ export default {
|
||||
title: '密码强度组件',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/tinymce',
|
||||
name: 'TinymceDemo',
|
||||
meta: {
|
||||
title: '富文本',
|
||||
},
|
||||
redirect: '/comp/tinymce/index',
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'Tinymce',
|
||||
component: () => import('/@/views/demo/comp/tinymce/index.vue'),
|
||||
meta: {
|
||||
title: '基础使用',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
name: 'TinymceEditor',
|
||||
component: () => import('/@/views/demo/comp/tinymce/Editor.vue'),
|
||||
meta: {
|
||||
title: '嵌入form使用',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
} as AppRouteModule;
|
||||
|
58
src/views/demo/comp/tinymce/Editor.vue
Normal file
58
src/views/demo/comp/tinymce/Editor.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="m-4">
|
||||
<CollapseContainer title="富文本表单">
|
||||
<BasicForm
|
||||
:labelWidth="100"
|
||||
:schemas="schemas"
|
||||
:actionColOptions="{ span: 24 }"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
</BasicForm>
|
||||
</CollapseContainer>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, h } from 'vue';
|
||||
import { BasicForm, FormSchema } from '/@/components/Form/index';
|
||||
import { CollapseContainer } from '/@/components/Container/index';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { Tinymce } from '/@/components/Tinymce/index';
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'title',
|
||||
component: 'Input',
|
||||
label: 'title',
|
||||
defaultValue: 'defaultValue',
|
||||
rules: [{ required: true }],
|
||||
},
|
||||
{
|
||||
field: 'tinymce',
|
||||
component: 'Input',
|
||||
label: 'tinymce',
|
||||
defaultValue: 'defaultValue',
|
||||
rules: [{ required: true }],
|
||||
render: ({ model, field }) => {
|
||||
return h(Tinymce, {
|
||||
value: model[field],
|
||||
onChange: (value: string) => {
|
||||
model[field] = value;
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
components: { BasicForm, CollapseContainer, Tinymce },
|
||||
setup() {
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
return {
|
||||
schemas,
|
||||
handleSubmit: (values: any) => {
|
||||
createMessage.success('click search,values:' + JSON.stringify(values));
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
19
src/views/demo/comp/tinymce/index.vue
Normal file
19
src/views/demo/comp/tinymce/index.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="flex p-4">
|
||||
<Tinymce value="Hello, World!" @change="handleChange" width="100%" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { Tinymce } from '/@/components/Tinymce/index';
|
||||
|
||||
export default defineComponent({
|
||||
components: { Tinymce },
|
||||
setup() {
|
||||
function handleChange(value: string) {
|
||||
console.log(value);
|
||||
}
|
||||
return { handleChange };
|
||||
},
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user