react实现窗口悬浮框,可拖拽、折叠、滚动

1、效果如下

2、如下两个文件不需要修改

drag.js

import React from "react";
import PropTypes from "prop-types";

export default class DragM extends React.Component {
  static propTypes = {
    children: PropTypes.element.isRequired
  };
  static defaultProps = {
    //默认是移动children dom,覆盖该方法,可以把tranform行为同步给外部
    updateTransform: (transformStr, tx, ty, tdom) => {
      tdom.style.transform = transformStr;
    }
  };
  position = {
    startX: 0,
    startY: 0,
    dx: 0,
    dy: 0,
    tx: 0,
    ty: 0
  };
  start = event => {
    if (event.button != 0) {
      //只允许左键,右键问题在于不选择conextmenu就不会触发mouseup事件
      return;
    }
    document.addEventListener("mousemove", this.docMove);
    this.position.startX = event.pageX - this.position.dx;
    this.position.startY = event.pageY - this.position.dy;
  };
  docMove = event => {
    const tx = event.pageX - this.position.startX;
    const ty = event.pageY - this.position.startY;
    const transformStr = `translate(${tx}px,${ty}px)`;
    this.props.updateTransform(transformStr, tx, ty, this.tdom);
    this.position.dx = tx;
    this.position.dy = ty;
  };
  docMouseUp = event => {
    document.removeEventListener("mousemove", this.docMove);
  };

  componentDidMount() {
    this.tdom.addEventListener("mousedown", this.start);
    //用document移除对mousemove事件的监听
    document.addEventListener("mouseup", this.docMouseUp);
  }

  componentWillUnmount() {
    this.tdom.removeEventListener("mousedown", this.start);
    document.removeEventListener("mouseup", this.docMouseUp);
    document.removeEventListener("mousemove", this.docMove);
  }

  render() {
    const {children} = this.props;
    const newStyle = {
      ...children.props.style,
      cursor: "move",
      userSelect: "none"
    };
    return React.cloneElement(React.Children.only(children), {
      ref: tdom => {
        return (this.tdom = tdom);
      },
      style: newStyle
    });
  }
}

index.js

import React from "react";
import PropTypes from "prop-types";
import DragM from "./drag";
import {Modal} from "antd";

class BuildTitle extends React.Component {
  updateTransform = transformStr => {
    this.modalDom.style.transform = transformStr;
  };

  componentDidMount() {
    const modalList = document.getElementsByClassName("ant-modal"); //modal的class是ant-modal
    this.modalDom = modalList[modalList.length - 1];
  }

  render() {
    const {title} = this.props;
    return (
        <DragM updateTransform={this.updateTransform}>
          <div>{title}</div>
        </DragM>
    );
  }
}

export default class DragModal extends React.Component {
  static propTypes = {
    drag: PropTypes.bool,
    destroyOnClose: PropTypes.bool
  };

  static defaultProps = {
    drag: true,
    destroyOnClose: true
  };

  render() {
    const {
      drag,
      visible,
      title,
      destroyOnClose,
      children,
      ...restProps
    } = this.props;

    //是否可拖拽
    const _title =
        title && drag ? (
            <BuildTitle visible={visible} title={title}/>
        ) : (
            title
        );

    return (
        <Modal
            visible={visible}
            title={_title}
            destroyOnClose={destroyOnClose}
            {...restProps}
        >
          {children}
        </Modal>
    );
  }
}

3、如下两个文件,自己适当修改接口数据来源即可

index.js

import React from "react";
import styles from "./index.less";
import {Badge, Icon, Tabs} from "antd";
import DragModal from "../DragModal";
import classNames from 'classnames';
import NHFetch from "../../../../utils/NHFetch";

const TabPane = Tabs.TabPane;

export default class ModalContent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: undefined,
      open: true
    };
  }

  componentDidMount() {
    this.getMessage();
  }

  componentDidUpdate(prevProps) {
    // 当props.params变化时获取新数据
    if (this.props.params !== prevProps.params) {
      console.log('----------------------------------------')
      this.getMessage();
    }
  }
  getMessage = () => {
    let xsid = this.props.params
    if (xsid) {
      NHFetch('api/zhxg-yxwz/shxd/getZzbdInfoList', 'get', {xsid: xsid}).then((res) => {
        if (res && res.code === 200) {
          this.setState({data: res.data});
        }
      })

    }
  }
  // 切换状态
  onChangeOpen = () => {
    this.setState({
      open: !this.state.open
    });
  };


  render() {
    const {data, open} = this.state;
    const {studentName} = this.props
    return (
        <DragModal
            className={classNames({
              [styles.modalClese]: !open
            })}
            wrapClassName={styles.dragWrap}
            closable={false}
            width={300}
            title={
              <div>
                {studentName + ":"}自助报道办理情况
                <div
                    className={styles.modalBtn}
                    onClick={this.onChangeOpen}

                >
                  {open ? <Icon type="down"/> : <Icon type="up"/>}
                </div>
              </div>
            }
            mask={false}
            visible={this.props.params}
            footer={false}
        >
          <div className={styles.modalContent}>
            {
                data && data.map((item, i) => {
                  return (
                      <div key={i} className={styles.modalListHeader}>
                        <Badge status={item.BLZT === '1' ? "success" : "processing"}/>
                        {item.HJMC + "  "}
                        <span style={item.BLZT === '1' ? {color: "green"} : {color: 'red'}}>
                        {item.BLZT === '1' ? '已办理' : "未办理"}
                        </span>
                      </div>
                  );
                })
            }
          </div>
        </DragModal>
    );
  }
}

css文件,index.less

.box {
  background-color: #fff;

  .danger {
    color: #f5222d
  }

  .primary {
    color: #1990ff
  }
}

/* 页签 */
.tabs {
  :global {
    .ant-tabs-bar {
      margin-bottom: 0;
    }

    .ant-tabs-tab {
      margin-right: 0;
    }

    .ant-badge {
      margin-left: 4px;
      margin-top: -4px;
    }

    .ant-badge-count {
      height: 16px;
      line-height: 16px;
    }

    .ant-badge-multiple-words {
      padding: 0 4px;
    }
  }

  .tabsExtra {
    :global {
      .ant-input {
        width: 270px;
      }

      .ant-btn {
        width: 80px;
        margin-left: 10px;
      }

      .ant-select-selection {
        border: none;
        box-shadow: none;
      }
    }
  }
}

/* 菜单 */
.menuLayout {
  &:global(.ant-layout) {
    background: #fff;
  }

  :global {
    .ant-layout-sider {
      box-shadow: 2px 0 4px 0 rgba(217, 217, 217, 0.5);
    }

    .ant-layout-content {
      padding: 10px;
    }
  }
}

.menu {
  padding: 10px 0;

  :global {
    .ant-menu-item {
      width: 100%;
      margin-top: 0;
      margin-bottom: 0 !important;

      &:after {
        right: inherit;
        left: 0;
      }
    }
  }
}

/* 表格 */
.tableTop {
  overflow: hidden;

  .tableTopLeft {
    float: left;

    button {
      margin-right: 10px;
    }
  }

  .tableTopRight {
    float: right;
  }
}

.table {
  margin-top: 10px;

  .audit {
    position: absolute;
    left: -70px;
    top: 50%;
    width: 80px;
    height: 56px;
    margin-top: -28px;
    pointer-events: none
  }

  :global {
    .ant-table-thead {
      position: relative;
      height: 50px;

      &:after {
        content: "";
        display: block;
        position: absolute;
        left: 0;
        right: 0;
        top: 42px;
        background-color: #fff;
        height: 10px;
      }

      tr {
        background: rgba(25, 144, 255, 0.2);

        &:first-child > th:first-child {
          border-top-left-radius: 0;
        }

        &:first-child > th:last-child {
          border-top-right-radius: 0;
        }
      }

      th {
        padding: 10px;
        height: 50px;
        padding-bottom: 20px;
        white-space: nowrap;
      }
    }

    .ant-table-tbody {
      border-left: 1px solid #e8e8e8;
      border-right: 1px solid #e8e8e8;

      tr:first-child td {
        border-top: 1px solid #e8e8e8;
      }

      tr > td {
        position: relative;

        &:after {
          content: "";
          position: absolute;
          right: 0;
          top: 16px;
          bottom: 16px;
          border-right: 1px solid #e8e8e8;
        }

        &:last-child,
        &:first-child {
          &:after {
            display: none;
          }
        }
      }
    }
  }
}

.tablePage {
  overflow: hidden;
  margin-top: 10px;
  padding: 0 10px;

  .tablePageLeft {
    float: left;
    color: #999;
    line-height: 32px;
  }

  .tablePageRight {
    float: right;
  }
}

/* 弹窗 */
.dragWrap {
  overflow: hidden;
  pointer-events: none;

  .modalBtn {
    position: absolute;
    top: 0;
    right: 0;
    height: 50px;
    width: 50px;
    text-align: center;
    line-height: 50px;
    cursor: pointer;
    user-select: none;
  }

  .modalClese {
    :global {
      .ant-modal-body {
        height: 0;
      }
    }
  }

  .modalContent {
    width: 300px;
    padding: 0 20px 10px 20px;
  }

  .modalListHeader {
    padding: 10px;
  }

  .modalListItem {
    position: relative;
    padding: 5px 30px 5px 23px;
    background-color: rgba(25, 144, 255, 0.05);
    border-radius: 8px;
    margin-bottom: 6px;
  }

  .modalItemBadge {
    position: absolute;
    left: 10px;
    top: 5px;
  }

  .itemInfo {
    font-size: 12px;
    color: #999;

    span {
      color: #1990ff;
    }
  }

  .modalItemIcon {
    position: absolute;
    right: 10px;
    top: 50%;
    margin-top: -15px;
    color: #1990ff;
    font-size: 20px;
  }

  :global {
    .ant-modal {
      position: absolute;
      top: auto;
      bottom: 0;
      right: 0;
      margin: 0;
      padding-bottom: 0;
      pointer-events: auto;
    }

    .ant-modal-header {
      padding: 14px 10px;
      background-color: #1990ff;

      .ant-modal-title {
        padding-right: 50px;
        color: #fff;
        font-size: 14px;
      }
    }

    .ant-modal-content {
      overflow: hidden;
    }

    .ant-modal-close {
      color: #fff;
    }

    .ant-modal-close-x {
      height: 50px;
      line-height: 50px;
    }

    .ant-modal-body {
      max-height: 350px;
      padding: 0;
      overflow: hidden;
      overflow-y: scroll;
      margin-right: -20px;
      transition: all 0.3s;
    }
  }
}

4、最后适当位置使用组件即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/726820.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是片上端接校准(On Die Termination Calibration)技术?

On Die Termination Calibration 随着对于数字系统性能要求的不断提高&#xff0c;对信号完整性的要求也越来越高&#xff0c;从而能够在更高的速率下可靠运行。信号线端接是信号完整性管理中的有用元件&#xff0c;可以在memory外部或memory内部使用。在DRAM器件中加入电阻端接…

ChatmoneyAI如狂风般席卷广告创意舞台,轻松闯荡财富之海!

本文由 ChatMoney团队出品 引言 在广告创意行业&#xff0c;创新和高效是赢得市场的关键。而我今天要分享的就是如何利用ChatmoneyAI这款强大的人工智能工具&#xff0c;打破创新难题&#xff0c;赚取丰厚收益。 让我告诉你一个小秘密&#xff0c;有客户曾在一个月内&#xf…

React Native性能优化红宝书

一、React Native介绍 React Native 是Facebook在React.js Conf2015 推出的开源框架&#xff0c;使用React和应用平台的原生功能来构建 Android 和 iOS 应用。通过 React Native&#xff0c;可以使用 JavaScript 来访问移动平台的 API&#xff0c;使用 React 组件来描述 UI 的…

MATLAB直方图有关的函数

histogram Histogram plot画直方图 histcounts 直方图 bin 计数 histcounts是histogram的主要计算函数。 discretize 将数据划分为 bin 或类别 histogram2 画二元直方图 histcounts2 二元直方图 bin 计数 hist和histc过时了。替换不建议使用的 hist 和 histc 实例 hist → \r…

202483读书笔记|《把你写进诗歌里》——人生是一场不知何时散场的约会,爱慕向来短暂,失去才是唯一出路

202483读书笔记|《把你写进诗歌里》——人生是一场不知何时散场的约会&#xff0c;爱慕向来短暂&#xff0c;失去才是唯一出路 摘录 《把你写进诗歌里&#xff08;2020年度中国优秀诗歌&#xff09;》&#xff0c;作者上官文露。并不惊艳&#xff0c;中英文双语对照的一本诗集&…

压缩pdf文件大小在线,在线免费压缩pdf

在现在办公中&#xff0c;PDF文档已经成为我们日常工作中不可或缺的一部分。然而&#xff0c;随着文档内容的不断丰富&#xff0c;PDF文件的大小也逐渐增大&#xff0c;这不仅占用了大量的存储空间&#xff0c;而且在传输和共享时也显得尤为不便。所以有时候我们需要把pdf压缩小…

connect-caption-and-trace——用于共同建模图像、文本和人类凝视轨迹预测

介绍 论文地址&#xff1a;https://arxiv.org/abs/2105.05964 源码地址&#xff1a;https://github.com/facebookresearch/connect-caption-and-trace 在过去&#xff0c;计算机视觉和自然语言处理领域的模型和算法的发展只有偶尔的重叠&#xff0c;但近年来&#xff0c;这两…

AI音乐大模型:是创意的助力还是产业的挑战?

近期音乐界迎来了一场前所未有的革命。随着多家科技公司纷纷推出音乐大模型&#xff0c;素人生产音乐的门槛被前所未有地拉低&#xff0c;一个崭新的“全民音乐时代”似乎已近在眼前。然而&#xff0c;在这场技术革新的浪潮中&#xff0c;关于AI产品版权归属、创意产业如何在AI…

服务器无法远程桌面连接,解决服务器进行无法远程桌面连接方法有哪些

当服务器无法建立远程桌面连接时&#xff0c;通常涉及多个层面的排查和修复。下面将详细列举一些专业的解决方法&#xff0c;以应对服务器远程桌面连接问题。 一、基础排查与验证 1. 确认网络连通性&#xff1a; - 使用ping命令检查客户端与服务器之间的网络连通性。 - …

数据结构之B数

目录 1.概述 2.特点 3.诞生 4.优缺点 4.1.优点 4.2.缺点 5.应用场景 6.C语言中的B树实现例子 7.总结 1.概述 B树&#xff08;B-tree&#xff09;是一种自平衡的树数据结构&#xff0c;广泛应用于数据库和文件系统中&#xff0c;以便高效地进行顺序读取、写入以及查找…

Cytoscape之操作界面介绍

Cytoscape 简介 Cytoscape是一个专注于开源网络可视化和分析的软件。软件的核心部分提供了网络显示、布局、查询等方面的基本功能。软件的核心可以通过插件架构进行扩展&#xff0c;这样就能快速地开发出新的功能。 Cytoscape 源自系统生物学&#xff0c;用于将生物分子交互网…

win10成功安装stable-diffusion-webui

目录 1.python下载安装 2.git下载安装 3.stable-diffusion-webui下载 4.安装s-d-webui的依赖包&#xff08;用国内镜像提速&#xff09; 5.git下载的stable-diffusion-webui&#xff0c;依赖包提示已安装&#xff0c;但运行webui-user.bat后&#xff0c;又开始下载 6.修改…

2024最新AI大模型-LLm八股合集(八)-Transformer模型

更多2024最新AI大模型-LLm八股合集可以拉到文末&#xff01;&#xff01;&#xff01; MHA & MQA & MGA &#xff08;1&#xff09;MHA 从多头注意力的结构图中&#xff0c;貌似这个所谓的多个头就是指多组线性变换层&#xff0c;其实并不是&#xff0c;只有使用了一…

ARM Linux 设备树详细介绍(1)

1. ARM&Device&Tree 起源 Linus Torvalds 在 2011 年 3 月 17 日的 ARM Linux 邮件列表宣称“this whole ARM thing is a f*cking pain in the ass”&#xff0c;引发 ARM Linux 社区的地震&#xff0c;随后 ARM 社区进行了一系列 的重大修正。 在过去的 ARM Linux 中&…

Pointnet++改进即插即用系列:全网首发FastKAN|即插即用,提升特征提取模块性能

简介:1.该教程提供大量的首发改进的方式,降低上手难度,多种结构改进,助力寻找创新点!2.本篇文章对Pointnet++特征提取模块进行改进,加入FastKAN,提升性能。3.专栏持续更新,紧随最新的研究内容。 目录 1.理论介绍 2.修改步骤 2.1 步骤一 2.2 步骤二 2.3 步骤三 1.理…

360vr党建线上主题展立体化呈现企业的文化理念和品牌形象

在现代科技的引领下&#xff0c;艺术与VR虚拟现实技术相融合必将成为趋势&#xff0c;深圳VR公司华锐视点荣幸地推出VR艺术品虚拟展厅&#xff0c;为您带来前所未有的艺术观赏体验。体验者足不出户即可置身于一个充满创意与灵感的虚拟艺术空间。 我们深入了解每一位客户的需求与…

计算机网络 —— 应用层(万维网)

计算机网络 —— 应用层&#xff08;万维网&#xff09; 万维网核心组成部分特点 URLHTTP版本请求消息结构响应消息结构工作流程 Cookie如何工作主要用途安全与隐私类型 Web缓存客户端缓存&#xff08;浏览器缓存&#xff09;服务器端缓存 今天我们来了解万维网&#xff1a; 万…

元宇宙与AI推动品牌营销进入全智能时代

近日&#xff0c;在2024年T-EDGE未来科技大会上&#xff0c;30位业界领袖、产业优秀企业代表&#xff0c;分享以AI为代表的新技术赋能科技产业&#xff0c;抓住中国企业全球化、数字化营销、绿色经济、智能家居多个产业和领域的创新发展趋势&#xff0c;以四大热门议题&#xf…

ffmpeg.dll丢失怎么办,解决找不到ffmpeg.dll的多种方法分享

ffmpeg.dll 是一个动态链接库文件&#xff0c;它是FFmpeg多媒体框架的一部分。FFmpeg是一个开源项目&#xff0c;可以用来记录、转换数字音视频&#xff0c;也可以转换成不同格式的流媒体。由于它是许多媒体处理任务的核心组件&#xff0c;ffmpeg.dll 缺失或损坏可能会导致依赖…

Windows11+CUDA12.0+RTX4090如何配置安装Tensorflow2-GPU环境?

1 引言 电脑配置 Windows 11 cuda 12.0 RTX4090 由于tensorflow2官网已经不支持cuda11以上的版本了&#xff0c;配置cuda和tensorflow可以通过以下步骤配置实现。 2 步骤 &#xff08;1&#xff09;创建conda环境并安装cuda和cudnn&#xff0c;以及安装tensorflow2.10 con…