import 'package:blog_app/apis/blog.dart'; import 'package:blog_app/models/blog.dart'; import 'package:blog_app/models/common.dart'; import 'package:blog_app/widget/chart.dart'; import 'package:blog_app/widget/common.dart'; import 'package:blog_app/widget/year_selector.dart'; import 'package:flutter/material.dart'; class StatsPage extends StatefulWidget { const StatsPage({super.key}); @override StatsPageState createState() => StatsPageState(); } class StatsPageState extends State { final double chartHeight = 400; final double statsHeight = 120; int currentYear = DateTime.now().year; late List approvedStats = []; late List visitStats = []; late List visitRankStats = []; late List categoryStats = []; late List readRankStats = []; late BlogStats overviewStats = BlogStats( blogCount: 0, categoryCount: 0, greatCount: 0, visitCount: 0, wordCount: 0, ); @override void initState() { super.initState(); _loadStatsList(); } Future _loadStatsList() async { try { final approvedResult = await queryBlogApprovedStatsApi(currentYear); final visitResult = await queryBlogVisitStatsApi(currentYear); final visitRankResult = await queryBlogVisitRankStatsApi(); final categoryResult = await queryBlogCategoryStatsApi(); final readRankResult = await queryBlogReadRankStatsApi(); final overviewResult = await queryBlogOverviewStatsApi(); setState(() { approvedStats = approvedResult; visitStats = visitResult; visitRankStats = visitRankResult; categoryStats = categoryResult; readRankStats = readRankResult; overviewStats = overviewResult; }); } catch (e) { throw Exception('获取统计数据失败: $e'); } } Widget _buildApprovedStats(BuildContext context) { return Column( children: [ buildChartTitle(context, '每月博客发布统计', Icons.show_chart), const SizedBox(height: 3), buildChartDivider(context), const SizedBox(height: 3), Expanded( child: lineChart( context: context, xAxisName: '月份', yAxisName: '数量', unit: '篇', data: approvedStats, ), ), ], ); } Widget _buildVisitStats(BuildContext context) { return Column( children: [ buildChartTitle(context, '每月博客访问统计', Icons.show_chart), const SizedBox(height: 3), buildChartDivider(context), const SizedBox(height: 3), Expanded( child: lineChart( context: context, xAxisName: '月份', yAxisName: '访问量', unit: '人次', data: visitStats, ), ), ], ); } Widget _buildVisitRankStats(BuildContext context) { return Column( children: [ buildChartTitle(context, '博客访问数量排行', Icons.bar_chart), const SizedBox(height: 3), buildChartDivider(context), const SizedBox(height: 3), Expanded( child: barChart( context: context, xAxisName: '名称', yAxisName: '访问量', unit: '人次', data: visitRankStats, ), ), ], ); } Widget _buildCategoryStats(BuildContext context) { return Column( children: [ buildChartTitle(context, '博客类别统计', Icons.pie_chart), const SizedBox(height: 3), buildChartDivider(context), const SizedBox(height: 3), Expanded( child: pieChart(context: context, unit: '篇', data: categoryStats), ), ], ); } Widget _buildReadRankStats(BuildContext context) { return Column( children: [ buildChartTitle(context, '博客阅读时长排行', Icons.bar_chart), const SizedBox(height: 3), buildChartDivider(context), const SizedBox(height: 3), Expanded( child: barChart( context: context, xAxisName: '名称', yAxisName: '时长', unit: '分钟', data: readRankStats, ), ), ], ); } Widget buildStatsCard({ required BuildContext context, required String title, required int count, required String unit, }) { return buildCard( context: context, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( title, style: TextStyle( fontSize: 16, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( count.toString(), style: const TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.black87, height: 1.0, ), ), const SizedBox(width: 4), Text( unit, style: TextStyle( fontSize: 14, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), ], ), ], ), ); } Widget buildBlogStatsGrid(BuildContext context) { return GridView.count( crossAxisCount: 2, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), childAspectRatio: 2, children: [ buildStatsCard( context: context, title: '博客数量', count: overviewStats.blogCount, unit: '篇', ), buildStatsCard( context: context, title: '分类数量', count: overviewStats.categoryCount, unit: '个', ), buildStatsCard( context: context, title: '访问量', count: overviewStats.visitCount, unit: '次', ), buildStatsCard( context: context, title: '总字数', count: overviewStats.wordCount, unit: '字', ), ], ); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Column( children: [ YearSelector( initialYear: DateTime.now().year, minYear: 2000, maxYear: 2100, onYearChanged: (year) => { setState(() { currentYear = year; _loadStatsList(); }), }, ), SizedBox(height: 6), buildBlogStatsGrid(context), SizedBox(height: 6), SizedBox( height: chartHeight, child: buildCard( context: context, child: _buildApprovedStats(context), ), ), SizedBox(height: 6), SizedBox( height: chartHeight, child: buildCard( context: context, child: _buildVisitStats(context), ), ), SizedBox(height: 6), SizedBox( height: chartHeight, child: buildCard( context: context, child: _buildVisitRankStats(context), ), ), SizedBox(height: 6), SizedBox( height: chartHeight, child: buildCard( context: context, child: _buildCategoryStats(context), ), ), SizedBox(height: 6), SizedBox( height: chartHeight, child: buildCard( context: context, child: _buildReadRankStats(context), ), ), ], ), ); } }