思路:
根据浏览器宽度,确定列数,请求的图片列表数据是列数的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">
- <InfiniteScroll
- dataLength={dataSource.length}
- next={handleSearch}
- refreshFunction={() => handleSearch({ page: 1, isRefresh: true })}
- pullDownToRefresh
- pullDownToRefreshThreshold={50}
- pullDownToRefreshContent={
- <h3 style={{ textAlign: 'center' }}>↓ 下拉刷新h3>
- }
- releaseToRefreshContent={
- <h3 style={{ textAlign: 'center' }}>↑ 释放刷新h3>
- }
- hasMore={isHasMore}
- loader={
- <Skeleton
- avatar
- paragraph={{
- rows: 3,
- }}
- active
- className="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">
- <img
- src={item.imgUrlCdn}
- className="m-ai-img"
- alt="图片"
- onClick={() => handleImgDrawSameStyleClick(item)}
- >img>
- LazyLoad>
- div>
- ))}
- div>
- )
- )}
- div>
-
- {dataSource.length === 0 ? (
- <Skeleton
- avatar
- paragraph={{
- rows: 3,
- }}
- active
- className="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时的bug
- const [state, setState] = useState({
- dataSource: [],
- pageSize: tempCount * 10,
- })
- const [isHasMore, setIsHasMore] = useState(true)
- // eslint-disable-next-line
- const [username, setUsername] = useState(localStorage.getItem('username'))
- const [form] = Form.useForm()
- // eslint-disable-next-line
- const [initValues, setInitValues] = useState({})
- // eslint-disable-next-line
- const [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.data
- let list = res.data.list
- if (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 + 1
- setCurrent(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-line
- props.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;}
效果图:
参考链接: