From 3328828da6287cd6d054e3405b28601bbc583bb6 Mon Sep 17 00:00:00 2001 From: jialin Date: Thu, 11 Dec 2025 10:25:03 +0800 Subject: [PATCH] refactor: card list resize container --- src/components/resize-container/index.tsx | 35 +++++++++ .../resize-container/use-responsive.ts | 23 ++++++ src/components/templates/card-list.tsx | 78 +++++-------------- src/components/templates/card-skelton.tsx | 47 +++++------ .../_components/infinite-scroller/index.tsx | 2 +- .../backends/components/backend-list.tsx | 63 +++++---------- .../llmodels/components/catalog-list.tsx | 75 ++++++------------ src/pages/llmodels/user-models.tsx | 2 - 8 files changed, 143 insertions(+), 182 deletions(-) create mode 100644 src/components/resize-container/index.tsx create mode 100644 src/components/resize-container/use-responsive.ts diff --git a/src/components/resize-container/index.tsx b/src/components/resize-container/index.tsx new file mode 100644 index 00000000..a45df56b --- /dev/null +++ b/src/components/resize-container/index.tsx @@ -0,0 +1,35 @@ +import { Col, Row } from 'antd'; +import ResizeObserver from 'rc-resize-observer'; +import useResponsive from './use-responsive'; + +interface ResizeObserverContainerProps { + dataList: any[]; + renderItem: (data: any) => React.ReactNode; + defaultSpan?: number; + resizable?: boolean; +} + +const ResizeContainer: React.FC = ({ + defaultSpan = 8, + dataList, + renderItem, + resizable = true +}) => { + const { span, handleResize } = useResponsive({ defaultSpan }); + + return ( + + + {dataList.map((item: any, index) => { + return ( + + {renderItem(item)} + + ); + })} + + + ); +}; + +export default ResizeContainer; diff --git a/src/components/resize-container/use-responsive.ts b/src/components/resize-container/use-responsive.ts new file mode 100644 index 00000000..81a0ef0b --- /dev/null +++ b/src/components/resize-container/use-responsive.ts @@ -0,0 +1,23 @@ +import breakpoints from '@/config/breakpoints'; +import { useMemoizedFn } from 'ahooks'; +import _ from 'lodash'; +import { useState } from 'react'; + +const useResponsive = ({ defaultSpan = 8 }: { defaultSpan?: number }) => { + const [span, setSpan] = useState(defaultSpan); + + const getSpanByWidth = (width: number) => { + if (width < breakpoints.md) return 24; + if (width < breakpoints.lg) return 12; + return 8; + }; + + const handleResize = useMemoizedFn( + _.throttle((size: { width: number; height: number }) => { + setSpan(getSpanByWidth(size.width)); + }, 100) + ); + return { span, handleResize }; +}; + +export default useResponsive; diff --git a/src/components/templates/card-list.tsx b/src/components/templates/card-list.tsx index 237a6192..2182c62d 100644 --- a/src/components/templates/card-list.tsx +++ b/src/components/templates/card-list.tsx @@ -1,10 +1,9 @@ -import breakpoints from '@/config/breakpoints'; +import ResizeContainer from '@/components/resize-container'; +import CardSkeleton from '@/components/templates/card-skelton'; import InfiniteScroller from '@/pages/_components/infinite-scroller'; import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context'; -import { Col, Row, Spin } from 'antd'; -import _ from 'lodash'; -import ResizeObserver from 'rc-resize-observer'; -import React, { useCallback } from 'react'; +import { Spin } from 'antd'; +import React from 'react'; import styled from 'styled-components'; const SpinWrapper = styled.div` @@ -30,22 +29,12 @@ interface CatalogListProps { activeId: Global.WithFalse; isFirst: boolean; renderItem: (data: any) => React.ReactNode; - Skeleton: React.ComponentType<{ span: number }>; } -const InnerSkeleton = (Skeleton: React.ComponentType<{ span: number }>) => { - return (props: any) => { - return ; - }; -}; - const ListSkeleton: React.FC<{ - span: number; loading: boolean; isFirst: boolean; - Skeleton: React.ComponentType<{ span: number }>; -}> = ({ span, loading, isFirst, Skeleton }) => { - const CatalogSkeleton = InnerSkeleton(Skeleton); +}> = ({ loading, isFirst }) => { return (
{loading && ( @@ -57,7 +46,7 @@ const ListSkeleton: React.FC<{ }} wrapperClassName="skelton-wrapper" > - {isFirst && } + {isFirst && } )} @@ -72,10 +61,8 @@ const CardList: React.FC = (props) => { isFirst, defaultSpan = 8, resizable = true, - Skeleton, renderItem } = props; - const [span, setSpan] = React.useState(defaultSpan); const { total, current, @@ -83,46 +70,21 @@ const CardList: React.FC = (props) => { refresh } = useScrollerContext(); - const getSpanByWidth = (width: number) => { - if (width < breakpoints.md) return 24; - if (width < breakpoints.lg) return 12; - return 8; - }; - - const handleResize = useCallback( - _.throttle((size: { width: number; height: number }) => { - setSpan(getSpanByWidth(size.width)); - }, 100), - [] - ); - return ( -
- - - - {dataList.map((item: any, index) => { - return ( - - {renderItem?.(item)} - - ); - })} - - - - -
+ + + + ); }; diff --git a/src/components/templates/card-skelton.tsx b/src/components/templates/card-skelton.tsx index 6f02f34d..334c5e67 100644 --- a/src/components/templates/card-skelton.tsx +++ b/src/components/templates/card-skelton.tsx @@ -1,38 +1,33 @@ -import { Col, Row, Skeleton } from 'antd'; +import { Skeleton } from 'antd'; import React from 'react'; +import ResizeContainer from '../resize-container'; interface CatalogSkeltonProps { - span: number; skeletonProps?: any; skeletonStyle?: React.CSSProperties; } const CardSkelton: React.FC = (props) => { return ( - - {Array(6) - .fill(1) - .map((_, index) => { - return ( - - - - ); - })} - + ( + + )} + > ); }; -export default React.memo(CardSkelton); +export default CardSkelton; diff --git a/src/pages/_components/infinite-scroller/index.tsx b/src/pages/_components/infinite-scroller/index.tsx index e805dc3b..bdee2a38 100644 --- a/src/pages/_components/infinite-scroller/index.tsx +++ b/src/pages/_components/infinite-scroller/index.tsx @@ -16,7 +16,7 @@ const InfiniteScroller: React.FC< const { observerRef, throttledLoadMore } = useInfiniteScroll(restProps); return ( -
+
{children}
= ({ span, loading, isFirst }) => { +}> = ({ loading, isFirst }) => { return (
{loading && ( @@ -67,7 +64,6 @@ const ListSkeleton: React.FC<{ {isFirst && ( = (props) => { resizable = true, onSelect } = props; - const [span, setSpan] = React.useState(defaultSpan); const { total, current, @@ -104,42 +99,22 @@ const CardList: React.FC = (props) => { throttleDelay } = useScrollerContext(); - const getSpanByWidth = (width: number) => { - if (width < breakpoints.md) return 24; - if (width < breakpoints.lg) return 12; - return 8; - }; - - const handleResize = useCallback( - _.throttle((size: { width: number; height: number }) => { - setSpan(getSpanByWidth(size.width)); - }, 100), - [] - ); - return ( -
- - - - {dataList.map((item: any) => { - return ( - - - - ); - })} - - - - -
+ + } + > + + ); }; diff --git a/src/pages/llmodels/components/catalog-list.tsx b/src/pages/llmodels/components/catalog-list.tsx index 05ced889..95cd8025 100644 --- a/src/pages/llmodels/components/catalog-list.tsx +++ b/src/pages/llmodels/components/catalog-list.tsx @@ -1,14 +1,10 @@ +import ResizeContainer from '@/components/resize-container'; import CatalogSkelton from '@/components/templates/card-skelton'; -import breakpoints from '@/config/breakpoints'; import InfiniteScroller from '@/pages/_components/infinite-scroller'; import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context'; -import { useIntl } from '@umijs/max'; -import { Col, Row, Spin } from 'antd'; -import _ from 'lodash'; -import ResizeObserver from 'rc-resize-observer'; -import React, { useCallback } from 'react'; +import { Spin } from 'antd'; +import React from 'react'; import styled from 'styled-components'; -import { CatalogItem as CatalogItemType } from '../config/types'; import CatalogItem from './catalog-item'; const SpinWrapper = styled.div` @@ -32,10 +28,9 @@ interface CatalogListProps { } const ListSkeleton: React.FC<{ - span: number; loading: boolean; isFirst: boolean; -}> = ({ span, loading, isFirst }) => { +}> = ({ loading, isFirst }) => { return (
{loading && ( @@ -47,7 +42,7 @@ const ListSkeleton: React.FC<{ }} wrapperClassName="skelton-wrapper" > - {isFirst && } + {isFirst && } )} @@ -56,7 +51,6 @@ const ListSkeleton: React.FC<{ }; const CatalogList: React.FC = (props) => { - const intl = useIntl(); const { dataList, loading, activeId, isFirst, onDeploy } = props; const { total, @@ -65,48 +59,27 @@ const CatalogList: React.FC = (props) => { refresh, throttleDelay } = useScrollerContext(); - const [span, setSpan] = React.useState(8); - - const getSpanByWidth = (width: number) => { - if (width < breakpoints.md) return 24; - if (width < breakpoints.lg) return 12; - return 8; - }; - - const handleResize = useCallback( - _.throttle((size: { width: number; height: number }) => { - setSpan(getSpanByWidth(size.width)); - }, 100), - [] - ); return ( -
- - - - {dataList.map((item: CatalogItemType, index) => { - return ( - - - - ); - })} - - - - -
+ + ( + + )} + > + + ); }; diff --git a/src/pages/llmodels/user-models.tsx b/src/pages/llmodels/user-models.tsx index d2c5bc11..fef08316 100644 --- a/src/pages/llmodels/user-models.tsx +++ b/src/pages/llmodels/user-models.tsx @@ -2,7 +2,6 @@ import IconFont from '@/components/icon-font'; import PageTools from '@/components/page-tools'; import BaseSelect from '@/components/seal-form/base/select'; import CardList from '@/components/templates/card-list'; -import CardSkeleton from '@/components/templates/card-skelton'; import useTableFetch from '@/hooks/use-table-fetch'; import { SyncOutlined } from '@ant-design/icons'; import { useIntl, useNavigate } from '@umijs/max'; @@ -236,7 +235,6 @@ const UserModels: React.FC = () => { loading={dataSource.loading} activeId={false} isFirst={!dataSource.loadend} - Skeleton={CardSkeleton} renderItem={renderCard} >