problem_card.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import 'package:flutter/material.dart';
  2. import '../models/problem.dart';
  3. class ProblemCard extends StatelessWidget {
  4. final Problem problem;
  5. final bool isSelected;
  6. final bool isInCart;
  7. final VoidCallback onTap;
  8. final ValueChanged<String> onAddToCart;
  9. final ValueChanged<String>? onRemoveFromCart;
  10. const ProblemCard({
  11. super.key,
  12. required this.problem,
  13. this.isSelected = false,
  14. this.isInCart = false,
  15. required this.onTap,
  16. required this.onAddToCart,
  17. this.onRemoveFromCart,
  18. });
  19. @override
  20. Widget build(BuildContext context) {
  21. final preview = problem.bodyPreview.isNotEmpty
  22. ? problem.bodyPreview
  23. : '${problem.questionType} · ${problem.difficultyLabel}(${problem.difficulty})';
  24. return Card(
  25. margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
  26. color: isSelected ? Theme.of(context).colorScheme.primaryContainer : null,
  27. child: ListTile(
  28. dense: true,
  29. leading: _typeIcon(),
  30. title: Text(
  31. preview,
  32. maxLines: 3,
  33. overflow: TextOverflow.ellipsis,
  34. style: const TextStyle(fontSize: 13, height: 1.4),
  35. ),
  36. subtitle: Row(
  37. children: [
  38. _difficultyChip(context),
  39. const SizedBox(width: 4),
  40. if (!problem.isAnnotated)
  41. const Icon(Icons.warning_amber, size: 14, color: Colors.orange),
  42. ],
  43. ),
  44. trailing: isInCart
  45. ? IconButton(
  46. icon: const Icon(Icons.remove_shopping_cart, size: 18, color: Colors.red),
  47. onPressed: () => onRemoveFromCart?.call(problem.id),
  48. tooltip: '从试题篮移除',
  49. )
  50. : IconButton(
  51. icon: const Icon(Icons.add_shopping_cart, size: 18),
  52. onPressed: () => onAddToCart(problem.id),
  53. tooltip: '加入试题篮',
  54. ),
  55. onTap: onTap,
  56. ),
  57. );
  58. }
  59. Widget _difficultyChip(BuildContext context) {
  60. Color color;
  61. switch (problem.difficultyLabel) {
  62. case '易': color = Colors.green; break;
  63. case '中': color = Colors.orange; break;
  64. default: color = Colors.red;
  65. }
  66. return Container(
  67. padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1),
  68. decoration: BoxDecoration(
  69. color: color.withValues(alpha: 0.15),
  70. borderRadius: BorderRadius.circular(8),
  71. ),
  72. child: Text(
  73. problem.difficultyLabel,
  74. style: TextStyle(fontSize: 11, color: color, fontWeight: FontWeight.w500),
  75. ),
  76. );
  77. }
  78. Widget _typeIcon() {
  79. IconData icon;
  80. Color color;
  81. switch (problem.questionType) {
  82. case '单选题': icon = Icons.radio_button_checked; color = Colors.blue; break;
  83. case '多选题': icon = Icons.check_box; color = Colors.purple; break;
  84. case '填空题': icon = Icons.edit_note; color = Colors.orange; break;
  85. case '解答题': icon = Icons.assignment; color = Colors.green; break;
  86. default: icon = Icons.question_mark; color = Colors.grey;
  87. }
  88. return Icon(icon, color: color, size: 20);
  89. }
  90. }