469 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			469 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'dart:math';
 | |
| 
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:qhd_prevention/customWidget/toast_util.dart';
 | |
| import 'package:qhd_prevention/pages/home/work_alert.dart';
 | |
| import 'package:qhd_prevention/pages/my_appbar.dart';
 | |
| import 'package:qhd_prevention/tools/tools.dart';
 | |
| import 'package:table_calendar/table_calendar.dart';
 | |
| import 'package:intl/intl.dart';
 | |
| 
 | |
| import '../../http/ApiService.dart';
 | |
| import '../../tools/h_colors.dart';
 | |
| 
 | |
| class WorkSetPage extends StatefulWidget {
 | |
|   const WorkSetPage({super.key});
 | |
| 
 | |
|   @override
 | |
|   State<WorkSetPage> createState() => _WorkSetPageState();
 | |
| }
 | |
| 
 | |
| class _WorkSetPageState extends State<WorkSetPage> {
 | |
|   DateTime _focusedDay = DateTime.now();
 | |
|   DateTime _selectedDay = DateTime.now();
 | |
| 
 | |
|   Map<String, dynamic> dayWork = {};
 | |
|   late List<dynamic> _list = [];
 | |
|   String title="";
 | |
|   String content="";
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     // TODO: implement initState
 | |
|     super.initState();
 | |
| 
 | |
|     _getAnPai();
 | |
|     String data= DateFormat('yyyy-MM-dd').format(DateTime.now());
 | |
|     _getRiCheng(data,false);
 | |
|   }
 | |
| 
 | |
|   Future<void> _getAnPai() async {
 | |
|     try {
 | |
| 
 | |
|       final result = await ApiService.getAnPai();
 | |
|       if (result['result'] == 'success') {
 | |
|         setState(() {
 | |
|           dayWork= result;
 | |
|         });
 | |
| 
 | |
|       }else{
 | |
|         _showMessage('加载数据失败');
 | |
|       }
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _getRiCheng(String data, bool bool) async {
 | |
|     try {
 | |
|       _list.clear();
 | |
| 
 | |
|       final result = await ApiService.getRiCheng(data);
 | |
| 
 | |
|       if (result['result'] == 'success') {
 | |
|         setState(() {
 | |
|           final List<dynamic> newList = result['varList'] ?? [];
 | |
|             _list.addAll(newList);
 | |
| 
 | |
|         });
 | |
|         if(bool) {
 | |
|           if ( _list.isNotEmpty) {
 | |
|             title = _list[0]["title"];
 | |
|             content = _list[0]["desc"];
 | |
|             selectDate();
 | |
|           } else {
 | |
|             title = "";
 | |
|             content = "";
 | |
|             selectDate();
 | |
|           }
 | |
|         }
 | |
|       }else{
 | |
|         _showMessage('加载数据失败');
 | |
|       }
 | |
| 
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> _addRiCheng(String title, String content) async {
 | |
|     try {
 | |
| 
 | |
|       String urlPath;
 | |
|       String id;
 | |
|       if(_list.isNotEmpty){
 | |
|         urlPath="edit";
 | |
|         id=_list[0]["id"];
 | |
|       }else{
 | |
|         urlPath="add";
 | |
|         id=Random().nextDouble().toString();
 | |
|       }
 | |
|       String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
 | |
|       final result = await ApiService.addRiCheng(data,title,content,id,urlPath);
 | |
|       if (result['result'] == 'success') {
 | |
|         setState(() {
 | |
|           ToastUtil.showNormal(context, '保存成功');
 | |
|           // _showMessage('保存成功');
 | |
|           String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
 | |
|           _getRiCheng(data,false);
 | |
|         });
 | |
| 
 | |
|       }else{
 | |
|         _showMessage('加载数据失败');
 | |
|       }
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void _goToToday() {
 | |
|     setState(() {
 | |
|       _focusedDay = DateTime.now();
 | |
|       _selectedDay = DateTime.now();
 | |
|       // selectDate();
 | |
|       getInfoDate();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   void _goToPrevMonth() {
 | |
|     setState(() {
 | |
|       _focusedDay = DateTime(_focusedDay.year, _focusedDay.month - 1);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   void _goToNextMonth() {
 | |
|     setState(() {
 | |
|       _focusedDay = DateTime(_focusedDay.year, _focusedDay.month + 1);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   void getInfoDate() {
 | |
|     String data= DateFormat('yyyy-MM-dd').format(_selectedDay);
 | |
|     _getRiCheng(data,true);
 | |
|   }
 | |
|   void selectDate() {
 | |
| 
 | |
|     print("======$_selectedDay");
 | |
| 
 | |
|     showWorkAlert(
 | |
|       context: context,
 | |
|       alertTitle: "标题:",
 | |
|       inputHint: "请输入",
 | |
|       contentHint: "请输入",
 | |
|       initialTitle: title,
 | |
|       initialContent: content,
 | |
|       onConfirm: (title, content) {
 | |
|         // 处理确定后的逻辑
 | |
|         // print("标题: $title");
 | |
|         // print("内容: $content");
 | |
| 
 | |
|         _addRiCheng(title,content);
 | |
|       },
 | |
|       onCancel: () {
 | |
|         // 处理取消逻辑
 | |
|         print("用户取消了操作");
 | |
|       },
 | |
|     );
 | |
| 
 | |
| 
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Scaffold(
 | |
|       backgroundColor: h_backGroundColor(),
 | |
|       appBar: MyAppbar(title: "工作安排"),
 | |
|       body: Column(
 | |
|         children: [
 | |
|           Padding(
 | |
|             padding: const EdgeInsets.symmetric(vertical: 1),
 | |
|             child: _calendarHeader(),
 | |
|           ),
 | |
|           Container(
 | |
|             padding: EdgeInsets.only(top: 10),
 | |
|             color: Colors.white,
 | |
|             child: TableCalendar(
 | |
|               locale: 'zh_CN', // 👈 设置为中文
 | |
|               firstDay: DateTime(2000),
 | |
|               lastDay: DateTime(2100),
 | |
|               focusedDay: _focusedDay,
 | |
|               selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
 | |
|               onDaySelected: (selectedDay, focusedDay) {
 | |
|                 setState(() {
 | |
|                   _selectedDay = selectedDay;
 | |
|                   _focusedDay = focusedDay;
 | |
|                   // selectDate();
 | |
|                   getInfoDate();
 | |
|                 });
 | |
|               },
 | |
|               daysOfWeekStyle: DaysOfWeekStyle(
 | |
|                 dowTextFormatter: (date, locale) {
 | |
|                   // date.weekday: 1=Mon ... 7=Sun
 | |
|                   const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
 | |
|                   return weekdays[date.weekday % 7]; // 0=Sun
 | |
|                 },
 | |
|                 weekdayStyle: const TextStyle(
 | |
|                   fontWeight: FontWeight.bold,
 | |
|                   color: Colors.black87,
 | |
|                 ),
 | |
|                 weekendStyle: const TextStyle(
 | |
|                   fontWeight: FontWeight.bold,
 | |
|                   color: Colors.black45,
 | |
|                 ),
 | |
|               ),
 | |
|               calendarFormat: CalendarFormat.month,
 | |
|               startingDayOfWeek: StartingDayOfWeek.sunday,
 | |
|               headerVisible: false,
 | |
|               enabledDayPredicate: (day) {
 | |
|                 //  禁用非当前月份日期
 | |
|                 return day.month == _focusedDay.month;
 | |
|               },
 | |
|               calendarStyle: const CalendarStyle(
 | |
|                 outsideTextStyle: TextStyle(color: Colors.grey),
 | |
|                 outsideDecoration: BoxDecoration(
 | |
|                   color: Colors.transparent,
 | |
|                   shape: BoxShape.rectangle,
 | |
|                 ),
 | |
|                 todayDecoration: BoxDecoration(
 | |
|                   color: Colors.transparent, // 不再使用默认 today 样式
 | |
|                 ),
 | |
|                 selectedDecoration: BoxDecoration(
 | |
|                   color: Colors.blue,
 | |
|                   shape: BoxShape.circle,
 | |
|                 ),
 | |
|               ),
 | |
|               calendarBuilders: CalendarBuilders(
 | |
|                 defaultBuilder: (context, day, focusedDay) {
 | |
|                   return _buildDayCell(day);
 | |
|                 },
 | |
|                 outsideBuilder: (context, day, focusedDay) {
 | |
|                   return _buildDayCell(day, isOutside: true);
 | |
|                 },
 | |
|                 todayBuilder: (context, day, focusedDay) {
 | |
|                   return _buildDayCell(day);
 | |
|                 },
 | |
|                 selectedBuilder: (context, day, focusedDay) {
 | |
|                   return _buildDayCell(day, isSelected: true);
 | |
|                 },
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|           Container(color: h_backGroundColor(), height: 10),
 | |
|           _workTipWidget(),
 | |
|           Container(color: h_backGroundColor(), height: 10),
 | |
|           _workRiCheng(),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   /// 本日工作题型
 | |
|   Widget _workTipWidget() {
 | |
|     return Container(
 | |
|       color: Colors.white,
 | |
|       padding: EdgeInsets.all(12),
 | |
|       child: Column(
 | |
|         spacing: 20,
 | |
|         children: [
 | |
|           Row(
 | |
|             mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|             children: [
 | |
|               Text("本日工作题型", style: TextStyle(fontSize: 16)),
 | |
|               Spacer(),
 | |
|             ],
 | |
|           ),
 | |
|           Column(
 | |
|             spacing: 5,
 | |
|             children: [
 | |
|               _itemCell("已进行${dayWork["fxyjcNum"]??"0"}项隐患排查", true),
 | |
|               _itemCell("需进行${dayWork["fxwjcNum"]??"0"}项隐患排查", false),
 | |
|               _itemCell("已进行${dayWork["yhyjcNum"]??"0"}项标准排查", true),
 | |
|               _itemCell("需进行${dayWork["yhwjcNum"]??"0"}项标准排查", false),
 | |
|             ],
 | |
| 
 | |
|           ),
 | |
| 
 | |
| 
 | |
|         ],
 | |
| 
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   /// 本日工作题型
 | |
|   Widget _workRiCheng() {
 | |
|     return Container(
 | |
|       color: Colors.white,
 | |
|       padding: EdgeInsets.all(12),
 | |
|       child: Column(
 | |
|         spacing: 20,
 | |
|         children: [
 | |
|           Row(
 | |
|             mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|             children: [
 | |
|               Text("本日日程安排", style: TextStyle(fontSize: 16)),
 | |
|               Spacer(),
 | |
|             ],
 | |
|           ),
 | |
| 
 | |
|           if(_list.isNotEmpty)
 | |
|           _itemRiCheng(_list[0]["desc"])
 | |
|           // if(_list.isEmpty)
 | |
|           // ListView.separated(
 | |
|           //   separatorBuilder: (_, __) => const Divider(height: 1),
 | |
|           //   itemCount: _list.length,
 | |
|           //   itemBuilder: (context, index) {
 | |
|           //     final item = _list[index];
 | |
|           //     return _itemRiCheng(item);
 | |
|           //   },
 | |
|           // ),
 | |
|         ],
 | |
| 
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _itemCell(final String title, bool isFinish) {
 | |
|     return Row(
 | |
|       mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|       children: [
 | |
|         Row(
 | |
|           spacing: 5,
 | |
|           children: [
 | |
|             Icon(Icons.circle, size: 10, color: Colors.blue),
 | |
|             Text(title, style: TextStyle(color: Colors.black45),),
 | |
|           ],
 | |
|         ),
 | |
|         Text(isFinish?"已完成":"未完成", style: TextStyle(color: isFinish?Colors.green:Colors.red)),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _itemRiCheng(final String title) {
 | |
|     return Row(
 | |
|       mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|       children: [
 | |
|         Row(
 | |
|           spacing: 5,
 | |
|           children: [
 | |
|             Icon(Icons.circle, size: 10, color: Colors.blue),
 | |
|             Text(title, style: TextStyle(color: Colors.black45),),
 | |
|           ],
 | |
|         ),
 | |
| 
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   ///日历头
 | |
|   Widget _calendarHeader() {
 | |
|     return Container(
 | |
|       color: Colors.white,
 | |
|       child: Row(
 | |
|         mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|         children: [
 | |
|           // 占位
 | |
|           const Spacer(),
 | |
|           const Spacer(),
 | |
|           // 中间内容:← 年月 →
 | |
|           Row(
 | |
|             mainAxisSize: MainAxisSize.min,
 | |
|             children: [
 | |
|               IconButton(
 | |
|                 icon: const Icon(Icons.chevron_left),
 | |
|                 onPressed: _goToPrevMonth,
 | |
|                 padding: EdgeInsets.zero,
 | |
|                 constraints: const BoxConstraints(),
 | |
|               ),
 | |
|               const SizedBox(width: 4),
 | |
|               Text(
 | |
|                 DateFormat('yyyy年MM月').format(_focusedDay),
 | |
|                 style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
 | |
|               ),
 | |
|               const SizedBox(width: 4),
 | |
|               IconButton(
 | |
|                 icon: const Icon(Icons.chevron_right),
 | |
|                 onPressed: _goToNextMonth,
 | |
|                 padding: EdgeInsets.zero,
 | |
|                 constraints: const BoxConstraints(),
 | |
|               ),
 | |
|             ],
 | |
|           ),
 | |
|           const Spacer(),
 | |
|           Container(
 | |
|             height: 24,
 | |
|             decoration: BoxDecoration(
 | |
|               color: h_backGroundColor(),
 | |
|               borderRadius: const BorderRadius.only(
 | |
|                 topLeft: Radius.circular(12),
 | |
|                 bottomLeft: Radius.circular(12),
 | |
|               ),
 | |
|             ),
 | |
|             child: TextButton(
 | |
|               onPressed: _goToToday,
 | |
|               style: TextButton.styleFrom(
 | |
|                 padding: const EdgeInsets.symmetric(horizontal: 7),
 | |
|                 minimumSize: Size.zero,
 | |
|                 tapTargetSize: MaterialTapTargetSize.shrinkWrap,
 | |
|               ),
 | |
|               child: const Text("回到今天", style: TextStyle(fontSize: 11)),
 | |
|             ),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildDayCell(
 | |
|     DateTime day, {
 | |
|     bool isSelected = false,
 | |
|     bool isOutside = false,
 | |
|   }) {
 | |
|     final bool isToday = isSameDay(day, DateTime.now());
 | |
|     final bool selected = isSameDay(day, _selectedDay);
 | |
| 
 | |
|     Color textColor;
 | |
|     if (selected) {
 | |
|       textColor = Colors.white;
 | |
|     } else if (isOutside) {
 | |
|       textColor = Colors.grey;
 | |
|     } else {
 | |
|       textColor = Colors.black87;
 | |
|     }
 | |
| 
 | |
|     return Column(
 | |
|       mainAxisAlignment: MainAxisAlignment.center,
 | |
|       children: [
 | |
|         Container(
 | |
|           width: 35,
 | |
|           height: 35,
 | |
|           alignment: Alignment.center,
 | |
|           decoration: BoxDecoration(
 | |
|             color: selected ? Colors.blue : Colors.transparent,
 | |
|             shape: BoxShape.circle,
 | |
|           ),
 | |
|           child: Text(
 | |
|             '${day.day}',
 | |
|             style: TextStyle(color: textColor, fontWeight: FontWeight.w500),
 | |
|           ),
 | |
|         ),
 | |
|         if (isToday)
 | |
|           Text(
 | |
|             "今天",
 | |
|             style: TextStyle(
 | |
|               fontSize: 12,
 | |
|               color: selected ? Colors.white : Colors.blue,
 | |
|             ),
 | |
|           ),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void _showMessage(String msg) {
 | |
|     ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
 | |
|   }
 | |
| }
 |