Editor.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <template>
  2. <div class="com-editor ui-input"></div>
  3. </template>
  4. <script>
  5. import config from "../../config";
  6. // import { htmlCut } from "../../utils/string";
  7. export default {
  8. props: {
  9. placeholder: String,
  10. maxlength: Number,
  11. html: String
  12. },
  13. mounted() {
  14. this.quill = new Quill(this.$el, {
  15. modules: {
  16. toolbar: false
  17. },
  18. placeholder: this.placeholder
  19. //preserveWhitespace:true
  20. });
  21. this.quill.root.innerHTML = this.html
  22. // this.$nextTick(() => (this.quill.root.innerHTML = html));
  23. const $editable = $(this.$el).find("[contenteditable]"); //this.$el.querySelector("[contenteditable]");
  24. $editable.on("paste", e => {
  25. e.preventDefault();
  26. let clp = (e.originalEvent || e).clipboardData;
  27. let text;
  28. if (clp === undefined || clp === null) {
  29. text = window.clipboardData.getData("text") || "";
  30. } else {
  31. text = clp.getData("text/plain") || "";
  32. }
  33. if (text) {
  34. //this.quill.root.innerHTML = this.quill.root.innerHTML+text;
  35. let index = this.quill.selection.savedRange.index
  36. if (typeof index == "undefined") {
  37. index = this.quill.getLength() - 1;
  38. }
  39. this.quill.insertText(index, text);
  40. setTimeout(() => {
  41. this.quill.setSelection(index + text.length);
  42. }, 10);
  43. }
  44. });
  45. $editable.on("mousewheel touchstart touchmove", e => {
  46. if (this.quill.hasFocus()) {
  47. e.stopPropagation();
  48. }
  49. });
  50. // this.quill.on("selection-change", (range, oldRange, source) => {
  51. // this._focusin = range !== null;
  52. // });
  53. // this.quill.on("text-change", (delta, oldDelta, source) => {
  54. // let size = this.quill.getLength() - 1;
  55. // let html = this.quill.root.innerHTML;
  56. // if (this.maxlength > 0 && size > this.maxlength) {
  57. // html = this.quill.root.innerHTML = htmlCut(
  58. // html,
  59. // this.maxlength
  60. // );
  61. // size = this.quill.getLength() - 1;
  62. // }
  63. // this.$emit("change", { html, size });
  64. // });
  65. this.quill.on("text-change", (delta, old, source) => {
  66. let html = this.quill.root.innerHTML == '<p><br></p>' ? '' : this.quill.root.innerHTML;
  67. // 过滤emoji表情
  68. html = html.replace(/(\ud83c[\udf00-\udfff])|(\ud83d[\udc00-\ude4f])|(\ud83d[\ude80-\udeff])/g, function (char) {
  69. var H, L, code;
  70. if (char.length === 2) {
  71. return ""
  72. } else {
  73. return char;
  74. }
  75. });
  76. if (this.maxlength > 0 && this.quill.getLength() > this.maxlength) {
  77. setTimeout(() => {
  78. this.quill.deleteText(
  79. this.maxlength,
  80. this.quill.getLength()
  81. );
  82. let size = this.quill.getLength() - 1;
  83. this.$emit("change", { html, size });
  84. }, 300);
  85. } else {
  86. let size = this.quill.getLength() - 1;
  87. this.$emit("change", { html, size });
  88. }
  89. });
  90. },
  91. methods: {
  92. setHtml(html = "") {
  93. this.$nextTick(() => (this.quill.root.innerHTML = html));
  94. //this.quill.clipboard.dangerouslyPasteHTML(0, html);
  95. },
  96. addLink(text, link) {
  97. if (!text || !link) {
  98. return;
  99. }
  100. if (!/http(s)?:\/\//.test(link)) {
  101. link = "https://" + link;
  102. }
  103. // if (!this._focusin) {
  104. // this.quill.focus();
  105. // }
  106. if (!this.quill.hasFocus()) {
  107. this.quill.focus();
  108. }
  109. let index = (this.quill.getSelection() || {}).index;
  110. if (typeof index == "undefined") {
  111. index = this.quill.getLength() - 1;
  112. }
  113. this.quill.insertText(index, text, "link", link);
  114. this.quill.blur();
  115. }
  116. }
  117. };
  118. </script>
  119. <style lang="less">
  120. .com-editor {
  121. height: 100%;
  122. padding: 0 0 30px 0;
  123. .ql-editor {
  124. padding: 10px;
  125. user-select: auto;
  126. font-size: 14px;
  127. white-space: normal !important;
  128. a {
  129. color: @color;
  130. }
  131. }
  132. .ql-editor.ql-blank::before {
  133. left: 10px;
  134. right: 10px;
  135. top: 10px;
  136. color: #505050;
  137. }
  138. .ql-clipboard {
  139. left: -100000px;
  140. height: 1px;
  141. overflow-y: hidden;
  142. position: absolute;
  143. top: 50%;
  144. }
  145. }
  146. [show-mode="mobile"],
  147. [edit-mode="mobile"] {
  148. .com-editor {
  149. .ql-editor {
  150. font-size: 100%;
  151. }
  152. }
  153. }
  154. </style>