import 'package:blog_app/models/blog.dart'; import 'package:blog_app/pages/blog_detail_page.dart'; import 'package:blog_app/pages/category_list_page.dart'; import 'package:blog_app/utils/date_utils.dart'; import 'package:blog_app/widget/common.dart'; import 'package:flutter/material.dart'; class BlogLabel { final String text; final IconData icon; final Color color; BlogLabel(this.text, this.icon, this.color); } class BlogCard extends StatelessWidget { final Blog blog; const BlogCard({super.key, required this.blog}); Widget _buildBlogLabelItem(String text, IconData icon, Color color) { return Container( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: color.withAlpha(30), borderRadius: BorderRadius.circular(8), border: Border.all(color: color.withAlpha(20), width: 1), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 12, color: color), SizedBox(width: 4), Text( text, style: TextStyle( fontSize: 10, color: color, fontWeight: FontWeight.w500, ), ), ], ), ); } Widget _buildBlogLabel() { return SizedBox( width: double.infinity, child: Wrap( spacing: 6, runSpacing: 6, alignment: WrapAlignment.center, children: [ if (blog.isGreat) _buildBlogLabelItem('精品', Icons.workspace_premium, Colors.deepOrange), if (blog.topValue > 1) _buildBlogLabelItem('置顶', Icons.push_pin, Colors.red), _buildBlogLabelItem(blog.category, Icons.folder, Colors.blue), _buildBlogLabelItem( formatDateString(blog.createTime), Icons.calendar_today, Colors.green, ), _buildBlogLabelItem( formatDateString(blog.updateTime), Icons.calendar_month, Colors.orange, ), _buildBlogLabelItem( '${blog.visitCount} 次', Icons.remove_red_eye, Colors.purple, ), _buildBlogLabelItem( '${blog.wordCount} 字', Icons.text_fields, Colors.indigo, ), _buildBlogLabelItem( '${blog.readDuration} 分钟', Icons.access_time, Colors.brown, ), ], ), ); } Widget _buildBlogTitle(BuildContext context) { return Text( blog.title, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary, ), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ); } Widget _buildBlogSummary() { return SizedBox( width: double.infinity, child: Text( blog.summary, style: TextStyle(color: Colors.grey.shade700, height: 1.6), overflow: TextOverflow.ellipsis, ), ); } @override Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; return BuildCard( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildBlogTitle(context), SizedBox(height: 16), _buildBlogLabel(), SizedBox(height: 16), Container(height: 1, width: 80, color: colors.primary), SizedBox(height: 16), _buildBlogSummary(), ], ), ); } } Widget buildCategoryTitle(BuildContext context, int count) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular(8), ), child: Text( '共 $count 个分类', style: const TextStyle( fontWeight: FontWeight.w500, color: Colors.white, ), ), ), ], ); } Widget buildCategoryCard(BuildContext context, BlogCategory category) { final colors = Theme.of(context).colorScheme; return BuildCard( child: ListTile( leading: Container( width: 50, height: 50, decoration: BoxDecoration( color: colors.primary.withAlpha(50), shape: BoxShape.circle, ), child: Icon(Icons.folder, color: colors.primary, size: 28), ), title: Text( category.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), ), subtitle: Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( '${category.count} 篇博客', style: TextStyle(fontSize: 14, color: Colors.grey.shade600), ), ), trailing: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: colors.primary.withAlpha(50), borderRadius: BorderRadius.circular(16), ), child: Text( category.count.toString(), style: TextStyle(color: colors.primary, fontWeight: FontWeight.bold), ), ), onTap: () => navigateToBlogList(context, category), ), ); } Widget buildListTitle(int count) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '博客列表', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), Text( '共 $count 篇', style: TextStyle(color: Colors.grey.shade600, fontSize: 14), ), ], ); } Widget buildBlogListItem(BuildContext context, Blog blog, int index) { final colors = Theme.of(context).colorScheme; return BuildCard( child: Padding( padding: EdgeInsets.all(0), child: Row( children: [ Text('$index.', style: TextStyle(fontWeight: FontWeight.w500)), SizedBox(width: 10), Text( formatDateString(blog.createTime), style: TextStyle(fontSize: 14, color: Colors.grey.shade600), ), SizedBox(width: 10), Expanded( child: Text( blog.title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: colors.primary, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ), ); } Widget buildStatsCard({ required BuildContext context, required IconData icon, required String title, required String count, required String unit, }) { final colors = Theme.of(context).colorScheme; return BuildCard( child: Row( children: [ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: colors.primary.withAlpha(50), shape: BoxShape.circle, ), child: Icon(icon, size: 26, color: colors.primary), ), SizedBox(width: 6), Expanded( 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: 6), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( count, style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: colors.primary, height: 1.0, ), ), const SizedBox(width: 4), Text( unit, style: TextStyle( fontSize: 14, color: Colors.grey.shade600, fontWeight: FontWeight.w500, ), ), ], ), ], ), ), ], ), ); } void navigatorToBlogDetail(BuildContext context, int blogId) { Navigator.push( context, MaterialPageRoute(builder: (context) => BlogDetailPage(blogId: blogId)), ); } void navigateToBlogList(BuildContext context, BlogCategory category) { Navigator.push( context, MaterialPageRoute( builder: (context) => CategoryListPage(category: category.name), ), ); } Widget buildEmpty() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('暂无数据', style: TextStyle(fontSize: 16, color: Colors.grey)), ], ), ); }