diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 4e1fc7f..cb31c88 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -15,7 +15,7 @@ if (keystorePropertiesFile.exists()) { } android { - namespace = "com.zhuoyun.qhdprevention.qhd_prevention" + namespace = "uni.UNI85F7A17" compileSdk = flutter.compileSdkVersion ndkVersion = "28.1.13356709" @@ -29,7 +29,7 @@ android { } defaultConfig { - applicationId = "com.zhuoyun.qhdprevention.qhd_prevention" + applicationId = "uni.UNI85F7A17" minSdk = 24 targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b058f0f..41899c8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -104,7 +104,7 @@ - when (call.method) { - "installApk" -> { - val path = call.argument("path") - if (path == null) { - result.error("NO_PATH", "no path provided", null) - return@setMethodCallHandler - } - installApk(path, result) - } - else -> result.notImplemented() - } - } - } - - private fun installApk(path: String, result: MethodChannel.Result) { - val file = File(path) - if (!file.exists()) { - result.error("NO_FILE", "file not exist", null) - return - } - - // Android 8.0+ 需要允许安装未知来源 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (!packageManager.canRequestPackageInstalls()) { - // 引导用户去设置允许安装未知来源(你可以在 Flutter 侧提示用户) - val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:$packageName")) - startActivity(intent) - result.error("NEED_INSTALL_PERMISSION", "need install permission", null) - return - } - } - - val apkUri: Uri = FileProvider.getUriForFile(this, "$packageName.fileprovider", file) - val intent = Intent(Intent.ACTION_VIEW) - intent.setDataAndType(apkUri, "application/vnd.android.package-archive") - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - startActivity(intent) - result.success(true) - } -} diff --git a/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MyApplication.kt b/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MyApplication.kt index 10b37dd..bc33b7f 100644 --- a/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MyApplication.kt +++ b/android/app/src/main/kotlin/com/zhuoyun/qhdprevention/qhd_prevention/MyApplication.kt @@ -1,4 +1,4 @@ -package com.zhuoyun.qhdprevention.qhd_prevention +package uni.UNI85F7A17 import android.app.Application import android.content.Context diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index af9ab3f..f3132a1 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -503,10 +503,10 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "flutter-weihua"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -523,7 +523,7 @@ DEVELOPMENT_TEAM = 8AKCJ9LW7D; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -542,7 +542,7 @@ DEVELOPMENT_TEAM = 8AKCJ9LW7D; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -559,7 +559,7 @@ DEVELOPMENT_TEAM = 8AKCJ9LW7D; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -697,10 +697,10 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "flutter-weihua"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -728,10 +728,10 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.zhuoyun.qhdprevention.qhdPrevention; + PRODUCT_BUNDLE_IDENTIFIER = uni.UNI85F7A17; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "flutter-weihua"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "qa-zsaq"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/lib/customWidget/remote_file_page.dart b/lib/customWidget/remote_file_page.dart index dd637b0..55dabba 100644 --- a/lib/customWidget/remote_file_page.dart +++ b/lib/customWidget/remote_file_page.dart @@ -33,6 +33,9 @@ class _RemoteFilePageState extends State { late PdfControllerPinch _pdfController; int _totalPages = 0; + // 用于短文档(<=3页)的停留计时器兜底 + Timer? _pageViewTimer; + @override void initState() { super.initState(); @@ -93,12 +96,36 @@ class _RemoteFilePageState extends State { @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; @@ -117,12 +144,14 @@ class _RemoteFilePageState extends State { onDocumentLoaded: (document) { setState(() { _totalPages = document.pagesCount; + // 如果文档只有 1 页,直接视为已看完 + if (_totalPages <= 1) { + _hasScrolledToBottom = true; + } }); }, onPageChanged: (page) { - if (page == _totalPages - 1) { - setState(() => _hasScrolledToBottom = true); - } + _onPageChanged(page); }, ), ), diff --git a/lib/http/ApiService.dart b/lib/http/ApiService.dart index c161ba9..0269636 100644 --- a/lib/http/ApiService.dart +++ b/lib/http/ApiService.dart @@ -19,13 +19,13 @@ class ApiService { // static const String projectManagerUrl = 'https://pm.qhdsafety.com/zy-projectManage/'; // static const String publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUoHAavCikaZxjlDM6Km8cX+ye78F4oF39AcEfnE1p2Yn9pJ9WFxYZ4Vkh6F8SKMi7k4nYsKceqB1RwG996SvHQ5C3pM3nbXCP4K15ad6QhN4a7lzlbLhiJcyIKszvvK8ncUDw8mVQ0j/2mwxv05yH6LN9OKU6Hzm1ninpWeE+awIDAQAB' /// 人脸识别服务 - // static const String baseFacePath = "https://qaaqwh.qhdsafety.com/whb_stu_face"; - static const String baseFacePath = "http://192.168.20.240:8500/whb_stu_face/"; + static const String baseFacePath = "https://qaaqwh.qhdsafety.com/whb_stu_face"; + // static const String baseFacePath = "http://192.168.20.240:8500/whb_stu_face/"; // static const String baseFacePath = "http://192.168.0.25:38199"; //王轩服务器 /// 登录及其他管理后台接口 - // static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb"; - static const String basePath = "http://192.168.20.240:8500/integrated_whb";//测试服务器 + static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb"; + // static const String basePath = "http://192.168.20.240:8500/integrated_whb";//测试服务器 // static const String basePath = "http://192.168.0.25:28199";//王轩服务器 // static const String basePath = "http://192.168.0.45:28199";//长久服务器 @@ -190,7 +190,7 @@ U6Hzm1ninpWeE+awIDAQAB '/app/versionmanager/getVersion', method: Method.post, data: { - 'FILETYPE':Platform.pathSeparator + 'FILETYPE':Platform.isIOS ? 'iOS' : 'Android' }, ); } diff --git a/lib/main.dart b/lib/main.dart index 3d17f5f..24bcd71 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'pages/mine/mine_set_pwd_page.dart'; final GlobalKey navigatorKey = GlobalKey(); // 全局路由 final RouteObserver routeObserver = RouteObserver(); - +bool _isLoggingOut = false; // 全局消息控制器 class GlobalMessage { static void showError(String message) { @@ -109,17 +109,32 @@ void main( ) async { // 初始化HTTP管理器未授权回调 HttpManager.onUnauthorized = () async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setBool('isLoggedIn', false); - await prefs.remove('token'); - navigatorKey.currentState?.pushNamedAndRemoveUntil( - '/login', - (route) => false, - ); + final navigatorState = navigatorKey.currentState; + if (navigatorState == null) return; - Future.delayed(const Duration(milliseconds: 100), () { - GlobalMessage.showError('您的账号已在其他设备登录,已自动下线,请使用单一设备进行学习。'); - }); + // 尝试获取当前路由名(注意:ModalRoute 可能为 null) + final currentRouteName = ModalRoute.of(navigatorState.context)?.settings.name; + if (currentRouteName == '/login') { + // 已在登录页,直接返回,避免重复登出流程与提示 + return; + } + + if (_isLoggingOut) return; // 防止并发多次触发 + _isLoggingOut = true; + + try { + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool('isLoggedIn', false); + await prefs.remove('token'); + + navigatorState.pushNamedAndRemoveUntil('/login', (route) => false); + + Future.delayed(const Duration(milliseconds: 100), () { + GlobalMessage.showError('您的账号已在其他设备登录,已自动下线,请使用单一设备进行学习。'); + }); + } finally { + _isLoggingOut = false; + } }; // 自动登录逻辑 final prefs = await SharedPreferences.getInstance(); diff --git a/lib/pages/home/SafeCheck/CheckPersonSign/safecheck_sign_detail.dart b/lib/pages/home/SafeCheck/CheckPersonSign/safecheck_sign_detail.dart index 7a72547..779ad7c 100644 --- a/lib/pages/home/SafeCheck/CheckPersonSign/safecheck_sign_detail.dart +++ b/lib/pages/home/SafeCheck/CheckPersonSign/safecheck_sign_detail.dart @@ -353,9 +353,9 @@ setState(() { Widget _mainWidget() { bool isShowCheck = false; - if (FormUtils.hasValue(inspectedForm, 'hiddenList')) { - List list = inspectedForm['hiddenList']; - if (list.isEmpty) { + if (FormUtils.hasValue(form, 'hiddenList')) { + List list = form['hiddenList']; + if (list.isNotEmpty) { isShowCheck = true; } } diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index cf9362b..28e3bf0 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -190,32 +190,32 @@ class HomePageState extends State { /// 首次加载:先恢复缓存(如果有),然后在后台去刷新(只有当无缓存时才显示 loading) Future _initialLoad() async { - /// 清单列表 - final data = await ApiService.getListData(); - if (data['result'] == 'success') { - final content = data['varList'] ?? []; - for (Map item in content) { - if (item['checkCount'] == 0) { - totalList.add(item); - } - } - } - final result = await AuthService.checkUpdate(); - if (FormUtils.hasValue(result, 'pd')) { - // 有更新 提示更新 - Map pd = result['pd']; - CustomAlertDialog.showAlert( - context, - title: '更新通知', - content: pd['UPLOAD_CONTENT'] ?? '', - onConfirm: () async{ - final apkUrl = 'http://192.168.1.191:8888/app-release.apk'; - await showUpdateConfirmDialog(context, apkUrl: apkUrl); - }, - ); - return; - } + try{ + if (FormUtils.hasValue(result, 'pd')) { + Map pd = result['pd']; + final versionInfo = await getAppVersion(); + bool isWifi = true; + if (versionInfo.versionName != pd['VERSION']) { + //有更新 提示更新 + final ok = await CustomAlertDialog.showConfirm( + context, + barrierDismissible:false, + title: '更新通知', + content: isWifi ? '发现新版本,是否更新?为了更好的体验,请更新到最新版本。' : '发现新版本,检查到您当前使用的是移动网络,是否更新?更新时请注意流量消耗。为了更好的体验,请更新到最新版本。', + cancelText: pd['ISUPDATE'] == '1' ? '' : '稍后更新', + confirmText: '立即更新' + ); + if (ok) { + final apkUrl = pd['FILEURL'] ?? ''; + await showUpdateConfirm(context, apkUrl: apkUrl); + } + return; + } + + } + }catch(_){} + final corppromiseData = await ApiService.checkSafeCorppromise(); if (corppromiseData['ISSIGN'] == 1) { @@ -241,7 +241,16 @@ class HomePageState extends State { _fetchData(); _fetchHiddenList(showLoading: hiddenList.isEmpty); fetchAndSaveBd09(context); - + /// 清单列表 + final data = await ApiService.getListData(); + if (data['result'] == 'success') { + final content = data['varList'] ?? []; + for (Map item in content) { + if (item['checkCount'] == 0) { + totalList.add(item); + } + } + } } Future _onRefresh() async { @@ -333,7 +342,16 @@ class HomePageState extends State { // “我的工作”数据 final data = await ApiService.getWork(); final hidCount = data['hidCount'] as Map? ?? {}; - + setState(() { + // ———— 更新 workInfos ———— + workInfos = + workInfos.map((info) { + final idx = info['index'] as int; + final key = _workKey(idx); + final num = (hidCount[key] ?? 0).toString(); + return {...info, 'num': num}; + }).toList(); + }); // // 告知BadgeManager去更新“安全巡检”和“八项作业”角标 // BadgeManager().updateEnvInspectCount(); // BadgeManager().updateEightWorkCount(); @@ -350,15 +368,6 @@ class HomePageState extends State { //更新页面状态 setState(() { - // ———— 更新 workInfos ———— - workInfos = - workInfos.map((info) { - final idx = info['index'] as int; - final key = _workKey(idx); - final num = (hidCount[key] ?? 0).toString(); - return {...info, 'num': num}; - }).toList(); - // ———— 从 BadgeManager 拿最新的本页角标 ———— _safetyEnvironmentalInspection = BadgeManager().envInspectCount; _eight_work_count = BadgeManager().eightWorkCount; diff --git a/lib/pages/home/study/face_ecognition_page.dart b/lib/pages/home/study/face_ecognition_page.dart index 5321792..b6982b5 100644 --- a/lib/pages/home/study/face_ecognition_page.dart +++ b/lib/pages/home/study/face_ecognition_page.dart @@ -80,6 +80,7 @@ class _FaceRecognitionPageState extends State // 可选:释放相机,节省资源 try { _cameraController?.dispose(); + Navigator.pop(context); } catch (_) {} _cameraController = null; } else if (state == AppLifecycleState.resumed) { diff --git a/lib/pages/home/study/study_detail_page.dart b/lib/pages/home/study/study_detail_page.dart index 5947bb9..a167e85 100644 --- a/lib/pages/home/study/study_detail_page.dart +++ b/lib/pages/home/study/study_detail_page.dart @@ -225,7 +225,7 @@ class _StudyDetailPageState extends State await _submitPlayTime( snapshot: prevSnapshot, end: false, - seconds: _lastReported.inSeconds, + seconds: _lastReported.inSeconds.toString(), ); } @@ -256,7 +256,7 @@ class _StudyDetailPageState extends State 'VIDEOCOURSEWARE_ID': data['VIDEOCOURSEWARE_ID'] ?? '', 'CURRICULUM_ID': data['CURRICULUM_ID'] ?? '', 'CHAPTER_ID': data['CHAPTER_ID'] ?? '', - 'VIDEOTIME': data['VIDEOTIME'] ?? 0, + 'VIDEOTIME': data['VIDEOTIME'] ?? '0.0', 'IS_NODE': hasNodes, 'FIRST_INDEX': fi, 'NODE_INDEX': ni, @@ -265,7 +265,7 @@ class _StudyDetailPageState extends State await _submitPlayTime( snapshot: docSnapshot, end: true, - seconds: int.parse('${data['VIDEOTIME'] ?? '0'}'), + seconds: data['VIDEOTIME'] ?? '0.0', ); } } else { @@ -324,6 +324,17 @@ class _StudyDetailPageState extends State await onPass(); } else { ToastUtil.showError(context, '人脸验证未通过,无法继续'); + if (_videoController != null) { + try { + _videoController?.removeListener(_onTimeUpdate); + } catch (_) {} + try { + _videoController?.dispose(); + } catch (_) {} + _videoController = null; + } + _faceTimer?.cancel(); + setState(() {}); } } else { final ok = await CustomAlertDialog.showConfirm( @@ -458,7 +469,7 @@ class _StudyDetailPageState extends State return _submitPlayTime( snapshot: snapshot, end: false, - seconds: pos.inSeconds, + seconds: pos.inSeconds.toString(), ); }) .whenComplete(() { @@ -490,7 +501,7 @@ class _StudyDetailPageState extends State await _submitPlayTime( snapshot: snapshot, end: true, - seconds: finalSeconds, + seconds: finalSeconds.toString(), ); }) .whenComplete(() { @@ -516,7 +527,7 @@ class _StudyDetailPageState extends State Future _submitPlayTime({ required Map snapshot, required bool end, - required int seconds, + required String seconds, }) async { // snapshot 必须包含 VIDEOCOURSEWARE_ID if (snapshot['VIDEOCOURSEWARE_ID'] == null || @@ -602,7 +613,7 @@ class _StudyDetailPageState extends State final resT = (resTraw is num) ? resTraw.toDouble() - : double.tryParse('$resTraw') ?? seconds.toDouble(); + : double.tryParse('$resTraw') ?? double.parse(seconds); final videoTimeRaw = snapshot['VIDEOTIME']; final videoTime = diff --git a/lib/pages/home/study/take_exam_page.dart b/lib/pages/home/study/take_exam_page.dart index bba221e..4ea91fb 100644 --- a/lib/pages/home/study/take_exam_page.dart +++ b/lib/pages/home/study/take_exam_page.dart @@ -232,7 +232,7 @@ class _TakeExamPageState extends State { content: passed ? '您的成绩为 $score 分,恭喜您通过本次考试,请继续保持!' - : '您的成绩为 $score 分,很遗憾您没有通过本次考试,请再接再 厉!', + : '您的成绩为 $score 分,很遗憾您没有通过本次考试,请再接再厉!', cancelText: '', confirmText: '确定', ); diff --git a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart index 09ebd58..81b5106 100644 --- a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart @@ -1322,6 +1322,7 @@ class SignItemWidget extends StatelessWidget { this.smallThumbSize = 50.0, this.signImageWidth = 200.0, this.signImageHeight = 100.0, + required this.isShowTime, }) : super(key: key); /// signs map 中用于查找签名列表的 key @@ -1348,6 +1349,7 @@ class SignItemWidget extends StatelessWidget { /// 签名图片展示尺寸(每张一行) final double signImageWidth; final double signImageHeight; + final bool isShowTime; @override Widget build(BuildContext context) { @@ -1579,22 +1581,25 @@ class SignItemWidget extends StatelessWidget { ), ), ); - // 时间文本(始终固定在最右侧并底部对齐) - list.add(const SizedBox(height: 10)); - list.add( - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const SizedBox(), - Text( - lastTime, - textAlign: TextAlign.right, - overflow: TextOverflow.ellipsis, - style: const TextStyle(fontSize: 13, color: Colors.black87), - ), - ], - ), - ); + if (isShowTime) { + // 时间文本(始终固定在最右侧并底部对齐) + list.add(const SizedBox(height: 10)); + list.add( + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(), + Text( + lastTime, + textAlign: TextAlign.right, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 13, color: Colors.black87), + ), + ], + ), + ); + } + return list; } @@ -1615,6 +1620,7 @@ class ConfirmWithSignWidget extends StatelessWidget { required this.nameKey, // 'CONFIRM_USER_NAME', required this.headerTitle, // '作业负责人意见', required this.roleTitle, // '作业负责人', + this.isShowTime = true, }) : super(key: key); // 允许外部传入 null(但构建内部会降级为 {},避免空异常) @@ -1643,6 +1649,8 @@ class ConfirmWithSignWidget extends StatelessWidget { /// 传给 SignItemWidget 的 title(例如 '作业负责人') final String roleTitle; + final bool isShowTime; + @override Widget build(BuildContext context) { // 容错:如果传入为 null,降级成空 Map,后续访问安全 @@ -1767,6 +1775,7 @@ class ConfirmWithSignWidget extends StatelessWidget { pd: safePd, signs: safeSigns, baseImgPath: baseImgPath, + isShowTime:isShowTime, ), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dangerous_options_page.dart b/lib/pages/home/tap/tabList/special_wrok/dangerous_options_page.dart index 93cc33c..8eabf59 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dangerous_options_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dangerous_options_page.dart @@ -26,11 +26,7 @@ class SignImageData { String? filePath; int? key; - SignImageData({ - required this.SIGNER_TIME, - this.filePath, - this.key, - }); + SignImageData({required this.SIGNER_TIME, this.filePath, this.key}); Map toJson() => { 'SIGNER_TIME': SIGNER_TIME, @@ -47,8 +43,10 @@ class SignImageData { } @override - String toString() => 'SignImageData(key:$key, filePath:$filePath, SIGNER_TIME:$SIGNER_TIME)'; + String toString() => + 'SignImageData(key:$key, filePath:$filePath, SIGNER_TIME:$SIGNER_TIME)'; } + class DangerousOptionsPage extends StatefulWidget { final int index; final int status; @@ -134,40 +132,61 @@ class _DangerousOptionsPageState extends State { return; } LoadingDialogHelper.show(); - List filePaths = - signImgList.map((img) => img.filePath ?? '').toList(); - final result = await ApiService.saveDangerousOptionsFile(filePaths); - final List signList = result['FILE_PATH_LIST']; - List> sineImageList = []; + List 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()); + final List signList = result['FILE_PATH_LIST']; + for (SignImageData data in filePaths) { for (Map img in signList) { String imgName = 'file${data.key}'; - if (data.filePath!.contains('uploadFiles')) { - final idata = { - 'filePath': data.filePath, - 'SIGNER_TIME': data.SIGNER_TIME, - 'key': data.key, - }; - sineImageList.add(idata); - } + if (imgName == img['key']) { final idata = { 'filePath': img['filePath'] ?? '', 'SIGNER_TIME': data.SIGNER_TIME, 'key': data.key, }; - sineImageList.add(idata); + severImageList.add(idata); } } } + setState(() => buttonLoading = true); LoadingDialogHelper.hide(); Navigator.pop(context, { 'imgList': - imgList - .map((e) => {'local': e.localPath, 'remote': e.serverPath}) - .toList(), - 'signImgList': sineImageList, + imgList + .map((e) => {'local': e.localPath, 'remote': e.serverPath}) + .toList(), + 'signImgList': severImageList, 'index': index, 'status': status, }); @@ -198,56 +217,56 @@ class _DangerousOptionsPageState extends State { Widget _signListWidget() { return Column( children: - signImgList.map((imgData) { - final idx = signImgList.indexOf(imgData); - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + signImgList.map((imgData) { + final idx = signImgList.indexOf(imgData); + return Column( children: [ - GestureDetector( - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 230, - maxHeight: 150, - ), - child: - (imgData.filePath ?? '').contains('uploadFiles') - ? Image.network( - '${ApiService.baseImgPath}${imgData.filePath}', - ) - : Image.file( - File(imgData.filePath ?? ''), - fit: BoxFit.contain, - ), - ), - onTap: - () => presentOpaque( - SingleImageViewer(imageUrl: imgData.filePath ?? ''), - context, - ), - ), - Column( + const SizedBox(height: 10), + const Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - CustomButton( - text: '删除', - height: 30, - padding: const EdgeInsets.symmetric(horizontal: 10), - backgroundColor: Colors.red, - onPressed: () { - setState(() => signImgList.removeAt(idx)); - }, + GestureDetector( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 230, + maxHeight: 150, + ), + child: + (imgData.filePath ?? '').contains('uploadFiles') + ? Image.network( + '${ApiService.baseImgPath}${imgData.filePath}', + ) + : Image.file( + File(imgData.filePath ?? ''), + fit: BoxFit.contain, + ), + ), + onTap: + () => presentOpaque( + SingleImageViewer(imageUrl: imgData.filePath ?? ''), + context, + ), + ), + Column( + children: [ + CustomButton( + text: '删除', + height: 30, + padding: const EdgeInsets.symmetric(horizontal: 10), + backgroundColor: Colors.red, + onPressed: () { + setState(() => signImgList.removeAt(idx)); + }, + ), + const SizedBox(height: 80), + ], ), - const SizedBox(height: 80), ], ), ], - ), - ], - ); - }).toList(), + ); + }).toList(), ); } @@ -343,14 +362,16 @@ class _DangerousOptionsPageState extends State { maxCount: 2, mediaType: MediaType.image, initialMediaPaths: - imgList - .map((e) => '${ApiService.baseImgPath}${e.serverPath}') - .toList(), + imgList + .map((e) => '${ApiService.baseImgPath}${e.serverPath}') + .toList(), onChanged: (paths) {}, onMediaAdded: _onImageAdded, onMediaRemoved: (path) { print(path); - final item = imgList.firstWhere((e) => path.contains(e.localPath) ); + final item = imgList.firstWhere( + (e) => path.contains(e.localPath), + ); _onImageRemoved(item); }, onAiIdentify: () {}, @@ -381,4 +402,4 @@ class _DangerousOptionsPageState extends State { ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/HotWorkDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/HotWorkDetailFormWidget.dart index 7e5048c..4d24051 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/HotWorkDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/HotWorkDetailFormWidget.dart @@ -223,6 +223,7 @@ class _HotWorkDetailFormWidgetState extends State { const Divider(), ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart index f0911d4..da62e78 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart @@ -110,7 +110,8 @@ class SpecialWorkFormBaseWork extends StatelessWidget { baseImgPath: baseImgPath, sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', - headerTitle: '安全交底人意见', + headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -121,12 +122,14 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'GUARDIAN')) ConfirmWithSignWidget( signs: signs, pd: pd, + isShowTime: false, baseImgPath: baseImgPath, sectionKey: 'GUARDIAN', nameKey: 'GUARDIAN_USER_NAME', diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/ysgd_work_detail/hotwork_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/ysgd_work_detail/hotwork_ysgd_detail.dart index b5a44aa..2aca5c4 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/ysgd_work_detail/hotwork_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/ysgd_work_detail/hotwork_ysgd_detail.dart @@ -387,7 +387,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadDetailFormWidget.dart index b2d5bc6..7984dbc 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadDetailFormWidget.dart @@ -212,6 +212,7 @@ class _CutroadDetailFormWidgetState extends State { ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart index 4c57ce7..9dd9a42 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart @@ -106,6 +106,7 @@ class CutroadFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -116,6 +117,7 @@ class CutroadFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'CONFIRM')) diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/ysgd_work_detail/cutroad_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/ysgd_work_detail/cutroad_ysgd_detail.dart index 6c31b1b..14cf1ea 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/ysgd_work_detail/cutroad_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/ysgd_work_detail/cutroad_ysgd_detail.dart @@ -378,7 +378,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/BreakgroundDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/BreakgroundDetailFormWidget.dart index f330186..bb8899c 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/BreakgroundDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/BreakgroundDetailFormWidget.dart @@ -210,6 +210,7 @@ class _BreakgroundDetailFormWidgetState ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart index 2cf212f..d2c22d0 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart @@ -116,6 +116,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -126,6 +127,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'CONFIRM')) diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/ysgd_work_detail/breakground_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/ysgd_work_detail/breakground_ysgd_detail.dart index 4969466..61ac714 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/ysgd_work_detail/breakground_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/ysgd_work_detail/breakground_ysgd_detail.dart @@ -381,7 +381,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/HoistworkDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/HoistworkDetailFormWidget.dart index 1745dba..c073032 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/HoistworkDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/HoistworkDetailFormWidget.dart @@ -261,6 +261,7 @@ class _HoistworkDetailFormWidgetState extends State { const Divider(), ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart index 279d013..0bf0450 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart @@ -278,6 +278,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -288,6 +289,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/ysgd_work_detail/hoistwork_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/ysgd_work_detail/hoistwork_ysgd_detail.dart index d2447aa..97f5ff7 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/ysgd_work_detail/hoistwork_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/ysgd_work_detail/hoistwork_ysgd_detail.dart @@ -381,7 +381,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/HighWorkDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/HighWorkDetailFormWidget.dart index 081339f..cb374bf 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/HighWorkDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/HighWorkDetailFormWidget.dart @@ -241,6 +241,7 @@ class _HighWorkDetailFormWidgetState extends State { const Divider(), ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart index 668c854..7215ead 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart @@ -115,6 +115,7 @@ class HighWorkFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -125,6 +126,7 @@ class HighWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'CONFIRM')) diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart index 47e17ac..5850949 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart @@ -436,7 +436,25 @@ class _HighworkApplyDetailState extends State { //FocusHelper.clearFocus(context); }); } + bool checkWorkTime(Map 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 = 7 * 24 * 60 * 60 * 1000; + if (diffMs >= max8h) { + ToastUtil.showNormal(context, '作业开始时间与结束时间应不超过7天,请重新选择'); + return false; + } + return true; + } /// 提交 1 提交 0暂存 Future _submit(String status) async { // 通用文本字段校验规则 diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart index 3664e87..f125446 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart @@ -59,6 +59,12 @@ class _HighworkJszyDetailState extends State { // 校验:结束时间必须晚于开始时间 if (end.isAtSameMomentAs(start) || end.isBefore(start)) { ToastUtil.showNormal(context, '作业开始时间不能晚于或等于结束时间,请重新选择'); + return false; + } + final diffMs = end.difference(start).inMilliseconds; + const max8h = 7 *24 * 60 * 60 * 1000; + if (diffMs >= max8h) { + ToastUtil.showNormal(context, '作业开始时间与结束时间应不超过7天,请重新选择'); return false; } @@ -68,7 +74,6 @@ class _HighworkJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - String? reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -84,19 +89,19 @@ class _HighworkJszyDetailState extends State { title: '作废原因', hintText: '请输入作废原因', cancelText: '取消', - confirmText: '确定' + confirmText: '确定', ); // 用户取消(或点遮罩、返回键) -if (reasonText == null) { - // 取消时什么也不做,不提示 - return; -} + if (reasonText == null) { + // 取消时什么也不做,不提示 + return; + } -// 用户点击确认但没填内容 -if (reasonText.isEmpty) { - ToastUtil.showNormal(context, '请填写作废原因'); - return; -} + // 用户点击确认但没填内容 + if (reasonText.isEmpty) { + ToastUtil.showNormal(context, '请填写作废原因'); + return; + } } // 存回 measures @@ -129,7 +134,7 @@ if (reasonText.isEmpty) { if (result['result'] == 'success') { ToastUtil.showSuccess(context, '保存成功'); Navigator.of(context).pop(true); - }else{ + } else { ToastUtil.showNormal(context, '操作失败:${result['msg'] ?? '未知错误'}'); } } catch (e) { @@ -214,7 +219,7 @@ if (reasonText.isEmpty) { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( -spacing: 12, + spacing: 12, children: [ // _setSafeDetailWidget(), HighWorkFormBaseWork( diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/ysgd_work_detail/highwork_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/ysgd_work_detail/highwork_ysgd_detail.dart index 0c0802e..6c048fa 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/ysgd_work_detail/highwork_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/ysgd_work_detail/highwork_ysgd_detail.dart @@ -381,7 +381,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/home_gas_test_page.dart b/lib/pages/home/tap/tabList/special_wrok/home_gas_test_page.dart index 0b70c43..206d51f 100644 --- a/lib/pages/home/tap/tabList/special_wrok/home_gas_test_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/home_gas_test_page.dart @@ -184,7 +184,6 @@ class _HomeGasTestPageState extends State { return; } if (status == 1) { - Map itemForm = { 'ANALYZE_GAS': _gasController.text, 'ANALYZE_RESULT': _resultController.text, @@ -219,16 +218,16 @@ class _HomeGasTestPageState extends State { confirmText: '确定', ); // 用户取消(或点遮罩、返回键) -if (reasonText == null) { - // 取消时什么也不做,不提示 - return; -} + if (reasonText == null) { + // 取消时什么也不做,不提示 + return; + } -// 用户点击确认但没填内容 -if (reasonText.isEmpty) { - ToastUtil.showNormal(context, '请填写作废原因'); - return; -} + // 用户点击确认但没填内容 + if (reasonText.isEmpty) { + ToastUtil.showNormal(context, '请填写作废原因'); + return; + } } final confirmed = await CustomAlertDialog.showConfirm( context, @@ -256,7 +255,7 @@ if (reasonText.isEmpty) { 'CORPINFO_ID': SessionService.instance.corpinfoId, 'USER_ID': SessionService.instance.loginUserId, }; - + LoadingDialogHelper.show(); try { await ApiService.saveGasTest('hotwork', formData, imagePaths); ToastUtil.showNormal(context, status == 1 ? '保存成功' : '作废成功'); @@ -266,6 +265,7 @@ if (reasonText.isEmpty) { } finally { setState(() => _loading = false); } + LoadingDialogHelper.hide(); } @override diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ElectricityDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ElectricityDetailFormWidget.dart index d3efb95..28daf39 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ElectricityDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ElectricityDetailFormWidget.dart @@ -244,6 +244,7 @@ class _ElectricityDetailFormWidgetState extends State( diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/SpecialWorkFormBaseWork.dart index 9a52d33..4cb1cc8 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/SpecialWorkFormBaseWork.dart @@ -292,7 +292,8 @@ class SpecialWorkFormBaseWork extends StatelessWidget { baseImgPath: baseImgPath, sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', - headerTitle: '安全交底人意见', + headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -303,6 +304,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/qtfx_work_detail/electricity_gas_test_page.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/qtfx_work_detail/electricity_gas_test_page.dart index 9b57cdc..732f5de 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/qtfx_work_detail/electricity_gas_test_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/qtfx_work_detail/electricity_gas_test_page.dart @@ -217,6 +217,7 @@ if (reasonText.isEmpty) { 'CORPINFO_ID': SessionService.instance.corpinfoId, 'USER_ID': SessionService.instance.loginUserId, }; + LoadingDialogHelper.show(); try { await ApiService.saveGasTest('electricity', formData, imagePaths); @@ -227,6 +228,7 @@ if (reasonText.isEmpty) { } finally { setState(() => _loading = false); } + LoadingDialogHelper.hide(); } /// 选择气体类型 diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ysgd_work_detail/electricity_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ysgd_work_detail/electricity_ysgd_detail.dart index b26d0fa..09fd631 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ysgd_work_detail/electricity_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/ysgd_work_detail/electricity_ysgd_detail.dart @@ -387,7 +387,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardDetailFormWidget.dart index 82424a7..ef19078 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardDetailFormWidget.dart @@ -642,6 +642,7 @@ class _BlindboardDetailFormWidgetState const Divider(), ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart index 5920eac..1dd381f 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart @@ -299,6 +299,7 @@ class BlindboardFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -309,6 +310,7 @@ class BlindboardFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'CONFIRM')) diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/ysgd_work_detail/blindboard_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/ysgd_work_detail/blindboard_ysgd_detail.dart index e46d3a5..d0cf1b0 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/ysgd_work_detail/blindboard_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/ysgd_work_detail/blindboard_ysgd_detail.dart @@ -374,7 +374,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpaceWorkDetailFormWidget.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpaceWorkDetailFormWidget.dart index 7e7372a..4d79db1 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpaceWorkDetailFormWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpaceWorkDetailFormWidget.dart @@ -254,6 +254,7 @@ class _SpaceWorkDetailFormWidgetState extends State { const Divider(), ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', + isInput: false, isEditable: widget.isEditable, onTap: () async { await showDialog( diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart index 225b1d0..8277dba 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart @@ -120,6 +120,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'CONFESS', nameKey: 'CONFESS_USER_NAME', headerTitle: '安全交底人', + isShowTime: false, roleTitle: '安全交底人', ), if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) @@ -130,6 +131,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { sectionKey: 'ACCEPT_CONFESS', nameKey: 'ACCEPT_CONFESS_USER_NAME', headerTitle: '接受交底人', + isShowTime: false, roleTitle: '', ), if (FormUtils.hasValue(signs, 'CONFIRM')) diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/qtfx_work_detail/spacework_gas_test_page.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/qtfx_work_detail/spacework_gas_test_page.dart index 1a86840..2e3f07c 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/qtfx_work_detail/spacework_gas_test_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/qtfx_work_detail/spacework_gas_test_page.dart @@ -252,6 +252,7 @@ if (reasonText.isEmpty) { barrierDismissible: false, ); if (!confirmed) return; + LoadingDialogHelper.show(); try { await ApiService.saveGasTest('confinedspace', formData, imagePaths); @@ -262,6 +263,7 @@ if (reasonText.isEmpty) { } finally { setState(() => _loading = false); } + LoadingDialogHelper.hide(); } /// 选择计量单位 diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/ysgd_work_detail/spacework_ysgd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/ysgd_work_detail/spacework_ysgd_detail.dart index 3ecaf46..35fca91 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/ysgd_work_detail/spacework_ysgd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/ysgd_work_detail/spacework_ysgd_detail.dart @@ -391,7 +391,7 @@ if (reasonText.isEmpty) { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( - allowPast:false, + minTimeStr: pd['WORK_END_DATE'], mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index fe592d4..1597d47 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -101,19 +101,20 @@ class _LoginPageState extends State { if (FormUtils.hasValue(result, 'pd')) { Map pd = result['pd']; final versionInfo = await getAppVersion(); - bool isWifi = await checkNetworkWifi(); + bool isWifi = true; if (versionInfo.versionName != pd['VERSION']) { //有更新 提示更新 final ok = await CustomAlertDialog.showConfirm( context, + barrierDismissible:false, title: '更新通知', content: isWifi ? '发现新版本,是否更新?为了更好的体验,请更新到最新版本。' : '发现新版本,检查到您当前使用的是移动网络,是否更新?更新时请注意流量消耗。为了更好的体验,请更新到最新版本。', cancelText: pd['ISUPDATE'] == '1' ? '' : '稍后更新', confirmText: '立即更新' ); if (ok) { - // await showUpdateConfirmDialog(context, apkUrl: apkUrl); - + final apkUrl = pd['FILEURL'] ?? ''; + await showUpdateConfirm(context, apkUrl: apkUrl); } return; } diff --git a/lib/pages/mine/mine_set_page.dart b/lib/pages/mine/mine_set_page.dart index c255b09..237d4b5 100644 --- a/lib/pages/mine/mine_set_page.dart +++ b/lib/pages/mine/mine_set_page.dart @@ -8,6 +8,7 @@ import 'package:qhd_prevention/pages/mine/mine_set_pwd_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; import 'package:qhd_prevention/services/auth_service.dart'; import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/update/update_dialogs.dart'; import '../../tools/tools.dart'; @@ -26,19 +27,26 @@ class _MineSetPageState extends State { final result = await AuthService.checkUpdate(); LoadingDialogHelper.hide(); if (FormUtils.hasValue(result, 'pd')) { - - // 有更新 提示更新 Map pd = result['pd']; - CustomAlertDialog.showConfirm( - context, - title: '更新通知', - cancelText: '', - confirmText: '我知道了', - content: pd['UPLOAD_CONTENT'] ?? '', - onConfirm: () { - ToastUtil.showNormal(context, '更新去吧!'); - } - ); + final versionInfo = await getAppVersion(); + bool isWifi = true; + if (versionInfo.versionName != pd['VERSION']) { + //有更新 提示更新 + final ok = await CustomAlertDialog.showConfirm( + context, + barrierDismissible:false, + title: '更新通知', + content: isWifi ? '发现新版本,是否更新?为了更好的体验,请更新到最新版本。' : '发现新版本,检查到您当前使用的是移动网络,是否更新?更新时请注意流量消耗。为了更好的体验,请更新到最新版本。', + cancelText: pd['ISUPDATE'] == '1' ? '' : '稍后更新', + confirmText: '立即更新' + ); + if (ok) { + final apkUrl = pd['FILEURL'] ?? ''; + await showUpdateConfirm(context, apkUrl: apkUrl); + } + return; + } + }else{ _loadAppVersion(); diff --git a/lib/tools/tools.dart b/lib/tools/tools.dart index adc53e1..9921602 100644 --- a/lib/tools/tools.dart +++ b/lib/tools/tools.dart @@ -600,6 +600,7 @@ Future checkNetworkWifi() async { final connectivityResult = await Connectivity().checkConnectivity(); if (connectivityResult == ConnectivityResult.mobile) { print("当前是移动网络(可能是 2G/3G/4G/5G)"); + return false; } else if (connectivityResult == ConnectivityResult.wifi) { return true; print("当前是 WiFi"); diff --git a/lib/tools/update/update_dialogs.dart b/lib/tools/update/update_dialogs.dart index ba0cec6..506a201 100644 --- a/lib/tools/update/update_dialogs.dart +++ b/lib/tools/update/update_dialogs.dart @@ -3,42 +3,15 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/services/update_service.dart'; /// 显示“发现新版本”确认对话框,点击更新后会弹出下载进度弹窗 -Future showUpdateConfirmDialog(BuildContext context, { +Future showUpdateConfirm(BuildContext context, { required String apkUrl, - String title = '发现新版本', - String content = '检测到新版本,是否立即更新?', - String updateButtonText = '更新', - String cancelButtonText = '稍后', + }) async { - final confirmed = await showDialog( + await showDialog( context: context, barrierDismissible: false, - builder: (ctx) { - return AlertDialog( - title: Text(title), - content: Text(content), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(false), - child: Text(cancelButtonText), - ), - ElevatedButton( - onPressed: () => Navigator.of(ctx).pop(true), - child: Text(updateButtonText), - ), - ], - ); - }, + builder: (ctx) => DownloadProgressDialog(apkUrl: apkUrl), ); - - if (confirmed == true) { - // 跳出下载进度弹窗(阻塞式,直到弹窗被关闭) - await showDialog( - context: context, - barrierDismissible: false, - builder: (ctx) => DownloadProgressDialog(apkUrl: apkUrl), - ); - } } /// 下载进度弹窗(会在 initState 里自动开始下载) diff --git a/pubspec.yaml b/pubspec.yaml index 60f0f26..a1cc40b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,8 +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+10 -version: 2.2.0 +version: 2.1.2+59 environment: sdk: ^3.7.0