2025.7.29 隐患快报完成
							parent
							
								
									d672f1d944
								
							
						
					
					
						commit
						0238689f1a
					
				|  | @ -1,4 +1,5 @@ | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:qhd_prevention/customWidget/toast_util.dart'; | ||||||
| 
 | 
 | ||||||
| import '../http/ApiService.dart'; | import '../http/ApiService.dart'; | ||||||
| import '../tools/tools.dart'; | import '../tools/tools.dart'; | ||||||
|  | @ -365,4 +366,77 @@ class ListItemFactory { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |   ///  分类头部 | ||||||
|  |   static Widget createYesNoSectionTwo({ | ||||||
|  |     required String title, | ||||||
|  |     required String yesLabel, | ||||||
|  |     required String noLabel, | ||||||
|  |     required bool groupValue, | ||||||
|  |     required bool canClick, | ||||||
|  |     required BuildContext context, | ||||||
|  |     required ValueChanged<bool> onChanged, | ||||||
|  |     double verticalPadding = 15, | ||||||
|  |     double horizontalPadding = 10, | ||||||
|  |   }) { | ||||||
|  |     return Padding( | ||||||
|  |       padding: EdgeInsets.only(top: 0, right: horizontalPadding, left: horizontalPadding, bottom: verticalPadding), | ||||||
|  |       child: Container( | ||||||
|  |         padding: EdgeInsets.symmetric(horizontal: 10), | ||||||
|  |         decoration: BoxDecoration( | ||||||
|  |           color: Colors.white, | ||||||
|  |           borderRadius: BorderRadius.circular(5), | ||||||
|  |         ), | ||||||
|  |         child: Row( | ||||||
|  |           children: [ | ||||||
|  |             Expanded( | ||||||
|  |               child: Text( | ||||||
|  |                 title, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   fontSize: 15, | ||||||
|  |                   fontWeight: FontWeight.bold, | ||||||
|  |                   color: Colors.black, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             Row( | ||||||
|  |               children: [ | ||||||
|  |                 Row( | ||||||
|  |                   children: [ | ||||||
|  |                     Radio<bool>( | ||||||
|  |                       activeColor: Colors.blue, | ||||||
|  |                       value: true, | ||||||
|  |                       groupValue: groupValue, | ||||||
|  |                       onChanged:(val) { | ||||||
|  |                         if(canClick){ | ||||||
|  |                           onChanged(val!); | ||||||
|  |                         }else{ | ||||||
|  |                           ToastUtil.showNormal(context, "重大隐患不允许选此项"); | ||||||
|  |                         } | ||||||
|  |                       } | ||||||
|  |                       // (val) => onChanged(val!), | ||||||
|  |                     ), | ||||||
|  |                     Text(yesLabel), | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |                 const SizedBox(width: 16), | ||||||
|  |                 Row( | ||||||
|  |                   children: [ | ||||||
|  |                     Radio<bool>( | ||||||
|  |                       activeColor: Colors.blue, | ||||||
|  |                       value: false, | ||||||
|  |                       groupValue: groupValue, | ||||||
|  |                       onChanged: (val) => onChanged(val!), | ||||||
|  |                     ), | ||||||
|  |                     Text(noLabel), | ||||||
|  |                   ], | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ class BottomPickerTwo { | ||||||
|         double height = 250, |         double height = 250, | ||||||
|       }) { |       }) { | ||||||
|     // 当前选中项 |     // 当前选中项 | ||||||
|     T selected = items[initialIndex]; |     dynamic selected = items[initialIndex]; | ||||||
| 
 | 
 | ||||||
|     return showModalBottomSheet<T>( |     return showModalBottomSheet<T>( | ||||||
|       context: context, |       context: context, | ||||||
|  | @ -55,7 +55,7 @@ class BottomPickerTwo { | ||||||
|                       child: const Text('取消'), |                       child: const Text('取消'), | ||||||
|                     ), |                     ), | ||||||
|                     TextButton( |                     TextButton( | ||||||
|                       onPressed: () => Navigator.of(ctx).pop(selected), |                       onPressed: () => Navigator.of(ctx).pop(selected["NAME"]), | ||||||
|                       child: const Text('确定'), |                       child: const Text('确定'), | ||||||
|                     ), |                     ), | ||||||
|                   ], |                   ], | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ class DepartmentPickerHiddenType extends StatefulWidget { | ||||||
| class _DepartmentPickerHiddenTypeState | class _DepartmentPickerHiddenTypeState | ||||||
|     extends State<DepartmentPickerHiddenType> { |     extends State<DepartmentPickerHiddenType> { | ||||||
|   String selectedId = ''; |   String selectedId = ''; | ||||||
|  |   String selectedName = ''; | ||||||
|   Set<String> expandedSet = {}; |   Set<String> expandedSet = {}; | ||||||
|   List<Category> original = []; |   List<Category> original = []; | ||||||
|   List<Category> filtered = []; |   List<Category> filtered = []; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,226 @@ | ||||||
|  | import 'dart:convert'; | ||||||
|  | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; | ||||||
|  | import 'package:qhd_prevention/http/ApiService.dart'; | ||||||
|  | import '../tools/tools.dart'; // 包含 SessionService | ||||||
|  | 
 | ||||||
|  | // 数据模型 | ||||||
|  | class Category { | ||||||
|  |   final String id; | ||||||
|  |   final String name; | ||||||
|  |   final String pdId; | ||||||
|  |   final List<Category> children; | ||||||
|  | 
 | ||||||
|  |   Category({ | ||||||
|  |     required this.id, | ||||||
|  |     required this.name, | ||||||
|  |     required this.pdId, | ||||||
|  |     this.children = const [], | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   factory Category.fromJson(Map<String, dynamic> json) { | ||||||
|  |     return Category( | ||||||
|  |       id: json['id'] as String, | ||||||
|  |       name: json['name'] as String, | ||||||
|  |       pdId: json['PARENT_ID'] as String, | ||||||
|  |       children: (json['children'] as List<dynamic>) | ||||||
|  |           .map((e) => Category.fromJson(e as Map<String, dynamic>)) | ||||||
|  |           .toList(), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// 弹窗回调签名:返回选中项的 id 和 name | ||||||
|  | typedef DeptSelectCallback = void Function(String id, String name,String pdId); | ||||||
|  | 
 | ||||||
|  | class DepartmentPickerTwo extends StatefulWidget { | ||||||
|  |   /// 回调,返回选中部门 id 与 name | ||||||
|  |   final DeptSelectCallback onSelected; | ||||||
|  | 
 | ||||||
|  |   const DepartmentPickerTwo({Key? key, required this.onSelected}) : super(key: key); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   _DepartmentPickerTwoState createState() => _DepartmentPickerTwoState(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class _DepartmentPickerTwoState extends State<DepartmentPickerTwo> { | ||||||
|  |   String selectedId = ''; | ||||||
|  |   String selectedPDId = ''; | ||||||
|  |   String selectedName = ''; | ||||||
|  |   Set<String> expandedSet = {}; | ||||||
|  | 
 | ||||||
|  |   List<Category> original = []; | ||||||
|  |   List<Category> filtered = []; | ||||||
|  |   bool loading = true; | ||||||
|  | 
 | ||||||
|  |   final TextEditingController _searchController = TextEditingController(); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     super.initState(); | ||||||
|  |     // 初始均为空 | ||||||
|  |     selectedId = ''; | ||||||
|  |     selectedName = ''; | ||||||
|  |     selectedPDId = ''; | ||||||
|  |     expandedSet = {}; | ||||||
|  |     _searchController.addListener(_onSearchChanged); | ||||||
|  |     _loadData(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   void dispose() { | ||||||
|  |     _searchController.removeListener(_onSearchChanged); | ||||||
|  |     _searchController.dispose(); | ||||||
|  |     super.dispose(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Future<void> _loadData() async { | ||||||
|  |     try { | ||||||
|  |       List<dynamic> raw; | ||||||
|  |       if (SessionService.instance.departmentJsonStr?.isNotEmpty ?? false) { | ||||||
|  |         raw = json.decode(SessionService.instance.departmentJsonStr!) as List<dynamic>; | ||||||
|  |       } else { | ||||||
|  |         final result = await ApiService.getHiddenTreatmentListTree(); | ||||||
|  |         final String nodes = result['zTreeNodes'] as String; | ||||||
|  |         SessionService.instance.departmentJsonStr = nodes; | ||||||
|  |         raw = json.decode(nodes) as List<dynamic>; | ||||||
|  |       } | ||||||
|  |       setState(() { | ||||||
|  |         original = raw.map((e) => Category.fromJson(e as Map<String, dynamic>)).toList(); | ||||||
|  |         filtered = original; | ||||||
|  |         loading = false; | ||||||
|  |       }); | ||||||
|  |     } catch (e) { | ||||||
|  |       setState(() => loading = false); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void _onSearchChanged() { | ||||||
|  |     final query = _searchController.text.toLowerCase().trim(); | ||||||
|  |     setState(() { | ||||||
|  |       filtered = query.isEmpty ? original : _filterCategories(original, query); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   List<Category> _filterCategories(List<Category> list, String query) { | ||||||
|  |     List<Category> result = []; | ||||||
|  |     for (var cat in list) { | ||||||
|  |       final children = _filterCategories(cat.children, query); | ||||||
|  |       if (cat.name.toLowerCase().contains(query) || children.isNotEmpty) { | ||||||
|  |         result.add(Category(id: cat.id, name: cat.name,pdId:cat.pdId, children: children)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Widget _buildRow(Category cat, int indent) { | ||||||
|  |     final hasChildren = cat.children.isNotEmpty; | ||||||
|  |     final isExpanded = expandedSet.contains(cat.id); | ||||||
|  |     final isSelected = cat.id == selectedId; | ||||||
|  |     return Column( | ||||||
|  |       children: [ | ||||||
|  |         InkWell( | ||||||
|  |           onTap: () { | ||||||
|  |             setState(() { | ||||||
|  |               if (hasChildren) { | ||||||
|  |                 isExpanded ? expandedSet.remove(cat.id) : expandedSet.add(cat.id); | ||||||
|  |                 selectedPDId=cat.pdId; | ||||||
|  |               }else{ | ||||||
|  |                 selectedPDId=cat.id; | ||||||
|  |               } | ||||||
|  |               selectedId = cat.id; | ||||||
|  |               selectedName = cat.name; | ||||||
|  | 
 | ||||||
|  |             }); | ||||||
|  |           }, | ||||||
|  |           child: Container( | ||||||
|  |             color: Colors.white, | ||||||
|  |             child: Row( | ||||||
|  |               children: [ | ||||||
|  |                 SizedBox(width: 16.0 * indent), | ||||||
|  |                 SizedBox( | ||||||
|  |                   width: 24, | ||||||
|  |                   child: hasChildren | ||||||
|  |                       ? Icon(isExpanded ? Icons.arrow_drop_down_rounded : Icons.arrow_right_rounded, | ||||||
|  |                       size: 35, color: Colors.grey[600]) | ||||||
|  |                       : const SizedBox.shrink(), | ||||||
|  |                 ), | ||||||
|  |                 const SizedBox(width: 5), | ||||||
|  |                 Expanded( | ||||||
|  |                   child: Padding( | ||||||
|  |                     padding: const EdgeInsets.symmetric(vertical: 12), | ||||||
|  |                     child: Text(cat.name), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 Padding( | ||||||
|  |                   padding: const EdgeInsets.symmetric(horizontal: 16), | ||||||
|  |                   child: Icon( | ||||||
|  |                     isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, | ||||||
|  |                     color: Colors.green, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         if (hasChildren && isExpanded) | ||||||
|  |           ...cat.children.map((c) => _buildRow(c, indent + 1)), | ||||||
|  |       ], | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     return Container( | ||||||
|  |       width: MediaQuery.of(context).size.width, | ||||||
|  |       height: MediaQuery.of(context).size.height * 0.7, | ||||||
|  |       color: Colors.white, | ||||||
|  |       child: Column( | ||||||
|  |         children: [ | ||||||
|  |           Container( | ||||||
|  |             color: Colors.white, | ||||||
|  |             padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | ||||||
|  |             child: Row( | ||||||
|  |               children: [ | ||||||
|  |                 GestureDetector( | ||||||
|  |                   onTap: () => Navigator.of(context).pop(), | ||||||
|  |                   child: const Text('取消', style: TextStyle(fontSize: 16)), | ||||||
|  |                 ), | ||||||
|  |                 Expanded( | ||||||
|  |                   child: Padding( | ||||||
|  |                     padding: const EdgeInsets.symmetric(horizontal: 12), | ||||||
|  |                     child: SearchBarWidget( | ||||||
|  |                       controller: _searchController, | ||||||
|  |                       isShowSearchButton: false, | ||||||
|  |                       onSearch: (keyboard) { | ||||||
|  |                       }, | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |                 GestureDetector( | ||||||
|  |                   onTap: () { | ||||||
|  |                     Navigator.of(context).pop(); | ||||||
|  |                     widget.onSelected(selectedId, selectedName,selectedPDId); | ||||||
|  |                   }, | ||||||
|  |                   child: const Text('确定', style: TextStyle(fontSize: 16, color: Colors.green)), | ||||||
|  |                 ), | ||||||
|  |               ], | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           Divider(), | ||||||
|  |           Expanded( | ||||||
|  |             child: loading | ||||||
|  |                 ? const Center(child: CircularProgressIndicator()) | ||||||
|  |                 : Container( | ||||||
|  |               color: Colors.white, | ||||||
|  |               child: ListView.builder( | ||||||
|  |                 itemCount: filtered.length, | ||||||
|  |                 itemBuilder: (ctx, idx) => _buildRow(filtered[idx], 0), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ], | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -819,7 +819,7 @@ U6Hzm1ninpWeE+awIDAQAB | ||||||
|     final fileName = file.path.split(Platform.pathSeparator).last; |     final fileName = file.path.split(Platform.pathSeparator).last; | ||||||
|     return HttpManager().uploadFaceImage( |     return HttpManager().uploadFaceImage( | ||||||
|         baseUrl: basePath, |         baseUrl: basePath, | ||||||
|         path: '/app/feedback/upload', |         path: '/app/imgfiles/add', | ||||||
|         fromData: { |         fromData: { | ||||||
|           'FOREIGN_KEY': id, |           'FOREIGN_KEY': id, | ||||||
|           'TYPE': type, |           'TYPE': type, | ||||||
|  | @ -834,6 +834,28 @@ U6Hzm1ninpWeE+awIDAQAB | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /// ai识别图片隐患 | ||||||
|  |   static Future<Map<String, dynamic>> identifyImg(String imagePath) async { | ||||||
|  |     final file = File(imagePath); | ||||||
|  |     if (!await file.exists()) { | ||||||
|  |       throw ApiException('file_not_found', '图片不存在:$imagePath'); | ||||||
|  |     } | ||||||
|  |     final fileName = file.path.split(Platform.pathSeparator).last; | ||||||
|  |     return HttpManager().uploadFaceImage( | ||||||
|  |         baseUrl: basePath, | ||||||
|  |         path: '/app/hidden/identifyImg', | ||||||
|  |         fromData: { | ||||||
|  |           'CORPINFO_ID': SessionService.instance.corpinfoId, | ||||||
|  |           'USER_ID': SessionService.instance.loginUserId, | ||||||
|  |           'FFILE': await MultipartFile.fromFile( | ||||||
|  |               file.path, | ||||||
|  |               filename: fileName | ||||||
|  |           ), | ||||||
|  |         } | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|   /// 修改密码 |   /// 修改密码 | ||||||
|   static Future<Map<String, dynamic>> changePassWord(String oldPwd,String confirmPwd) { |   static Future<Map<String, dynamic>> changePassWord(String oldPwd,String confirmPwd) { | ||||||
|     return HttpManager().request( |     return HttpManager().request( | ||||||
|  | @ -1411,6 +1433,45 @@ U6Hzm1ninpWeE+awIDAQAB | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /// 上传隐患快报 | ||||||
|  |   static Future<Map<String, dynamic>> addRiskListCheckApp( | ||||||
|  |       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/hidden/riskListCheckAppAdd', | ||||||
|  |       method: Method.post, | ||||||
|  |       data: { | ||||||
|  |         "HIDDEN_ID": "", | ||||||
|  |         "SOURCE": '1', | ||||||
|  |         "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, | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,15 +1,20 @@ | ||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:geolocator/geolocator.dart'; | ||||||
| import 'package:intl/intl.dart'; | import 'package:intl/intl.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; | import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/bottom_picker.dart'; | import 'package:qhd_prevention/customWidget/bottom_picker.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/bottom_picker_two.dart'; | import 'package:qhd_prevention/customWidget/bottom_picker_two.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/custom_button.dart'; | import 'package:qhd_prevention/customWidget/custom_button.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/date_picker_dialog.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.dart'; | ||||||
| import 'package:qhd_prevention/customWidget/department_picker_hidden_type.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/my_appbar.dart'; | import 'package:qhd_prevention/pages/my_appbar.dart'; | ||||||
|  | import 'package:qhd_prevention/tools/tools.dart'; | ||||||
| import '../../../customWidget/photo_picker_row.dart'; | import '../../../customWidget/photo_picker_row.dart'; | ||||||
| import '../../../http/ApiService.dart'; | import '../../../http/ApiService.dart'; | ||||||
| 
 | 
 | ||||||
|  | @ -25,21 +30,31 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|   final _partController = TextEditingController(); |   final _partController = TextEditingController(); | ||||||
|   final _dangerDetailController = TextEditingController(); |   final _dangerDetailController = TextEditingController(); | ||||||
| 
 | 
 | ||||||
|    String _repairLevel = ""; |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|  |    String _repairLevelName = ""; | ||||||
|   late bool _isDanger = false; |   late bool _isDanger = false; | ||||||
| 
 |   late bool _canClick = true; | ||||||
|   late List<dynamic> _hazardLeveLlist = []; //隐患级别 |   late List<dynamic> _hazardLeveLlist = []; //隐患级别 | ||||||
|  |   // 存储各单位的人员列表 | ||||||
|  |   List<Map<String, dynamic>> _personCache = []; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |   List<String> _yinHuanImages = []; | ||||||
|  |   String _yinHuanVido=""; | ||||||
|   dynamic _hazardLeve; |   dynamic _hazardLeve; | ||||||
|   String yinHuanId = ""; |   String yinHuanId = ""; | ||||||
|   String yinHuanName = ""; |   String yinHuanName = ""; | ||||||
|   String buMenId = ""; |   String buMenId = ""; | ||||||
|  |   String buMenPDId = ""; | ||||||
|   String buMenName = ""; |   String buMenName = ""; | ||||||
|  |   String responsibleId=""; | ||||||
|  |   String responsibleName=""; | ||||||
|   String dataTime = ""; |   String dataTime = ""; | ||||||
| 
 | 
 | ||||||
|  |   List<String> _zhengGaiImages = []; | ||||||
|  |   List<String> _yinHuanTypeIds = []; | ||||||
|  |   List<String> _yinHuanTypeNames = []; | ||||||
|  | 
 | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
|     // TODO: implement initState |     // TODO: implement initState | ||||||
|  | @ -52,7 +67,7 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|     try { |     try { | ||||||
|       final result = await ApiService.getHazardLevel(); |       final result = await ApiService.getHazardLevel(); | ||||||
|       if (result['result'] == 'success') { |       if (result['result'] == 'success') { | ||||||
|         final List<dynamic> newList = result['varList'] ?? []; |         final List<dynamic> newList = result['list'] ?? []; | ||||||
|         setState(() { |         setState(() { | ||||||
|           _hazardLeveLlist.addAll(newList); |           _hazardLeveLlist.addAll(newList); | ||||||
|         }); |         }); | ||||||
|  | @ -116,9 +131,22 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                 isShowAI: true, |                 isShowAI: true, | ||||||
|                 onChanged: (List<File> files) { |                 onChanged: (List<File> files) { | ||||||
|                   // 上传图片 files |                   // 上传图片 files | ||||||
|  |                   _yinHuanImages.clear(); | ||||||
|  |                   for(int i=0;i<files.length;i++){ | ||||||
|  |                     _yinHuanImages.add(files[i].path); | ||||||
|  |                   } | ||||||
|                 }, |                 }, | ||||||
|                 onAiIdentify: () { |                 onAiIdentify: () { | ||||||
|                   // AI 识别逻辑 |                   // AI 识别逻辑 | ||||||
|  |                   if(_yinHuanImages.isEmpty){ | ||||||
|  |                     ToastUtil.showNormal(context, "请先上传一张图片"); | ||||||
|  |                     return; | ||||||
|  |                   } | ||||||
|  |                   if(_yinHuanImages.length>1){ | ||||||
|  |                     ToastUtil.showNormal(context, "识别暂时只能上传一张图片"); | ||||||
|  |                     return; | ||||||
|  |                   } | ||||||
|  |                   _identifyImg(_yinHuanImages[0]); | ||||||
|                 }, |                 }, | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|  | @ -129,6 +157,7 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                 mediaType: MediaType.video, |                 mediaType: MediaType.video, | ||||||
|                 onChanged: (List<File> files) { |                 onChanged: (List<File> files) { | ||||||
|                   // 上传视频 files |                   // 上传视频 files | ||||||
|  |                   _yinHuanVido=files[0].path; | ||||||
|                 }, |                 }, | ||||||
|                 onAiIdentify: () { |                 onAiIdentify: () { | ||||||
|                   // AI 视频识别逻辑 |                   // AI 视频识别逻辑 | ||||||
|  | @ -151,23 +180,35 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|             ), |             ), | ||||||
|             GestureDetector( |             GestureDetector( | ||||||
|                 onTap: () async { |                 onTap: () async { | ||||||
|                   final choice = await BottomPickerTwo.show<String>( |                   String choice = await BottomPickerTwo.show<String>( | ||||||
|                     context, |                     context, | ||||||
|                     items: _hazardLeveLlist, |                     items: _hazardLeveLlist, | ||||||
|                     itemBuilder: (item) => Text(item, textAlign: TextAlign.center), |                     itemBuilder: (item) => Text(item["NAME"], textAlign: TextAlign.center), | ||||||
|                     initialIndex: 0, |                     initialIndex: 0, | ||||||
|                   ); |                   ); | ||||||
|                   if (choice != null) { |                   if (choice != null) { | ||||||
|  |                     for(int i=0;i<_hazardLeveLlist.length;i++){ | ||||||
|  |                       if(choice==_hazardLeveLlist[i]["NAME"]){ | ||||||
|  |                         _hazardLeve = _hazardLeveLlist[i]; | ||||||
|  |                       } | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     setState(() { |                     setState(() { | ||||||
|                       _hazardLeve = choice; |                       _repairLevelName=_hazardLeve["NAME"]; | ||||||
|                       _repairLevel=_hazardLeve[""]; |                       if("5ff9daf78e9a4fb1b40d77980656799d"==_hazardLeve["DICTIONARIES_ID"]){ | ||||||
|  |                         _isDanger=false; | ||||||
|  |                         _canClick=false; | ||||||
|  |                       }else{ | ||||||
|  |                         _canClick=true; | ||||||
|  |                       } | ||||||
|  | 
 | ||||||
|                     }); |                     }); | ||||||
|                   } |                   } | ||||||
|                 }, |                 }, | ||||||
|                 child: _buildSectionContainer( |                 child: _buildSectionContainer( | ||||||
|               child: ListItemFactory.createRowSpaceBetweenItem( |               child: ListItemFactory.createRowSpaceBetweenItem( | ||||||
|                 leftText: "隐患级别", |                 leftText: "隐患级别", | ||||||
|                 rightText: _repairLevel.isNotEmpty?_repairLevel:"请选择", |                 rightText: _repairLevelName.isNotEmpty?_repairLevelName:"请选择", | ||||||
|                 isRight: true, |                 isRight: true, | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|  | @ -181,9 +222,18 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                   backgroundColor: Colors.transparent, |                   backgroundColor: Colors.transparent, | ||||||
|                   builder: |                   builder: | ||||||
|                       (ctx) => DepartmentPickerHiddenType( |                       (ctx) => DepartmentPickerHiddenType( | ||||||
|                         onSelected: (json) { |                         onSelected: (jsonString) { | ||||||
|                           print(jsonEncode(json)); |                           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 = []; | ||||||
|                         }, |                         }, | ||||||
|                       ), |                       ), | ||||||
|                 ); |                 ); | ||||||
|  | @ -197,13 +247,15 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|             _buildSectionContainer( |             _buildSectionContainer( | ||||||
|               child: ListItemFactory.createYesNoSection( |               child: ListItemFactory.createYesNoSectionTwo( | ||||||
|                 title: "是否立即整改", |                 title: "是否立即整改", | ||||||
|                 horizontalPadding: 0, |                 horizontalPadding: 0, | ||||||
|                 verticalPadding: 0, |                 verticalPadding: 0, | ||||||
|                 yesLabel: "是", |                 yesLabel: "是", | ||||||
|                 noLabel: "否", |                 noLabel: "否", | ||||||
|                 groupValue: _isDanger, |                 groupValue: _isDanger, | ||||||
|  |                 canClick: _canClick, | ||||||
|  |                 context:context, | ||||||
|                 onChanged: (val) { |                 onChanged: (val) { | ||||||
|                   setState(() { |                   setState(() { | ||||||
|                     _isDanger = val; |                     _isDanger = val; | ||||||
|  | @ -231,8 +283,15 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                       isShowAI: false, |                       isShowAI: false, | ||||||
|                       onChanged: (List<File> files) { |                       onChanged: (List<File> files) { | ||||||
|                         // 上传图片 files |                         // 上传图片 files | ||||||
|  |                         _zhengGaiImages.clear(); | ||||||
|  |                         for(int i=0;i<files.length;i++){ | ||||||
|  |                           _zhengGaiImages.add(files[i].path); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                       }, | ||||||
|  |                       onAiIdentify: () { | ||||||
|  | 
 | ||||||
|                       }, |                       }, | ||||||
|                       onAiIdentify: () {}, |  | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
|                 ], |                 ], | ||||||
|  | @ -248,12 +307,21 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                         barrierColor: Colors.black54, |                         barrierColor: Colors.black54, | ||||||
|                         backgroundColor: Colors.transparent, |                         backgroundColor: Colors.transparent, | ||||||
|                         builder: |                         builder: | ||||||
|                             (ctx) => DepartmentPicker( |                             (ctx) => DepartmentPickerTwo( | ||||||
|                               onSelected: (id, name) async { |                               onSelected: (id, name,pdId) async { | ||||||
|                                 setState(() { |                                 setState(() { | ||||||
|                                   buMenId = id; |                                   buMenId = id; | ||||||
|                                   buMenName = name; |                                   buMenName = name; | ||||||
|  |                                   buMenPDId=pdId; | ||||||
|  | 
 | ||||||
|  |                                   responsibleId=""; | ||||||
|  |                                   responsibleName=""; | ||||||
|                                 }); |                                 }); | ||||||
|  |                                 // 拉取该单位的人员列表并缓存 | ||||||
|  |                                 final result = await ApiService.getListTreePersonList(id); | ||||||
|  |                                 _personCache=List<Map<String, dynamic>>.from( | ||||||
|  |                                   result['userList'] as List, | ||||||
|  |                                 ); | ||||||
|                               }, |                               }, | ||||||
|                             ), |                             ), | ||||||
|                       ); |                       ); | ||||||
|  | @ -266,6 +334,46 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                       ), |                       ), | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                   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( |                   GestureDetector( | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
|                       showDialog( |                       showDialog( | ||||||
|  | @ -274,13 +382,15 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|                             (_) => HDatePickerDialog( |                             (_) => HDatePickerDialog( | ||||||
|                               initialDate: DateTime.now(), |                               initialDate: DateTime.now(), | ||||||
|                               onCancel: () => Navigator.of(context).pop(), |                               onCancel: () => Navigator.of(context).pop(), | ||||||
|                               onConfirm: (selected) { |                               onConfirm: (selected) async { | ||||||
|                                 Navigator.of(context).pop(); |                                 Navigator.of(context).pop(); | ||||||
|                                 setState(() { |                                 setState(() { | ||||||
|                                   dataTime = DateFormat( |                                   dataTime = DateFormat( | ||||||
|                                     'yyyy-MM-dd', |                                     'yyyy-MM-dd', | ||||||
|                                   ).format(selected); |                                   ).format(selected); | ||||||
|                                 }); |                                 }); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|                               }, |                               }, | ||||||
|                             ), |                             ), | ||||||
|                       ); |                       ); | ||||||
|  | @ -298,7 +408,9 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
| 
 | 
 | ||||||
|             SizedBox(height: 30), |             SizedBox(height: 30), | ||||||
|             CustomButton( |             CustomButton( | ||||||
|               onPressed: () {}, |               onPressed: () { | ||||||
|  |                 _riskListCheckAppAdd(); | ||||||
|  |               }, | ||||||
|               text: "提交", |               text: "提交", | ||||||
|               backgroundColor: Colors.blue, |               backgroundColor: Colors.blue, | ||||||
|             ), |             ), | ||||||
|  | @ -307,4 +419,237 @@ class _QuickReportPageState extends State<QuickReportPage> { | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   Future<void> _riskListCheckAppAdd() async { | ||||||
|  |     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; | ||||||
|  |     } | ||||||
|  |     String hazardLeve = _hazardLeve["BIANMA"]; | ||||||
|  | 
 | ||||||
|  |     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.addRiskListCheckApp( | ||||||
|  |          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'] ; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             for (int i=0;i<_yinHuanImages.length;i++){ | ||||||
|  |               _addImgFiles(_yinHuanImages[i],"3",hiddenId); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             _addImgFiles(_yinHuanVido,"3",hiddenId); | ||||||
|  | 
 | ||||||
|  |           if(_isDanger){ | ||||||
|  |             for (int i=0;i<_zhengGaiImages.length;i++){ | ||||||
|  |               _addImgFiles(_zhengGaiImages[i],"4",hiddenId); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         setState(() { | ||||||
|  |           ToastUtil.showNormal(context, "提交成功"); | ||||||
|  |           Navigator.pop(context); | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |     } catch (e) { | ||||||
|  |       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); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										278
									
								
								pubspec.lock
								
								
								
								
							
							
						
						
									
										278
									
								
								pubspec.lock
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue