chore: infinite scroller
This commit is contained in:
+1
-3
@@ -1,4 +1,2 @@
|
|||||||
#!/bin/sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
npx lint-staged
|
npx lint-staged
|
||||||
|
|||||||
+2
-1
@@ -64,12 +64,13 @@
|
|||||||
"overlayscrollbars-react": "^0.5.6",
|
"overlayscrollbars-react": "^0.5.6",
|
||||||
"pdfjs-dist": "^4.7.76",
|
"pdfjs-dist": "^4.7.76",
|
||||||
"query-string": "^9.0.0",
|
"query-string": "^9.0.0",
|
||||||
"rc-resize-observer": "^1.4.0",
|
"rc-resize-observer": "^1.4.3",
|
||||||
"rc-virtual-list": "^3.14.8",
|
"rc-virtual-list": "^3.14.8",
|
||||||
"re-resizable": "^6.10.1",
|
"re-resizable": "^6.10.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hotkeys-hook": "^4.5.0",
|
"react-hotkeys-hook": "^4.5.0",
|
||||||
|
"react-intersection-observer": "^9.16.0",
|
||||||
"react-markdown": "^9.0.3",
|
"react-markdown": "^9.0.3",
|
||||||
"rehype-katex": "^7.0.1",
|
"rehype-katex": "^7.0.1",
|
||||||
"remark-breaks": "^4.0.0",
|
"remark-breaks": "^4.0.0",
|
||||||
|
|||||||
Generated
+1107
-218
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,6 @@
|
|||||||
import breakpoints from '@/config/breakpoints';
|
import breakpoints from '@/config/breakpoints';
|
||||||
|
import InfiniteScroller from '@/pages/_components/infinite-scroller';
|
||||||
|
import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
|
||||||
import { Col, FloatButton, Row, Spin } from 'antd';
|
import { Col, FloatButton, Row, Spin } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import ResizeObserver from 'rc-resize-observer';
|
import ResizeObserver from 'rc-resize-observer';
|
||||||
@@ -74,6 +76,12 @@ const CardList: React.FC<CatalogListProps> = (props) => {
|
|||||||
renderItem
|
renderItem
|
||||||
} = props;
|
} = props;
|
||||||
const [span, setSpan] = React.useState(defaultSpan);
|
const [span, setSpan] = React.useState(defaultSpan);
|
||||||
|
const {
|
||||||
|
total,
|
||||||
|
current,
|
||||||
|
loading: contextLoading,
|
||||||
|
refresh
|
||||||
|
} = useScrollerContext();
|
||||||
|
|
||||||
const getSpanByWidth = (width: number) => {
|
const getSpanByWidth = (width: number) => {
|
||||||
if (width < breakpoints.md) return 24;
|
if (width < breakpoints.md) return 24;
|
||||||
@@ -91,7 +99,12 @@ const CardList: React.FC<CatalogListProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="relative" style={{ width: '100%' }}>
|
<div className="relative" style={{ width: '100%' }}>
|
||||||
<ResizeObserver onResize={handleResize} disabled={!resizable}>
|
<ResizeObserver onResize={handleResize} disabled={!resizable}>
|
||||||
<div style={{ width: '100%' }}>
|
<InfiniteScroller
|
||||||
|
total={total}
|
||||||
|
current={current}
|
||||||
|
loading={contextLoading}
|
||||||
|
refresh={refresh}
|
||||||
|
>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{dataList.map((item: any, index) => {
|
{dataList.map((item: any, index) => {
|
||||||
return (
|
return (
|
||||||
@@ -107,7 +120,7 @@ const CardList: React.FC<CatalogListProps> = (props) => {
|
|||||||
isFirst={isFirst}
|
isFirst={isFirst}
|
||||||
Skeleton={Skeleton}
|
Skeleton={Skeleton}
|
||||||
/>
|
/>
|
||||||
</div>
|
</InfiniteScroller>
|
||||||
</ResizeObserver>
|
</ResizeObserver>
|
||||||
<FloatButton.BackTop visibilityHeight={1000} />
|
<FloatButton.BackTop visibilityHeight={1000} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
useInfiniteScroll,
|
||||||
|
UseInfiniteScrollOptions
|
||||||
|
} from './use-infinite-scroll';
|
||||||
|
|
||||||
|
const InfiniteScroller: React.FC<
|
||||||
|
UseInfiniteScrollOptions & { children: React.ReactNode }
|
||||||
|
> = (props) => {
|
||||||
|
const { children, ...restProps } = props;
|
||||||
|
const { observerRef } = useInfiniteScroll(restProps);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{children}
|
||||||
|
<div ref={observerRef} style={{ height: 1 }}>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InfiniteScroller;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { useMemoizedFn } from 'ahooks';
|
||||||
|
import { throttle } from 'lodash';
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { useInView } from 'react-intersection-observer';
|
||||||
|
|
||||||
|
export interface UseInfiniteScrollOptions {
|
||||||
|
total: number;
|
||||||
|
current: number;
|
||||||
|
loading: boolean;
|
||||||
|
refresh: (nextPage: number) => void;
|
||||||
|
onBottom?: () => void;
|
||||||
|
throttleDelay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useInfiniteScroll({
|
||||||
|
total,
|
||||||
|
current,
|
||||||
|
loading,
|
||||||
|
refresh,
|
||||||
|
onBottom,
|
||||||
|
throttleDelay = 300
|
||||||
|
}: UseInfiniteScrollOptions) {
|
||||||
|
const { ref: observerRef, inView } = useInView({
|
||||||
|
threshold: 0.2
|
||||||
|
});
|
||||||
|
const isInitialLoad = useRef(true);
|
||||||
|
|
||||||
|
const throttledLoadMore = useMemoizedFn(
|
||||||
|
throttle(() => {
|
||||||
|
if (loading) return;
|
||||||
|
if (current >= total) return;
|
||||||
|
|
||||||
|
onBottom?.();
|
||||||
|
refresh(current + 1);
|
||||||
|
}, throttleDelay)
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (inView) {
|
||||||
|
if (isInitialLoad.current) {
|
||||||
|
isInitialLoad.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throttledLoadMore();
|
||||||
|
}
|
||||||
|
}, [inView, throttledLoadMore]);
|
||||||
|
|
||||||
|
return { observerRef };
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { createContext, useContext } from 'react';
|
||||||
|
|
||||||
|
interface ScrollerContextProps {
|
||||||
|
total: number;
|
||||||
|
current: number;
|
||||||
|
loading: boolean;
|
||||||
|
refresh: (nextPage: number) => void;
|
||||||
|
onBottom?: () => void;
|
||||||
|
throttleDelay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ScrollerContext = createContext<ScrollerContextProps>(
|
||||||
|
{} as ScrollerContextProps
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useScrollerContext = () => {
|
||||||
|
const context = useContext(ScrollerContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
'useScrollerContext must be used within a ScrollerProvider'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import CardSkeleton from '@/components/templates/card-skelton';
|
import CardSkeleton from '@/components/templates/card-skelton';
|
||||||
import breakpoints from '@/config/breakpoints';
|
import breakpoints from '@/config/breakpoints';
|
||||||
|
import InfiniteScroller from '@/pages/_components/infinite-scroller';
|
||||||
|
import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
|
||||||
import { Col, FloatButton, Row, Spin } from 'antd';
|
import { Col, FloatButton, Row, Spin } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import ResizeObserver from 'rc-resize-observer';
|
import ResizeObserver from 'rc-resize-observer';
|
||||||
@@ -72,6 +74,13 @@ const CardList: React.FC<BackendListProps> = (props) => {
|
|||||||
onSelect
|
onSelect
|
||||||
} = props;
|
} = props;
|
||||||
const [span, setSpan] = React.useState(defaultSpan);
|
const [span, setSpan] = React.useState(defaultSpan);
|
||||||
|
const {
|
||||||
|
total,
|
||||||
|
current,
|
||||||
|
loading: contextLoading,
|
||||||
|
refresh,
|
||||||
|
throttleDelay
|
||||||
|
} = useScrollerContext();
|
||||||
|
|
||||||
const getSpanByWidth = (width: number) => {
|
const getSpanByWidth = (width: number) => {
|
||||||
if (width < breakpoints.md) return 24;
|
if (width < breakpoints.md) return 24;
|
||||||
@@ -89,7 +98,13 @@ const CardList: React.FC<BackendListProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="relative" style={{ width: '100%' }}>
|
<div className="relative" style={{ width: '100%' }}>
|
||||||
<ResizeObserver onResize={handleResize} disabled={!resizable}>
|
<ResizeObserver onResize={handleResize} disabled={!resizable}>
|
||||||
<div style={{ width: '100%' }}>
|
<InfiniteScroller
|
||||||
|
total={total}
|
||||||
|
current={current}
|
||||||
|
loading={contextLoading}
|
||||||
|
refresh={refresh}
|
||||||
|
throttleDelay={throttleDelay}
|
||||||
|
>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{dataList.map((item: any) => {
|
{dataList.map((item: any) => {
|
||||||
return (
|
return (
|
||||||
@@ -100,7 +115,7 @@ const CardList: React.FC<BackendListProps> = (props) => {
|
|||||||
})}
|
})}
|
||||||
</Row>
|
</Row>
|
||||||
<ListSkeleton span={span} loading={loading} isFirst={isFirst} />
|
<ListSkeleton span={span} loading={loading} isFirst={isFirst} />
|
||||||
</div>
|
</InfiniteScroller>
|
||||||
</ResizeObserver>
|
</ResizeObserver>
|
||||||
<FloatButton.BackTop visibilityHeight={1000} />
|
<FloatButton.BackTop visibilityHeight={1000} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import { PageActionType } from '@/config/types';
|
|||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
|
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { ScrollerContext } from '../_components/infinite-scroller/use-scroller-context';
|
||||||
import {
|
import {
|
||||||
createBackend,
|
createBackend,
|
||||||
createBackendFromYAML,
|
createBackendFromYAML,
|
||||||
@@ -141,6 +143,13 @@ const BackendList = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadMore = useMemoizedFn((nextPage: number) => {
|
||||||
|
fetchData({
|
||||||
|
...queryParams,
|
||||||
|
page: nextPage
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer
|
<PageContainer
|
||||||
ghost
|
ghost
|
||||||
@@ -170,13 +179,23 @@ const BackendList = () => {
|
|||||||
showSelect={false}
|
showSelect={false}
|
||||||
></FilterBar>
|
></FilterBar>
|
||||||
|
|
||||||
<BackendCardList
|
<ScrollerContext.Provider
|
||||||
dataList={dataSource.dataList}
|
value={{
|
||||||
loading={dataSource.loading}
|
total: dataSource.totalPage,
|
||||||
activeId={false}
|
current: queryParams.page!,
|
||||||
isFirst={!dataSource.loadend}
|
loading: dataSource.loading,
|
||||||
onSelect={handleOnSelect}
|
refresh: loadMore,
|
||||||
></BackendCardList>
|
throttleDelay: 300
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BackendCardList
|
||||||
|
dataList={dataSource.dataList}
|
||||||
|
loading={dataSource.loading}
|
||||||
|
activeId={false}
|
||||||
|
isFirst={!dataSource.loadend}
|
||||||
|
onSelect={handleOnSelect}
|
||||||
|
></BackendCardList>
|
||||||
|
</ScrollerContext.Provider>
|
||||||
<AddModal
|
<AddModal
|
||||||
action={openModalStatus.action}
|
action={openModalStatus.action}
|
||||||
onClose={() => setOpenModalStatus({ open: false, action: 'create' })}
|
onClose={() => setOpenModalStatus({ open: false, action: 'create' })}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { modelsExpandKeysAtom } from '@/atoms/models';
|
import { modelsExpandKeysAtom } from '@/atoms/models';
|
||||||
import MoreButton from '@/components/buttons/more';
|
|
||||||
import PageTools from '@/components/page-tools';
|
import PageTools from '@/components/page-tools';
|
||||||
import BaseSelect from '@/components/seal-form/base/select';
|
import BaseSelect from '@/components/seal-form/base/select';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||||
|
import { ScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
|
||||||
import { IS_FIRST_LOGIN, writeState } from '@/utils/localstore/index';
|
import { IS_FIRST_LOGIN, writeState } from '@/utils/localstore/index';
|
||||||
import { SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
import { SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { useIntl, useNavigate } from '@umijs/max';
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Button, Input, Pagination, Space, message } from 'antd';
|
import { Button, Input, Pagination, Space, message } from 'antd';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -213,12 +214,12 @@ const Catalog: React.FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadMore = () => {
|
const loadMore = useMemoizedFn((nextPage: number) => {
|
||||||
fetchData({
|
fetchData({
|
||||||
...queryParams,
|
...queryParams,
|
||||||
page: queryParams.page + 1
|
page: nextPage
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
@@ -303,18 +304,23 @@ const Catalog: React.FC = () => {
|
|||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
></PageTools>
|
></PageTools>
|
||||||
<CatalogList
|
<ScrollerContext.Provider
|
||||||
dataList={dataSource.dataList}
|
value={{
|
||||||
loading={dataSource.loading}
|
total: dataSource.totalPage,
|
||||||
onDeploy={handleOnDeploy}
|
current: queryParams.page,
|
||||||
activeId={-1}
|
loading: dataSource.loading,
|
||||||
isFirst={isFirst}
|
refresh: loadMore,
|
||||||
></CatalogList>
|
throttleDelay: 300
|
||||||
<MoreButton
|
}}
|
||||||
show={queryParams.page < dataSource.totalPage}
|
>
|
||||||
loading={dataSource.loading}
|
<CatalogList
|
||||||
loadMore={loadMore}
|
dataList={dataSource.dataList}
|
||||||
></MoreButton>
|
loading={dataSource.loading}
|
||||||
|
onDeploy={handleOnDeploy}
|
||||||
|
activeId={-1}
|
||||||
|
isFirst={isFirst}
|
||||||
|
></CatalogList>
|
||||||
|
</ScrollerContext.Provider>
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<Pagination
|
<Pagination
|
||||||
hideOnSinglePage={queryParams.perPage === 100}
|
hideOnSinglePage={queryParams.perPage === 100}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import CatalogSkelton from '@/components/templates/card-skelton';
|
import CatalogSkelton from '@/components/templates/card-skelton';
|
||||||
import breakpoints from '@/config/breakpoints';
|
import breakpoints from '@/config/breakpoints';
|
||||||
|
import InfiniteScroller from '@/pages/_components/infinite-scroller';
|
||||||
|
import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
|
||||||
import { Col, FloatButton, Row, Spin } from 'antd';
|
import { Col, FloatButton, Row, Spin } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import ResizeObserver from 'rc-resize-observer';
|
import ResizeObserver from 'rc-resize-observer';
|
||||||
@@ -54,6 +56,13 @@ const ListSkeleton: React.FC<{
|
|||||||
|
|
||||||
const CatalogList: React.FC<CatalogListProps> = (props) => {
|
const CatalogList: React.FC<CatalogListProps> = (props) => {
|
||||||
const { dataList, loading, activeId, isFirst, onDeploy } = props;
|
const { dataList, loading, activeId, isFirst, onDeploy } = props;
|
||||||
|
const {
|
||||||
|
total,
|
||||||
|
current,
|
||||||
|
loading: contextLoading,
|
||||||
|
refresh,
|
||||||
|
throttleDelay
|
||||||
|
} = useScrollerContext();
|
||||||
const [span, setSpan] = React.useState(8);
|
const [span, setSpan] = React.useState(8);
|
||||||
|
|
||||||
const getSpanByWidth = (width: number) => {
|
const getSpanByWidth = (width: number) => {
|
||||||
@@ -72,7 +81,13 @@ const CatalogList: React.FC<CatalogListProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div className="relative" style={{ width: '100%' }}>
|
<div className="relative" style={{ width: '100%' }}>
|
||||||
<ResizeObserver onResize={handleResize}>
|
<ResizeObserver onResize={handleResize}>
|
||||||
<div>
|
<InfiniteScroller
|
||||||
|
total={total}
|
||||||
|
current={current}
|
||||||
|
loading={contextLoading}
|
||||||
|
refresh={refresh}
|
||||||
|
throttleDelay={throttleDelay}
|
||||||
|
>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{dataList.map((item: CatalogItemType, index) => {
|
{dataList.map((item: CatalogItemType, index) => {
|
||||||
return (
|
return (
|
||||||
@@ -87,11 +102,11 @@ const CatalogList: React.FC<CatalogListProps> = (props) => {
|
|||||||
})}
|
})}
|
||||||
</Row>
|
</Row>
|
||||||
<ListSkeleton span={span} loading={loading} isFirst={isFirst} />
|
<ListSkeleton span={span} loading={loading} isFirst={isFirst} />
|
||||||
</div>
|
</InfiniteScroller>
|
||||||
</ResizeObserver>
|
</ResizeObserver>
|
||||||
<FloatButton.BackTop visibilityHeight={1000} />
|
<FloatButton.BackTop visibilityHeight={1000} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default React.memo(CatalogList);
|
export default CatalogList;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const backendOptionsMap = {
|
|||||||
vllm: 'vLLM',
|
vllm: 'vLLM',
|
||||||
voxBox: 'vox-box',
|
voxBox: 'vox-box',
|
||||||
ascendMindie: 'MindIE',
|
ascendMindie: 'MindIE',
|
||||||
custom: 'custom'
|
custom: 'Custom'
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface BackendParameter {
|
export interface BackendParameter {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ const BackendFields: React.FC = () => {
|
|||||||
required
|
required
|
||||||
allowClear
|
allowClear
|
||||||
scaleSize={true}
|
scaleSize={true}
|
||||||
label="Image Name"
|
label={intl.formatMessage({ id: 'backend.imageName' })}
|
||||||
></SealInput.Input>
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData> name="run_command" rules={[{ required: true }]}>
|
<Form.Item<FormData> name="run_command" rules={[{ required: true }]}>
|
||||||
@@ -122,7 +122,7 @@ const BackendFields: React.FC = () => {
|
|||||||
required
|
required
|
||||||
scaleSize={true}
|
scaleSize={true}
|
||||||
allowClear
|
allowClear
|
||||||
label="Execution Command"
|
label={intl.formatMessage({ id: 'backend.runCommand' })}
|
||||||
></SealInput.TextArea>
|
></SealInput.TextArea>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
key: 'performance',
|
key: 'performance',
|
||||||
label: 'Performance',
|
label: intl.formatMessage({ id: 'models.form.performance' }),
|
||||||
forceRender: true,
|
forceRender: true,
|
||||||
children: <Performance></Performance>
|
children: <Performance></Performance>
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import MoreButton from '@/components/buttons/more';
|
|
||||||
import PageTools from '@/components/page-tools';
|
import PageTools from '@/components/page-tools';
|
||||||
import BaseSelect from '@/components/seal-form/base/select';
|
import BaseSelect from '@/components/seal-form/base/select';
|
||||||
import CardList from '@/components/templates/card-list';
|
import CardList from '@/components/templates/card-list';
|
||||||
@@ -7,8 +6,10 @@ import useTableFetch from '@/hooks/use-table-fetch';
|
|||||||
import { SyncOutlined } from '@ant-design/icons';
|
import { SyncOutlined } from '@ant-design/icons';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { useIntl, useNavigate } from '@umijs/max';
|
import { useIntl, useNavigate } from '@umijs/max';
|
||||||
|
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
|
||||||
import { Button, Input, Space } from 'antd';
|
import { Button, Input, Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { ScrollerContext } from '../_components/infinite-scroller/use-scroller-context';
|
||||||
import { MY_MODELS_API, queryMyModels } from './apis';
|
import { MY_MODELS_API, queryMyModels } from './apis';
|
||||||
import ModelItem from './components/model-item';
|
import ModelItem from './components/model-item';
|
||||||
import { categoryOptions, modelCategoriesMap } from './config';
|
import { categoryOptions, modelCategoriesMap } from './config';
|
||||||
@@ -30,13 +31,6 @@ const UserModels: React.FC = () => {
|
|||||||
});
|
});
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const loadMore = () => {
|
|
||||||
fetchData({
|
|
||||||
...queryParams,
|
|
||||||
page: queryParams.page + 1
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCategoryChange = (value: string) => {
|
const handleCategoryChange = (value: string) => {
|
||||||
handleQueryChange({
|
handleQueryChange({
|
||||||
categories: value
|
categories: value
|
||||||
@@ -67,6 +61,13 @@ const UserModels: React.FC = () => {
|
|||||||
return <ModelItem model={data} onClick={handleOnClick} />;
|
return <ModelItem model={data} onClick={handleOnClick} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadMore = useMemoizedFn((nextPage: number) => {
|
||||||
|
fetchData({
|
||||||
|
...queryParams,
|
||||||
|
page: nextPage
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContainer
|
<PageContainer
|
||||||
ghost
|
ghost
|
||||||
@@ -116,19 +117,23 @@ const UserModels: React.FC = () => {
|
|||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
></PageTools>
|
></PageTools>
|
||||||
<CardList
|
<ScrollerContext.Provider
|
||||||
dataList={dataSource.dataList}
|
value={{
|
||||||
loading={dataSource.loading}
|
total: dataSource.totalPage,
|
||||||
activeId={false}
|
current: queryParams.page,
|
||||||
isFirst={!dataSource.loadend}
|
loading: dataSource.loading,
|
||||||
Skeleton={CardSkeleton}
|
refresh: loadMore
|
||||||
renderItem={renderCard}
|
}}
|
||||||
></CardList>
|
>
|
||||||
<MoreButton
|
<CardList
|
||||||
show={queryParams.page < dataSource.totalPage}
|
dataList={dataSource.dataList}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
loadMore={loadMore}
|
activeId={false}
|
||||||
></MoreButton>
|
isFirst={!dataSource.loadend}
|
||||||
|
Skeleton={CardSkeleton}
|
||||||
|
renderItem={renderCard}
|
||||||
|
></CardList>
|
||||||
|
</ScrollerContext.Provider>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user