Merge branch 'feat/upgrade-infinityList' into 'develop'
Feat/upgrade infinity list See merge request web-project/zhst-lambo!30
This commit is contained in:
commit
d95fe37e43
@ -2,14 +2,14 @@
|
|||||||
* Created by jiangzhixiong on 2024/04/28
|
* Created by jiangzhixiong on 2024/04/28
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { forwardRef, useContext, useImperativeHandle } from 'react'
|
import React, { forwardRef, MouseEventHandler, ReactNode, useContext, useImperativeHandle } from 'react'
|
||||||
import { ConfigProvider, EMPTY_BASE64 } from '@zhst/meta'
|
import { ConfigProvider, EMPTY_BASE64 } from '@zhst/meta'
|
||||||
import { Flex, Image } from 'antd';
|
import { Flex, Image } from 'antd';
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
export interface Idata {
|
export interface IData {
|
||||||
id?: string | number;
|
id?: string | number;
|
||||||
url?: string;
|
url?: string;
|
||||||
sort?: number;
|
sort?: number;
|
||||||
@ -17,24 +17,25 @@ export interface Idata {
|
|||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchCardProps extends Idata {
|
export interface CommonCardProps extends IData {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
data?: Idata
|
data?: IData
|
||||||
width?: string;
|
width?: string;
|
||||||
height?: string;
|
height?: string;
|
||||||
onCreateTxt?: string;
|
onCreateTxt?: string;
|
||||||
onCreate?: (data: any) => void;
|
onCreate?: () => void;
|
||||||
onAddTxt?: string;
|
onAddTxt?: string;
|
||||||
onAdd?: (data: any) => void;
|
onAdd?: (data: any) => void;
|
||||||
onRemoveTxt?: string;
|
onRemoveTxt?: string;
|
||||||
onRemove?: (data: any) => void;
|
onRemove?: (data: any) => void;
|
||||||
customOptionRender?: React.ReactNode
|
actions?: ReactNode[]
|
||||||
|
onItemClick?: (data: any, e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchCardRefProps {
|
export interface CommonCardRefProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref) => {
|
const CommonCard = forwardRef<CommonCardRefProps, CommonCardProps>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
url,
|
url,
|
||||||
@ -43,26 +44,29 @@ const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref)
|
|||||||
subtitle,
|
subtitle,
|
||||||
sort,
|
sort,
|
||||||
data,
|
data,
|
||||||
onCreate,
|
actions = [],
|
||||||
onCreateTxt = '创建检索',
|
|
||||||
onAddTxt = '添加目标',
|
|
||||||
onRemoveTxt = '移除轨迹',
|
|
||||||
onAdd,
|
|
||||||
onRemove,
|
|
||||||
customOptionRender,
|
|
||||||
width = '184px',
|
width = '184px',
|
||||||
height = '100%'
|
height = '100%',
|
||||||
|
onItemClick
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext)
|
const { getPrefixCls } = useContext(ConfigContext)
|
||||||
const componentName = getPrefixCls('biz-search-card', customizePrefixCls);
|
const componentName = getPrefixCls('biz-search-card', customizePrefixCls);
|
||||||
|
|
||||||
const stopBumble = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, fn?: ((data: Idata) => void), data?: Idata) => {
|
const optionListRender = (_actions: ReactNode[]) => {
|
||||||
e.stopPropagation()
|
return _actions.map((action, i) => (
|
||||||
fn?.(data!)
|
// eslint-disable-next-line react/no-array-index-key
|
||||||
|
<li key={`${componentName}-main-opt-action-${i}`}>
|
||||||
|
{action}
|
||||||
|
{i !== _actions.length - 1 && <em className={`${componentName}-main-opt-action-split`} />}
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleItemClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, _data: IData | undefined) => {
|
||||||
|
onItemClick?.(data, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -72,9 +76,10 @@ const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref)
|
|||||||
width,
|
width,
|
||||||
height
|
height
|
||||||
}}
|
}}
|
||||||
|
onClick={e => handleItemClick(e, data)}
|
||||||
>
|
>
|
||||||
<div className={`${componentName}-main`}>
|
<div className={`${componentName}-main`}>
|
||||||
<i className={`${componentName}-main-num`}>{id || sort}</i>
|
<i className={`${componentName}-main-num`}>{sort || id}</i>
|
||||||
<Image
|
<Image
|
||||||
className={`${componentName}-main-img`}
|
className={`${componentName}-main-img`}
|
||||||
src={url || data?.url}
|
src={url || data?.url}
|
||||||
@ -82,17 +87,9 @@ const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref)
|
|||||||
preview={false}
|
preview={false}
|
||||||
fallback={EMPTY_BASE64}
|
fallback={EMPTY_BASE64}
|
||||||
/>
|
/>
|
||||||
<Flex align='center' justify='space-between' className={`${componentName}-main-opt`}>
|
<ul className={`${componentName}-main-opt`}>
|
||||||
{customOptionRender || (
|
{optionListRender(actions)}
|
||||||
<>
|
</ul>
|
||||||
<a onClick={(e) => stopBumble(e, onCreate, data)}>{onCreateTxt}</a>
|
|
||||||
|
|
|
||||||
<a onClick={(e) => stopBumble(e, onAdd, data)}>{onAddTxt}</a>
|
|
||||||
|
|
|
||||||
<a onClick={(e) => stopBumble(e, onRemove, data)}>{onRemoveTxt}</a>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={`${componentName}-footer`}>
|
<div className={`${componentName}-footer`}>
|
||||||
<p className={`${componentName}-footer-tit`}>{title || data?.title}</p>
|
<p className={`${componentName}-footer-tit`}>{title || data?.title}</p>
|
||||||
@ -102,4 +99,4 @@ const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default SearchCard
|
export default CommonCard
|
@ -1,18 +1,23 @@
|
|||||||
.zhst-biz-search-card {
|
.zhst-biz-search-card {
|
||||||
|
display: inline-block;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
transition: .1s ease-in all;
|
transition: .1s ease-in all;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
transition: .5s ease all;
|
||||||
border: 2px solid #09f;
|
border: 2px solid #09f;
|
||||||
|
|
||||||
.zhst-biz-search-card-main-opt {
|
.zhst-biz-search-card-main-opt {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-main {
|
&-main {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&-num {
|
&-num {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -32,11 +37,17 @@
|
|||||||
|
|
||||||
&-img {
|
&-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 240px;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transition: .5s ease-in all;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-opt {
|
&-opt {
|
||||||
display: none;
|
display: none;
|
||||||
|
margin: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 6px 3px;
|
padding: 6px 3px;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -48,11 +59,28 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
transition: .2s ease-in all;
|
transition: .2s ease-in all;
|
||||||
|
|
||||||
|
li {
|
||||||
|
position: relative;
|
||||||
|
list-style: none;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-action-split {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
width: 1px;
|
||||||
|
height: 80%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.9;
|
opacity: 0.88;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import CommonCard from './CommonCard'
|
||||||
|
|
||||||
|
export type { CommonCardProps, CommonCardRefProps } from './CommonCard'
|
||||||
|
|
||||||
|
export default CommonCard
|
42
packages/biz/src/CustomCard/demo/commonCard.tsx
Normal file
42
packages/biz/src/CustomCard/demo/commonCard.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { CommonCard } from '@zhst/biz'
|
||||||
|
import { uniqueId } from '@zhst/func'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [data, setData] = useState([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
let res = body.results.map((o, index) => {
|
||||||
|
return {
|
||||||
|
id: uniqueId(),
|
||||||
|
sort: index + 1,
|
||||||
|
title: o.name.first,
|
||||||
|
subtitle: o.name.last,
|
||||||
|
url: o.picture.large
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setData(res);
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{data?.map(item => (
|
||||||
|
<CommonCard
|
||||||
|
key={item.id}
|
||||||
|
sort={item.sort}
|
||||||
|
data={item}
|
||||||
|
width="184px"
|
||||||
|
actions={[
|
||||||
|
<a>创建检索</a>,
|
||||||
|
<a>创建布控</a>,
|
||||||
|
<a>删除点位</a>
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
31
packages/biz/src/CustomCard/index.md
Normal file
31
packages/biz/src/CustomCard/index.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
category: Components
|
||||||
|
title: CustomCard 定制化卡片
|
||||||
|
toc: content
|
||||||
|
group:
|
||||||
|
title: 数据展示
|
||||||
|
---
|
||||||
|
|
||||||
|
定制化卡片
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
<code src="./demo/commonCard.tsx">基本卡片</code>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### CommonCardProps
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| data | 数据源 | IData[] | [] | - |
|
||||||
|
| prefixCls | 数据源 | string | [] | - |
|
||||||
|
| width | 宽度 | string | [] | - |
|
||||||
|
| height | 高度 | string | [] | - |
|
||||||
|
| onCreateTxt | 创建方法文字 | string | [] | - |
|
||||||
|
| onCreate | 创建方法 | () => void | [] | - |
|
||||||
|
| onAddTxt | 数据源 | string | [] | - |
|
||||||
|
| onAdd | 数据源 | () => void | [] | - |
|
||||||
|
| onRemoveTxt | 数据源 | string | [] | - |
|
||||||
|
| onRemove | 数据源 | () => void | [] | - |
|
||||||
|
| customOptionRender | 数据源 | React.ReactNode | - | - |
|
6
packages/biz/src/CustomCard/index.tsx
Normal file
6
packages/biz/src/CustomCard/index.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Created by jiangzhixiong on 2024/04/28
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { default as CommonCard } from './components/commonCard'
|
||||||
|
export type { CommonCardProps, CommonCardRefProps } from './components/commonCard'
|
@ -9,6 +9,11 @@ export type { TreeTransferProps } from './treeTransfer'
|
|||||||
export { default as TreeTransferModal } from './treeTransferModal'
|
export { default as TreeTransferModal } from './treeTransferModal'
|
||||||
export type { TreeTransferModalProps } from './treeTransferModal'
|
export type { TreeTransferModalProps } from './treeTransferModal'
|
||||||
export { default as WarningRecordCard } from './WarningRecordCard'
|
export { default as WarningRecordCard } from './WarningRecordCard'
|
||||||
|
export { CommonCard } from './CustomCard'
|
||||||
|
export type {
|
||||||
|
CommonCardProps,
|
||||||
|
CommonCardRefProps
|
||||||
|
} from './CustomCard'
|
||||||
export type { IRecord, WarningRecordCardProps } from './WarningRecordCard'
|
export type { IRecord, WarningRecordCardProps } from './WarningRecordCard'
|
||||||
export { default as OdModal } from './odModal'
|
export { default as OdModal } from './odModal'
|
||||||
export type { ODModalProps } from './odModal'
|
export type { ODModalProps } from './odModal'
|
||||||
|
@ -2,24 +2,30 @@
|
|||||||
* Created by jiangzhixiong
|
* Created by jiangzhixiong
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { forwardRef, ReactNode, useContext, useImperativeHandle, useRef } from 'react'
|
import React, { forwardRef, ReactNode, useContext, useEffect, useImperativeHandle, useRef } from 'react'
|
||||||
import { ConfigProvider } from '@zhst/meta';
|
import { ConfigProvider } from '@zhst/meta';
|
||||||
import { Divider, Flex } from 'antd';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import InfiniteScroll from 'react-infinite-scroll-component';
|
import InfiniteScroll from 'react-infinite-scroll-component';
|
||||||
import { SearchCard, SearchCardProps } from './components';
|
import { Spin, SpinProps } from 'antd';
|
||||||
|
import { useSize } from '@zhst/hooks';
|
||||||
import './index.less'
|
import './index.less'
|
||||||
import { Idata } from './components/SearchCard';
|
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
export interface InfiniteListProps {
|
export interface IData {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
index?: number;
|
||||||
|
[k: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InfiniteListProps extends React.HtmlHTMLAttributes<HTMLDivElement> {
|
||||||
type?: 'custom' | 'auto'
|
type?: 'custom' | 'auto'
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
height?: number;
|
height?: number;
|
||||||
itemRender?: (data?: any) => React.ReactNode
|
itemRender?: (data?: IData, index?: number) => React.ReactNode
|
||||||
loading?: boolean; //
|
loading?: boolean; //
|
||||||
data: Idata[];
|
data: IData[];
|
||||||
targetId?: string; // 滚动列表 ID
|
targetId?: string; // 滚动列表 ID
|
||||||
loadMore?: (data?: any) => any;
|
loadMore?: (data?: any) => any;
|
||||||
params?: {
|
params?: {
|
||||||
@ -28,101 +34,79 @@ export interface InfiniteListProps {
|
|||||||
hasMore: boolean;
|
hasMore: boolean;
|
||||||
endMessage?: ReactNode
|
endMessage?: ReactNode
|
||||||
loadingMessage?: ReactNode
|
loadingMessage?: ReactNode
|
||||||
onItemClick?: (data: any) => void;
|
loadingProps?: SpinProps
|
||||||
searchCardProps?: SearchCardProps
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InfiniteListRefProps {
|
export interface InfiniteListRefProps {
|
||||||
|
scrollViewSize?: { width: number; height: number }
|
||||||
|
listSize?: { width: number; height: number }
|
||||||
}
|
}
|
||||||
|
|
||||||
const InfiniteList = forwardRef<InfiniteListRefProps, InfiniteListProps>((props, ref) => {
|
const InfiniteList = forwardRef<InfiniteListRefProps, InfiniteListProps>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
height,
|
height = 600,
|
||||||
|
loading,
|
||||||
type = 'auto',
|
type = 'auto',
|
||||||
loadingMessage = <p style={{ textAlign: 'center' }}>加载中...</p>,
|
loadingMessage = <p style={{ textAlign: 'center' }}>加载中...</p>,
|
||||||
targetId = 'scrollableDiv',
|
targetId = 'scrollableDiv',
|
||||||
itemRender,
|
itemRender = (data) => <div>{data?.title}</div>,
|
||||||
hasMore,
|
hasMore,
|
||||||
onItemClick,
|
|
||||||
loadMore,
|
loadMore,
|
||||||
data = [],
|
data = [],
|
||||||
endMessage = <Divider plain>没有更多数据了...🤐</Divider>,
|
endMessage = <div style={{ textAlign: 'center' }} >没有更多数据了...🤐</div>,
|
||||||
searchCardProps
|
style,
|
||||||
|
loadingProps,
|
||||||
|
className
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext);
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
const componentName = getPrefixCls('biz-infinite-list', customizePrefixCls);
|
const componentName = getPrefixCls('biz-infinite-list', customizePrefixCls);
|
||||||
const listRef = useRef<HTMLDivElement>(null);
|
const listRef = useRef<HTMLDivElement>(null);
|
||||||
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
const scrollViewSize = useSize(listRef.current) || { width: 0, height: 0 }; // 无限滚动视窗大小
|
||||||
|
// @ts-ignore
|
||||||
|
const listSize = useSize(scrollRef.current?._infScroll) || { width: 0, height: 0 } // 无限滚动列表大小
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 当数据不够一屏时继续加载
|
||||||
|
if (listSize.height < scrollViewSize.height) {
|
||||||
|
loadMore?.()
|
||||||
|
}
|
||||||
|
}, [listSize.height])
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
scrollViewSize,
|
||||||
|
listSize
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Spin spinning={loading} {...loadingProps}>
|
||||||
id={targetId}
|
<div
|
||||||
className={classNames(componentName)}
|
id={targetId}
|
||||||
ref={listRef}
|
className={classNames(componentName, className)}
|
||||||
style={{
|
ref={listRef}
|
||||||
height,
|
style={{
|
||||||
overflow: 'auto',
|
height,
|
||||||
padding: 12
|
overflow: 'auto',
|
||||||
}}
|
...style
|
||||||
>
|
}}
|
||||||
{/* {loading ? (
|
|
||||||
<p>加载中...</p>
|
|
||||||
) : (
|
|
||||||
<Flex wrap='wrap' gap="small" className={classNames(componentName + 'items')}>
|
|
||||||
{data?.list?.map((item) => (
|
|
||||||
itemRender?.(item) || (
|
|
||||||
<div className={classNames(componentName + 'items-item')}>
|
|
||||||
<SearchCard data={item} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
))}
|
|
||||||
</Flex>
|
|
||||||
)} */}
|
|
||||||
<InfiniteScroll
|
|
||||||
dataLength={data.length}
|
|
||||||
next={type === 'auto' ? loadMore! : () => {}}
|
|
||||||
hasMore={hasMore}
|
|
||||||
loader={loadingMessage}
|
|
||||||
endMessage={endMessage}
|
|
||||||
scrollableTarget={targetId}
|
|
||||||
>
|
>
|
||||||
<Flex wrap='wrap' gap="small" className={classNames(componentName + 'items')}>
|
<InfiniteScroll
|
||||||
|
// @ts-ignore
|
||||||
|
ref={scrollRef}
|
||||||
|
dataLength={data.length}
|
||||||
|
next={type === 'auto' ? loadMore! : () => {}}
|
||||||
|
hasMore={hasMore}
|
||||||
|
loader={loadingMessage}
|
||||||
|
endMessage={endMessage}
|
||||||
|
scrollableTarget={targetId}
|
||||||
|
>
|
||||||
{data?.map((item, idx) => (
|
{data?.map((item, idx) => (
|
||||||
itemRender?.(item) || (
|
itemRender?.({ ...item, index: idx})
|
||||||
<div
|
|
||||||
key={idx}
|
|
||||||
className={classNames(componentName + 'items-item')}
|
|
||||||
onClick={() => {
|
|
||||||
onItemClick?.(item)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SearchCard
|
|
||||||
id={idx + 1}
|
|
||||||
data={item}
|
|
||||||
width="184px"
|
|
||||||
{...searchCardProps}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</InfiniteScroll>
|
||||||
</InfiniteScroll>
|
</div>
|
||||||
{/* <div style={{ marginTop: 8 }}>
|
</Spin>
|
||||||
{!noMore && (
|
|
||||||
<Button onClick={loadMore} disabled={loadingMore}>
|
|
||||||
{loadingMore ? '加载中...' : '点击加载更多'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{noMore && <span>没有更多数据了</span>}
|
|
||||||
</div> */}
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
/**
|
|
||||||
* Created by jiangzhixiong on 2024/04/28
|
|
||||||
*/
|
|
||||||
|
|
||||||
export { default as SearchCard } from './SearchCard'
|
|
||||||
export type { SearchCardProps, SearchCardRefProps } from './SearchCard'
|
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { InfiniteList } from '@zhst/biz'
|
import { InfiniteList, CommonCard } from '@zhst/biz'
|
||||||
|
import { uniqueId } from '@zhst/func'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [data, setData] = useState([])
|
const [data, setData] = useState([])
|
||||||
@ -13,8 +14,10 @@ export default () => {
|
|||||||
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((body) => {
|
.then((body) => {
|
||||||
let res = body.results.map(o => {
|
let res = body.results.map((o, index) => {
|
||||||
return {
|
return {
|
||||||
|
id: uniqueId(),
|
||||||
|
sort: index + 1,
|
||||||
title: o.name.first,
|
title: o.name.first,
|
||||||
subtitle: o.name.last,
|
subtitle: o.name.last,
|
||||||
url: o.picture.large
|
url: o.picture.large
|
||||||
@ -36,14 +39,23 @@ export default () => {
|
|||||||
<InfiniteList
|
<InfiniteList
|
||||||
loading={loading}
|
loading={loading}
|
||||||
loadMore={loadMoreData}
|
loadMore={loadMoreData}
|
||||||
height={300}
|
height={1200}
|
||||||
hasMore={data.length < 100}
|
hasMore={data.length < 60}
|
||||||
data={data}
|
data={data}
|
||||||
onItemClick={_data => console.log('item点击:', _data)}
|
itemRender={(item) => {
|
||||||
searchCardProps={{
|
return (
|
||||||
onAdd: (_data) => console.log('新增', _data),
|
<CommonCard
|
||||||
onCreate: (_data) => console.log('创建', _data),
|
key={item.id}
|
||||||
onRemove: (_data) => console.log('删除', _data),
|
sort={item.sort}
|
||||||
|
data={item}
|
||||||
|
width="184px"
|
||||||
|
actions={[
|
||||||
|
<a>创建检索</a>,
|
||||||
|
<a>创建布控</a>,
|
||||||
|
<a>删除点位</a>
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -3,11 +3,11 @@ import { InfiniteList } from '@zhst/biz'
|
|||||||
import { Button, Input, Space } from 'antd'
|
import { Button, Input, Space } from 'antd'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [data, setData] = useState([])
|
const [data, setData] = useState<any>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [params, setParams] = useState({})
|
const [params, setParams] = useState({})
|
||||||
|
|
||||||
const loadMoreData = (params?: { name: string; age?: number; sex: string; tel: number }) => {
|
const loadMoreData = (params?: any) => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -15,7 +15,7 @@ export default () => {
|
|||||||
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((body) => {
|
.then((body) => {
|
||||||
let res = body.results.map(o => {
|
let res = body.results.map((o: { name: { first: any; last: any }; picture: { large: any } }) => {
|
||||||
return {
|
return {
|
||||||
title: o.name.first,
|
title: o.name.first,
|
||||||
subtitle: o.name.last,
|
subtitle: o.name.last,
|
||||||
@ -35,7 +35,7 @@ export default () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space direction='vertical'>
|
<Space direction='vertical' size={10} style={{ padding: '12px', border: '1px solid #ccc' }}>
|
||||||
<Space>
|
<Space>
|
||||||
<Input placeholder='名称' onChange={(e) => setParams(pre => ({ ...pre, name: e.target.value }))} style={{ width: '120px' }} />
|
<Input placeholder='名称' onChange={(e) => setParams(pre => ({ ...pre, name: e.target.value }))} style={{ width: '120px' }} />
|
||||||
<Input placeholder='年龄' onChange={(e) => setParams(pre => ({ ...pre, age: e.target.value }))} style={{ width: '120px' }} />
|
<Input placeholder='年龄' onChange={(e) => setParams(pre => ({ ...pre, age: e.target.value }))} style={{ width: '120px' }} />
|
||||||
@ -49,9 +49,7 @@ export default () => {
|
|||||||
height={300}
|
height={300}
|
||||||
hasMore={data.length < 100}
|
hasMore={data.length < 100}
|
||||||
data={data}
|
data={data}
|
||||||
type="custom"
|
|
||||||
loadingMessage={<Button onClick={() => loadMoreData(params)}>加载更多</Button>}
|
loadingMessage={<Button onClick={() => loadMoreData(params)}>加载更多</Button>}
|
||||||
onItemClick={data => console.log('item点击:', data)}
|
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
)
|
)
|
||||||
|
@ -18,21 +18,20 @@ group:
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| data | 数据源 | Idata[] | [] | - |
|
| data | 数据源 | IData[] | [] | - |
|
||||||
|
| height | 无限滚动列表可视区高度 | number | 600 | - |
|
||||||
| loading | 数据源 | Array[] | [] | - |
|
| loading | 数据源 | Array[] | [] | - |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| dataLength | 数据数量 | number | [] | - |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| next | 下一页方法 | function | () => {} | - |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| hasMore | 是否还有更多 | boolean | false | - |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| loadingProps | 参考 antd-spin | spinProps | [] | - |
|
||||||
| data | 数据源 | Array[] | [] | - |
|
| itemRender | 自定义渲染项 | (IData) => ReactNode | - | - |
|
||||||
|
|
||||||
## Idata
|
## 设计思路
|
||||||
|
|
||||||
```js
|
无限滚动,同时支持:
|
||||||
interface Idata {
|
|
||||||
id?: string | number;
|
1. 自动、主动加载更多
|
||||||
url?: string; // 链接
|
2. 一屏没加载完,继续加载,直到填满屏幕:
|
||||||
title?: string; // 标题
|
- 需要第二次加载的内容是否为空,为空则停止加载
|
||||||
subtitle?: string; // 副标题
|
- 通过整体的page-height 和 浏览器可视区域
|
||||||
}
|
|
||||||
```
|
|
||||||
|
0
packages/biz/src/infiniteList/type.ts
Normal file
0
packages/biz/src/infiniteList/type.ts
Normal file
Loading…
Reference in New Issue
Block a user