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:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user