594 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			594 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:intl/intl.dart';
 | |
| import 'package:qhd_prevention/pages/my_appbar.dart';
 | |
| 
 | |
| import '../../http/ApiService.dart';
 | |
| import '../../tools/tools.dart';
 | |
| import 'mine_duty_application.dart';
 | |
| import 'mine_duty_detail.dart';
 | |
| 
 | |
| class LeaveRecord {
 | |
|   final String applicant;
 | |
|   final String department;
 | |
|   final String position;
 | |
|   final DateTime startDate;
 | |
|   final DateTime endDate;
 | |
|   final String status;
 | |
|   final Color statusColor;
 | |
| 
 | |
|   LeaveRecord({
 | |
|     required this.applicant,
 | |
|     required this.department,
 | |
|     required this.position,
 | |
|     required this.startDate,
 | |
|     required this.endDate,
 | |
|     required this.status,
 | |
|     required this.statusColor,
 | |
|   });
 | |
| }
 | |
| 
 | |
| ///离岗管理列表
 | |
| class MineDutyManagementPage extends StatefulWidget {
 | |
|   const MineDutyManagementPage({super.key});
 | |
| 
 | |
|   @override
 | |
|   State<MineDutyManagementPage> createState() => _MineDutyManagementPageState();
 | |
| }
 | |
| 
 | |
| class _MineDutyManagementPageState extends State<MineDutyManagementPage> {
 | |
|   int showCount = -1;
 | |
|   int currentPage = 1;
 | |
|   late List<dynamic> _list = [];
 | |
| 
 | |
|   Future<void> _onRefresh() async {
 | |
|     // 模拟网络请求
 | |
|     await Future.delayed(const Duration(seconds: 2));
 | |
|     // 刷新数据逻辑,如 fetchData()
 | |
|     setState(() {
 | |
|       // TODO: 更新数据源
 | |
|       refreshData();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     _getListData();
 | |
|   }
 | |
| 
 | |
|   void refreshData() {
 | |
|     currentPage = 1;
 | |
|     _list.clear();
 | |
|     _getListData();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     // 模拟数据
 | |
|     // final leaveRecords = [
 | |
|     //   LeaveRecord(
 | |
|     //     applicant: "王轩",
 | |
|     //     department: "测试部",
 | |
|     //     position: "测试员",
 | |
|     //     startDate: DateTime(2025, 7, 18),
 | |
|     //     endDate: DateTime(2025, 7, 18),
 | |
|     //     status: "无需审批",
 | |
|     //     statusColor: const Color(0xFF4CAF50),
 | |
|     //   ),
 | |
|     //   LeaveRecord(
 | |
|     //     applicant: "王轩",
 | |
|     //     department: "测试部",
 | |
|     //     position: "测试员",
 | |
|     //     startDate: DateTime(2025, 7, 16),
 | |
|     //     endDate: DateTime(2025, 7, 16),
 | |
|     //     status: "无需审批",
 | |
|     //     statusColor: const Color(0xFF4CAF50),
 | |
|     //   ),
 | |
|     //   LeaveRecord(
 | |
|     //     applicant: "李思",
 | |
|     //     department: "开发部",
 | |
|     //     position: "高级工程师",
 | |
|     //     startDate: DateTime(2025, 7, 20),
 | |
|     //     endDate: DateTime(2025, 7, 22),
 | |
|     //     status: "待审批",
 | |
|     //     statusColor: const Color(0xFFF57C00),
 | |
|     //   ),
 | |
|     //   LeaveRecord(
 | |
|     //     applicant: "张伟",
 | |
|     //     department: "产品部",
 | |
|     //     position: "产品经理",
 | |
|     //     startDate: DateTime(2025, 7, 15),
 | |
|     //     endDate: DateTime(2025, 7, 17),
 | |
|     //     status: "已拒绝",
 | |
|     //     statusColor: const Color(0xFFF44336),
 | |
|     //   ),
 | |
|     // ];
 | |
| 
 | |
|     return Scaffold(
 | |
|       backgroundColor: const Color(0xFFF5F7FA),
 | |
|       appBar: MyAppbar(
 | |
|         title: "离岗管理",
 | |
|         actions: [
 | |
|           TextButton(
 | |
|             onPressed: () {
 | |
|               Navigator.push(
 | |
|                 context,
 | |
|                 MaterialPageRoute(
 | |
|                   builder:
 | |
|                       (context) => MineDutyApplicationPage(
 | |
|                         onClose: (result) {
 | |
|                           // print('详情页面已关闭,返回结果: $result');
 | |
|                           refreshData();
 | |
|                         },
 | |
|                       ),
 | |
|                 ),
 | |
|               );
 | |
|               // pushPage(MineDutyApplicationPage(), context);
 | |
|             },
 | |
|             child: Text(
 | |
|               "申请",
 | |
|               style: TextStyle(
 | |
|                 color: Colors.white,
 | |
|                 fontSize: 16,
 | |
|                 fontWeight: FontWeight.bold,
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|       body: RefreshIndicator(
 | |
|         onRefresh: _onRefresh,
 | |
|         child:
 | |
|         // Column(
 | |
|         //    children: [
 | |
|         // 顶部信息栏
 | |
|         // Container(
 | |
|         //   padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
 | |
|         //   color: const Color(0xFFE3F2FD),
 | |
|         //   child: const Row(
 | |
|         //     children: [
 | |
|         //     Icon(Icons.info_outline, color: Color(0xFF1976D2)),
 | |
|         //     SizedBox(width: 8),
 | |
|         //     Text(
 | |
|         //       "离岗记录显示最近30天内的申请记录",
 | |
|         //       style: TextStyle(color: Color(0xFF1976D2), fontSize: 14),
 | |
|         //     ),
 | |
|         //     ],
 | |
|         //   ),
 | |
|         // ),
 | |
|         // 记录列表
 | |
|         // Expanded(
 | |
|         //   child:
 | |
|               _list.isEmpty
 | |
|                   ? NoDataWidget.show()
 | |
|                   : ListView.builder(
 | |
|                     padding: const EdgeInsets.symmetric(vertical: 16),
 | |
|                     itemCount: _list.length,
 | |
|                     itemBuilder: (context, index) {
 | |
|                       final record = _list[index];
 | |
|                       return _buildRecordCard(record, context);
 | |
|                     },
 | |
|                   ),
 | |
|           //   ),
 | |
|           // ],
 | |
|         // ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildRecordCard(final item, BuildContext context) {
 | |
|     // final dateFormat = DateFormat('yyyy-MM-dd');
 | |
|     // final isSameDay = record.startDate == record.endDate;
 | |
|     // final dateRange = isSameDay
 | |
|     //     ? dateFormat.format(record.startDate)
 | |
|     //     : "${dateFormat.format(record.startDate)} 至 ${dateFormat.format(record.endDate)}";
 | |
|     final dateRange = "${item['STARTTIME']} 至 ${item['ENDTIME']}";
 | |
| 
 | |
|     return GestureDetector(
 | |
|       onTap: () {
 | |
|         pushPage(MineDutyDetailPage(item), context);
 | |
|       },
 | |
|       child: Container(
 | |
|         margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
 | |
|         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: Padding(
 | |
|           padding: const EdgeInsets.all(16),
 | |
|           child: Column(
 | |
|             crossAxisAlignment: CrossAxisAlignment.start,
 | |
|             children: [
 | |
|               // 申请人信息
 | |
|               Row(
 | |
|                 children: [
 | |
|                   // Container(
 | |
|                   //   width: 40,
 | |
|                   //   height: 40,
 | |
|                   //   decoration: BoxDecoration(
 | |
|                   //     color: const Color(0xFFE3F2FD),
 | |
|                   //     shape: BoxShape.circle,
 | |
|                   //   ),
 | |
|                   //   child: const Icon(Icons.person, color: Color(0xFF1976D2)),
 | |
|                   // ),
 | |
|                   // const SizedBox(width: 12),
 | |
|                   Column(
 | |
|                     crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                     children: [
 | |
|                       Text(
 | |
|                         "申请人:${item['USER_NAME']}",
 | |
|                         style: const TextStyle(
 | |
|                           fontSize: 16,
 | |
|                           fontWeight: FontWeight.w600,
 | |
|                         ),
 | |
|                       ),
 | |
|                       const SizedBox(height: 4),
 | |
|                       Text(
 | |
|                         "部门:${item['DEPARTMENTNAME']} \n岗位:${item['POSTNAME']}",
 | |
|                         style: TextStyle(fontSize: 13, color: Colors.grey[600]),
 | |
|                       ),
 | |
|                     ],
 | |
|                   ),
 | |
| 
 | |
|                   // const Spacer(),
 | |
|                 ],
 | |
|               ),
 | |
| 
 | |
|               const SizedBox(height: 8),
 | |
| 
 | |
|               // 离岗时间
 | |
|               Row(
 | |
|                 children: [
 | |
|                   const Icon(
 | |
|                     Icons.calendar_today,
 | |
|                     size: 18,
 | |
|                     color: Colors.grey,
 | |
|                   ),
 | |
|                   const SizedBox(width: 8),
 | |
|                   Expanded(
 | |
|                     child: Text(
 | |
|                       "离岗时间: $dateRange",
 | |
|                       style: const TextStyle(color: Colors.grey),
 | |
|                     ),
 | |
|                   ),
 | |
|                 ],
 | |
|               ),
 | |
| 
 | |
|               const SizedBox(height: 4),
 | |
|               // Container(
 | |
|               //   padding: const EdgeInsets.symmetric( vertical: 6),
 | |
|               //   // decoration: BoxDecoration(
 | |
|               //   //   color: record.statusColor.withOpacity(0.1),
 | |
|               //   //   borderRadius: BorderRadius.circular(20),
 | |
|               //   // ),
 | |
|               //   child:
 | |
|               Text(
 | |
|                 "审核状态:${_getTypeReturn(item)}",
 | |
|                 // record.status,
 | |
|                 style: TextStyle(
 | |
|                   color: Colors.black,
 | |
|                   fontWeight: FontWeight.w500,
 | |
|                 ),
 | |
|               ),
 | |
| 
 | |
|               // ),
 | |
|               const SizedBox(height: 4),
 | |
| 
 | |
|               // 操作按钮
 | |
|               // if (item["REVIEW_STATUS"] == "0" && isBeforeNow(item["ENDTIME"]) &&
 | |
|               //     (item["REVIEW_USER_ID"] == SessionService.instance.loginUserId) &&
 | |
|               //     SessionService.instance.loginUser?["USERNAME"] == "1" &&
 | |
|               //     item['REVIEW_STATUS'] == "0")
 | |
| 
 | |
|                 Row(
 | |
|                   mainAxisAlignment: MainAxisAlignment.end,
 | |
|                   children: [
 | |
|                     if(item["REVIEW_STATUS"]== '0' &&
 | |
|                         (item["REVIEW_USER_ID"]== SessionService.instance.loginUserId ||
 | |
|                             item["REVIEW_USER_ID"]!=null &&
 | |
|                                 SessionService.instance.loginUser?["ISLEADER"] == '1'))
 | |
|                     ElevatedButton(
 | |
|                       onPressed: () {
 | |
|                         showDialog(
 | |
|                           context: context,
 | |
|                           builder:
 | |
|                               (context) => DutyDialog(
 | |
|                                 item,
 | |
|                                 1,
 | |
|                                 onClose: (result) {
 | |
|                                   // print('详情页面已关闭,返回结果: $result');
 | |
|                                   refreshData();
 | |
|                                 },
 | |
|                               ),
 | |
|                         );
 | |
|                       },
 | |
|                       style: ElevatedButton.styleFrom(
 | |
|                         backgroundColor: const Color(0xFF1976D2),
 | |
|                         // padding: const EdgeInsets.symmetric(horizontal: 10),
 | |
|                       ),
 | |
|                       child: const Text(
 | |
|                         "审 批",
 | |
|                         style: TextStyle(color: Colors.white, fontSize: 12),
 | |
|                       ),
 | |
|                     ),
 | |
| 
 | |
|                     const SizedBox(width: 16),
 | |
| 
 | |
|                     if(item["REVIEW_STATUS"]== '0'&&
 | |
|                      (item["REVIEW_USER_ID"]== SessionService.instance.loginUserId ||
 | |
|                       item["USER_ID"]==SessionService.instance.loginUserId))
 | |
|                     ElevatedButton(
 | |
|                       onPressed: () {
 | |
|                         showDialog(
 | |
|                           context: context,
 | |
|                           builder:
 | |
|                               (context) => DutyDialog(
 | |
|                                 item,
 | |
|                                 2,
 | |
|                                 onClose: (result) {
 | |
|                                   // print('详情页面已关闭,返回结果: $result');
 | |
|                                   refreshData();
 | |
|                                 },
 | |
|                               ),
 | |
|                         );
 | |
|                       },
 | |
|                       style: ElevatedButton.styleFrom(
 | |
|                         backgroundColor: Colors.red,
 | |
|                         // padding: const EdgeInsets.symmetric(horizontal: 10),
 | |
|                       ),
 | |
|                       child: const Text(
 | |
|                         "取 消",
 | |
|                         style: TextStyle(color: Colors.white, fontSize: 12),
 | |
|                       ),
 | |
|                     ),
 | |
|                   ],
 | |
|                 ),
 | |
|             ],
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Future<void> _getListData() async {
 | |
|     try {
 | |
|       LoadingDialogHelper.show();
 | |
|       final result = await ApiService.getDutyManagement(showCount, currentPage);
 | |
|       LoadingDialogHelper.hide();
 | |
|       if (result['result'] == 'success') {
 | |
|         final List<dynamic> newList = result['varList'] ?? [];
 | |
|         setState(() {
 | |
|           _list.addAll(newList);
 | |
|         });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       LoadingDialogHelper.hide();
 | |
|       print('加载出错: $e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   String _getTypeReturn(final item) {
 | |
|     String type = item['REVIEW_STATUS'];
 | |
|     if ("0" == type) {
 | |
|       return "待审批";
 | |
|     } else if ("1" == type) {
 | |
|       return "审批通过";
 | |
|     } else if ("2" == type) {
 | |
|       return "无需审批";
 | |
|     } else if ("-1" == type) {
 | |
|       String type2 = item['ISDELETE'];
 | |
|       if ("1" == type2) {
 | |
|         if (item['CREATOR'] == item['OPERATOR']) {
 | |
|           return "申请人取消";
 | |
|         } else {
 | |
|           return "审批人取消";
 | |
|         }
 | |
|       } else {
 | |
|         return "审批打回";
 | |
|       }
 | |
|     } else {
 | |
|       return "审批错误";
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| enum FeedbackType { tongGuo, Dahui }
 | |
| 
 | |
| class DutyDialog extends StatefulWidget {
 | |
|   const DutyDialog(this.item, this.type, {super.key, required this.onClose});
 | |
| 
 | |
|   final Function(String) onClose; // 回调函数
 | |
|   final item;
 | |
|   final int type;
 | |
| 
 | |
|   @override
 | |
|   State<DutyDialog> createState() => _DutyDialogState();
 | |
| }
 | |
| 
 | |
| class _DutyDialogState extends State<DutyDialog> {
 | |
|   final TextEditingController _reasonController = TextEditingController();
 | |
| 
 | |
|   // 反馈类型
 | |
|   FeedbackType? _selectedType = FeedbackType.tongGuo;
 | |
| 
 | |
|   // 获取反馈类型名称
 | |
|   String _getTypeName(FeedbackType type) {
 | |
|     switch (type) {
 | |
|       case FeedbackType.tongGuo:
 | |
|         return '通过';
 | |
|       case FeedbackType.Dahui:
 | |
|         return '打回';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _dutyApproval() async {
 | |
|     try {
 | |
|       String typeString;
 | |
|       if (FeedbackType.tongGuo == _selectedType) {
 | |
|         typeString = "1";
 | |
|       } else {
 | |
|         typeString = "-1";
 | |
|       }
 | |
| 
 | |
|       final result = await ApiService.dutyApproval(
 | |
|         typeString,
 | |
|         _reasonController.text,
 | |
|         widget.item["OFFDUTY_ID"],
 | |
|       );
 | |
|       if (result['result'] == 'success') {
 | |
|         widget.onClose('关闭提交'); // 触发回调
 | |
|       }
 | |
|     } catch (e) {
 | |
|       print('加载出错: $e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _dutyReturned() async {
 | |
|     try {
 | |
|       final result = await ApiService.dutyReturned(
 | |
|         "-1",
 | |
|         _reasonController.text,
 | |
|         widget.item["OFFDUTY_ID"],
 | |
|       );
 | |
|       if (result['result'] == 'success') {
 | |
|         widget.onClose('关闭提交'); // 触发回调
 | |
|       }
 | |
|     } catch (e) {
 | |
|       print('加载出错: $e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Dialog(
 | |
|       shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
 | |
|       child: Container(
 | |
|         padding: const EdgeInsets.all(20),
 | |
|         child: Column(
 | |
|           mainAxisSize: MainAxisSize.min,
 | |
|           crossAxisAlignment: CrossAxisAlignment.start,
 | |
|           children: [
 | |
|             // 标题
 | |
|             const Center(
 | |
|               child: Text(
 | |
|                 '离岗审批',
 | |
|                 style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
 | |
|               ),
 | |
|             ),
 | |
| 
 | |
|             const SizedBox(height: 20),
 | |
| 
 | |
|             // 操作按钮行
 | |
|             // Row(
 | |
|             //   mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | |
|             //   children: [
 | |
|             //     _buildActionButton('通过', Colors.green),
 | |
|             //     _buildActionButton('打印', Colors.blue),
 | |
|             //   ],
 | |
|             // ),
 | |
|             if (1 == widget.type)
 | |
|               Center(
 | |
|                 child: Wrap(
 | |
|                   spacing: 16,
 | |
|                   children:
 | |
|                       FeedbackType.values.map((type) {
 | |
|                         return ChoiceChip(
 | |
|                           label: Text(_getTypeName(type)),
 | |
|                           selected: _selectedType == type,
 | |
|                           onSelected: (selected) {
 | |
|                             setState(() {
 | |
|                               if (selected) {
 | |
|                                 _selectedType = type;
 | |
|                               }
 | |
|                             });
 | |
|                           },
 | |
|                         );
 | |
|                       }).toList(),
 | |
|                 ),
 | |
|               ),
 | |
| 
 | |
|             const SizedBox(height: 20),
 | |
| 
 | |
|             // 输入框
 | |
|             TextField(
 | |
|               controller: _reasonController,
 | |
|               decoration: InputDecoration(
 | |
|                 border: OutlineInputBorder(),
 | |
|                 hintText: widget.type == 1 ? '请输入审批意见' : '请输入原因',
 | |
|                 contentPadding: EdgeInsets.symmetric(
 | |
|                   horizontal: 12,
 | |
|                   vertical: 16,
 | |
|                 ),
 | |
|               ),
 | |
|               maxLines: 4,
 | |
|             ),
 | |
| 
 | |
|             const SizedBox(height: 20),
 | |
| 
 | |
|             // 底部按钮
 | |
|             Row(
 | |
|               mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 | |
|               children: [
 | |
|                 Expanded(
 | |
|                   child: ElevatedButton(
 | |
|                     onPressed: () {
 | |
|                       if (_reasonController.text.isEmpty) {
 | |
|                         ScaffoldMessenger.of(context).showSnackBar(
 | |
|                           SnackBar(
 | |
|                             content: Text(
 | |
|                               widget.type == 1 ? '请输入审批意见' : '请输入原因',
 | |
|                             ),
 | |
|                           ),
 | |
|                         );
 | |
|                         return;
 | |
|                       }
 | |
| 
 | |
|                       if (1 == widget.type) {
 | |
|                         _dutyApproval(); //审批
 | |
|                       } else {
 | |
|                         _dutyReturned(); //打回
 | |
|                       }
 | |
|                       Navigator.pop(context);
 | |
|                     },
 | |
|                     style: ElevatedButton.styleFrom(
 | |
|                       backgroundColor: Colors.blue,
 | |
|                       padding: const EdgeInsets.symmetric(vertical: 14),
 | |
|                     ),
 | |
|                     child: const Text(
 | |
|                       '提交',
 | |
|                       style: TextStyle(color: Colors.white),
 | |
|                     ),
 | |
|                   ),
 | |
|                 ),
 | |
|                 const SizedBox(width: 15),
 | |
|                 Expanded(
 | |
|                   child: ElevatedButton(
 | |
|                     onPressed: () {
 | |
|                       Navigator.pop(context);
 | |
|                     },
 | |
|                     style: ElevatedButton.styleFrom(
 | |
|                       backgroundColor: Colors.grey,
 | |
|                       padding: const EdgeInsets.symmetric(vertical: 14),
 | |
|                     ),
 | |
|                     child: const Text(
 | |
|                       '关闭',
 | |
|                       style: TextStyle(color: Colors.white),
 | |
|                     ),
 | |
|                   ),
 | |
|                 ),
 | |
|               ],
 | |
|             ),
 | |
|           ],
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |