React 图片瀑布流
思路:
根据浏览器宽度,确定列数,请求的图片列表数据是列数的10倍,按列数取数据渲染

Index.js:
import React from 'react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { SinglePageHeader } from '../../../../../components/light'
import InfiniteScroll from 'react-infinite-scroll-component'
import { Divider, Skeleton } from 'antd'
import useList from './useList'
import LazyLoad from 'react-lazy-load'import './index.css'function Index(props) {const {dataSource,isHasMore,columnCount,handleSearch,handleImgDrawSameStyleClick,} = useList(props)return (<div className="m-ai-img-wrap-box"><div className={`m-ai-img-wrap-chat`}><SinglePageHeader title="AI绘画作品展示"></SinglePageHeader><div className="m-ai-img-list" id="scrollableDiv"><InfiniteScrolldataLength={dataSource.length}next={handleSearch}refreshFunction={() => handleSearch({ page: 1, isRefresh: true })}pullDownToRefreshpullDownToRefreshThreshold={50}pullDownToRefreshContent={<h3 style={{ textAlign: 'center' }}>↓ 下拉刷新</h3>}releaseToRefreshContent={<h3 style={{ textAlign: 'center' }}>↑ 释放刷新</h3>}hasMore={isHasMore}loader={<Skeletonavatarparagraph={{rows: 3,}}activeclassName="m-h5-lesson-play-skeleton"/>}endMessage={dataSource.length === 0 ? null : (<Divider plain>已经到底啦~</Divider>)}scrollableTarget="scrollableDiv"><div className="m-ai-img-list-inner">{Array.from({ length: columnCount }, () => '').map((item, index) => (<div className="m-ai-img-list-column" key={index}>{dataSource.filter((item, dataSourceIndex) =>dataSourceIndex % columnCount === index).map((item) => (<div key={item.imgUid}><LazyLoad className="m-ai-img-lazy-load"><imgsrc={item.imgUrlCdn}className="m-ai-img"alt="图片"onClick={() => handleImgDrawSameStyleClick(item)}></img></LazyLoad></div>))}</div>))}</div>{dataSource.length === 0 ? (<Skeletonavatarparagraph={{rows: 3,}}activeclassName="m-h5-lesson-play-skeleton"/>) : null}</InfiniteScroll></div></div></div>)
}const mapStateToProps = (state) => {return {collapsed: state.getIn(['light', 'collapsed']),isRNGotToken: state.getIn(['light', 'isRNGotToken']),}
}const mapDispatchToProps = (dispatch) => {return {onSetState(key, value) {dispatch({ type: 'SET_LIGHT_STATE', key, value })},onDispatch(action) {dispatch(action)},}
}export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Index))
useList.js:
import { useState, useEffect } from 'react'
import { Form } from 'antd'
import Api from '../../../../../api'
import { message } from 'antd'
import * as clipboard from 'clipboard-polyfill/text'export default function useList(props) {const [total, setTotal] = useState(10)const [current, setCurrent] = useState(1)let tempCount = Math.floor((window.innerWidth - 10) / 180)tempCount = Math.floor((window.innerWidth - (5 + tempCount * 5)) / 180)console.log('tempCount1', tempCount)//把dataSource和pageSize单独放在一起是为了避免切换pageSize时的bugconst [state, setState] = useState({dataSource: [],pageSize: tempCount * 10,})const [isHasMore, setIsHasMore] = useState(true)// eslint-disable-next-lineconst [username, setUsername] = useState(localStorage.getItem('username'))const [form] = Form.useForm()// eslint-disable-next-lineconst [initValues, setInitValues] = useState({})// eslint-disable-next-lineconst [columnCount, setColumnCount] = useState(tempCount)//搜索const handleSearch = ({page = current,pageSize = state.pageSize,isRefresh = false,} = {}) => {if (isRefresh) {setState({dataSource: [],pageSize: tempCount * 10,})}let searchData = { pageNum: page, pageSize }Api.h5.sdImgSearch(searchData).then((res) => {if (res.code === 200) {const { pageNum, pageSize, total } = res.datalet list = res.data.listif (isRefresh) {setState({dataSource: [...list],pageSize: res.data.pageSize,})} else {setState({dataSource: [...state.dataSource, ...list],pageSize: res.data.pageSize,})}setTotal(res.data.total)const currentTemp = res.data.pageNum + 1setCurrent(currentTemp)setIsHasMore(pageNum < Math.ceil(total / pageSize))}})}//添加或编辑const handleFinish = (values) => {console.log('Success:', values)Api.h5.exchangeCodeAppUse(values).then((res) => {if (res.code === 200) {message.success('恭喜您,兑换成功')//props.history.push('/h5/index/me')}})}//校验失败const handleFinishFailed = (errorInfo) => {console.log('Failed:', errorInfo)}//退出const handleQuit = () => {Api.light.userLogout().then((res) => {if (res.code === 200) {props.history.push('/h5/login')window.localStorage.removeItem('username')window.localStorage.removeItem('token')}})}//跳转const handleJumpPage = (path) => {// eslint-disable-next-lineprops.history.push(path)}const handleCopy = (text) => {clipboard.writeText(text).then(() => {message.success('复制成功')})}const handleImgDrawSameStyleClick = (item) => {console.log(item)props.history.push(`/single/home/sdSimple?modelId=${item.id}&name=${item.name}&link=${item.link}&imgUid=${item.imgUid}`)}useEffect(() => {if (window.platform === 'rn') {if (props.isRNGotToken === true) {handleSearch()}} else {handleSearch()}// eslint-disable-next-line}, [props.isRNGotToken])return {username,form,initValues,dataSource: state.dataSource,total,current,pageSize: state.pageSize,isHasMore,columnCount,handleFinish,handleFinishFailed,handleQuit,handleJumpPage,handleCopy,handleSearch,handleImgDrawSameStyleClick,}
}
index.css:
.m-ai-img-wrap-box{display: flex;justify-content: center;background: #ddd;background: #ddd;position: absolute;top: 0;left: 0;right: 0;bottom: 0;overflow: hidden;}
.m-ai-img-wrap-chat{position: relative; display: flex;flex-direction: column;width: 100%;background: #ededed;}
.m-ai-img-main{flex:1;display: flex;flex-direction: column;overflow-y: auto;}
.m-ai-img-list{flex: 1;padding: 0px 0;overflow-y: auto;}
.m-ai-img-list-inner{position: relative;padding: 0 0 0 5px; display: flex; flex-wrap: wrap;justify-content: center;}
.m-ai-img-list-column{display: flex;flex-direction: column;width: 175px;margin: 0 5px 0 0;}
.m-ai-img-lazy-load{position: relative;min-width: 175px; display: flex;flex-direction: column;justify-content: center; min-height: 175px;margin: 0 0 5px 0;border-radius: 5px; background: #dddddd;}
.m-ai-img{width: 175px;border-radius: 5px;}
效果图:


参考链接:
https://chat.xutongbao.top/
相关文章:
React 图片瀑布流
思路: 根据浏览器宽度,确定列数,请求的图片列表数据是列数的10倍,按列数取数据渲染 Index.js: import React from react import { connect } from react-redux import { withRouter } from react-router-dom import { SinglePag…...
C++数据结构X篇_21_插入排序(稳定的排序)
文章目录 1. 插入排序原理2. 算法图解3. 核心代码:4. 插入排序整体代码实现 1. 插入排序原理 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相…...
【Unity】3D跑酷游戏
展示 finish_all * 方块跑酷 1.教程链接 翻墙:https://www.youtube.com/watch?v9ZEu_I-ido4&listPLPV2KyIb3jR53Jce9hP7G5xC4O9AgnOuL&index3 2.基础制作 最终成果 2.1 基本场景 1.创建Cube作为跑道 1)记得把位置Reset; 2&#…...
bp前端验证码绕过及token绕过
前端验证码绕过及token绕过 原文参考:xiu 文章目录 前端验证码绕过及token绕过原文参考:[xiu](http://www.xiusafe.com/2023/10/25/%E9%AA%8C%E8%AF%81%E7%A0%81%E7%BB%95%E8%BF%87/)1 验证码爆破1. 登录Pikachu,先获取登录的api接口2 验证码…...
Jmeter(十四):跨线程组传递jmeter变量及cookie的处理详解
setUp线程组 setUp thread group 一种特殊类型的线程组,用于在执行常规线程组之前执行一些必要的操作。 在 setup线程组下提到的线程行为与普通线程组完全相同。不同的是执行顺序--- 它会在普通线程组执行之前被触发; 应用场景举例: A、测…...
css实现圆形进度条
能用现成组件就用,实现不行再自己写,因为牵扯到上传文件,进度实时出不来,所以只能使用dom元素操作; 1.实现 效果: 上图是100%,如果需要根据百分比显示,我们需要看下代码里面left和…...
适用于 Windows 10 和 Windows 11 设备的笔记本电脑管理软件
便携式计算机管理软件使 IT 管理员能够简化企业中使用的便携式计算机的部署和管理,当今大多数员工使用Windows 笔记本电脑作为他们的主要工作机器,他们确实已成为几乎每个组织不可或缺的一部分。由于与台式机相比,笔记本电脑足够便携…...
YOLOv5论文作图教程(1)— 软件介绍及下载安装(包括软件包+下载安装详细步骤)
前言:Hello大家好,我是小哥谈。在学习YOLOv5算法的过程中,很多同学都有发表论文的需求。作为文章内容的支撑,图表是最直接的整合数据的工具,能够更清晰地反映出研究对象的结果、流程或趋势。在发表论文的时候,审稿人除了关注论文的内容和排版外,也会审核图表是否清晰美观…...
AutoCAD 2024 Mac中文附激活补丁 兼容M1.M2电脑
AutoCAD 2024是一款功能强大的CAD设计绘图工具,旨在帮助用户创建和编辑高质量的设计图纸和模型。该软件支持2D和3D设计,具有丰富的功能和工具,可用于绘图、建模、注释、标注、尺寸设置等多种操作。AutoCAD 2024还引入了智能对象捕捉、实时预览…...
Jmeter基础---while控制器举例说明
一、 While 控制器 首先创建一个While Controller (While 循环控制器) 设置界面如下: Condition (function or variable) :条件说明 条件为 Flase 的时候,才会跳出 While 循环,否则一直执行 While 控制器下的样例 1、不填…...
正点原子嵌入式linux驱动开发——RGB转HDMI
目前大多数的显示器都提供了HDMI接口,HDMI的应用范围也越来越广,但是STM32MP157这颗芯片原生并不支持HDMI显示。可以通过RGB转HDMI芯片将RGB信号转为HDMI信号,这样就可以连接HDMI显示器了。本章就来学习一下如何在正点原子的STM32MP1开发板上…...
前端时间分片渲染
在经典的面试题中:”如果后端返回了十万条数据要你插入到页面中,你会怎么处理?” 除了像 useVirtualList 这样的虚拟列表来处理外,我们还可以通过 时间分片 来处理 通过 setTimeout 直接上一个例子: <!--* Autho…...
亿图导出word和PDF中清晰度保留方法
步骤一 在亿图软件中画一个元件大小搭配合理的图。注意字体大小的安排,尤其是角标的大小要合适,示范如下 选中所有元器件,右键使用组合功能将电路图组合为一个整体 步骤二: 将亿图软件中的图保存为SVG格式。示范如下 在导出到…...
chatGPT结构及商业级相似模型应用调研
GPT前言 说明 ChatGPT这项技术的历史可以追溯到2018年,当时由Facebook实验室的团队开发出该技术,以开发聊天机器人为目的。随后,ChatGPT在2019年由来自谷歌的DeepMind团队在国际会议ICLR上发表了论文,其中提出了ChatGPT的技术框架…...
HarmonyOS鸿蒙原生应用开发设计- 华为分享图标
HarmonyOS设计文档中,为大家提供了独特的华为分享图标,开发者可以根据需要直接引用。 开发者直接使用官方提供的华为分享图标内容,既可以符合HarmonyOS原生应用的开发上架运营规范,又可以防止使用别人的内容产生的侵权意外情况等&…...
Java基础-反射
代理相关 为什么需要代理? 代理可以无侵入式的对方法进行增强,而不需要修改原始方法的代码,这样就可以在不修改原始方法的情况下,对方法进行增强。 代理长什么样子? 代理里面就是对象要被代理的方法 Java通过什么方式…...
计算机毕设 大数据二手房数据爬取与分析可视化 -python 数据分析 可视化
# 1 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通…...
【转载】 Bytedance火山引擎智能拥塞控制算法 VICC
BytedanceTechBlog : 火山引擎实时、低延时拥塞控制算法的优化实践 火山引擎 网站如何利用播放器节省20%点播成本点击下面的链接进入原文:原创 翟强俊、唐辉 字节跳动技术团队 2023-10-18 11:59 发表于北京 一些专利摘要 火山引擎智能拥塞控制算法 VICC(Volcano Intelligent…...
Postman如何测试WebService接口
前言: 由于工作所需,需要使用Postman测试工具,对基于ws规范的WebService接口进行测试.在经过多种尝试后,终于找到了正确的测试方法.下面我便详细记录测试步骤,以便以后再次测试时可以拿来主义. 第一步:确保WebService服务端正常启动(注意服务端各个接口发布的url地址) 第二步…...
微服务-Eureka
文章目录 提供者与消费者Eureka注册中心搭建EurekaServer服务注册服务发现项目结构 提供者与消费者 Eureka注册中心 服务消费者该如何获取服务提供者的地址信息? 服务提供者启动时向eureka注册自己的信息 eureka保存这些信息 消费者根据服务名称向eureka拉取提供者信…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
