import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:flutter/material.dart'; import '../core/theme/context_tokens.dart'; import '../core/utils/date_util.dart'; /// 可键入日期框 + 日历图标(替代旧的「年/月/日」三下拉)。 /// /// - **直接键入**:支持「2024」「2024-5」「2024-5-12」「20240512」等,归一为 `yyyy-MM-dd`, /// 缺的月/日补 `01`(老酒只知道年份,填 2024 即 2024-01-01)。失焦时把显示归一化。 /// - **日历图标**:弹 Material `showDatePicker`(input 模式可直接键入年份,选老年份方便)。 /// - 值以 `yyyy-MM-dd` 字符串进出([value] / [onChanged]);无有效年时回调 null。 class DatePickerField extends StatefulWidget { final String? value; // yyyy-MM-dd final ValueChanged onChanged; final bool isRequired; final String? label; const DatePickerField({ super.key, this.value, required this.onChanged, this.isRequired = false, this.label, }); @override State createState() => _DatePickerFieldState(); } class _DatePickerFieldState extends State { late final TextEditingController _ctrl; final FocusNode _focus = FocusNode(); @override void initState() { super.initState(); _ctrl = TextEditingController(text: widget.value ?? ''); _focus.addListener(() { // 失焦时把输入归一化显示(如 2024 → 2024-01-01) if (!_focus.hasFocus) { final n = normalizeYmd(_ctrl.text); if (n != null && n != _ctrl.text) { _ctrl.text = n; } } }); } @override void didUpdateWidget(DatePickerField old) { super.didUpdateWidget(old); // 仅在无焦点(非用户正在输入)时同步外部值,避免回流打断输入 if (!_focus.hasFocus && old.value != widget.value && (widget.value ?? '') != _ctrl.text) { _ctrl.text = widget.value ?? ''; } } @override void dispose() { _ctrl.dispose(); _focus.dispose(); super.dispose(); } Future _pickFromCalendar(FormFieldState field) async { final init = parseYmd(normalizeYmd(_ctrl.text) ?? widget.value) ?? DateTime.now(); final picked = await showDatePicker( context: context, initialDate: init, firstDate: DateTime(1900), lastDate: DateTime(2200), initialEntryMode: DatePickerEntryMode.input, ); if (picked != null) { final v = formatYmd(picked); _ctrl.text = v; field.didChange(v); widget.onChanged(v); } } @override Widget build(BuildContext context) { return FormField( initialValue: widget.value, validator: widget.isRequired ? (_) => normalizeYmd(_ctrl.text) == null ? '请输入日期' : null : null, builder: (field) { return TextField( controller: _ctrl, focusNode: _focus, keyboardType: TextInputType.datetime, style: const TextStyle(fontSize: 13), decoration: InputDecoration( isDense: true, hintText: '年-月-日', hintStyle: const TextStyle(fontSize: 12), contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), errorText: field.errorText, suffixIcon: IconButton( icon: Icon(LucideIcons.calendar, size: 16, color: context.tokens.muted), padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 34, minHeight: 34), tooltip: '选择日期', onPressed: () => _pickFromCalendar(field), ), ), onChanged: (v) { final n = normalizeYmd(v); field.didChange(n); widget.onChanged(n); }, ); }, ); } }