77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { View, Text } from '@tarojs/components';
|
|
import HqHeader from '../../components/HqHeader';
|
|
import { request } from '../../lib/api';
|
|
import { useHqSession } from '../../lib/session';
|
|
import { ORDER_STATUS_LABELS } from '../../lib/constants';
|
|
import './index.css';
|
|
|
|
type Stats = {
|
|
usersTotal: number;
|
|
guestUsers: number;
|
|
verifiedUsers: number;
|
|
ordersToday: number;
|
|
storesTotal: number;
|
|
partnersTotal: number;
|
|
redeemToday: number;
|
|
deliveriesTotal: number;
|
|
mergedUsers: number;
|
|
ordersByStatus: Array<{ status: string; count: number }>;
|
|
};
|
|
|
|
export default function ReportsPage() {
|
|
useHqSession();
|
|
const [stats, setStats] = useState<Stats | null>(null);
|
|
|
|
useEffect(() => {
|
|
request<Stats>('/admin/dashboard/stats').then(setStats).catch(() => undefined);
|
|
}, []);
|
|
|
|
const dist = stats?.ordersByStatus ?? [];
|
|
const max = Math.max(1, ...dist.map((d) => d.count));
|
|
|
|
return (
|
|
<View className="hq-page">
|
|
<HqHeader title="数据报表" back />
|
|
|
|
<Text className="hq-section-title">核心指标</Text>
|
|
<View className="hq-stat-grid">
|
|
<View className="hq-stat">
|
|
<Text className="hq-stat__label">有效用户</Text>
|
|
<Text className="hq-stat__value">{stats?.usersTotal ?? 0}</Text>
|
|
<Text className="hq-stat__sub">已验手机 {stats?.verifiedUsers ?? 0}</Text>
|
|
</View>
|
|
<View className="hq-stat">
|
|
<Text className="hq-stat__label">今日下单</Text>
|
|
<Text className="hq-stat__value">{stats?.ordersToday ?? 0}</Text>
|
|
<Text className="hq-stat__sub">今日核销 {stats?.redeemToday ?? 0}</Text>
|
|
</View>
|
|
<View className="hq-stat">
|
|
<Text className="hq-stat__label">门店 / 合伙人</Text>
|
|
<Text className="hq-stat__value">{stats?.storesTotal ?? 0}/{stats?.partnersTotal ?? 0}</Text>
|
|
<Text className="hq-stat__sub">配送单 {stats?.deliveriesTotal ?? 0}</Text>
|
|
</View>
|
|
<View className="hq-stat">
|
|
<Text className="hq-stat__label">访客未验证</Text>
|
|
<Text className="hq-stat__value">{stats?.guestUsers ?? 0}</Text>
|
|
<Text className="hq-stat__sub">已合并 {stats?.mergedUsers ?? 0}</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<Text className="hq-section-title">订单状态分布</Text>
|
|
<View className="hq-card">
|
|
{dist.length === 0 && <Text className="hq-muted">暂无数据</Text>}
|
|
{dist.map((d) => (
|
|
<View key={d.status} className="report-bar-row">
|
|
<Text className="report-bar-label">{ORDER_STATUS_LABELS[d.status] || d.status}</Text>
|
|
<View className="report-bar-track">
|
|
<View className="report-bar-fill" style={`width:${(d.count / max) * 100}%`} />
|
|
</View>
|
|
<Text className="report-bar-count">{d.count}</Text>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|