252 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:intl/intl.dart';
 | |
| import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
 | |
| import 'package:qhd_prevention/customWidget/custom_button.dart';
 | |
| import 'package:qhd_prevention/customWidget/date_picker_dialog.dart';
 | |
| import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart';
 | |
| import 'package:qhd_prevention/customWidget/toast_util.dart';
 | |
| import 'package:qhd_prevention/pages/my_appbar.dart';
 | |
| 
 | |
| import '../../http/ApiService.dart';
 | |
| import '../../tools/tools.dart';
 | |
| 
 | |
| class MineDutyApplicationPage extends StatefulWidget {
 | |
|   const MineDutyApplicationPage({super.key, required this.onClose});
 | |
| 
 | |
|   final Function(String) onClose; // 回调函数
 | |
| 
 | |
|   @override
 | |
|   State<MineDutyApplicationPage> createState() => _MineDutyApplicationPage();
 | |
| }
 | |
| 
 | |
| class _MineDutyApplicationPage extends State<MineDutyApplicationPage> {
 | |
|   DateTime? _startDate;
 | |
|   DateTime? _endDate;
 | |
|   final TextEditingController _reasonController = TextEditingController();
 | |
| 
 | |
|   Future<void> _submitApplicationLeaving() async {
 | |
|     try {
 | |
|       var formatter = DateFormat('yyyy-MM-dd'); // 或者使用 'dd-MM-yyyy' 取决于你的需求
 | |
|       String startTime = formatter.format(_startDate!);
 | |
|       String endTime = formatter.format(_endDate!);
 | |
| 
 | |
|       final result = await ApiService.submitApplicationLeaving(
 | |
|         startTime,
 | |
|         endTime,
 | |
|         _reasonController.text,
 | |
|       );
 | |
|       if (result['result'] == 'success') {
 | |
|         ToastUtil.showSuccess(context, '提交成功');
 | |
|         widget.onClose('关闭提交'); // 触发回调
 | |
|         Navigator.pop(context); // 关闭页面
 | |
|       }else{
 | |
|         ToastUtil.showError(context, '提交失败');
 | |
|       }
 | |
|     } catch (e) {
 | |
|       print('加载出错: $e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _selectDate(BuildContext context, bool isStartDate) async {
 | |
|     DateTime? picked = await BottomDateTimePicker.showDate(
 | |
|       context,
 | |
|       mode: BottomPickerMode.date,
 | |
|       allowFuture: true,
 | |
|       minTimeStr: '0-0-0 00:00',
 | |
|     );
 | |
|     if (picked != null) {
 | |
|       setState(() {
 | |
|         if (isStartDate) {
 | |
|           if (picked.isBefore(DateTime.now().subtract(Duration(days: 1)))) {
 | |
|             ToastUtil.showNormal(context, '开始日期不能早于当前日期');
 | |
| 
 | |
|           } else {
 | |
|             _startDate = picked;
 | |
|             // 如果结束日期早于开始日期,自动更新结束日期
 | |
|             if (_endDate == null || _endDate!.isBefore(picked)) {
 | |
|               _endDate = picked;
 | |
|             }
 | |
|           }
 | |
|         } else {
 | |
|           if (picked.isBefore(DateTime.now().subtract(Duration(days: 1)))) {
 | |
|             ToastUtil.showNormal(context, '结束日期不能早于当前日期');
 | |
| 
 | |
|           } else {
 | |
|             // 确保结束日期不早于开始日期
 | |
|             if (_startDate != null && picked.isBefore(_startDate!)) {
 | |
|               ToastUtil.showNormal(context, '结束日期不能早于开始日期');
 | |
| 
 | |
|             } else {
 | |
|               _endDate = picked;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       });
 | |
|     }
 | |
| 
 | |
| 
 | |
|   }
 | |
| 
 | |
|   void _submitApplication() async{
 | |
|     if (_startDate == null || _endDate == null) {
 | |
|       ToastUtil.showNormal(context, '请选择离岗时间');
 | |
| 
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (_reasonController.text.isEmpty) {
 | |
|       ToastUtil.showNormal(context, '请输入离岗原因');
 | |
| 
 | |
|       return;
 | |
|     }
 | |
|     final ok = await CustomAlertDialog.showConfirm(context, title: '申请提交', content: '您确定提交离岗申请吗?', cancelText: '取消');
 | |
|     if (ok) {
 | |
|       _submitApplicationLeaving();
 | |
| 
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Scaffold(
 | |
|       backgroundColor: const Color(0xFFF5F7FA),
 | |
|       appBar: MyAppbar(title: "离岗申请"),
 | |
|       body: SingleChildScrollView(
 | |
|         padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
 | |
|         child: Column(
 | |
|           crossAxisAlignment: CrossAxisAlignment.start,
 | |
|           children: [
 | |
|             // 离岗开始时间
 | |
|             _buildDateField(
 | |
|               label: "离岗开始时间",
 | |
|               date: _startDate,
 | |
|               onTap: () => _selectDate(context, true),
 | |
|             ),
 | |
| 
 | |
|             const SizedBox(height: 16),
 | |
| 
 | |
|             // 离岗结束时间
 | |
|             _buildDateField(
 | |
|               label: "离岗结束时间",
 | |
|               date: _endDate,
 | |
|               onTap: () => _selectDate(context, false),
 | |
|             ),
 | |
| 
 | |
|             const SizedBox(height: 24),
 | |
| 
 | |
|             // 离岗原因标题
 | |
|             const Text(
 | |
|               "离岗原因",
 | |
|               style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500),
 | |
|             ),
 | |
|             const SizedBox(height: 8),
 | |
| 
 | |
|             // 原因输入框
 | |
|             Container(
 | |
|               padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
 | |
|               decoration: BoxDecoration(
 | |
|                 color: Colors.white,
 | |
|                 borderRadius: BorderRadius.circular(12),
 | |
|                 boxShadow: [
 | |
|                   BoxShadow(
 | |
|                     color: Colors.blue.withOpacity(0.1),
 | |
|                     spreadRadius: 1,
 | |
|                     blurRadius: 6,
 | |
|                     offset: const Offset(0, 2),
 | |
|                   ),
 | |
|                 ],
 | |
|               ),
 | |
|               child: TextField(
 | |
|                 controller: _reasonController,
 | |
|                 maxLines: 5,
 | |
|                 maxLength: 120, // 限制最大字数为 200
 | |
|                 decoration: const InputDecoration(
 | |
|                   hintText: "请输入离岗原因",
 | |
|                   hintStyle: TextStyle(color: Color(0xFF9E9E9E)),
 | |
|                   border: InputBorder.none,
 | |
|                 ),
 | |
|               ),
 | |
|             ),
 | |
| 
 | |
|             const SizedBox(height: 24),
 | |
| 
 | |
|             // 申请人信息
 | |
|             // _buildInfoRow("申请人", _applicant),
 | |
|             _buildInfoRow("申请人", SessionService.instance.username.toString()),
 | |
| 
 | |
|             const SizedBox(height: 40),
 | |
|             CustomButton(text: '提交', backgroundColor: Colors.blue, onPressed: _submitApplication),
 | |
|           ],
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildDateField({
 | |
|     required String label,
 | |
|     required DateTime? date,
 | |
|     required VoidCallback onTap,
 | |
|   }) {
 | |
|     return GestureDetector(
 | |
|       onTap: onTap,
 | |
|       child: Container(
 | |
|         padding: const EdgeInsets.all(16),
 | |
|         decoration: BoxDecoration(
 | |
|           color: Colors.white,
 | |
|           borderRadius: BorderRadius.circular(12),
 | |
|           boxShadow: [
 | |
|             BoxShadow(
 | |
|               color: Colors.grey.withOpacity(0.1),
 | |
|               spreadRadius: 1,
 | |
|               blurRadius: 6,
 | |
|               offset: const Offset(0, 2),
 | |
|             ),
 | |
|           ],
 | |
|         ),
 | |
|         child: Row(
 | |
|           mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|           children: [
 | |
|             Text(label, style: const TextStyle(fontSize: 14)),
 | |
|             Text(
 | |
|               date != null ? DateFormat('yyyy-MM-dd').format(date) : "请选择日期",
 | |
|               style: TextStyle(
 | |
|                 fontSize: 14,
 | |
|                 color: date != null ? Colors.black : const Color(0xFF9E9E9E),
 | |
|               ),
 | |
|             ),
 | |
|           ],
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildInfoRow(String title, String value) {
 | |
|     return Container(
 | |
|       padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
 | |
|       decoration: BoxDecoration(
 | |
|         color: Colors.white,
 | |
|         borderRadius: BorderRadius.circular(12),
 | |
|         boxShadow: [
 | |
|           BoxShadow(
 | |
|             color: Colors.grey.withOpacity(0.1),
 | |
|             spreadRadius: 1,
 | |
|             blurRadius: 6,
 | |
|             offset: const Offset(0, 2),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|       child: Row(
 | |
|         mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|         children: [
 | |
|           Text(title, style: const TextStyle(fontSize: 14)),
 | |
|           Text(
 | |
|             value,
 | |
|             style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |