import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../core/utils/date_utils.dart' as du; import '../../core/utils/responsive.dart'; import '../../shared/widgets/form_section.dart'; import '../../shared/widgets/form_field_row.dart'; import 'overtime_apply_controller.dart'; class OvertimeApplyPage extends ConsumerStatefulWidget { final String? editId; const OvertimeApplyPage({super.key, this.editId}); @override ConsumerState createState() => _OvertimeApplyPageState(); } class _OvertimeApplyPageState extends ConsumerState { final _reasonController = TextEditingController(); static const _types = ['工作日加班', '休息日加班', '节假日加班']; static const _compensations = ['加班费', '调休']; @override void dispose() { _reasonController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final ctrl = ref.watch(overtimeApplyProvider(widget.editId).notifier); final state = ref.watch(overtimeApplyProvider(widget.editId)); final r = ResponsiveHelper.of(context); return Scaffold( appBar: TDNavBar( title: widget.editId != null ? '编辑加班' : '加班申请', titleColor: Colors.white, backgroundColor: const Color(0xFF00ABF3), centerTitle: false, ), body: Column( children: [ Expanded( child: Align(alignment: Alignment.topCenter, child: ConstrainedBox( constraints: BoxConstraints(maxWidth: r.formMaxWidth), child: SingleChildScrollView( padding: const EdgeInsets.symmetric(vertical: 8), child: Column( children: [ FormSection( title: '基本信息', children: [ FormFieldRow( label: '加班日期', value: du.DateUtils.formatDate(state.overtime.otDate), onTap: () => _pickDate(ctrl.updateOtDate, state.overtime.otDate), ), FormFieldRow( label: '开始时间', value: du.DateUtils.formatDateTime(state.overtime.startTime), onTap: () => _pickDateTime(ctrl.updateStartTime, state.overtime.startTime), ), FormFieldRow( label: '结束时间', value: du.DateUtils.formatDateTime(state.overtime.endTime), onTap: () => _pickDateTime(ctrl.updateEndTime, state.overtime.endTime), ), FormFieldRow( label: '加班类型', value: state.overtime.otType, onTap: () => _showPicker(_types, ctrl.updateType, title: '选择加班类型'), ), FormFieldRow( label: '补偿方式', value: state.overtime.compensationType, onTap: () => _showPicker(_compensations, ctrl.updateCompensation, title: '选择补偿方式'), ), FormFieldRow( label: '加班原因', value: state.overtime.reason.isEmpty ? null : state.overtime.reason, hint: '请描述加班内容和原因', onTap: () => _showReasonEditor(), ), ], ), ], ), ), ), ), ), _buildBottomButtons(ctrl, state), ], ), ); } Widget _buildBottomButtons(OvertimeApplyController ctrl, OvertimeApplyState state) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.05), blurRadius: 4, offset: const Offset(0, -1))], ), child: Row( children: [ Expanded( child: TDButton( text: '存草稿', type: TDButtonType.outline, isBlock: true, disabled: state.isSubmitting, onTap: state.isSubmitting ? null : () async { await ctrl.saveDraft(); if (context.mounted) context.pop(); }, ), ), const SizedBox(width: 12), Expanded( flex: 2, child: TDButton( text: '提交审批', type: TDButtonType.fill, theme: TDButtonTheme.primary, isBlock: true, disabled: state.isSubmitting, onTap: state.isSubmitting ? null : () async { final ok = await ctrl.submit(); if (context.mounted && ok) context.pop(); }, ), ), ], ), ); } void _showPicker(List options, void Function(String) onPick, {String title = '请选择'}) { TDPicker.showMultiPicker( context, title: title, data: [options], onConfirm: (selected) { onPick(selected.first); }, ); } void _pickDate(void Function(DateTime) onPicked, DateTime initial) { TDPicker.showDatePicker( context, title: '选择日期', useYear: true, useMonth: true, useDay: true, initialDate: [initial.year, initial.month, initial.day], onConfirm: (selected) { onPicked(DateTime(selected['year']!, selected['month']!, selected['day']!)); }, ); } void _pickDateTime(void Function(DateTime) onPicked, DateTime initial) { TDPicker.showDatePicker( context, title: '选择日期时间', useYear: true, useMonth: true, useDay: true, useHour: true, useMinute: true, initialDate: [initial.year, initial.month, initial.day, initial.hour, initial.minute], onConfirm: (selected) { onPicked(DateTime(selected['year']!, selected['month']!, selected['day']!, selected['hour']!, selected['minute']!)); }, ); } void _showReasonEditor() { final state = ref.read(overtimeApplyProvider(widget.editId)); _reasonController.text = state.overtime.reason; showDialog( context: context, builder: (_) => TDAlertDialog( title: '加班原因', contentWidget: TextField( controller: _reasonController, maxLines: 4, decoration: const InputDecoration( hintText: '请详细描述加班内容和原因…', border: OutlineInputBorder(), ), ), leftBtnAction: () => Navigator.pop(context), rightBtnAction: () { ref .read(overtimeApplyProvider(widget.editId).notifier) .updateReason(_reasonController.text); Navigator.pop(context); }, leftBtn: TDDialogButtonOptions( title: '取消', action: () => Navigator.pop(context), ), rightBtn: TDDialogButtonOptions( title: '确定', theme: TDButtonTheme.primary, action: () { ref .read(overtimeApplyProvider(widget.editId).notifier) .updateReason(_reasonController.text); Navigator.pop(context); }, ), ), ); } }