[UEditor rich text box] React supports image pasting

Support picture pasting

  /**
   * 图本粘贴处理
   * @param url String 图片链接
   */
  function pasteWordWithImg(htmlStr, imgArr) {
    let str = htmlStr;
    if (imgArr.length === 1) {
      const { upImgUrl, upWidth, upHeight } = imgArr[0];
      getImgToBase64(
        upImgUrl,
        parseInt(upWidth) + "",
        parseInt(upHeight) + "",
        (data) => {
          if (data) {
            // 只能是ClipboardItempng格式,但可以复制JPG
            const blob = base64ToBlob(data, "image/png");
            const file = new window.File([blob], "image.png", {
              type: blob.type,
            });
            requestUploadImg(file, width, pageHeight).then((res) => {
              str = replaceImgUrl(str, [
                {
                  originUrl: upImgUrl,
                  replaceUrl: res.datas.url,
                },
              ]);
              editor.execCommand("inserthtml", str);
            });
          } else {
            message.error("图片粘贴不成功。试试单独复制原图并用Ctrl+V粘贴");
            str = replaceImgUrl(str, [
              {
                originUrl: upImgUrl,
                replaceUrl: "",
              },
            ]);
            editor.execCommand("inserthtml", str);
          }
        }
      );
    } else if (imgArr.length > 1 && imgArr.length <= 10) {
      let total = 0;
      imgArr.forEach((citem, index) => {
        const { upImgUrl, upWidth, upHeight } = citem;
        getImgToBase64(
          upImgUrl,
          parseInt(upWidth) + "",
          parseInt(upHeight) + "",
          (data) => {
            if (data) {
              // 只能是ClipboardItempng格式,但可以复制JPG
              const blob = base64ToBlob(data, "image/png");
              const file = new window.File([blob], "image.png", {
                type: blob.type,
              });
              requestUploadImg(file, width, pageHeight)
                .then((res) => {
                  str = replaceImgUrl(str, [
                    {
                      originUrl: upImgUrl,
                      replaceUrl: res.datas.url,
                    },
                  ]);
                  total++;
                  if (total === imgArr.length) {
                    editor.execCommand("inserthtml", str);
                  }
                });
            } else {
              //只执行最后一次插入动作。
              if (index === imgArr.length - 1) {
                imgArr.forEach((citem) => {
                  const { upImgUrl } = citem;
                  str = replaceImgUrl(str, [
                    {
                      originUrl: upImgUrl,
                      replaceUrl: "",
                    },
                  ]);
                });
                const parser = new DOMParser();
                const doc = parser.parseFromString(str, "text/html");
                editor.execCommand("inserthtml", doc && doc.body.outerHTML);
                message.error("图片粘贴不成功。试试单独复制原图并用Ctrl+V粘贴");
              }
            }
          }
        );
      });
    } else if (imgArr.length > 10) {
      imgArr.forEach((citem) => {
        const { upImgUrl } = citem;
        str = replaceImgUrl(str, [
          {
            originUrl: upImgUrl,
            replaceUrl: "",
          },
        ]);
        // editor.execCommand('inserthtml', str)
      });
      const parser = new DOMParser();
      const doc = parser.parseFromString(str, "text/html");
      editor.execCommand("inserthtml", doc && doc.body.outerHTML);
      message.error("图片超出十张请分批粘贴");
    }
  } 

  const replacePicturePath = (html) => {
    const imgArr = [];

    // 此处matchStr匹配的img标签的整体内容,groups匹配的是img中src的url
    // imgArr是要当前html中要批量上传的图片地址
    html.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, (matchStr, groups) => {
      const widthReg = /width=['"]([^'"]+)/;
      const heightReg = /height=['"]([^'"]+)/;
      imgArr.push({
        upImgUrl: groups,
        matchStr: matchStr,
        upWidth: matchStr.match(widthReg) ? matchStr.match(widthReg)[1] : "200",
        upHeight: matchStr.match(heightReg)
          ? matchStr.match(heightReg)[1]
          : "200",
      });
      return matchStr;
    });
    return imgArr;
  };

const getClipboardData = (e) => {
    const cbd = (e || e.originalEvent).clipboardData;
    if (cbd && cbd.items) {
      e.preventDefault();
      const list = Array.from(cbd.items);
      const imgItem = list.find(
        (o) => o.kind == "file" && o.type.match("image")
      );
      const strItem = list.find(
        (o) => o.kind === "string" && o.type === "text/plain"
      );
      const htmlItem = list.find(
        (o) => o.kind == "string" && o.type === "text/html"
      );
      if (imgItem) {
        const blob = imgItem.getAsFile();
        requestUploadImg(blob, width, pageHeight).then((res) => {
          editor.execCommand("insertimage", {
            src: res.datas.url,
            width: res.w,
            height: res.h,
          });
          //触发编辑器失焦事件
          document && document.getElementById("focusInput").focus();
          document.getElementById("focusInput").blur();
        });
      } else if (htmlItem) {
        htmlItem.getAsString((htmlStr) => {
          const str = htmlStr;
          const imgArr = replacePicturePath(str);
          if (imgArr.length > 0) {
            pasteWordWithImg(htmlStr, imgArr);
          } else {
            const parser = new DOMParser();
            const doc = parser.parseFromString(htmlStr, "text/html");
            //解决外部带格式横线粘贴时格式不吻合问题,只适配自动输入的下划线,排除U标签下划线干扰
            const reg = /<(span|h[1-6]|div|a|u)[^>]*>/g;
            const str = doc.body.outerHTML.replace(reg, (matchStr, groups) => {
              if (
                matchStr.includes("text-decoration:underline") &&
                !/<(u)[^>]*>/.test(doc.body.outerHTML)
              ) {
                return matchStr
                  .replace(
                    "text-decoration:underline",
                    "border-bottom: 1px solid #888"
                  )
                  .replaceAll(groups, "a");
              } else if (
                /<(u)[^>]*>/.test(doc.body.outerHTML) &&
                matchStr.includes("text-decoration:underline")
              ) {
                return matchStr.replace("text-decoration:underline", "");
              }

              return matchStr;
            });
            editor.execCommand("inserthtml", str);
          }
        });
      } else if (strItem) {
        strItem.getAsString((str) => {
          editor.execCommand("inserthtml", str);
        });
      }
    } else if (window.clipboardData) {
      if (!window.clipboardData.files || !window.clipboardData.files.length) {
        e.preventDefault();
        const txt = window.clipboardData.getData("text");
        const textNode = document.createTextNode(txt);
        const range = window.getRange();
        range.insertNode(textNode);
        window.setRange(range, textNode);
      }
    }
  };

editor.document.addEventListener("paste", (e) => {
  e.preventDefault();
  e.stopPropagation();
  getClipboardData(e);
});

Guess you like

Origin blog.csdn.net/gkf6104/article/details/122641806