section_card.dart 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import '../../core/theme/app_colors.dart';
  2. import 'package:flutter/material.dart';
  3. import '../../core/theme/app_colors_extension.dart';
  4. /// Pencil Component/SectionCard — 分组卡片容器
  5. ///
  6. /// 带标题头(16号/600字重)和右侧可选操作按钮,内容区可放任意Widget列表。
  7. /// 圆角8,背景bgCard,padding 16,gap 16。
  8. class SectionCard extends StatelessWidget {
  9. final String title;
  10. final String? actionText;
  11. final IconData? actionIcon;
  12. final VoidCallback? onActionTap;
  13. final List<Widget> children;
  14. final bool showAction;
  15. const SectionCard({
  16. super.key,
  17. required this.title,
  18. this.actionText,
  19. this.actionIcon,
  20. this.onActionTap,
  21. required this.children,
  22. this.showAction = true,
  23. });
  24. @override
  25. Widget build(BuildContext context) {
  26. final colors = Theme.of(context).extension<AppColorsExtension>()!;
  27. return Container(
  28. padding: const EdgeInsets.all(16),
  29. decoration: BoxDecoration(
  30. color: colors.bgCard,
  31. borderRadius: BorderRadius.circular(8),
  32. ),
  33. child: Column(
  34. crossAxisAlignment: CrossAxisAlignment.start,
  35. children: [
  36. // 标题行
  37. Row(
  38. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  39. children: [
  40. Text(
  41. title,
  42. style: TextStyle(
  43. fontSize: AppFontSizes.subtitle,
  44. fontWeight: FontWeight.w600,
  45. color: colors.textPrimary,
  46. ),
  47. ),
  48. if (showAction && (actionText != null || actionIcon != null))
  49. GestureDetector(
  50. onTap: onActionTap,
  51. child: Row(
  52. mainAxisSize: MainAxisSize.min,
  53. children: [
  54. if (actionText != null)
  55. Text(
  56. actionText!,
  57. style: TextStyle(
  58. fontSize: AppFontSizes.body,
  59. color: colors.textSecondary,
  60. ),
  61. ),
  62. if (actionIcon != null) ...[
  63. const SizedBox(width: 2),
  64. Icon(
  65. actionIcon,
  66. size: 16,
  67. color: colors.textSecondary,
  68. ),
  69. ],
  70. ],
  71. ),
  72. ),
  73. ],
  74. ),
  75. // 分隔线
  76. if (children.isNotEmpty) ...[
  77. const SizedBox(height: 16),
  78. ...children,
  79. ],
  80. ],
  81. ),
  82. );
  83. }
  84. }