From 2bb1fae09b507bb7050b0979028f0e138a7c85d4 Mon Sep 17 00:00:00 2001 From: hs <873121290@qq.com> Date: Wed, 17 Sep 2025 10:58:46 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=82=E3=80=82=E3=80=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/ApiService.dart | 4 +- .../safeCheck_assignment_detail_page.dart | 5 +- .../study/strengthen_video_study_page.dart | 2 +- lib/pages/home/study/study_detail_page.dart | 97 +- lib/pages/home/study/study_my_task_page.dart | 2 +- lib/pages/home/study/take_exam_page.dart | 6 + lib/pages/home/tap/item_list_widget.dart | 528 +++++++---- .../special_wrok/MeasuresListWidget.dart | 881 ++++++++++-------- .../dh_work/HotWorkDetailFormWidget.dart | 6 +- .../hotwork_safe_func_sure.dart | 12 +- .../dbbz_work_detail/hotwork_dbbz_detail.dart | 6 +- .../dh_work_detai/hotwork_apply_detail.dart | 10 +- .../dh_work/hotwork_list_page.dart | 360 ++++--- .../ysgd_work_detail/hotwork_ysgd_detail.dart | 1 + .../dl_work/CutroadDetailFormWidget.dart | 6 +- .../cutroad_safe_func_sure.dart | 279 +++--- .../dl_work/cutroad_list_page.dart | 121 +-- .../dl_work_detai/cutroad_apply_detail.dart | 14 +- .../ysgd_work_detail/cutroad_ysgd_detail.dart | 1 + .../zyr_work_detail/cutroad_zyr_detail.dart | 2 +- .../dt_work/BreakgroundDetailFormWidget.dart | 72 +- .../breakground_safe_func_sure.dart | 12 +- .../dt_work/breakground_list_page.dart | 124 +-- .../breakground_apply_detail.dart | 10 +- .../breakground_ysgd_detail.dart | 1 + .../breakground_zyr_detail.dart | 2 +- .../dz_work/HoistworkDetailFormWidget.dart | 7 +- .../hoistwork_safe_func_sure.dart | 12 +- .../dz_work_detai/hoistwork_apply_detail.dart | 10 +- .../dz_work/hoistwork_list_page.dart | 348 +++---- .../hoistwork_ysgd_detail.dart | 1 + .../gc_work/HighWorkDetailFormWidget.dart | 6 +- .../highwork_safe_func_sure.dart | 12 +- .../gc_work_detai/highwork_apply_detail.dart | 10 +- .../gc_work/highwork_list_page.dart | 164 +--- .../highwork_ysgd_detail.dart | 1 + .../ElectricityDetailFormWidget.dart | 2 + .../electricity_safe_func_sure.dart | 12 +- .../lsyd_work/electricity_list_page.dart | 164 +--- .../electricity_apply_detail.dart | 10 +- .../electricity_ysgd_detail.dart | 1 + .../mbcd_work/BlindboardDetailFormWidget.dart | 6 +- .../blindboard_safe_func_sure.dart | 12 +- .../mbcd_work/blindboard_list_page.dart | 112 +-- .../blindboard_apply_detail.dart | 10 +- .../blindboard_ysgd_detail.dart | 1 + .../sxkj_work/SpaceWorkDetailFormWidget.dart | 7 +- .../spacework_safe_func_sure.dart | 12 +- .../spacework_apply_detail.dart | 10 +- .../sxkj_work/spacework_list_page.dart | 133 +-- .../spacework_ysgd_detail.dart | 1 + 51 files changed, 1709 insertions(+), 1919 deletions(-) diff --git a/lib/http/ApiService.dart b/lib/http/ApiService.dart index 29ddaaa..37401fd 100644 --- a/lib/http/ApiService.dart +++ b/lib/http/ApiService.dart @@ -25,9 +25,9 @@ class ApiService { /// 登录及其他管理后台接口 // 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.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";//长久服务器 + // static const String basePath = "http://192.168.0.45:28199";//长久服务器 /// 图片文件服务 static const String baseImgPath = "https://file.zcloudchina.com/YTHFile"; diff --git a/lib/pages/home/SafeCheck/DangeCheck/safeCheck_assignment_detail_page.dart b/lib/pages/home/SafeCheck/DangeCheck/safeCheck_assignment_detail_page.dart index cef5f77..9757b4c 100644 --- a/lib/pages/home/SafeCheck/DangeCheck/safeCheck_assignment_detail_page.dart +++ b/lib/pages/home/SafeCheck/DangeCheck/safeCheck_assignment_detail_page.dart @@ -280,10 +280,7 @@ class _SafecheckAssignmentDetailPageState isEditable: _isEdit, isRequired: false, isClean: false, - onTapClean: () { - ToastUtil.showNormal(context, '已清除'); - setState(() {}); - }, + onTapClean: () {}, text: form['RECTIFICATIONDEPTNAME'] ?? '请选择', onTap: () => chooseUnitHandle('key'), ), diff --git a/lib/pages/home/study/strengthen_video_study_page.dart b/lib/pages/home/study/strengthen_video_study_page.dart index f0394ed..e10ca3e 100644 --- a/lib/pages/home/study/strengthen_video_study_page.dart +++ b/lib/pages/home/study/strengthen_video_study_page.dart @@ -202,7 +202,7 @@ class _StrengthenStudyPageState extends State { 'STUDENT_ID': widget.studentId, 'STRENGTHEN_PAPER_QUESTION_ID': _info['STRENGTHEN_STAGEEXAMPAPER_INPUT_ID'], ...data - }, examType: type), context); + }, examType: type, jumpType: 2,), context); } else { ToastUtil.showError(context, '请求错误'); } diff --git a/lib/pages/home/study/study_detail_page.dart b/lib/pages/home/study/study_detail_page.dart index 00d134f..c278296 100644 --- a/lib/pages/home/study/study_detail_page.dart +++ b/lib/pages/home/study/study_detail_page.dart @@ -212,12 +212,7 @@ class _StudyDetailPageState extends State seconds: _lastReported.inSeconds, ); } - _lastReported = Duration.zero; - _currentVideoData = data; - _hasNodes = hasNodes; - _currentFirstIndex = fi; - _currentNodeIndex = ni; // 暂停已有播放器(安全) try { @@ -250,6 +245,7 @@ class _StudyDetailPageState extends State 'IS_NODE': hasNodes, 'FIRST_INDEX': fi, 'NODE_INDEX': ni, + 'IS_VIDEO': 1, }; await _submitPlayTime( snapshot: docSnapshot, @@ -262,6 +258,12 @@ class _StudyDetailPageState extends State ToastUtil.showNormal(context, '课件文件资源已失效,请联系管理员'); } } else { + _currentVideoData = data; + _lastReported = Duration.zero; + + _hasNodes = hasNodes; + _currentFirstIndex = fi; + _currentNodeIndex = ni; LoadingDialogHelper.show(); // 视频 await _getVideoPlayInfo(data['VIDEOCOURSEWARE_ID']); @@ -475,14 +477,14 @@ class _StudyDetailPageState extends State required bool end, required int seconds, }) async { - // snapshot 中应该包含 VIDEOCOURSEWARE_ID, CURRICULUM_ID, CHAPTER_ID, VIDEOTIME, ... + // snapshot 必须包含 VIDEOCOURSEWARE_ID if (snapshot['VIDEOCOURSEWARE_ID'] == null || - snapshot['VIDEOCOURSEWARE_ID'] == '') - return; + snapshot['VIDEOCOURSEWARE_ID'] == '') return; - // 如果已经上报结束并且当前不是结束上报,则跳过非结束上报 + // 如果已经上报结束并且当前不是结束上报,则跳过非结束上报(原逻辑) if (_endReported && !end) return; + // 构造要上报的参数 Map data = { 'VIDEOCOURSEWARE_ID': snapshot['VIDEOCOURSEWARE_ID'] ?? '', 'CURRICULUM_ID': snapshot['CURRICULUM_ID'] ?? '', @@ -495,6 +497,10 @@ class _StudyDetailPageState extends State 'loading': false, }; + // 如果这是“非视频课件”(通过 snapshot['IS_VIDEO']==1 标记), + // 则按照“学完即 100%”的规则单次上报并把 UI 设置为 100%。 + final isNonVideo = (snapshot['IS_VIDEO'] != null && snapshot['IS_VIDEO'].toString() == '1'); + const int maxRetries = 2; int attempt = 0; while (true) { @@ -503,32 +509,70 @@ class _StudyDetailPageState extends State final resData = await ApiService.fnSubmitPlayTime(data); final pd = resData['pd'] ?? {}; - // 解析后端返回的 RESOURCETIME(可能是数字或字符串) + if (isNonVideo) { + // 非视频课件:强制显示 100%,不依赖后端返回的 RESOURCETIME 比例 + final str = '100%'; + if (mounted) { + setState(() { + if (snapshot['IS_NODE'] == true) { + final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex; + final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex; + if (fi >= 0 && fi < _videoList.length) { + final nodes = _videoList[fi]['nodes'] as List?; + if (nodes != null && ni >= 0 && ni < nodes.length) { + _videoList[fi]['nodes'][ni]['percent'] = str; + } + } + } else { + final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex; + if (fi >= 0 && fi < _videoList.length) { + _videoList[fi]['percent'] = str; + } + } + }); + } + + // 如果后端在 pd 中表明可以考试,按之前逻辑处理(和视频一致) + if (end && pd['CANEXAM'] == '1') { + _videoController?.pause(); + + final ok = await CustomAlertDialog.showConfirm( + context, + title: '温馨提示', + content: '当前任务内所有课程均已学完,是否直接参加考试?', + cancelText: '否', + confirmText: '是', + ); + if (ok) { + _startExam(resData); + } + } + + break; // 非视频已上报并处理完毕 -> 退出 + } + + // 以下为视频上报原有逻辑:解析后端返回数据并更新进度 final resTraw = pd['RESOURCETIME']; - final resT = - (resTraw is num) - ? resTraw.toDouble() - : double.tryParse('$resTraw') ?? seconds.toDouble(); + final resT = (resTraw is num) ? resTraw.toDouble() : double.tryParse('$resTraw') ?? seconds.toDouble(); final videoTimeRaw = snapshot['VIDEOTIME']; - final videoTime = - (videoTimeRaw is String) - ? double.tryParse(videoTimeRaw) ?? 1.0 - : (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0); + final videoTime = (videoTimeRaw is String) + ? double.tryParse(videoTimeRaw) ?? 1.0 + : (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0); final comp = pd['PLAYCOUNT'] != null && pd['PLAYCOUNT'] > 0; - - final pctDouble = - comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0); - final pct = (pctDouble.clamp(0.00, 100.00) * 100).round() / 100; - final str = '${pct}%'; + final pctDouble = comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0); + // 保留两位小数并去掉不必要末尾 + double pctClamped = pctDouble.clamp(0.00, 100.00); + // 四舍五入到 2 位小数 + final pctRounded = (pctClamped * 100).round() / 100; + final str = '${pctRounded}%'; if (mounted) { setState(() { if (snapshot['IS_NODE'] == true) { final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex; final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex; - // 保护性检查,避免索引越界 if (fi >= 0 && fi < _videoList.length) { final nodes = _videoList[fi]['nodes'] as List?; if (nodes != null && ni >= 0 && ni < nodes.length) { @@ -544,7 +588,7 @@ class _StudyDetailPageState extends State }); } - // 如果是结束上报且后端标注可考试,则弹窗处理 + // 如果是结束上报且后端标注可考试,则弹窗处理(原逻辑) if (end && pd['CANEXAM'] == '1') { _videoController?.pause(); @@ -572,6 +616,7 @@ class _StudyDetailPageState extends State } } + /// 开始考试 Future _startExam(Map resData) async { Map pd = resData['pd'] ?? {}; @@ -604,7 +649,7 @@ class _StudyDetailPageState extends State paper['STAGEEXAMPAPERINPUT_ID'] ?? '', ...data, }, - examType: TakeExamType.video_study, + examType: TakeExamType.video_study, jumpType: 2, ), context, ); diff --git a/lib/pages/home/study/study_my_task_page.dart b/lib/pages/home/study/study_my_task_page.dart index 8612a73..0db6432 100644 --- a/lib/pages/home/study/study_my_task_page.dart +++ b/lib/pages/home/study/study_my_task_page.dart @@ -212,7 +212,7 @@ class _StudyMyTaskPageState extends State resData['STAGEEXAMPAPERINPUT_ID'] ?? '', ...data }, - examType: TakeExamType.video_study), + examType: TakeExamType.video_study, jumpType: 1,), context); } else { ToastUtil.showError(context, '请求错误'); diff --git a/lib/pages/home/study/take_exam_page.dart b/lib/pages/home/study/take_exam_page.dart index 4dcc55c..2914d59 100644 --- a/lib/pages/home/study/take_exam_page.dart +++ b/lib/pages/home/study/take_exam_page.dart @@ -50,11 +50,14 @@ class TakeExamPage extends StatefulWidget { const TakeExamPage({ required this.examInfo, required this.examType, + required this.jumpType, super.key, }); final Map examInfo; final TakeExamType examType; + final int jumpType; + @override State createState() => _TakeExamPageState(); @@ -113,6 +116,9 @@ class _TakeExamPageState extends State { content: '您无考试次数!', ); if (ok) { + if (widget.jumpType == 2) { + Navigator.pop(context); + } Navigator.pop(context); }; } diff --git a/lib/pages/home/tap/item_list_widget.dart b/lib/pages/home/tap/item_list_widget.dart index 302fe0f..108b006 100644 --- a/lib/pages/home/tap/item_list_widget.dart +++ b/lib/pages/home/tap/item_list_widget.dart @@ -37,16 +37,21 @@ class ItemListWidget { /// 强制必选 不受是否可以编译和是否必选影响 }) { // 如果启用数字输入,使用数字键盘 - final actualKeyboardType = isNumericInput - ? const TextInputType.numberWithOptions(decimal: true) - : keyboardType; + final actualKeyboardType = + isNumericInput + ? const TextInputType.numberWithOptions(decimal: true) + : keyboardType; return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( - mainAxisAlignment: isEditable - ? MainAxisAlignment.start - : MainAxisAlignment.spaceBetween, + mainAxisAlignment: + isEditable + ? MainAxisAlignment.start + : MainAxisAlignment.spaceBetween, children: [ Row( children: [ @@ -64,54 +69,63 @@ class ItemListWidget { const SizedBox(width: 8), isEditable ? Expanded( - child: TextField( - autofocus: false, - controller: controller, - onChanged: onChanged, - onSubmitted: onFieldSubmitted, - keyboardType: actualKeyboardType, - style: TextStyle(fontSize: fontSize), - maxLines: 1, - // 添加输入格式化器(如果是数字输入) - inputFormatters: isNumericInput - ? [ - // 过滤非数字和小数点字符 - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]')), - // 自定义格式化器,限制小数位数 - TextInputFormatter.withFunction((oldValue, newValue) { - if (newValue.text.isEmpty) return newValue; + child: TextField( + autofocus: false, + controller: controller, + onChanged: onChanged, + onSubmitted: onFieldSubmitted, + keyboardType: actualKeyboardType, + style: TextStyle(fontSize: fontSize), + maxLines: 1, + // 添加输入格式化器(如果是数字输入) + inputFormatters: + isNumericInput + ? [ + // 过滤非数字和小数点字符 + FilteringTextInputFormatter.allow( + RegExp(r'[\d\.]'), + ), + // 自定义格式化器,限制小数位数 + TextInputFormatter.withFunction(( + oldValue, + newValue, + ) { + if (newValue.text.isEmpty) return newValue; - // 检查多个小数点的情况 - if (newValue.text.split('.').length > 2) { - return oldValue; - } + // 检查多个小数点的情况 + if (newValue.text.split('.').length > 2) { + return oldValue; + } - // 使用正则表达式匹配有效输入 - if (RegExp(r'^\d*\.?\d{0,' + maxDecimalPlaces.toString() + r'}$') - .hasMatch(newValue.text)) { - return newValue; - } + // 使用正则表达式匹配有效输入 + if (RegExp( + r'^\d*\.?\d{0,' + + maxDecimalPlaces.toString() + + r'}$', + ).hasMatch(newValue.text)) { + return newValue; + } - return oldValue; - }), - ] - : null, - decoration: InputDecoration( - isDense: true, - hintText: hintText, - contentPadding: EdgeInsets.symmetric(vertical: 8), - ), - ), - ) + return oldValue; + }), + ] + : null, + decoration: InputDecoration( + isDense: true, + hintText: hintText, + contentPadding: EdgeInsets.symmetric(vertical: 8), + ), + ), + ) : Expanded( - child: Text( - text ?? '', - maxLines: maxLines, - style: TextStyle(fontSize: fontSize, color: detailtextColor), - textAlign: TextAlign.right, - overflow: TextOverflow.ellipsis, // 超出省略 - ), - ), + child: Text( + text ?? '', + maxLines: maxLines, + style: TextStyle(fontSize: fontSize, color: detailtextColor), + textAlign: TextAlign.right, + overflow: TextOverflow.ellipsis, // 超出省略 + ), + ), ], ), ); @@ -130,7 +144,6 @@ class ItemListWidget { bool isRequired = true, String hintText = '请输入', ValueChanged? onChanged, - }) { return Container( // 统一左右 padding,保证标题和内容在同一左侧基线 @@ -206,12 +219,15 @@ class ItemListWidget { VoidCallback? onTapTip, // 提醒回调 bool isRequired = true, String cleanText = '清除', - double horizontalnum= horizontal_inset, + double horizontalnum = horizontal_inset, }) { return InkWell( onTap: isEditable ? onTap : null, child: Container( - padding: EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontalnum), + padding: EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontalnum, + ), child: Row( children: [ // 1. 标题 @@ -232,13 +248,19 @@ class ItemListWidget { if (isTip) Column( children: [ - IconButton(onPressed: onTapTip, icon: Icon(Icons.error_outline,color: Colors.blue,size: 20,)), - const SizedBox() + IconButton( + onPressed: onTapTip, + icon: Icon( + Icons.error_outline, + color: Colors.blue, + size: 20, + ), + ), + const SizedBox(), ], - ) + ), ], - ) - + ), ], ), if (isClean) @@ -251,7 +273,7 @@ class ItemListWidget { textStyle: TextStyle(fontSize: 11, color: Colors.white), borderRadius: 10, backgroundColor: - cleanText.contains('清除') ? Colors.red : Colors.green, + cleanText.contains('清除') ? Colors.red : Colors.green, onPressed: onTapClean, ), SizedBox(height: 20), @@ -270,7 +292,12 @@ class ItemListWidget { textAlign: TextAlign.right, style: TextStyle( fontSize: fontSize, - color: isEditable ? (text == '请选择' ? Colors.black87 :Colors.black) : detailtextColor, + color: + isEditable + ? (text == '请选择' + ? Colors.black87 + : Colors.black) + : detailtextColor, ), ), ), @@ -306,7 +333,10 @@ class ItemListWidget { return InkWell( onTap: isEditable ? onTap : null, child: Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -390,7 +420,10 @@ class ItemListWidget { bool isRequired = true, }) { return Container( - padding: EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -482,7 +515,10 @@ class ItemListWidget { bool isRequired = true, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -519,7 +555,11 @@ class ItemListWidget { vertical: 2, horizontal: 10, ), - textStyle: TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold), + textStyle: TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.bold, + ), backgroundColor: Colors.green, onPressed: onTap, ), @@ -532,7 +572,7 @@ class ItemListWidget { height: row2Height, padding: const EdgeInsets.symmetric(vertical: 8), child: - (isEditable && isInput) + (isEditable && isInput) ? TextField( autofocus: false, controller: controller, @@ -569,10 +609,13 @@ class ItemListWidget { required String text, // 显示内容或提示 required VoidCallback? onTap, // 第一行点击回调 double fontSize = 14, // 字体大小 - String buttonText = '分析详情' + String buttonText = '气体分析详情', }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -604,11 +647,12 @@ class ItemListWidget { CustomButton( text: buttonText, height: 30, - padding: const EdgeInsets.symmetric( - vertical: 2, - horizontal: 10, + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 10), + textStyle: TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.bold, ), - textStyle: TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold), backgroundColor: Colors.green, onPressed: onTap, ), @@ -628,7 +672,10 @@ class ItemListWidget { bool isRequired = false, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -655,27 +702,28 @@ class ItemListWidget { ), ); } + /// 单行布局: /// 标题 + 按钮(挨着) static Widget OneRowStartButtonTitle({ required String label, // 标题 - String buttonText = '分析详情', // 按钮文字 + String buttonText = '气体分析详情', // 按钮文字 String text = '', // 标题 required VoidCallback onTap, // 点击回调 double fontSize = 14, // 字体大小 Color btnColor = Colors.green, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( label, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold), ), CustomButton( text: buttonText, @@ -701,7 +749,10 @@ class ItemListWidget { void Function(String)? onTapCallBack, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -720,21 +771,21 @@ class ItemListWidget { children: [ GestureDetector( onTap: () { - if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}$imgPath'); + if (onTapCallBack != null) + onTapCallBack('${ApiService.baseImgPath}$imgPath'); }, child: - imgPath.isNotEmpty - ? Image.network( - '${ApiService.baseImgPath}${imgPath}', - width: 80, - height: 80, - ) - : SizedBox(), + imgPath.isNotEmpty + ? Image.network( + '${ApiService.baseImgPath}${imgPath}', + width: 80, + height: 80, + ) + : SizedBox(), ), - if (text.isNotEmpty) - Text(text) + if (text.isNotEmpty) Text(text), ], - ) + ), ], ), ); @@ -757,16 +808,16 @@ class ItemListWidget { children: [ // 标题部分 if (title.isNotEmpty) - Padding( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), - child: Text( - title, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, + Padding( + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), + child: Text( + title, + style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold), ), ), - ), // 图片横向滚动区域 SizedBox( @@ -779,16 +830,20 @@ class ItemListWidget { return Container( margin: const EdgeInsets.only(right: 8), // 图片间距 child: ClipRRect( - borderRadius: BorderRadius.circular(8), child: GestureDetector( onTap: () { - if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}${imageUrls![index] ?? ''}'); + if (onTapCallBack != null) + onTapCallBack( + '${ApiService.baseImgPath}${imageUrls![index] ?? ''}', + ); }, child: Image.network( '${ApiService.baseImgPath}${imageUrls![index] ?? ''}', - width: 80, // 图片宽度 - height: 80, // 图片高度 + width: 80, + // 图片宽度 + height: 80, + // 图片高度 fit: BoxFit.fill, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; @@ -796,7 +851,9 @@ class ItemListWidget { width: 80, height: 80, color: Colors.grey[200], - child: const Center(child: CircularProgressIndicator()), + child: const Center( + child: CircularProgressIndicator(), + ), ); }, errorBuilder: (context, error, stackTrace) { @@ -808,7 +865,7 @@ class ItemListWidget { ); }, ), - ) + ), ), ); }, @@ -817,6 +874,7 @@ class ItemListWidget { ], ); } + /// 多行垂直布局: /// 标题+按钮 /// 编辑框列表,多个编辑框可删除 @@ -832,7 +890,10 @@ class ItemListWidget { bool isRequired = true, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -881,44 +942,48 @@ class ItemListWidget { height: row2Height, padding: const EdgeInsets.symmetric(vertical: 8), child: - isEditable - ? TextField( - autofocus: false, - controller: controller, - keyboardType: TextInputType.multiline, - maxLines: null, - expands: true, - style: TextStyle(fontSize: fontSize), - decoration: InputDecoration( - hintText: hintText, - //contentPadding: EdgeInsets.zero, - border: InputBorder.none, - ), - ) - : SingleChildScrollView( - padding: EdgeInsets.zero, - child: Text( - text, - style: TextStyle( - fontSize: fontSize, - color: detailtextColor, - ), - ), - ), + isEditable + ? TextField( + autofocus: false, + controller: controller, + keyboardType: TextInputType.multiline, + maxLines: null, + expands: true, + style: TextStyle(fontSize: fontSize), + decoration: InputDecoration( + hintText: hintText, + //contentPadding: EdgeInsets.zero, + border: InputBorder.none, + ), + ) + : SingleChildScrollView( + padding: EdgeInsets.zero, + child: Text( + text, + style: TextStyle( + fontSize: fontSize, + color: detailtextColor, + ), + ), + ), ), ], ), ); } + /// 多行垂直布局: /// 标题、图片、说明、签字信息 static Widget mulColumnRowTitleAndImages({ required String title, // 第一行标题 required List? imageUrls, required String text, // 描述 - required List? signUrls, /// 签字 - required List? signTimes, /// 签字时间 + required List? signUrls, + /// 签字 + required List? signTimes, + + /// 签字时间 double row2Height = 80, // 第二行高度 double fontSize = 14, // 字体大小 void Function(String)? onTapCallBack, @@ -930,13 +995,13 @@ class ItemListWidget { children: [ // 标题部分 Padding( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Text( title, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold), ), ), @@ -951,41 +1016,48 @@ class ItemListWidget { return Container( margin: const EdgeInsets.only(right: 8), // 图片间距 child: ClipRRect( - borderRadius: BorderRadius.circular(8), - child: GestureDetector( - onTap: () { - if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}${imageUrls![index] ?? ''}'); + borderRadius: BorderRadius.circular(8), + child: GestureDetector( + onTap: () { + if (onTapCallBack != null) + onTapCallBack( + '${ApiService.baseImgPath}${imageUrls![index] ?? ''}', + ); + }, + child: Image.network( + '${ApiService.baseImgPath}${imageUrls![index] ?? ''}', + width: 80, + // 图片宽度 + height: 80, + // 图片高度 + fit: BoxFit.fill, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return Container( + width: 80, + height: 80, + color: Colors.grey[200], + child: const Center( + child: CircularProgressIndicator(), + ), + ); }, - child: Image.network( - '${ApiService.baseImgPath}${imageUrls![index] ?? ''}', - width: 80, // 图片宽度 - height: 80, // 图片高度 - fit: BoxFit.fill, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - return Container( - width: 80, - height: 80, - color: Colors.grey[200], - child: const Center(child: CircularProgressIndicator()), - ); - }, - errorBuilder: (context, error, stackTrace) { - return Container( - width: 80, - height: 80, - color: Colors.transparent, - child: SizedBox(), - ); - }, - ), - ) + errorBuilder: (context, error, stackTrace) { + return Container( + width: 80, + height: 80, + color: Colors.transparent, + child: SizedBox(), + ); + }, + ), + ), ), ); }, ), ), - Row() + Row(), ], ); } @@ -1000,17 +1072,17 @@ class ItemListWidget { bool isRequired = true, }) { return Container( - padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + padding: const EdgeInsets.symmetric( + vertical: vertical_inset, + horizontal: horizontal_inset, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 第一行:标题 Text( label, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -1019,17 +1091,18 @@ class ItemListWidget { text, maxLines: 5, overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: fontSize, - color: detailtextColor, - ), + style: TextStyle(fontSize: fontSize, color: detailtextColor), ), ], ), ); } - static Widget itemContainer(Widget child, {double horizontal = horizontal_inset, double vertical = vertical_inset}) { + static Widget itemContainer( + Widget child, { + double horizontal = horizontal_inset, + double vertical = vertical_inset, + }) { return Container( decoration: BoxDecoration( color: Colors.white, @@ -1040,10 +1113,111 @@ class ItemListWidget { ); } + // static Widget aaa({}){ + // return + // } + static Widget buildFlowStepItem({ + required List> flowList, + }) { + final int lastDoneIndex = flowList.lastIndexWhere((e) => e['STATUS'] == 1); + return ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 16), + itemCount: flowList.length + 1, // +1 用来放标题 + itemBuilder: (context, i) { + if (i == 0) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text( + '查看流程图', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + ); + } + final idx = i - 1; + final item = flowList[idx]; + final bool isFirst = idx == 0; + final bool isLast = idx == flowList.length - 1; + // 根据 lastDoneIndex 自动计算“进行中” + final int status; + if (idx <= lastDoneIndex) { + status = 1; // 已完成 + } else if (idx == lastDoneIndex + 1) { + status = 0; // 进行中 + } else { + status = -1; // 未到达 + } + // 依据状态设色 + final Color dotColor = + status == 1 + ? Colors.green + : (status == 0 ? Colors.blue : Colors.grey); + final Color textColor = + status == 1 + ? Colors.green + : (status == 0 ? Colors.blue : Colors.black); + return ListTile( + visualDensity: VisualDensity(vertical: -4), - + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + leading: Container( + width: 24, + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // 上方线段或占位 + isFirst + ? SizedBox(height: 6 + 5) + : Expanded( + child: Container(width: 1, color: Colors.grey[300]), + ), + // 圆点 + CircleAvatar(radius: 6, backgroundColor: dotColor), + // 下方线段或占位 + isLast + ? SizedBox(height: 6 + 5) + : Expanded( + child: Container(width: 1, color: Colors.grey[300]), + ), + ], + ), + ), + title: Text( + item['STEP_NAME'] ?? '', + style: TextStyle(color: textColor, fontSize: 15), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (item['SIGN_USER'] != null) ...[ + Text( + item['SIGN_USER'], + style: TextStyle(color: textColor, fontSize: 13), + ), + ] else if (item['FINISHED_SIGN_USER'] != null) ...[ + Text( + item['FINISHED_SIGN_USER'], + style: TextStyle(color: textColor, fontSize: 13), + ), + ] else if (item['ACT_USER_NAME'] != null) ...[ + Text( + item['ACT_USER_NAME'], + style: TextStyle(color: textColor, fontSize: 13), + ), + ], + if (item['ACT_TIME'] != null) + Text( + item['ACT_TIME'], + style: TextStyle(color: textColor, fontSize: 13), + ), + ], + ), + ); + }, + ); + } } diff --git a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart index 625a3ca..b9bc170 100644 --- a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart @@ -61,204 +61,247 @@ class MeasuresListWidget extends StatelessWidget { border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(4), ), - child: Table( - defaultVerticalAlignment: TableCellVerticalAlignment.middle, + child: LayoutBuilder( + builder: (context, constraints) { + // 可用宽度(减去外层 margin) + final containerWidth = constraints.maxWidth; - // 或 .top / .bottom - columnWidths: { - 0: FlexColumnWidth(10), - 1: FixedColumnWidth(210), - 2: FlexColumnWidth(20), - if (!isAllowEdit) 3: FixedColumnWidth(60), - }, - border: TableBorder( - horizontalInside: BorderSide(color: Colors.grey.shade300), - verticalInside: BorderSide(color: Colors.grey.shade300), - ), - children: [ - // 表头 - TableRow( - decoration: BoxDecoration(color: Colors.grey.shade100), + // 期望的固定列宽(可以根据需要微调) + double col0Fixed = 40; // 第一列:序号(较窄) + double col2Fixed = 60; // 第三列:操作(保留较宽以放按钮) + double col3Fixed = 80; // 第四列:确认人(头像列) + + // 如果不显示第4列(isAllowEdit == true),则第4列宽为0,不计入固定总和 + final showCol3 = !isAllowEdit; + + // 计算固定列总和并在超窄屏下进行缩放保护 + double fixedTotal = + col0Fixed + col2Fixed + (showCol3 ? col3Fixed : 0); + // 保证至少留 10% 的空间给可伸缩列,避免其被压扁为 0 + final minFlexPortion = containerWidth * 0.10; + if (fixedTotal + minFlexPortion > containerWidth && + fixedTotal > 0) { + final availableForFixed = (containerWidth - minFlexPortion) + .clamp(0.0, containerWidth); + final scale = availableForFixed / fixedTotal; + col0Fixed = (col0Fixed * scale).clamp( + 28.0, + col0Fixed, + ); // 最小28px避免看不清 + col2Fixed = (col2Fixed * scale).clamp( + 60.0, + col2Fixed, + ); // 最小60px给按钮留空间 + if (showCol3) + col3Fixed = (col3Fixed * scale).clamp( + 36.0, + col3Fixed, + ); // 头像最小36px + fixedTotal = + col0Fixed + col2Fixed + (showCol3 ? col3Fixed : 0); + } + + // 列宽分配:第一列、第三列、第四列为固定;第二列为弹性 + final columnWidths = { + 0: FixedColumnWidth(col0Fixed), + 1: const FlexColumnWidth(1), + 2: FixedColumnWidth(col2Fixed), + }; + if (showCol3) { + columnWidths[3] = FixedColumnWidth(col3Fixed); + } + + return Table( + defaultVerticalAlignment: TableCellVerticalAlignment.middle, + columnWidths: columnWidths, + border: TableBorder( + horizontalInside: BorderSide(color: Colors.grey.shade300), + verticalInside: BorderSide(color: Colors.grey.shade300), + ), children: [ - const Padding( - padding: EdgeInsets.all(2), - child: Center( - child: Text( - '序号', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - const Padding( - padding: EdgeInsets.all(8), - child: Center( - child: Text( - '安全措施', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - Padding( - padding: const EdgeInsets.all(2), - child: Center( - child: Text( - isAllowEdit ? '操作' : '是否\n涉及', - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ), - ), - if (!isAllowEdit) - const Padding( - padding: EdgeInsets.all(5), - child: Center( - child: Text( - '确认人', - style: TextStyle(fontWeight: FontWeight.bold), + // 表头 + TableRow( + decoration: BoxDecoration(color: Colors.grey.shade100), + children: [ + const Padding( + padding: EdgeInsets.all(2), + child: Center( + child: Text( + '序号', + style: TextStyle(fontWeight: FontWeight.bold), + ), ), ), - ), - ], - ), - // 数据行 - for (var item in measuresList) - TableRow( - children: [ - Padding( - padding: const EdgeInsets.all(8), - child: Center( - child: Text('${measuresList.indexOf(item) + 1}'), + const Padding( + padding: EdgeInsets.all(8), + child: Center( + child: Text( + '安全措施', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), ), - ), - // 第二列:措施 + 签名 + 问题答案 - Padding( - padding: const EdgeInsets.all(8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 主要安全措施 - Text(item['PROTECTIVE_MEASURES'] as String? ?? ''), - // // 签名图片 - // if (item.containsKey('SIGN_PATH') && - // (item['SIGN_PATH'] as String).isNotEmpty) - // ..._buildImageRows( - // context, - // (item['SIGN_PATH'] as String).split(','), - // item['SIGN_TIME'] as String? ?? '', - // ), - - // 问题1~4 + 答案(可编辑或只读) - for (var i = 1; i <= 4; i++) - if ((item['QUESTION$i'] as String?)?.isNotEmpty ?? - false) - _buildQnA(item, i), - // 操作图片 - if (item.containsKey('IMG_PATH') && - (item['IMG_PATH'] as String).isNotEmpty && - isShowSign) - Row( - children: [ - ..._buildImageRows( - context, - (item['IMG_PATH'] as String).split(','), - '', - 8, - ), - ], + Padding( + padding: const EdgeInsets.all(2), + child: Center( + child: Text( + isAllowEdit ? '操作' : '是否\n涉及', + style: const TextStyle( + fontWeight: FontWeight.bold, ), - ], + ), + ), ), - ), - - // 第二列:状态文字/按钮 + 操作图片 - Padding( - padding: const EdgeInsets.all(8), - child: Column( - children: [ - // 签字或状态 - isAllowEdit - ? TextButton( - onPressed: () { - onSign?.call(item); - }, - child: Text( - (item['SIGN_ITEM'] ?? '') - .toString() - .isNotEmpty - ? '已签字' - : '签字', - style: TextStyle( - color: - (item['SIGN_ITEM'] ?? '') - .toString() - .isNotEmpty - ? Colors.grey.shade600 - : Colors.blue, - ), - ), - ) - : Text( - (item['STATUS'] as String?) == '-1' - ? '不涉及' - : '涉及', - style: TextStyle( - color: - (item['STATUS'] as String?) == '-1' - ? Colors.black - : Colors.black, - ), + if (!isAllowEdit) + const Padding( + padding: EdgeInsets.all(5), + child: Center( + child: Text( + '确认人', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ], + ), + // 数据行 + for (var item in measuresList) + TableRow( + children: [ + Padding( + padding: const EdgeInsets.all(8), + child: Center( + child: Text('${measuresList.indexOf(item) + 1}'), + ), + ), + // 第二列:措施 + 签名 + 问题答案 + Padding( + padding: const EdgeInsets.all(8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 主要安全措施 + Text( + item['PROTECTIVE_MEASURES'] as String? ?? '', ), - ], - ), - ), - if (!isAllowEdit) - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - if (item.containsKey('SIGN_PATH') && - (item['SIGN_PATH'] as String).isNotEmpty) - // 把 SIGN_PATH 切分为单张图片 path 列表,并去掉可能的空格 - ...((item['SIGN_PATH'] as String) - .split(',') - .map((s) => s.trim()) - .where((s) => s.isNotEmpty)).map((path) { - final imageUrl = '$baseImgPath$path'; - return Padding( - padding: const EdgeInsets.only(top: 5), - child: Center( - child: GestureDetector( - onTap: () { - presentOpaque( - SingleImageViewer(imageUrl: imageUrl), - context, - ); + // 问题1~4 + 答案(可编辑或只读) + for (var i = 1; i <= 4; i++) + if ((item['QUESTION$i'] as String?) + ?.isNotEmpty ?? + false) + _buildQnA(item, i), + // 操作图片 + if (item.containsKey('IMG_PATH') && + (item['IMG_PATH'] as String).isNotEmpty && + isShowSign) + Row( + children: [ + ..._buildImageRows( + context, + (item['IMG_PATH'] as String).split(','), + '', + 8, + ), + ], + ), + ], + ), + ), + + // 第三列:状态文字/按钮 + 操作图片 + Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + // 签字或状态 + isAllowEdit + ? TextButton( + onPressed: () { + onSign?.call(item); }, - child: Image.network( - imageUrl, - width: 40, - height: 40, - fit: BoxFit.fill, - // 防止图片加载失败导致布局异常 - errorBuilder: - (_, __, ___) => Container( - width: 40, - height: 40, - color: Colors.grey.shade200, - child: const Icon( - Icons.broken_image, - size: 18, - color: Colors.grey, - ), - ), + child: Text( + (item['SIGN_ITEM'] ?? '') + .toString() + .isNotEmpty + ? '已签字' + : '签字', + style: TextStyle( + color: + (item['SIGN_ITEM'] ?? '') + .toString() + .isNotEmpty + ? Colors.grey.shade600 + : Colors.blue, + ), + ), + ) + : Text( + (item['STATUS'] as String?) == '-1' + ? '不涉及' + : '涉及', + style: TextStyle( + color: + (item['STATUS'] as String?) == '-1' + ? Colors.black + : Colors.black, ), ), - ), - ); - }).toList(), - ], - ), - ], - ), - ], + ], + ), + ), + + // 第四列:确认人(只在非编辑模式显示) + if (!isAllowEdit) + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (item.containsKey('SIGN_PATH') && + (item['SIGN_PATH'] as String).isNotEmpty) + ...((item['SIGN_PATH'] as String) + .split(',') + .map((s) => s.trim()) + .where((s) => s.isNotEmpty)).map((path) { + final imageUrl = '$baseImgPath$path'; + return Padding( + padding: const EdgeInsets.only(top: 5), + child: Center( + child: GestureDetector( + onTap: () { + presentOpaque( + SingleImageViewer( + imageUrl: imageUrl, + ), + context, + ); + }, + child: Image.network( + imageUrl, + width: 40, + height: 40, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => Container( + width: 40, + height: 40, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 18, + color: Colors.grey, + ), + ), + ), + ), + ), + ); + }).toList(), + ], + ), + ], + ), + ], + ); + }, ), ), ], @@ -1144,67 +1187,75 @@ class _SelectionPopupState extends State { ), // 列表多选 Expanded( - child: - ListTileTheme( - dense: true, - contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 0), - child: ListView.builder( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), - itemCount: list.length, - itemBuilder: (c, i) { - final item = list[i]; - final value = selectValue; - final key = - widget.type == 'assignments' - ? item['CHECK_NO'] as String? ?? '' - : item['NAME'] as String? ?? ''; - final checked = value.contains(key); - return CheckboxListTile( - controlAffinity: ListTileControlAffinity.leading, - contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 0), - activeColor: Colors.blue, - dense: true, // 更紧凑 - visualDensity: const VisualDensity(vertical: -4), // 调整垂直密度:-1..-4 - title: Column( - mainAxisSize: MainAxisSize.min, // 避免 Column 占用多余高度 - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - key, - style: const TextStyle(fontSize: 13, height: 1.0), - ), - if (widget.type == 'assignments') ...[ - const SizedBox(height: 4), // 子文本间距可更小 - Text( - '作业内容: ${item['WORK_CONTENT'] ?? ''}', - style: const TextStyle(fontSize: 13, height: 1.0), - ), - Text( - '作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}', - style: const TextStyle(fontSize: 13, height: 1.0), - ), - Text( - '作业申请时间: ${item['CREATTIME'] ?? ''}', - style: const TextStyle(fontSize: 13, height: 1.0), - ), - ], - ], + child: ListTileTheme( + dense: true, + contentPadding: const EdgeInsets.symmetric( + vertical: 0, + horizontal: 0, + ), + child: ListView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 12, ), - value: checked, - onChanged: (v) { - setState(() { - if (v == true) - selectValue.add(key); - else - selectValue.remove(key); - }); + itemCount: list.length, + itemBuilder: (c, i) { + final item = list[i]; + final value = selectValue; + final key = + widget.type == 'assignments' + ? item['CHECK_NO'] as String? ?? '' + : item['NAME'] as String? ?? ''; + final checked = value.contains(key); + return CheckboxListTile( + controlAffinity: ListTileControlAffinity.leading, + contentPadding: const EdgeInsets.symmetric( + vertical: 0, + horizontal: 0, + ), + activeColor: Colors.blue, + dense: true, + // 更紧凑 + visualDensity: const VisualDensity(vertical: -4), + // 调整垂直密度:-1..-4 + title: Column( + mainAxisSize: MainAxisSize.min, // 避免 Column 占用多余高度 + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + key, + style: const TextStyle(fontSize: 13, height: 1.0), + ), + if (widget.type == 'assignments') ...[ + const SizedBox(height: 4), // 子文本间距可更小 + Text( + '作业内容: ${item['WORK_CONTENT'] ?? ''}', + style: const TextStyle(fontSize: 13, height: 1.0), + ), + Text( + '作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}', + style: const TextStyle(fontSize: 13, height: 1.0), + ), + Text( + '作业申请时间: ${item['CREATTIME'] ?? ''}', + style: const TextStyle(fontSize: 13, height: 1.0), + ), + ], + ], + ), + value: checked, + onChanged: (v) { + setState(() { + if (v == true) + selectValue.add(key); + else + selectValue.remove(key); + }); + }, + ); }, - ) - ; - }, - ), - ) - + ), + ), ), // 确定/关闭 Padding( @@ -1315,26 +1366,28 @@ class SignItemWidget extends StatelessWidget { // 解析 SIGN_PATH 并聚合 List signPaths = []; final rawSP = - FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; + FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; if (rawSP is String && rawSP.isNotEmpty) { - signPaths = rawSP - .split(',') - .map((s) => s.trim()) - .where((s) => s.isNotEmpty) - .toList(); + signPaths = + rawSP + .split(',') + .map((s) => s.trim()) + .where((s) => s.isNotEmpty) + .toList(); } else if (rawSP is List) { - signPaths = rawSP - .cast() - .map((s) => s.trim()) - .where((s) => s.isNotEmpty) - .toList(); + signPaths = + rawSP + .cast() + .map((s) => s.trim()) + .where((s) => s.isNotEmpty) + .toList(); } aggregatedSignPaths.addAll(signPaths); // 解析 SIGN_TIME 并聚合(保留原有行为:split 不会 trim 时间内部空格) List signTimes = []; final rawST = - FormUtils.hasValue(item, 'SIGN_TIME') ? item['SIGN_TIME'] : null; + FormUtils.hasValue(item, 'SIGN_TIME') ? item['SIGN_TIME'] : null; if (rawST is String && rawST.isNotEmpty) { signTimes = rawST.split(','); } else if (rawST is List) { @@ -1350,16 +1403,15 @@ class SignItemWidget extends StatelessWidget { final item = Map.from(raw); final rawIP = - FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null; + FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null; if (rawIP is String && rawIP.isNotEmpty) { aggregatedImgPaths.addAll( - rawIP.split(',') - .map((s) => s.trim()) - .where((s) => s.isNotEmpty), + rawIP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty), ); } else if (rawIP is List) { aggregatedImgPaths.addAll( - rawIP.cast() + rawIP + .cast() .map((s) => s.trim()) .where((s) => s.isNotEmpty), ); @@ -1374,33 +1426,39 @@ class SignItemWidget extends StatelessWidget { Container( padding: EdgeInsets.symmetric(horizontal: 12), child: Row( - children: displayImgPaths.map((p) { - final fullUrl = '$baseImgPath$p'; - return GestureDetector( - onTap: () => presentOpaque( - SingleImageViewer(imageUrl: fullUrl), - context, - ), - child: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: ClipRRect( - borderRadius: BorderRadius.circular(2), - child: Image.network( - fullUrl, - width: smallThumbSize, - height: smallThumbSize, - fit: BoxFit.cover, - errorBuilder: (_, __, ___) => Container( - width: smallThumbSize, - height: smallThumbSize, - color: Colors.grey.shade200, - child: const Icon(Icons.broken_image, size: 24), + children: + displayImgPaths.map((p) { + final fullUrl = '$baseImgPath$p'; + return GestureDetector( + onTap: + () => presentOpaque( + SingleImageViewer(imageUrl: fullUrl), + context, + ), + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(2), + child: Image.network( + fullUrl, + width: smallThumbSize, + height: smallThumbSize, + fit: BoxFit.cover, + errorBuilder: + (_, __, ___) => Container( + width: smallThumbSize, + height: smallThumbSize, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 24, + ), + ), + ), ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ), ); @@ -1415,9 +1473,8 @@ class SignItemWidget extends StatelessWidget { } // 聚合后的最后一个签名时间(如果没有则为空串) - final lastTime = aggregatedSignTimes.isNotEmpty - ? aggregatedSignTimes.last.trim() - : ''; + final lastTime = + aggregatedSignTimes.isNotEmpty ? aggregatedSignTimes.last.trim() : ''; // 每张图片的尺寸与间距(保持你原来的数值) const double thumbSize = 60.0; @@ -1433,8 +1490,9 @@ class SignItemWidget extends StatelessWidget { child: LayoutBuilder( builder: (ctx, constraints) { // 图片区域最大宽度 = 可用宽度 - 时间宽度 - 间隔 - final double maxImageAreaWidth = - (constraints.maxWidth - timeBoxWidth - 8) + final double maxImageAreaWidth = (constraints.maxWidth - + timeBoxWidth - + 8) .clamp(0.0, constraints.maxWidth); return Align( @@ -1448,7 +1506,9 @@ class SignItemWidget extends StatelessWidget { // 图片区域(限制最大宽度,使用 Wrap 自动换行,不滚动) if (aggregatedSignPaths.isNotEmpty) ConstrainedBox( - constraints: BoxConstraints(maxWidth: maxImageAreaWidth), + constraints: BoxConstraints( + maxWidth: maxImageAreaWidth, + ), child: Padding( padding: const EdgeInsets.only(left: 6.0), child: Wrap( @@ -1456,41 +1516,43 @@ class SignItemWidget extends StatelessWidget { runSpacing: 6.0, alignment: WrapAlignment.start, crossAxisAlignment: WrapCrossAlignment.end, - children: aggregatedSignPaths.map((imgPath) { - final fullUrl = '$baseImgPath$imgPath'; - return GestureDetector( - onTap: () => presentOpaque( - SingleImageViewer(imageUrl: fullUrl), - context, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Image.network( - fullUrl, - width: thumbSize, - height: thumbSize, - fit: BoxFit.fill, - errorBuilder: (_, __, ___) => Container( - width: thumbSize, - height: thumbSize, - color: Colors.grey.shade200, - child: const Icon( - Icons.broken_image, - size: 24, + children: + aggregatedSignPaths.map((imgPath) { + final fullUrl = '$baseImgPath$imgPath'; + return GestureDetector( + onTap: + () => presentOpaque( + SingleImageViewer(imageUrl: fullUrl), + context, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: Image.network( + fullUrl, + width: thumbSize, + height: thumbSize, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => Container( + width: thumbSize, + height: thumbSize, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 24, + ), + ), ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ), ), // 图片与时间之间的小间隔(仅在有图片时展示) - if (aggregatedSignPaths.isNotEmpty) const SizedBox(width: 8), - - + if (aggregatedSignPaths.isNotEmpty) + const SizedBox(width: 8), ], ), ); @@ -1500,27 +1562,26 @@ 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, + 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; } } + /// 签名意见回显 class ConfirmWithSignWidget extends StatelessWidget { const ConfirmWithSignWidget({ @@ -1571,14 +1632,16 @@ class ConfirmWithSignWidget extends StatelessWidget { final safePd = pd ?? {}; // 如果没有该 section 则不渲染 - if (!FormUtils.hasValue(safeSigns, sectionKey)) { - return const SizedBox.shrink(); - } + // if (!FormUtils.hasValue(safeSigns, sectionKey)) { + // return const SizedBox.shrink(); + // } // 从 signs 中取第一个意见(保持与你原来逻辑一致) final sectionList = safeSigns[sectionKey]; String descrText = ''; - if (sectionList is List && sectionList.isNotEmpty && sectionList[0] is Map) { + if (sectionList is List && + sectionList.isNotEmpty && + sectionList[0] is Map) { final first = sectionList[0] as Map; final dynamic ds = first[descrField]; if (ds != null) { @@ -1607,7 +1670,17 @@ class ConfirmWithSignWidget extends StatelessWidget { ), child: Row( children: [ - Expanded(child: ListItemFactory.headerTitle('$headerTitle')), + Expanded( + child: Text( + '$headerTitle', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ), + maxLines: 5, + overflow: TextOverflow.ellipsis, + ), + ), const SizedBox(), // 仅当 pd 中存在 nameKey 且不为空时显示 // if (FormUtils.hasValue(safePd, nameKey)) @@ -1622,7 +1695,10 @@ class ConfirmWithSignWidget extends StatelessWidget { // 描述内容(当 descrText 有意义才显示) if (descrText.isNotEmpty) Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 5, + ), child: Text( descrText, maxLines: 100, @@ -1633,25 +1709,31 @@ class ConfirmWithSignWidget extends StatelessWidget { // 如果 imgsKey 有值并且 safePd 中有对应图片数据则显示(ItemListWidget.twoRowTitleAndImages 期望的 imageUrls) if (imgsKey.isNotEmpty && FormUtils.hasValue(safePd, imgsKey)) - Builder(builder: (ctx) { - final dynamic rawImgs = safePd[imgsKey]; - // 传给 ItemListWidget 的 imageUrls 需要类型兼容,这里仅在 rawImgs 非空时才调用 - if (rawImgs != null) { - return ItemListWidget.twoRowTitleAndImages( - onTapCallBack: (val) { - // 使用传入的 context 打开预览 - presentOpaque(SingleImageViewer(imageUrl: val), context); - }, - title: '', - imageUrls: rawImgs, - ); - } else { - return const SizedBox.shrink(); - } - }), + Builder( + builder: (ctx) { + final dynamic rawImgs = safePd[imgsKey]; + // 传给 ItemListWidget 的 imageUrls 需要类型兼容,这里仅在 rawImgs 非空时才调用 + if (rawImgs != null) { + return ItemListWidget.twoRowTitleAndImages( + onTapCallBack: (val) { + // 使用传入的 context 打开预览 + presentOpaque( + SingleImageViewer(imageUrl: val), + context, + ); + }, + title: '', + imageUrls: rawImgs, + ); + } else { + return const SizedBox.shrink(); + } + }, + ), // 如果 contentKey 有值并且 pd 中存在则显示(类型转换为字符串以防出错) - if (contentKey.isNotEmpty && FormUtils.hasValue(safePd, contentKey)) + if (contentKey.isNotEmpty && + FormUtils.hasValue(safePd, contentKey)) ItemListWidget.itemContainer( Text( (safePd[contentKey] ?? '').toString(), @@ -1701,7 +1783,8 @@ class SignRowImageTitle extends StatelessWidget { final List imagePaths = []; final safeSigns = signs ?? {}; - final rawList = FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null; + final rawList = + FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null; if (rawList == null) return imagePaths; @@ -1711,14 +1794,16 @@ class SignRowImageTitle extends StatelessWidget { if (raw is! Map) continue; final item = Map.from(raw); - final rawSP = FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; + final rawSP = + FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; if (rawSP is String && rawSP.isNotEmpty) { imagePaths.addAll( rawSP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty), ); } else if (rawSP is List) { imagePaths.addAll( - rawSP.cast() + rawSP + .cast() .where((e) => e != null) .map((e) => e.toString().trim()) .where((s) => s.isNotEmpty), @@ -1732,14 +1817,18 @@ class SignRowImageTitle extends StatelessWidget { ); } else if (rawList is Map) { // 若误传了单条 Map,也尝试从中抽取 SIGN_PATH - final rawSP = FormUtils.hasValue(rawList, 'SIGN_PATH') ? rawList['SIGN_PATH'] : null; + final rawSP = + FormUtils.hasValue(rawList, 'SIGN_PATH') + ? rawList['SIGN_PATH'] + : null; if (rawSP is String && rawSP.isNotEmpty) { imagePaths.addAll( rawSP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty), ); } else if (rawSP is List) { imagePaths.addAll( - rawSP.cast() + rawSP + .cast() .where((e) => e != null) .map((e) => e.toString().trim()) .where((s) => s.isNotEmpty), @@ -1764,8 +1853,7 @@ class SignRowImageTitle extends StatelessWidget { try { presentOpaque(SingleImageViewer(imageUrl: fullUrl), context); return; - } catch (_) { - } + } catch (_) {} } @override @@ -1773,10 +1861,7 @@ class SignRowImageTitle extends StatelessWidget { final imagePaths = _extractSignPaths(); return Container( - padding: const EdgeInsets.symmetric( - vertical: 5, - horizontal: 12, - ), + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -1784,10 +1869,7 @@ class SignRowImageTitle extends StatelessWidget { // 左侧标题 Text( label, - style: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold), ), // const SizedBox(width: 12), @@ -1804,27 +1886,32 @@ class SignRowImageTitle extends StatelessWidget { runSpacing: gap, alignment: WrapAlignment.end, crossAxisAlignment: WrapCrossAlignment.end, - children: imagePaths.map((p) { - final fullUrl = '${ApiService.baseImgPath}$p'; - return GestureDetector( - onTap: () => _openPreview(context, fullUrl), - child: ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Image.network( - fullUrl, - width: imageSize, - height: imageSize, - fit: BoxFit.cover, - errorBuilder: (_, __, ___) => Container( - width: imageSize, - height: imageSize, - color: Colors.grey.shade200, - child: const Icon(Icons.broken_image, size: 24), + children: + imagePaths.map((p) { + final fullUrl = '${ApiService.baseImgPath}$p'; + return GestureDetector( + onTap: () => _openPreview(context, fullUrl), + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: Image.network( + fullUrl, + width: imageSize, + height: imageSize, + fit: BoxFit.cover, + errorBuilder: + (_, __, ___) => Container( + width: imageSize, + height: imageSize, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 24, + ), + ), + ), ), - ), - ), - ); - }).toList(), + ); + }).toList(), ), ) else if (text.isNotEmpty) @@ -1843,5 +1930,3 @@ class SignRowImageTitle extends StatelessWidget { ); } } - - 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 2c38beb..87b28ec 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 @@ -167,13 +167,13 @@ class _HotWorkDetailFormWidgetState extends State { hintText: '请选择动火人及证书编号', onTap: widget.onChooseHotworkUser, ), - if (FormUtils.hasValue(pd, 'UNIT_NAME') && + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME') && !widget.isEditable) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['UNIT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && @@ -252,6 +252,7 @@ class _HotWorkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -303,6 +304,7 @@ class _HotWorkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart index d74d453..6fd01e7 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart @@ -187,10 +187,7 @@ class _HotworkSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -201,6 +198,10 @@ class _HotworkSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -242,7 +243,7 @@ class _HotworkSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -370,6 +371,7 @@ class _HotworkSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/dbbz_work_detail/hotwork_dbbz_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/dbbz_work_detail/hotwork_dbbz_detail.dart index fd0d042..f0aaa09 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/dbbz_work_detail/hotwork_dbbz_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/dbbz_work_detail/hotwork_dbbz_detail.dart @@ -263,7 +263,7 @@ class _HotworkDbbzDetailState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: MyAppbar(title: '班长验票'), + appBar: MyAppbar(title: '动火前,岗位当班班长验票情况'), body: SafeArea( child: SingleChildScrollView( padding: EdgeInsets.all(12), @@ -290,7 +290,7 @@ class _HotworkDbbzDetailState extends State { Column( children: [ ListItemFactory.createBuildMultilineInput( - '动火前在岗班长意见', + '动火前,岗位当班班长意见', '请输入意见', _contentController, isRequired: true, @@ -301,7 +301,7 @@ class _HotworkDbbzDetailState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ListItemFactory.headerTitle('动火前在岗班长'), + ListItemFactory.headerTitle('动火前,岗位当班班长'), CustomButton( text: '新增手写签字', height: 36, diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart index 8a6d3c0..a7b857f 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart @@ -379,8 +379,10 @@ class _HotworkApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -579,7 +581,7 @@ class _HotworkApplyDetailState extends State { pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; pd['TASK_ID'] = taskId; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['HOTWORK_ID'] = widget.HOTWORK_ID; @@ -598,7 +600,7 @@ class _HotworkApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } else { ToastUtil.showError(context, result['msg'] ?? '提交失败'); diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/hotwork_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/hotwork_list_page.dart index cfbf922..028aa4c 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/hotwork_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/hotwork_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/aqgl_work_detail/hotwork_aqgl_detail.dart'; @@ -137,9 +138,12 @@ class _HotWorkListPageState extends State { } /// 申请 - void _handleApply() async{ + void _handleApply() async { // 处理申请按钮点击逻辑 - await pushPage(HotworkApplyDetail(HOTWORK_ID: '', flow: widget.flow), context); + await pushPage( + HotworkApplyDetail(HOTWORK_ID: '', flow: widget.flow), + context, + ); _fetchData(); LoadingDialogHelper.hide(); } @@ -286,78 +290,10 @@ class _HotWorkListPageState extends State { break; } - await _fetchData(); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } - Widget _buildListItem(Map item) { return Card( color: Colors.white, @@ -368,107 +304,196 @@ class _HotWorkListPageState extends State { padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, + spacing: 8, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "编号: ${item['CHECK_NO'] ?? ''}", - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), - Text( - "作业级别: ${item['WORK_LEVEL'] ?? ''}", - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("申请人: ${item['APPLY_USER_NAME'] ?? ''}"), - Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"), - Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}"), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - Expanded(child: Text("动火点负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - ], - ), - const SizedBox(height: 8), - if (item['AUDIT_USER_NAME'] != null) - Text("安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}"), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [Text("动火前在岗班长: ${item['MONITOR_USER_NAME'] ?? ''}")], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}"), + child: Text( + "编号: ${item['CHECK_NO'] ?? ''}", + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + "作业级别: ${item['WORK_LEVEL'] ?? ''}", + textAlign: TextAlign.right, + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), ), ], ), - const SizedBox(height: 8), + + Row( + children: [ + Expanded( + child: Text( + "申请人: ${item['APPLY_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + "分析人: ${item['ANALYZE_USER_NAME'] ?? ''}", + textAlign: TextAlign.right, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + ], + ), + + Row( + children: [ + Expanded( + child: Text( + "监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + const SizedBox(width: 8), + Expanded( + child: item['APPROVE_USER_NAME'] != null + ? Text( + "审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}", + textAlign: TextAlign.right, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ) + : const SizedBox.shrink(), + ), + ], + ), + + Row( + children: [ + Expanded( + child: Text( + "安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + "接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}", + textAlign: TextAlign.right, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + ], + ), + + Row( + children: [ + Expanded( + child: Text( + "作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + "所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}", + textAlign: TextAlign.right, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + ], + ), + + if (item['AUDIT_USER_NAME'] != null) + Text( + "安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + if (FormUtils.hasValue(item, 'APPROVE_USER_NAME')) + Row( + children: [ + Expanded( + child: Text( + "动火审批负责人: ${item['APPROVE_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + textAlign: TextAlign.left, + ) + ), + ], + ), + + Row( + children: [ + Expanded( + child: Text( + "动火前在岗班长: ${item['MONITOR_USER_NAME'] ?? ''}", + textAlign: TextAlign.left, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + Expanded( + child: Text( + "验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}", + textAlign: TextAlign.right, + softWrap: true, + maxLines: null, + overflow: TextOverflow.visible, + ), + ), + ], + ), + Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( "审核状态: ${_getStatusText(item)}", overflow: TextOverflow.ellipsis, + softWrap: true, + maxLines: null, ), ), ], ), - const SizedBox(height: 8), + Row( children: [ CustomButton( text: '查看流程图', height: 35, - padding: EdgeInsets.symmetric(horizontal: 12), - margin: EdgeInsets.only(left: 0), + padding: const EdgeInsets.symmetric(horizontal: 12), + margin: const EdgeInsets.only(left: 0), backgroundColor: Colors.blue, onPressed: () => _openFlowDrawer(item['HOTWORK_ID']), ), - SizedBox(width: 1), + const SizedBox(width: 8), ], ), ], @@ -581,48 +606,7 @@ class _HotWorkListPageState extends State { child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), 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 0eba2f1..e0c398e 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 @@ -380,6 +380,7 @@ class _HotworkYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, 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 5f78b5e..b2d5bc6 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 @@ -121,12 +121,12 @@ class _CutroadDetailFormWidgetState extends State { isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && @@ -247,6 +247,7 @@ class _CutroadDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -299,6 +300,7 @@ class _CutroadDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart index 63bff37..0526219 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart @@ -39,8 +39,6 @@ class _CutroadSafeFuncSureState extends State { /// 其他安全措施 final TextEditingController _otherController = TextEditingController(); - - /// 安全防护措施列表 List imagePaths = []; List signTimes = []; // 签字时间列表 @@ -48,8 +46,8 @@ class _CutroadSafeFuncSureState extends State { void initState() { super.initState(); _getData(); - } + late Map pd = {}; late Map signs = {}; late List> measuresList = []; @@ -60,36 +58,53 @@ class _CutroadSafeFuncSureState extends State { try { // 并行发起三个请求,并在出错时返回安全的默认值(避免 Future.wait 因一个失败而中断) - final futurePd = ApiService.getHomeworkFindById('cutroad', widget.CUTROAD_ID) - .catchError((e) { + final futurePd = ApiService.getHomeworkFindById( + 'cutroad', + widget.CUTROAD_ID, + ).catchError((e) { // 可加入日志记录 e return {}; // 回退为空 map }); - final futureSigns = ApiService.listSignFinished('cutroad', widget.CUTROAD_ID) - .catchError((e) { + final futureSigns = ApiService.listSignFinished( + 'cutroad', + widget.CUTROAD_ID, + ).catchError((e) { return {'signs': {}}; }); - final futureMeasures = ApiService.listSignSureAllMeasures('cutroad', widget.CUTROAD_ID) - .catchError((e) { - return {'measuresForSignList': >[]}; + final futureMeasures = ApiService.listSignSureAllMeasures( + 'cutroad', + widget.CUTROAD_ID, + ).catchError((e) { + return { + 'measuresForSignList': >[], + }; }); - final results = await Future.wait([futurePd, futureSigns, futureMeasures]); + final results = await Future.wait([ + futurePd, + futureSigns, + futureMeasures, + ]); - final pdResult = results[0] as Map? ?? {}; - final signsResult = results[1] as Map? ?? {}; - final measuresResult = results[2] as Map? ?? {}; + final pdResult = + results[0] as Map? ?? {}; + final signsResult = + results[1] as Map? ?? {}; + final measuresResult = + results[2] as Map? ?? {}; // 从各自的结果里提取需要的字段,使用默认值以防字段缺失或类型不对 - final newPd = (pdResult['pd'] is Map) - ? Map.from(pdResult['pd']) - : {}; + final newPd = + (pdResult['pd'] is Map) + ? Map.from(pdResult['pd']) + : {}; - final newSigns = (signsResult['signs'] is Map) - ? Map.from(signsResult['signs']) - : {}; + final newSigns = + (signsResult['signs'] is Map) + ? Map.from(signsResult['signs']) + : {}; final newMeasuresList = >[]; final rawMeasures = measuresResult['measuresForSignList']; @@ -114,6 +129,7 @@ class _CutroadSafeFuncSureState extends State { LoadingDialogHelper.hide(); } } + /// 弹出单位选择 void chooseUnitHandle(MeasureItem item) { showModalBottomSheet( @@ -122,8 +138,7 @@ class _CutroadSafeFuncSureState extends State { barrierColor: Colors.black54, backgroundColor: Colors.transparent, builder: - (_) => - DepartmentPicker( + (_) => DepartmentPicker( onSelected: (id, name) async { setState(() { item.DEPARTMENT_ID = id; @@ -145,8 +160,6 @@ class _CutroadSafeFuncSureState extends State { }); } - - /// 签字 Future _sign() async { await NativeOrientation.setLandscape(); @@ -155,7 +168,7 @@ class _CutroadSafeFuncSureState extends State { MaterialPageRoute(builder: (context) => MineSignPage()), ); await NativeOrientation.setPortrait(); -if (path != null) { + if (path != null) { final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); setState(() { imagePaths.add(path); @@ -167,60 +180,61 @@ if (path != null) { Widget _signListWidget() { return Column( children: - imagePaths.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + imagePaths.map((path) { + return Column( children: [ - GestureDetector( - child: // 用一个 ConstrainedBox 限制最大尺寸,并改为 BoxFit.contain - ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 200, - maxHeight: 150, - ), - child: Image.file( - File(path), - // 改为完整显示 - fit: BoxFit.contain, - ), - ), - onTap: () { - presentOpaque( - SingleImageViewer(imageUrl: path), - context, - ); - }, - ), - Column( + const SizedBox(height: 10), + const Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Container( - padding: const EdgeInsets.only(right: 5), - child: CustomButton( - text: 'X', - height: 30, - padding: const EdgeInsets.symmetric(horizontal: 10), - backgroundColor: Colors.red, - onPressed: () { - setState(() { - imagePaths.remove(path); - }); - }, + GestureDetector( + child: // 用一个 ConstrainedBox 限制最大尺寸,并改为 BoxFit.contain + ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 200, + maxHeight: 150, + ), + child: Image.file( + File(path), + // 改为完整显示 + fit: BoxFit.contain, + ), ), + onTap: () { + presentOpaque( + SingleImageViewer(imageUrl: path), + context, + ); + }, + ), + Column( + children: [ + Container( + padding: const EdgeInsets.only(right: 5), + child: CustomButton( + text: 'X', + height: 30, + padding: const EdgeInsets.symmetric(horizontal: 10), + backgroundColor: Colors.red, + onPressed: () { + setState(() { + imagePaths.remove(path); + }); + }, + ), + ), + const SizedBox(height: 80), + ], ), - const SizedBox(height: 80), ], ), ], - ), - ], - ); - }).toList(), + ); + }).toList(), ); } + bool _validateAndProceed(BuildContext context) { for (var i = 0; i < measuresList.length; i++) { final m = measuresList[i]; @@ -234,10 +248,9 @@ if (path != null) { // 只有 STATUS == '1' 时才检查后续 ANSWER if (m['STATUS'] == '1') { for (var j = 1; j <= 4; j++) { - if (FormUtils.hasValue(m, 'QUESTION${j}') - ) { - if (!FormUtils.hasValue(m, 'ANSWER${j}') - || (m['ANSWER${j}'] as String?)!.length == 0) { + if (FormUtils.hasValue(m, 'QUESTION${j}')) { + if (!FormUtils.hasValue(m, 'ANSWER${j}') || + (m['ANSWER${j}'] as String?)!.length == 0) { ToastUtil.showNormal(context, '第${i + 1}项未填写第${j}项'); return false; } @@ -247,12 +260,10 @@ if (path != null) { } return true; } - /// 提交 1 提交 0暂存 + + /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -261,15 +272,19 @@ if (path != null) { if (status == '1') { if (!_validateAndProceed(context)) { - return; + return; + } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; } } else { reasonText = await CustomAlertDialog.showInput( - context, - title: '作废原因', - hintText: '请输入作废原因', - cancelText: '取消', - confirmText: '确定' + context, + title: '作废原因', + hintText: '请输入作废原因', + cancelText: '取消', + confirmText: '确定', ); if (reasonText.isEmpty) { ToastUtil.showNormal(context, '请填写作废原因'); @@ -295,26 +310,22 @@ if (path != null) { barrierDismissible: false, ); if (confirmed) { - LoadingDialogHelper.show(); - try { - final result = await ApiService.saveSafeFunctionSure( - 'cutroad', - formData, - imagePaths, - ); - LoadingDialogHelper.hide(); - if (result['result'] == 'success') { - ToastUtil.showSuccess( - context, - status == '1' ? '提交成功' : '已暂存', - ); - Navigator.of(context).pop(true); // 传 true 表示成功(可选) - } - } catch (e) { - LoadingDialogHelper.hide(); - ToastUtil.showNormal(context, '操作失败:$e'); - } - + LoadingDialogHelper.show(); + try { + final result = await ApiService.saveSafeFunctionSure( + 'cutroad', + formData, + imagePaths, + ); + LoadingDialogHelper.hide(); + if (result['result'] == 'success') { + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); + Navigator.of(context).pop(true); // 传 true 表示成功(可选) + } + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '操作失败:$e'); + } } } @@ -333,45 +344,55 @@ if (path != null) { final List imgList = []; if ((measures['IMG_PATH'] as String?)?.isNotEmpty ?? false) { for (var path in (measures['IMG_PATH'] as String).split(',')) { - imgList.add(ImageData(localPath:path, serverPath: path)); + imgList.add(ImageData(localPath: path, serverPath: path)); } } //measures['STATUS'] - final result = await pushPage(DangerousOptionsPage(index: index,status: int.parse(FormUtils.hasValue(measures, 'STATUS') ? measures['STATUS'] : '1'), - measures: measures['PROTECTIVE_MEASURES'] ?? '', - imgList: imgList, - signImgList: signImgList), context); + final result = await pushPage( + DangerousOptionsPage( + index: index, + status: int.parse( + FormUtils.hasValue(measures, 'STATUS') ? measures['STATUS'] : '1', + ), + measures: measures['PROTECTIVE_MEASURES'] ?? '', + imgList: imgList, + signImgList: signImgList, + ), + context, + ); if (result != null) { setState(() { // 更新返回的图片列表(local + remote) final returned = result['imgList'] as List; // 先映射成 ImageData 列表 - final imgDataList = returned.map((m) { - return ImageData( - localPath: m['local'] as String, - serverPath: m['remote'] as String, - ); - }).toList(); + final imgDataList = + returned.map((m) { + return ImageData( + localPath: m['local'] as String, + serverPath: m['remote'] as String, + ); + }).toList(); // 抽取所有非空的 serverPath 并拼成逗号分隔的字符串 final serverPathString = imgDataList .map((e) => e.serverPath) .where((s) => s.isNotEmpty) - .map((s) => s) // 将 String? 转回 String + .map((s) => s) // 将 String? 转回 String .join(','); // 存回 measures measures['IMG_PATH'] = serverPathString; // 更新签字列表 - measures['SIGN_ITEM'] = List>.from(result['signImgList'] as List); + measures['SIGN_ITEM'] = List>.from( + result['signImgList'] as List, + ); // 更新状态、序号等 measures['STATUS'] = result['status'].toString(); index = result['index'] as int; //FocusHelper.clearFocus(context); }); } - } /// 安全防护措施 @@ -392,8 +413,7 @@ if (path != null) { Container( color: Colors.white, child: MeasuresListWidget( - measuresList: - measuresList, // List> + measuresList: measuresList, // List> baseImgPath: ApiService.baseImgPath, isAllowEdit: true, onSign: (item) { @@ -403,11 +423,13 @@ if (path != null) { ), ], ), - ItemListWidget.singleLineTitleText(label: '其他安全措施:', - isEditable: true, - hintText: '请输入其他安全措施', - controller - :_otherController), + ItemListWidget.singleLineTitleText( + isNumericInput: true, + label: '其他安全措施:', + isEditable: true, + hintText: '请输入其他安全措施', + controller: _otherController, + ), SizedBox(height: 20), Row( @@ -508,9 +530,8 @@ class MeasureItem { List>? userList, this.userIndex = -1, List>? selectMeasures, - }) - : userList = userList ?? [], - selectMeasures = selectMeasures ?? []; + }) : userList = userList ?? [], + selectMeasures = selectMeasures ?? []; Map toJson() { return { diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/cutroad_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/cutroad_list_page.dart index fe6aaca..67a9ecb 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/cutroad_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/cutroad_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart'; @@ -237,72 +238,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + @@ -371,8 +307,14 @@ ToastUtil.showNormal(context, '获取流程图失败'); maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), - Expanded(child: Text("消防、安全管理部门: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, + + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: Text("消防、安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true, + textAlign: TextAlign.left, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), @@ -528,48 +470,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart index d9c2b52..199c735 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart @@ -178,8 +178,10 @@ class _CutroadApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -356,8 +358,7 @@ class _CutroadApplyDetailState extends State { pd['CREATOR'] = SessionService.instance.loginUserId; pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; - - // 提交参数 + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; if (msg == 'add') { pd['STEP_ID'] = status; pd['TASK_ID'] = taskId; @@ -368,8 +369,7 @@ class _CutroadApplyDetailState extends State { pd['APPLY_USER_ID'] = SessionService.instance.loginUserId; pd['APPLY_USER_NAME'] = SessionService.instance.username; pd['USER_ID'] = SessionService.instance.loginUserId; - pd['SPECIAL_WORK'] = - FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; + } LoadingDialogHelper.show(); @@ -380,7 +380,7 @@ class _CutroadApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } } catch (e) { 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 2c73184..8dbecb2 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 @@ -371,6 +371,7 @@ class _CutroadYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/zyr_work_detail/cutroad_zyr_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/zyr_work_detail/cutroad_zyr_detail.dart index a57ca3f..51b0d9c 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/zyr_work_detail/cutroad_zyr_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/zyr_work_detail/cutroad_zyr_detail.dart @@ -176,7 +176,7 @@ class _CutroadZyrDetailState extends State { formData['WORK_CONTENT'] = _contentController.text.trim(); formData['CONIMG_PATH'] = serverPathString; - formData['DESCR'] = FormUtils.hasValue(pd, 'DESCR') ? pd['DESCR'] : '无'; + formData['DESCR'] = pd['DESCR'] ?? ''; formData['CUTROAD_ID'] = widget.CUTROAD_ID; formData['SIGNTIME'] = signTimes.join(','); formData['USER_ID'] = SessionService.instance.loginUserId; 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 deab302..f330186 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 @@ -117,12 +117,12 @@ class _BreakgroundDetailFormWidgetState text: pd['CREATTIME'] ?? '', ), ], - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], const Divider(), @@ -190,49 +190,24 @@ class _BreakgroundDetailFormWidgetState controller: widget.relatedController, text: pd['SPECIAL_WORK'] ?? '无', ), - const Divider(), - if (FormUtils.hasValue(pd, 'WORK_CONTENT')) ...[ - ItemListWidget.singleLineTitleText( - label: '作业内容、范围、方式:', - isEditable: false, - text: pd['WORK_CONTENT'] ?? '', - ), - const Divider(), - ], - if (FormUtils.hasValue(pd, 'CONTENT_IMG_PATH')) ...[ - ItemListWidget.singleLineTitleText( - label: '作业内容、范围、方式简图:', - isEditable: false, - text: '', - ), - SizedBox(height: 5), - Padding( - padding: EdgeInsets.symmetric(horizontal: 12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, // 对齐到底部 - children: List.generate(pd['CONTENT_IMG_PATH'].length, (index) { - final fullUrl = - ApiService.baseImgPath + pd['CONTENT_IMG_PATH'][index]; - return Container( - margin: const EdgeInsets.only(right: 20), // 右侧 20px 间隔 - width: 60, - height: 60, - child: GestureDetector( - onTap: () { - presentOpaque( - SingleImageViewer(imageUrl: fullUrl), - context, - ); - }, - child: Image.network(fullUrl, fit: BoxFit.fill), - ), - ); - }), - ), + + if (FormUtils.hasValue(pd, 'CONTENT_IMG_PATH') && + !widget.isEditable) ...[ + ConfirmWithSignWidget( + signs: widget.signs, + pd: pd, + baseImgPath: ApiService.baseImgPath, + sectionKey: 'WORK_USER', + nameKey: 'WORK_CONTENT', + headerTitle: '作业范围、内容、方式(包括深度、面积,并附简图):', + imgsKey: 'CONTENT_IMG_PATH', + contentKey: 'WORK_CONTENT', + roleTitle: '', ), const Divider(), ], + ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', isEditable: widget.isEditable, @@ -270,6 +245,7 @@ class _BreakgroundDetailFormWidgetState isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -321,6 +297,7 @@ class _BreakgroundDetailFormWidgetState isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -402,18 +379,7 @@ class _BreakgroundDetailFormWidgetState text: pd['VIDEONAME'] ?? '', ), - if (FormUtils.hasValue(widget.signs, 'WORK_USER')) ...[ - const Divider(), - ConfirmWithSignWidget( - signs: widget.signs, - pd: pd, - baseImgPath: ApiService.baseImgPath, - sectionKey: 'WORK_USER', - nameKey: 'WORK_USER_USER_NAME', - headerTitle: '作业人签字', - roleTitle: '', - ), - ], + ], ), ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart index 1460ef0..3ad6d6d 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart @@ -187,10 +187,7 @@ class _BreakgroundSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -201,6 +198,10 @@ class _BreakgroundSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -242,7 +243,7 @@ class _BreakgroundSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -382,6 +383,7 @@ class _BreakgroundSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/breakground_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/breakground_list_page.dart index 31d785a..5fc4ee9 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/breakground_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/breakground_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/aqjd_work_detail/breakground_aqjd_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart'; @@ -320,72 +321,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + String _getWorkLevelText(dynamic level) { switch (level?.toString()) { @@ -478,28 +414,25 @@ ToastUtil.showNormal(context, '获取流程图失败'); children: [ Expanded( child: Text( - "有关水、电、汽、工艺、设备、消防安全等部门: ${item['SAFETY_USER_NAME'] ?? ''}", + "有关部门负责人: ${item['SAFETY_USER_NAME'] ?? ''}", softWrap: true, maxLines: null, // 不限制行数 overflow: TextOverflow.visible, ), ), - ], - ), - if (FormUtils.hasValue(item, 'APPROVE_USER_NAME')) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( + if (FormUtils.hasValue(item, 'APPROVE_USER_NAME')) + Expanded( child: Text( "审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}", softWrap: true, + textAlign: TextAlign.right, maxLines: null, // 不限制行数 overflow: TextOverflow.visible, ), ), ], ), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -642,48 +575,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart index 65f8bd7..807f77a 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart @@ -320,8 +320,10 @@ class _BreakgroundApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -494,7 +496,7 @@ class _BreakgroundApplyDetailState extends State { pd['CREATOR'] = SessionService.instance.loginUserId; pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['TASK_ID'] = taskId; @@ -513,7 +515,7 @@ class _BreakgroundApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } } catch (e) { 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 4c2bb5d..e88fd79 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 @@ -374,6 +374,7 @@ class _BreakgroundYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, mode: BottomPickerMode.dateTimeWithSeconds, context, ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/zyr_work_detail/breakground_zyr_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/zyr_work_detail/breakground_zyr_detail.dart index 300dbb1..91ce054 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/zyr_work_detail/breakground_zyr_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/zyr_work_detail/breakground_zyr_detail.dart @@ -180,7 +180,7 @@ class _BreakgroundZyrDetailState extends State { .toList() .join(','); formData['WORK_CONTENT'] = _contentController.text; - formData['DESCR'] = pd['DESCR'] ?? '无'; + formData['DESCR'] = pd['DESCR'] ?? ''; final confirmed = await CustomAlertDialog.showConfirm( context, title: '提示', 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 180adb9..c684e5b 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 @@ -115,12 +115,13 @@ class _HoistworkDetailFormWidgetState extends State { isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], if (FormUtils.hasValue(pd, 'CREATTIME') && !widget.isEditable) ...[ @@ -294,6 +295,7 @@ class _HoistworkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -345,6 +347,7 @@ class _HoistworkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart index 829ee84..be4d3b3 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart @@ -186,10 +186,7 @@ class _HoistworkSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -200,6 +197,10 @@ class _HoistworkSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -241,7 +242,7 @@ class _HoistworkSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -381,6 +382,7 @@ class _HoistworkSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart index 87ebff3..4722303 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart @@ -320,8 +320,10 @@ class _HoistworkApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -505,7 +507,7 @@ class _HoistworkApplyDetailState extends State { pd['CREATOR'] = SessionService.instance.loginUserId; pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['STEP_ID'] = status; @@ -526,7 +528,7 @@ class _HoistworkApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } } catch (e) { diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/hoistwork_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/hoistwork_list_page.dart index fa7699d..e1b5fe3 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/hoistwork_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/hoistwork_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/aqjd_work_detail/hoistwork_aqjd_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart'; @@ -24,7 +25,6 @@ import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; import 'package:qhd_prevention/http/ApiService.dart'; - class HoistworkListPage extends StatefulWidget { final String flow; final String workTypeTitle; @@ -88,7 +88,6 @@ class _HoistworkListPageState extends State { stepList = [ {'STEP_NAME': '全部', 'STEP_ID': ''}, ...response['list'] ?? [], - ]; }); } catch (e) { @@ -139,9 +138,12 @@ class _HoistworkListPageState extends State { } /// 申请 - void _handleApply() async{ + void _handleApply() async { // 处理申请按钮点击逻辑 - await pushPage(HoistworkApplyDetail(HOISTING_ID: '', flow: widget.flow), context); + await pushPage( + HoistworkApplyDetail(HOISTING_ID: '', flow: widget.flow), + context, + ); _fetchData(); LoadingDialogHelper.hide(); } @@ -164,8 +166,8 @@ class _HoistworkListPageState extends State { }); } catch (e) { print('Error fetching flow data: $e'); - -ToastUtil.showNormal(context, '获取流程图失败'); + + ToastUtil.showNormal(context, '获取流程图失败'); } } @@ -178,132 +180,154 @@ ToastUtil.showNormal(context, '获取流程图失败'); if (!allowed) return; switch (widget.flow) { case '提交申请': - await pushPage(HoistworkApplyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkApplyDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '司索人签字': - await pushPage(HoistworkSsrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkSsrDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '设置安全措施确认人': - await pushPage(HoistworkSetSafeDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkSetSafeDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '安全措施确认': - await pushPage(HoistworkSafeFuncSure(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkSafeFuncSure( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '监护人签字': - await pushPage(HoistworkJhrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkJhrDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '安全交底人签字': - await pushPage(HoistworkAqjdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkAqjdDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '接受交底人签字': - await pushPage(HoistworkJsjdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkJsjdDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '作业人签字': - await pushPage(HoistworkZyrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkZyrDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; // case '作业负责人签字': // await pushPage(HoistworkZyfzDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); // break; case '吊装指挥人签字': - await pushPage(HoistworkDzzhDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkDzzhDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '所在单位签字': - await pushPage(HoistworkSzdwDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkSzdwDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '审核人签字': - await pushPage(HoistworkShbmDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkShbmDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '审批人签字': - await pushPage(HoistworkSpbmDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkSpbmDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '开始作业': - await pushPage(HoistworkKszyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkKszyDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '结束作业': - await pushPage(HoistworkJszyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkJszyDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; case '验收签字': - await pushPage(HoistworkYsgdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context); + await pushPage( + HoistworkYsgdDetail( + HOISTING_ID: item['HOISTING_ID'], + flow: widget.flow, + ), + context, + ); break; default: break; } - await _fetchData(); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } - String _getWorkLevelText(dynamic level) { switch (level?.toString()) { case '1': @@ -346,52 +370,103 @@ ToastUtil.showNormal(context, '获取流程图失败'); mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("申请人: ${item['APPLY_USER_NAME'] ?? ''}"), + Text("司索人: ${item['SISUO_USER_NAME'] ?? ''}"), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"), + + Expanded( + child: Text( + "安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) + Expanded( + child: Text( + "接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.left, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), ), - Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) + Expanded( + child: Text( + "作业人: ${item['WORK_USER_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text("审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - Expanded(child: Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true, - textAlign: TextAlign.right, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) + Expanded( + child: Text( + "作业指挥负责人: ${item['PROJECT_MANAGER_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.left, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + Expanded( + child: Text( + "所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), ), ], ), + + if (FormUtils.hasValue(item, 'AUDIT_USER_NAME')) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}", + softWrap: true, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + if (FormUtils.hasValue(item, 'APPROVE_USER_NAME')) + Expanded( + child: Text( + "审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + ], + ), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}"), - SizedBox() + SizedBox(), ], ), Row( @@ -528,48 +603,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), 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 ecae435..a228b2c 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 @@ -374,6 +374,7 @@ class _HoistworkYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, 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 e861e44..081339f 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 @@ -174,12 +174,12 @@ class _HighWorkDetailFormWidgetState extends State { }, text: _getWorkLevelText(pd['WORK_LEVEL']), ), - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], if (FormUtils.hasValue(pd, 'WORK_USER_USER_NAME') && @@ -277,6 +277,7 @@ class _HighWorkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -328,6 +329,7 @@ class _HighWorkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart index c555953..b0bc152 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart @@ -185,10 +185,7 @@ class _HighworkSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -199,6 +196,10 @@ class _HighworkSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -240,7 +241,7 @@ class _HighworkSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -369,6 +370,7 @@ class _HighworkSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', 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 402345c..bc519fd 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 @@ -336,8 +336,10 @@ class _HighworkApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -525,7 +527,7 @@ class _HighworkApplyDetailState extends State { pd['CREATOR'] = SessionService.instance.loginUserId; pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['STEP_ID'] = status; @@ -547,7 +549,7 @@ class _HighworkApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); }else{ ToastUtil.showError(context, result['msg'] ?? '提交失败'); diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/highwork_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/highwork_list_page.dart index b886b9c..e0bc124 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/highwork_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/highwork_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/aqjd_work_detail/highwork_aqjd_detail.dart'; @@ -233,72 +234,7 @@ class _HighworkListPageState extends State { LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + String _getWorkLevelText(dynamic level) { switch (level?.toString()) { @@ -362,31 +298,64 @@ class _HighworkListPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), - Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 textAlign: TextAlign.right, overflow: TextOverflow.visible,) ), + ], ), - - if (item['AUDIT_USER_NAME'] != null) - Text("安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}"), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (item['APPROVE_USER_NAME'] != null) - Expanded(child: Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true, - maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) + Expanded( + child: Text( + "所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.left, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), ), + ], + ), + if (FormUtils.hasValue(item, 'AUDIT_USER_NAME')) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + "审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.left, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + if (FormUtils.hasValue(item, 'APPROVE_USER_NAME')) + Expanded( + child: Text( + "审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}", + softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible, + ), + ), + ], + ), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ Expanded(child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 - textAlign: TextAlign.right, + textAlign: TextAlign.left, overflow: TextOverflow.visible,) ), ], @@ -525,48 +494,7 @@ class _HighworkListPageState extends State { child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), 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 a76f21c..d6ae4ea 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 @@ -374,6 +374,7 @@ class _HighworkYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, mode: BottomPickerMode.dateTimeWithSeconds, context, ); 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 37987c9..d3efb95 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 @@ -278,6 +278,7 @@ class _ElectricityDetailFormWidgetState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -202,6 +199,10 @@ class _ElectricitySafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -243,7 +244,7 @@ class _ElectricitySafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -371,6 +372,7 @@ class _ElectricitySafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/electricity_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/electricity_list_page.dart index 6849393..a292ca6 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/electricity_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/electricity_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/aqcs_work_detail/electricity_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/aqjd_work_detail/electricity_aqjd_detail.dart'; @@ -323,72 +324,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + Widget _buildListItem(Map item) { return Card( @@ -399,6 +335,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: Padding( padding: const EdgeInsets.all(12.0), child: Column( + spacing: 8, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( @@ -410,7 +347,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); ), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -419,54 +356,68 @@ ToastUtil.showNormal(context, '获取流程图失败'); Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"), - Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("用电人: ${item['ELECTRICITY_USER_NAME'] ?? ''}",softWrap: true, textAlign: TextAlign.right, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), + ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true, + textAlign: TextAlign.left, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), + Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true, + maxLines: null, // 不限制行数 + textAlign: TextAlign.right, + overflow: TextOverflow.visible,) + ), + + ], + ), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), - ], - ), - const SizedBox(height: 8), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: Text("用电单位负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("用电负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 - overflow: TextOverflow.visible,) - ), - Expanded(child: Text("配送电单位负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true, textAlign: TextAlign.right, - maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), + ], ), - const SizedBox(height: 8), + + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Expanded(child: Text("配送电单位负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true, + textAlign: TextAlign.left, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible,) + ),], + ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}")], ), - const SizedBox(height: 8), + + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -478,7 +429,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); ), ], ), - const SizedBox(height: 8), + Row( children: [ CustomButton( @@ -602,48 +553,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart index c4fe199..3b81a40 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart @@ -308,8 +308,10 @@ class _ElectricityApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -518,7 +520,7 @@ class _ElectricityApplyDetailState extends State { pd['ISANALYZE'] = _isGasAnalyze ? 1 : 0; pd['APPLY_STATUS'] = status; pd['TASK_ID'] = taskId; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['ELECTRICITY_ID'] = widget.ELECTRICITY_ID; @@ -537,7 +539,7 @@ class _ElectricityApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } else { ToastUtil.showSuccess(context, '提交失败'); 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 bc9fa28..f04c000 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 @@ -380,6 +380,7 @@ class _ElectricityYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, 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 1c21cb3..cd3a345 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 @@ -346,12 +346,12 @@ class _BlindboardDetailFormWidgetState isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], const Divider(), @@ -499,6 +499,7 @@ class _BlindboardDetailFormWidgetState isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -551,6 +552,7 @@ class _BlindboardDetailFormWidgetState isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/aqcs_work_detail/blindboard_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/aqcs_work_detail/blindboard_safe_func_sure.dart index b775cd0..8da5868 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/aqcs_work_detail/blindboard_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/aqcs_work_detail/blindboard_safe_func_sure.dart @@ -197,10 +197,7 @@ class _BlindboardSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -211,6 +208,10 @@ class _BlindboardSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -252,7 +253,7 @@ class _BlindboardSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -384,6 +385,7 @@ class _BlindboardSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/blindboard_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/blindboard_list_page.dart index 0acb6d9..567a1b0 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/blindboard_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/blindboard_list_page.dart @@ -22,6 +22,8 @@ import 'package:qhd_prevention/customWidget/bottom_picker.dart'; import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; + class BlindboardListPage extends StatefulWidget { final String flow; @@ -235,72 +237,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + String _getWorkLevelText(dynamic level) { switch (level?.toString()) { @@ -503,48 +440,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/mbcd_work_detai/blindboard_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/mbcd_work_detai/blindboard_apply_detail.dart index 512f757..b6ff222 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/mbcd_work_detai/blindboard_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/mbcd_work_detai/blindboard_apply_detail.dart @@ -318,8 +318,10 @@ class _BlindboardApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -506,7 +508,7 @@ class _BlindboardApplyDetailState extends State { pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; pd['boardList'] = jsonEncode(boardList).toString(); - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['STEP_ID'] = status; @@ -528,7 +530,7 @@ class _BlindboardApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } } catch (e) { 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 925b737..0b65b78 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 @@ -367,6 +367,7 @@ class _BlindboardYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, 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 fd778f7..7e7372a 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 @@ -186,12 +186,12 @@ class _SpaceWorkDetailFormWidgetState extends State { controller: widget.contentController, text: pd['WORK_CONTENT'] ?? '', ), - if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[ const Divider(), ItemListWidget.singleLineTitleText( label: '作业单位:', isEditable: false, - text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '', ), ], if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && @@ -297,6 +297,7 @@ class _SpaceWorkDetailFormWidgetState extends State { isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, @@ -345,9 +346,11 @@ class _SpaceWorkDetailFormWidgetState extends State { const Divider(), ItemListWidget.selectableLineTitleTextRightButton( label: '预计作业结束时间:', + isEditable: widget.isEditable, onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, context, minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', allowFuture: true, diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart index f272393..3d5b7b7 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart @@ -186,10 +186,7 @@ class _SpaceworkSafeFuncSureState extends State { /// 提交 1 提交 0暂存 Future _submit(String status) async { - if (_otherController.text.trim().isEmpty) { - ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); - return; - } + if (imagePaths.isEmpty) { ToastUtil.showNormal(context, '请签字'); return; @@ -200,6 +197,10 @@ class _SpaceworkSafeFuncSureState extends State { if (!_validateAndProceed(context)) { return; } + if (_otherController.text.trim().isEmpty) { + ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”'); + return; + } } else { reasonText = await CustomAlertDialog.showInput( context, @@ -241,7 +242,7 @@ class _SpaceworkSafeFuncSureState extends State { ); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); // 传 true 表示成功(可选) } } catch (e) { @@ -369,6 +370,7 @@ class _SpaceworkSafeFuncSureState extends State { ], ), ItemListWidget.singleLineTitleText( + isNumericInput: true, label: '其他安全措施:', isEditable: true, hintText: '请输入其他安全措施', diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart index 8d8d6e6..142977e 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart @@ -329,8 +329,10 @@ class _SpaceworkApplyDetailState extends State { onTapClean: () { ToastUtil.showNormal(context, '已清除'); setState(() { - pd['${type.name}_DEPARTMENT_NAME'] = ''; - pd['${type.name}_USER_NAME'] = ''; + set_pd_USER_ID(type, ''); + set_pd_USER_Name(type, ''); + set_pd_DEPARTMENT_NAME(type, ''); + set_pd_DEPARTMENT_ID(type, ''); _personCache.remove(type); }); }, @@ -503,7 +505,7 @@ class _SpaceworkApplyDetailState extends State { pd['ACTION_USER'] = SessionService.instance.username; pd['APPLY_STATUS'] = status; pd['TASK_ID'] = '4'; - + pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无'; // 提交参数 if (msg == 'add') { pd['APPLY_DEPARTMENT_ID'] = SessionService.instance.deptId; @@ -521,7 +523,7 @@ class _SpaceworkApplyDetailState extends State { final result = await ApiService.submitHomework(url, pd); LoadingDialogHelper.hide(); if (result['result'] == 'success') { - ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); + ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功'); Navigator.of(context).pop(true); } else { ToastUtil.showError(context, result['msg'] ?? '提交失败'); diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/spacework_list_page.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/spacework_list_page.dart index c3d9184..1aa9041 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/spacework_list_page.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/spacework_list_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/aqgl_work_detail/spacework_aqgl_detail.dart'; @@ -345,72 +346,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); LoadingDialogHelper.hide(); } - Widget _buildFlowStepItem({ - required Map item, - required bool isFirst, - required bool isLast, - required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达 - }) { - // 依据状态设色 - final Color dotColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey); - final Color textColor = - status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black); - - return ListTile( - visualDensity: VisualDensity(vertical: -4), - - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - leading: Container( - width: 24, - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - // 上方线段或占位 - isFirst - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - // 圆点 - CircleAvatar(radius: 6, backgroundColor: dotColor), - // 下方线段或占位 - isLast - ? SizedBox(height: 6 + 5) - : Expanded(child: Container(width: 1, color: Colors.grey[300])), - ], - ), - ), - title: Text( - item['STEP_NAME'] ?? '', - style: TextStyle(color: textColor, fontSize: 15), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item['SIGN_USER'] != null) - Text( - item['SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['FINISHED_SIGN_USER'] != null) - Text( - item['FINISHED_SIGN_USER'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_USER_NAME'] != null) - Text( - item['ACT_USER_NAME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - if (item['ACT_TIME'] != null) - Text( - item['ACT_TIME'], - style: TextStyle(color: textColor, fontSize: 13), - ), - ], - ), - ); - } + Widget _buildListItem(Map item) { return Card( @@ -421,6 +357,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: Padding( padding: const EdgeInsets.all(12.0), child: Column( + spacing: 8, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( @@ -432,7 +369,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); ), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -440,7 +377,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -452,7 +389,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); ), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -460,29 +397,32 @@ ToastUtil.showNormal(context, '获取流程图失败'); maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), - Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",softWrap: true, textAlign: TextAlign.right, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), ], ), - const SizedBox(height: 8), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), - Expanded(child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true, + Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true, textAlign: TextAlign.right, maxLines: null, // 不限制行数 overflow: TextOverflow.visible,) ), ], ), - const SizedBox(height: 8), + Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true, + textAlign: TextAlign.right, + maxLines: null, // 不限制行数 + overflow: TextOverflow.visible,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -494,7 +434,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); ), ], ), - const SizedBox(height: 8), + Row( children: [ CustomButton( @@ -618,48 +558,7 @@ ToastUtil.showNormal(context, '获取流程图失败'); child: flowList.isEmpty ? Center(child: Text('暂无流程图数据')) - : ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 16), - itemCount: flowList.length + 1, // +1 用来放标题 - itemBuilder: (context, i) { - if (i == 0) { - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: Text( - '查看流程图', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ); - } - final idx = i - 1; - final item = flowList[idx]; - final bool isFirst = idx == 0; - final bool isLast = idx == flowList.length - 1; - - // 根据 lastDoneIndex 自动计算“进行中” - final int status; - if (idx <= lastDoneIndex) { - status = 1; // 已完成 - } else if (idx == lastDoneIndex + 1) { - status = 0; // 进行中 - } else { - status = -1; // 未到达 - } - - return _buildFlowStepItem( - item: item, - isFirst: isFirst, - isLast: isLast, - status: status, - ); - }, - ), + : ItemListWidget.buildFlowStepItem(flowList: flowList), ), ), 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 32e8f1c..12f67bb 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 @@ -384,6 +384,7 @@ class _SpaceworkYsgdDetailState extends State { ), onTap: () async { DateTime? picked = await BottomDateTimePicker.showDate( + allowPast:false, mode: BottomPickerMode.dateTimeWithSeconds, context, );