parent
							
								
									2850a9d49b
								
							
						
					
					
						commit
						440f4fec75
					
				|  | @ -33,9 +33,6 @@ class _RemoteFilePageState extends State<RemoteFilePage> { | |||
|   late PdfControllerPinch _pdfController; | ||||
|   int _totalPages = 0; | ||||
| 
 | ||||
|   // 用于短文档(<=3页)的停留计时器兜底 | ||||
|   Timer? _pageViewTimer; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|  | @ -96,36 +93,12 @@ class _RemoteFilePageState extends State<RemoteFilePage> { | |||
|   @override | ||||
|   void dispose() { | ||||
|     _countdownTimer?.cancel(); | ||||
|     _pageViewTimer?.cancel(); | ||||
|     if (!_isLoading) { | ||||
|       _pdfController.dispose(); | ||||
|     } | ||||
|     super.dispose(); | ||||
|   } | ||||
| 
 | ||||
|   // 当页面改变时调用(pdfx 的 page 是 1-based) | ||||
|   void _onPageChanged(int page) { | ||||
|     // 取消可能存在的短页面计时器(重新开始) | ||||
|     _pageViewTimer?.cancel(); | ||||
| 
 | ||||
|     // 如果到达最后一页(注意页码从 1 开始) | ||||
|     if (_totalPages > 0 && page >= _totalPages) { | ||||
|       // 直接标记为已翻到底 | ||||
|       setState(() => _hasScrolledToBottom = true); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     // 对于特别短的文档(例如 <=3 页),我们做一个停留计时器:如果用户停留在最后一页一小段时间,也视为已浏览完毕 | ||||
|     if (_totalPages > 0 && _totalPages <= 3) { | ||||
|       // 如果当前页已经是最后一页(page == _totalPages),启动短计时器 | ||||
|       if (page == _totalPages) { | ||||
|         _pageViewTimer = Timer(const Duration(seconds: 1), () { | ||||
|           if (mounted) setState(() => _hasScrolledToBottom = true); | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final isButtonEnabled = _timerFinished && _hasScrolledToBottom; | ||||
|  | @ -142,16 +115,16 @@ class _RemoteFilePageState extends State<RemoteFilePage> { | |||
|                 controller: _pdfController, | ||||
|                 scrollDirection: Axis.vertical, | ||||
|                 onDocumentLoaded: (document) { | ||||
|                   setState(() { | ||||
|                     _totalPages = document.pagesCount; | ||||
|                     // 如果文档只有 1 页,直接视为已看完 | ||||
|                     if (_totalPages <= 1) { | ||||
|                       _hasScrolledToBottom = true; | ||||
|                     } | ||||
|                   }); | ||||
|                   _totalPages = document.pagesCount; | ||||
|                   // 兜底:如果只有 1 页(无需滚动),直接视为已看完 | ||||
|                   if (_totalPages <= 1) { | ||||
|                     _hasScrolledToBottom = true; | ||||
|                   } | ||||
|                 }, | ||||
|                 onPageChanged: (page) { | ||||
|                   _onPageChanged(page); | ||||
|                   if (page == _totalPages - 1) { | ||||
|                     setState(() => _hasScrolledToBottom = true); | ||||
|                   } | ||||
|                 }, | ||||
|               ), | ||||
|             ), | ||||
|  |  | |||
|  | @ -190,7 +190,7 @@ U6Hzm1ninpWeE+awIDAQAB | |||
|       '/app/versionmanager/getVersion', | ||||
|       method: Method.post, | ||||
|       data: { | ||||
|         'FILETYPE':Platform.pathSeparator | ||||
|         'FILETYPE':Platform.isIOS ? 'iOS' : 'Android' | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| import 'dart:async'; | ||||
| import 'dart:convert'; | ||||
| import 'dart:io'; | ||||
| 
 | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; | ||||
|  | @ -192,6 +193,7 @@ class HomePageState extends State<HomePage> { | |||
|   Future<void> _initialLoad() async { | ||||
|     final result = await AuthService.checkUpdate(); | ||||
|     try{ | ||||
| 
 | ||||
|       if (FormUtils.hasValue(result, 'pd')) { | ||||
|         Map pd = result['pd']; | ||||
|         final versionInfo = await getAppVersion(); | ||||
|  | @ -207,8 +209,13 @@ class HomePageState extends State<HomePage> { | |||
|               confirmText: '立即更新' | ||||
|           ); | ||||
|           if (ok) { | ||||
|             final apkUrl = pd['FILEURL'] ?? ''; | ||||
|             await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|             if (Platform.isIOS) { | ||||
|               openAppStore(); | ||||
|             }else{ | ||||
|               final apkUrl = pd['FILEURL'] ?? ''; | ||||
|               await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|             } | ||||
| 
 | ||||
|           } | ||||
|           return; | ||||
|         } | ||||
|  |  | |||
|  | @ -24,13 +24,16 @@ class ImageData { | |||
| class SignImageData { | ||||
|   String SIGNER_TIME; | ||||
|   String? filePath; | ||||
|   String? localPath; | ||||
| 
 | ||||
|   int? key; | ||||
| 
 | ||||
|   SignImageData({required this.SIGNER_TIME, this.filePath, this.key}); | ||||
|   SignImageData({required this.SIGNER_TIME, this.filePath,this.localPath, this.key}); | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() => { | ||||
|     'SIGNER_TIME': SIGNER_TIME, | ||||
|     'filePath': filePath, | ||||
|     'localPath': localPath, | ||||
|     'key': key, | ||||
|   }; | ||||
| 
 | ||||
|  | @ -38,13 +41,14 @@ class SignImageData { | |||
|     return SignImageData( | ||||
|       SIGNER_TIME: m['SIGNER_TIME'] ?? '', | ||||
|       filePath: m['filePath'], | ||||
|       localPath: m['localPath'], | ||||
|       key: m['key'] != null ? int.tryParse(m['key'].toString()) : null, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => | ||||
|       'SignImageData(key:$key, filePath:$filePath, SIGNER_TIME:$SIGNER_TIME)'; | ||||
|       'SignImageData(key:$key, filePath:$filePath, localPath:$localPath,SIGNER_TIME:$SIGNER_TIME)'; | ||||
| } | ||||
| 
 | ||||
| class DangerousOptionsPage extends StatefulWidget { | ||||
|  | @ -131,44 +135,46 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> { | |||
|       return; | ||||
|     } | ||||
|     LoadingDialogHelper.show(); | ||||
|     List<SignImageData> filePaths = []; | ||||
|     // List<SignImageData> filePaths = []; | ||||
|     List severImageList = []; | ||||
| 
 | ||||
|     for (SignImageData data in signImgList) { | ||||
|       String path = data.filePath ?? ''; | ||||
|       if (!path.contains('uploadFiles')) { | ||||
|         filePaths.add(data); | ||||
|       } else { | ||||
|         severImageList.add({ | ||||
|           'filePath': data.filePath, | ||||
|           'SIGNER_TIME': data.SIGNER_TIME, | ||||
|           'key': data.key, | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|     if (filePaths.length == 0) { | ||||
|       // 如果没有本地未提交,直接返回 | ||||
|       setState(() => buttonLoading = true); | ||||
|       LoadingDialogHelper.hide(); | ||||
|       Navigator.pop(context, { | ||||
|         'imgList': | ||||
|             imgList | ||||
|                 .map((e) => {'local': e.localPath, 'remote': e.serverPath}) | ||||
|                 .toList(), | ||||
|         'signImgList': signImgList, | ||||
|         'index': index, | ||||
|         'status': status, | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|     final result = await ApiService.saveDangerousOptionsFile(filePaths.map((item) => item.filePath).toList()); | ||||
|     // for (SignImageData data in signImgList) { | ||||
|     //   String path = data.filePath ?? ''; | ||||
|     //   if (!path.contains('uploadFiles')) { | ||||
|     //     filePaths.add(data); | ||||
|     //   } else { | ||||
|     //     severImageList.add({ | ||||
|     //       'filePath': '', | ||||
|     //       'localPath':data.filePath, | ||||
|     //       'SIGNER_TIME': data.SIGNER_TIME, | ||||
|     //       'key': data.key, | ||||
|     //     }); | ||||
|     //   } | ||||
|     // } | ||||
|     // if (filePaths.length == 0) { | ||||
|     //   // 如果没有本地未提交,直接返回 | ||||
|     //   setState(() => buttonLoading = true); | ||||
|     //   LoadingDialogHelper.hide(); | ||||
|     //   Navigator.pop(context, { | ||||
|     //     'imgList': | ||||
|     //         imgList | ||||
|     //             .map((e) => {'local': e.localPath, 'remote': e.serverPath}) | ||||
|     //             .toList(), | ||||
|     //     'signImgList': signImgList, | ||||
|     //     'index': index, | ||||
|     //     'status': status, | ||||
|     //   }); | ||||
|     //   return; | ||||
|     // } | ||||
|     final result = await ApiService.saveDangerousOptionsFile(signImgList.map((item) => item.localPath).toList()); | ||||
|     final List<dynamic> signList = result['FILE_PATH_LIST']; | ||||
|     for (SignImageData data in filePaths) { | ||||
|     for (SignImageData data in signImgList) { | ||||
|       for (Map<String, dynamic> img in signList) { | ||||
|         String imgName = 'file${data.key}'; | ||||
| 
 | ||||
|         if (imgName == img['key']) { | ||||
|           final idata = { | ||||
|             'localPath':data.localPath, | ||||
|             'filePath': img['filePath'] ?? '', | ||||
|             'SIGNER_TIME': data.SIGNER_TIME, | ||||
|             'key': data.key, | ||||
|  | @ -203,7 +209,8 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> { | |||
|       setState(() { | ||||
|         final imageData = SignImageData( | ||||
|           SIGNER_TIME: now, | ||||
|           filePath: path, | ||||
|           filePath: '', | ||||
|           localPath: path, | ||||
|           key: signImgList.length, | ||||
|         ); | ||||
|         signImgList.add(imageData); | ||||
|  | @ -237,7 +244,7 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> { | |||
|                                   '${ApiService.baseImgPath}${imgData.filePath}', | ||||
|                                 ) | ||||
|                                 : Image.file( | ||||
|                                   File(imgData.filePath ?? ''), | ||||
|                                   File(imgData.localPath ?? ''), | ||||
|                                   fit: BoxFit.contain, | ||||
|                                 ), | ||||
|                       ), | ||||
|  |  | |||
|  | @ -218,7 +218,7 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> { | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -480,7 +480,40 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> { | |||
|       //FocusHelper.clearFocus(context); | ||||
|     }); | ||||
|   } | ||||
|   bool checkWorkTime(Map<String, dynamic> pd, BuildContext context) { | ||||
|     // 解析开始和结束时间 | ||||
|     final start = DateTime.parse(pd['WORK_EXPECTED_START_TIME'] as String); | ||||
|     final end = DateTime.parse(pd['WORK_EXPECTED_END_TIME'] as String); | ||||
| 
 | ||||
|     // 校验:结束时间必须晚于开始时间 | ||||
|     if (end.isAtSameMomentAs(start) || end.isBefore(start)) { | ||||
|       ToastUtil.showNormal(context, '作业开始时间不能晚于或等于结束时间,请重新选择'); | ||||
| 
 | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     // 特级或一级:最长不超过 8 小时(8 * 60 * 60 * 1000 ms) | ||||
|     if (pd['WORK_LEVEL'] == '特级' || pd['WORK_LEVEL'] == '一级') { | ||||
|       final diffMs = end.difference(start).inMilliseconds; | ||||
|       const max8h = 8 * 60 * 60 * 1000; | ||||
|       if (diffMs >= max8h) { | ||||
|         ToastUtil.showNormal(context, '动火级别为特级或一级时,动火作业开始时间与结束时间应不超过8小时,请重新选择'); | ||||
| 
 | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // 二级:最长不超过 72 小时(72 * 60 * 60 * 1000 ms) | ||||
|     if (pd['WORK_LEVEL'] == '二级') { | ||||
|       final diffMs = end.difference(start).inMilliseconds; | ||||
|       const max72h = 72 * 60 * 60 * 1000; | ||||
|       if (diffMs >= max72h) { | ||||
|         ToastUtil.showNormal(context, '动火级别为二级时,动火作业开始时间与结束时间应不超过72小时,请重新选择'); | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|   /// 提交  1 提交 0暂存 | ||||
|   Future<void> _submit(String status) async { | ||||
|     // 通用文本字段校验规则 | ||||
|  | @ -540,6 +573,9 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> { | |||
|         ToastUtil.showNormal(context, '请选择预计作业结束时间'); | ||||
|         return; | ||||
|       } | ||||
|       if (!checkWorkTime(pd, context)) { | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       if (pd['IS_CONTRACTOR_WORK'] == '1' && | ||||
|           !FormUtils.hasValue(pd, 'UNITS_ID')) { | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ class _HotworkKszyDetailState extends State<HotworkKszyDetail> { | |||
|       final intervalMs = workStart.difference(analyzeTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '气体分析时间与开始时间间隔超过30分钟,请重新上传气体检测结果'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -104,7 +104,6 @@ class _HotworkGasListState extends State<HotworkGasList> { | |||
|             Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 Text('检测值: ${item['GAS_VALUE'] ?? ''}'), | ||||
|                 Text('计量单位: ${item['GAS_UNIT'] ?? ''}'), | ||||
|               ], | ||||
|             ), | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ class _HotworkYsgdDetailState extends State<HotworkYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -191,7 +191,7 @@ class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> { | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           if (FormUtils.hasValue(signs, 'PROJECT_MANAGER') && | ||||
|  |  | |||
|  | @ -201,7 +201,7 @@ class _CutroadYsgdDetailState extends State<CutroadYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -161,16 +161,16 @@ class _CutroadZyrDetailState extends State<CutroadZyrDetail> { | |||
|         confirmText: '确定', | ||||
|       ); | ||||
|       // 用户取消(或点遮罩、返回键) | ||||
| if (reasonText == null) { | ||||
|   // 取消时什么也不做,不提示 | ||||
|   return; | ||||
| } | ||||
|       if (reasonText == null) { | ||||
|         // 取消时什么也不做,不提示 | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
| // 用户点击确认但没填内容 | ||||
| if (reasonText.isEmpty) { | ||||
|   ToastUtil.showNormal(context, '请填写作废原因'); | ||||
|   return; | ||||
| } | ||||
|       // 用户点击确认但没填内容 | ||||
|       if (reasonText.isEmpty) { | ||||
|         ToastUtil.showNormal(context, '请填写作废原因'); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|     final serverPathString = imgList | ||||
|         .map((e) => e.serverPath) | ||||
|  |  | |||
|  | @ -188,7 +188,7 @@ class _BreakgroundDetailFormWidgetState | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
| 
 | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ class _BreakgroundYsgdDetailState extends State<BreakgroundYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -256,7 +256,7 @@ class _HoistworkDetailFormWidgetState extends State<HoistWorkDetailFormWidget> { | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ class _HoistworkYsgdDetailState extends State<HoistworkYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -236,7 +236,7 @@ class _HighWorkDetailFormWidgetState extends State<HighWorkDetailFormWidget> { | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -505,6 +505,9 @@ class _HighworkApplyDetailState extends State<HighworkApplyDetail> { | |||
|         ToastUtil.showNormal(context, '请选择预计作业结束时间'); | ||||
|         return; | ||||
|       } | ||||
|       if (!checkWorkTime(pd, context)) { | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       if (pd['IS_CONTRACTOR_WORK'] == '1' && | ||||
|           !FormUtils.hasValue(pd, 'UNITS_ID')) { | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ class _HighworkYsgdDetailState extends State<HighworkYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -43,7 +43,6 @@ class _HomeGasTestPageState extends State<HomeGasTestPage> { | |||
|     {"name": 'UPPER_LIMIT', "message": '请输入量程上限'}, | ||||
|     {"name": 'LOWER_LIMIT', "message": '请输入量程下限'}, | ||||
|     {"name": 'GAS_UNIT', "message": '请输入计量单位'}, | ||||
|     {"name": 'GAS_VALUE', "message": '请输入检测值'}, | ||||
|     {"name": 'ANALYZE_TIME', "message": '请输入分析时间'}, | ||||
|     {"name": 'ANALYZE_GAS', "message": '请输入代表性气体'}, | ||||
|     {"name": 'ANALYZE_RESULT', "message": '请输入分析结果'}, | ||||
|  | @ -336,19 +335,19 @@ class _HomeGasTestPageState extends State<HomeGasTestPage> { | |||
|                                 }); | ||||
|                               }, | ||||
|                             ), | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '检测值:', | ||||
|                               isEditable: true, | ||||
|                               isNumericInput: true, | ||||
|                               hintText: '请输入数字保留两位小数', | ||||
|                               text: pd['GAS_VALUE'] ?? '', | ||||
|                               onChanged: (v) { | ||||
|                                 setState(() { | ||||
|                                   pd['GAS_VALUE'] = v; | ||||
|                                 }); | ||||
|                               }, | ||||
|                             ), | ||||
|                             // const Divider(), | ||||
|                             // ItemListWidget.singleLineTitleText( | ||||
|                             //   label: '检测值:', | ||||
|                             //   isEditable: true, | ||||
|                             //   isNumericInput: true, | ||||
|                             //   hintText: '请输入数字保留两位小数', | ||||
|                             //   text: pd['GAS_VALUE'] ?? '', | ||||
|                             //   onChanged: (v) { | ||||
|                             //     setState(() { | ||||
|                             //       pd['GAS_VALUE'] = v; | ||||
|                             //     }); | ||||
|                             //   }, | ||||
|                             // ), | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '分析结果:', | ||||
|  |  | |||
|  | @ -239,7 +239,7 @@ class _ElectricityDetailFormWidgetState extends State<ElectricityDetailFormWidge | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -62,7 +62,12 @@ class _ElectricityJszyDetailState extends State<ElectricityJszyDetail> { | |||
| 
 | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     final diffMs = end.difference(start).inMilliseconds; | ||||
|     const max8h = 30 * 24 * 60 * 60 * 1000; | ||||
|     if (diffMs >= max8h) { | ||||
|       ToastUtil.showNormal(context, '临时用电时间一般不超过15天,特殊情况不应超过30天,请重新选择'); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ class _ElectricityKszyDetailState extends State<ElectricityKszyDetail> { | |||
|         final intervalMs = workStart.difference(analyzeTime).inMilliseconds; | ||||
|         const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|         if (intervalMs >= thresholdMs) { | ||||
|         if (intervalMs.abs() >= thresholdMs) { | ||||
|           ToastUtil.showNormal(context, '气体分析时间与开始时间间隔超过30分钟,请重新上传气体检测结果'); | ||||
|           return; | ||||
|         } | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ enum EditUserType { | |||
|   ELECTRICITY('用电单位', '用电人', true),// | ||||
|   CONFESS('安全交底人单位', '安全交底人', true), | ||||
|   ACCEPT_CONFESS('接受交底人单位', '接受交底人', true), | ||||
|   WORK('作业人单位', '作业人', true), // | ||||
|   WORK_USER('作业人单位', '作业人', true), // | ||||
|   CONFIRM('作业负责人单位', '作业负责人', true), | ||||
|   AUDIT('用电单位', '用电单位负责人', true), | ||||
|   APPROVE('配送电单位', '配送电单负责人', true), | ||||
|  | @ -132,7 +132,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|       pd['WORK_VOLTAGE'] = _VController.text.trim(); | ||||
|     }); | ||||
|     _fzCardController.addListener(() { | ||||
|       pd['LEADER_CARD_NO'] = _VController.text.trim(); | ||||
|       pd['LEADER_CARD_NO'] = _fzCardController.text.trim(); | ||||
|     }); | ||||
|     _relatedController.addListener(() { | ||||
|       pd['SPECIAL_WORK'] = _relatedController.text.trim(); | ||||
|  | @ -255,11 +255,22 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|   } | ||||
| 
 | ||||
|   void set_pd_USER_ID(EditUserType type, String id) { | ||||
|     pd['${type.name}_USER_ID'] = id; | ||||
|     if (type == EditUserType.WORK_USER) { | ||||
|       pd['${type.name}_ID'] = id; | ||||
| 
 | ||||
|     }else{ | ||||
|       pd['${type.name}_USER_ID'] = id; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   void set_pd_USER_Name(EditUserType type, String name) { | ||||
|     pd['${type.name}_USER_NAME'] = name; | ||||
|     if (type == EditUserType.WORK_USER) { | ||||
|       pd['${type.name}_NAME'] = name; | ||||
| 
 | ||||
|     }else{ | ||||
|       pd['${type.name}_USER_NAME'] = name; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   String get_pd_DEPARTMENT_ID(EditUserType type) { | ||||
|  | @ -268,17 +279,24 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
| 
 | ||||
|   String get_pd_DEPARTMENT_NAME(EditUserType type) { | ||||
|     return pd['${type.name}_DEPARTMENT_NAME'] ?? ''; | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   String get_pd_USER_ID(EditUserType type) { | ||||
|     return pd['${type.name}_USER_ID'] ?? ''; | ||||
|     if (type == EditUserType.WORK_USER) { | ||||
|       return pd['${type.name}_ID'] ?? ''; | ||||
|     } else { | ||||
|       return pd['${type.name}_USER_ID'] ?? ''; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   String get_pd_USER_Name(EditUserType type) { | ||||
|     if (type == EditUserType.WORK) { | ||||
|       return pd['${type.name}_USER_USER_NAME'] ?? ''; | ||||
|     if (type == EditUserType.WORK_USER) { | ||||
|       return pd['${type.name}_NAME'] ?? ''; | ||||
|     }else{ | ||||
|       return pd['${type.name}_USER_NAME'] ?? ''; | ||||
| 
 | ||||
|     } | ||||
|     return pd['${type.name}_USER_NAME'] ?? ''; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -323,7 +341,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|           isRequired: isRequired, | ||||
|           label: type.personName, | ||||
|           isEditable: isEditable, | ||||
|           text: pd['${type.name}_USER_NAME'] ?? '请选择', | ||||
|           text: type == EditUserType.WORK_USER ? (pd['${type.name}_NAME'] ??'') :  (pd['${type.name}_USER_NAME']??'') ?? '请选择', | ||||
|           onTap: () => choosePersonHandle(type), | ||||
|         ), | ||||
|         if (type == EditUserType.CONFIRM) | ||||
|  | @ -422,7 +440,25 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|       //FocusHelper.clearFocus(context); | ||||
|     }); | ||||
|   } | ||||
|   bool checkWorkTime(Map<String, dynamic> pd, BuildContext context) { | ||||
|     // 解析开始和结束时间 | ||||
|     final start = DateTime.parse(pd['WORK_EXPECTED_START_TIME'] as String); | ||||
|     final end = DateTime.parse(pd['WORK_EXPECTED_END_TIME'] as String); | ||||
| 
 | ||||
|     // 校验:结束时间必须晚于开始时间 | ||||
|     if (end.isAtSameMomentAs(start) || end.isBefore(start)) { | ||||
|       ToastUtil.showNormal(context, '作业开始时间不能晚于或等于结束时间,请重新选择'); | ||||
| 
 | ||||
|       return false; | ||||
|     } | ||||
|     final diffMs = end.difference(start).inMilliseconds; | ||||
|     const max8h = 30 * 24 * 60 * 60 * 1000; | ||||
|     if (diffMs >= max8h) { | ||||
|       ToastUtil.showNormal(context, '临时用电时间一般不超过15天,特殊情况不应超过30天,请重新选择'); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|   /// 提交  1 提交 0暂存 | ||||
|   Future<void> _submit(String status) async { | ||||
|     // 通用文本字段校验规则 | ||||
|  | @ -457,7 +493,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|       EditUserType.ELECTRICITY, | ||||
|       EditUserType.CONFESS, | ||||
|       EditUserType.ACCEPT_CONFESS, | ||||
|       EditUserType.WORK, | ||||
|       EditUserType.WORK_USER, | ||||
|       EditUserType.CONFIRM, | ||||
|       EditUserType.AUDIT, | ||||
|       EditUserType.APPROVE, | ||||
|  | @ -542,7 +578,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|         ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); | ||||
|         Navigator.of(context).pop(true); | ||||
|       } else { | ||||
|         ToastUtil.showSuccess(context, '提交失败'); | ||||
|         ToastUtil.showError(context, '提交失败'); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       LoadingDialogHelper.hide(); | ||||
|  | @ -559,6 +595,9 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|     ); | ||||
|     setState(() { | ||||
|       pd = data['pd']; | ||||
|       if (FormUtils.hasValue(pd, 'ANALYZE_DEPARTMENT_ID')) { | ||||
|         _isGasAnalyze = true; | ||||
|       } | ||||
|       if (pd['STEP_ID'] == 0) { | ||||
|         isEditable = true; | ||||
|       } else { | ||||
|  | @ -568,12 +607,14 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|       //  给所有输入框赋值 | ||||
|       _contentController.text = pd['WORK_CONTENT'] ?? ''; | ||||
|       _locationController.text = pd['WORK_PLACE'] ?? ''; | ||||
|       _cardController.text = pd['WORK_FUNCTION'] ?? ''; | ||||
|       _powerController.text = pd['WORK_USER'] ?? ''; | ||||
|       _ratedPowerController.text = pd['SPECIAL_WORK'] ?? ''; | ||||
|       _cardController.text = pd['CARD_NO'] ?? ''; | ||||
|       _powerController.text = pd["ALLOW_POWER"] ?? ''; | ||||
|       _ratedPowerController.text = pd['RATED_POWER'] ?? ''; | ||||
|       _VController.text = pd['WORK_VOLTAGE'] ?? ''; | ||||
|       _relatedController.text = pd['SPECIAL_WORK'] ?? ''; | ||||
|       _riskController.text = pd['RISK_IDENTIFICATION'] ?? ''; | ||||
|       _fzCardController.text = pd["LEADER_CARD_NO"] ?? ''; | ||||
| 
 | ||||
|     }); | ||||
|     // final data = await ApiService.getHomeworkFindById('electricity', widget.ELECTRICITY_ID); | ||||
|     // setState(() { | ||||
|  | @ -674,7 +715,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> { | |||
|                     SizedBox(height: 15), | ||||
|                     _card(_chooseItem(EditUserType.ACCEPT_CONFESS)), | ||||
|                     SizedBox(height: 15), | ||||
|                     _card(_chooseItem(EditUserType.WORK)), | ||||
|                     _card(_chooseItem(EditUserType.WORK_USER)), | ||||
|                     SizedBox(height: 15), | ||||
|                     _card(_chooseItem(EditUserType.CONFIRM)), | ||||
|                     SizedBox(height: 15), | ||||
|  |  | |||
|  | @ -96,7 +96,6 @@ class _ElectricityGasListState extends State<ElectricityGasList> { | |||
|             Row( | ||||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 Text('检测值: ${item['GAS_VALUE'] ?? ''}'), | ||||
|                 Text('计量单位: ${item['GAS_UNIT'] ?? ''}'), | ||||
|               ], | ||||
|             ), | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ class _ElectricityGasTestPageState extends State<ElectricityGasTestPage> { | |||
|     {'name': 'UPPER_LIMIT', 'message': '请输入量程上限'}, | ||||
|     {'name': 'LOWER_LIMIT', 'message': '请输入量程下限'}, | ||||
|     {'name': 'GAS_UNIT', 'message': '请输入计量单位'}, | ||||
|     {'name': 'GAS_VALUE', 'message': '请输入检测值'}, | ||||
|     {'name': 'ANALYZE_TIME', 'message': '请输入分析时间'}, | ||||
|     {'name': 'ANALYZE_PLACE', 'message': '请输入分析点'}, | ||||
|     {'name': 'ANALYZE_RESULT', 'message': '请输入分析结果'}, | ||||
|  | @ -338,19 +337,7 @@ if (reasonText.isEmpty) { | |||
|                                 }); | ||||
|                               }, | ||||
|                             ), | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '检测值:', | ||||
|                               isEditable: true, | ||||
|                               isNumericInput: true, | ||||
|                               hintText: '请输入检测值,数字保留两位小数', | ||||
|                               text: pd['GAS_VALUE'] ?? '', | ||||
|                               onChanged: (v) { | ||||
|                                 setState(() { | ||||
|                                   pd['GAS_VALUE'] = v; | ||||
|                                 }); | ||||
|                               }, | ||||
|                             ), | ||||
| 
 | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '分析点:', | ||||
|  |  | |||
|  | @ -202,7 +202,7 @@ class _ElectricityYsgdDetailState extends State<ElectricityYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -637,7 +637,7 @@ class _BlindboardDetailFormWidgetState | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -249,7 +249,7 @@ class _SpaceWorkDetailFormWidgetState extends State<SpaceWorkDetailFormWidget> { | |||
|             }, | ||||
|             hintText: '请输入关联的其他特殊作业及安全作业票编号', | ||||
|             controller: widget.relatedController, | ||||
|             text: pd['SPECIAL_WORK'] ?? '无', | ||||
|             text: pd['SPECIAL_WORK'] ?? '', | ||||
|           ), | ||||
|           const Divider(), | ||||
|           ItemListWidget.twoRowButtonTitleText( | ||||
|  |  | |||
|  | @ -62,7 +62,12 @@ class _SpaceworkJszyDetailState extends State<SpaceworkJszyDetail> { | |||
| 
 | ||||
|       return false; | ||||
|     } | ||||
| 
 | ||||
|     final diffMs = end.difference(start).inMilliseconds; | ||||
|     const max8h = 24 * 60 * 60 * 1000; | ||||
|     if (diffMs >= max8h) { | ||||
|       ToastUtil.showNormal(context, '作业开始时间与结束时间应不超过24小时,请重新选择'); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ class _SpaceworkKszyDetailState extends State<SpaceworkKszyDetail> { | |||
|       final intervalMs = workStart.difference(analyzeTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '气体分析时间与开始时间间隔超过30分钟,请重新上传气体检测结果'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -121,8 +121,6 @@ class _SpaceworkGasListState extends State<SpaceworkGasList> { | |||
|               mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|               children: [ | ||||
|                 Text('含氧量: ${item['OXYGEN_CONTENT'] ?? ''}'), | ||||
|                 if ((item['ANALYZE_PLACE'] ?? '').toString().isNotEmpty) | ||||
|                   Text('分析地点: ${item['ANALYZE_PLACE']}'), | ||||
|               ], | ||||
|             ), | ||||
|             const SizedBox(height: 6), | ||||
|  |  | |||
|  | @ -36,8 +36,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|   Map<String, dynamic> pd = {}; | ||||
|   final TextEditingController _PartController = TextEditingController(); // 部位 | ||||
|   final TextEditingController _O2Controller = TextEditingController(); // 结果 | ||||
|   final TextEditingController _addressController = | ||||
|       TextEditingController(); // 地点 | ||||
| 
 | ||||
|   List<Map<String, dynamic>> RESULTS_UNIT_LIST = [ | ||||
|     {"NAME": "%", "VALUE": "1"}, | ||||
|  | @ -48,7 +46,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|     {'name': 'ANALYZE_TIME', 'message': '请输入取样分析时间'}, | ||||
|     {'name': 'ANALYZE_PART', 'message': '请输入分析部位'}, | ||||
|     {'name': 'OXYGEN_CONTENT', 'message': '请输入氧气含量'}, | ||||
|     {'name': 'ANALYZE_PLACE', 'message': '请输入分析地点'}, | ||||
|   ]; | ||||
|   bool _loading = false; | ||||
| 
 | ||||
|  | @ -57,7 +54,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|     pd['ANALYZE_USER'] = SessionService.instance.username; | ||||
|     pd['CONFINEDSPACE_ID'] = widget.CONFINEDSPACE_ID; | ||||
|     super.initState(); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _chooseDatePicker() async { | ||||
|  | @ -69,6 +65,7 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|       }); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   List<Map<String, dynamic>> _gas_new_rules(String type) { | ||||
|     String name = widget.saveParams['GAS_NAME$type']; | ||||
|     return [ | ||||
|  | @ -79,7 +76,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|     ]; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   Future<void> _sign() async { | ||||
|     await NativeOrientation.setLandscape(); | ||||
|     final path = await Navigator.push( | ||||
|  | @ -164,9 +160,7 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|         ToastUtil.showNormal(context, '请选择取样分析时间'); | ||||
|         return; | ||||
|       } | ||||
|       if (_PartController.text.isEmpty || | ||||
|           _O2Controller.text.isEmpty || | ||||
|           _addressController.text.isEmpty) { | ||||
|       if (_PartController.text.isEmpty || _O2Controller.text.isEmpty) { | ||||
|         ToastUtil.showNormal(context, '请完善所有字段'); | ||||
|         return; | ||||
|       } | ||||
|  | @ -174,7 +168,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|         ...pd, | ||||
|         'ANALYZE_PART': _PartController.text, | ||||
|         'OXYGEN_CONTENT': _O2Controller.text, | ||||
|         'ANALYZE_PLACE': _addressController.text, | ||||
|       }; | ||||
|       bool required = true; | ||||
|       List<Map<String, dynamic>> rule = []; | ||||
|  | @ -207,7 +200,6 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|       } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     String? reasonText = ''; | ||||
|     if (status != 1) { | ||||
|       reasonText = await CustomAlertDialog.showInput( | ||||
|  | @ -218,16 +210,16 @@ class _SpaceworkGasTestPageState extends State<SpaceworkGasTestPage> { | |||
|         confirmText: '确定', | ||||
|       ); | ||||
|       // 用户取消(或点遮罩、返回键) | ||||
| if (reasonText == null) { | ||||
|   // 取消时什么也不做,不提示 | ||||
|   return; | ||||
| } | ||||
|       if (reasonText == null) { | ||||
|         // 取消时什么也不做,不提示 | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
| // 用户点击确认但没填内容 | ||||
| if (reasonText.isEmpty) { | ||||
|   ToastUtil.showNormal(context, '请填写作废原因'); | ||||
|   return; | ||||
| } | ||||
|       // 用户点击确认但没填内容 | ||||
|       if (reasonText.isEmpty) { | ||||
|         ToastUtil.showNormal(context, '请填写作废原因'); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     setState(() => _loading = true); | ||||
|  | @ -236,7 +228,6 @@ if (reasonText.isEmpty) { | |||
|       ...pd, | ||||
|       'ANALYZE_PART': _PartController.text, | ||||
|       'OXYGEN_CONTENT': _O2Controller.text, | ||||
|       'ANALYZE_PLACE': _addressController.text, | ||||
|       'APPLY_STATUS': status, | ||||
|       'STEP_REASON': reasonText ?? '', | ||||
|       'SIGNTIME': signTimes.join(','), | ||||
|  | @ -309,7 +300,7 @@ if (reasonText.isEmpty) { | |||
|           }, | ||||
|         ), | ||||
| 
 | ||||
|         const SizedBox(height: 2,), | ||||
|         const SizedBox(height: 2), | ||||
|         ItemListWidget.selectableLineTitleTextRightButton( | ||||
|           label: '计量单位', | ||||
|           isEditable: true, | ||||
|  | @ -319,7 +310,6 @@ if (reasonText.isEmpty) { | |||
|           }, | ||||
|         ), | ||||
|         const Divider(), | ||||
| 
 | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
|  | @ -358,11 +348,11 @@ if (reasonText.isEmpty) { | |||
|                                     isNumericInput: true, | ||||
|                                     isRequired: true, | ||||
|                                     strongRequired: false, | ||||
|                                       onChanged: (v) { | ||||
|                                         setState(() { | ||||
|                                           pd['DATA1'] = v; | ||||
|                                         }); | ||||
|                                       } | ||||
|                                     onChanged: (v) { | ||||
|                                       setState(() { | ||||
|                                         pd['DATA1'] = v; | ||||
|                                       }); | ||||
|                                     }, | ||||
|                                   ), | ||||
|                                   _gas_new_widget('1'), | ||||
|                                 ], | ||||
|  | @ -380,11 +370,11 @@ if (reasonText.isEmpty) { | |||
|                                     isNumericInput: true, | ||||
|                                     isRequired: true, | ||||
|                                     strongRequired: false, | ||||
|                                       onChanged: (v) { | ||||
|                                         setState(() { | ||||
|                                           pd['DATA2'] = v; | ||||
|                                         }); | ||||
|                                       } | ||||
|                                     onChanged: (v) { | ||||
|                                       setState(() { | ||||
|                                         pd['DATA2'] = v; | ||||
|                                       }); | ||||
|                                     }, | ||||
|                                   ), | ||||
|                                   _gas_new_widget('2'), | ||||
|                                 ], | ||||
|  | @ -402,11 +392,11 @@ if (reasonText.isEmpty) { | |||
|                                     isNumericInput: true, | ||||
|                                     isRequired: true, | ||||
|                                     strongRequired: false, | ||||
|                                       onChanged: (v) { | ||||
|                                         setState(() { | ||||
|                                           pd['DATA3'] = v; | ||||
|                                         }); | ||||
|                                       } | ||||
|                                     onChanged: (v) { | ||||
|                                       setState(() { | ||||
|                                         pd['DATA3'] = v; | ||||
|                                       }); | ||||
|                                     }, | ||||
|                                   ), | ||||
|                                   _gas_new_widget('3'), | ||||
|                                 ], | ||||
|  | @ -428,7 +418,7 @@ if (reasonText.isEmpty) { | |||
|                                       setState(() { | ||||
|                                         pd['DATA4'] = v; | ||||
|                                       }); | ||||
|                                     } | ||||
|                                     }, | ||||
|                                   ), | ||||
|                                   _gas_new_widget('4'), | ||||
|                                 ], | ||||
|  | @ -455,14 +445,6 @@ if (reasonText.isEmpty) { | |||
|                               isEditable: true, | ||||
|                               controller: _O2Controller, | ||||
|                             ), | ||||
| 
 | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '分析地点:', | ||||
|                               hintText: '请输入分析地点', | ||||
|                               isEditable: true, | ||||
|                               controller: _addressController, | ||||
|                             ), | ||||
|                             const Divider(), | ||||
|                             ItemListWidget.singleLineTitleText( | ||||
|                               label: '分析人:', | ||||
|  |  | |||
|  | @ -430,7 +430,25 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> { | |||
|       //FocusHelper.clearFocus(context); | ||||
|     }); | ||||
|   } | ||||
|   bool checkWorkTime(Map<String, dynamic> pd, BuildContext context) { | ||||
|     // 解析开始和结束时间 | ||||
|     final start = DateTime.parse(pd['WORK_EXPECTED_START_TIME'] as String); | ||||
|     final end = DateTime.parse(pd['WORK_EXPECTED_END_TIME'] as String); | ||||
| 
 | ||||
|     // 校验:结束时间必须晚于开始时间 | ||||
|     if (end.isAtSameMomentAs(start) || end.isBefore(start)) { | ||||
|       ToastUtil.showNormal(context, '作业开始时间不能晚于或等于结束时间,请重新选择'); | ||||
| 
 | ||||
|       return false; | ||||
|     } | ||||
|     final diffMs = end.difference(start).inMilliseconds; | ||||
|     const max8h = 24 * 60 * 60 * 1000; | ||||
|     if (diffMs >= max8h) { | ||||
|       ToastUtil.showNormal(context, '作业开始时间与结束时间应不超过24小时,请重新选择'); | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|   /// 提交  1 提交 0暂存 | ||||
|   Future<void> _submit(String status) async { | ||||
|     // 通用文本字段校验规则 | ||||
|  | @ -475,7 +493,9 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> { | |||
|       ToastUtil.showNormal(context, '请选择预计作业结束时间'); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     if (!checkWorkTime(pd, context)) { | ||||
|       return; | ||||
|     } | ||||
|     if (pd['IS_CONTRACTOR_WORK'] == '1' && | ||||
|         !FormUtils.hasValue(pd, 'UNITS_ID')) { | ||||
|       ToastUtil.showNormal(context, '请选择承包商'); | ||||
|  |  | |||
|  | @ -203,7 +203,7 @@ class _SpaceworkYsgdDetailState extends State<SpaceworkYsgdDetail> { | |||
|       final intervalMs = endTime.difference(acceptTime).inMilliseconds; | ||||
|       const thresholdMs = 30 * 60 * 1000; | ||||
| 
 | ||||
|       if (intervalMs >= thresholdMs) { | ||||
|       if (intervalMs.abs() >= thresholdMs) { | ||||
|         ToastUtil.showNormal(context, '请在作业结束30分钟内完成验收'); | ||||
|         return; | ||||
|       } | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| import 'dart:io'; | ||||
| 
 | ||||
| import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | @ -113,8 +115,12 @@ class _LoginPageState extends State<LoginPage> { | |||
|             confirmText: '立即更新' | ||||
|           ); | ||||
|           if (ok) { | ||||
|             final apkUrl = pd['FILEURL'] ?? ''; | ||||
|             await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|             if (Platform.isIOS) { | ||||
|               openAppStore(); | ||||
|             }else{ | ||||
|               final apkUrl = pd['FILEURL'] ?? ''; | ||||
|               await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|             } | ||||
|           } | ||||
|           return; | ||||
|         } | ||||
|  | @ -428,10 +434,10 @@ class _LoginPageState extends State<LoginPage> { | |||
|       } | ||||
| 
 | ||||
|       if (data['result'] == 'success') { | ||||
|         if(data['WEAK_PASSWORD']=='1'){ | ||||
|         if(FormUtils.hasValue(data, 'WEAK_PASSWORD') && data['WEAK_PASSWORD'] == '1'){ | ||||
|           pushPage(const MineSetPwdPage("1"), context); | ||||
| 
 | ||||
|         }else if(data['LONG_TERM_PASSWORD_NOT_CHANGED']=='1'){ | ||||
|         }else if(FormUtils.hasValue(data, 'LONG_TERM_PASSWORD_NOT_CHANGED') && data['LONG_TERM_PASSWORD_NOT_CHANGED']=='1'){ | ||||
|           pushPage(const MineSetPwdPage("2"), context); | ||||
| 
 | ||||
|         }else{ | ||||
|  |  | |||
|  | @ -21,9 +21,10 @@ class _MineAboutPageState extends State<MineAboutPage> { | |||
|   } | ||||
| 
 | ||||
|   Future<void> _loadAppVersion() async { | ||||
| 
 | ||||
|     final versionInfo = await getAppVersion(); | ||||
|     setState(() { | ||||
|       appVersion = versionInfo.fullVersion; | ||||
|       appVersion = versionInfo.versionName; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class _MineDutyApplicationPage extends State<MineDutyApplicationPage> { | |||
|         widget.onClose('关闭提交'); // 触发回调 | ||||
|         Navigator.pop(context); // 关闭页面 | ||||
|       }else{ | ||||
|         ToastUtil.showSuccess(context, '提交失败'); | ||||
|         ToastUtil.showError(context, '提交失败'); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('加载出错: $e'); | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| import 'dart:io'; | ||||
| 
 | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; | ||||
| import 'package:qhd_prevention/customWidget/toast_util.dart'; | ||||
|  | @ -41,10 +43,16 @@ class _MineSetPageState extends State<MineSetPage> { | |||
|             confirmText: '立即更新' | ||||
|         ); | ||||
|         if (ok) { | ||||
|           final apkUrl = pd['FILEURL'] ?? ''; | ||||
|           await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|           if (Platform.isIOS) { | ||||
|             openAppStore(); | ||||
|           }else{ | ||||
|             final apkUrl = pd['FILEURL'] ?? ''; | ||||
|             await showUpdateConfirm(context, apkUrl: apkUrl); | ||||
|           } | ||||
|         } | ||||
|         return; | ||||
|       }else{ | ||||
|         _loadAppVersion(); | ||||
|       } | ||||
| 
 | ||||
|     }else{ | ||||
|  | @ -54,7 +62,7 @@ class _MineSetPageState extends State<MineSetPage> { | |||
|   } | ||||
|   Future<void> _loadAppVersion() async { | ||||
|     final versionInfo = await getAppVersion(); | ||||
|     ToastUtil.showNormal(context, '已经是最新版本!当前版本号:${versionInfo.fullVersion}'); | ||||
|     ToastUtil.showNormal(context, '已经是最新版本!当前版本号:${versionInfo.versionName}'); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,12 +48,12 @@ class AuthService { | |||
|     await prefs.setBool(_keyIsLoggedIn, true); | ||||
| 
 | ||||
|     SessionService.instance | ||||
|       ..setLoginUserId(data['USER_ID'] as String) | ||||
|       ..setCorpinfoId(data['CORPINFO_ID'] as String) | ||||
|       ..setDeptId(data['DEPARTMENT_ID'] as String) | ||||
|       ..setDeptLevel(data['DEPARTMENT_LEVEL'] as String) | ||||
|       ..setIsRest(data['ISREST'] as String) | ||||
|       ..setUsername(data['NAME'] as String) | ||||
|       ..setLoginUserId(data['USER_ID'] ?? '' ) | ||||
|       ..setCorpinfoId(data['CORPINFO_ID'] ?? '' ) | ||||
|       ..setDeptId(data['DEPARTMENT_ID'] ?? '' ) | ||||
|       ..setDeptLevel(data['DEPARTMENT_LEVEL'] ?? '' ) | ||||
|       ..setIsRest(data['ISREST'] ?? '' ) | ||||
|       ..setUsername(data['NAME'] ?? '' ) | ||||
|       ..setLoginUser(data); | ||||
| 
 | ||||
|     return data; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import 'dart:io'; | |||
| import 'package:image_picker/image_picker.dart'; | ||||
| import 'package:permission_handler/permission_handler.dart'; | ||||
| import 'package:connectivity_plus/connectivity_plus.dart'; | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
| 
 | ||||
| int getRandomWithNum(int min, int max) { | ||||
|   if (max < min) { | ||||
|  | @ -612,3 +613,22 @@ Future<bool> checkNetworkWifi() async { | |||
|   return false; | ||||
| 
 | ||||
| } | ||||
| Future<void> openAppStore() async { | ||||
|   String appId = '6739233192'; | ||||
|   // 优先使用 itms-apps 直接打开 App Store 应用(iOS) | ||||
|   final Uri uri = Uri.parse('itms-apps://itunes.apple.com/app/id$appId'); | ||||
|   // 可选:直接打开写评论页: | ||||
|   // final Uri uri = Uri.parse('itms-apps://itunes.apple.com/app/id$appId?action=write-review'); | ||||
| 
 | ||||
|   if (await canLaunchUrl(uri)) { | ||||
|     await launchUrl(uri, mode: LaunchMode.externalApplication); | ||||
|   } else { | ||||
|     // 回退到 https 链接(在浏览器中打开 App Store 页面) | ||||
|     final Uri webUri = Uri.parse('https://itunes.apple.com/app/id$appId'); | ||||
|     if (await canLaunchUrl(webUri)) { | ||||
|       await launchUrl(webUri, mode: LaunchMode.externalApplication); | ||||
|     } else { | ||||
|       throw 'Could not launch App Store for app id $appId'; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev | |||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||
| # In Windows, build-name is used as the major, minor, and patch parts | ||||
| # of the product and file versions while build-number is used as the build suffix. | ||||
| version: 2.1.2+59 | ||||
| version: 2.2.0+59 | ||||
| 
 | ||||
| environment: | ||||
|   sdk: ^3.7.0 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue