TinymceEditor.vue 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <template>
  2. <div>
  3. <Editor
  4. api-key="写你的key"
  5. :init="init"
  6. v-model:content="content"
  7. ref="tinymce"
  8. />
  9. </div>
  10. </template>
  11. <script setup name="TinymceEditor">
  12. import Editor from "@tinymce/tinymce-vue";
  13. const { proxy } = getCurrentInstance();
  14. const props = defineProps(["value"]);
  15. const emit = defineEmits(["updateValue"]);
  16. const content = ref("");
  17. const tinymce = ref(null);
  18. const value = ref("");
  19. const init = reactive({
  20. plugins: "lists link image table code help wordcount",
  21. toolbar:
  22. "myButton | fontselect | fontsizeselect | formatselect | bold italic underline forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table | image | removeformat",
  23. content_css: "tinymce-5", //主题tinymce-5-dark || tinymce-5 || default || writer || document || dark
  24. custom_undo_redo_levels: 50, //回退数量
  25. end_container_on_empty_block: true, //块级文本是否换行
  26. keep_styles: true, //回车是否保存原有样式,例如code块回车是否截断
  27. menubar: false, //是否开启顶部菜单 > false 关闭菜单 | 'edit insert view format table tools help' 菜单按照这里排序 | 参考:https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/
  28. toolbar_mode: "wrap", //功能栏是否换行 > | wrap 换行 | scrolling 滚动 | sliding 省略
  29. toolbar_location: "top", //菜单栏位置 > bottom 底部 | top 顶部
  30. style_formats_merge: true, //是否开启默认功能
  31. elementpath: false, //是否展示编辑层级 > p span
  32. resize: true, //调整宽高 > true 调整高 | false 不可调整宽高 | both 宽高可调
  33. language: "zh_CN", //中文
  34. images_upload_url: "/demo/upimg.php",
  35. images_upload_base_path: "/demo",
  36. // 自定义快捷将
  37. text_patterns: [
  38. { start: "---", replacement: "<hr/>" },
  39. { start: "--", replacement: "—" },
  40. { start: "-", replacement: "—" },
  41. { start: "(c)", replacement: "©" },
  42. { start: "//brb", replacement: "Be Right Back" },
  43. {
  44. start: "//h",
  45. replacement:
  46. '<h1 style="color: blue">Heading here</h1> <h2>Author: Name here</h2> <p><em>Date: 01/01/2000</em></p> <hr />',
  47. },
  48. ],
  49. images_upload_handler: function (blobInfo, succFun, failFun) {
  50. var xhr, formData;
  51. var file = blobInfo.blob(); //转化为易于理解的file对象
  52. xhr = new XMLHttpRequest();
  53. xhr.withCredentials = false;
  54. xhr.open("POST", "/demo/upimg.php");
  55. xhr.onload = function () {
  56. var json;
  57. if (xhr.status != 200) {
  58. failFun("HTTP Error: " + xhr.status);
  59. return;
  60. }
  61. json = JSON.parse(xhr.responseText);
  62. if (!json || typeof json.location != "string") {
  63. failFun("Invalid JSON: " + xhr.responseText);
  64. return;
  65. }
  66. succFun(json.location);
  67. };
  68. formData = new FormData();
  69. formData.append("file", file, file.name); //此处与源文档不一样
  70. xhr.send(formData);
  71. },
  72. // 自定义指令
  73. text_patterns_lookup: (ctx) => {
  74. const parentTag = ctx.block.nodeName.toLowerCase();
  75. if (parentTag === "pre" || parentTag === "p") {
  76. return [{ start: "`", end: "`", format: "code" }];
  77. } else if (parentTag === "p") {
  78. return [{ start: "*", end: "*", format: "bold" }];
  79. } else if (parentTag === "span") {
  80. return [
  81. // ctx.text is the string from the start of the block to the cursor
  82. { start: "brb", replacement: ctx.text + ": Be Right Back" },
  83. ];
  84. } else {
  85. return [];
  86. }
  87. },
  88. });
  89. onMounted(() => {
  90. content.value = props.value;
  91. });
  92. </script>
  93. <style lang="scss" scoped>
  94. </style>