index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <template>
  2. <div>
  3. <!-- 图片上传组件辅助 -->
  4. <el-upload
  5. class="avatar-uploader quill-img"
  6. :action="uploadImgUrl"
  7. name="file"
  8. :headers="headers"
  9. :show-file-list="false"
  10. :on-success="quillImgSuccess"
  11. :on-error="uploadError"
  12. :before-upload="quillImgBefore"
  13. accept='.jpg,.jpeg,.png,.gif'
  14. ></el-upload>
  15. <!-- 富文本组件 -->
  16. <quill-editor
  17. class="editor"
  18. v-model="content"
  19. ref="quillEditor"
  20. :options="editorOption"
  21. @blur="onEditorBlur($event)"
  22. @focus="onEditorFocus($event)"
  23. @change="onEditorChange($event)"
  24. ></quill-editor>
  25. </div>
  26. </template>
  27. <script>
  28. import { getToken } from '@/utils/auth'
  29. // 工具栏配置
  30. const toolbarOptions = [
  31. ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
  32. ["blockquote", "code-block"], // 引用 代码块
  33. [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
  34. [{ indent: "-1" }, { indent: "+1" }], // 缩进
  35. [{ size: ["small", false, "large", "huge"] }], // 字体大小
  36. [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  37. [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  38. [{ align: [] }], // 对齐方式
  39. ["clean"], // 清除文本格式
  40. ["link", "image", "video"] // 链接、图片、视频
  41. ];
  42. import { quillEditor } from "vue-quill-editor";
  43. import "quill/dist/quill.core.css";
  44. import "quill/dist/quill.snow.css";
  45. import "quill/dist/quill.bubble.css";
  46. export default {
  47. props: {
  48. /* 编辑器的内容 */
  49. value: {
  50. type: String
  51. },
  52. /* 图片大小 */
  53. maxSize: {
  54. type: Number,
  55. default: 4000 //kb
  56. }
  57. },
  58. components: { quillEditor },
  59. data() {
  60. return {
  61. content: this.value,
  62. uploadImgUrl: "",
  63. editorOption: {
  64. placeholder: "",
  65. theme: "snow", // or 'bubble'
  66. placeholder: "请输入内容",
  67. modules: {
  68. toolbar: {
  69. container: toolbarOptions,
  70. handlers: {
  71. image: function(value) {
  72. if (value) {
  73. // 触发input框选择图片文件
  74. document.querySelector(".quill-img input").click();
  75. } else {
  76. this.quill.format("image", false);
  77. }
  78. }
  79. }
  80. }
  81. }
  82. },
  83. uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
  84. headers: {
  85. Authorization: 'Bearer ' + getToken()
  86. }
  87. };
  88. },
  89. watch: {
  90. value: function() {
  91. this.content = this.value;
  92. }
  93. },
  94. methods: {
  95. onEditorBlur() {
  96. //失去焦点事件
  97. },
  98. onEditorFocus() {
  99. //获得焦点事件
  100. },
  101. onEditorChange() {
  102. //内容改变事件
  103. this.$emit("input", this.content);
  104. },
  105. // 富文本图片上传前
  106. quillImgBefore(file) {
  107. let fileType = file.type;
  108. if(fileType === 'image/jpeg' || fileType === 'image/png'){
  109. return true;
  110. }else {
  111. this.$message.error('请插入图片类型文件(jpg/jpeg/png)');
  112. return false;
  113. }
  114. },
  115. quillImgSuccess(res, file) {
  116. // res为图片服务器返回的数据
  117. // 获取富文本组件实例
  118. let quill = this.$refs.quillEditor.quill;
  119. // 如果上传成功
  120. if (res.code == 200) {
  121. // 获取光标所在位置
  122. let length = quill.getSelection().index;
  123. // 插入图片 res.url为服务器返回的图片地址
  124. quill.insertEmbed(length, "image", res.url);
  125. // 调整光标到最后
  126. quill.setSelection(length + 1);
  127. } else {
  128. this.$message.error("图片插入失败");
  129. }
  130. },
  131. // 富文本图片上传失败
  132. uploadError() {
  133. // loading动画消失
  134. this.$message.error("图片插入失败");
  135. }
  136. }
  137. };
  138. </script>
  139. <style>
  140. .editor {
  141. white-space: pre-wrap!important;
  142. line-height: normal !important;
  143. height: 192px;
  144. }
  145. .quill-img {
  146. display: none;
  147. }
  148. .ql-snow .ql-tooltip[data-mode="link"]::before {
  149. content: "请输入链接地址:";
  150. }
  151. .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  152. border-right: 0px;
  153. content: "保存";
  154. padding-right: 0px;
  155. }
  156. .ql-snow .ql-tooltip[data-mode="video"]::before {
  157. content: "请输入视频地址:";
  158. }
  159. .ql-snow .ql-picker.ql-size .ql-picker-label::before,
  160. .ql-snow .ql-picker.ql-size .ql-picker-item::before {
  161. content: "14px";
  162. }
  163. .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
  164. .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  165. content: "10px";
  166. }
  167. .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
  168. .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  169. content: "18px";
  170. }
  171. .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
  172. .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  173. content: "32px";
  174. }
  175. .ql-snow .ql-picker.ql-header .ql-picker-label::before,
  176. .ql-snow .ql-picker.ql-header .ql-picker-item::before {
  177. content: "文本";
  178. }
  179. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
  180. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  181. content: "标题1";
  182. }
  183. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
  184. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  185. content: "标题2";
  186. }
  187. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
  188. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  189. content: "标题3";
  190. }
  191. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
  192. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  193. content: "标题4";
  194. }
  195. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
  196. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  197. content: "标题5";
  198. }
  199. .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
  200. .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  201. content: "标题6";
  202. }
  203. .ql-snow .ql-picker.ql-font .ql-picker-label::before,
  204. .ql-snow .ql-picker.ql-font .ql-picker-item::before {
  205. content: "标准字体";
  206. }
  207. .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
  208. .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  209. content: "衬线字体";
  210. }
  211. .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
  212. .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  213. content: "等宽字体";
  214. }
  215. </style>