You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.4 KiB
TypeScript
135 lines
3.4 KiB
TypeScript
import React, { useState, useEffect, ReactNode } from 'react';
|
|
import {
|
|
Grid,
|
|
Card,
|
|
Typography,
|
|
Divider,
|
|
Skeleton,
|
|
Link
|
|
} from '@arco-design/web-react';
|
|
import { useSelector } from 'react-redux';
|
|
import axios from 'axios';
|
|
import locale from './locale';
|
|
import useLocale from '@/utils/useLocale';
|
|
import styles from './style/overview.module.less';
|
|
import IconCalendar from './assets/calendar.svg';
|
|
import IconComments from './assets/comments.svg';
|
|
import IconContent from './assets/content.svg';
|
|
import IconIncrease from './assets/increase.svg';
|
|
import HeatMap from '@/components/Chart/heat-map';
|
|
import { getOverviewHome } from '@/api/overview';
|
|
|
|
const { Row, Col } = Grid;
|
|
|
|
type StatisticItemType = {
|
|
icon?: ReactNode;
|
|
title?: ReactNode;
|
|
count?: ReactNode;
|
|
loading?: boolean;
|
|
unit?: ReactNode;
|
|
};
|
|
|
|
function StatisticItem(props: StatisticItemType) {
|
|
const { icon, title, count, loading, unit } = props;
|
|
return (
|
|
<div className={styles.item}>
|
|
<div className={styles.icon}>{icon}</div>
|
|
<div>
|
|
<Skeleton loading={loading} text={{ rows: 2, width: 60 }} animation>
|
|
<div className={styles.title}>{title}</div>
|
|
<div className={styles.count}>
|
|
{count}
|
|
<span className={styles.unit}>{unit}</span>
|
|
</div>
|
|
</Skeleton>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
type DataType = {
|
|
sceneNum?: string | number;
|
|
compNum?: string | number;
|
|
appNum?: string | number;
|
|
instanceNum?: string | number;
|
|
chartData?: { count?: number; date?: string }[];
|
|
down?: boolean;
|
|
};
|
|
|
|
function Overview() {
|
|
const [data, setData] = useState<DataType>({});
|
|
const [loading, setLoading] = useState(true);
|
|
const t = useLocale(locale);
|
|
|
|
const userInfo = useSelector((state: any) => state.user?.userInfo || {});
|
|
|
|
const fetchData = async () => {
|
|
setLoading(true);
|
|
const res: any = await getOverviewHome();
|
|
if (res.code === 200) setData(res.data);
|
|
setLoading(false);
|
|
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, []);
|
|
|
|
return (
|
|
<Card>
|
|
<Typography.Title heading={5}>
|
|
{t['workplace.welcomeBack']}
|
|
{userInfo.username}
|
|
</Typography.Title>
|
|
<Divider />
|
|
<Row>
|
|
<Col flex={1}>
|
|
<StatisticItem
|
|
icon={<IconCalendar />}
|
|
title="工程数量"
|
|
count={data.sceneNum}
|
|
loading={loading}
|
|
unit={t['workplace.pecs']}
|
|
/>
|
|
</Col>
|
|
<Divider type="vertical" className={styles.divider} />
|
|
<Col flex={1}>
|
|
<StatisticItem
|
|
icon={<IconContent />}
|
|
title="组件数量"
|
|
count={data.compNum}
|
|
loading={loading}
|
|
unit={t['workplace.pecs']}
|
|
/>
|
|
</Col>
|
|
<Divider type="vertical" className={styles.divider} />
|
|
<Col flex={1}>
|
|
<StatisticItem
|
|
icon={<IconComments />}
|
|
title="应用数量"
|
|
count={data.appNum}
|
|
loading={loading}
|
|
unit={t['workplace.pecs']}
|
|
/>
|
|
</Col>
|
|
<Divider type="vertical" className={styles.divider} />
|
|
<Col flex={1}>
|
|
<StatisticItem
|
|
icon={<IconIncrease />}
|
|
title="应用实例数量"
|
|
count={data.instanceNum}
|
|
loading={loading}
|
|
/>
|
|
</Col>
|
|
</Row>
|
|
<Divider />
|
|
<div>
|
|
{/*热力图*/}
|
|
<HeatMap></HeatMap>
|
|
</div>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
export default Overview;
|