refactor: deployments dir tree

This commit is contained in:
jialin
2026-03-19 12:28:18 +08:00
committed by jialin
parent 9840a48301
commit fd1a079271
44 changed files with 118 additions and 306 deletions
@@ -0,0 +1,160 @@
import fallbackImg from '@/assets/images/img.png';
import AutoTooltip from '@/components/auto-tooltip';
import IconFont from '@/components/icon-font';
import ThemeTag from '@/components/tags-wrapper/theme-tag';
import { categoryConfig } from '@/pages/_components/model-tag';
import { useIntl } from '@umijs/max';
import { Typography } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import React, { useCallback, useMemo } from 'react';
import { modelCategories } from '../../config';
import { CatalogItem as CatalogItemType } from '../../config/types';
import '../../style/catalog-item.less';
interface CatalogItemProps {
activeId: number;
data: CatalogItemType;
onClick: (data: CatalogItemType) => void;
}
const CatalogItem: React.FC<CatalogItemProps> = (props) => {
const intl = useIntl();
const { onClick, activeId, data } = props;
const handleOnClick = useCallback(() => {
onClick(data);
}, [data, onClick]);
const handleOnError = (e: any) => {
e.target.src = fallbackImg;
};
const description = useMemo(() => {
return (
<Typography.Paragraph
className="desc"
ellipsis={{
rows: 2,
tooltip: (
<div
className="custome-scrollbar"
style={{
display: 'flex',
justifyContent: 'flex-start',
maxHeight: 300,
maxWidth: 300,
overflow: 'auto'
}}
>
{data.description}
</div>
)
}}
>
{data.description}
</Typography.Paragraph>
);
}, [data.description]);
return (
<div
onClick={handleOnClick}
className={classNames('catalog-item', { active: activeId === data.id })}
>
<div className="content">
<div className="title">
<div className="img">
<img
src={data.icon || fallbackImg}
alt=""
onError={handleOnError}
/>
</div>
<AutoTooltip ghost>{data.name}</AutoTooltip>
</div>
</div>
<div className="item-footer">
<div className="update-time">
<span
className="flex-center"
title={intl.formatMessage({ id: 'models.catalog.release.date' })}
>
<IconFont
type="icon-new_release_outlined"
style={{
color: 'var(--ant-color-text-tertiary)',
marginRight: 5
}}
></IconFont>
{data.release_date}
</span>
<span className="flex-center">
{_.map(data.licenses, (license: string, index: number) => {
return (
<span key={license} className="flex-center m-r-8">
<IconFont
type="icon-license"
style={{
color: 'var(--ant-color-text-tertiary)',
marginRight: 5
}}
></IconFont>
<span>{license}</span>
</span>
);
})}
</span>
</div>
<div className="tags gap-6">
{data.categories.map((sItem, i) => {
return (
<ThemeTag
icon={categoryConfig[sItem]?.icon}
key={sItem}
className="tag-item"
color={categoryConfig[sItem]?.color || 'blue'}
opacity={0.7}
>
{_.find(modelCategories, { value: sItem })?.label || sItem}
</ThemeTag>
);
})}
{data.capabilities?.length > 0 &&
data.capabilities.map((sItem, i) => {
return (
<ThemeTag
key={sItem}
className="tag-item"
color="purple"
opacity={0.7}
>
{_.map(_.split(sItem, '/'), (s: string) => {
return _.split(s, '_').join(' ');
})
.reverse()
.join(' ')}
</ThemeTag>
);
})}
{data.size > 0 && (
<>
<span className="dot"></span>
<AutoTooltip
style={{
borderRadius: 4
}}
>
{data.activated_size
? `${data.size}${data.size_unit || 'B'}-A${data.activated_size}B`
: `${data.size}${data.size_unit || 'B'}`}
</AutoTooltip>
</>
)}
</div>
</div>
</div>
);
};
export default CatalogItem;
@@ -0,0 +1,88 @@
import ResizeContainer from '@/components/resize-container';
import CatalogSkelton from '@/components/templates/card-skelton';
import InfiniteScroller from '@/pages/_components/infinite-scroller';
import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context';
import { Spin } from 'antd';
import React from 'react';
import styled from 'styled-components';
import CatalogItem from './catalog-item';
const SpinWrapper = styled.div`
width: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
max-height: 400px;
right: 0;
`;
interface CatalogListProps {
dataList: any[];
loading: boolean;
activeId: number;
isFirst: boolean;
onDeploy: (data: any) => void;
}
const ListSkeleton: React.FC<{
loading: boolean;
isFirst: boolean;
}> = ({ loading, isFirst }) => {
return (
<div>
{loading && (
<SpinWrapper>
<Spin
spinning={loading}
style={{
width: '100%'
}}
classNames={{
root: 'skelton-wrapper'
}}
>
{isFirst && <CatalogSkelton></CatalogSkelton>}
</Spin>
</SpinWrapper>
)}
</div>
);
};
const CatalogList: React.FC<CatalogListProps> = (props) => {
const { dataList, loading, activeId, isFirst, onDeploy } = props;
const {
total,
current,
loading: contextLoading,
refresh,
throttleDelay
} = useScrollerContext();
return (
<InfiniteScroller
total={total}
current={current}
loading={contextLoading}
refresh={refresh}
throttleDelay={throttleDelay}
>
<ResizeContainer
dataList={dataList}
renderItem={(item) => (
<CatalogItem
onClick={onDeploy}
activeId={activeId}
data={item}
></CatalogItem>
)}
></ResizeContainer>
<ListSkeleton loading={loading} isFirst={isFirst} />
</InfiniteScroller>
);
};
export default CatalogList;