style: skeleton for search result

This commit is contained in:
jialin
2025-06-25 14:35:00 +08:00
parent adfdf41e85
commit a4d1d3b16c
4 changed files with 77 additions and 29 deletions
@@ -8,13 +8,24 @@ const Wrapper = styled(Flex)`
background-color: var(--ant-color-bg-container); background-color: var(--ant-color-bg-container);
`; `;
const FileSkeleton = () => { const FileSkeleton: React.FC<{ counts: number; itemHeight?: number }> = ({
counts = 2,
itemHeight
}) => {
return ( return (
<Wrapper vertical justify={'space-between'}> <Wrapper
vertical
justify={'space-between'}
style={{ height: itemHeight || 'auto' }}
>
<Skeleton paragraph={{ rows: 1, width: '100%' }} title={false}></Skeleton> <Skeleton paragraph={{ rows: 1, width: '100%' }} title={false}></Skeleton>
<Space> <Space>
<Skeleton.Node style={{ width: 60, height: 22 }}></Skeleton.Node> {Array.from({ length: counts }).map((_, index) => (
<Skeleton.Node style={{ width: 60, height: 22 }}></Skeleton.Node> <Skeleton.Node
style={{ width: 60, height: 22 }}
key={index}
></Skeleton.Node>
))}
</Space> </Space>
</Wrapper> </Wrapper>
); );
@@ -385,7 +385,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
{dataSource.loading ? ( {dataSource.loading ? (
<ItemFileWrapper> <ItemFileWrapper>
{_.times(5, (index: number) => { {_.times(5, (index: number) => {
return <FileSkeleton key={index}></FileSkeleton>; return <FileSkeleton key={index} counts={3}></FileSkeleton>;
})} })}
</ItemFileWrapper> </ItemFileWrapper>
) : dataSource.fileList.length ? ( ) : dataSource.fileList.length ? (
+57 -24
View File
@@ -2,11 +2,14 @@ import IconFont from '@/components/icon-font';
import SimpleOverlay from '@/components/simple-overlay'; import SimpleOverlay from '@/components/simple-overlay';
import { SearchOutlined } from '@ant-design/icons'; import { SearchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Col, Empty, Row, Spin } from 'antd'; import { Button, Empty, Spin } from 'antd';
import _ from 'lodash';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import 'simplebar-react/dist/simplebar.min.css'; import 'simplebar-react/dist/simplebar.min.css';
import styled from 'styled-components';
import { modelSourceMap } from '../config'; import { modelSourceMap } from '../config';
import '../style/search-result.less'; import '../style/search-result.less';
import FileSkeleton from './file-skeleton';
import HFModelItem from './hf-model-item'; import HFModelItem from './hf-model-item';
interface SearchResultProps { interface SearchResultProps {
@@ -20,6 +23,25 @@ interface SearchResultProps {
isEvaluating?: boolean; isEvaluating?: boolean;
} }
const ItemFileWrapper = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
gap: 24px;
`;
const SpinWrapper = styled.div`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
bottom: 0;
display: flex;
justify-content: center;
`;
const SearchResult: React.FC<SearchResultProps> = (props) => { const SearchResult: React.FC<SearchResultProps> = (props) => {
const { resultList, onSelect, isEvaluating, source, networkError } = props; const { resultList, onSelect, isEvaluating, source, networkError } = props;
const intl = useIntl(); const intl = useIntl();
@@ -94,32 +116,43 @@ const SearchResult: React.FC<SearchResultProps> = (props) => {
<Spin spinning={props.loading}> <Spin spinning={props.loading}>
<div style={{ minHeight: 200 }}> <div style={{ minHeight: 200 }}>
{resultList.length ? ( {resultList.length ? (
<Row gutter={[16, 24]}> <ItemFileWrapper>
{resultList.map((item, index) => ( {resultList.map((item, index) => (
<Col span={24} key={item.name}> <div
<div key={item.name}
onClick={(e) => handleSelect(e, item)} onClick={(e) => handleSelect(e, item)}
onKeyDown={(e) => handleOnEnter(e, item)} onKeyDown={(e) => handleOnEnter(e, item)}
> >
<HFModelItem <HFModelItem
source={source} source={source}
tags={item.tags} tags={item.tags}
key={index} key={index}
title={item.name} title={item.name}
downloads={item.downloads} downloads={item.downloads}
likes={item.likes} likes={item.likes}
task={item.task} task={item.task}
updatedAt={item.updatedAt} updatedAt={item.updatedAt}
evaluateResult={item.evaluateResult} evaluateResult={item.evaluateResult}
active={item.id === props.current} active={item.id === props.current}
isEvaluating={isEvaluating} isEvaluating={isEvaluating}
/> />
</div> </div>
</Col>
))} ))}
</Row> </ItemFileWrapper>
) : props.loading ? (
<ItemFileWrapper>
{_.times(10, (index: number) => {
return (
<FileSkeleton
key={index}
counts={3}
itemHeight={82}
></FileSkeleton>
);
})}
</ItemFileWrapper>
) : ( ) : (
!props.loading && renderEmpty renderEmpty
)} )}
</div> </div>
</Spin> </Spin>
@@ -3,6 +3,10 @@
.search-result-wrap { .search-result-wrap {
padding: 16px @padding; padding: 16px @padding;
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base); border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
.ant-spin-container.ant-spin-blur {
opacity: unset;
}
} }
.gguf-tips { .gguf-tips {