form_section.dart 2.7 KB

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