首次提交
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { api } from '../services/api'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
export default function Dashboard() {
|
||||
const [stats, setStats] = useState<any>(null)
|
||||
const [recentUsers, setRecentUsers] = useState<any[]>([])
|
||||
const [recentPosts, setRecentPosts] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
api.get<any>('/api/admin/dashboard'),
|
||||
api.get<any>('/api/admin/users?page=1&pageSize=5'),
|
||||
api.get<any>('/api/admin/posts?page=1&pageSize=5'),
|
||||
]).then(([dashData, usersData, postsData]) => {
|
||||
setStats({
|
||||
totalUsers: dashData.totalUsers || 0,
|
||||
totalPosts: dashData.totalPosts || 0,
|
||||
totalCheckins: dashData.totalRecords || 0,
|
||||
totalItems: dashData.totalItems || 0,
|
||||
newUsersToday: dashData.newUsersToday || 0,
|
||||
})
|
||||
setRecentUsers(usersData.list || [])
|
||||
setRecentPosts(postsData.list || [])
|
||||
}).catch(() => {
|
||||
setStats({ totalUsers: 0, totalPosts: 0, totalCheckins: 0, totalItems: 0, newUsersToday: 0 })
|
||||
}).finally(() => setLoading(false))
|
||||
}, [])
|
||||
|
||||
if (loading) return <div style={{ textAlign: 'center', padding: 40, color: '#86868B' }}>加载中...</div>
|
||||
if (!stats) return <div style={{ textAlign: 'center', padding: 40, color: '#86868B' }}>暂无数据</div>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className='page-title'>数据概览</h1>
|
||||
|
||||
{/* 统计卡片 */}
|
||||
<div className='stat-grid'>
|
||||
<div className='stat-card' onClick={() => navigate('/users')} style={{ cursor: 'pointer' }}>
|
||||
<div className='stat-value'>{stats.totalUsers}</div>
|
||||
<div className='stat-label'>总用户数</div>
|
||||
</div>
|
||||
<div className='stat-card' onClick={() => navigate('/users')} style={{ cursor: 'pointer' }}>
|
||||
<div className='stat-value'>{stats.newUsersToday}</div>
|
||||
<div className='stat-label'>今日新增</div>
|
||||
</div>
|
||||
<div className='stat-card'>
|
||||
<div className='stat-value'>{stats.totalCheckins}</div>
|
||||
<div className='stat-label'>总打卡次数</div>
|
||||
</div>
|
||||
<div className='stat-card'>
|
||||
<div className='stat-value'>{stats.totalItems}</div>
|
||||
<div className='stat-label'>总打卡项</div>
|
||||
</div>
|
||||
<div className='stat-card' onClick={() => navigate('/posts')} style={{ cursor: 'pointer' }}>
|
||||
<div className='stat-value'>{stats.totalPosts}</div>
|
||||
<div className='stat-label'>动态总数</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
|
||||
{/* 最近用户 */}
|
||||
<div className='card'>
|
||||
<h3 style={{ marginBottom: 12, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span>最近注册</span>
|
||||
<a href='/users' style={{ fontSize: 13, color: '#FF6B35', textDecoration: 'none' }}>查看全部 →</a>
|
||||
</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>昵称</th><th>手机号</th><th>积分</th><th>时间</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{recentUsers.map((u: any) => (
|
||||
<tr key={u.id}>
|
||||
<td>{u.nickname || '--'}</td>
|
||||
<td>{u.phone || '--'}</td>
|
||||
<td>{u.points}</td>
|
||||
<td style={{ fontSize: 12 }}>{u.createdAt?.slice(0, 10) || '--'}</td>
|
||||
</tr>
|
||||
))}
|
||||
{recentUsers.length === 0 && <tr><td colSpan={4} style={{ textAlign: 'center', color: '#86868B' }}>暂无用户</td></tr>}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* 最近动态 */}
|
||||
<div className='card'>
|
||||
<h3 style={{ marginBottom: 12, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span>最新动态</span>
|
||||
<a href='/posts' style={{ fontSize: 13, color: '#FF6B35', textDecoration: 'none' }}>查看全部 →</a>
|
||||
</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>内容</th><th>用户</th><th>时间</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{recentPosts.map((p: any) => (
|
||||
<tr key={p.id}>
|
||||
<td style={{ maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.content || '--'}</td>
|
||||
<td>{p.user?.nickname || '--'}</td>
|
||||
<td style={{ fontSize: 12 }}>{p.createdAt?.slice(0, 10) || '--'}</td>
|
||||
</tr>
|
||||
))}
|
||||
{recentPosts.length === 0 && <tr><td colSpan={3} style={{ textAlign: 'center', color: '#86868B' }}>暂无动态</td></tr>}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user