573 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			573 lines
		
	
	
		
			17 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"&&DateTime.now().isBefore(item["ENDTIME"])&&
 | |
|                   (item["REVIEW_USER_ID"]==SessionService.instance.loginUserId)&&
 | |
|                   SessionService.instance.loginUser?["USERNAME"]=="1"&&item['REVIEW_STATUS']=="0")
 | |
|               Row(
 | |
|                 mainAxisAlignment: MainAxisAlignment.end,
 | |
|                 children: [
 | |
|                   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),
 | |
| 
 | |
|                     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 {
 | |
| 
 | |
|       final result = await ApiService.getDutyManagement(showCount,currentPage);
 | |
|       if (result['result'] == 'success') {
 | |
|         final List<dynamic> newList = result['varList'] ?? [];
 | |
|         setState(() {
 | |
|           _list.addAll(newList);
 | |
|         });
 | |
|       }
 | |
|     } catch (e) {
 | |
|       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),),
 | |
|                   ),
 | |
|                 ),
 | |
|               ],
 | |
|             ),
 | |
|           ],
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 |