Files
shaguabijia-admin-web/src/app/(main)/dashboard/page.tsx
T
OuYingJun1024 8c31cecb37 feat(dashboard): 首页轮播种子管理 + 三统计配置增强
数据大盘新增/增强两块运营配置:
- 首页轮播种子(新):列表/新增/编辑/批量生成/预览效果;用户名可空(留空自动合成)、金额区间(min~max)
- 首页数据配置(增强):自增长「百分比/固定增量」切换、真实值基数偏移、「允许数字下降」(只增不减)开关、下次预计值、立即更新二次确认;倍率上限 1.5
- 依赖 @ant-design/v5-patch-for-react-19(React 19 兼容,providers 顶部 import)
- start.sh/stop.sh 跨平台重写;.run-logs/ 加入 .gitignore

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:14:06 +08:00

63 lines
2.3 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { Alert, Card, Col, Row, Spin, Statistic } from 'antd';
import { api } from '@/lib/api';
import type { DashboardOverview } from '@/lib/types';
import HomeStatsConfig from './HomeStatsConfig';
import HomeMarqueeSeeds from './HomeMarqueeSeeds';
const yuan = (cents: number) => `¥${(cents / 100).toFixed(2)}`;
export default function DashboardPage() {
const [data, setData] = useState<DashboardOverview | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
api
.get<DashboardOverview>('/admin/api/stats/overview')
.then((r) => setData(r.data))
.finally(() => setLoading(false));
}, []);
if (loading || !data) return <Spin style={{ display: 'block', marginTop: 80 }} />;
const cards: { title: string; value: string | number; suffix?: string; danger?: boolean }[] = [
{ title: '总用户', value: data.users.total },
{ title: '今日活跃 DAU', value: data.users.dau },
{ title: '今日新增', value: data.users.new_today },
{ title: '封禁用户', value: data.users.disabled, danger: data.users.disabled > 0 },
{ title: '累计发放金币', value: data.coins.granted_total },
{ title: '累计成功提现', value: yuan(data.cash.withdraw_success_cents) },
{ title: '待处理提现', value: data.cash.withdraw_pending_count, danger: data.cash.withdraw_pending_count > 0 },
{ title: '比价成功率', value: (data.comparison.success_rate * 100).toFixed(1), suffix: '%' },
{ title: '比价总次数', value: data.comparison.total },
{ title: '待处理反馈', value: data.feedback.new, danger: data.feedback.new > 0 },
];
return (
<div>
<h2></h2>
<Row gutter={[16, 16]}>
{cards.map((c) => (
<Col key={c.title} xs={12} sm={8} md={6} xl={4}>
<Card>
<Statistic
title={c.title}
value={c.value}
suffix={c.suffix}
valueStyle={c.danger ? { color: '#cf1322' } : undefined}
/>
</Card>
</Col>
))}
</Row>
{!data.cps.available && (
<Alert style={{ marginTop: 16 }} type="info" showIcon message={`CPS 收入:${data.cps.note}`} />
)}
<HomeStatsConfig />
<HomeMarqueeSeeds />
</div>
);
}