import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/app_provider.dart'; import '../models/data_models.dart'; import '../utils/app_theme.dart'; /// 书籍列表项组件 class BookListItem extends StatelessWidget { final Book book; const BookListItem({super.key, required this.book}); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.only(bottom: 12), child: InkWell( onTap: () { // 跳转到详情页 Navigator.pushNamed(context, '/book-detail', arguments: book); }, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 封面占位图 _buildCover(), const SizedBox(width: 12), // 书籍信息 Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 Text( book.title, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), if (book.author != null) ...[ const SizedBox(height: 4), Text( book.author!, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], const SizedBox(height: 8), // 评分和状态 Row( children: [ if (book.rating != null) ...[ Icon( Icons.star, size: 16, color: Colors.amber[700], ), const SizedBox(width: 4), Text( book.rating.toString(), style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.amber[700], ), ), const SizedBox(width: 12), ], // 状态标签 _buildStatusTag(context), ], ), if (book.readDate != null) ...[ const SizedBox(height: 6), Text( '阅读日期:${_formatDate(book.readDate!)}', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ], if (book.note != null && book.note!.isNotEmpty) ...[ const SizedBox(height: 6), Text( book.note!, style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ], ), ), // 右侧操作按钮 Column( children: [ IconButton( icon: const Icon(Icons.edit, size: 20), onPressed: () { Navigator.pushNamed(context, '/book-form', arguments: book); }, padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), IconButton( icon: const Icon(Icons.delete_outline, size: 20), color: Colors.red, onPressed: () => _showDeleteDialog(context, book), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ], ), ], ), ), ), ); } /// 构建封面占位图 Widget _buildCover() { return Container( width: 60, height: 90, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.menu_book, color: Colors.grey[500], size: 32, ), ); } /// 构建状态标签 Widget _buildStatusTag(BuildContext context) { Color statusColor; String statusText; switch (book.status) { case 'read': statusColor = AppTheme.readColor; statusText = '读完'; break; case 'reading': statusColor = AppTheme.readingColor; statusText = '在读'; break; case 'want_to_read': statusColor = AppTheme.wantToReadColor; statusText = '准备读'; break; default: statusColor = Colors.grey; statusText = '未知'; } return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: statusColor.withOpacity(0.1), borderRadius: BorderRadius.circular(4), border: Border.all( color: statusColor, width: 1, ), ), child: Text( statusText, style: TextStyle( fontSize: 11, color: statusColor, fontWeight: FontWeight.bold, ), ), ); } /// 格式化日期 String _formatDate(DateTime date) { return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; } /// 显示删除对话框 void _showDeleteDialog(BuildContext context, Book book) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认删除'), content: Text('确定要删除"${book.title}"吗?此操作不可恢复。'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () async { await context.read().removeBook(book.id); if (!context.mounted) return; Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('已删除'), behavior: SnackBarBehavior.floating, ), ); }, child: const Text( '删除', style: TextStyle(color: Colors.red), ), ), ], ), ); } }