import 'package:provider/provider.dart'; import 'package:blog_app/provider/blog.dart'; import 'package:blog_app/widget/blog.dart'; import 'package:blog_app/widget/common.dart'; import 'package:blog_app/widget/year_selector.dart'; import 'package:flutter/material.dart'; import 'package:timelines_plus/timelines_plus.dart'; class TimelinePage extends StatefulWidget { const TimelinePage({super.key}); @override State createState() => TimelinePageState(); } class TimelinePageState extends State { @override void initState() { super.initState(); // 初始化加载数据 WidgetsBinding.instance.addPostFrameCallback((_) { context.read().refreshBlogByYear(); }); } Widget _buildBlogList(BlogProvider provider) { final colors = Theme.of(context).colorScheme; return Timeline.tileBuilder( theme: TimelineThemeData(nodePosition: 0, indicatorPosition: 0), padding: EdgeInsets.all(6), builder: TimelineTileBuilder.connected( itemCount: provider.blogList.length, connectorBuilder: (context, index, type) => Connector.solidLine(thickness: 2, color: colors.primary), indicatorBuilder: (context, index) { return Indicator.dot(size: 12.0, color: colors.primary); }, contentsBuilder: (context, index) { final blog = provider.blogList[index]; return InkWell( onTap: () => navigatorToBlogDetail(context, blog.id), child: buildBlogListItem(context, blog, index + 1), ); }, ), ); } Widget _buildContent(BlogProvider provider) { if (provider.error != null) { return buildErrorInfo( errorInfo: provider.error!, onPressed: () => provider.refreshBlogByYear(), ); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ YearSelector( initialYear: DateTime.now().year, minYear: 2000, maxYear: 2100, onYearChanged: (year) { setState(() { provider.currentYear = year; provider.refreshBlogByYear(); }); }, ), const SizedBox(height: 8), buildListTitle(provider.blogList.length), const SizedBox(height: 8), Expanded( child: provider.blogList.isEmpty ? buildEmpty() : _buildBlogList(provider), ), ], ); } @override Widget build(BuildContext context) { final blogProvider = context.watch(); return Column( children: [ Expanded( child: Stack( children: [ if (blogProvider.isLoading) buildLoadingIndicator() else _buildContent(blogProvider), ], ), ), ], ); } }