// stats_page.dart — 统计页(指标卡 + 本周柱状图) import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../pangolin_theme.dart'; import '../state/app_providers.dart'; import '../widgets/app_top_bar.dart'; class StatsPage extends ConsumerWidget { const StatsPage({super.key, required this.isWide}); final bool isWide; static const _vals = [2.1, 3.4, 1.8, 4.6, 5.2, 6.1, 3.0]; @override Widget build(BuildContext context, WidgetRef ref) { final c = context.pangolin; final t = ref.watch(appTextProvider); final maxV = _vals.reduce((a, b) => a > b ? a : b); final pad = isWide ? 28.0 : 20.0; final metrics = [ (t.trafficMonth, '42.6', 'GB'), (t.avgPing, '29', 'ms'), (t.durMonth, '86.4', 'h'), ]; final body = ListView( padding: EdgeInsets.fromLTRB(pad, isWide ? 6 : 0, pad, 24), children: [ Row(children: [ for (var i = 0; i < metrics.length; i++) Expanded( child: Padding( padding: EdgeInsets.only(right: i < metrics.length - 1 ? 12 : 0), child: _MetricCard(label: metrics[i].$1, value: metrics[i].$2, unit: metrics[i].$3), ), ), ]), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: c.surface, borderRadius: BorderRadius.circular(PangolinRadius.lg), border: Border.all(color: c.border), boxShadow: PangolinShadow.sm, ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(t.weekTraffic, style: PangolinText.sm.copyWith(color: c.fg1, fontWeight: FontWeight.w600)), const SizedBox(height: 18), SizedBox( height: isWide ? 150 : 120, child: Row(crossAxisAlignment: CrossAxisAlignment.end, children: [ for (var i = 0; i < _vals.length; i++) Expanded( child: Column(mainAxisAlignment: MainAxisAlignment.end, children: [ Text('${_vals[i]}', style: PangolinText.mono.copyWith(fontSize: 11, color: c.fg3)), const SizedBox(height: 6), Container( height: (isWide ? 104 : 84) * (_vals[i] / maxV), margin: const EdgeInsets.symmetric(horizontal: 6), decoration: BoxDecoration( color: c.accent.withOpacity(0.85), borderRadius: const BorderRadius.vertical(top: Radius.circular(6)), ), ), const SizedBox(height: 6), Text(t.days7[i], style: PangolinText.caption.copyWith(color: c.fg3)), ]), ), ]), ), ]), ), ], ); if (isWide) return body; return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ AppTopBar(brand: t.brand), PageTitle(title: t.statsTitle), Expanded(child: body), ]); } } class _MetricCard extends StatelessWidget { const _MetricCard({required this.label, required this.value, required this.unit}); final String label, value, unit; @override Widget build(BuildContext context) { final c = context.pangolin; return Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: c.surface, borderRadius: BorderRadius.circular(PangolinRadius.lg), border: Border.all(color: c.border), boxShadow: PangolinShadow.sm, ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, overflow: TextOverflow.ellipsis, style: PangolinText.caption.copyWith(color: c.fg3, fontWeight: FontWeight.w600)), const SizedBox(height: 6), Text.rich(TextSpan( text: value, style: PangolinText.mono.copyWith(fontSize: 20, color: c.fg1, fontWeight: FontWeight.w500), children: [TextSpan(text: ' $unit', style: PangolinText.caption.copyWith(color: c.fg3))], )), ]), ); } }