Editor.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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.getSelection() || {}).index;
  36. if (typeof index == "undefined") {
  37. index = this.quill.getLength() - 1;
  38. }
  39. this.quill.insertText(index, text);
  40. }
  41. });
  42. $editable.on("mousewheel touchstart touchmove", e => {
  43. if (this.quill.hasFocus()) {
  44. e.stopPropagation();
  45. }
  46. });
  47. // this.quill.on("selection-change", (range, oldRange, source) => {
  48. // this._focusin = range !== null;
  49. // });
  50. // this.quill.on("text-change", (delta, oldDelta, source) => {
  51. // let size = this.quill.getLength() - 1;
  52. // let html = this.quill.root.innerHTML;
  53. // if (this.maxlength > 0 && size > this.maxlength) {
  54. // html = this.quill.root.innerHTML = htmlCut(
  55. // html,
  56. // this.maxlength
  57. // );
  58. // size = this.quill.getLength() - 1;
  59. // }
  60. // this.$emit("change", { html, size });
  61. // });
  62. this.quill.on("text-change", (delta, old, source) => {
  63. let html = this.quill.root.innerHTML == '<p><br></p>' ? '' : this.quill.root.innerHTML;
  64. console.dir(this.quill.root, 'wdwdwd');
  65. // 过滤emoji表情
  66. html = html.replace(/(\ud83c[\udf00-\udfff])|(\ud83d[\udc00-\ude4f])|(\ud83d[\ude80-\udeff])/g, function (char) {
  67. var H, L, code;
  68. if (char.length === 2) {
  69. return ""
  70. } else {
  71. return char;
  72. }
  73. });
  74. if (this.maxlength > 0 && this.quill.getLength() > this.maxlength) {
  75. setTimeout(() => {
  76. this.quill.deleteText(
  77. this.maxlength,
  78. this.quill.getLength()
  79. );
  80. let size = this.quill.getLength() - 1;
  81. this.$emit("change", { html, size });
  82. }, 300);
  83. } else {
  84. let size = this.quill.getLength() - 1;
  85. this.$emit("change", { html, size });
  86. }
  87. });
  88. },
  89. methods: {
  90. setHtml(html = "") {
  91. this.$nextTick(() => (this.quill.root.innerHTML = html));
  92. //this.quill.clipboard.dangerouslyPasteHTML(0, html);
  93. },
  94. addLink(text, link) {
  95. if (!text || !link) {
  96. return;
  97. }
  98. if (!/http(s)?:\/\//.test(link)) {
  99. link = "https://" + link;
  100. }
  101. // if (!this._focusin) {
  102. // this.quill.focus();
  103. // }
  104. if (!this.quill.hasFocus()) {
  105. this.quill.focus();
  106. }
  107. let index = (this.quill.getSelection() || {}).index;
  108. if (typeof index == "undefined") {
  109. index = this.quill.getLength() - 1;
  110. }
  111. this.quill.insertText(index, text, "link", link);
  112. this.quill.blur();
  113. }
  114. }
  115. };
  116. </script>
  117. <style lang="less">
  118. .com-editor {
  119. height: 100%;
  120. padding: 0 0 30px 0;
  121. .ql-editor {
  122. padding: 10px;
  123. user-select: auto;
  124. font-size: 14px;
  125. white-space: normal !important;
  126. a {
  127. color: @color;
  128. }
  129. }
  130. .ql-editor.ql-blank::before {
  131. left: 10px;
  132. right: 10px;
  133. top: 10px;
  134. color: #888888;
  135. }
  136. .ql-clipboard {
  137. left: -100000px;
  138. height: 1px;
  139. overflow-y: hidden;
  140. position: absolute;
  141. top: 50%;
  142. }
  143. }
  144. [show-mode="mobile"],
  145. [edit-mode="mobile"] {
  146. .com-editor {
  147. .ql-editor {
  148. font-size: 100%;
  149. }
  150. }
  151. }
  152. </style>