👨🏻‍💻👩🏻‍💻 Use Ant Design like a Pro!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

297 lines
8.3 KiB

import { Radar } from '@ant-design/plots';
import { PageContainer } from '@ant-design/pro-components';
import { Link, useRequest } from '@umijs/max';
import { Avatar, Card, Col, List, Row, Skeleton, Statistic } from 'antd';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import type { FC } from 'react';
import EditableLinkGroup from './components/EditableLinkGroup';
import type { ActivitiesType, CurrentUser } from './data.d';
import { fakeChartData, queryActivities, queryProjectNotice } from './service';
import useStyles from './style.style';
dayjs.extend(relativeTime);
const links = [
{
title: '操作一',
href: '',
},
{
title: '操作二',
href: '',
},
{
title: '操作三',
href: '',
},
{
title: '操作四',
href: '',
},
{
title: '操作五',
href: '',
},
{
title: '操作六',
href: '',
},
];
const PageHeaderContent: FC<{
currentUser: Partial<CurrentUser>;
}> = ({ currentUser }) => {
const { styles } = useStyles();
const loading = currentUser && Object.keys(currentUser).length;
if (!loading) {
return (
<Skeleton
avatar
paragraph={{
rows: 1,
}}
active
/>
);
}
return (
<div className={styles.pageHeaderContent}>
<div className={styles.avatar}>
<Avatar size="large" src={currentUser.avatar} />
</div>
<div className={styles.content}>
<div className={styles.contentTitle}>
{currentUser.name}
</div>
<div>
{currentUser.title} |{currentUser.group}
</div>
</div>
</div>
);
};
const ExtraContent: FC<Record<string, any>> = () => {
const { styles } = useStyles();
return (
<div className={styles.extraContent}>
<div className={styles.statItem}>
<Statistic title="项目数" value={56} />
</div>
<div className={styles.statItem}>
<Statistic title="团队内排名" value={8} suffix="/ 24" />
</div>
<div className={styles.statItem}>
<Statistic title="项目访问" value={2223} />
</div>
</div>
);
};
const Workplace: FC = () => {
const { styles } = useStyles();
const { loading: projectLoading, data: projectNotice = [] } =
useRequest(queryProjectNotice);
const { loading: activitiesLoading, data: activities = [] } =
useRequest(queryActivities);
const { data } = useRequest(fakeChartData);
const renderActivities = (item: ActivitiesType) => {
const events = item.template.split(/@\{([^{}]*)\}/gi).map((key) => {
if (item[key as keyof ActivitiesType]) {
const value = item[key as 'user'];
return (
<a href={value?.link} key={value?.name}>
{value.name}
</a>
);
}
return key;
});
return (
<List.Item key={item.id}>
<List.Item.Meta
avatar={<Avatar src={item.user.avatar} />}
title={
<span>
<a className={styles.username}>{item.user.name}</a>
&nbsp;
<span className={styles.event}>{events}</span>
</span>
}
description={
<span className={styles.datetime} title={item.updatedAt}>
{dayjs(item.updatedAt).fromNow()}
</span>
}
/>
</List.Item>
);
};
return (
<PageContainer
content={
<PageHeaderContent
currentUser={{
avatar:
'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
name: '吴彦祖',
userid: '00000001',
email: 'antdesign@alipay.com',
signature: '海纳百川,有容乃大',
title: '交互专家',
group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED',
}}
/>
}
extraContent={<ExtraContent />}
>
<Row gutter={24}>
<Col xl={16} lg={24} md={24} sm={24} xs={24}>
<Card
className={styles.projectList}
style={{
marginBottom: 24,
}}
title="进行中的项目"
bordered={false}
extra={<Link to="/"></Link>}
loading={projectLoading}
bodyStyle={{
padding: 0,
}}
>
{projectNotice.map((item) => (
<Card.Grid className={styles.projectGrid} key={item.id}>
<Card
bodyStyle={{
padding: 0,
}}
bordered={false}
>
<Card.Meta
title={
<div className={styles.cardTitle}>
<Avatar size="small" src={item.logo} />
<Link to={item.href || '/'}>{item.title}</Link>
</div>
}
description={item.description}
style={{
width: '100%',
}}
/>
<div className={styles.projectItemContent}>
<Link to={item.memberLink || '/'}>{item.member || ''}</Link>
{item.updatedAt && (
<span className={styles.datetime} title={item.updatedAt}>
{dayjs(item.updatedAt).fromNow()}
</span>
)}
</div>
</Card>
</Card.Grid>
))}
</Card>
<Card
bodyStyle={{
padding: 0,
}}
bordered={false}
className={styles.activeCard}
title="动态"
loading={activitiesLoading}
>
<List<ActivitiesType>
loading={activitiesLoading}
renderItem={(item) => renderActivities(item)}
dataSource={activities}
className={styles.activitiesList}
size="large"
/>
</Card>
</Col>
<Col xl={8} lg={24} md={24} sm={24} xs={24}>
<Card
style={{
marginBottom: 24,
}}
title="快速开始 / 便捷导航"
bordered={false}
bodyStyle={{
padding: 0,
}}
>
<EditableLinkGroup
onAdd={() => {}}
links={links}
linkElement={Link}
/>
</Card>
<Card
style={{
marginBottom: 24,
}}
bordered={false}
title="XX 指数"
loading={data?.radarData?.length === 0}
>
<div>
<Radar
height={343}
data={data?.radarData || []}
xField="label"
colorField="name"
yField="value"
shapeField="smooth"
area={{
style: {
fillOpacity: 0.4,
},
}}
axis={{
y: {
gridStrokeOpacity: 0.5,
},
}}
legend={{
color: {
position: 'bottom',
layout: { justifyContent: 'center' },
},
}}
/>
</div>
</Card>
<Card
bodyStyle={{
paddingTop: 12,
paddingBottom: 12,
}}
bordered={false}
title="团队"
loading={projectLoading}
>
<div className={styles.members}>
<Row gutter={48}>
{projectNotice.map((item) => {
return (
<Col span={12} key={`members-item-${item.id}`}>
<a>
<Avatar src={item.logo} size="small" />
<span className={styles.member}>
{item.member.substring(0, 3)}
</span>
</a>
</Col>
);
})}
</Row>
</div>
</Card>
</Col>
</Row>
</PageContainer>
);
};
export default Workplace;