|
|
import React, { useEffect, useState } from 'react';
|
|
|
import styles from './style/compCard.module.less';
|
|
|
import { Card, Grid, Rate, Typography, Pagination, Spin, Empty, Image } from '@arco-design/web-react';
|
|
|
import { useRouter } from 'next/router';
|
|
|
import { getComponentMarket } from '@/api/componentMarket';
|
|
|
import { IconStarFill } from '@arco-design/web-react/icon';
|
|
|
|
|
|
const { Row, Col } = Grid;
|
|
|
|
|
|
interface CompCardProps {
|
|
|
selectedTab: string;
|
|
|
componentClassify: string;
|
|
|
searchClassify: string;
|
|
|
searchKeyword: string;
|
|
|
selectedComp: (component: ComponentItem) => void;
|
|
|
}
|
|
|
|
|
|
interface ComponentItem {
|
|
|
id: string;
|
|
|
name: string;
|
|
|
identifier?: string;
|
|
|
componentClassify?: string;
|
|
|
deployType?: string;
|
|
|
star?: number;
|
|
|
description?: string;
|
|
|
|
|
|
[key: string]: any;
|
|
|
}
|
|
|
|
|
|
const CompCard: React.FC<CompCardProps> = ({
|
|
|
selectedTab,
|
|
|
componentClassify,
|
|
|
searchClassify,
|
|
|
searchKeyword,
|
|
|
selectedComp
|
|
|
}) => {
|
|
|
const [componentList, setComponentList] = useState<ComponentItem[]>([]);
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
const [current, setCurrent] = useState(1);
|
|
|
const [total, setTotal] = useState(0);
|
|
|
const pageSize = 12; // 每页显示12条数据
|
|
|
const router = useRouter();
|
|
|
|
|
|
// 获取组件市场数据
|
|
|
const fetchComponentData = async (page = 1) => {
|
|
|
try {
|
|
|
setLoading(true);
|
|
|
|
|
|
// 根据搜索条件或当前Tab确定分类
|
|
|
let classifyLabel = '全部';
|
|
|
|
|
|
// 如果搜索框有选择分类,使用搜索框的分类
|
|
|
if (searchClassify && searchClassify !== '全部') {
|
|
|
classifyLabel = searchClassify;
|
|
|
}
|
|
|
// 否则使用当前Tab的分类
|
|
|
else if (componentClassify && componentClassify !== '全部') {
|
|
|
classifyLabel = componentClassify;
|
|
|
}
|
|
|
|
|
|
const params = {
|
|
|
componentClassify: classifyLabel,
|
|
|
keyword: searchKeyword || '',
|
|
|
current: page,
|
|
|
size: pageSize
|
|
|
};
|
|
|
|
|
|
const res: any = await getComponentMarket(params);
|
|
|
|
|
|
if (res?.code === 200 && res?.data) {
|
|
|
setComponentList(res.data.list || []);
|
|
|
setTotal(res.data.totalCount || 0);
|
|
|
}
|
|
|
else {
|
|
|
setComponentList([]);
|
|
|
setTotal(0);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取组件市场数据失败:', error);
|
|
|
setComponentList([]);
|
|
|
setTotal(0);
|
|
|
} finally {
|
|
|
setLoading(false);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 监听分类、搜索条件变化
|
|
|
useEffect(() => {
|
|
|
setCurrent(1);
|
|
|
fetchComponentData(1);
|
|
|
}, [searchKeyword, selectedTab]);
|
|
|
|
|
|
// 处理分页变化
|
|
|
const handlePageChange = (page: number) => {
|
|
|
setCurrent(page);
|
|
|
fetchComponentData(page);
|
|
|
};
|
|
|
|
|
|
// 跳转到组件详情
|
|
|
const handleDetails = (component: ComponentItem) => {
|
|
|
selectedComp(component);
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<div className={styles['comp-card']}>
|
|
|
<Spin loading={loading} style={{ width: '100%' }}>
|
|
|
{componentList.length > 0 ? (
|
|
|
<>
|
|
|
<Row style={{ marginBottom: 16 }}>
|
|
|
{componentList.map((item) => (
|
|
|
<Col
|
|
|
xs={12}
|
|
|
sm={12}
|
|
|
md={12}
|
|
|
lg={6}
|
|
|
xl={6}
|
|
|
xxl={6}
|
|
|
key={item.id}
|
|
|
style={{ marginBottom: 16 }}
|
|
|
>
|
|
|
<Card
|
|
|
style={{ cursor: 'pointer', border: '1px solid #d9d9d9' }}
|
|
|
onClick={() => handleDetails(item)}
|
|
|
hoverable
|
|
|
>
|
|
|
{/*左侧图片*/}
|
|
|
<div className={styles['img-box']}>
|
|
|
<Image width={'100%'} height={'100%'} src={item.logoUrl} alt="暂无图片"></Image>
|
|
|
</div>
|
|
|
{/*右侧数据*/}
|
|
|
<div className={styles['info-box']}>
|
|
|
<div className={styles['info-title']}>{item.name || '未命名组件'}</div>
|
|
|
<div className={styles['info-author']}>{item.identifier || '-'}</div>
|
|
|
<div className={styles['info-score']}>
|
|
|
<div>组件评分:</div>
|
|
|
<div className={styles['info-rate']}>
|
|
|
{/*<Rate readonly allowHalf value={item.star || 5} />*/}
|
|
|
<Typography.Text style={{ margin: '0 5px', fontSize: 14 }}>
|
|
|
{item.star || 5}
|
|
|
</Typography.Text>
|
|
|
<IconStarFill
|
|
|
style={{ color: '#ffcd00' }} />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</Card>
|
|
|
<div className={styles['comp-card-footer']}>
|
|
|
<div className={styles['comp-type']}>{item.componentClassify || '-'}</div>
|
|
|
<div className={styles['comp-language']}>{item.codeLanguage || '-'}</div>
|
|
|
</div>
|
|
|
</Col>
|
|
|
))}
|
|
|
</Row>
|
|
|
|
|
|
{/* 分页组件 */}
|
|
|
{total > pageSize && (
|
|
|
<div style={{ display: 'flex', justifyContent: 'center', marginTop: 24 }}>
|
|
|
<Pagination
|
|
|
current={current}
|
|
|
pageSize={pageSize}
|
|
|
total={total}
|
|
|
onChange={handlePageChange}
|
|
|
showTotal
|
|
|
showJumper
|
|
|
sizeCanChange={false}
|
|
|
/>
|
|
|
</div>
|
|
|
)}
|
|
|
</>
|
|
|
) : (
|
|
|
<Empty description="暂无组件数据" />
|
|
|
)}
|
|
|
</Spin>
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
export default CompCard; |