2025.8.1 已还记录基本完成,有bug正在改
							parent
							
								
									ef5b1ff229
								
							
						
					
					
						commit
						853000839d
					
				|  | @ -45,3 +45,6 @@ app.*.map.json | |||
| /android/app/release | ||||
| /android/key.properties | ||||
| /android/app/build.gradle.kts | ||||
| 
 | ||||
| # 或更精确的忽略 | ||||
| build.gradle.kts | ||||
|  |  | |||
|  | @ -1863,5 +1863,75 @@ U6Hzm1ninpWeE+awIDAQAB | |||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /// 暂存隐患记录 | ||||
|   static Future<Map<String, dynamic>> temporaryStorageOfHidden( | ||||
|       String msg,item,unqualifiedInspectionItemID, | ||||
|       String hazardDescription,String partDescription,String latitude,String longitude, | ||||
|       String dangerDetail,String dataTime,String type,String responsibleId, | ||||
|       String yinHuanTypeIds,String hazardLeve,String buMenId,String buMenPDId, | ||||
|       String yinHuanTypeNames,String hiddenType1,String hiddenType2,String hiddenType3,) { | ||||
|     return HttpManager().request( | ||||
|       basePath, | ||||
|       '/app/customHidden/$msg', | ||||
|       method: Method.post, | ||||
|       data: { | ||||
|         "HIDDEN_ID":unqualifiedInspectionItemID, | ||||
| 
 | ||||
| 
 | ||||
|         "CUSTOM_ID": item["CUSTOM_ID"]??"", | ||||
|         "CUSTOM_ITEM_ID": item["CUSTOM_ITEM_ID"]??"", | ||||
|         "RECORDITEM_ID": item["RECORDITEM_ID"]??"", | ||||
|         "CHECK_CATEGORY": item["CHECK_CATEGORY"]??"", | ||||
|         "CHECK_CATEGORY_NAME": item["CHECK_CATEGORY_NAME"]??"", | ||||
|         "CHECK_ITEM": item["CHECK_ITEM"]??"", | ||||
|         "CHECK_ITEM_NAME":item["CHECK_ITEM_NAME"]??"", | ||||
|         "CHECK_CONTENT": item["CHECK_CONTENT"]??"", | ||||
|         "CHECK_STANDARD": item["CHECK_STANDARD"]??"", | ||||
|         "REFERENCE_BASIS":item["REFERENCE_BASIS"] ??"", | ||||
|         "SOURCE": '2', | ||||
|         "STATE": '0', | ||||
| 
 | ||||
| 
 | ||||
|         "HIDDENDESCR": hazardDescription, | ||||
|         "HIDDENPART": partDescription, | ||||
|         "LATITUDE": latitude, | ||||
|         "LONGITUDE": longitude, | ||||
| 
 | ||||
|         "RECTIFYDESCR": dangerDetail, | ||||
|         "RECTIFICATIONDEADLINE": dataTime, | ||||
|         "RECTIFICATIONTYPE": type, | ||||
|         "RECTIFICATIONOR": responsibleId, | ||||
| 
 | ||||
|         "HIDDENTYPE": yinHuanTypeIds, | ||||
|         "HIDDENLEVEL":hazardLeve, | ||||
|         "RECTIFICATIONDEPT": buMenId, | ||||
|         "HIDDENFINDDEPT": buMenPDId.isNotEmpty?buMenPDId:buMenId, | ||||
| 
 | ||||
|         "CREATOR": SessionService.instance.loginUserId, | ||||
|         "HIDDENTYPE_NAME": yinHuanTypeNames, | ||||
|         "HIDDENTYPE1": hiddenType1 , | ||||
|         "HIDDENTYPE2": hiddenType2 , | ||||
|         "HIDDENTYPE3": hiddenType3 , | ||||
|         "CORPINFO_ID": SessionService.instance.corpinfoId, | ||||
|         "USER_ID": SessionService.instance.loginUserId, | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /// 获取暂存隐患记录 | ||||
|   static Future<Map<String, dynamic>> getTemporaryStorageOfHidden(String id) { | ||||
|     return HttpManager().request( | ||||
|       basePath, | ||||
|       '/app/customHidden/goEdit', | ||||
|       method: Method.post, | ||||
|       data: { | ||||
|         "HIDDEN_ID": id, | ||||
|         "CORPINFO_ID": SessionService.instance.corpinfoId, | ||||
|         "USER_ID":SessionService.instance.loginUserId, | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,753 @@ | |||
| import 'dart:convert'; | ||||
| import 'dart:io'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:geolocator/geolocator.dart'; | ||||
| import 'package:intl/intl.dart'; | ||||
| import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; | ||||
| import 'package:qhd_prevention/customWidget/bottom_picker.dart'; | ||||
| import 'package:qhd_prevention/customWidget/bottom_picker_two.dart'; | ||||
| import 'package:qhd_prevention/customWidget/custom_button.dart'; | ||||
| import 'package:qhd_prevention/customWidget/date_picker_dialog.dart'; | ||||
| import 'package:qhd_prevention/customWidget/department_person_picker.dart'; | ||||
| import 'package:qhd_prevention/customWidget/department_picker.dart'; | ||||
| import 'package:qhd_prevention/customWidget/department_picker_hidden_type.dart'; | ||||
| import 'package:qhd_prevention/customWidget/department_picker_two.dart'; | ||||
| import 'package:qhd_prevention/customWidget/toast_util.dart'; | ||||
| import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; | ||||
| import 'package:qhd_prevention/pages/my_appbar.dart'; | ||||
| import 'package:qhd_prevention/tools/tools.dart'; | ||||
| import '../../../customWidget/photo_picker_row.dart'; | ||||
| import '../../../http/ApiService.dart'; | ||||
| 
 | ||||
| class HazardRegistrationPage extends StatefulWidget { | ||||
|   const HazardRegistrationPage(this.item, this.result,  {super.key,required this.onClose}); | ||||
| 
 | ||||
|   final item; | ||||
|   final Map<String, dynamic> result; | ||||
|   final Function(String) onClose; | ||||
|   @override | ||||
|   State<HazardRegistrationPage> createState() => _HazardRegistrationPageState(); | ||||
| } | ||||
| 
 | ||||
| class _HazardRegistrationPageState extends State<HazardRegistrationPage> { | ||||
|   final _standardController = TextEditingController(); | ||||
|   final _partController = TextEditingController(); | ||||
|   final _dangerDetailController = TextEditingController(); | ||||
| 
 | ||||
| 
 | ||||
|    String _repairLevelName = ""; | ||||
|   String hazardLeve =""; | ||||
|   late bool _isDanger = false;//true 1 false 2 | ||||
|   late bool _canClick = true; | ||||
|   late List<dynamic> _hazardLeveLlist = []; //隐患级别 | ||||
|   // 存储各单位的人员列表 | ||||
|   List<Map<String, dynamic>> _personCache = []; | ||||
| 
 | ||||
| 
 | ||||
|   List<String> _yinHuanImages = []; | ||||
|   List<String> _yinHuanVido = []; | ||||
|   // String _yinHuanVido=""; | ||||
|   dynamic _hazardLeve; | ||||
|   String yinHuanId = ""; | ||||
|   String yinHuanName = ""; | ||||
|   String buMenId = ""; | ||||
|   String buMenPDId = ""; | ||||
|   String buMenName = ""; | ||||
|   String responsibleId=""; | ||||
|   String responsibleName=""; | ||||
|   String dataTime = ""; | ||||
| 
 | ||||
|   List<String> _zhengGaiImages = []; | ||||
|   List<String> _yinHuanTypeIds = []; | ||||
|   List<String> _yinHuanTypeNames = []; | ||||
| 
 | ||||
|    String unqualifiedInspectionItemID=""; | ||||
|   String neiRong=""; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     // TODO: implement initState | ||||
|     super.initState(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     setState(() { | ||||
|       neiRong=widget.item['CHECK_CONTENT'] ?? ''; | ||||
|       _standardController.text=widget.item["CHECK_UNQUALIFIED"]??""; | ||||
|     }); | ||||
|     unqualifiedInspectionItemID=SessionService.instance.unqualifiedInspectionItemID.toString(); | ||||
|     setState(() { | ||||
|       if(unqualifiedInspectionItemID.isNotEmpty){ | ||||
|         List<dynamic> hImgs=widget.result["hImgs"]; | ||||
|         List<dynamic> rImgs=widget.result["rImgs"]; | ||||
|         dynamic pd=widget.result["pd"]; | ||||
| 
 | ||||
|         for(int i=0;i<hImgs.length;i++){ | ||||
|           if (hImgs[i]['FILEPATH'].toString().endsWith('.mp4')) { | ||||
|             _yinHuanVido.add(ApiService.baseImgPath +hImgs[i]['FILEPATH']); | ||||
|           } else { | ||||
|             _yinHuanImages.add(ApiService.baseImgPath +hImgs[i]["FILEPATH"]); | ||||
|           } | ||||
|         } | ||||
|         // _yinHuanVido视频 | ||||
|         // _yinHuanImages= hImgs.map((e) =>  ApiService.baseImgPath +e["FILEPATH"]).toList(); | ||||
|         _standardController.text=pd["HIDDENDESCR"]; | ||||
|         _partController.text=pd["HIDDENPART"]; | ||||
|          _repairLevelName =pd["HIDDENLEVELNAME"]; | ||||
|          hazardLeve =pd["HIDDENLEVEL"]; | ||||
|         _yinHuanTypeIds= pd["HIDDENTYPE"].toString().split(","); | ||||
|         _yinHuanTypeNames= pd["HIDDENTYPE_NAME"].toString().split("/"); | ||||
|         yinHuanName=pd["HIDDENTYPE_NAME"].toString(); | ||||
| 
 | ||||
|         if(pd["RECTIFICATIONTYPE"]==1){ | ||||
|           _isDanger=true; | ||||
|         }else{ | ||||
|           _isDanger=false; | ||||
|         } | ||||
| 
 | ||||
|         buMenId=pd["RECTIFICATIONDEPT"]; | ||||
|         buMenPDId=pd["HIDDENFINDDEPT"]; | ||||
|         buMenName=pd["RECTIFICATIONDEPTNAME"]; | ||||
|         responsibleId=pd["RECTIFICATIONOR"]; | ||||
|         responsibleName=pd["RECTIFICATIONORNAME"]; | ||||
|         dataTime=pd["RECTIFICATIONDEADLINE"]; | ||||
| 
 | ||||
|         _dangerDetailController.text=pd["RECTIFYDESCR"]; | ||||
|         _zhengGaiImages= rImgs.map((e) =>  ApiService.baseImgPath +e["FILEPATH"]).toList(); | ||||
|         // _zhengGaiImages整改图片"rImgs" -> [_GrowableList] | ||||
| 
 | ||||
|       } | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     _getHazardLevel(); | ||||
| 
 | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _getHazardLevel() async { | ||||
|     try { | ||||
|       final result = await ApiService.getHazardLevel(); | ||||
|       if (result['result'] == 'success') { | ||||
|         final List<dynamic> newList = result['list'] ?? []; | ||||
|         setState(() { | ||||
|           _hazardLeveLlist.addAll(newList); | ||||
|         }); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error fetching data: $e'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   void dispose() { | ||||
|     _standardController.dispose(); | ||||
|     _partController.dispose(); | ||||
|     _dangerDetailController.dispose(); | ||||
|     super.dispose(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|       appBar: MyAppbar(title: "隐患登记"), | ||||
|       body: Column( | ||||
|         children: [ | ||||
|           // 详情滚动区域 | ||||
|           _pageDetail(), | ||||
|           // 底部警示文字,固定在页面底部 | ||||
|           // Container( | ||||
|           //   padding: const EdgeInsets.all(15), | ||||
|           //   color: Colors.white, | ||||
|           //   child: Text( | ||||
|           //     '        严禁在本互联网非涉密平台处理、传输国家秘密和工作秘密,请确认扫描、传输的文件资料不涉及国家秘密和工作秘密', | ||||
|           //     style: TextStyle(fontSize: 14, color: Colors.red), | ||||
|           //   ), | ||||
|           // ), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Widget _buildSectionContainer({required Widget child}) { | ||||
|     return Container( | ||||
|       margin: const EdgeInsets.only(top: 10), | ||||
|       color: Colors.white, | ||||
|       padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), | ||||
|       child: child, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Widget _pageDetail() { | ||||
|     return Expanded( | ||||
|       child: SingleChildScrollView( | ||||
|         padding: const EdgeInsets.only(bottom: 20), | ||||
|         child: Column( | ||||
|           crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|           children: [ | ||||
| 
 | ||||
|             _buildSectionContainer( | ||||
|               child: ItemListWidget.multiLineTitleTextField( | ||||
|                 label: '检查内容:', | ||||
|                 isEditable: false, | ||||
|                 text: widget.item['CHECK_CONTENT'] ?? '', | ||||
|               ), | ||||
|             ), | ||||
| 
 | ||||
|             _buildSectionContainer( | ||||
|               child: RepairedPhotoSection( | ||||
|                 title: "隐患照片", | ||||
|                 maxCount: 4, | ||||
|                 mediaType: MediaType.image, | ||||
|                 initialMediaPaths:_yinHuanImages, | ||||
|                 isShowAI: true, | ||||
|                 onMediaAdded: (value) { | ||||
|                   _yinHuanImages.add(value); | ||||
|                 }, | ||||
|                 onMediaRemoved: (value) { | ||||
| 
 | ||||
|                 }, | ||||
|                 onChanged: (List<File> files) { | ||||
|                   // // 上传图片 files | ||||
|                   // _yinHuanImages.clear(); | ||||
|                   // for(int i=0;i<files.length;i++){ | ||||
|                   //   _yinHuanImages.add(files[i].path); | ||||
|                   // } | ||||
|                 }, | ||||
|                 onAiIdentify: () { | ||||
|                   // AI 识别逻辑 | ||||
|                   if(_yinHuanImages.isEmpty){ | ||||
|                     ToastUtil.showNormal(context, "请先上传一张图片"); | ||||
|                     return; | ||||
|                   } | ||||
|                   if(_yinHuanImages.length>1){ | ||||
|                     ToastUtil.showNormal(context, "识别暂时只能上传一张图片"); | ||||
|                     return; | ||||
|                   } | ||||
|                   _identifyImg(_yinHuanImages[0]); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|             _buildSectionContainer( | ||||
|               child: RepairedPhotoSection( | ||||
|                 title: "隐患视频", | ||||
|                 maxCount: 1, | ||||
|                 mediaType: MediaType.video, | ||||
|                 initialMediaPaths: _yinHuanVido, | ||||
|                 onMediaAdded: (value) { | ||||
|                   _yinHuanVido.add(value); | ||||
|                 }, | ||||
|                 onChanged: (List<File> files) { | ||||
|                   // 上传视频 files | ||||
|                   // _yinHuanVido=files[0].path; | ||||
|                 }, | ||||
|                 onAiIdentify: () { | ||||
|                   // AI 视频识别逻辑 | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|             _buildSectionContainer( | ||||
|               child: ListItemFactory.createBuildMultilineInput( | ||||
|                 "隐患描述", | ||||
|                 "请对隐患进行详细描述(必填项)", | ||||
|                 _standardController, | ||||
|               ), | ||||
|             ), | ||||
|             _buildSectionContainer( | ||||
|               child: ListItemFactory.createBuildMultilineInput( | ||||
|                 "隐患部位", | ||||
|                 "请对隐患部位进行详细描述(必填项)", | ||||
|                 _partController, | ||||
|               ), | ||||
|             ), | ||||
|             GestureDetector( | ||||
|                 onTap: () async { | ||||
|                   String choice = await BottomPickerTwo.show<String>( | ||||
|                     context, | ||||
|                     items: _hazardLeveLlist, | ||||
|                     itemBuilder: (item) => Text(item["NAME"], textAlign: TextAlign.center), | ||||
|                     initialIndex: 0, | ||||
|                   ); | ||||
|                   if (choice != null) { | ||||
|                     for(int i=0;i<_hazardLeveLlist.length;i++){ | ||||
|                       if(choice==_hazardLeveLlist[i]["NAME"]){ | ||||
|                         _hazardLeve = _hazardLeveLlist[i]; | ||||
|                       } | ||||
|                     } | ||||
| 
 | ||||
|                     setState(() { | ||||
|                       _repairLevelName=_hazardLeve["NAME"]; | ||||
|                       hazardLeve = _hazardLeve["BIANMA"]; | ||||
|                       if("5ff9daf78e9a4fb1b40d77980656799d"==_hazardLeve["DICTIONARIES_ID"]){ | ||||
|                         _isDanger=false; | ||||
|                         _canClick=false; | ||||
|                       }else{ | ||||
|                         _canClick=true; | ||||
|                       } | ||||
| 
 | ||||
|                     }); | ||||
|                   } | ||||
|                 }, | ||||
|                 child: _buildSectionContainer( | ||||
|               child: ListItemFactory.createRowSpaceBetweenItem( | ||||
|                 leftText: "隐患级别", | ||||
|                 rightText: _repairLevelName.isNotEmpty?_repairLevelName:"请选择", | ||||
|                 isRight: true, | ||||
|               ), | ||||
|             ), | ||||
|             ), | ||||
|             GestureDetector( | ||||
|               onTap: () { | ||||
|                 showModalBottomSheet( | ||||
|                   context: context, | ||||
|                   isScrollControlled: true, | ||||
|                   barrierColor: Colors.black54, | ||||
|                   backgroundColor: Colors.transparent, | ||||
|                   builder: | ||||
|                       (ctx) => DepartmentPickerHiddenType( | ||||
|                         onSelected: (jsonString) { | ||||
|                           Map<String, List<String>> result = jsonString; | ||||
|                            _yinHuanTypeIds = List<String>.from(result['id']!); | ||||
|                            _yinHuanTypeNames = List<String>.from(result['name']!); | ||||
|                           setState(() { | ||||
|                             yinHuanName=_yinHuanTypeNames[_yinHuanTypeNames.length-1]; | ||||
|                           }); | ||||
| 
 | ||||
| 
 | ||||
|                           // print(jsonEncode(json)); | ||||
|                           // List<String> _yinHuanTypeIds = []; | ||||
|                           // List<String> _yinHuanTypeNames = []; | ||||
|                         }, | ||||
|                       ), | ||||
|                 ); | ||||
|               }, | ||||
|               child: _buildSectionContainer( | ||||
|                 child: ListItemFactory.createRowSpaceBetweenItem( | ||||
|                   leftText: "隐患类型", | ||||
|                   rightText: yinHuanName.isNotEmpty?truncateText(yinHuanName):"请选择", | ||||
|                   isRight: true, | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             _buildSectionContainer( | ||||
|               child: ListItemFactory.createYesNoSectionTwo( | ||||
|                 title: "是否立即整改", | ||||
|                 horizontalPadding: 0, | ||||
|                 verticalPadding: 0, | ||||
|                 yesLabel: "是", | ||||
|                 noLabel: "否", | ||||
|                 groupValue: _isDanger, | ||||
|                 canClick: _canClick, | ||||
|                 context:context, | ||||
|                 onChanged: (val) { | ||||
|                   setState(() { | ||||
|                     _isDanger = val; | ||||
|                   }); | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|             if (_isDanger) | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   _buildSectionContainer( | ||||
|                     child: ListItemFactory.createBuildMultilineInput( | ||||
|                       "整改描述", | ||||
|                       "请对隐患进行整改描述(必填项)", | ||||
|                       _dangerDetailController, | ||||
|                     ), | ||||
|                   ), | ||||
|                   SizedBox(height: 10), | ||||
|                   _buildSectionContainer( | ||||
|                     child: RepairedPhotoSection( | ||||
|                       title: "整改后图片", | ||||
|                       maxCount: 4, | ||||
|                       horizontalPadding: 0, | ||||
|                       mediaType: MediaType.image, | ||||
|                       isShowAI: false, | ||||
|                       initialMediaPaths: _zhengGaiImages, | ||||
|                       onMediaAdded: (value) { | ||||
|                         _zhengGaiImages.add(value); | ||||
|                       }, | ||||
|                       onChanged: (List<File> files) { | ||||
|                         // 上传图片 files | ||||
|                         // _zhengGaiImages.clear(); | ||||
|                         // for(int i=0;i<files.length;i++){ | ||||
|                         //   _zhengGaiImages.add(files[i].path); | ||||
|                         // } | ||||
| 
 | ||||
|                       }, | ||||
|                       onAiIdentify: () { | ||||
| 
 | ||||
|                       }, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
|             if (!_isDanger) | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   GestureDetector( | ||||
|                     onTap: () { | ||||
|                       showModalBottomSheet( | ||||
|                         context: context, | ||||
|                         isScrollControlled: true, | ||||
|                         barrierColor: Colors.black54, | ||||
|                         backgroundColor: Colors.transparent, | ||||
|                         builder: | ||||
|                             (ctx) => DepartmentPickerTwo( | ||||
|                               onSelected: (id, name,pdId) async { | ||||
|                                 setState(() { | ||||
|                                   buMenId = id; | ||||
|                                   buMenName = name; | ||||
|                                   buMenPDId=pdId; | ||||
| 
 | ||||
|                                   responsibleId=""; | ||||
|                                   responsibleName=""; | ||||
|                                 }); | ||||
|                                 // 拉取该单位的人员列表并缓存 | ||||
|                                 final result = await ApiService.getListTreePersonList(id); | ||||
|                                 _personCache=List<Map<String, dynamic>>.from( | ||||
|                                   result['userList'] as List, | ||||
|                                 ); | ||||
|                               }, | ||||
|                             ), | ||||
|                       ); | ||||
|                     }, | ||||
|                     child: _buildSectionContainer( | ||||
|                       child: ListItemFactory.createRowSpaceBetweenItem( | ||||
|                         leftText: "整改责任部门", | ||||
|                         rightText: buMenName.isNotEmpty ? buMenName : "请选择", | ||||
|                         isRight: true, | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
| 
 | ||||
| 
 | ||||
|                   SizedBox(height: 10), | ||||
| 
 | ||||
|                   GestureDetector( | ||||
|                     onTap: () { | ||||
|                       if ( buMenId.isEmpty) { | ||||
|                         ToastUtil.showNormal(context, '请先选择部门'); | ||||
|                         return; | ||||
|                       } | ||||
|                       DepartmentPersonPicker.show( | ||||
|                         context, | ||||
|                         personsData: _personCache, | ||||
|                         onSelected: (userId, name) { | ||||
|                           setState(() { | ||||
|                             // renYuanId = userId; | ||||
|                             // renYuanName = name; | ||||
| 
 | ||||
|                             responsibleId=userId; | ||||
|                             responsibleName=name; | ||||
| 
 | ||||
|                           }); | ||||
| 
 | ||||
|                         }, | ||||
|                       ); | ||||
|                     }, | ||||
|                     child:Container( | ||||
|                       padding: EdgeInsets.symmetric(horizontal: 15), | ||||
|                       decoration: BoxDecoration( | ||||
|                         color: Colors.white, | ||||
|                         borderRadius: BorderRadius.circular(5), | ||||
|                       ), | ||||
|                       child: ListItemFactory.createRowSpaceBetweenItem( | ||||
|                         leftText: "整改负责人", | ||||
|                         rightText: responsibleName.isNotEmpty?responsibleName:"请选择", | ||||
|                         isRight: true, | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
| 
 | ||||
|                   GestureDetector( | ||||
|                     onTap: () { | ||||
|                       showDialog( | ||||
|                         context: context, | ||||
|                         builder: | ||||
|                             (_) => HDatePickerDialog( | ||||
|                               initialDate: DateTime.now(), | ||||
|                               onCancel: () => Navigator.of(context).pop(), | ||||
|                               onConfirm: (selected) async { | ||||
|                                 Navigator.of(context).pop(); | ||||
|                                 setState(() { | ||||
|                                   dataTime = DateFormat( | ||||
|                                     'yyyy-MM-dd', | ||||
|                                   ).format(selected); | ||||
|                                 }); | ||||
| 
 | ||||
| 
 | ||||
|                               }, | ||||
|                             ), | ||||
|                       ); | ||||
|                     }, | ||||
|                     child: _buildSectionContainer( | ||||
|                       child: ListItemFactory.createRowSpaceBetweenItem( | ||||
|                         leftText: "整改期限", | ||||
|                         rightText: dataTime.isNotEmpty ? dataTime : "请选择", | ||||
|                         isRight: true, | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ], | ||||
|               ), | ||||
| 
 | ||||
|             SizedBox(height: 30), | ||||
|             CustomButton( | ||||
|               onPressed: () { | ||||
|                 _riskListCheckAppAdd(); | ||||
|               }, | ||||
|               text: "提交", | ||||
|               backgroundColor: Colors.blue, | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _riskListCheckAppAdd() async { | ||||
|     LoadingDialogHelper.show(context); | ||||
|     if(_yinHuanImages.isEmpty){ | ||||
|       ToastUtil.showNormal(context, "请上传隐患图片"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     String hazardDescription=_standardController.text.trim(); | ||||
|     if(hazardDescription.isEmpty){ | ||||
|       ToastUtil.showNormal(context, "请填隐患描述"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     String partDescription=_partController.text.trim(); | ||||
|     if(partDescription.isEmpty){ | ||||
|       ToastUtil.showNormal(context, "请填隐患部位"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     if(hazardLeve.isEmpty){ | ||||
|       ToastUtil.showNormal(context, "请选择隐患级别"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     if(_yinHuanTypeIds.isEmpty){ | ||||
|       ToastUtil.showNormal(context, "请选择隐患类型"); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     String type="1"; | ||||
|     String dangerDetail=""; | ||||
|     if(_isDanger){ | ||||
|       type="1"; | ||||
|        dangerDetail=_dangerDetailController.text.trim(); | ||||
|       if(dangerDetail.isEmpty){ | ||||
|         ToastUtil.showNormal(context, "请填整改描述"); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       if(_zhengGaiImages.isEmpty){ | ||||
|         ToastUtil.showNormal(context, "请上传整改后图片"); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     }else{ | ||||
|       type="2"; | ||||
|       if(buMenId.isEmpty){ | ||||
|         ToastUtil.showNormal(context, "请选择整改部门"); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       if(responsibleId.isEmpty){ | ||||
|         ToastUtil.showNormal(context, "请选择整改人"); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       if(dataTime.isEmpty){ | ||||
|         ToastUtil.showNormal(context, "请选择整改期限"); | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     String yinHuanTypeIds=""; | ||||
|     String yinHuanTypeNames=""; | ||||
|     for(int i=0;i<_yinHuanTypeIds.length;i++){ | ||||
|      String yinHuanTypeId= _yinHuanTypeIds[i]; | ||||
|      String yinHuanTypeName= _yinHuanTypeNames[i]; | ||||
|      if(yinHuanTypeIds.isEmpty){ | ||||
|        yinHuanTypeIds=yinHuanTypeId; | ||||
|      }else{ | ||||
|        yinHuanTypeIds="$yinHuanTypeIds,$yinHuanTypeId"; | ||||
|      } | ||||
|      if(yinHuanTypeNames.isEmpty){ | ||||
|        yinHuanTypeNames=yinHuanTypeName; | ||||
|      }else{ | ||||
|        yinHuanTypeNames="$yinHuanTypeNames/$yinHuanTypeName"; | ||||
|      } | ||||
|     } | ||||
| 
 | ||||
|     String hiddenType1=""; | ||||
|     if(_yinHuanTypeIds.length>1){ | ||||
|       hiddenType1=_yinHuanTypeIds[0]; | ||||
|     } | ||||
|     String hiddenType2=""; | ||||
|     if(_yinHuanTypeIds.length>2){ | ||||
|       hiddenType1=_yinHuanTypeIds[1]; | ||||
|     } | ||||
|     String hiddenType3=""; | ||||
|     if(_yinHuanTypeIds.length>3){ | ||||
|       hiddenType1=_yinHuanTypeIds[2]; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     //获取定位 | ||||
|     Position position = await _determinePosition(); | ||||
|     String longitude=position.longitude.toString(); | ||||
|     String latitude=position.latitude.toString(); | ||||
|      | ||||
|     try { | ||||
|       final result = await ApiService.temporaryStorageOfHidden( | ||||
|         unqualifiedInspectionItemID.isNotEmpty?"edit":"add",widget.item,unqualifiedInspectionItemID, | ||||
|          hazardDescription, partDescription, latitude, longitude, | ||||
|          dangerDetail, dataTime, type, responsibleId, | ||||
|          yinHuanTypeIds, hazardLeve, buMenId, buMenPDId, | ||||
|          yinHuanTypeNames, hiddenType1, hiddenType2, hiddenType3,); | ||||
|       if (result['result'] == 'success') { | ||||
| 
 | ||||
|         String hiddenId = result['pd']['HIDDEN_ID'] ; | ||||
|         SessionService.instance.setUnqualifiedInspectionItemIDJson(hiddenId); | ||||
| 
 | ||||
|             for (int i=0;i<_yinHuanImages.length;i++){ | ||||
|               _addImgFiles(_yinHuanImages[i],"3",hiddenId); | ||||
|             } | ||||
| 
 | ||||
|             if(_yinHuanVido.isNotEmpty) { | ||||
|               _addImgFiles(_yinHuanVido[0],"3",hiddenId); | ||||
|             } | ||||
| 
 | ||||
|           if(_isDanger){ | ||||
|             for (int i=0;i<_zhengGaiImages.length;i++){ | ||||
|               _addImgFiles(_zhengGaiImages[i],"4",hiddenId); | ||||
|             } | ||||
|           } | ||||
|         LoadingDialogHelper.hide(context); | ||||
|         setState(() { | ||||
|           ToastUtil.showNormal(context, "提交成功"); | ||||
|           Navigator.pop(context); | ||||
|           widget.onClose(hiddenId); | ||||
|         }); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       LoadingDialogHelper.hide(context); | ||||
|       print('Error fetching data: $e'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   Future<String> _addImgFiles(String imagePath,String type,String id) async { | ||||
|     try { | ||||
| 
 | ||||
|       final raw = await ApiService.addImgFiles( imagePath, type, id); | ||||
|       if (raw['result'] == 'success') { | ||||
|         return raw['imgPath']; | ||||
|       }else{ | ||||
|         // _showMessage('反馈提交失败'); | ||||
|         return ""; | ||||
|       } | ||||
| 
 | ||||
|     } catch (e) { | ||||
|       // 出错时可以 Toast 或者在页面上显示错误状态 | ||||
|       print('加载首页数据失败:$e'); | ||||
|       return ""; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   Future<void> _identifyImg(String imagePath) async { | ||||
|     try { | ||||
|       LoadingDialogHelper.show(context); | ||||
|       final raw = await ApiService.identifyImg( imagePath); | ||||
|       if (raw['result'] == 'success') { | ||||
|         final List<dynamic> newList = raw['aiHiddens'] ?? []; | ||||
| 
 | ||||
|         String miaoShuText=""; | ||||
|         String zhengGaiText=""; | ||||
|         for(int i=0;i<newList.length;i++){ | ||||
|           // 1. 将字符串解析为 Map | ||||
|           final Map<String, dynamic> item1 = jsonDecode(newList[i]); | ||||
|           if(miaoShuText.isEmpty){ | ||||
|             miaoShuText=item1["hiddenDescr"]; | ||||
|           }else{ | ||||
|             miaoShuText=miaoShuText+";"+item1["hiddenDescr"]; | ||||
|           } | ||||
| 
 | ||||
|           if(zhengGaiText.isEmpty){ | ||||
|             zhengGaiText=item1["rectificationSuggestions"]; | ||||
|           }else{ | ||||
|             zhengGaiText=zhengGaiText+";"+item1["rectificationSuggestions"]; | ||||
|           } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         LoadingDialogHelper.hide(context); | ||||
|         setState(() { | ||||
|           _isDanger=true; | ||||
|           _standardController.text=miaoShuText; | ||||
|           _dangerDetailController.text=zhengGaiText; | ||||
|         }); | ||||
|       }else{ | ||||
|         ToastUtil.showNormal(context, "识别失败"); | ||||
|         LoadingDialogHelper.hide(context); | ||||
|         // _showMessage('反馈提交失败'); | ||||
|         // return ""; | ||||
|       } | ||||
| 
 | ||||
|     } catch (e) { | ||||
|       // 出错时可以 Toast 或者在页面上显示错误状态 | ||||
|       print('加载首页数据失败:$e'); | ||||
|       // return ""; | ||||
|       LoadingDialogHelper.hide(context); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<Position> _determinePosition() async { | ||||
|     bool serviceEnabled; | ||||
|     LocationPermission permission; | ||||
| 
 | ||||
|     // 检查定位服务是否启用 | ||||
|     serviceEnabled = await Geolocator.isLocationServiceEnabled(); | ||||
|     if (!serviceEnabled) { | ||||
|       return Future.error('Location services are disabled.'); | ||||
|     } | ||||
| 
 | ||||
|     // 获取权限 | ||||
|     permission = await Geolocator.checkPermission(); | ||||
|     if (permission == LocationPermission.denied) { | ||||
|       permission = await Geolocator.requestPermission(); | ||||
|       if (permission == LocationPermission.denied) { | ||||
|         return Future.error('Location permissions are denied'); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (permission == LocationPermission.deniedForever) { | ||||
|       return Future.error( | ||||
|           'Location permissions are permanently denied, we cannot request permissions.'); | ||||
|     } | ||||
| 
 | ||||
|     // 获取当前位置 | ||||
|     return await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); | ||||
|   } | ||||
| 
 | ||||
|   String truncateText(String text, {int maxLength = 17}) { | ||||
|     if (text.length <= maxLength) return text; | ||||
|     return '${text.substring(0, maxLength)}...'; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -3,6 +3,7 @@ import 'package:flutter_html/flutter_html.dart'; | |||
| import 'package:qhd_prevention/customWidget/toast_util.dart'; | ||||
| import 'package:qhd_prevention/http/ApiService.dart'; | ||||
| import 'package:qhd_prevention/pages/app/Danger_paicha/danger_image_updata_page.dart'; | ||||
| import 'package:qhd_prevention/pages/app/Danger_paicha/hazard_registration_page.dart'; | ||||
| import 'package:qhd_prevention/tools/h_colors.dart'; | ||||
| import 'package:qhd_prevention/tools/tools.dart'; | ||||
| import 'package:qhd_prevention/pages/my_appbar.dart'; | ||||
|  | @ -42,11 +43,15 @@ class _DangerProjectPageState extends State<DangerProjectPage> { | |||
|   ]; | ||||
| 
 | ||||
|   List<dynamic> listDates = []; | ||||
| 
 | ||||
|   String unqualifiedInspectionItemID=""; | ||||
|   Map<String, dynamic> nullResult={}; | ||||
|   @override | ||||
|   void initState() { | ||||
|     // TODO: implement initState | ||||
|     super.initState(); | ||||
| 
 | ||||
|     SessionService.instance.setUnqualifiedInspectionItemIDJson(""); | ||||
| 
 | ||||
|     _getInvestigationItems(); | ||||
|   } | ||||
| 
 | ||||
|  | @ -181,8 +186,13 @@ class _DangerProjectPageState extends State<DangerProjectPage> { | |||
|                         icon: option['icon'], | ||||
|                         color: option['color'], | ||||
|                         screenWidth: screenWidth, | ||||
|                         item: item, | ||||
|                         onImageTap: () { | ||||
|                           _getAlreadyUpImages(item); | ||||
|                              if(_selectedValue=="option1") { | ||||
|                                _getAlreadyUpImages(item); | ||||
|                              }else if(_selectedValue=="option2") { | ||||
|                               _goUnqualifiedPage(item); | ||||
|                              } | ||||
|                         }, | ||||
|                       ); | ||||
|                     }).toList(), | ||||
|  | @ -246,6 +256,7 @@ class _DangerProjectPageState extends State<DangerProjectPage> { | |||
|     required IconData icon, | ||||
|     required Color color, | ||||
|     required double screenWidth, | ||||
|     required dynamic item, | ||||
|     VoidCallback? onImageTap, | ||||
|   }) { | ||||
|     final isSelected = _selectedValue == value; | ||||
|  | @ -254,27 +265,37 @@ class _DangerProjectPageState extends State<DangerProjectPage> { | |||
|     return GestureDetector( | ||||
|       onTap: () { | ||||
|         setState(() { | ||||
|           _selectedValue = value; | ||||
|           if(value!="option2") { | ||||
|             SessionService.instance.setUnqualifiedInspectionItemIDJson(""); | ||||
|             _selectedValue = value; | ||||
|           }else{ | ||||
|             _goUnqualifiedPage(item); | ||||
|             // pushPage(HazardRegistrationPage(item), context); | ||||
|           } | ||||
|         }); | ||||
|       }, | ||||
|       child: Container( | ||||
|         width: buttonWidth, | ||||
|         padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), | ||||
|         padding: const EdgeInsets.symmetric(vertical: 12), | ||||
| 
 | ||||
|         child: Row( | ||||
|         child: Expanded(child: Row( | ||||
|           mainAxisSize: MainAxisSize.min, | ||||
|           mainAxisAlignment: MainAxisAlignment.start, | ||||
|           children: [ | ||||
|             Icon(icon, color: isSelected ? color : Colors.grey, size: 30), | ||||
|             const SizedBox(width: 8), | ||||
|             Text( | ||||
|               label, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 14, | ||||
|                 fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, | ||||
|                 color: isSelected ? color : Colors.grey[600], | ||||
|             Row(children: [ | ||||
|               Icon(icon, color: isSelected ? color : Colors.grey, size: 30), | ||||
|               const SizedBox(width: 8), | ||||
|               Text( | ||||
|                 label, | ||||
|                 style: TextStyle( | ||||
|                   fontSize: 14, | ||||
|                   fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, | ||||
|                   color: isSelected ? color : Colors.grey[600], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             if(value=="option1"&&_selectedValue=="option1") | ||||
|             ],), | ||||
|             if((value=="option1"&&_selectedValue=="option1")|| | ||||
|                 (value=="option2"&&_selectedValue=="option2"&&unqualifiedInspectionItemID.isNotEmpty)) | ||||
|             // 添加图片点击处理 | ||||
|               GestureDetector( | ||||
|                 onTap: () { | ||||
|  | @ -294,11 +315,74 @@ class _DangerProjectPageState extends State<DangerProjectPage> { | |||
|                 ), | ||||
|               ), | ||||
|           ], | ||||
|         ), | ||||
|         )), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   void _goUnqualifiedPage(item) { | ||||
|     String hiddenId=SessionService.instance.unqualifiedInspectionItemID.toString(); | ||||
|     if(hiddenId.isNotEmpty) { | ||||
|       _getTemporaryStorageOfHidden(item,hiddenId); | ||||
|     }else{ | ||||
|       pushPage(HazardRegistrationPage( | ||||
|           item,nullResult, | ||||
|           onClose: (String departmentId) { | ||||
|             setState(() { | ||||
|               _selectedValue="option2"; | ||||
|               unqualifiedInspectionItemID=departmentId; | ||||
|             }); | ||||
| 
 | ||||
|         }, | ||||
|       ), context); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _getTemporaryStorageOfHidden(Map item,String hiddenId) async { | ||||
| 
 | ||||
|     try { | ||||
|       final result = await ApiService.getTemporaryStorageOfHidden(hiddenId); | ||||
|       if (result['result'] == 'success') { | ||||
| 
 | ||||
|         pushPage(HazardRegistrationPage( | ||||
|           item,result, | ||||
|           onClose: (String departmentId) { | ||||
|             setState(() { | ||||
|               _selectedValue="option2"; | ||||
|               unqualifiedInspectionItemID=departmentId; | ||||
|             }); | ||||
| 
 | ||||
|           }, | ||||
|         ), context); | ||||
| 
 | ||||
|         // final List<dynamic> newList = result['imgs'] ?? []; | ||||
|         // List<PhotoItem> imgList = []; | ||||
|         // for (Map item in newList) { | ||||
|         //   String id = item['IMGFILES_ID'] ?? ''; | ||||
|         //   String filePath = item['FILEPATH'] ?? ''; | ||||
|         //   imgList.add( | ||||
|         //     PhotoItem( | ||||
|         //       id: id, // 新图片没有ID | ||||
|         //       filePath: ApiService.baseImgPath+filePath, | ||||
|         //       type: "1", | ||||
|         //     ), | ||||
|         //   ); | ||||
|         // } | ||||
|         // pushPage(DangerImageUpdataPage(item["RECORDITEM_ID"], imgList: imgList), context); | ||||
| 
 | ||||
|       } else { | ||||
|         ToastUtil.showNormal(context, "加载数据失败"); | ||||
|         // _showMessage('加载数据失败'); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       // 出错时可以 Toast 或者在页面上显示错误状态 | ||||
|       print('加载数据失败:$e'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   void _submit() { | ||||
|     if (_selectedValue == null) return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -182,6 +182,7 @@ class SessionService { | |||
|   String? departmentJsonStr; | ||||
|   String? departmentHiddenTypeJsonStr; | ||||
|   String? customRecordDangerJson; | ||||
|   String? unqualifiedInspectionItemID; | ||||
| 
 | ||||
|   /// 如果以下任何一项为空,则跳转到登录页 | ||||
|   void loginSession(BuildContext context) { | ||||
|  | @ -223,6 +224,9 @@ class SessionService { | |||
| 
 | ||||
|   void setCustomRecordDangerJson(String json) => customRecordDangerJson = json; | ||||
| 
 | ||||
|   void setUnqualifiedInspectionItemIDJson(String json) => unqualifiedInspectionItemID = json; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /// ------------------------------------------------------ | ||||
|  |  | |||
							
								
								
									
										278
									
								
								pubspec.lock
								
								
								
								
							
							
						
						
									
										278
									
								
								pubspec.lock
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue