191 lines
5.9 KiB
TypeScript
191 lines
5.9 KiB
TypeScript
/**
|
|
* Admin Analytics 数据分析页面
|
|
*/
|
|
import React from 'react';
|
|
import { Card, Row, Col, Statistic, Table, DatePicker, Space } from 'antd';
|
|
import {
|
|
LineChart,
|
|
Line,
|
|
BarChart,
|
|
Bar,
|
|
PieChart,
|
|
Pie,
|
|
Cell,
|
|
XAxis,
|
|
YAxis,
|
|
CartesianGrid,
|
|
Tooltip,
|
|
Legend,
|
|
ResponsiveContainer,
|
|
} from 'recharts';
|
|
import {
|
|
ArrowUpOutlined,
|
|
UserAddOutlined,
|
|
DollarOutlined,
|
|
ProjectOutlined,
|
|
} from '@ant-design/icons';
|
|
|
|
const { RangePicker } = DatePicker;
|
|
|
|
const Analytics: React.FC = () => {
|
|
// 模拟用户增长数据
|
|
const userGrowthData = [
|
|
{ month: '1月', users: 120, paid: 15 },
|
|
{ month: '2月', users: 180, paid: 28 },
|
|
{ month: '3月', users: 240, paid: 42 },
|
|
{ month: '4月', users: 320, paid: 58 },
|
|
{ month: '5月', users: 450, paid: 89 },
|
|
{ month: '6月', users: 620, paid: 135 },
|
|
];
|
|
|
|
// 模拟营收数据
|
|
const revenueData = [
|
|
{ month: '1月', revenue: 1480 },
|
|
{ month: '2月', revenue: 2770 },
|
|
{ month: '3月', revenue: 4160 },
|
|
{ month: '4月', revenue: 5740 },
|
|
{ month: '5月', revenue: 8810 },
|
|
{ month: '6月', revenue: 13365 },
|
|
];
|
|
|
|
// 订阅计划分布
|
|
const planDistribution = [
|
|
{ name: 'Free', value: 485, color: '#8884d8' },
|
|
{ name: 'Pro', value: 120, color: '#82ca9d' },
|
|
{ name: 'Enterprise', value: 15, color: '#ffc658' },
|
|
];
|
|
|
|
// 活跃度统计
|
|
const activityStats = [
|
|
{ metric: '日活跃用户 (DAU)', value: 892, growth: '+12.5%', icon: <UserAddOutlined /> },
|
|
{ metric: '月活跃用户 (MAU)', value: 3456, growth: '+8.3%', icon: <ArrowUpOutlined /> },
|
|
{ metric: '本月收入', value: 13365, prefix: '¥', growth: '+51.6%', icon: <DollarOutlined /> },
|
|
{ metric: '活跃项目数', value: 2341, growth: '+18.2%', icon: <ProjectOutlined /> },
|
|
];
|
|
|
|
// 用户留存表格
|
|
const retentionData = [
|
|
{ cohort: '2024-01', day1: '100%', day7: '68%', day30: '45%', day90: '28%' },
|
|
{ cohort: '2024-02', day1: '100%', day7: '72%', day30: '48%', day90: '31%' },
|
|
{ cohort: '2024-03', day1: '100%', day7: '75%', day30: '52%', day90: '-' },
|
|
{ cohort: '2024-04', day1: '100%', day7: '78%', day30: '55%', day90: '-' },
|
|
{ cohort: '2024-05', day1: '100%', day7: '80%', day30: '-', day90: '-' },
|
|
];
|
|
|
|
const retentionColumns = [
|
|
{ title: 'Cohort', dataIndex: 'cohort', key: 'cohort' },
|
|
{ title: 'Day 1', dataIndex: 'day1', key: 'day1' },
|
|
{ title: 'Day 7', dataIndex: 'day7', key: 'day7' },
|
|
{ title: 'Day 30', dataIndex: 'day30', key: 'day30' },
|
|
{ title: 'Day 90', dataIndex: 'day90', key: 'day90' },
|
|
];
|
|
|
|
return (
|
|
<div style={{ padding: '24px' }}>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
|
|
<h1>数据分析</h1>
|
|
<Space>
|
|
<RangePicker />
|
|
</Space>
|
|
</div>
|
|
|
|
{/* 关键指标 */}
|
|
<Row gutter={16} style={{ marginBottom: 24 }}>
|
|
{activityStats.map((stat, index) => (
|
|
<Col span={6} key={index}>
|
|
<Card>
|
|
<Statistic
|
|
title={stat.metric}
|
|
value={stat.value}
|
|
prefix={stat.prefix}
|
|
suffix={stat.icon}
|
|
valueStyle={{ color: '#3f8600' }}
|
|
/>
|
|
<div style={{ marginTop: 8, color: '#52c41a', fontSize: 14 }}>
|
|
{stat.growth} vs 上月
|
|
</div>
|
|
</Card>
|
|
</Col>
|
|
))}
|
|
</Row>
|
|
|
|
{/* 图表区域 */}
|
|
<Row gutter={16} style={{ marginBottom: 24 }}>
|
|
{/* 用户增长趋势 */}
|
|
<Col span={16}>
|
|
<Card title="用户增长趋势">
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<LineChart data={userGrowthData}>
|
|
<CartesianGrid strokeDasharray="3 3" />
|
|
<XAxis dataKey="month" />
|
|
<YAxis />
|
|
<Tooltip />
|
|
<Legend />
|
|
<Line type="monotone" dataKey="users" stroke="#8884d8" name="总用户" />
|
|
<Line type="monotone" dataKey="paid" stroke="#82ca9d" name="付费用户" />
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</Card>
|
|
</Col>
|
|
|
|
{/* 订阅计划分布 */}
|
|
<Col span={8}>
|
|
<Card title="订阅计划分布">
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<PieChart>
|
|
<Pie
|
|
data={planDistribution}
|
|
cx="50%"
|
|
cy="50%"
|
|
labelLine={false}
|
|
label={(entry) => `${entry.name}: ${entry.value}`}
|
|
outerRadius={80}
|
|
fill="#8884d8"
|
|
dataKey="value"
|
|
>
|
|
{planDistribution.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip />
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
|
|
{/* 营收趋势 */}
|
|
<Row gutter={16} style={{ marginBottom: 24 }}>
|
|
<Col span={24}>
|
|
<Card title="营收趋势">
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<BarChart data={revenueData}>
|
|
<CartesianGrid strokeDasharray="3 3" />
|
|
<XAxis dataKey="month" />
|
|
<YAxis />
|
|
<Tooltip />
|
|
<Legend />
|
|
<Bar dataKey="revenue" fill="#ffc658" name="收入 (¥)" />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
|
|
{/* 用户留存表 */}
|
|
<Card title="用户留存率 (Cohort Analysis)">
|
|
<Table
|
|
columns={retentionColumns}
|
|
dataSource={retentionData}
|
|
rowKey="cohort"
|
|
pagination={false}
|
|
/>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Analytics;
|
|
|
|
export const Component = Analytics;
|