feat(web): wire Home dashboard to real API data

Replace hardcoded placeholder values with live data fetched from
/users, /roles, /workflow/instances, and message store unread count.
Uses Promise.allSettled for resilient parallel loading.
This commit is contained in:
iven
2026-04-11 14:37:52 +08:00
parent 4bfd9573db
commit c02fcecbfc

View File

@@ -1,37 +1,97 @@
import { Typography, Card, Row, Col, Statistic } from 'antd';
import { useEffect, useState } from 'react';
import { Typography, Card, Row, Col, Statistic, Spin } from 'antd';
import {
UserOutlined,
TeamOutlined,
FileTextOutlined,
BellOutlined,
} from '@ant-design/icons';
import client from '../api/client';
import { useMessageStore } from '../stores/message';
interface DashboardStats {
userCount: number;
roleCount: number;
processInstanceCount: number;
unreadMessages: number;
}
export default function Home() {
const [stats, setStats] = useState<DashboardStats>({
userCount: 0,
roleCount: 0,
processInstanceCount: 0,
unreadMessages: 0,
});
const [loading, setLoading] = useState(true);
const { unreadCount, fetchUnreadCount } = useMessageStore();
useEffect(() => {
async function loadStats() {
setLoading(true);
try {
// 并行请求各模块统计数据
const [usersRes, rolesRes, instancesRes] = await Promise.allSettled([
client.get('/users', { params: { page: 1, page_size: 1 } }),
client.get('/roles', { params: { page: 1, page_size: 1 } }),
client.get('/workflow/instances', { params: { page: 1, page_size: 1 } }),
]);
const extractTotal = (res: PromiseSettledResult<{ data: { data?: { total?: number } } }>) =>
res.status === 'fulfilled' ? (res.value.data?.data?.total ?? 0) : 0;
setStats({
userCount: extractTotal(usersRes),
roleCount: extractTotal(rolesRes),
processInstanceCount: extractTotal(instancesRes),
unreadMessages: unreadCount,
});
} catch {
// 静默处理,显示默认值
} finally {
setLoading(false);
}
}
fetchUnreadCount();
loadStats();
}, [fetchUnreadCount, unreadCount]);
return (
<div>
<Typography.Title level={4}></Typography.Title>
<Spin spinning={loading}>
<Row gutter={[16, 16]}>
<Col xs={24} sm={12} md={6}>
<Card>
<Statistic title="用户总数" value={0} prefix={<UserOutlined />} />
<Statistic title="用户总数" value={stats.userCount} prefix={<UserOutlined />} />
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card>
<Statistic title="角色数量" value={0} prefix={<TeamOutlined />} />
<Statistic title="角色数量" value={stats.roleCount} prefix={<TeamOutlined />} />
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card>
<Statistic title="流程实例" value={0} prefix={<FileTextOutlined />} />
<Statistic
title="流程实例"
value={stats.processInstanceCount}
prefix={<FileTextOutlined />}
/>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card>
<Statistic title="未读消息" value={0} prefix={<BellOutlined />} />
<Statistic
title="未读消息"
value={stats.unreadMessages}
prefix={<BellOutlined />}
/>
</Card>
</Col>
</Row>
</Spin>
</div>
);
}