form_section.dart 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. behavior: HitTestBehavior.opaque,
  61. child: Padding(
  62. padding: const EdgeInsetsDirectional.only(start: 16, top: 6, bottom: 6),
  63. child: Row(
  64. mainAxisSize: MainAxisSize.min,
  65. children: [
  66. Text(
  67. actionText ?? '',
  68. style: TextStyle(
  69. fontSize: AppFontSizes.body,
  70. color: colors.primary,
  71. ),
  72. ),
  73. const SizedBox(width: 4),
  74. Icon(
  75. actionIcon ?? Icons.add,
  76. size: 20,
  77. color: colors.primary,
  78. ),
  79. ],
  80. ),
  81. ),
  82. ),
  83. ],
  84. ),
  85. const SizedBox(height: 16),
  86. ...children,
  87. ],
  88. ),
  89. );
  90. }
  91. }