zoukankan      html  css  js  c++  java
  • vue-quill-editor + + antd 组件封装(包含图片上传)

    QuillEditor 组件封装:

    需要 使用 npm 安装依赖:

    "vue-quill-editor": "^3.0.6",
    "quill-image-resize-module": "^3.0.0",

    QuillEditor .vue 代码:

      1 <template>
      2   <div>
      3     <quill-editor
      4       class="editor"
      5       ref="myTextEditor"
      6       v-model="editorContent"
      7       :options="editorOption"
      8       @change="onEditorChange($event)"
      9       @ready="ready($event)"
     10     >
     11     </quill-editor>
     12     <a-upload
     13       class="ant-my-uploader"
     14       style="display:none"
     15       action="/content/file/upload-oss-image"
     16       :before-upload="beforeUpload"
     17       @change="handleChange"
     18     >
     19       <a-button> <a-icon type="upload" />Upload </a-button>
     20     </a-upload>
     21     <div>
     22       剩余可输入
     23       <span :style="{ color: 5000 - innerText.length < 0 ? 'red' : 'black' }">{{
     24         5000 - innerText.length
     25       }}</span>
     26  27     </div>
     28   </div>
     29 </template>
     30 
     31 <script>
     32 import { quillEditor } from "vue-quill-editor";
     33 import "quill/dist/quill.core.css";
     34 import "quill/dist/quill.snow.css";
     35 import "quill/dist/quill.bubble.css";
     36 import Quill from "quill";
     37 import ImageResize from "quill-image-resize-module";
     38 Quill.register("modules/imageResize", ImageResize);
     39 // 自定义文字大小
     40 let fontSizeStyle = Quill.import("attributors/style/size");
     41 fontSizeStyle.whitelist = [
     42   "10px",
     43   "11px",
     44   "12px",
     45   "13px",
     46   "14px",
     47   "15px",
     48   "16px",
     49   "17px",
     50   "18px",
     51   "19px",
     52   "20px",
     53   "21px",
     54   "22px",
     55   "23px",
     56   "24px",
     57   "25px",
     58   "26px"
     59 ];
     60 Quill.register(fontSizeStyle, true);
     61 import { lineHeightStyle } from "@/utils/lineheight";
     62 //工具菜单栏配置
     63 const toolbarOptions = [
     64   ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
     65   ["blockquote", "code-block"], // 引用  代码块
     66   [{ header: 1 }, { header: 2 }], // 1、2 级标题
     67   [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
     68   [{ script: "sub" }, { script: "super" }], // 上标/下标
     69   [{ indent: "-1" }, { indent: "+1" }], // 缩进
     70   // [{'direction': 'rtl'}],                         // 文本方向
     71   // [{ size: ["small", false, "large", "huge"] }], // 字体大小
     72   [{ size: fontSizeStyle.whitelist }], // 字体大小
     73   [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
     74   [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
     75   [{ font: [] }], // 字体种类
     76   [{ align: [] }], // 对齐方式
     77   [{ lineheight: ["initial", "1", "1.5", "1.75", "2", "3", "4", "5"] }], // 对齐方式
     78   ["clean"], // 清除文本格式
     79   ["link", "image", "video"] // 链接、图片、视频
     80 ];
     81 export default {
     82   components: {
     83     quillEditor
     84   },
     85   props: {
     86     content: String
     87   },
     88   data() {
     89     return {
     90       innerText: "",
     91       editorContent: null,
     92       editorOption: {
     93         placeholder: "请在这里输入", //提示
     94         readyOnly: false, //是否只读
     95         theme: "snow", //主题 snow/bubble
     96         syntax: true, //语法检测
     97         modules: {
     98           imageResize: {
     99             //添加
    100             displayStyles: {
    101               //添加
    102               backgroundColor: "black",
    103               border: "none",
    104               color: "white"
    105             },
    106             modules: ["Resize", "DisplaySize", "Toolbar"] //添加
    107           },
    108           toolbar: {
    109             container: toolbarOptions,
    110             handlers: {
    111               image: function(value) {
    112                 if (value) {
    113                   console.log(value);
    114                   // 触发input框选择图片文件
    115                   document.querySelector(".ant-my-uploader input").click();
    116                 } else {
    117                   this.quill.format("image", false);
    118                 }
    119               },
    120               lineheight: function(value) {
    121                 if (value) {
    122                   this.quill.format("lineHeight", value);
    123                 } else {
    124                   console.log(value);
    125                 }
    126               }
    127             }
    128           }
    129         }
    130       },
    131       loading: false
    132     };
    133   },
    134   computed: {
    135     editor() {
    136       return this.$refs.myTextEditor.quillEditor;
    137     }
    138   },
    139   mounted() {
    140     // Quill.register({ "formats/line-height": LineHeight }, true);
    141   },
    142   watch: {
    143     content: {
    144       handler: function(val) {
    145         this.editorContent = val;
    146       },
    147       immediate: true
    148     }
    149   },
    150   methods: {
    151     ready() {
    152       Quill.register({ "formats/lineHeight": lineHeightStyle }, true);
    153     },
    154     onEditorChange(editor) {
    155       // this.editorContent = editor.html;
    156       this.innerText = editor.text.replace(/[
    ]$/g, "");
    157       this.$emit("onChange", {
    158         content: editor.html,
    159         textLength: this.innerText.length
    160       });
    161     },
    162     // 上传图片
    163     uploadSuccess(val) {
    164       let quill = this.$refs.myTextEditor.quill;
    165       // 获取光标所在位置
    166       let length = quill.getSelection().index;
    167       // 插入图片  res.url为服务器返回的图片地址
    168       quill.insertEmbed(length, "image", val);
    169       // 调整光标到最后
    170       quill.setSelection(length + 1);
    171     },
    172     handleChange(info) {
    173       switch (info.file.status) {
    174         case "uploading":
    175           this.loading = true;
    176           break;
    177         case "done":
    178           this.loading = false;
    179           // eslint-disable-next-line no-case-declarations
    180           const { response } = info.file; // 请求返回的数据
    181           if (response.code == 200) {
    182             this.uploadSuccess(response.data);
    183             this.$message.success({
    184               content: "上传成功!",
    185               key: "uploadPic",
    186               duration: 2
    187             });
    188           } else {
    189             this.$message.error({
    190               content: response.msg || "上传发生错误" + response.code,
    191               key: "uploadPic",
    192               duration: 2
    193             });
    194           }
    195           break;
    196         case "error":
    197           this.loading = false;
    198           // 错误消息提示
    199           this.$message.error({
    200             content: "网络错误请稍后再试",
    201             key: "uploadPic",
    202             duration: 2
    203           });
    204           break;
    205         default:
    206           break;
    207       }
    208     },
    209     beforeUpload(file) {
    210       return new Promise((resolve, reject) => {
    211         this.$message.success({
    212           content: "上传中",
    213           key: "uploadPic",
    214           duration: 2
    215         });
    216         const isJpgOrPng =
    217           file.type === "image/jpeg" ||
    218           file.type === "image/png" ||
    219           file.type === "image/jpg";
    220         if (!isJpgOrPng) {
    221           this.$message.error("图片仅支持 jpeg 或 png 或 jpg 格式");
    222           return reject(false);
    223         }
    224         // const isLt300kb = file.size / 1024 < 300;
    225         const isLt2M = file.size / 1024 / 1024 < 2;
    226         if (!isLt2M) {
    227           this.$message.error("图片大于 2M");
    228           return reject(false);
    229         }
    230         return resolve(true);
    231       });
    232     }
    233   }
    234 };
    235 </script>
    236 
    237 <style>
    238 .editor {
    239   line-height: normal !important;
    240   /* height: 400px; */
    241   background-color: #ffffff;
    242 }
    243 .ql-snow .ql-tooltip[data-mode="link"]::before {
    244   content: "请输入链接地址:";
    245 }
    246 .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    247   border-right: 0px;
    248   content: "保存";
    249   padding-right: 0px;
    250 }
    251 .ql-snow .ql-tooltip a.ql-action::after {
    252   content: "编辑";
    253 }
    254 .ql-snow .ql-tooltip a.ql-remove::before {
    255   content: "移除";
    256 }
    257 .ql-snow .ql-tooltip[data-mode="video"]::before {
    258   content: "请输入视频地址:";
    259 }
    260 .ql-snow .ql-picker.ql-size .ql-picker-label::before,
    261 .ql-snow .ql-picker.ql-size .ql-picker-item::before {
    262   content: "14px";
    263 }
    264 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
    265 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
    266   content: "10px";
    267 }
    268 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
    269 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
    270   content: "18px";
    271 }
    272 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
    273 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
    274   content: "32px";
    275 }
    276 
    277 .ql-snow .ql-picker.ql-header .ql-picker-label::before,
    278 .ql-snow .ql-picker.ql-header .ql-picker-item::before {
    279   content: "文本";
    280 }
    281 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
    282 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
    283   content: "标题1";
    284 }
    285 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
    286 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
    287   content: "标题2";
    288 }
    289 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
    290 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
    291   content: "标题3";
    292 }
    293 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
    294 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
    295   content: "标题4";
    296 }
    297 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
    298 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
    299   content: "标题5";
    300 }
    301 .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
    302 .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
    303   content: "标题6";
    304 }
    305 .ql-snow .ql-picker.ql-font .ql-picker-label::before,
    306 .ql-snow .ql-picker.ql-font .ql-picker-item::before {
    307   content: "标准字体";
    308 }
    309 .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
    310 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
    311   content: "衬线字体";
    312 }
    313 .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
    314 .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
    315   content: "等宽字体";
    316 }
    317 /* 编辑器内部出现滚动条 */
    318 .ql-container {
    319   /* overflow-y: auto; */
    320   height: 400px !important;
    321 }
    322 /*滚动条整体样式*/
    323 .ql-container ::-webkit-scrollbar {
    324    10px; /*竖向滚动条的宽度*/
    325   height: 10px; /*横向滚动条的高度*/
    326 }
    327 .ql-container ::-webkit-scrollbar-thumb {
    328   /*滚动条里面的小方块*/
    329   background: #666666;
    330   border-radius: 5px;
    331 }
    332 .ql-container ::-webkit-scrollbar-track {
    333   /*滚动条轨道的样式*/
    334   background: #ccc;
    335   border-radius: 5px;
    336 }
    337 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before,
    338 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {
    339   content: "10px";
    340 }
    341 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="11px"]::before,
    342 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="11px"]::before {
    343   content: "11px";
    344 }
    345 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
    346 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
    347   content: "12px";
    348 }
    349 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="13px"]::before,
    350 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="13px"]::before {
    351   content: "13px";
    352 }
    353 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
    354 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
    355   content: "14px";
    356 }
    357 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="15px"]::before,
    358 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="15px"]::before {
    359   content: "15px";
    360 }
    361 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
    362 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
    363   content: "16px";
    364 }
    365 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="17px"]::before,
    366 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="17px"]::before {
    367   content: "17px";
    368 }
    369 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
    370 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
    371   content: "18px";
    372 }
    373 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="19px"]::before,
    374 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="19px"]::before {
    375   content: "19px";
    376 }
    377 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
    378 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
    379   content: "20px";
    380 }
    381 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="21px"]::before,
    382 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="21px"]::before {
    383   content: "21px";
    384 }
    385 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
    386 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
    387   content: "22px";
    388 }
    389 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="23px"]::before,
    390 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="23px"]::before {
    391   content: "23px";
    392 }
    393 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before,
    394 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
    395   content: "24px";
    396 }
    397 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="25px"]::before,
    398 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="25px"]::before {
    399   content: "25px";
    400 }
    401 .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
    402 .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
    403   content: "26px";
    404 }
    405 .ql-snow .ql-picker.ql-lineheight .ql-picker-label::before{
    406   content: "行高";
    407 }
    408 .ql-snow
    409   .ql-picker.ql-lineheight
    410   .ql-picker-item[data-value="initial"]::before {
    411   content: "默认";
    412 }
    413 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="1"]::before {
    414   content: "1";
    415 }
    416 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="1.5"]::before {
    417   content: "1.5";
    418 }
    419 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="1.75"]::before {
    420   content: "1.75";
    421 }
    422 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="2"]::before {
    423   content: "2";
    424 }
    425 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="3"]::before {
    426   content: "3";
    427 }
    428 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="4"]::before {
    429   content: "4";
    430 }
    431 .ql-snow .ql-picker.ql-lineheight .ql-picker-item[data-value="5"]::before {
    432   content: "5";
    433 }
    434 .ql-snow .ql-picker.ql-lineheight {
    435    70px;
    436 }
    437 </style>
  • 相关阅读:
    HTML(图像img、表格table、列表)
    HTML(标题h、段落p、文本格式化、链接a、头部head)
    List的复制 (浅拷贝与深拷贝)
    最新CentOS6.5安装Docker, 使用阿里云源下载(亲测)
    VirtualBox安装CentOS6.5
    P1010 幂次方 题解
    P1469 找筷子 题解
    P1866 编号 题解
    EasyNVR通道离线但视频流可正常播放是什么原因导致的?
    EasyNVR通过国标GB28181协议级联出现报错及播放不了的问题调整
  • 原文地址:https://www.cnblogs.com/kitty-blog/p/14031723.html
Copyright © 2011-2022 走看看