418 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			418 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:qhd_prevention/customWidget/toast_util.dart';
 | |
| import 'package:qhd_prevention/pages/my_appbar.dart';
 | |
| import 'package:qhd_prevention/tools/coord_convert.dart';
 | |
| import 'package:qhd_prevention/tools/tools.dart';
 | |
| import 'package:geolocator/geolocator.dart';
 | |
| import 'package:shared_preferences/shared_preferences.dart';
 | |
| 
 | |
| import '../../../http/ApiService.dart';
 | |
| import '../../../tools/h_colors.dart';
 | |
| 
 | |
| class RiskDetailPage extends StatefulWidget {
 | |
|   const RiskDetailPage({super.key, required this.itemData});
 | |
| 
 | |
|   final dynamic itemData;
 | |
| 
 | |
|   @override
 | |
|   State<RiskDetailPage> createState() => _RiskDetailPageState();
 | |
| }
 | |
| 
 | |
| class _RiskDetailPageState extends State<RiskDetailPage> {
 | |
| 
 | |
| 
 | |
|   late List<dynamic> _list = [];
 | |
|   // 风险等级文本
 | |
|   final List<String> _levelTexts = ["重大风险", "较大风险", "一般风险", "低风险"];
 | |
|   // 风险等级颜色
 | |
|   final List<Color> _fxColors = [
 | |
|     const Color(0xFFFADBD9),
 | |
|     const Color(0xFFFCE6D2),
 | |
|     const Color(0xFFFDF2CE),
 | |
|     const Color(0xFFCCE6FF),
 | |
|   ];
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     // TODO: implement initState
 | |
|     super.initState();
 | |
| 
 | |
|     _getForIdentification();
 | |
|   }
 | |
| 
 | |
| 
 | |
|   Future<void> _getForIdentification() async {
 | |
|     try {
 | |
| 
 | |
|       final result = await ApiService.getForIdentification(  widget.itemData["IDENTIFICATIONPARTS_ID"]);
 | |
| 
 | |
|       if (result['result'] == 'success') {
 | |
|         final List<dynamic> newList = result['varList'] ?? [];
 | |
|         setState(() {
 | |
|           _list.addAll(newList);
 | |
|         });
 | |
| 
 | |
| 
 | |
|       }else{
 | |
|         ToastUtil.showNormal(context, "加载数据失败");
 | |
|         // _showMessage('加载数据失败');
 | |
|       }
 | |
| 
 | |
|     } catch (e) {
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   Future<void> _addCoordinate() async {
 | |
|     try {
 | |
|       LoadingDialogHelper.show(message: "提交中...");
 | |
|       //获取定位
 | |
|       await fetchAndSaveBd09(context);
 | |
|       final prefs = await SharedPreferences.getInstance();
 | |
|       String latitude = prefs.getString('bd_lat') ?? '';
 | |
|       String longitude = prefs.getString('bd_lon') ?? '';
 | |
|       final result = await ApiService.addCoordinate(  widget.itemData["IDENTIFICATIONPARTS_ID"],
 | |
|           longitude,latitude);
 | |
|       LoadingDialogHelper.hide();
 | |
|       if (result['result'] == 'success') {
 | |
|         setState(() {
 | |
|           ToastUtil.showNormal(context, "提交成功");
 | |
|           // _showMessage('提交成功');
 | |
|           Navigator.pop(context);
 | |
|         });
 | |
| 
 | |
|       }else{
 | |
|         ToastUtil.showNormal(context, "提交失败");
 | |
|         // _showMessage('加载数据失败');
 | |
|       }
 | |
|     } catch (e) {
 | |
|       LoadingDialogHelper.hide();
 | |
|       // 出错时可以 Toast 或者在页面上显示错误状态
 | |
|       print('加载数据失败:$e');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Scaffold(
 | |
|       appBar: MyAppbar(title: "风险分布-详情"),
 | |
|       body: SafeArea(
 | |
|         child: LayoutBuilder(
 | |
|           builder: (context, constraints) {
 | |
|             // 设置底部最小高度,要预留出来
 | |
|             const double bottomAreaHeight = 100;
 | |
|             final double maxCardHeight =
 | |
|                 constraints.maxHeight - bottomAreaHeight-10;
 | |
| 
 | |
|             return Column(
 | |
|               children: [
 | |
|                 // 卡片区:最大高度受限
 | |
|                 Padding(
 | |
|                   padding:  EdgeInsets.all(15),
 | |
|                   child: ConstrainedBox(
 | |
|                     constraints: BoxConstraints(maxHeight: maxCardHeight),
 | |
|                     child: Container(
 | |
|                       decoration: BoxDecoration(
 | |
|                         color: Colors.white,
 | |
|                         borderRadius: BorderRadius.circular(5),
 | |
|                         boxShadow: [/* ... */],
 | |
|                       ),
 | |
|                       child: Column(
 | |
|                         mainAxisSize: MainAxisSize.min,
 | |
|                         crossAxisAlignment: CrossAxisAlignment.stretch,
 | |
|                         children: [
 | |
| 
 | |
|                           // ★ 这个 Flexible 包裹 SingleChildScrollView ★
 | |
|                           Flexible(
 | |
|                             fit: FlexFit.loose,
 | |
|                             child: SingleChildScrollView(
 | |
|                               padding: const EdgeInsets.symmetric(vertical: 10),
 | |
|                               physics: const ClampingScrollPhysics(),
 | |
|                               child: Column(
 | |
|                                 mainAxisSize: MainAxisSize.min,
 | |
|                                 children: [
 | |
| 
 | |
|                                   _buildHeader(),
 | |
|                                   const Divider(
 | |
|                                     height: .5,
 | |
|                                     thickness: .5,
 | |
|                                     color: Colors.grey,
 | |
|                                   ),
 | |
| 
 | |
|                                   _itemCell("存在风险",0),
 | |
|                                   _itemCell("主要管控措施",1),
 | |
|                                   _itemCell("管控部门",2),
 | |
|                                   _itemCell("事故类型",3),
 | |
|                                   const Divider(
 | |
|                                     height: .5,
 | |
|                                     thickness: .5,
 | |
|                                     color: Colors.grey,
 | |
|                                   ),
 | |
|                                   _buildFooter(),
 | |
|                                 ],
 | |
|                                 // children: _dataInfos.map(_itemCell).toList(),
 | |
|                               ),
 | |
|                             ),
 | |
|                           ),
 | |
| 
 | |
| 
 | |
|                         ],
 | |
|                       ),
 | |
|                     ),
 | |
|                   ),
 | |
|                 ),
 | |
|                 Spacer(),
 | |
|                 // 底部按钮固定
 | |
|                 _buildBottomButton(),
 | |
|                 SizedBox(height: 10,)
 | |
|               ],
 | |
|             );
 | |
|           },
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // 头部信息组件
 | |
|   Widget _buildHeader() {
 | |
|     return Padding(
 | |
|       padding:  EdgeInsets.only(top:5,left: 15,right: 15,bottom: 15),
 | |
|       child: Row(
 | |
|         mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|         crossAxisAlignment: CrossAxisAlignment.start,
 | |
|         children: [
 | |
|           Expanded(
 | |
|               child: Text(
 | |
|                 widget.itemData['RISKUNITNAME']?? "",
 | |
|                 style: TextStyle(fontSize: 16, color: Colors.black54),
 | |
|               ),
 | |
|           ),
 | |
|           SizedBox(width: 15,),
 | |
|           Expanded(
 | |
|           child: Text(
 | |
|                   widget.itemData['PARTSNAME'] ?? "未知地区",
 | |
|                   style: const TextStyle(fontSize: 16, color: Colors.black54),
 | |
|                 ),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // 风险等级标签
 | |
|   Widget _buildFooter() {
 | |
|     return Padding(
 | |
|       padding: const EdgeInsets.all(15),
 | |
|       child: Row(
 | |
|         children: [
 | |
|           Container(
 | |
|             margin: const EdgeInsets.only(bottom: 8),
 | |
|             padding: const EdgeInsets.all(5),
 | |
|             decoration: BoxDecoration(
 | |
|               color: _getLevelColor(),
 | |
|               borderRadius: BorderRadius.circular(2),
 | |
|             ),
 | |
|             child: Text(
 | |
|               _getLevel(),
 | |
|               style: TextStyle(color: Colors.black),
 | |
|             ),
 | |
|           ),
 | |
|           const Spacer(),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   String _getLevel(){
 | |
|     int level;
 | |
|     // 确保level在有效范围内 (1-4)
 | |
|     // level = level.clamp(1, 4) - 1;
 | |
|     if(widget.itemData['LEVELID']=="levelA"){
 | |
|       level=0;
 | |
|     }else if(widget.itemData['LEVELID']=="levelB"){
 | |
|       level=1;
 | |
|     }else if(widget.itemData['LEVELID']=="levelC"){
 | |
|       level=2;
 | |
|     }else {
 | |
|       level=3;
 | |
|     }
 | |
|     return _levelTexts[level];
 | |
|   }
 | |
| 
 | |
|   Color _getLevelColor(){
 | |
|     int level;
 | |
|     // 确保level在有效范围内 (1-4)
 | |
|     // level = level.clamp(1, 4) - 1;
 | |
|     if(widget.itemData['LEVELID']=="levelA"){
 | |
|       level=0;
 | |
|     }else if(widget.itemData['LEVELID']=="levelB"){
 | |
|       level=1;
 | |
|     }else if(widget.itemData['LEVELID']=="levelC"){
 | |
|       level=2;
 | |
|     }else {
 | |
|       level=3;
 | |
|     }
 | |
|     return _fxColors[level];
 | |
|   }
 | |
| 
 | |
|   // 底部按钮
 | |
|   Widget _buildBottomButton() {
 | |
|     return Padding(
 | |
|       padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
 | |
|       child: SizedBox(
 | |
|         width: double.infinity,
 | |
|         height: 50,
 | |
|         child: ElevatedButton(
 | |
|           style: ElevatedButton.styleFrom(
 | |
|             backgroundColor: Colors.green,
 | |
|             foregroundColor: Colors.white,
 | |
|             shape: RoundedRectangleBorder(
 | |
|               borderRadius: BorderRadius.circular(8),
 | |
|             ),
 | |
|             elevation: 3,
 | |
|           ),
 | |
|           onPressed: () {
 | |
|             // 按钮点击事件
 | |
|             _addCoordinate();
 | |
|           },
 | |
|           child: const Text(
 | |
|             "提交位置",
 | |
|             style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
|   // 多项项信息组件
 | |
|   Widget _itemCell(String title,int type) {
 | |
|     // final details = item["detail"] as List<String>;
 | |
|     return Padding(
 | |
|       padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
 | |
|       child: Column(
 | |
|         crossAxisAlignment: CrossAxisAlignment.start,
 | |
|         children: [
 | |
|           // 标题行
 | |
|           Row(
 | |
|             children: [
 | |
|               Container(
 | |
|                 width: 4,
 | |
|                 height: 16,
 | |
|                 decoration: BoxDecoration(
 | |
|                   color: Colors.black38,
 | |
|                   borderRadius: BorderRadius.circular(2),
 | |
|                 ),
 | |
|               ),
 | |
|               const SizedBox(width: 5),
 | |
|               Text(
 | |
|                 title,
 | |
|                 style: const TextStyle(
 | |
|                   fontSize: 15,
 | |
|                   fontWeight: FontWeight.bold,
 | |
|                   color: Colors.black87,
 | |
|                 ),
 | |
|               ),
 | |
|             ],
 | |
|           ),
 | |
|           const SizedBox(height: 10),
 | |
|           // // 内容区域
 | |
|           // ...details.map((text) => _textItem(text, false)).toList(),
 | |
| 
 | |
|           if(0==type||1==type)
 | |
|             Column(
 | |
|               crossAxisAlignment: CrossAxisAlignment.start,
 | |
|               children: [
 | |
|               for(int i = 0; i < _list.length; i++)
 | |
|                 _getWitchItem(type, i),
 | |
|             ],)
 | |
|           else
 | |
|             _getWitchItemTwo(type, type),
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|   Widget _getWitchItem(int type,int position) {
 | |
|     String text="";
 | |
|     switch(type){
 | |
|       case 0:
 | |
|         text= "$position.${_list[position]["RISK_DESCR"]}";
 | |
|         break;
 | |
|       case 1:
 | |
|         text= "$position.${_list[position]["MEASURES"]}";
 | |
|         break;
 | |
|       // case 2:
 | |
|       //   text= _list[position]["RISK_DESCR"];
 | |
|       //   break;
 | |
|       // case 3:
 | |
|       //   text= _list[position]["RISK_DESCR"];
 | |
|       //   break;
 | |
|     }
 | |
| 
 | |
|     return _textItem(text,false);
 | |
|   }
 | |
| 
 | |
|   Widget _getWitchItemTwo(int type,int position) {
 | |
|     String text="";
 | |
|     switch(type){
 | |
|       // case 0:
 | |
|       //   text= _list[position]["RISK_DESCR"];
 | |
|       //   break;
 | |
|       // case 1:
 | |
|       //   text= _list[position]["MEASURES"];
 | |
|       //   break;
 | |
|     case 2:
 | |
|       text= widget.itemData["DEPT_NAME"];
 | |
|       break;
 | |
|     case 3:
 | |
|       for(int i=0;i<_list.length;i++){
 | |
|         if(text.isEmpty){
 | |
|           text=_list[i]["ACCIDENTS_NAME"];
 | |
|         }else{
 | |
|           text="$text,${_list[i]["ACCIDENTS_NAME"]}";
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     return _textItem(text,false);
 | |
|   }
 | |
| 
 | |
|   // 文本项组件
 | |
|   Widget _textItem(String text, bool isInfinity) {
 | |
|     return Container(
 | |
|       width: isInfinity ? double.infinity : null,
 | |
|       margin: const EdgeInsets.only(bottom: 8),
 | |
|       padding: const EdgeInsets.all(12),
 | |
|       decoration: BoxDecoration(
 | |
|         color: h_backGroundColor(),
 | |
|         borderRadius: BorderRadius.circular(6),
 | |
|       ),
 | |
|       child: Text(
 | |
|         text,
 | |
|         style: const TextStyle(
 | |
|           fontSize: 14,
 | |
|           color: Colors.black87,
 | |
|           height: 1.5,
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void _showMessage(String msg) {
 | |
|     ToastUtil.showNormal(context, msg);
 | |
|   }
 | |
| }
 |