Files
dukang/apps/mini-hq/src/pages/reports/index.tsx
T

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>
);
}