Feedback.js 7.53 KB
/* eslint-disable */
import React, { useEffect, useRef, useState } from "react";
import { Button, Badge } from "antd";
import { MessageOutlined } from "@ant-design/icons";
import Draggable from "react-draggable";
import styles from "./index.less";

const _this = {};

const Feedback = props => {
  const { app } = props;
  const { userinfo } = app;
  const [showState, setShowState] = useState(false);
  const iframeRef = useRef(null);
  const [unReadCount, setUnReadCount] = useState(0);
  const [unReadCountColor, setUnReadCountColor] = useState(0);
  const iframeId = useRef(
    Math.random()
      .toString(36)
      .substring(2)
  );
  useEffect(() => {
    const recMessage = e => {
      if (e && e.data) {
        const { payload, action, iCount, color } = e.data;
        if (payload === "commonFeedback") {
          switch (action) {
            case "closeModal":
              setTimeout(() => {
                setShowState(false);
              }, 500);
              break;
            case "unReadCountChange":
              setUnReadCount(iCount);
              setUnReadCountColor(color);
              break;
            default:
              break;
          }
        }
      }
    };
    window.addEventListener("message", recMessage);
    return () => {
      window.removeEventListener("message", recMessage);
    };
  }, []);

  const sendMessage = () => {
    setShowState(true);
    iframeRef.current.contentWindow.postMessage(
      {
        payload: "commonFeedback",
        action: "openModal",
        currentPane: JSON.parse(localStorage.getItem("xlybusinesscurrentPane")),
        app: { userinfo }
      },
      "*"
    );
  };

  // 设置按钮活动范围
  const [positionOffset, setPositionOffset] = useState({ x: 0, y: -200 });
  const [tempClient, setTempClient] = useState([0, 0]);
  const [bounds, setBounds] = useState(null);
  const btnRef = useRef(null);
  const [showBtn, setShowBtn] = useState(true); // 按钮是否显示
  useEffect(() => {
    const handleResize = () => {
      setShowBtn(false);
      const btnWith = 32;
      const btnHeight = 32;
      const feedbackBtnRecord =
        sessionStorage.getItem("feedbackBtnRecord") || "0,0";
      const diffX = Number(feedbackBtnRecord.split(",")[0]);
      const diffY = Number(feedbackBtnRecord.split(",")[1]);
      let newX = positionOffset.x + diffX;
      let newY = positionOffset.y + diffY;
      newX = Math.max(-window.innerWidth + btnWith, newX);
      newX = Math.min(newX, 0);
      newY = Math.max(-window.innerHeight + btnHeight + 53, newY);
      newY = Math.min(newY, 0);
      sessionStorage.setItem(
        "feedbackBtnRecord",
        `${newX - positionOffset.x},${newY - positionOffset.y}`
      );
      const positionOffsetNew = {
        x: newX,
        y: newY
      };
      setPositionOffset(positionOffsetNew);
      const { x: offsetX, y: offsetY } = positionOffsetNew;
      setBounds({
        top: -(window.innerHeight + offsetY - 53 - btnHeight), // 按钮上方可移动范围
        left: -(window.innerWidth + offsetX - btnWith), // 按钮左边可移动用范围
        right: -offsetX, // 按钮右边可移动用范围
        bottom: -offsetY // 按钮下边可移动范围
      });
      setTimeout(() => {
        setShowBtn(true);
        hideEdgeBtn();
      }, 100);
    };
    handleResize();
    window.addEventListener("resize", handleResize);
    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

  // 记录按钮位置
  const recordBtnPostion = (diffX, diffY) => {
    const feedbackBtnRecord = sessionStorage.getItem("feedbackBtnRecord");
    let feedbackBtnRecordNew = `${diffX},${diffY}`;
    if (feedbackBtnRecord) {
      feedbackBtnRecordNew = `${Number(feedbackBtnRecord.split(",")[0]) +
        diffX},${Number(feedbackBtnRecord.split(",")[1]) + diffY}`;
    }
    sessionStorage.setItem("feedbackBtnRecord", feedbackBtnRecordNew);
  };

  // 隐藏边缘按钮
  const timer = useRef(null);
  const [badgeClass, setBadgeClass] = useState(null);
  const hideEdgeBtn = () => {
    if (_this.draging) {
      return;
    }
    const feedbackBtnRecord =
      sessionStorage.getItem("feedbackBtnRecord") || "0,0";
    const diffX = Number(feedbackBtnRecord.split(",")[0]);
    const diffY = Number(feedbackBtnRecord.split(",")[1]);

    clearTimeout(timer.current);
    timer.current = null;
    if (Math.abs(diffX) < 1) {
      setTimeout(() => {
        // document.querySelector("html").style.overflowX = "hidden";
        setBadgeClass(styles.hideBtnToRight);
      }, 1500);
    } else if (window.innerWidth - Math.abs(diffX) - 32 < 1) {
      setTimeout(() => {
        // document.querySelector("html").style.overflowX = "hidden";
        setBadgeClass(styles.hideBtnToLeft);
      }, 1500);
    } else if (Math.abs(diffY - 200) < 1) {
      setTimeout(() => {
        // document.querySelector("html").style.overflowY = "hidden";
        setBadgeClass(styles.hideBtnToBottom);
      }, 1500);
    }
  };

  return (
    <>
      <div
        style={{
          position: "absolute",
          bottom: 0,
          right: 0,
          zIndex: 998
        }}
      >
        {showBtn && (
          <Draggable
            bounds={bounds}
            positionOffset={positionOffset}
            onStart={() => {
              const { x, y } = btnRef.current.getBoundingClientRect();
              setTempClient([x, y]);
            }}
            onDrag={() => {
              _this.draging = true;
              clearTimeout(timer.current);
              timer.current = null;
              setBadgeClass("");
            }}
            onStop={() => {
              _this.draging = false;
              const { x, y } = btnRef.current.getBoundingClientRect();
              const diffX = x - tempClient[0];
              const diffY = y - tempClient[1];
              recordBtnPostion(diffX, diffY);
              hideEdgeBtn();
              if (Math.abs(diffX) <= 2 && Math.abs(diffY) <= 2) {
                sendMessage();
              }
            }}
          >
            <div>
              <Badge
                className={badgeClass}
                count={unReadCount}
                offset={badgeClass === styles.hideBtnToLeft ? [0, 5] : [-30, 5]}
                color={unReadCountColor}
                onMouseOver={() => {
                  clearTimeout(timer.current);
                  timer.current = null;
                  setBadgeClass("");
                  // document.querySelector("html").style.overflowX = "auto";
                  // document.querySelector("html").style.overflowY = "auto";
                }}
                onMouseLeave={() => {
                  hideEdgeBtn();
                }}
              >
                <Button ref={btnRef} type="primary" shape="circle" size="large">
                  <MessageOutlined />
                </Button>
              </Badge>
            </div>
          </Draggable>
        )}
      </div>
      <div
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          width: "100vw",
          height: "100vh",
          zIndex: 1001,
          overflow: "hidden",
          display: showState ? "" : "none"
        }}
      >
        <iframe
          ref={iframeRef}
          // src={`http://localhost:8000/commonFeedback?iframeId=${
          //   iframeId.current
          // }`}
          src={`https://project.xlyprint.cn/commonFeedback?iframeId=${
            iframeId.current
          }`}
          title="问题反馈"
          width="100%"
          height="100%"
          frameborder="0"
        />
      </div>
    </>
  );
};

export default Feedback;