feat(zhst/biz): 新增无限滚动列表组件
This commit is contained in:
parent
57af643093
commit
aea6e2ec4c
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -2,9 +2,9 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"name": "http://localhost:8000/metas/big-image-preview",
|
"name": "lambo",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"url": "http://localhost:8000/metas/big-image-preview"
|
"url": "http://localhost:8000/metas"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,18 @@
|
|||||||
# @zhst/biz
|
# @zhst/biz
|
||||||
|
|
||||||
|
## 0.17.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 视频添加 OD 框,查看大图首次点击修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.15.0
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
- @zhst/hooks@0.9.2
|
||||||
|
|
||||||
## 0.16.1
|
## 0.16.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/biz",
|
"name": "@zhst/biz",
|
||||||
"version": "0.16.1",
|
"version": "0.17.0",
|
||||||
"description": "业务库",
|
"description": "业务库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
@ -47,6 +47,7 @@
|
|||||||
"antd": "^5.12.5",
|
"antd": "^5.12.5",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"rc-util": "^5.38.1"
|
"rc-util": "^5.38.1",
|
||||||
|
"react-infinite-scroll-component": "^6.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,4 +17,5 @@ export { default as ViewLargerImageModal, useViewLargerImageModal } from './View
|
|||||||
export type { VideoPlayerCardProps } from './VideoPlayerCard'
|
export type { VideoPlayerCardProps } from './VideoPlayerCard'
|
||||||
export { default as VideoPlayerCard } from './VideoPlayerCard'
|
export { default as VideoPlayerCard } from './VideoPlayerCard'
|
||||||
export { default as RealTimeMonitor } from './RealTimeMonitor'
|
export { default as RealTimeMonitor } from './RealTimeMonitor'
|
||||||
|
export { default as InfiniteList } from './infiniteList'
|
||||||
|
// export type { InfiniteListProps, InfiniteListRefProps } from './infiniteList'
|
||||||
|
126
packages/biz/src/infiniteList/InfiniteList.tsx
Normal file
126
packages/biz/src/infiniteList/InfiniteList.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* Created by jiangzhixiong
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { forwardRef, ReactNode, useContext, useImperativeHandle, useRef } from 'react'
|
||||||
|
import { ConfigProvider } from '@zhst/meta';
|
||||||
|
import { Divider, Flex } from 'antd';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import InfiniteScroll from 'react-infinite-scroll-component';
|
||||||
|
import { SearchCard, SearchCardProps } from './components';
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
|
export interface InfiniteListProps {
|
||||||
|
type?: 'custom' | 'auto'
|
||||||
|
prefixCls?: string;
|
||||||
|
height?: number;
|
||||||
|
itemRender?: (data?: any) => React.ReactNode
|
||||||
|
loading?: boolean; //
|
||||||
|
data: any[];
|
||||||
|
targetId?: string; // 滚动列表 ID
|
||||||
|
loadMore?: (data?: any) => any;
|
||||||
|
params?: {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
hasMore: boolean;
|
||||||
|
endMessage?: ReactNode
|
||||||
|
loadingMessage?: ReactNode
|
||||||
|
onItemClick?: (data: any) => void;
|
||||||
|
searchCardProps?: SearchCardProps
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InfiniteListRefProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const InfiniteList = forwardRef<InfiniteListRefProps, InfiniteListProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
height,
|
||||||
|
type = 'auto',
|
||||||
|
loadingMessage = <p style={{ textAlign: 'center' }}>加载中...</p>,
|
||||||
|
targetId = 'scrollableDiv',
|
||||||
|
itemRender,
|
||||||
|
hasMore,
|
||||||
|
onItemClick,
|
||||||
|
loadMore,
|
||||||
|
data = [],
|
||||||
|
endMessage = <Divider plain>没有更多数据了...🤐</Divider>,
|
||||||
|
searchCardProps
|
||||||
|
} = props
|
||||||
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
|
const componentName = getPrefixCls('biz-infinite-list', customizePrefixCls);
|
||||||
|
const listRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id={targetId}
|
||||||
|
className={classNames(componentName)}
|
||||||
|
ref={listRef}
|
||||||
|
style={{
|
||||||
|
height,
|
||||||
|
overflow: 'auto',
|
||||||
|
padding: 12
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* {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')}>
|
||||||
|
{data?.map((item) => (
|
||||||
|
itemRender?.(item) || (
|
||||||
|
<div
|
||||||
|
key={item.key || item.id}
|
||||||
|
className={classNames(componentName + 'items-item')}
|
||||||
|
onClick={(e) => {
|
||||||
|
onItemClick?.(item)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SearchCard
|
||||||
|
data={item}
|
||||||
|
{...searchCardProps}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</InfiniteScroll>
|
||||||
|
{/* <div style={{ marginTop: 8 }}>
|
||||||
|
{!noMore && (
|
||||||
|
<Button onClick={loadMore} disabled={loadingMore}>
|
||||||
|
{loadingMore ? '加载中...' : '点击加载更多'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{noMore && <span>没有更多数据了</span>}
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default InfiniteList
|
94
packages/biz/src/infiniteList/components/SearchCard.tsx
Normal file
94
packages/biz/src/infiniteList/components/SearchCard.tsx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* Created by jiangzhixiong on 2024/04/28
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { forwardRef, useContext, useImperativeHandle } from 'react'
|
||||||
|
import { ConfigProvider, EMPTY_BASE64 } from '@zhst/meta'
|
||||||
|
import { Flex, Image } from 'antd';
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
|
export interface SearchCardProps {
|
||||||
|
prefixCls?: string;
|
||||||
|
id?: string;
|
||||||
|
key?: string;
|
||||||
|
url?: string;
|
||||||
|
data?: {
|
||||||
|
key?: string;
|
||||||
|
url?: string;
|
||||||
|
sort?: number;
|
||||||
|
title?: string;
|
||||||
|
subtitle?: string;
|
||||||
|
}
|
||||||
|
onCreateTxt?: string;
|
||||||
|
onCreate?: (data: any) => void;
|
||||||
|
onAddTxt?: string;
|
||||||
|
onAdd?: (data: any) => void;
|
||||||
|
onRemoveTxt?: string;
|
||||||
|
onRemove?: (data: any) => void;
|
||||||
|
customOptionRender?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchCardRefProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
const SearchCard = forwardRef<SearchCardRefProps, SearchCardProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
url,
|
||||||
|
id,
|
||||||
|
key,
|
||||||
|
data,
|
||||||
|
onCreate,
|
||||||
|
onCreateTxt = '创建检索',
|
||||||
|
onAddTxt = '添加目标',
|
||||||
|
onRemoveTxt = '移除轨迹',
|
||||||
|
onAdd,
|
||||||
|
onRemove,
|
||||||
|
customOptionRender
|
||||||
|
} = props
|
||||||
|
const { getPrefixCls } = useContext(ConfigContext)
|
||||||
|
const componentName = getPrefixCls('biz-search-card', customizePrefixCls);
|
||||||
|
|
||||||
|
const stopBumble = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, fn: ((data: any) => void) | undefined, data: { url?: string | undefined; key?: string | undefined; title?: string | undefined; subtitle?: string | undefined; } | undefined) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
fn?.(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={componentName} key={id || key}>
|
||||||
|
<div className={`${componentName}-main`}>
|
||||||
|
<i className={`${componentName}-main-num`}>-</i>
|
||||||
|
<Image
|
||||||
|
src={url}
|
||||||
|
preview={false}
|
||||||
|
width={'100%'}
|
||||||
|
height={'240px'}
|
||||||
|
fallback={EMPTY_BASE64}
|
||||||
|
/>
|
||||||
|
<Flex align='center' justify='space-between' className={`${componentName}-main-opt`}>
|
||||||
|
{customOptionRender || (
|
||||||
|
<>
|
||||||
|
<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 className={`${componentName}-footer`}>
|
||||||
|
<p className={`${componentName}-footer-tit`}>04/28 08:21:58</p>
|
||||||
|
<p className={`${componentName}-footer-subtitle`}>西2-1</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default SearchCard
|
75
packages/biz/src/infiniteList/components/index.less
Normal file
75
packages/biz/src/infiniteList/components/index.less
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
.zhst-biz-search-card {
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: .1s ease-in all;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 2px solid #09f;
|
||||||
|
|
||||||
|
.zhst-biz-search-card-main-opt {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-main {
|
||||||
|
position: relative;
|
||||||
|
width: 184px;
|
||||||
|
height: 240px;
|
||||||
|
|
||||||
|
&-num {
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 2px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: rgb(153, 153, 153);
|
||||||
|
background-color: rgba(255, 255, 255, 75%);
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-opt {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
padding: 6px 3px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: #09f;
|
||||||
|
color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: .2s ease-in all;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-footer {
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&-tit {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-subtitle {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 20px;
|
||||||
|
transition: .1s ease-in all;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #09f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
packages/biz/src/infiniteList/components/index.tsx
Normal file
6
packages/biz/src/infiniteList/components/index.tsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Created by jiangzhixiong on 2024/04/28
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { default as SearchCard } from './SearchCard'
|
||||||
|
export type { SearchCardProps, SearchCardRefProps } from './SearchCard'
|
43
packages/biz/src/infiniteList/demo/basic.tsx
Normal file
43
packages/biz/src/infiniteList/demo/basic.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { InfiniteList } from '@zhst/biz'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [data, setData] = useState([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const loadMoreData = () => {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
setData([...data, ...body.results]);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadMoreData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<InfiniteList
|
||||||
|
loading={loading}
|
||||||
|
loadMore={loadMoreData}
|
||||||
|
height={300}
|
||||||
|
hasMore={data.length < 100}
|
||||||
|
data={data}
|
||||||
|
onItemClick={_data => console.log('item点击:', _data)}
|
||||||
|
searchCardProps={{
|
||||||
|
onAdd: (_data) => console.log('新增', _data),
|
||||||
|
onCreate: (_data) => console.log('创建', _data),
|
||||||
|
onRemove: (_data) => console.log('删除', _data),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
51
packages/biz/src/infiniteList/demo/custom.tsx
Normal file
51
packages/biz/src/infiniteList/demo/custom.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { InfiniteList } from '@zhst/biz'
|
||||||
|
import { Button, Input, Space } from 'antd'
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [data, setData] = useState([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [params, setParams] = useState({})
|
||||||
|
|
||||||
|
const loadMoreData = (params?: { name: string; age?: number; sex: string; tel: number }) => {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo')
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
setData([...data, ...body.results]);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadMoreData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction='vertical'>
|
||||||
|
<Space>
|
||||||
|
<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, sex: e.target.value }))} style={{ width: '120px' }} />
|
||||||
|
<Input placeholder='手机号' onChange={(e) => setParams(pre => ({ ...pre, tel: e.target.value }))} style={{ width: '120px' }} />
|
||||||
|
<Button onClick={() => loadMoreData(params)}>加载更多</Button>
|
||||||
|
</Space>
|
||||||
|
<InfiniteList
|
||||||
|
loading={loading}
|
||||||
|
loadMore={() => loadMoreData(params)}
|
||||||
|
height={300}
|
||||||
|
hasMore={data.length < 100}
|
||||||
|
data={data}
|
||||||
|
type="custom"
|
||||||
|
loadingMessage={<Button onClick={() => loadMoreData(params)}>加载更多</Button>}
|
||||||
|
onItemClick={data => console.log('item点击:', data)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
66
packages/biz/src/infiniteList/demo/customItem.tsx
Normal file
66
packages/biz/src/infiniteList/demo/customItem.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { InfiniteList } from '@zhst/biz'
|
||||||
|
import { Button, Input, Space } from 'antd'
|
||||||
|
|
||||||
|
interface IData { name: string; age?: number; sex: string; tel: number }
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [data, setData] = useState<any>([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [params, setParams] = useState<IData>({
|
||||||
|
name: '',
|
||||||
|
tel: 123,
|
||||||
|
age: 12,
|
||||||
|
sex: '男'
|
||||||
|
})
|
||||||
|
|
||||||
|
const loadMoreData = (params?: IData) => {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
fetch('https://randomuser.me/api/?results=10&inc=id,key,name,gender,email,nat,picture&noinfo', {
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((body) => {
|
||||||
|
setData([...data, ...body.results]);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadMoreData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction='vertical'>
|
||||||
|
<Space>
|
||||||
|
<Input placeholder='名称' onChange={(e) => setParams(pre => ({ ...pre, name: e.target.value }))} style={{ width: '120px' }} />
|
||||||
|
<Input placeholder='年龄' onChange={(e) => setParams(pre => ({ ...pre, age: Number(e.target.value) }))} style={{ width: '120px' }} />
|
||||||
|
<Input placeholder='性别' onChange={(e) => setParams(pre => ({ ...pre, sex: e.target.value }))} style={{ width: '120px' }} />
|
||||||
|
<Input placeholder='手机号' onChange={(e) => setParams(pre => ({ ...pre, tel: Number(e.target.value) }))} style={{ width: '120px' }} />
|
||||||
|
<Button onClick={() => loadMoreData(params)}>加载更多</Button>
|
||||||
|
</Space>
|
||||||
|
<InfiniteList
|
||||||
|
loading={loading}
|
||||||
|
loadMore={() => loadMoreData(params)}
|
||||||
|
height={300}
|
||||||
|
hasMore={data.length < 100}
|
||||||
|
data={data}
|
||||||
|
type="custom"
|
||||||
|
loadingMessage={<Button onClick={() => loadMoreData(params)}>加载更多</Button>}
|
||||||
|
itemRender={() => {
|
||||||
|
return (
|
||||||
|
<div style={{ width: '200px', height: '200px', border: '1px solid #000' }}>
|
||||||
|
自定义的子元素
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onItemClick={data => console.log('item点击:', data)}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
17
packages/biz/src/infiniteList/demo/mock.ts
Normal file
17
packages/biz/src/infiniteList/demo/mock.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const resultData = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13'];
|
||||||
|
|
||||||
|
export function getLoadMoreList(nextId: string | undefined, limit: number): Promise<any> {
|
||||||
|
let start = 0;
|
||||||
|
const end = start + limit;
|
||||||
|
const list = resultData.slice(start, end);
|
||||||
|
const nId = resultData.length >= end ? resultData[end] : undefined;
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({
|
||||||
|
list,
|
||||||
|
nextId: nId,
|
||||||
|
isNoMore: list.length > 20
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
}
|
5
packages/biz/src/infiniteList/index.less
Normal file
5
packages/biz/src/infiniteList/index.less
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.zhst-biz-infinite-list {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
21
packages/biz/src/infiniteList/index.md
Normal file
21
packages/biz/src/infiniteList/index.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
category: Components
|
||||||
|
title: infiniteList 无限滚动列表
|
||||||
|
toc: content
|
||||||
|
group:
|
||||||
|
title: 数据展示
|
||||||
|
---
|
||||||
|
|
||||||
|
无限滚动列表
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
<code src="./demo/basic.tsx">基本用法</code>
|
||||||
|
<code src="./demo/custom.tsx">手动触发</code>
|
||||||
|
<code src="./demo/customItem.tsx">自定义子元素</code>
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| data | 数据源 | Array[] | [] | - |
|
5
packages/biz/src/infiniteList/index.tsx
Normal file
5
packages/biz/src/infiniteList/index.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import InfinityList from './InfiniteList'
|
||||||
|
|
||||||
|
// export { InfiniteListProps, InfiniteListRefProps } from './InfiniteList'
|
||||||
|
|
||||||
|
export default InfinityList
|
@ -1,5 +1,19 @@
|
|||||||
# @zhst/material
|
# @zhst/material
|
||||||
|
|
||||||
|
## 0.11.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 视频添加 OD 框,查看大图首次点击修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.15.0
|
||||||
|
- @zhst/biz@0.17.0
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
- @zhst/hooks@0.9.2
|
||||||
|
|
||||||
## 0.10.4
|
## 0.10.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/material",
|
"name": "@zhst/material",
|
||||||
"version": "0.10.4",
|
"version": "0.11.0",
|
||||||
"description": "物料库",
|
"description": "物料库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -21,6 +21,9 @@ export interface Option {
|
|||||||
* @default: true
|
* @default: true
|
||||||
*/
|
*/
|
||||||
scaleAble?: boolean;
|
scaleAble?: boolean;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
backgroundColor?: string;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 是否允许拖拽
|
* 是否允许拖拽
|
||||||
@ -81,7 +84,11 @@ class Viewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
const { width = 300, height = 150 } = this.options
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
|
|
||||||
|
canvas.width = width || canvas.width
|
||||||
|
canvas.height = height || canvas.height
|
||||||
addClass(canvas, CLASS_CANVAS);
|
addClass(canvas, CLASS_CANVAS);
|
||||||
this.element.appendChild(canvas);
|
this.element.appendChild(canvas);
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
|
@ -102,3 +102,4 @@ export type { AppProps } from './app';
|
|||||||
export { default as notification } from './notification';
|
export { default as notification } from './notification';
|
||||||
export type { ArgsProps as NotificationArgsProps } from './notification';
|
export type { ArgsProps as NotificationArgsProps } from './notification';
|
||||||
export { default as ButtonList } from './ButtonList'
|
export { default as ButtonList } from './ButtonList'
|
||||||
|
export * from './utils'
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export * from './constants'
|
Loading…
Reference in New Issue
Block a user