From 74c0d83f2110556a3987ca2e4f1623bab780f61e Mon Sep 17 00:00:00 2001 From: hs <873121290@qq.com> Date: Wed, 10 Sep 2025 13:48:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=AD=E8=B7=AF=E3=80=81=E7=9B=B2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/customWidget/ItemWidgetFactory.dart | 4 +- lib/customWidget/center_multi_picker.dart | 263 +++++ lib/http/ApiService.dart | 17 +- .../SafeCheck/custom/safe_drawer_page.dart | 37 +- lib/pages/badge_manager.dart | 268 ++++-- .../DangeCheck/safeCheck_acceptance_page.dart | 902 ++++++++++++------ lib/pages/home/home_page.dart | 6 +- lib/pages/home/tap/item_list_widget.dart | 85 +- .../special_wrok/MeasuresListWidget.dart | 877 +++++++++++++++-- .../dh_work/HotWorkDetailFormWidget.dart | 245 +++-- .../dh_work/SpecialWorkFormBaseWork.dart | 382 ++------ .../dh_work_detai/hotwork_apply_detail.dart | 114 +-- .../jszy_work_detail/hotwork_jszy_detail.dart | 103 +- .../kszy_work_detail/hotwork_kszy_detail.dart | 101 +- .../dl_work/CutroadDetailFormWidget.dart | 539 ++++++----- .../dl_work/CutroadFormBaseWork.dart | 194 ++-- .../aqjd_work_detail/cutroad_aqjd_detail.dart | 2 + .../dl_work/cutroad_list_page.dart | 4 +- .../dl_work_detai/cutroad_apply_detail.dart | 2 +- .../jszy_work_detail/cutroad_jszy_detail.dart | 198 ++-- .../kszy_work_detail/cutroad_kszy_detail.dart | 171 +--- .../ysgd_work_detail/cutroad_ysgd_detail.dart | 2 +- .../dt_work/BreakgroundDetailFormWidget.dart | 4 +- .../dt_work/SpecialWorkFormBaseWork.dart | 26 +- .../breakground_jszy_detail.dart | 102 +- .../breakground_kszy_detail.dart | 108 +-- .../dz_work/HoistworkDetailFormWidget.dart | 4 +- .../dz_work/SpecialWorkFormBaseWork.dart | 14 +- .../hoistwork_jszy_detail.dart | 103 +- .../hoistwork_kszy_detail.dart | 109 +-- .../gc_work/HighWorkDetailFormWidget.dart | 4 +- .../gc_work/SpecialWorkFormBaseWork.dart | 16 +- .../highwork_jszy_detail.dart | 103 +- .../highwork_kszy_detail.dart | 108 +-- .../ElectricityDetailFormWidget.dart | 6 +- .../lsyd_work/SpecialWorkFormBaseWork.dart | 15 +- .../electricity_jszy_detail.dart | 102 +- .../electricity_kszy_detail.dart | 103 +- .../mbcd_work/BlindboardDetailFormWidget.dart | 411 ++++++-- .../mbcd_work/BlindboardFormBaseWork.dart | 165 +--- .../mbcd_work/blindboard_list_page.dart | 24 +- .../blindboard_cjry_detail.dart | 138 +-- .../blindboard_jszy_detail.dart | 104 +- .../blindboard_kszy_detail.dart | 107 +-- .../blindboard_apply_detail.dart | 6 +- .../blindboard_set_safe_detail.dart | 15 +- .../sxkj_work/SpaceWorkDetailFormWidget.dart | 6 +- .../sxkj_work/SpecialWorkFormBaseWork.dart | 15 +- .../spacework_jszy_detail.dart | 103 +- .../spacework_kszy_detail.dart | 102 +- .../home/tap/tabList/work_tab_mbcd_list.dart | 4 +- lib/tools/h_colors.dart | 3 + lib/tools/tools.dart | 2 +- 53 files changed, 3330 insertions(+), 3318 deletions(-) create mode 100644 lib/customWidget/center_multi_picker.dart diff --git a/lib/customWidget/ItemWidgetFactory.dart b/lib/customWidget/ItemWidgetFactory.dart index 5b80380..940f904 100644 --- a/lib/customWidget/ItemWidgetFactory.dart +++ b/lib/customWidget/ItemWidgetFactory.dart @@ -407,8 +407,10 @@ class ListItemFactory { } /// 单纯标题 - static Widget headerTitle(String title, {bool isRequired = false}) { + static Widget headerTitle(String title, {bool isRequired = false, double verticalPadding = 0, + double horizontalPadding = 0,}) { return Container( + padding: EdgeInsets.symmetric(horizontal: horizontalPadding, vertical: verticalPadding), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), diff --git a/lib/customWidget/center_multi_picker.dart b/lib/customWidget/center_multi_picker.dart new file mode 100644 index 0000000..718c555 --- /dev/null +++ b/lib/customWidget/center_multi_picker.dart @@ -0,0 +1,263 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; + +/// 居中多选弹窗(Dialog) +/// 返回 Future?>:用户点击确定返回所选项列表;取消或关闭返回 null。 +class CenterMultiPicker { + static Future?> show( + BuildContext context, { + required List items, + required Widget Function(T item) itemBuilder, + List? initialSelectedIndices, + int? maxSelection, + bool allowEmpty = false, + double itemHeight = 52, + double maxHeightFactor = 0.75, // 屏幕高度的最大占比 + String? title, + }) { + if (items.isEmpty) return Future.value(null); + + // 安全化初始索引 + final initialSet = {}; + if (initialSelectedIndices != null) { + for (final i in initialSelectedIndices) { + // if (i >= 0 && i < items.length) initialSet.add(i); + } + } + + return showDialog?>( + context: context, + barrierDismissible: true, + builder: (ctx) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + insetPadding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 24, + ), + child: _CenterMultiPickerBody( + items: items, + itemBuilder: itemBuilder, + initialSelected: initialSet, + maxSelection: maxSelection, + allowEmpty: allowEmpty, + itemHeight: itemHeight, + maxHeightFactor: maxHeightFactor, + title: title, + ), + ); + }, + ); + } +} + +class _CenterMultiPickerBody extends StatefulWidget { + const _CenterMultiPickerBody({ + Key? key, + required this.items, + required this.itemBuilder, + required this.initialSelected, + required this.maxSelection, + required this.allowEmpty, + required this.itemHeight, + required this.maxHeightFactor, + this.title, + }) : super(key: key); + + final List items; + final Widget Function(T item) itemBuilder; + final Set initialSelected; + final int? maxSelection; + final bool allowEmpty; + final double itemHeight; + final double maxHeightFactor; + final String? title; + + @override + State<_CenterMultiPickerBody> createState() => + _CenterMultiPickerBodyState(); +} + +class _CenterMultiPickerBodyState extends State<_CenterMultiPickerBody> { + late Set _selected; + + // 固定的 header / footer 高度估算 + static const double _headerHeight = 56; + static const double _footerHeight = 58; + static const double _verticalPadding = 16; // Dialog 内上下 padding + + @override + void initState() { + super.initState(); + _selected = Set.from(widget.initialSelected); + } + + void _toggle(int idx) { + setState(() { + if (_selected.contains(idx)) { + _selected.remove(idx); + } else { + if (widget.maxSelection != null && + _selected.length >= widget.maxSelection!) { + ToastUtil.showNormal(context, '最多可选择 ${widget.maxSelection} 项'); + return; + } + _selected.add(idx); + } + }); + } + + @override + Widget build(BuildContext context) { + final items = widget.items; + final screenH = MediaQuery.of(context).size.height; + final contentHeight = + items.length * widget.itemHeight + + _headerHeight + + _footerHeight + + _verticalPadding * 2; + final maxAllowed = screenH * widget.maxHeightFactor; + final dialogHeight = + contentHeight <= maxAllowed ? contentHeight : maxAllowed; + + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10) + ), + width: double.infinity, + height: dialogHeight, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // header + Container( + height: _headerHeight, + padding: const EdgeInsets.symmetric(horizontal: 16), + alignment: Alignment.centerLeft, + child: Row( + children: [ + if (widget.title != null) + Expanded( + child: Text( + widget.title!, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + ) + else + Expanded( + child: Text( + '已选 ${_selected.length}${widget.maxSelection != null ? '/${widget.maxSelection}' : ''}', + style: const TextStyle(fontSize: 15), + ), + ), + // 可将一些快捷按钮放在右侧(如全选/反选),这里暂不显示 + ], + ), + ), + const Divider(height: 1), + // 列表区域(可滚动) + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Scrollbar( + thumbVisibility: true, + child: ListView.separated( + physics: const BouncingScrollPhysics(), + itemCount: items.length, + separatorBuilder: (_, __) => const Divider(height: 1), + itemBuilder: (ctx, idx) { + final isSelected = _selected.contains(idx); + return InkWell( + onTap: () => _toggle(idx), + child: Container( + height: widget.itemHeight, + padding: const EdgeInsets.symmetric( + horizontal: 14, + vertical: 6, + ), + child: Row( + children: [ + Container( + width: 22, + height: 22, + decoration: BoxDecoration( + color: + isSelected + ? Colors.blue + : Colors.transparent, + border: Border.all( + color: + isSelected ? Colors.blue : Colors.black26, + ), + borderRadius: BorderRadius.circular(4), + ), + child: + isSelected + ? const Icon( + Icons.check, + size: 18, + color: Colors.white, + ) + : null, + ), + const SizedBox(width: 12), + Expanded(child: widget.itemBuilder(items[idx])), + ], + ), + ), + ); + }, + ), + ), + ), + ), + const Divider(height: 1), + // footer: 取消 / 确定(固定在底部) + Container( + height: _footerHeight, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( + children: [ + Expanded( + child: CustomButton( + text: '取消', + backgroundColor: Colors.grey.shade200, + textStyle: TextStyle(fontSize: 14, color: Colors.black), + onPressed: () { + Navigator.of(context).pop(null); + }, + ), + ), + const SizedBox(width: 12), + Expanded( + child: CustomButton( + text: '确定', + backgroundColor: Colors.blue, + onPressed: () { + if (!widget.allowEmpty && _selected.isEmpty) { + ToastUtil.showNormal(context, '请至少选择一项'); + return; + } + final result = _selected + .map((i) => items[i]) + .toList(growable: false); + Navigator.of(context).pop(result); + }, + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/http/ApiService.dart b/lib/http/ApiService.dart index 8862380..606a289 100644 --- a/lib/http/ApiService.dart +++ b/lib/http/ApiService.dart @@ -20,12 +20,12 @@ class ApiService { // static const String publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUoHAavCikaZxjlDM6Km8cX+ye78F4oF39AcEfnE1p2Yn9pJ9WFxYZ4Vkh6F8SKMi7k4nYsKceqB1RwG996SvHQ5C3pM3nbXCP4K15ad6QhN4a7lzlbLhiJcyIKszvvK8ncUDw8mVQ0j/2mwxv05yH6LN9OKU6Hzm1ninpWeE+awIDAQAB' /// 人脸识别服务 // static const String baseFacePath = "https://qaaqwh.qhdsafety.com/whb_stu_face"; - static const String baseFacePath = - "http://192.168.20.240:8500/whb_stu_face/"; + static const String baseFacePath = "http://192.168.20.240:8500/whb_stu_face/"; /// 登录及其他管理后台接口 // static const String basePath = "http://192.168.20.240:8500/integrated_whb";//测试服务器 // static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb"; static const String basePath = "http://192.168.20.240:8500/integrated_whb"; + // static const String basePath = "http://192.168.0.25:28199";//王轩服务器 // static const String basePath = "http://192.168.0.45:28199";//长久服务器 /// 图片文件服务 @@ -171,6 +171,19 @@ U6Hzm1ninpWeE+awIDAQAB }, ); } + /// 安全检查隐患验收提交 + static Future> safeCheckDangerAcceptanceSubmit(Map data) { + return HttpManager().request( + basePath, + '/app/hidden/finalcheck', + method: Method.post, + data: { + ...data, + }, + ); + } + + static Future> getUpdateInfo() { return HttpManager().request( diff --git a/lib/pages/KeyProjects/SafeCheck/custom/safe_drawer_page.dart b/lib/pages/KeyProjects/SafeCheck/custom/safe_drawer_page.dart index cb35693..c420961 100644 --- a/lib/pages/KeyProjects/SafeCheck/custom/safe_drawer_page.dart +++ b/lib/pages/KeyProjects/SafeCheck/custom/safe_drawer_page.dart @@ -256,6 +256,7 @@ class _SafeDrawerPageState extends State { child: _section( ListItemFactory.createRowSpaceBetweenItem( leftText: '隐患级别', + isRequired: true, rightText: hiddenForm['HIDDENLEVEL_NAME']?.toString() ?? '请选择', @@ -270,6 +271,7 @@ class _SafeDrawerPageState extends State { child: _section( ListItemFactory.createRowSpaceBetweenItem( leftText: '隐患类型', + isRequired: true, rightText: hiddenForm['HIDDENTYPE_NAME']?.toString() ?? '请选择', @@ -325,27 +327,11 @@ class _SafeDrawerPageState extends State { ), ), ] else ...[ - // limited rectify: department, person, date - // GestureDetector( - // onTap: _isEdit ? _pickDept : null, - // child: _section( - // ListItemFactory.createRowSpaceBetweenItem( - // leftText: '整改部门', - // rightText: - // _isEdit - // ? (hiddenForm['RECTIFICATIONDEPT_NAME'] - // ?.toString() ?? - // '请选择') - // : hiddenForm['RECTIFICATIONDEPT_NAME'] - // ?.toString() ?? - // '', - // isRight: _isEdit, - // ), - // ), - // ), + const SizedBox(height: 10), ItemListWidget.itemContainer(horizontal: 15,ListItemFactory.createRowSpaceBetweenItem( leftText: '整改部门', + isRequired: true, rightText:hiddenForm['RECTIFICATIONDEPT_NAME'] ?? '', isRight: false, ),), @@ -360,6 +346,7 @@ class _SafeDrawerPageState extends State { ), child: ListItemFactory.createRowSpaceBetweenItem( leftText: '整改人', + isRequired: true, rightText: hiddenForm['RECTIFICATIONOR_NAME'] ?.toString() ?? @@ -373,6 +360,7 @@ class _SafeDrawerPageState extends State { child: _section( ListItemFactory.createRowSpaceBetweenItem( leftText: '整改期限', + isRequired: true, rightText: hiddenForm['RECTIFICATIONDEADLINE'] ?.toString() ?? @@ -510,8 +498,10 @@ class _SafeDrawerPageState extends State { '1', ); setState( - () => - _personCache = List>.from(res['varList'] ?? []), + () { + _personCache = List>.from(res['varList'] ?? []); + + } ); } @@ -528,11 +518,12 @@ class _SafeDrawerPageState extends State { // 用户点击确定并选择了 choice setState(() { hiddenForm['RECTIFICATIONOR_NAME'] = choice; - Map? target = widget.toCheckUnitList.firstWhere( - (item) => item['RECTIFICATIONOR_NAME'] == choice, + Map target = _personCache.firstWhere( + (item) => item['NAME'] == choice, orElse: () => {}, ); - hiddenForm['RECTIFICATIONOR'] = target?['PERSONNELMANAGEMENT_ID']; + hiddenForm['RECTIFICATIONOR'] = target['PERSONNELMANAGEMENT_ID'] ?? ''; + hiddenForm['RECTIFICATIONOR_INDEX'] = _personCache.indexOf(target); //FocusHelper.clearFocus(context); }); } diff --git a/lib/pages/badge_manager.dart b/lib/pages/badge_manager.dart index dd3e1bb..a0f7a60 100644 --- a/lib/pages/badge_manager.dart +++ b/lib/pages/badge_manager.dart @@ -1,91 +1,179 @@ -import 'package:flutter/material.dart'; +import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter_new_badger/flutter_new_badger.dart'; import 'package:qhd_prevention/http/ApiService.dart'; -import 'package:qhd_prevention/tools/tools.dart'; +import 'package:flutter/material.dart'; -/// 单例角标管理,多接口分模块更新及全局原生角标同步 +/// 优化版 BadgeManager:每个接口超时保护、增量更新、notify 合并、原生角标 debounce class BadgeManager extends ChangeNotifier { BadgeManager._internal(); - static final BadgeManager _instance = BadgeManager._internal(); - factory BadgeManager() => _instance; // 各模块未读 int _appCount = 0; - int _appDysCount = 0; // 新增:待验收 - int _appDzgCount = 0; // 新增:待整改 + int _appDysCount = 0; + int _appDzgCount = 0; int _notifCount = 0; int _envInspectCount = 0; int _eightWorkCount = 0; - /// 总未读角标数 + // 读取接口值的公开 getter int get count => _appCount + _notifCount + _envInspectCount + _eightWorkCount; - - /// MainPage 整体“应用”角标 int get appCount => _appCount; - - /// MainPage “待验收”子项 int get appDysCount => _appDysCount; - - /// MainPage “待整改”子项 int get appDzgCount => _appDzgCount; - int get notifCount => _notifCount; - int get envInspectCount => _envInspectCount; - int get eightWorkCount => _eightWorkCount; - /// 登录后或有用户上下文时,初始化所有接口汇总数,并同步原生角标 - Future initAllModules() async { + // 通知合并控制(短时间内多次更新只触发一次 notify) + Timer? _notifyTimer; + Duration _notifyDelay = const Duration(milliseconds: 180); + void _scheduleNotify() { + // 如果已有计划,不需要再立即计划(合并) + _notifyTimer?.cancel(); + _notifyTimer = Timer(_notifyDelay, () { + try { + notifyListeners(); + } catch (e) { + debugPrint('BadgeManager.notifyListeners error: $e'); + } + _notifyTimer = null; + }); + } + + // 原生角标同步 debounce(防止短时间内频繁调用) + Timer? _syncTimer; + Duration _syncDelay = const Duration(milliseconds: 250); + void _syncNativeDebounced() { + _syncTimer?.cancel(); + _syncTimer = Timer(_syncDelay, () { + try { + final total = count; + if (total > 0) { + FlutterNewBadger.setBadge(total); + } else { + FlutterNewBadger.removeBadge(); + } + } catch (e) { + debugPrint('BadgeManager._syncNativeDebounced error: $e'); + } + _syncTimer = null; + }); + } + + // safe wrapper: 给单个 future 加超时与兜底返回 + Future _safe(Future future, T fallback, {Duration timeout = const Duration(seconds: 5)}) async { try { - final results = await Future.wait([ - ApiService.getWork(), // 应用中心 - ApiService.getNotifRedPoint(), // 通知公告 - ApiService.getSafetyEnvironmentalInspectionCount(), // 安全巡检 - ApiService.getRedPoint(), // 八项作业 - ]); - - // 应用中心部分 - final workJson = results[0]; - final hid = workJson['hidCount'] as Map? ?? {}; - _appDysCount = (hid['dys'] ?? 0) as int; - _appDzgCount = (hid['dzg'] ?? 0) as int; - _appCount = _appDysCount + _appDzgCount; - - // 通知公告部分 - final notifJson = results[1]; - _notifCount = notifJson['count'] as int? ?? 0; - - // 安全巡检部分 - final checkJson = results[2]; - _envInspectCount = - checkJson['repulseCount']?['repulseCount'] ?? 0; - - // 八项作业部分 - final redPointJson = results[3]; - _eightWorkCount = 0; - (redPointJson['count'] as Map? ?? {}).values.forEach(( - v, - ) { - _eightWorkCount += (v ?? 0) as int; - }); - - _syncNative(); - notifyListeners(); - } catch (e) { - debugPrint('BadgeManager.initAllModules error: $e'); + return await future.timeout(timeout); + } catch (e, st) { + // 报错不抛出到外层,记录并返回 fallback + debugPrint('BadgeManager._safe error: $e\n$st'); + return fallback; } } - /// 更新 MainPage 的应用中心角标 + /// 初始化所有模块(并行发起,但每个接口独立 timeout & 提交结果) + Future initAllModules() async { + // 不 await 整个 Future.wait,使调用方不会因为单个慢接口阻塞 + try { + // 每个请求都通过 _safe 包裹,设置超时与兜底 + final fWork = _safe>( + ApiService.getWork().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 6), + ); + final fNotif = _safe>( + ApiService.getNotifRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 4), + ); + final fCheck = _safe>( + ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 5), + ); + final fRed = _safe>( + ApiService.getRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 5), + ); + + // 按接口独立处理:完成即更新并合并通知(progressive update) + fWork.then((workJson) { + try { + final hid = (workJson['hidCount'] as Map?) ?? {}; + _appDysCount = (hid['dys'] ?? 0) as int? ?? 0; + _appDzgCount = (hid['dzg'] ?? 0) as int? ?? 0; + _appCount = _appDysCount + _appDzgCount; + } catch (e, st) { + debugPrint('BadgeManager.parse workJson error: $e\n$st'); + } + _scheduleNotify(); + _syncNativeDebounced(); + }); + + fNotif.then((notifJson) { + try { + _notifCount = (notifJson['count'] as int?) ?? 0; + } catch (e, st) { + debugPrint('BadgeManager.parse notifJson error: $e\n$st'); + } + _scheduleNotify(); + _syncNativeDebounced(); + }); + + fCheck.then((checkJson) { + try { + // 兼容不同返回结构,防止空指针 + int checkedCount = 0, repulseAndCheckCount = 0, confirmCount = 0, repulseCount = 0; + if (checkJson['checkedCount'] is Map) checkedCount = (checkJson['checkedCount']['checkedCount'] ?? 0) as int? ?? 0; + if (checkJson['repulseAndCheckCount'] is Map) repulseAndCheckCount = (checkJson['repulseAndCheckCount']['repulseAndCheckCount'] ?? 0) as int? ?? 0; + if (checkJson['confirmCount'] is Map) confirmCount = (checkJson['confirmCount']['confirmCount'] ?? 0) as int? ?? 0; + if (checkJson['repulseCount'] is Map) repulseCount = (checkJson['repulseCount']['repulseCount'] ?? 0) as int? ?? 0; + _envInspectCount = checkedCount + repulseAndCheckCount + confirmCount + repulseCount; + } catch (e, st) { + debugPrint('BadgeManager.parse checkJson error: $e\n$st'); + } + _scheduleNotify(); + _syncNativeDebounced(); + }); + + fRed.then((redPointJson) { + try { + _eightWorkCount = 0; + final m = (redPointJson['count'] as Map?) ?? {}; + for (final v in m.values) { + _eightWorkCount += (v ?? 0) as int? ?? 0; + } + } catch (e, st) { + debugPrint('BadgeManager.parse redPointJson error: $e\n$st'); + } + _scheduleNotify(); + _syncNativeDebounced(); + }); + + // 可选:等待所有结束(不阻塞调用方),用于 debug 或需要最终一致性的场景 + unawaited(Future.wait([fWork, fNotif, fCheck, fRed]).then((_) { + debugPrint('BadgeManager.initAllModules: all done at ${DateTime.now()}'); + })); + } catch (e, st) { + debugPrint('BadgeManager.initAllModules unexpected error: $e\n$st'); + } + } + + // 下面的 updateX 方法也做了超时保护并使用 _onModuleChanged 合并通知 void updateAppCount() async { try { - final workJson = await ApiService.getWork(); - final hid = workJson['hidCount'] as Map? ?? {}; - _appDysCount = (hid['dys'] ?? 0) as int; - _appDzgCount = (hid['dzg'] ?? 0) as int; + final workJson = await _safe>( + ApiService.getWork().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 5), + ); + final hid = (workJson['hidCount'] as Map?) ?? {}; + _appDysCount = (hid['dys'] ?? 0) as int? ?? 0; + _appDzgCount = (hid['dzg'] ?? 0) as int? ?? 0; _appCount = _appDysCount + _appDzgCount; _onModuleChanged(); } catch (e) { @@ -93,43 +181,49 @@ class BadgeManager extends ChangeNotifier { } } - /// 更新 MainPage 的通知公告角标 void updateNotifCount() async { try { - final notifJson = await ApiService.getNotifRedPoint(); - _notifCount = notifJson['count'] as int? ?? 0; + final notifJson = await _safe>( + ApiService.getNotifRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 4), + ); + _notifCount = (notifJson['count'] as int?) ?? 0; _onModuleChanged(); } catch (e) { debugPrint('updateNotifCount error: $e'); } } - /// 更新 HomePage 安全巡检角标 void updateEnvInspectCount() async { try { - final checkJson = - await ApiService.getSafetyEnvironmentalInspectionCount(); - _envInspectCount = - (checkJson['confirmCount']?['confirmCount'] ?? 0)( - checkJson['repulseCount']?['repulseCount'] ?? 0, - )(checkJson['repulseAndCheckCount']?['repulseAndCheckCount'] ?? 0) - as int; + final checkJson = await _safe>( + ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 5), + ); + int checkedCount = 0, repulseAndCheckCount = 0, confirmCount = 0, repulseCount = 0; + if (checkJson['checkedCount'] is Map) checkedCount = (checkJson['checkedCount']['checkedCount'] ?? 0) as int? ?? 0; + if (checkJson['repulseAndCheckCount'] is Map) repulseAndCheckCount = (checkJson['repulseAndCheckCount']['repulseAndCheckCount'] ?? 0) as int? ?? 0; + if (checkJson['confirmCount'] is Map) confirmCount = (checkJson['confirmCount']['confirmCount'] ?? 0) as int? ?? 0; + if (checkJson['repulseCount'] is Map) repulseCount = (checkJson['repulseCount']['repulseCount'] ?? 0) as int? ?? 0; + _envInspectCount = checkedCount + repulseAndCheckCount + confirmCount + repulseCount; _onModuleChanged(); } catch (e) { debugPrint('updateEnvInspectCount error: $e'); } } - /// 更新 HomePage 八项作业角标 void updateEightWorkCount() async { try { - final redPointJson = await ApiService.getRedPoint(); + final redPointJson = await _safe>( + ApiService.getRedPoint().then((r) => r as Map), + {}, + timeout: const Duration(seconds: 5), + ); int sum = 0; - (redPointJson['count'] as Map? ?? {}).values.forEach(( - v, - ) { - sum += (v ?? 0) as int; - }); + final m = (redPointJson['count'] as Map?) ?? {}; + for (final v in m.values) sum += (v ?? 0) as int? ?? 0; _eightWorkCount = sum; _onModuleChanged(); } catch (e) { @@ -137,25 +231,15 @@ class BadgeManager extends ChangeNotifier { } } - /// 清空所有角标 void clearAll() { _appCount = _notifCount = _envInspectCount = _eightWorkCount = 0; _appDysCount = _appDzgCount = 0; - _syncNative(); - notifyListeners(); + _syncNativeDebounced(); + _scheduleNotify(); } void _onModuleChanged() { - _syncNative(); - notifyListeners(); - } - - void _syncNative() { - final total = count; - if (total > 0) { - FlutterNewBadger.setBadge(total); - } else { - FlutterNewBadger.removeBadge(); - } + _syncNativeDebounced(); + _scheduleNotify(); } } diff --git a/lib/pages/home/SafeCheck/DangeCheck/safeCheck_acceptance_page.dart b/lib/pages/home/SafeCheck/DangeCheck/safeCheck_acceptance_page.dart index da375f2..941994a 100644 --- a/lib/pages/home/SafeCheck/DangeCheck/safeCheck_acceptance_page.dart +++ b/lib/pages/home/SafeCheck/DangeCheck/safeCheck_acceptance_page.dart @@ -1,33 +1,45 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/customWidget/big_video_viewer.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/full_screen_video_page.dart'; +import 'package:qhd_prevention/customWidget/photo_picker_row.dart'; +import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:qhd_prevention/pages/app/danger_wait_list_page.dart'; import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/services/auth_service.dart'; import 'package:qhd_prevention/tools/tools.dart'; import 'dart:convert'; import 'package:video_player/video_player.dart'; - - class SafecheckAcceptancePage extends StatefulWidget { - const SafecheckAcceptancePage(this.dangerType, this.item, {Key? key}) : super(key: key); - + const SafecheckAcceptancePage(this.dangerType, this.item, {Key? key}) + : super(key: key); final DangerType dangerType; final item; @override - _SafecheckAcceptancePageState createState() => _SafecheckAcceptancePageState(); + _SafecheckAcceptancePageState createState() => + _SafecheckAcceptancePageState(); } class _SafecheckAcceptancePageState extends State { late Map pd = {}; late Map hs = {}; + late Map form = { + 'FINAL_CHECK': '1', + 'FINAL_CHECKTIME': '', + 'FINAL_CHECKDESCR': '', + }; + List imgList = []; + List files = []; List files2 = []; List files4 = []; @@ -37,7 +49,6 @@ class _SafecheckAcceptancePageState extends State { List checkList = []; List files7 = []; - bool modalShow = false; String videoSrc = ""; VideoPlayerController? _videoController; @@ -45,9 +56,9 @@ class _SafecheckAcceptancePageState extends State { @override void initState() { super.initState(); - if("2"==widget.item['HIDDEN_RISKSTANDARD']){ + if ("2" == widget.item['HIDDEN_RISKSTANDARD']) { getDataTwo(); - }else { + } else { getData(); } } @@ -62,7 +73,6 @@ class _SafecheckAcceptancePageState extends State { try { final data = await ApiService.getDangerDetail(widget.item['HIDDEN_ID']); if (data['result'] == 'success') { - setState(() { pd = data['pd']; hs = data['hs'] ?? {}; @@ -91,16 +101,15 @@ class _SafecheckAcceptancePageState extends State { } files6 = data['yImgs'] ?? []; checkList = data['checkList'] ?? []; - if(checkList.isNotEmpty) { + if (checkList.isNotEmpty) { for (var img in checkList[0]['cImgs']) { files7.add(img["FILEPATH"]); } } }); - }else{ + } else { getDataTwo(); } - } catch (e) { print('Error fetching data: $e'); } @@ -108,9 +117,10 @@ class _SafecheckAcceptancePageState extends State { Future getDataTwo() async { try { - final data = await ApiService.getDangerDetailTwo(widget.item['HIDDEN_ID']); + final data = await ApiService.getDangerDetailTwo( + widget.item['HIDDEN_ID'], + ); if (data['result'] == 'success') { - setState(() { pd = data['pd']; hs = data['hs'] ?? {}; @@ -140,24 +150,21 @@ class _SafecheckAcceptancePageState extends State { files6 = data['yImgs'] ?? []; checkList = data['checkList'] ?? []; - if(checkList.isNotEmpty) { + if (checkList.isNotEmpty) { for (var img in checkList[0]['cImgs']) { files7.add(img["FILEPATH"]); } } }); } - } catch (e) { print('Error fetching data: $e'); } } - - Widget _buildInfoItem(String title, String value) { return Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 10), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -168,347 +175,648 @@ class _SafecheckAcceptancePageState extends State { style: const TextStyle(fontWeight: FontWeight.bold), ), ), - Expanded(child: Text(value,textAlign: TextAlign.right,)), + Expanded(child: Text(value, textAlign: TextAlign.right)), ], ), ); } + Widget safeCheckWidget() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 10, left: 10, right: 10), + child: Row( + children: [ + Container(width: 3, height: 15, color: Colors.blue), + const SizedBox(width: 8), + Text( + "安全检查验收", + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ListItemFactory.createYesNoSection( + horizontalPadding: 0, + verticalPadding: 0, + title: '是否合格', + yesLabel: '是', + noLabel: '否', + isRequired: true, + groupValue: form['FINAL_CHECK'] == '1' ? true : false, + onChanged: (val) { + setState(() { + form['FINAL_CHECK'] = val ? '1' : '2'; + }); + }, + ), + // const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + Divider(height: 1), + ItemListWidget.multiLineTitleTextField( + label: '验收描述', + isEditable: true, + hintText: '请输入验收描述', + text: form['FINAL_CHECKDESCR'] ?? '', + onChanged: (v) { + setState(() { + form['FINAL_CHECKDESCR'] = v; + }); + }, + ), + Divider(height: 1), + ItemListWidget.selectableLineTitleTextRightButton( + label: '验收日期', + isEditable: true, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.date, + context, + allowPast: false, + ); + if (picked != null) { + setState(() { + form['FINAL_CHECKTIME'] = DateFormat( + 'yyyy-MM-dd', + ).format(picked); + }); + } + }, + text: form['FINAL_CHECKTIME'] ?? '', + ), + Divider(height: 1), + ItemListWidget.itemContainer( + horizontal: 6, + RepairedPhotoSection( + title: '验收图片', + maxCount: 4, + isRequired: true, + mediaType: MediaType.image, + onChanged: + (files) => setState(() { + imgList.clear(); + for(int i=0;i _submit() async { + final textRules = >[ + {'value': form['FINAL_CHECKDESCR'], 'message': '请输入验收描述'}, + {'value': form['FINAL_CHECKTIME'], 'message': '请选择验收日期'}, + ]; + for (var rule in textRules) { + if ((rule['value'] as String).isEmpty) { + ToastUtil.showNormal(context, rule['message']); + return; + } + } + if (imgList.isEmpty) { + ToastUtil.showNormal(context, '请上传验收照片'); + return; + } + LoadingDialogHelper.show(); + form['HIDDEN_ID'] = widget.item['HIDDEN_ID']; + form['INSPECTION_ID'] = widget.item['INSPECTION_ID']; + form['FINAL_CHECKOR'] = SessionService.instance.loginUserId; + final result = await ApiService.safeCheckDangerAcceptanceSubmit(form); + try { + if (result['result'] == 'success') { + for (String p in imgList) { + final upResult = await ApiService.addNormalImgFiles(p, { + 'TYPE': '50', + 'FOREIGN_KEY': widget.item['HIDDEN_ID'], + }); + if (FormUtils.hasValue(upResult, 'network_error')) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '上传文件出错'); + return; + } + ToastUtil.showNormal(context, '验收成功'); + + Navigator.of(context).pop(); + LoadingDialogHelper.hide(); + } + }else{ + ToastUtil.showNormal(context, result['msg'] ?? '提交失败'); + LoadingDialogHelper.hide(); + + } + } catch (e) { + ToastUtil.showNormal(context, '提交失败'); + LoadingDialogHelper.hide(); + } + } + @override Widget build(BuildContext context) { return Scaffold( appBar: MyAppbar(title: widget.dangerType.detailTitle), - body: pd.isEmpty - ? const Center(child: CircularProgressIndicator()) - : LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: Padding( - padding: const EdgeInsets.all(10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Card( - color: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildInfoItem('隐患描述', pd['HIDDENDESCR'] ?? ''), - Divider(height: 1), - // 隐患来源 - _buildInfoItem('隐患来源', _getSourceText(pd['SOURCE'])), - Divider(height: 1), - // 条件渲染部分 - if (pd['SOURCE'] == '2') ...[ - _buildInfoItem('风险点(单元)', pd['RISK_UNIT'] ?? ''), - Divider(height: 1), - _buildInfoItem('辨识部位', pd['IDENTIFICATION'] ?? ''), - Divider(height: 1), - _buildInfoItem('存在风险', pd['RISK_DESCR'] ?? ''), - Divider(height: 1), - _buildInfoItem('风险分级', pd['LEVEL'] ?? ''), - Divider(height: 1), - _buildInfoItem('检查内容', pd['CHECK_CONTENT'] ?? ''), - Divider(height: 1), - ], - - _buildInfoItem('隐患部位', pd['HIDDENPART'] ?? ''), - Divider(height: 1), - _buildInfoItem('发现人', pd['CREATORNAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('发现时间', pd['CREATTIME'] ?? ''), - Divider(height: 1), - - if (pd['HIDDEN_CATEGORY']?.isNotEmpty == true) - _buildInfoItem('隐患类别', pd['HIDDEN_CATEGORY_NAME'] ?? ''), - - _buildInfoItem('隐患类型', pd['HIDDENTYPE_NAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('整改类型', _getRectificationType(pd['RECTIFICATIONTYPE'])), - - if (pd['RECTIFICATIONTYPE'] == '2') - _buildInfoItem('整改期限', pd['RECTIFICATIONDEADLINE'] ?? ''), - Divider(height: 1), - // 隐患照片 - // const Text('隐患照片', style: TextStyle(fontWeight: FontWeight.bold)), - // _buildImageGrid(files, onTap: (index) => _showImageGallery(files, index)), - ListItemFactory.createTextImageItem( - text: "隐患照片", - imageUrls: files, - horizontalPadding:10, - onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl:ApiService.baseImgPath + files[index]), - context, - ); - }, - ), - - // 隐患视频 - if (videoList.isNotEmpty) ...[ - SizedBox(height: 10), - Padding( - padding: EdgeInsets.only(left: 10,right: 10), - child: Text('隐患视频', style: TextStyle(fontWeight: FontWeight.bold)), - - ), - - GestureDetector( - onTap: () { - showDialog( - context: context, - barrierColor: Colors.black54, - builder: (_) => VideoPlayerPopup(videoUrl: ApiService.baseImgPath + videoList[0]['FILEPATH']), - ); - - // present( - // BigVideoViewer(videoUrl:ApiService.baseImgPath + videoList[0]['FILEPATH']), - // context, - // ); - }, - // => _playVideo(ApiService.baseImgPath + videoList[0]['FILEPATH']), - child: Image.asset( - 'assets/image/videostart.png', // 替换为你的视频占位图 - color: Colors.blue, - width: 120, - height: 120, - ), - ), - ], - - - ], + body: + pd.isEmpty + ? const Center(child: CircularProgressIndicator()) + : LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, ), - ), - - - - - - // 整改信息部分 - if (pd['STATE'] != null && int.parse(pd['STATE']) >= 2 && int.parse(pd['STATE']) <= 4) ...[ - SizedBox(height: 10,), - // const Divider(height: 10,color: Colors.grey,), - Card( - color: Colors.white, + child: Padding( + padding: const EdgeInsets.all(10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: EdgeInsets.only(top: 10,left: 10,right: 10), - child: Row( - children: [ - Container(width: 3, height: 15, color: Colors.blue), - const SizedBox(width: 8), - Text( - "整改信息", - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), - ], - ), - ), - - - - // const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - Divider(height: 1), - _buildInfoItem('整改描述', pd['RECTIFYDESCR'] ?? ''), - Divider(height: 1), - _buildInfoItem('整改部门', pd['RECTIFICATIONDEPTNAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('整改人', pd['RECTIFICATIONORNAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('整改时间', pd['RECTIFICATIONTIME'] ?? ''), - Divider(height: 1), - // const Text('整改后图片', style: TextStyle(fontWeight: FontWeight.bold)), - // _buildImageGrid(files2, onTap: (index) => _showImageGallery(files2, index)), - ListItemFactory.createTextImageItem( - text: "整改后图片", - imageUrls: files2, - horizontalPadding: 10, - onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl: ApiService.baseImgPath +files2[index]), - context, - ); - }, - ), - - - Divider(height: 1), - _buildInfoItem('整改方案', pd['HAVESCHEME']=="1" ? '有':'无'), - Divider(height: 1), - if(pd['HAVESCHEME']=="1") - Column( + Card( + color: Colors.white, + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildInfoItem('排查日期', hs['SCREENINGDATE'] ?? ''), + _buildInfoItem( + '隐患描述', + pd['HIDDENDESCR'] ?? '', + ), Divider(height: 1), - _buildInfoItem('隐患清单', hs['LISTNAME'] ?? ''), + // 隐患来源 + _buildInfoItem( + '隐患来源', + _getSourceText(pd['SOURCE']), + ), Divider(height: 1), - _buildInfoItem('治理标准要求', hs['GOVERNSTANDARDS'] ?? ''), + // 条件渲染部分 + if (pd['SOURCE'] == '2') ...[ + _buildInfoItem( + '风险点(单元)', + pd['RISK_UNIT'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '辨识部位', + pd['IDENTIFICATION'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '存在风险', + pd['RISK_DESCR'] ?? '', + ), + Divider(height: 1), + _buildInfoItem('风险分级', pd['LEVEL'] ?? ''), + Divider(height: 1), + _buildInfoItem( + '检查内容', + pd['CHECK_CONTENT'] ?? '', + ), + Divider(height: 1), + ], + + _buildInfoItem( + '隐患部位', + pd['HIDDENPART'] ?? '', + ), Divider(height: 1), - _buildInfoItem('治理方法', hs['GOVERNMETHOD'] ?? ''), + _buildInfoItem( + '发现人', + pd['CREATORNAME'] ?? '', + ), Divider(height: 1), - _buildInfoItem('经费和物资的落实', hs['EXPENDITURE'] ?? ''), + _buildInfoItem('发现时间', pd['CREATTIME'] ?? ''), Divider(height: 1), - _buildInfoItem('负责治理人员', hs['PRINCIPAL'] ?? ''), + + if (pd['HIDDEN_CATEGORY']?.isNotEmpty == true) + _buildInfoItem( + '隐患类别', + pd['HIDDEN_CATEGORY_NAME'] ?? '', + ), + + _buildInfoItem( + '隐患类型', + pd['HIDDENTYPE_NAME'] ?? '', + ), Divider(height: 1), - _buildInfoItem('工时安排', hs['PROGRAMMING'] ?? ''), - Divider(height: 1), - _buildInfoItem('时限要求', hs['TIMELIMITFOR'] ?? ''), - Divider(height: 1), - _buildInfoItem('工作要求', hs['JOBREQUIREMENT'] ?? ''), - Divider(height: 1), - _buildInfoItem('其他事项', hs['OTHERBUSINESS'] ?? ''), + _buildInfoItem( + '整改类型', + _getRectificationType( + pd['RECTIFICATIONTYPE'], + ), + ), + + if (pd['RECTIFICATIONTYPE'] == '2') + _buildInfoItem( + '整改期限', + pd['RECTIFICATIONDEADLINE'] ?? '', + ), Divider(height: 1), + // 隐患照片 + // const Text('隐患照片', style: TextStyle(fontWeight: FontWeight.bold)), + // _buildImageGrid(files, onTap: (index) => _showImageGallery(files, index)), ListItemFactory.createTextImageItem( - text: "方案图片", - imageUrls: files4, + text: "隐患照片", + imageUrls: files, horizontalPadding: 10, onImageTapped: (index) { presentOpaque( - SingleImageViewer(imageUrl: ApiService.baseImgPath +files2[index]), + SingleImageViewer( + imageUrl: + ApiService.baseImgPath + + files[index], + ), context, ); }, ), + // 隐患视频 + if (videoList.isNotEmpty) ...[ + SizedBox(height: 10), + Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: Text( + '隐患视频', + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), - ], - ), + GestureDetector( + onTap: () { + showDialog( + context: context, + barrierColor: Colors.black54, + builder: + (_) => VideoPlayerPopup( + videoUrl: + ApiService.baseImgPath + + videoList[0]['FILEPATH'], + ), + ); - Divider(height: 1), - _buildInfoItem('整改计划', pd['HAVEPLAN']=="1" ? '有':'无'), - Divider(height: 1), - if(pd['HAVEPLAN']=="1") - ListItemFactory.createTextImageItem( - text: "计划图片", - imageUrls: files2, - horizontalPadding: 10, - onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl: ApiService.baseImgPath +files2[index]), - context, - ); - }, - ), - ], - ), - ), - // ... 其他整改信息字段 - ], - - - - // 验收信息部分 - if ((6==widget.dangerType.index||1==widget.dangerType.index||0==widget.dangerType.index)&&checkList.isNotEmpty) ...[ - // const Divider(height: 10,color: Colors.grey,), - SizedBox(height: 10,), - Card( - color: Colors.white, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Padding( - padding: EdgeInsets.only(top: 10,left: 10,right: 10), - child: - Row( - children: [ - Container(width: 3, height: 15, color: Colors.blue), - const SizedBox(width: 8), - Text( - "验收信息", - style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), + // present( + // BigVideoViewer(videoUrl:ApiService.baseImgPath + videoList[0]['FILEPATH']), + // context, + // ); + }, + // => _playVideo(ApiService.baseImgPath + videoList[0]['FILEPATH']), + child: Image.asset( + 'assets/image/videostart.png', // 替换为你的视频占位图 + color: Colors.blue, + width: 120, + height: 120, + ), + ), + ], ], ), ), + // 整改信息部分 + if (pd['STATE'] != null && + int.parse(pd['STATE']) >= 2 && + int.parse(pd['STATE']) <= 4) ...[ + SizedBox(height: 10), + // const Divider(height: 10,color: Colors.grey,), + Card( + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + top: 10, + left: 10, + right: 10, + ), + child: Row( + children: [ + Container( + width: 3, + height: 15, + color: Colors.blue, + ), + const SizedBox(width: 8), + Text( + "整改信息", + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), - // const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), - Divider(height: 1), - _buildInfoItem('验收描述', checkList[0]['CHECKDESCR'] ?? ''), - Divider(height: 1), - _buildInfoItem('是否合格',_getText (checkList[0]['STATUS'] )), - Divider(height: 1), - _buildInfoItem('验收部门', checkList[0]['CHECKDEPTNAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('验收部门负责人', checkList[0]['CHECKORNAME'] ?? ''), - Divider(height: 1), - _buildInfoItem('验收时间', checkList[0]['CHECK_TIME'] ?? ''), - Divider(height: 1), - // const Text('整改后图片', style: TextStyle(fontWeight: FontWeight.bold)), - // _buildImageGrid(files2, onTap: (index) => _showImageGallery(files2, index)), - ListItemFactory.createTextImageItem( - text: "验收图片", - imageUrls: files7, - horizontalPadding: 10, - onImageTapped: (index) { - presentOpaque( - SingleImageViewer(imageUrl: ApiService.baseImgPath +files5[index]), - context, - ); + // const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + Divider(height: 1), + _buildInfoItem( + '整改描述', + pd['RECTIFYDESCR'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '整改部门', + pd['RECTIFICATIONDEPTNAME'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '整改人', + pd['RECTIFICATIONORNAME'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '整改时间', + pd['RECTIFICATIONTIME'] ?? '', + ), + Divider(height: 1), + // const Text('整改后图片', style: TextStyle(fontWeight: FontWeight.bold)), + // _buildImageGrid(files2, onTap: (index) => _showImageGallery(files2, index)), + ListItemFactory.createTextImageItem( + text: "整改后图片", + imageUrls: files2, + horizontalPadding: 10, + onImageTapped: (index) { + presentOpaque( + SingleImageViewer( + imageUrl: + ApiService.baseImgPath + + files2[index], + ), + context, + ); + }, + ), + + Divider(height: 1), + _buildInfoItem( + '整改方案', + pd['HAVESCHEME'] == "1" ? '有' : '无', + ), + Divider(height: 1), + if (pd['HAVESCHEME'] == "1") + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + _buildInfoItem( + '排查日期', + hs['SCREENINGDATE'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '隐患清单', + hs['LISTNAME'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '治理标准要求', + hs['GOVERNSTANDARDS'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '治理方法', + hs['GOVERNMETHOD'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '经费和物资的落实', + hs['EXPENDITURE'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '负责治理人员', + hs['PRINCIPAL'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '工时安排', + hs['PROGRAMMING'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '时限要求', + hs['TIMELIMITFOR'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '工作要求', + hs['JOBREQUIREMENT'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '其他事项', + hs['OTHERBUSINESS'] ?? '', + ), + Divider(height: 1), + ListItemFactory.createTextImageItem( + text: "方案图片", + imageUrls: files4, + horizontalPadding: 10, + onImageTapped: (index) { + presentOpaque( + SingleImageViewer( + imageUrl: + ApiService.baseImgPath + + files2[index], + ), + context, + ); + }, + ), + ], + ), + + Divider(height: 1), + _buildInfoItem( + '整改计划', + pd['HAVEPLAN'] == "1" ? '有' : '无', + ), + Divider(height: 1), + if (pd['HAVEPLAN'] == "1") + ListItemFactory.createTextImageItem( + text: "计划图片", + imageUrls: files5, + horizontalPadding: 10, + onImageTapped: (index) { + presentOpaque( + SingleImageViewer( + imageUrl: + ApiService.baseImgPath + + files5[index], + ), + context, + ); + }, + ), + ], + ), + ), + // ... 其他整改信息字段 + ], + + // 验收信息部分 + if (pd['STATE'] == '4') ...[ + // const Divider(height: 10,color: Colors.grey,), + SizedBox(height: 10), + Card( + color: Colors.white, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only( + top: 10, + left: 10, + right: 10, + ), + child: Row( + children: [ + Container( + width: 3, + height: 15, + color: Colors.blue, + ), + const SizedBox(width: 8), + Text( + "验收信息", + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + + // const Text('整改信息', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + Divider(height: 1), + _buildInfoItem( + '验收描述', + checkList[0]['CHECKDESCR'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '是否合格', + _getText(checkList[0]['STATUS']), + ), + Divider(height: 1), + _buildInfoItem( + '验收部门', + checkList[0]['CHECKDEPTNAME'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '验收部门负责人', + checkList[0]['CHECKORNAME'] ?? '', + ), + Divider(height: 1), + _buildInfoItem( + '验收时间', + checkList[0]['CHECK_TIME'] ?? '', + ), + Divider(height: 1), + // const Text('整改后图片', style: TextStyle(fontWeight: FontWeight.bold)), + // _buildImageGrid(files2, onTap: (index) => _showImageGallery(files2, index)), + ListItemFactory.createTextImageItem( + text: "验收图片", + imageUrls: files7, + horizontalPadding: 10, + onImageTapped: (index) { + presentOpaque( + SingleImageViewer( + imageUrl: + ApiService.baseImgPath + + files5[index], + ), + context, + ); + }, + ), + ], + ), + ), + ], + const SizedBox(height: 10), + ItemListWidget.itemContainer( + horizontal: 0, + safeCheckWidget(), + ), + + + SizedBox(height: 20), + CustomButton( + onPressed: () { + _submit(); }, + text: "提交", + backgroundColor: Colors.blue, + ), + // 添加底部安全区域间距 + SizedBox( + height: + MediaQuery.of(context).padding.bottom + 20, ), ], ), ), - ], - - - // 添加底部安全区域间距 - SizedBox(height: MediaQuery.of(context).padding.bottom + 20), - ], - ), + ), + ); + }, ), - ), - ); - }, - ), ); } String _getText(String source) { - if(source.isNotEmpty){ - if(source=="1"){ + if (source.isNotEmpty) { + if (source == "1") { return "是"; - }else{ + } else { return "否"; } - }else{ + } else { return ""; } - } - String _getSourceText(String? source) { - switch (source) { - case '1': return '隐患快报'; - case '2': return '隐患排查清单检查'; - case '3': return '标准排查清单检查'; - case '4': return '专项检查'; - case '5': return '安全检查'; - case '6': return 'NFC设备巡检'; + case '1': + return '隐患快报'; + case '2': + return '隐患排查清单检查'; + case '3': + return '标准排查清单检查'; + case '4': + return '专项检查'; + case '5': + return '安全检查'; + case '6': + return 'NFC设备巡检'; - default: return ''; + default: + return ''; } } String _getRectificationType(String? type) { switch (type) { - case '1': return '立即整改'; - case '2': return '限期整改'; - default: return ''; + case '1': + return '立即整改'; + case '2': + return '限期整改'; + default: + return ''; } } } - diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index 0595744..311171d 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -334,9 +334,9 @@ class HomePageState extends State { final data = await ApiService.getWork(); final hidCount = data['hidCount'] as Map? ?? {}; - // 告知BadgeManager去更新“安全巡检”和“八项作业”角标 - BadgeManager().updateEnvInspectCount(); - BadgeManager().updateEightWorkCount(); + // // 告知BadgeManager去更新“安全巡检”和“八项作业”角标 + // BadgeManager().updateEnvInspectCount(); + // BadgeManager().updateEightWorkCount(); // 拉取其他数据 final results = await Future.wait([ diff --git a/lib/pages/home/tap/item_list_widget.dart b/lib/pages/home/tap/item_list_widget.dart index 41a2f0f..7b551b6 100644 --- a/lib/pages/home/tap/item_list_widget.dart +++ b/lib/pages/home/tap/item_list_widget.dart @@ -709,6 +709,7 @@ class ItemListWidget { children: [ // 标题部分 + if (title.isNotEmpty) Padding( padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), child: Text( @@ -862,15 +863,95 @@ class ItemListWidget { ), ); } + /// 多行垂直布局: + /// 标题、图片、说明、签字信息 + static Widget mulColumnRowTitleAndImages({ + required String title, // 第一行标题 + required List? imageUrls, + required String text, // 描述 + required List? signUrls, /// 签字 + required List? signTimes, /// 签字时间 - static Widget itemContainer(Widget child, {double horizontal = horizontal_inset}) { + double row2Height = 80, // 第二行高度 + double fontSize = 14, // 字体大小 + void Function(String)? onTapCallBack, + bool isRequired = true, + }) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + + children: [ + // 标题部分 + Padding( + padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset), + child: Text( + title, + style: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + ), + ), + ), + + // 图片横向滚动区域 + SizedBox( + height: 80, // 图片区域固定高度 + child: ListView.builder( + padding: EdgeInsets.symmetric(horizontal: 12), + scrollDirection: Axis.horizontal, + itemCount: imageUrls?.length, + itemBuilder: (context, index) { + 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] ?? ''}'); + }, + 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(), + ); + }, + ), + ) + ), + ); + }, + ), + ), + Row() + ], + ); + } + + + static Widget itemContainer(Widget child, {double horizontal = horizontal_inset, double vertical = vertical_inset}) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), - padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical_inset), + padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: child, ); } diff --git a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart index 7c1db77..99662ce 100644 --- a/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart +++ b/lib/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart @@ -1,12 +1,16 @@ import 'dart:convert'; +import 'dart:math'; +import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/customWidget/date_picker_dialog.dart'; import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart'; import 'package:qhd_prevention/tools/tools.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart'; @@ -25,7 +29,7 @@ class MeasuresListWidget extends StatelessWidget { }); /// 接口返回的原始 Map 列表 - final List> measuresList; + final List measuresList; /// 图片的基础路径 final String baseImgPath; @@ -61,9 +65,11 @@ class MeasuresListWidget extends StatelessWidget { defaultVerticalAlignment: TableCellVerticalAlignment.middle, // 或 .top / .bottom - columnWidths: const { - 0: FlexColumnWidth(3), - 1: FixedColumnWidth(100), + columnWidths: { + 0: FlexColumnWidth(10), + 1: FixedColumnWidth(210), + 2: FlexColumnWidth(20), + if (!isAllowEdit) 3: FixedColumnWidth(60), }, border: TableBorder( horizontalInside: BorderSide(color: Colors.grey.shade300), @@ -73,32 +79,57 @@ class MeasuresListWidget extends StatelessWidget { // 表头 TableRow( decoration: BoxDecoration(color: Colors.grey.shade100), - children: const [ - Padding( + 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: EdgeInsets.all(8), + padding: const EdgeInsets.all(2), child: Center( child: Text( - '操作', - style: TextStyle(fontWeight: FontWeight.bold), + 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), + ), + ), + ), ], ), // 数据行 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( @@ -106,21 +137,34 @@ class MeasuresListWidget extends StatelessWidget { 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? ?? '', - ), + // // 签名图片 + // 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, + ), + ], + ), ], ), ), @@ -163,19 +207,55 @@ class MeasuresListWidget extends StatelessWidget { : Colors.black, ), ), - - // 操作图片 - if (item.containsKey('IMG_PATH') && - (item['IMG_PATH'] as String).isNotEmpty && - isShowSign) - ..._buildImageRows( - context, - (item['IMG_PATH'] as String).split(','), - '', - ), ], ), ), + 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, + ); + }, + child: Image.network( + imageUrl, + width: 40, + height: 40, + fit: BoxFit.cover, + // 防止图片加载失败导致布局异常 + errorBuilder: + (_, __, ___) => Container( + width: 40, + height: 40, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 18, + color: Colors.grey, + ), + ), + ), + ), + ), + ); + }).toList(), + ], + ), ], ), ], @@ -265,24 +345,56 @@ class MeasuresListWidget extends StatelessWidget { BuildContext context, List paths, String time, + double right, ) { - return paths.map((p) { - return Padding( - padding: const EdgeInsets.only(top: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, // ← 这一行 + if (paths.isEmpty) return []; + const int imagesPerRow = 4; + const double imageSize = 40.0; + const double spacing = 8.0; + + // 把 paths 切成若干行(chunk) + final rows = >[]; + for (var i = 0; i < paths.length; i += imagesPerRow) { + rows.add(paths.sublist(i, min(i + imagesPerRow, paths.length))); + } + + return rows.map((rowPaths) { + return Padding( + padding: EdgeInsets.only(right: right, top: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - GestureDetector( - onTap: () { - presentOpaque( - SingleImageViewer(imageUrl: '$baseImgPath$p'), - context, - ); - }, - child: Image.network('$baseImgPath$p', width: 60, height: 60), - ), - if (time.isNotEmpty) ...[const SizedBox(width: 8), Text(time)], + for (var i = 0; i < rowPaths.length; i++) ...[ + GestureDetector( + onTap: () { + presentOpaque( + SingleImageViewer(imageUrl: '$baseImgPath${rowPaths[i]}'), + context, + ); + }, + child: Image.network( + '$baseImgPath${rowPaths[i]}', + width: imageSize, + height: imageSize, + fit: BoxFit.cover, + errorBuilder: + (_, __, ___) => Container( + width: imageSize, + height: imageSize, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 18, + color: Colors.grey, + ), + ), + ), + ), + if (i != rowPaths.length - 1) SizedBox(width: spacing), + ], + // 如果希望每行右侧也填充占位使宽度平均,可加 Expanded 占位 + // Expanded(child: SizedBox()), ], ), ); @@ -599,28 +711,31 @@ class SignaturesListWidget extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 20), child: Wrap( spacing: 8, - children: (first['IMG_PATH'] as List) - .cast() - .map((img) { - final fullUrl = '$baseImgPath$img'; - return GestureDetector( - onTap: () { - presentOpaque(SingleImageViewer(imageUrl: fullUrl), context); - }, - child: Image.network( - fullUrl, - width: 50, - height: 50, - fit: BoxFit.cover, - errorBuilder: (ctx, err, st) => Container( - width: 50, - height: 50, - color: Colors.grey[200], - child: const Icon(Icons.broken_image, size: 20), - ), - ), - ); - }).toList(), + children: + (first['IMG_PATH'] as List).cast().map((img) { + final fullUrl = '$baseImgPath$img'; + return GestureDetector( + onTap: () { + presentOpaque( + SingleImageViewer(imageUrl: fullUrl), + context, + ); + }, + child: Image.network( + fullUrl, + width: 50, + height: 50, + fit: BoxFit.cover, + errorBuilder: + (ctx, err, st) => Container( + width: 50, + height: 50, + color: Colors.grey[200], + child: const Icon(Icons.broken_image, size: 20), + ), + ), + ); + }).toList(), ), ), @@ -897,7 +1012,6 @@ class _SelectionPopupState extends State { @override Widget build(BuildContext context) { - return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), // 圆角半径 @@ -1010,7 +1124,7 @@ class _SelectionPopupState extends State { onPressed: _getData, ), ), - const SizedBox(width: 10,), + const SizedBox(width: 10), // 清空 Expanded( child: CustomButton( @@ -1042,17 +1156,28 @@ class _SelectionPopupState extends State { : item['NAME'] as String? ?? ''; final checked = value.contains(key); return CheckboxListTile( - controlAffinity: ListTileControlAffinity.leading, // <-- 把图标放左边 - contentPadding: EdgeInsets.zero, // 可选:移除左右默认 padding,使图标贴近左侧 + controlAffinity: ListTileControlAffinity.leading, + // <-- 把图标放左边 + contentPadding: EdgeInsets.zero, + // 可选:移除左右默认 padding,使图标贴近左侧 activeColor: Colors.blue, title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(key, style: TextStyle(fontSize: 15)), if (widget.type == 'assignments') ...[ - Text('作业内容: ${item['WORK_CONTENT'] ?? ''}', style: TextStyle(fontSize: 15),), - Text('作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}', style: TextStyle(fontSize: 15)), - Text('作业申请时间: ${item['CREATTIME'] ?? ''}', style: TextStyle(fontSize: 15)), + Text( + '作业内容: ${item['WORK_CONTENT'] ?? ''}', + style: TextStyle(fontSize: 15), + ), + Text( + '作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}', + style: TextStyle(fontSize: 15), + ), + Text( + '作业申请时间: ${item['CREATTIME'] ?? ''}', + style: TextStyle(fontSize: 15), + ), ], ], ), @@ -1066,7 +1191,6 @@ class _SelectionPopupState extends State { }); }, ); - }, ), ), @@ -1102,3 +1226,606 @@ class _SelectionPopupState extends State { ); } } + +/// 签字意见 +/// 显示签名/图片/时间等信息的项 +class SignItemWidget extends StatelessWidget { + const SignItemWidget({ + Key? key, + required this.signKey, + required this.nameKey, + required this.title, + required this.pd, + required this.signs, + required this.baseImgPath, + this.smallThumbSize = 50.0, + this.signImageWidth = 200.0, + this.signImageHeight = 100.0, + }) : super(key: key); + + /// signs map 中用于查找签名列表的 key + final String signKey; + + /// pd map 中用于显示右侧字段的 key + final String nameKey; + + /// 标题文本(左侧) + final String title; + + /// pd 数据(用来显示右侧信息) + final Map pd; + + /// signs 数据(包含 SIGN_PATH / SIGN_TIME / IMG_PATH 等) + final Map signs; + + /// 图片基准路径(会拼接到每个 path 之前) + final String baseImgPath; + + /// 小图(IMG_PATH)缩略图尺寸 + final double smallThumbSize; + + /// 签名图片展示尺寸(每张一行) + final double signImageWidth; + final double signImageHeight; + + @override + Widget build(BuildContext context) { + return SizedBox( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // signs 中的各项 + if (FormUtils.hasValue(signs, signKey)) ..._buildSignItems(context), + ], + ), + ); + } + + List _buildSignItems(BuildContext context) { + final list = []; + + final rawList = signs[signKey]; + if (rawList is! List) { + return list; + } + + // 聚合所有条目的签字路径和签名时间(避免为每条记录都生成一个签字行) + final List aggregatedSignPaths = []; + final List aggregatedSignTimes = []; + + // 保留原来每条记录的 IMG_PATH 行(如果你也想合并这些小图行到一行,可以改这里) + final List smallThumbRows = []; + + for (final raw in rawList) { + if (raw is! Map) continue; + final item = Map.from(raw); + + // 解析 SIGN_PATH 并聚合 + List signPaths = []; + final rawSP = + 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(); + } else if (rawSP is List) { + 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; + if (rawST is String && rawST.isNotEmpty) { + signTimes = rawST.split(','); + } else if (rawST is List) { + signTimes = rawST.cast(); + } + aggregatedSignTimes.addAll(signTimes); + + // 解析 IMG_PATH(取最多 2 张缩略图)——保持原来行为,但改成先收集 widget 再统一加入 list + final List aggregatedImgPaths = []; + + for (final raw in rawList) { + if (raw is! Map) continue; + final item = Map.from(raw); + + final rawIP = + 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), + ); + } else if (rawIP is List) { + aggregatedImgPaths.addAll( + rawIP.cast() + .map((s) => s.trim()) + .where((s) => s.isNotEmpty), + ); + } + } + + // 最终只取 2 张 + final displayImgPaths = aggregatedImgPaths.take(2).toList(); + + if (displayImgPaths.isNotEmpty) { + smallThumbRows.add( + 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), + ), + ), + ), + ), + ); + }).toList(), + ), + ), + ); + + smallThumbRows.add(const SizedBox(height: 8)); + } + } // end for + + // 先把所有小缩略图行加入(保持原来每条记录的小图显示行为) + if (smallThumbRows.isNotEmpty) { + list.addAll(smallThumbRows); + } + + // 聚合后的最后一个签名时间(如果没有则为空串) + final lastTime = aggregatedSignTimes.isNotEmpty + ? aggregatedSignTimes.last.trim() + : ''; + + // 每张图片的尺寸与间距(保持你原来的数值) + const double thumbSize = 60.0; + const double gapBetweenThumbs = 8.0; + const double timeBoxWidth = 120.0; // 时间文本固定宽度(可调整) + + // 单独渲染一行:签字: [多个签字图片水平滚动] 时间(只会渲染一次) + // 单独渲染一行:签字: [多个签字图片多行显示(Wrap)] 时间(只会渲染一次,超过宽度自动换行) + list.add( + Padding( + padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10), + child: SizedBox( + width: double.infinity, + child: LayoutBuilder( + builder: (ctx, constraints) { + // 图片区域最大宽度 = 可用宽度 - 时间宽度 - 间隔 + final double maxImageAreaWidth = + (constraints.maxWidth - timeBoxWidth - 8) + .clamp(0.0, constraints.maxWidth); + + return Align( + alignment: Alignment.bottomRight, + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, // 底部对齐 + children: [ + const Text('签字:', style: TextStyle(fontSize: 13)), + + // 图片区域(限制最大宽度,使用 Wrap 自动换行,不滚动) + if (aggregatedSignPaths.isNotEmpty) + ConstrainedBox( + constraints: BoxConstraints(maxWidth: maxImageAreaWidth), + child: Padding( + padding: const EdgeInsets.only(left: 6.0), + child: Wrap( + spacing: gapBetweenThumbs, + 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.cover, + errorBuilder: (_, __, ___) => Container( + width: thumbSize, + height: thumbSize, + color: Colors.grey.shade200, + child: const Icon( + Icons.broken_image, + size: 24, + ), + ), + ), + ), + ); + }).toList(), + ), + ), + ), + + // 图片与时间之间的小间隔(仅在有图片时展示) + if (aggregatedSignPaths.isNotEmpty) const SizedBox(width: 8), + + // 时间文本(始终固定在最右侧并底部对齐) + SizedBox( + width: timeBoxWidth, + child: Text( + lastTime, + textAlign: TextAlign.right, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 13, + color: Colors.black87, + ), + ), + ), + ], + ), + ); + }, + ), + ), + ), + ); + + + return list; + } +} +/// 签名意见回显 +class ConfirmWithSignWidget extends StatelessWidget { + const ConfirmWithSignWidget({ + Key? key, + required this.signs, + required this.pd, + required this.baseImgPath, + // 可定制的 key 与标题,保持与你原来的调用一致为默认值 + required this.sectionKey, // 'CONFIRM', + this.descrField = 'DESCR', + this.imgsKey = '', + this.contentKey = '', + required this.nameKey, // 'CONFIRM_USER_NAME', + required this.headerTitle, // '作业负责人意见', + required this.roleTitle, // '作业负责人', + }) : super(key: key); + + // 允许外部传入 null(但构建内部会降级为 {},避免空异常) + final Map? signs; + final Map? pd; + final String baseImgPath; + + /// signs map 中用来查找意见与签名的 key(例如 'CONFIRM') + final String sectionKey; + + /// 意见文本字段名(通常 'DESCR') + final String descrField; + + /// 取pd中指定图片信息(可选) + final String imgsKey; + + /// 取pd中指定描述信息(可选) + final String contentKey; + + /// pd map 中显示在 header 右侧的字段 + final String nameKey; + + /// 顶部卡片左侧标题文字(例如 '作业负责人意见') + final String headerTitle; + + /// 传给 SignItemWidget 的 title(例如 '作业负责人') + final String roleTitle; + + @override + Widget build(BuildContext context) { + // 容错:如果传入为 null,降级成空 Map,后续访问安全 + final safeSigns = signs ?? {}; + final safePd = pd ?? {}; + + // 如果没有该 section 则不渲染 + 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) { + final first = sectionList[0] as Map; + final dynamic ds = first[descrField]; + if (ds != null) { + descrText = ds.toString(); + } + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // 意见卡片(复用你之前的 _itemContainer 风格) + Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题行 + Padding( + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 10, + ), + child: Row( + children: [ + Expanded(child: ListItemFactory.headerTitle('$headerTitle:')), + const SizedBox(), + // 仅当 pd 中存在 nameKey 且不为空时显示 + // if (FormUtils.hasValue(safePd, nameKey)) + // Text( + // (safePd[nameKey] ?? '').toString(), + // style: const TextStyle(fontSize: 14), + // ), + ], + ), + ), + + // 描述内容(当 descrText 有意义才显示) + if (descrText.isNotEmpty && descrText != '无') + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + child: Text( + descrText, + maxLines: 100, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 13), + ), + ), + + // 如果 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(); + } + }), + + // 如果 contentKey 有值并且 pd 中存在则显示(类型转换为字符串以防出错) + if (contentKey.isNotEmpty && FormUtils.hasValue(safePd, contentKey)) + ItemListWidget.itemContainer( + Text( + (safePd[contentKey] ?? '').toString(), + style: const TextStyle(fontSize: 14, color: Colors.black54), + ), + ), + + // SignItemWidget 需要非空 Map 参数,传入 safeSigns / safePd(即使为空 Map 也不会崩溃) + SignItemWidget( + signKey: sectionKey, + nameKey: nameKey, + title: roleTitle, + pd: safePd, + signs: safeSigns, + baseImgPath: baseImgPath, + ), + ], + ), + ), + ], + ); + } +} + +/// 单行显示标题+签字/电子姓名 +class SignRowImageTitle extends StatelessWidget { + const SignRowImageTitle({ + Key? key, + required this.label, + required this.signKey, + required this.signs, // 可以为 null,内部会容错 + this.fontSize = 14, + this.text = '', + this.imageSize = 40, + this.gap = 8.0, + }) : super(key: key); + + final String label; + final String signKey; + final Map? signs; // 允许为 null + final double fontSize; + final String text; + final double imageSize; + final double gap; + + List _extractSignPaths() { + final List imagePaths = []; + final safeSigns = signs ?? {}; + + final rawList = FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null; + + if (rawList == null) return imagePaths; + + // rawList 可能是 List、String 等 —— 以 List 为主处理,兼容其他类型 + if (rawList is List) { + for (final raw in rawList) { + if (raw is! Map) continue; + final item = Map.from(raw); + + 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() + .where((e) => e != null) + .map((e) => e.toString().trim()) + .where((s) => s.isNotEmpty), + ); + } + } + } else if (rawList is String) { + // 有些后端直接把路径以逗号连接成字符串返回 + imagePaths.addAll( + rawList.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty), + ); + } else if (rawList is Map) { + // 若误传了单条 Map,也尝试从中抽取 SIGN_PATH + 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() + .where((e) => e != null) + .map((e) => e.toString().trim()) + .where((s) => s.isNotEmpty), + ); + } + } + + // 可选:去重并保持顺序 + final seen = {}; + final deduped = []; + for (final p in imagePaths) { + if (!seen.contains(p)) { + seen.add(p); + deduped.add(p); + } + } + + return deduped; + } + + void _openPreview(BuildContext context, String fullUrl) { + try { + presentOpaque(SingleImageViewer(imageUrl: fullUrl), context); + return; + } catch (_) { + } + } + + @override + Widget build(BuildContext context) { + final imagePaths = _extractSignPaths(); + + return Container( + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 12, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 左侧标题 + Text( + label, + style: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + ), + ), + + // const SizedBox(width: 12), + // 右侧:优先显示图片(若无图片则显示 text;无 text 则不显示) + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (imagePaths.isNotEmpty) + Align( + alignment: Alignment.centerRight, + child: Wrap( + spacing: gap, + 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), + ), + ), + ), + ); + }).toList(), + ), + ) + else if (text.isNotEmpty) + Text( + text, + textAlign: TextAlign.right, + style: TextStyle(fontSize: 14, color: Colors.black54), + ) + else + const SizedBox.shrink(), + ], + ), + ), + ], + ), + ); + } +} + + 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 c45e870..f29ed32 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 @@ -5,7 +5,7 @@ import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用明细表单组件(支持编辑/只读) class HotWorkDetailFormWidget extends StatefulWidget { @@ -15,17 +15,21 @@ class HotWorkDetailFormWidget extends StatefulWidget { final VoidCallback onChooseHotworkUser; final VoidCallback onAnalyzeTap; - - // 新增 -/// 选择摄像头 - final VoidCallback? onChooseVideoManager;/// 承包商 + /// 选择摄像头 + final VoidCallback? onChooseVideoManager; + + /// 承包商 final VoidCallback? onContractorHandle; + /// 作业区域 final VoidCallback? onWorkAreaHandle; + /// 作业地点经纬度 final VoidCallback? onWorkAreaLocationHandle; + /// 其他签字数据 + final signs; /// 编辑模式下需提供以下控制器,非编辑可不传 final TextEditingController? contentController; @@ -42,6 +46,7 @@ class HotWorkDetailFormWidget extends StatefulWidget { required this.onChooseLevel, required this.onChooseHotworkUser, required this.onAnalyzeTap, + /// 新增 this.onChooseVideoManager, this.onContractorHandle, @@ -54,7 +59,7 @@ class HotWorkDetailFormWidget extends StatefulWidget { this.hotworkPersonController, this.relatedController, this.riskController, - + this.signs = null, }) : assert( !isEditable || (contentController != null && @@ -74,10 +79,12 @@ class HotWorkDetailFormWidget extends StatefulWidget { class _HotWorkDetailFormWidgetState extends State { bool IS_CONTRACTOR_WORK = false; + @override Widget build(BuildContext context) { if (FormUtils.hasValue(widget.pd, 'LATITUDE')) { - widget.pd['LATITUDE_LONGITUDE'] = '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map + widget.pd['LATITUDE_LONGITUDE'] = + '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map } final pd = widget.pd; @@ -90,8 +97,16 @@ class _HotWorkDetailFormWidgetState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + if (FormUtils.hasValue(pd, 'CHECK_NO') && !widget.isEditable) ...[ + ItemListWidget.singleLineTitleText( + label: '编号:', + isEditable: false, + text: pd['CHECK_NO'] ?? '', + ), + const Divider(), + ], ItemListWidget.singleLineTitleText( - label: '申请单位:', + label: '作业申请单位:', isEditable: false, text: pd['APPLY_DEPARTMENT_NAME'] ?? '', ), @@ -101,12 +116,12 @@ class _HotWorkDetailFormWidgetState extends State { isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), - if (FormUtils.hasValue(pd, 'CHECK_NO')) ...[ + if (FormUtils.hasValue(pd, 'CREATTIME') && !widget.isEditable) ...[ const Divider(), ItemListWidget.singleLineTitleText( - label: '编号:', + label: '作业申请时间:', isEditable: false, - text: pd['CHECK_NO'] ?? '', + text: pd['CREATTIME'] ?? '', ), ], const Divider(), @@ -139,22 +154,37 @@ class _HotWorkDetailFormWidgetState extends State { controller: widget.methodController, text: pd['WORK_FUNCTION'] ?? '', ), - if (pd['WORK_START_DATE']?.toString().isNotEmpty == true) ...[ - const Divider(), - ItemListWidget.singleLineTitleText( - label: '动火作业实施时间:', - isEditable: false, - text: '${pd['WORK_START_DATE']} 至 ${pd['WORK_END_DATE'] ?? '--'}', - ), - ], + const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( + ItemListWidget.twoRowButtonTitleText( + buttonText: '选择', isRequired: widget.isEditable, label: '动火人及证书编号:', + isInput: false, isEditable: widget.isEditable, - text:pd['WORK_USER'] ?? '', + text: pd['WORK_USER'] ?? '请选择动火人及证书编号', + hintText: '请选择动火人及证书编号', onTap: widget.onChooseHotworkUser, ), + if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME') && + !widget.isEditable) ...[ + const Divider(), + ItemListWidget.singleLineTitleText( + label: '作业单位:', + isEditable: false, + text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + ), + ], + if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && + !widget.isEditable) ...[ + const Divider(), + SignRowImageTitle( + label: '作业负责人:', + signKey: 'CONFIRM', + signs: widget.signs, + text: pd['CONFIRM_USER_NAME'] ?? '', + ), + ], const Divider(), ItemListWidget.twoRowButtonTitleText( label: '关联其他特殊作业及安全作业票编号', @@ -206,75 +236,98 @@ class _HotWorkDetailFormWidgetState extends State { controller: widget.riskController, text: pd['RISK_IDENTIFICATION'] ?? '', ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '作业视频监控:', - isClean: widget.isEditable && (pd['WORK_LEVEL'] == '一级' || pd['WORK_LEVEL'] == '二级'), - cleanText: '清除监控', - isRequired: pd['WORK_LEVEL'] == '特级', - isEditable: widget.isEditable, - onTapClean: () { - setState(() { - pd['VIDEONAME'] = ''; - pd['VIDEOMANAGER_ID'] = ''; - }); - }, - onTap: widget.onChooseVideoManager ?? () {}, - text: pd['VIDEONAME'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业开始时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - mode: BottomPickerMode.dateTimeWithSeconds, - context, - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_START_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); + if (FormUtils.hasValue(pd, 'WORK_START_DATE') && + !widget.isEditable) ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '动火作业实施时间:', + isEditable: widget.isEditable, + text: + FormUtils.hasValue(pd, 'WORK_END_DATE') + ? '${pd['WORK_START_DATE'] ?? ''}\n-${pd['WORK_END_DATE'] ?? ''}' + : pd['WORK_START_DATE'] ?? '', + + ), + if (!FormUtils.hasValue(pd, 'WORK_END_DATE')) + ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业结束时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + context, + minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_END_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + }); + } + }, + text: pd['WORK_EXPECTED_END_TIME'] ?? '', + ), + ], + ] else ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业开始时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, + context, + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_START_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + + /// 开始时间必须早于结束时间 + if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && + !isBeforeStr( + pd['WORK_EXPECTED_START_TIME'], + pd['WORK_EXPECTED_END_TIME'], + )) { + pd['WORK_EXPECTED_END_TIME'] = ''; + } + }); + } + }, + text: pd['WORK_EXPECTED_START_TIME'] ?? '', + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业结束时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + context, + minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_END_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + }); + } + }, + text: pd['WORK_EXPECTED_END_TIME'] ?? '', + ), + ], + - /// 开始时间必须早于结束时间 - if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && - !isBeforeStr( - pd['WORK_EXPECTED_START_TIME'], - pd['WORK_EXPECTED_END_TIME'], - )) { - pd['WORK_EXPECTED_END_TIME'] = ''; - } - }); - } - }, - text: pd['WORK_EXPECTED_START_TIME'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业结束时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - context, - minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_END_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); - }); - } - }, - text: pd['WORK_EXPECTED_END_TIME'] ?? '', - ), const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', @@ -313,10 +366,28 @@ class _HotWorkDetailFormWidgetState extends State { isInput: false, isEditable: widget.isEditable, buttonText: '定位', - onTap: widget.onWorkAreaLocationHandle ?? (){}, + onTap: widget.onWorkAreaLocationHandle ?? () {}, hintText: '', text: pd['LATITUDE_LONGITUDE'] ?? (widget.isEditable ? '' : '无'), ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '作业视频监控:', + isClean: + widget.isEditable && + (pd['WORK_LEVEL'] == '一级' || pd['WORK_LEVEL'] == '二级'), + cleanText: '清除监控', + isRequired: pd['WORK_LEVEL'] == '特级', + isEditable: widget.isEditable, + onTapClean: () { + setState(() { + pd['VIDEONAME'] = ''; + pd['VIDEOMANAGER_ID'] = ''; + }); + }, + onTap: widget.onChooseVideoManager ?? () {}, + text: pd['VIDEONAME'] ?? '', + ), if (FormUtils.hasValue(pd, 'ANALYZE_TIME') && !widget.isEditable) ...[ const Divider(), diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart index 18582ca..60b0de3 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/SpecialWorkFormBaseWork.dart @@ -1,10 +1,11 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; + import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; import 'HotWorkDetailFormWidget.dart'; class SpecialWorkFormBaseWork extends StatelessWidget { @@ -55,168 +56,6 @@ class SpecialWorkFormBaseWork extends StatelessWidget { ); } - Widget signItemWidget( - String signKey, - String nameKey, - String name, - BuildContext context, - ) { - return _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 标题行 - Padding( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - child: Row( - children: [ - Expanded( - child: ListItemFactory.headerTitle(name), - ), - if (FormUtils.hasValue(pd, nameKey)) - Text( - pd[nameKey]?.toString() ?? '', - style: const TextStyle(fontSize: 16), - ), - ], - ), - ), - const SizedBox(height: 8), - - if (FormUtils.hasValue(signs, signKey)) - ...((signs[signKey] as List) - .cast>() - .map((item) { - // 解析 SIGN_PATH - List signPaths = []; - final rawSP = FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; - if (rawSP is String && rawSP.isNotEmpty) { - signPaths = rawSP.split(',').map((s) => s.trim()).toList(); - } else if (rawSP is List) { - signPaths = rawSP.cast(); - } - - // 解析 SIGN_TIME 保留空格 - List signTimes = []; - final rawST = FormUtils.hasValue(item, 'SIGN_TIME') ? item['SIGN_TIME'] : null; - if (rawST is String && rawST.isNotEmpty) { - signTimes = rawST.split(','); - } else if (rawST is List) { - signTimes = rawST.cast(); - } - - final pairCount = math.min(signPaths.length, signTimes.length); - - // 解析 IMG_PATH, 最多 2 张 - List imgPaths = []; - final rawIP = FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null; - if (rawIP is String && rawIP.isNotEmpty) { - imgPaths = rawIP.split(',').map((s) => s.trim()).take(2).toList(); - } else if (rawIP is List) { - imgPaths = rawIP.cast().take(2).toList(); - } - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (imgPaths.isNotEmpty) ...[ - Row( - children: imgPaths.map((p) { - final fullUrl = '$baseImgPath$p'; - return GestureDetector( - onTap: () => SingleImageViewer(imageUrl: fullUrl), - child: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: ClipRRect( - borderRadius: BorderRadius.circular(2), - child: Image.network( - fullUrl, - width: 50, - height: 50, - fit: BoxFit.fill, - errorBuilder: (_, __, ___) => const Icon( - Icons.broken_image, - size: 40, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 8), - ], - - // 签名及时间 - ...List.generate(pairCount, (index) { - final imgPath = signPaths[index]; - final timeLabel = signTimes[index]; - final fullUrl = '$baseImgPath$imgPath'; - const imageWidth = 200.0; - const imageHeight = 100.0; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () => presentOpaque( - SingleImageViewer(imageUrl: fullUrl), - context, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Image.network( - fullUrl, - width: imageWidth, - height: imageHeight, - fit: BoxFit.fill, - errorBuilder: (_, __, ___) => - const Icon(Icons.broken_image, size: 60), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: SizedBox( - height: imageHeight, - child: Align( - alignment: Alignment.bottomRight, - child: Text( - timeLabel, - style: const TextStyle( - fontSize: 14, - color: Colors.black87, - ), - ), - ), - ), - ), - ], - ), - if (index < pairCount - 1) - const Padding( - padding: EdgeInsets.only(top: 8.0), - child: Divider(height: 1), - ), - ], - ), - ); - }), - ], - ), - ); - }).toList()), - ], - ), - ); - } - @override Widget build(BuildContext context) { return Column( @@ -230,6 +69,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { onChooseLevel: onChooseLevel, onChooseHotworkUser: onChooseHotworkUser, onAnalyzeTap: onAnalyzeTap, + signs: signs, ), // 2. 安全防护措施 @@ -257,6 +97,7 @@ class SpecialWorkFormBaseWork extends StatelessWidget { children: [ ListItemFactory.createBuildSimpleSection('其他安全防护措施'), OtherMeasuresWidget( + otherMeasures: signs['MEASURES_CONFIRM'], baseImgPath: baseImgPath, ), @@ -264,138 +105,97 @@ class SpecialWorkFormBaseWork extends StatelessWidget { ), ), - // 4. 各环节签字及意见 - if (FormUtils.hasValue(signs, 'GUARDIAN')) - signItemWidget('GUARDIAN', 'GUARDIAN_USER_NAME', '监护人', context), - - if (FormUtils.hasValue(signs, 'CONFESS')) - signItemWidget('CONFESS', 'CONFESS_USER_NAME', '安全交底人', context), - - if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) - signItemWidget('ACCEPT_CONFESS', 'ACCEPT_CONFESS_USER_NAME', '接受交底人', context), - - // 作业负责人意见 - if (FormUtils.hasValue(signs, 'CONFIRM')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('作业负责人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['CONFIRM'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('CONFIRM', 'CONFIRM_USER_NAME', '作业负责人', context), - ], - ) - - ], - - // 所在单位负责人意见 - if (FormUtils.hasValue(signs, 'LEADER')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('所在单位意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['LEADER'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('LEADER', 'LEADER_USER_NAME', '所在单位负责人', context), - ], - ) - ], - - // 安全管理部门负责人意见 - if (FormUtils.hasValue(signs, 'AUDIT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('安全管理部门意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['AUDIT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('AUDIT', 'AUDIT_USER_NAME', '安全管理部门负责人', context), - ], - ) - ], - - // 动火审批人意见 - if (FormUtils.hasValue(signs, 'APPROVE')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('动火审批人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['APPROVE'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('APPROVE', 'APPROVE_USER_NAME', '动火审批人', context), - ], - ) - ], + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFESS', + nameKey: 'CONFESS_USER_NAME', + headerTitle: '安全交底人意见', + roleTitle: '安全交底人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'ACCEPT_CONFESS', + nameKey: 'ACCEPT_CONFESS_USER_NAME', + headerTitle: '接受交底人', + roleTitle: '', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'GUARDIAN', + nameKey: 'GUARDIAN_USER_NAME', + headerTitle: '监护人意见', + roleTitle: '监护人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFIRM', + nameKey: 'CONFIRM_USER_NAME', + headerTitle: '作业负责人意见', + roleTitle: '作业负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'LEADER', + nameKey: 'LEADER_USER_NAME', + headerTitle: '所在单位意见', + roleTitle: '所在单位负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'AUDIT', + nameKey: 'AUDIT_USER_NAME', + headerTitle: '安全管理部门意见', + roleTitle: '安全管理部门', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'APPROVE', + nameKey: 'APPROVE_USER_NAME', + headerTitle: '动火审批人意见', + roleTitle: '动火审批人', + ), // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'MONITOR')) - signItemWidget('MONITOR', 'MONITOR_USER_NAME', '动火前在岗班长', context), + // if (FormUtils.hasValue(signs, 'MONITOR')) + // signItemWidget('MONITOR', 'MONITOR_USER_NAME', '动火前在岗班长', context), + // + // // 作业开始负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_START')) + // signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'MONITOR', + nameKey: 'MONITOR_USER_NAME', + headerTitle: '动火前,岗位当班班长验票情况', + roleTitle: '动火前,岗位当班班长验票情况', + ), - // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'ACCEPT', + nameKey: 'ACCEPT_USER_NAME', + headerTitle: '验收部门负责人意见', + roleTitle: '验收部门负责人', + ), - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), - - // 完工验收意见和签字 - if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('完工验收意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['ACCEPT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('ACCEPT', 'ACCEPT_USER_NAME', '验收部门负责人', context), - ], - ) - ], ], ); } 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 b488270..268ea7d 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 @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/BaiDuMap/Map_page.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/center_multi_picker.dart'; import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/department_person_picker.dart'; import 'package:qhd_prevention/customWidget/department_picker.dart'; @@ -25,7 +26,6 @@ enum EditUserType { GUARDIAN('监护人单位', '监护人', true), CONFESS('安全交底人单位', '安全交底人', true), ACCEPT_CONFESS('接受交底人单位', '接受交底人', true), - WORK_USER('作业人单位', '作业人', true), CONFIRM('作业负责人单位', '作业负责人', true), LEADER('所在单位', '所在单位负责人', true), AUDIT('安全管理部门', '安全管理部门负责人', true), @@ -67,7 +67,7 @@ class _HotworkApplyDetailState extends State { /// 详情 late Map pd = {}; late Map signs = {}; - late List> measuresList = []; + late List measuresList = []; final TextEditingController _contentController = TextEditingController(); final TextEditingController _locationController = TextEditingController(); @@ -83,10 +83,13 @@ class _HotworkApplyDetailState extends State { /// ------------------- 新增 ------------------- /// 视频监控摄像 late List videoMonitoringList = []; + /// 承包商列表 late List unitAllList = []; + /// 作业区域列表 - late List> workAreaList = []; + late List workAreaList = []; + /// -------------------------------------- // 存储各单位的人员列表 @@ -107,7 +110,6 @@ class _HotworkApplyDetailState extends State { pd['APPLY_USER_ID'] = SessionService.instance.loginUserId; pd['APPLY_USER_NAME'] = SessionService.instance.username; pd['IS_CONTRACTOR_WORK'] = '0'; - } _getHotWorkNameList(); _getVideoList(); @@ -125,9 +127,7 @@ class _HotworkApplyDetailState extends State { _methodController.addListener(() { pd['WORK_FUNCTION'] = _methodController.text.trim(); }); - _hotworkPersonController.addListener(() { - pd['WORK_USER'] = _hotworkPersonController.text.trim(); - }); + _relatedController.addListener(() { pd['SPECIAL_WORK'] = _relatedController.text.trim(); }); @@ -145,11 +145,9 @@ class _HotworkApplyDetailState extends State { } void set_pd_USER_ID(EditUserType type, String id) { - if (type == EditUserType.WORK_USER) { - pd['${type.name}_ID'] = id; - }else{ + pd['${type.name}_USER_ID'] = id; - } + } void set_pd_USER_Name(EditUserType type, String name) { @@ -165,11 +163,8 @@ class _HotworkApplyDetailState extends State { } String get_pd_USER_ID(EditUserType type) { - if (type == EditUserType.WORK_USER) { - return pd['${type.name}_ID'] ?? ''; - } else { return pd['${type.name}_USER_ID'] ?? ''; - } + } String get_pd_USER_Name(EditUserType type) { @@ -193,26 +188,39 @@ class _HotworkApplyDetailState extends State { } Future _chooseHorkUser() async { - final choice = await BottomPicker.show( + final res = await CenterMultiPicker.show( context, items: workUserList.map((item) => item['NAME'] as String).toList(), - itemBuilder: (item) => Text(item, textAlign: TextAlign.center), - initialIndex: 0, + itemBuilder: (it) => Text(it), + initialSelectedIndices: [1, 3], + maxSelection: 100, + allowEmpty: false, + title: '动火人及证书编号', ); - if (choice != null) { + + if (res != null) { + // 点击确定,res 为 List setState(() { - pd['WORK_USER'] = choice; - _hotworkPersonController.text = choice; - Map result = workUserList.firstWhere( - (item) => item['NAME'] == choice, - orElse: () => {}, // 避免找不到时报错 - ); - if (FormUtils.hasValue(result, 'USER_ID')) { - pd['WORK_USER_ID'] = result['USER_ID']; + List names = []; + List ids = []; + + for (String name in res) { + for (final item in workUserList) { + if (item['NAME'] == name) { + names.add(item['UNAME']); + ids.add(item['PERSONNELMANAGEMENT_ID']); + } + } } - //FocusHelper.clearFocus(context); + pd['WORK_USER_NAME'] = names.join(','); + pd['WORK_USER_ID'] = ids.join(','); + pd['WORK_USER'] = res.join(','); + print('${pd['WORK_USER_NAME']}\n${pd['WORK_USER_ID']}\n${pd['WORK_USER']}'); }); + } else { + // 取消或关闭对话框 } + } /// ---------------------------- 新增 -------------------------------- @@ -242,6 +250,7 @@ class _HotworkApplyDetailState extends State { }); } } + /// 选择承包商 Future _chooseUnitManager() async { final choice = await BottomPicker.show( @@ -267,7 +276,7 @@ class _HotworkApplyDetailState extends State { } /// 选择经纬度 - Future _showLocationHandle() async{ + Future _showLocationHandle() async { if (!FormUtils.hasValue(pd, 'ELECTRONIC_FENCE_AREA_ID')) { ToastUtil.showNormal(context, '请选择作业区域'); return; @@ -276,11 +285,11 @@ class _HotworkApplyDetailState extends State { setState(() { pd['LONGITUDE'] = mapData['longitue'] ?? ''; pd['LATITUDE'] = mapData['latitude'] ?? ''; - pd['LATITUDE_LONGITUDE'] = '${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}'; + pd['LATITUDE_LONGITUDE'] = + '${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}'; }); - - } + /// 作业区域 Future _getWorkArea() async { //FocusHelper.clearFocus(context); @@ -291,16 +300,17 @@ class _HotworkApplyDetailState extends State { backgroundColor: Colors.transparent, builder: (_) => WorkAreaPicker( - onSelected: (String id, String POSITIONS, String name) { - pd['ELECTRONIC_FENCE_AREA_ID'] = id; - pd['POSITIONS'] = POSITIONS; - pd['PLS_NAME'] = name; - }, - ), + onSelected: (String id, String POSITIONS, String name) { + pd['ELECTRONIC_FENCE_AREA_ID'] = id; + pd['POSITIONS'] = POSITIONS; + pd['PLS_NAME'] = name; + }, + ), ).then((_) { //FocusHelper.clearFocus(context); }); } + /// 获取摄像头列表 Future _getVideoList() async { final result = await ApiService.getVideomanagerList(); @@ -308,6 +318,7 @@ class _HotworkApplyDetailState extends State { videoMonitoringList = result['varList'] ?? []; }); } + /// 获承包商列表 Future _getUnitListAll() async { final result = await ApiService.getUnitListAll(); @@ -315,6 +326,7 @@ class _HotworkApplyDetailState extends State { unitAllList = result['varList'] ?? []; }); } + /// 作业区域列表 Future _getPlsList() async { final result = await ApiService.getWorkAreaList(); @@ -323,8 +335,8 @@ class _HotworkApplyDetailState extends State { workAreaList = jsonDecode(zTreeNodes); }); } - /// ------------------------------------------------------------ + /// ------------------------------------------------------------ Widget _card(Widget child) { return Container( @@ -476,11 +488,7 @@ class _HotworkApplyDetailState extends State { {'value': _contentController.text.trim(), 'message': '请填写作业内容'}, {'value': _locationController.text.trim(), 'message': '请填写动火地点及部位'}, {'value': _methodController.text.trim(), 'message': '请填写动火方式'}, - {'value': _hotworkPersonController.text.trim(), 'message': '请填写动火人及证书编号'}, - // { - // 'value': _relatedController.text.trim(), - // 'message': '请输入关联的其他特殊作业及安全作业票编号', - // }, + {'value': pd['WORK_USER'], 'message': '请选择动火人及证书编号'}, {'value': _riskController.text.trim(), 'message': '请填写风险辨识结果'}, ]; final level = pd['WORK_LEVEL'] ?? ''; @@ -492,7 +500,6 @@ class _HotworkApplyDetailState extends State { EditUserType.GUARDIAN, EditUserType.CONFESS, EditUserType.ACCEPT_CONFESS, - EditUserType.WORK_USER, EditUserType.CONFIRM, EditUserType.LEADER, // 如果不是二级,或者SAFETY_USER_ID有值就加上 AUDIT @@ -534,7 +541,8 @@ class _HotworkApplyDetailState extends State { return; } - if (pd['IS_CONTRACTOR_WORK'] == '1' && !FormUtils.hasValue(pd, 'UNITS_ID')) { + if (pd['IS_CONTRACTOR_WORK'] == '1' && + !FormUtils.hasValue(pd, 'UNITS_ID')) { ToastUtil.showNormal(context, '请选择承包商'); return; } @@ -595,7 +603,7 @@ class _HotworkApplyDetailState extends State { ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存'); Navigator.of(context).pop(true); } else { - ToastUtil.showError(context, '提交失败'); + ToastUtil.showError(context, result['msg'] ?? '提交失败'); } } catch (e) { LoadingDialogHelper.hide(); @@ -610,9 +618,7 @@ class _HotworkApplyDetailState extends State { }); } - - -/// ---------------------------- 接口请求 -------------------------------- + /// ---------------------------- 接口请求 -------------------------------- /// 初始化拉取数据 Future _getData() async { @@ -632,12 +638,11 @@ class _HotworkApplyDetailState extends State { _contentController.text = pd['WORK_CONTENT'] ?? ''; _locationController.text = pd['WORK_PLACE'] ?? ''; _methodController.text = pd['WORK_FUNCTION'] ?? ''; - _hotworkPersonController.text = pd['WORK_USER'] ?? ''; _relatedController.text = pd['SPECIAL_WORK'] ?? ''; _riskController.text = pd['RISK_IDENTIFICATION'] ?? ''; }); - } + Future _getSigns(String homework_id) async { final data = await ApiService.listSignFinished( 'hotwork', @@ -647,13 +652,14 @@ class _HotworkApplyDetailState extends State { signs = data['signs'] ?? {}; }); } + Future _getMeasures(String homework_id) async { final data = await ApiService.listSignFinishMeasures( 'hotwork', homework_id.length > 0 ? homework_id : widget.HOTWORK_ID, ); setState(() { - measuresList = List>.from( + measuresList = List.from( data['finishMeasuresList'] ?? >[], ); }); @@ -706,8 +712,6 @@ class _HotworkApplyDetailState extends State { SizedBox(height: 15), _card(_chooseItem(EditUserType.ACCEPT_CONFESS)), SizedBox(height: 15), - _card(_chooseItem(EditUserType.WORK_USER)), - SizedBox(height: 15), _card(_chooseItem(EditUserType.CONFIRM)), SizedBox(height: 15), _card(_chooseItem(EditUserType.LEADER)), diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/jszy_work_detail/hotwork_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/jszy_work_detail/hotwork_jszy_detail.dart index 1ac0990..064ff47 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/jszy_work_detail/hotwork_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/jszy_work_detail/hotwork_jszy_detail.dart @@ -51,81 +51,6 @@ class _HotworkJszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -163,10 +88,7 @@ class _HotworkJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -305,7 +227,6 @@ class _HotworkJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -349,29 +270,11 @@ class _HotworkJszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dh_work/kszy_work_detail/hotwork_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dh_work/kszy_work_detail/hotwork_kszy_detail.dart index 7c31837..8d67175 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dh_work/kszy_work_detail/hotwork_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dh_work/kszy_work_detail/hotwork_kszy_detail.dart @@ -52,87 +52,8 @@ class _HotworkKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -277,7 +198,6 @@ class _HotworkKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -320,29 +240,10 @@ class _HotworkKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业开始时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 29bd47e..38a50f9 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 @@ -9,7 +9,7 @@ import 'package:qhd_prevention/http/ApiService.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用断路作业明细表单组件(支持编辑/只读) class CutroadDetailFormWidget extends StatefulWidget { @@ -18,19 +18,24 @@ class CutroadDetailFormWidget extends StatefulWidget { final VoidCallback onChooseLevel; /// 编辑模式下需提供以下控制器,非编辑模式可不传 - final TextEditingController? unitController; // 涉及部门 - final TextEditingController? contentController; // 原因 + final TextEditingController? unitController; // 涉及部门 + final TextEditingController? contentController; // 原因 final TextEditingController? relatedController; final TextEditingController? riskController; // 新增 -/// 选择摄像头 - final VoidCallback? onChooseVideoManager;/// 承包商 + /// 选择摄像头 + final VoidCallback? onChooseVideoManager; + + /// 承包商 final VoidCallback? onContractorHandle; + /// 作业区域 final VoidCallback? onWorkAreaHandle; + /// 作业地点经纬度 final VoidCallback? onWorkAreaLocationHandle; + /// 其他签字数据 final signs; @@ -51,19 +56,19 @@ class CutroadDetailFormWidget extends StatefulWidget { this.relatedController, this.riskController, this.signs = null, - }) : assert( - !isEditable || - (unitController != null && - contentController != null && - relatedController != null && - riskController != null), - 'Editable mode requires all TextEditingController parameters', - ), - super(key: key); + !isEditable || + (unitController != null && + contentController != null && + relatedController != null && + riskController != null), + 'Editable mode requires all TextEditingController parameters', + ), + super(key: key); @override - State createState() => _CutroadDetailFormWidgetState(); + State createState() => + _CutroadDetailFormWidgetState(); } class _CutroadDetailFormWidgetState extends State { @@ -77,174 +82,184 @@ class _CutroadDetailFormWidgetState extends State { child: child, ); } + Widget signItemWidget( - String signKey, - String nameKey, - String name, - BuildContext context, - ) { + String signKey, + BuildContext context, + ) { return _itemContainer( Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // 标题行 - Padding( - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - child: Row( - children: [ - Expanded( - child: ListItemFactory.headerTitle(name), - ), - if (FormUtils.hasValue(widget.pd, nameKey)) - Text( - widget.pd[nameKey]?.toString() ?? '', - style: const TextStyle(fontSize: 16), - ), - ], - ), - ), - const SizedBox(height: 8), - if (FormUtils.hasValue(widget.signs, signKey)) ...((widget.signs[signKey] as List) .cast>() .map((item) { - // 解析 SIGN_PATH - List signPaths = []; - final rawSP = FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null; - if (rawSP is String && rawSP.isNotEmpty) { - signPaths = rawSP.split(',').map((s) => s.trim()).toList(); - } else if (rawSP is List) { - signPaths = rawSP.cast(); - } + // 解析 SIGN_PATH + List signPaths = []; + final rawSP = + FormUtils.hasValue(item, 'SIGN_PATH') + ? item['SIGN_PATH'] + : null; + if (rawSP is String && rawSP.isNotEmpty) { + signPaths = rawSP.split(',').map((s) => s.trim()).toList(); + } else if (rawSP is List) { + signPaths = rawSP.cast(); + } - // 解析 SIGN_TIME 保留空格 - List signTimes = []; - final rawST = FormUtils.hasValue(item, 'SIGN_TIME') ? item['SIGN_TIME'] : null; - if (rawST is String && rawST.isNotEmpty) { - signTimes = rawST.split(','); - } else if (rawST is List) { - signTimes = rawST.cast(); - } + // 解析 SIGN_TIME 保留空格 + List signTimes = []; + final rawST = + FormUtils.hasValue(item, 'SIGN_TIME') + ? item['SIGN_TIME'] + : null; + if (rawST is String && rawST.isNotEmpty) { + signTimes = rawST.split(','); + } else if (rawST is List) { + signTimes = rawST.cast(); + } - final pairCount = math.min(signPaths.length, signTimes.length); + final pairCount = math.min( + signPaths.length, + signTimes.length, + ); - // 解析 IMG_PATH, 最多 2 张 - List imgPaths = []; - final rawIP = FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null; - if (rawIP is String && rawIP.isNotEmpty) { - imgPaths = rawIP.split(',').map((s) => s.trim()).take(2).toList(); - } else if (rawIP is List) { - imgPaths = rawIP.cast().take(2).toList(); - } - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (imgPaths.isNotEmpty) ...[ - Row( - children: imgPaths.map((p) { - final fullUrl = '${ApiService.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: 50, - height: 50, - fit: BoxFit.fill, - errorBuilder: (_, __, ___) => const Icon( - Icons.broken_image, - size: 40, - ), - ), - ), - ), - ); - }).toList(), - ), - const SizedBox(height: 8), - ], - - // 签名及时间 - ...List.generate(pairCount, (index) { - final imgPath = signPaths[index]; - final timeLabel = signTimes[index]; - final fullUrl = '${ApiService.baseImgPath}$imgPath'; - const imageWidth = 200.0; - const imageHeight = 100.0; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () => presentOpaque( - SingleImageViewer(imageUrl: fullUrl), - context, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Image.network( - fullUrl, - width: imageWidth, - height: imageHeight, - fit: BoxFit.fill, - errorBuilder: (_, __, ___) => - const Icon(Icons.broken_image, size: 60), - ), - ), - ), - const SizedBox(width: 12), - Expanded( - child: SizedBox( - height: imageHeight, - child: Align( - alignment: Alignment.bottomRight, - child: Text( - timeLabel, - style: const TextStyle( - fontSize: 14, - color: Colors.black87, + // 解析 IMG_PATH, 最多 2 张 + List imgPaths = []; + final rawIP = + FormUtils.hasValue(item, 'IMG_PATH') + ? item['IMG_PATH'] + : null; + if (rawIP is String && rawIP.isNotEmpty) { + imgPaths = + rawIP.split(',').map((s) => s.trim()).take(2).toList(); + } else if (rawIP is List) { + imgPaths = rawIP.cast().take(2).toList(); + } + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, + horizontal: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (imgPaths.isNotEmpty) ...[ + Row( + children: + imgPaths.map((p) { + final fullUrl = '${ApiService.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: 50, + height: 50, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => const Icon( + Icons.broken_image, + size: 40, + ), ), ), ), - ), + ); + }).toList(), + ), + const SizedBox(height: 8), + ], + + // 签名及时间 + ...List.generate(pairCount, (index) { + final imgPath = signPaths[index]; + final timeLabel = signTimes[index]; + final fullUrl = '${ApiService.baseImgPath}$imgPath'; + const imageWidth = 200.0; + const imageHeight = 100.0; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: + () => presentOpaque( + SingleImageViewer( + imageUrl: fullUrl, + ), + context, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: Image.network( + fullUrl, + width: imageWidth, + height: imageHeight, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => const Icon( + Icons.broken_image, + size: 60, + ), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: SizedBox( + height: imageHeight, + child: Align( + alignment: Alignment.bottomRight, + child: Text( + timeLabel, + style: const TextStyle( + fontSize: 14, + color: Colors.black87, + ), + ), + ), + ), + ), + ], ), + if (index < pairCount - 1) + const Padding( + padding: EdgeInsets.only(top: 8.0), + child: Divider(height: 1), + ), ], ), - if (index < pairCount - 1) - const Padding( - padding: EdgeInsets.only(top: 8.0), - child: Divider(height: 1), - ), - ], - ), - ); - }), - ], - ), - ); - }).toList()), + ); + }), + ], + ), + ); + }) + .toList()), ], ), ); } + @override Widget build(BuildContext context) { if (FormUtils.hasValue(widget.pd, 'LATITUDE')) { - widget.pd['LATITUDE_LONGITUDE'] = '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map + widget.pd['LATITUDE_LONGITUDE'] = + '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map } final pd = widget.pd; @@ -276,8 +291,20 @@ class _CutroadDetailFormWidgetState extends State { isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), + if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + const Divider(), + ItemListWidget.singleLineTitleText( + label: '作业单位:', + isEditable: false, + text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + ), + ], + if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME')&& !widget.isEditable) ...[ + const Divider(), + // ItemListWidget.OneRowImageTitle(label: '作业负责人', imgPatlabel: '作业负责人', imgPath: imgPathh: imgPath) + SignRowImageTitle(label: '作业负责人:', signKey: 'CONFIRM', signs: widget.signs, text: pd['CONFIRM_USER_NAME']??'',), + ], const Divider(), - ItemListWidget.singleLineTitleText( label: '涉及相关单位(部门):', isEditable: widget.isEditable, @@ -285,6 +312,11 @@ class _CutroadDetailFormWidgetState extends State { controller: widget.unitController, text: pd['OTHER_DEPT'] ?? '', ), + if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME')&& !widget.isEditable) ...[ + const Divider(), + // ItemListWidget.OneRowImageTitle(label: '作业负责人', imgPath: imgPath) + SignRowImageTitle(label: '监护人:', signKey: 'GUARDIAN', signs: widget.signs, text: pd['GUARDIAN_USER_NAME']??'',), + ], const Divider(), ItemListWidget.multiLineTitleTextField( label: '断路原因:', @@ -301,16 +333,17 @@ class _CutroadDetailFormWidgetState extends State { onTap: () async { final val = await showDialog( context: context, - builder: (_) => SelectionPopup( - type: 'assignments', - initialValue: pd['SPECIAL_WORK'] ?? '', - onConfirm: (v) { - setState(() { - pd['SPECIAL_WORK'] = v; - widget.relatedController?.text = v; - }); - }, - ), + builder: + (_) => SelectionPopup( + type: 'assignments', + initialValue: pd['SPECIAL_WORK'] ?? '', + onConfirm: (v) { + setState(() { + pd['SPECIAL_WORK'] = v; + widget.relatedController?.text = v; + }); + }, + ), ); //FocusHelper.clearFocus(context); }, @@ -319,41 +352,35 @@ class _CutroadDetailFormWidgetState extends State { text: pd['SPECIAL_WORK'] ?? '', ), const Divider(), + ConfirmWithSignWidget( + signs: widget.signs, + pd: pd, + baseImgPath: ApiService.baseImgPath, + sectionKey: 'GUARDIAN', + nameKey: 'WORK_CONTENT', + headerTitle: '断路地段示意图(可另附图)及相关说明', + imgsKey: 'CONTENT_IMG_PATH', + contentKey: 'WORK_CONTENT', + roleTitle: '', + ), - if (!widget.isEditable && FormUtils.hasValue(pd, 'WORK_CONTENT')) ...[ - ItemListWidget.singleLineTitleText( - label: '断路地段示意图(可另附图)及相关说明:', - isEditable: false, - text: pd['WORK_CONTENT'] ?? '', - ), - const Divider(), - ], - if (!widget.isEditable && FormUtils.hasValue(pd, 'CONTENT_IMG_PATH')) ...[ - ItemListWidget.twoRowTitleAndImages( - onTapCallBack: (val) { - presentOpaque(SingleImageViewer(imageUrl: val), context); - }, - title: '断路地段示意图:', - imageUrls: pd['CONTENT_IMG_PATH'], - ), - const Divider(), - ], ItemListWidget.twoRowButtonTitleText( label: '风险辨识结果', isEditable: widget.isEditable, onTap: () async { await showDialog( context: context, - builder: (_) => SelectionPopup( - type: 'identification', - initialValue: pd['RISK_IDENTIFICATION'] ?? '', - onConfirm: (v) { - setState(() { - pd['RISK_IDENTIFICATION'] = v; - widget.riskController?.text = v; - }); - }, - ), + builder: + (_) => SelectionPopup( + type: 'identification', + initialValue: pd['RISK_IDENTIFICATION'] ?? '', + onConfirm: (v) { + setState(() { + pd['RISK_IDENTIFICATION'] = v; + widget.riskController?.text = v; + }); + }, + ), ); //FocusHelper.clearFocus(context); }, @@ -361,59 +388,69 @@ class _CutroadDetailFormWidgetState extends State { controller: widget.riskController, text: pd['RISK_IDENTIFICATION'] ?? '', ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业开始时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - mode: BottomPickerMode.dateTimeWithSeconds, - context, - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_START_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); + if (FormUtils.hasValue(pd, 'WORK_START_DATE')) ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '断路作业实施时间:', + isEditable: widget.isEditable, + text: pd['WORK_START_DATE'] ?? '', + ), + ] else ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业开始时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, + context, + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_START_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); - /// 开始时间必须早于结束时间 - if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && - !isBeforeStr( - pd['WORK_EXPECTED_START_TIME'], - pd['WORK_EXPECTED_END_TIME'], - )) { - pd['WORK_EXPECTED_END_TIME'] = ''; - } - }); - } - }, - text: pd['WORK_EXPECTED_START_TIME'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业结束时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - context, - minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_END_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); - }); - } - }, - text: pd['WORK_EXPECTED_END_TIME'] ?? '', - ), + /// 开始时间必须早于结束时间 + if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && + !isBeforeStr( + pd['WORK_EXPECTED_START_TIME'], + pd['WORK_EXPECTED_END_TIME'], + )) { + pd['WORK_EXPECTED_END_TIME'] = ''; + } + }); + } + }, + text: pd['WORK_EXPECTED_START_TIME'] ?? '', + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业结束时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + context, + minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_END_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + }); + } + }, + text: pd['WORK_EXPECTED_END_TIME'] ?? '', + ), + ], const Divider(), + ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', @@ -452,7 +489,7 @@ class _CutroadDetailFormWidgetState extends State { isInput: false, isEditable: widget.isEditable, buttonText: '定位', - onTap: widget.onWorkAreaLocationHandle ?? (){}, + onTap: widget.onWorkAreaLocationHandle ?? () {}, hintText: '', text: pd['LATITUDE_LONGITUDE'] ?? (widget.isEditable ? '' : '无'), ), @@ -473,14 +510,6 @@ class _CutroadDetailFormWidgetState extends State { onTap: widget.onChooseVideoManager ?? () {}, text: pd['VIDEONAME'] ?? '', ), - - if (widget.signs != null && FormUtils.hasValue(widget.signs, 'PROJECT_MANAGER')) - Column( - children: [ - Divider(), - signItemWidget('PROJECT_MANAGER', 'PROJECT_MANAGER_USER_NAME', '断路示意图负责人签字', context), - ], - ) ], ), ); diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart index 0f57f3a..cb40d34 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; import 'CutroadDetailFormWidget.dart'; class CutroadFormBaseWork extends StatelessWidget { @@ -67,7 +67,7 @@ class CutroadFormBaseWork extends StatelessWidget { child: Row( children: [ Expanded( - child: ListItemFactory.headerTitle(name), + child: ListItemFactory.headerTitle('$name'), ), if (FormUtils.hasValue(pd, nameKey)) Text( @@ -261,135 +261,71 @@ class CutroadFormBaseWork extends StatelessWidget { ], ), ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFESS', + nameKey: 'CONFESS_USER_NAME', + headerTitle: '安全交底人', + roleTitle: '安全交底人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'ACCEPT_CONFESS', + nameKey: 'ACCEPT_CONFESS_USER_NAME', + headerTitle: '接受交底人', + roleTitle: '', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFIRM', + nameKey: 'CONFIRM_USER_NAME', + headerTitle: '作业负责人意见', + roleTitle: '作业负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'LEADER', + nameKey: 'LEADER_USER_NAME', + headerTitle: '所在单位负责人意见', + roleTitle: '所在单位负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'AUDIT', + nameKey: 'AUDIT_USER_NAME', + headerTitle: '消防、安全管理部门负责人意见', + roleTitle: '消防、安全管理部门负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'APPROVE', + nameKey: 'APPROVE_USER_NAME', + headerTitle: '审批部门负责人意见', + roleTitle: '审批部门负责人', + ), - // 4. 各环节签字及意见 - if (FormUtils.hasValue(signs, 'GUARDIAN')) - signItemWidget('GUARDIAN', 'GUARDIAN_USER_NAME', '监护人', context), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'ACCEPT', + nameKey: 'ACCEPT_USER_NAME', + headerTitle: '验收部门负责人意见', + roleTitle: '验收部门负责人', + ), - if (FormUtils.hasValue(signs, 'CONFESS')) - signItemWidget('CONFESS', 'CONFESS_USER_NAME', '安全交底人', context), - - if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) - signItemWidget('ACCEPT_CONFESS', 'ACCEPT_CONFESS_USER_NAME', '接受交底人', context), - - // 作业负责人意见 - if (FormUtils.hasValue(signs, 'CONFIRM')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('作业负责人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['CONFIRM'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('CONFIRM', 'CONFIRM_USER_NAME', '作业负责人', context), - ], - ) - - ], - - // 所在单位负责人意见 - if (FormUtils.hasValue(signs, 'LEADER')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('所在单位意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['LEADER'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('LEADER', 'LEADER_USER_NAME', '所在单位负责人', context), - ], - ) - ], - - // 安全管理部门负责人意见 - if (FormUtils.hasValue(signs, 'AUDIT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('消防、安全管理部门意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['AUDIT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('AUDIT', 'AUDIT_USER_NAME', '消防、安全管理部门负责人', context), - ], - ) - ], - - // 审批人意见 - if (FormUtils.hasValue(signs, 'APPROVE')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('审批人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['APPROVE'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('APPROVE', 'APPROVE_USER_NAME', '审批负责人', context), - ], - ) - ], - - // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), - - // 完工验收意见和签字 - if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('完工验收意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['ACCEPT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('ACCEPT', 'ACCEPT_USER_NAME', '验收部门负责人', context), - ], - ) - ], ], ); } diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart index f26d2cf..d080787 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart @@ -310,6 +310,7 @@ class _CutroadAqjdDetailState extends State { onAnalyzeTap: () {}, ), ItemListWidget.itemContainer( + horizontal: 5, Column( children: [ RepairedPhotoSection( @@ -327,6 +328,7 @@ class _CutroadAqjdDetailState extends State { onAiIdentify: () {}, ), ItemListWidget.itemContainer( + horizontal: 5, Column( children: [ Row( 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 d8cd3c6..05bc03d 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 @@ -101,7 +101,7 @@ class _CutroadListPageState extends State { int code = 0; for (Map item in stepList) { if (item['STEP_NAME'] == widget.flow) { - code = item['STEP_ID'] ?? 0; + code = item['STEP_ID'] ?? ''; } } try { @@ -112,7 +112,7 @@ class _CutroadListPageState extends State { widget.flow == '气体检测' ? SessionService.instance.loginUserId : '', 'STEP_NAME': (widget.flow == '提交申请' || widget.flow == '气体检测') ? '' : widget.flow, - 'STEP_CODE': code, + 'STEP_CODE': (widget.flow == '提交申请' || widget.flow == '气体检测') ? '' : code, 'STEP_ID': sindex > 0 ? stepList[sindex]['STEP_ID'] : '', 'KEYWORDS': searchKeywords, 'WORK_STATE': '0', 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 3170cca..e48a7b7 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 @@ -27,7 +27,7 @@ enum EditUserType { ACCEPT_CONFESS('接受交底人单位', '接受交底人', true), CONFIRM('作业负责人单位', '作业负责人', true), LEADER('所在单位', '所在单位负责人', true), - AUDIT('消防、安全管理部门', '安全管理部门负责人', true), + AUDIT('消防、安全管理部门', '消防、安全管理部门负责人', true), APPROVE('审批部门', '审批部门负责人', true), WORK_START('作业开始负责人单位', '作业开始负责人', true), WORK_END('作业结束负责人单位', '作业结束负责人', true), diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/jszy_work_detail/cutroad_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/jszy_work_detail/cutroad_jszy_detail.dart index d379fde..7fb2719 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/jszy_work_detail/cutroad_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/jszy_work_detail/cutroad_jszy_detail.dart @@ -51,80 +51,80 @@ class _CutroadJszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } + // /// 签字 + // Future _sign() async { + // await NativeOrientation.setLandscape(); + // final path = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => MineSignPage()), + // ); + // await NativeOrientation.setPortrait(); + // if (path != null) { + // final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); + // setState(() { + // signImages.add(path); + // signTimes.add(now); + // }); + // } + // } + // + // Widget _signListWidget() { + // return Column( + // children: + // signImages.map((path) { + // return Column( + // children: [ + // const SizedBox(height: 10), + // const Divider(), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // 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( + // 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(() { + // signImages.remove(path); + // }); + // }, + // ), + // ), + // const SizedBox(height: 80), + // ], + // ), + // ], + // ), + // ], + // ); + // }).toList(), + // ); + // } bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 @@ -143,10 +143,10 @@ class _CutroadJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + // if (signImages.isEmpty) { + // ToastUtil.showNormal(context, '请签字'); + // return; + // } String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -283,7 +283,6 @@ class _CutroadJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), CutroadFormBaseWork( @@ -322,29 +321,30 @@ class _CutroadJszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + // Divider(), + // Column( + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // ListItemFactory.headerTitle('作业结束时间负责人'), + // CustomButton( + // text: '新增手写签字', + // height: 36, + // backgroundColor: Colors.green, + // onPressed: () { + // _sign(); + // }, + // ), + // ], + // ), + // if (signImages.isNotEmpty) _signListWidget(), + // ], + // ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dl_work/kszy_work_detail/cutroad_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dl_work/kszy_work_detail/cutroad_kszy_detail.dart index 6b52264..a637263 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dl_work/kszy_work_detail/cutroad_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dl_work/kszy_work_detail/cutroad_kszy_detail.dart @@ -52,101 +52,22 @@ class _CutroadKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); -setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { ToastUtil.showNormal(context, '请选择作业开始时间'); return; } - } else { reasonText = await CustomAlertDialog.showInput( context, title: '作废原因', hintText: '请输入作废原因', cancelText: '取消', - confirmText: '确定' + confirmText: '确定', ); if (reasonText.isEmpty) { ToastUtil.showNormal(context, '请填写作废原因'); @@ -173,23 +94,22 @@ setState(() { barrierDismissible: false, ); if (confirmed) { - LoadingDialogHelper.show(); - try { - final result = await ApiService.saveSafeFunctionSure( - 'cutroad', - formData, - signImages, - ); - LoadingDialogHelper.hide(); - if (result['result'] == 'success') { - ToastUtil.showSuccess(context, '保存成功'); - Navigator.of(context).pop(true); - } - } catch (e) { - LoadingDialogHelper.hide(); - ToastUtil.showNormal(context, '操作失败:$e'); - } - + LoadingDialogHelper.show(); + try { + final result = await ApiService.saveSafeFunctionSure( + 'cutroad', + formData, + signImages, + ); + LoadingDialogHelper.hide(); + if (result['result'] == 'success') { + ToastUtil.showSuccess(context, '保存成功'); + Navigator.of(context).pop(true); + } + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '操作失败:$e'); + } } } @@ -268,7 +188,6 @@ setState(() { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), CutroadFormBaseWork( @@ -290,7 +209,8 @@ setState(() { child: ListItemFactory.createRowSpaceBetweenItem( leftText: '作业开始时间', rightText: startTime.isEmpty ? '请选择' : startTime, - isRight: true, isRequired: true + isRight: true, + isRequired: true, ), ), ], @@ -310,34 +230,35 @@ setState(() { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text('* ', style: TextStyle(color: Colors.red)), - ListItemFactory.headerTitle('作业开始时间负责人'), - ], - ), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + // Divider(), + // Column( + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Row( + // children: [ + // Text('* ', style: TextStyle(color: Colors.red)), + // ListItemFactory.headerTitle('作业开始时间负责人'), + // ], + // ), + // CustomButton( + // text: '新增手写签字', + // height: 36, + // backgroundColor: Colors.green, + // onPressed: () { + // _sign(); + // }, + // ), + // ], + // ), + // if (signImages.isNotEmpty) _signListWidget(), + // ], + // ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 e61de04..4dc0dd2 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 @@ -344,7 +344,7 @@ class _CutroadYsgdDetailState extends State { Column( children: [ ListItemFactory.createBuildMultilineInput( - '完工验收', + '完工验收意见', '请输入意见', _contentController, isRequired: true, 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 34f90d2..33927a3 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 @@ -10,7 +10,7 @@ import 'package:qhd_prevention/tools/h_colors.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用动土作业明细表单组件(支持编辑/只读) class BreakgroundDetailFormWidget extends StatefulWidget { @@ -472,7 +472,7 @@ class _BreakgroundDetailFormWidgetState const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart index 6c67683..d679fa9 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/SpecialWorkFormBaseWork.dart @@ -5,7 +5,7 @@ import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/Break import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; class SpecialWorkFormBaseWork extends StatelessWidget { /// 基础数据 @@ -425,18 +425,18 @@ class SpecialWorkFormBaseWork extends StatelessWidget { ), ], - // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget( - 'WORK_START', - 'WORK_START_USER_NAME', - '作业开始负责人', - context, - ), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), + // // 作业开始负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_START')) + // signItemWidget( + // 'WORK_START', + // 'WORK_START_USER_NAME', + // '作业开始负责人', + // context, + // ), + // + // // 作业结束负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_END')) + // signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), // 完工验收意见和签字 if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/jszy_work_detail/breakground_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/jszy_work_detail/breakground_jszy_detail.dart index 0b9370c..833ba48 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/jszy_work_detail/breakground_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/jszy_work_detail/breakground_jszy_detail.dart @@ -51,81 +51,6 @@ class _BreakgroundJszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -143,10 +68,7 @@ class _BreakgroundJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -285,7 +207,6 @@ class _BreakgroundJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -323,29 +244,10 @@ class _BreakgroundJszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dt_work/kszy_work_detail/breakground_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dt_work/kszy_work_detail/breakground_kszy_detail.dart index 3134c52..7ab9caa 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dt_work/kszy_work_detail/breakground_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dt_work/kszy_work_detail/breakground_kszy_detail.dart @@ -52,87 +52,9 @@ class _BreakgroundKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -268,7 +190,6 @@ class _BreakgroundKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -311,34 +232,11 @@ class _BreakgroundKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text('* ', style: TextStyle(color: Colors.red)), - ListItemFactory.headerTitle('作业开始时间负责人'), - ], - ), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 0fb3c36..e6cb1ba 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 @@ -9,7 +9,7 @@ import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用高处作业明细表单组件(支持编辑/只读) class HoistWorkDetailFormWidget extends StatefulWidget { @@ -453,7 +453,7 @@ class _HoistworkDetailFormWidgetState extends State { const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart index 3bc235e..39fa5d0 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/SpecialWorkFormBaseWork.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; import 'HoistWorkDetailFormWidget.dart'; class SpecialWorkFormBaseWork extends StatelessWidget { @@ -363,12 +363,12 @@ class SpecialWorkFormBaseWork extends StatelessWidget { ], // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), + // if (FormUtils.hasValue(signs, 'WORK_START')) + // signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), + // + // // 作业结束负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_END')) + // signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), // 完工验收意见和签字 if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/jszy_work_detail/hoistwork_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/jszy_work_detail/hoistwork_jszy_detail.dart index e22f114..4e087be 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/jszy_work_detail/hoistwork_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/jszy_work_detail/hoistwork_jszy_detail.dart @@ -51,81 +51,6 @@ class _HoistworkJszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -143,10 +68,7 @@ class _HoistworkJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -285,7 +207,6 @@ class _HoistworkJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -322,30 +243,10 @@ class _HoistworkJszyDetailState extends State { } }, ), - - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/dz_work/kszy_work_detail/hoistwork_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/dz_work/kszy_work_detail/hoistwork_kszy_detail.dart index 118e7da..4324b2d 100644 --- a/lib/pages/home/tap/tabList/special_wrok/dz_work/kszy_work_detail/hoistwork_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/dz_work/kszy_work_detail/hoistwork_kszy_detail.dart @@ -51,88 +51,9 @@ class _HoistworkKszyDetailState extends State { super.initState(); _getData(); } - - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -268,7 +189,6 @@ class _HoistworkKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -311,34 +231,11 @@ class _HoistworkKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text('* ', style: TextStyle(color: Colors.red)), - ListItemFactory.headerTitle('作业开始时间负责人'), - ], - ), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 51e9f20..7a1fd4d 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 @@ -4,7 +4,7 @@ import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用高处作业明细表单组件(支持编辑/只读) class HighWorkDetailFormWidget extends StatefulWidget { @@ -242,7 +242,7 @@ class _HighWorkDetailFormWidgetState extends State { const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart index a56beb1..f51137a 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/SpecialWorkFormBaseWork.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; import 'HighWorkDetailFormWidget.dart'; class HighWorkFormBaseWork extends StatelessWidget { @@ -360,13 +360,13 @@ class HighWorkFormBaseWork extends StatelessWidget { ) ], - // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), + // // 作业开始负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_START')) + // signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), + // + // // 作业结束负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_END')) + // signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), // 完工验收意见和签字 if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart index 7a706e7..7800b93 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/jszy_work_detail/highwork_jszy_detail.dart @@ -51,81 +51,6 @@ class _HighworkJszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -143,10 +68,7 @@ class _HighworkJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -285,7 +207,6 @@ class _HighworkJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), HighWorkFormBaseWork( @@ -322,30 +243,10 @@ class _HighworkJszyDetailState extends State { } }, ), - - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/gc_work/kszy_work_detail/highwork_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/gc_work/kszy_work_detail/highwork_kszy_detail.dart index c07a86d..38614d0 100644 --- a/lib/pages/home/tap/tabList/special_wrok/gc_work/kszy_work_detail/highwork_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/gc_work/kszy_work_detail/highwork_kszy_detail.dart @@ -52,87 +52,9 @@ class _HighworkKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -268,7 +190,6 @@ class _HighworkKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), HighWorkFormBaseWork( @@ -311,34 +232,11 @@ class _HighworkKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text('* ', style: TextStyle(color: Colors.red)), - ListItemFactory.headerTitle('作业开始时间负责人'), - ], - ), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), + ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 f74db75..8f9b667 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 @@ -4,7 +4,7 @@ import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用明细表单组件(支持编辑/只读) class ElectricityDetailFormWidget extends StatefulWidget { @@ -87,7 +87,7 @@ class _ElectricityDetailFormWidgetState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -143,10 +68,7 @@ class _ElectricityJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -285,7 +207,6 @@ class _ElectricityJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -329,29 +250,10 @@ class _ElectricityJszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/kszy_work_detail/electricity_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/kszy_work_detail/electricity_kszy_detail.dart index 902e599..5e3888f 100644 --- a/lib/pages/home/tap/tabList/special_wrok/lsyd_work/kszy_work_detail/electricity_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/lsyd_work/kszy_work_detail/electricity_kszy_detail.dart @@ -51,88 +51,9 @@ class _ElectricityKszyDetailState extends State { super.initState(); _getData(); } - - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -280,7 +201,6 @@ class _ElectricityKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -323,29 +243,10 @@ class _ElectricityKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业开始时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 8115ee7..7cc1655 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 @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; @@ -6,9 +7,10 @@ import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; +import 'package:qhd_prevention/http/ApiService.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; class MBCD_data_model { String BOARD_MATERIAL; @@ -46,12 +48,17 @@ class BlindboardDetailFormWidget extends StatefulWidget { final bool isEditable; final VoidCallback onChooseLevel; -// 新增 -/// 选择摄像头 - final VoidCallback? onChooseVideoManager;/// 承包商 + + // 新增 + /// 选择摄像头 + final VoidCallback? onChooseVideoManager; + + /// 承包商 final VoidCallback? onContractorHandle; + /// 作业区域 final VoidCallback? onWorkAreaHandle; + /// 作业地点经纬度 final VoidCallback? onWorkAreaLocationHandle; @@ -64,12 +71,16 @@ class BlindboardDetailFormWidget extends StatefulWidget { final TextEditingController? relatedController; final TextEditingController? riskController; + /// 其他签字数据 + final signs; + const BlindboardDetailFormWidget({ Key? key, required this.pd, required this.isEditable, required this.onChooseLevel, required this.boardList, + /// 新增 this.onChooseVideoManager, this.onContractorHandle, @@ -82,6 +93,7 @@ class BlindboardDetailFormWidget extends StatefulWidget { this.pressureController, this.relatedController, this.riskController, + this.signs = null, }) : assert( !isEditable || (nameController != null && @@ -115,15 +127,196 @@ class _BlindboardDetailFormWidgetState } } + Widget _itemContainer(Widget child) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8), + child: child, + ); + } + + Widget signItemWidget(String signKey, BuildContext context) { + return _itemContainer( + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (FormUtils.hasValue(widget.signs, signKey)) + ...((widget.signs[signKey] as List) + .cast>() + .map((item) { + // 解析 SIGN_PATH + List signPaths = []; + final rawSP = + FormUtils.hasValue(item, 'SIGN_PATH') + ? item['SIGN_PATH'] + : null; + if (rawSP is String && rawSP.isNotEmpty) { + signPaths = rawSP.split(',').map((s) => s.trim()).toList(); + } else if (rawSP is List) { + signPaths = rawSP.cast(); + } + + // 解析 SIGN_TIME 保留空格 + List signTimes = []; + final rawST = + FormUtils.hasValue(item, 'SIGN_TIME') + ? item['SIGN_TIME'] + : null; + if (rawST is String && rawST.isNotEmpty) { + signTimes = rawST.split(','); + } else if (rawST is List) { + signTimes = rawST.cast(); + } + + final pairCount = math.min( + signPaths.length, + signTimes.length, + ); + + // 解析 IMG_PATH, 最多 2 张 + List imgPaths = []; + final rawIP = + FormUtils.hasValue(item, 'IMG_PATH') + ? item['IMG_PATH'] + : null; + if (rawIP is String && rawIP.isNotEmpty) { + imgPaths = + rawIP.split(',').map((s) => s.trim()).take(2).toList(); + } else if (rawIP is List) { + imgPaths = rawIP.cast().take(2).toList(); + } + + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, + horizontal: 10, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (imgPaths.isNotEmpty) ...[ + Row( + children: + imgPaths.map((p) { + final fullUrl = '${ApiService.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: 50, + height: 50, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => const Icon( + Icons.broken_image, + size: 40, + ), + ), + ), + ), + ); + }).toList(), + ), + const SizedBox(height: 8), + ], + + // 签名及时间 + ...List.generate(pairCount, (index) { + final imgPath = signPaths[index]; + final timeLabel = signTimes[index]; + final fullUrl = '${ApiService.baseImgPath}$imgPath'; + const imageWidth = 200.0; + const imageHeight = 100.0; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: + () => presentOpaque( + SingleImageViewer( + imageUrl: fullUrl, + ), + context, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: Image.network( + fullUrl, + width: imageWidth, + height: imageHeight, + fit: BoxFit.fill, + errorBuilder: + (_, __, ___) => const Icon( + Icons.broken_image, + size: 60, + ), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: SizedBox( + height: imageHeight, + child: Align( + alignment: Alignment.bottomRight, + child: Text( + timeLabel, + style: const TextStyle( + fontSize: 14, + color: Colors.black87, + ), + ), + ), + ), + ), + ], + ), + if (index < pairCount - 1) + const Padding( + padding: EdgeInsets.only(top: 8.0), + child: Divider(height: 1), + ), + ], + ), + ); + }), + ], + ), + ); + }) + .toList()), + ], + ), + ); + } + @override Widget build(BuildContext context) { final boardList = widget.boardList; if (FormUtils.hasValue(widget.pd, 'LATITUDE')) { - widget.pd['LATITUDE_LONGITUDE'] = '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map + widget.pd['LATITUDE_LONGITUDE'] = + '${widget.pd['LATITUDE']},${widget.pd['LONGITUDE']}'; //参数map } final pd = widget.pd; - return Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: const BoxDecoration( @@ -142,7 +335,7 @@ class _BlindboardDetailFormWidgetState const Divider(), ], ItemListWidget.singleLineTitleText( - label: '申请部门:', + label: '作业申请单位:', isEditable: false, text: pd['APPLY_DEPARTMENT_NAME'] ?? '', ), @@ -152,16 +345,24 @@ class _BlindboardDetailFormWidgetState isEditable: false, text: pd['APPLY_USER_NAME'] ?? '', ), + if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[ + const Divider(), + ItemListWidget.singleLineTitleText( + label: '作业单位:', + isEditable: false, + text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '', + ), + ], const Divider(), ItemListWidget.selectableLineTitleTextRightButton( - label: '作业方式:', + label: '作业类别:', isEditable: widget.isEditable, onTap: widget.onChooseLevel, text: _getWorkLevelText(pd['WORK_TYPE']), ), const Divider(), ItemListWidget.singleLineTitleText( - label: '设备管道名称:', + label: '设备、管道名称:', isEditable: widget.isEditable, controller: widget.nameController, text: pd['NAME'] ?? '', @@ -205,7 +406,10 @@ class _BlindboardDetailFormWidgetState Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ListItemFactory.createBuildSimpleSection('盲板抽堵参数', horPadding: 0), + ListItemFactory.createBuildSimpleSection( + '盲板抽堵参数', + horPadding: 0, + ), if (widget.isEditable) CustomButton( onPressed: () { @@ -237,6 +441,7 @@ class _BlindboardDetailFormWidgetState ), ItemListWidget.singleLineTitleText( label: '材质:', + isRequired: widget.isEditable, isEditable: widget.isEditable, text: board['BOARD_MATERIAL'], hintText: '请输入材质', @@ -245,12 +450,12 @@ class _BlindboardDetailFormWidgetState board['BOARD_MATERIAL'] = val; }); }, - isRequired: false, ), const Divider(), ItemListWidget.singleLineTitleText( label: '规格:', + isRequired: widget.isEditable, isEditable: widget.isEditable, text: board['BOARD_SPECIFICATION'], onChanged: (val) { @@ -259,13 +464,13 @@ class _BlindboardDetailFormWidgetState }); }, hintText: '请输入规格', - isRequired: false, ), const Divider(), ItemListWidget.singleLineTitleText( label: '编号:', isEditable: widget.isEditable, + isRequired: widget.isEditable, text: board['BOARD_NO'], onChanged: (val) { setState(() { @@ -273,35 +478,99 @@ class _BlindboardDetailFormWidgetState }); }, hintText: '请输入编号', - isRequired: false, ), - if (boardList.indexOf(board) != boardList.length-1) + if (boardList.indexOf(board) != boardList.length - 1) const Divider(), - ], ), ); }), - const Divider(), - if (!widget.isEditable && FormUtils.hasValue(pd, 'BOARD_PATH')) ...[ - ItemListWidget.singleLineTitleText( - label: '盲板抽堵位置及安全措施:', - isEditable: false, - text:'', - ), + if (FormUtils.hasValue(pd, 'WORK_START_DATE')) ...[ const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '盲板作业实施时间:', + isEditable: widget.isEditable, + text: pd['WORK_START_DATE'] ?? '', + ), + ] else ...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业开始时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + mode: BottomPickerMode.dateTimeWithSeconds, + context, + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_START_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); - ], - if (!widget.isEditable && FormUtils.hasValue(pd, 'BOARD_PATH')) ...[ - ItemListWidget.twoRowTitleAndImages( - onTapCallBack: (val) { - presentOpaque(SingleImageViewer(imageUrl: val), context); + /// 开始时间必须早于结束时间 + if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && + !isBeforeStr( + pd['WORK_EXPECTED_START_TIME'], + pd['WORK_EXPECTED_END_TIME'], + )) { + pd['WORK_EXPECTED_END_TIME'] = ''; + } + }); + } }, - title: '断路地段示意图:', - imageUrls: pd['BOARD_PATH'], + text: pd['WORK_EXPECTED_START_TIME'] ?? '', ), const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '预计作业结束时间:', + isEditable: widget.isEditable, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + context, + minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', + allowFuture: true, + ); + if (picked != null) { + setState(() { + pd['WORK_EXPECTED_END_TIME'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + }); + } + }, + text: pd['WORK_EXPECTED_END_TIME'] ?? '', + ), ], + if (!widget.isEditable && + FormUtils.hasValue(pd, 'BOARD_PATH_NO')) + ConfirmWithSignWidget( + signs: widget.signs, + pd: pd, + baseImgPath: ApiService.baseImgPath, + sectionKey: 'WORKSHOP', + nameKey: '', + headerTitle: '盲板位置图(可另附图)及编号', + imgsKey: 'BOARD_PATH', + contentKey: 'BOARD_PATH_NO', + roleTitle: '', + ), + + if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && !widget.isEditable) ...[ + const Divider(), + SignRowImageTitle(label: '作业负责人:', signKey: 'CONFIRM', signs: widget.signs, text: pd['CONFIRM_USER_NAME']??'',), + ], + if (FormUtils.hasValue(pd, 'WORK_USER_USER_NAME') && !widget.isEditable) ...[ + const Divider(), + SignRowImageTitle(label: '作业人:', signKey: 'WORK_USER', signs: widget.signs, text: pd['WORK_USER_USER_NAME']??'',), + ], + if (FormUtils.hasValue(pd, 'GUARDIAN_USER_NAME') && !widget.isEditable) ...[ + const Divider(), + SignRowImageTitle(label: '监护人:', signKey: 'GUARDIAN', signs: widget.signs, text: pd['GUARDIAN_USER_NAME']??'',), + ], + const Divider(), + ItemListWidget.twoRowButtonTitleText( label: '关联其他特殊作业及安全作业票编号', isRequired: false, @@ -352,75 +621,11 @@ class _BlindboardDetailFormWidgetState controller: widget.riskController, text: pd['RISK_IDENTIFICATION'] ?? '', ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '作业视频监控:', - isClean: widget.isEditable, - cleanText: '清除监控', - onTapClean: () { - setState(() { - pd['VIDEONAME'] = ''; - pd['VIDEOMANAGER_ID'] = ''; - }); - }, - isRequired: false, - isEditable: widget.isEditable, - onTap: widget.onChooseVideoManager ?? () {}, - text: pd['VIDEONAME'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业开始时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - mode: BottomPickerMode.dateTimeWithSeconds, - context, - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_START_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); - /// 开始时间必须早于结束时间 - if (FormUtils.hasValue(pd, 'WORK_EXPECTED_END_TIME') && - !isBeforeStr( - pd['WORK_EXPECTED_START_TIME'], - pd['WORK_EXPECTED_END_TIME'], - )) { - pd['WORK_EXPECTED_END_TIME'] = ''; - } - }); - } - }, - text: pd['WORK_EXPECTED_START_TIME'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '预计作业结束时间:', - isEditable: widget.isEditable, - onTap: () async { - DateTime? picked = await BottomDateTimePicker.showDate( - context, - minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '', - allowFuture: true, - ); - if (picked != null) { - setState(() { - pd['WORK_EXPECTED_END_TIME'] = DateFormat( - 'yyyy-MM-dd HH:mm:ss', - ).format(picked); - }); - } - }, - text: pd['WORK_EXPECTED_END_TIME'] ?? '', - ), const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', @@ -459,10 +664,26 @@ class _BlindboardDetailFormWidgetState isInput: false, isEditable: widget.isEditable, buttonText: '定位', - onTap: widget.onWorkAreaLocationHandle ?? (){}, + onTap: widget.onWorkAreaLocationHandle ?? () {}, hintText: '', text: pd['LATITUDE_LONGITUDE'] ?? (widget.isEditable ? '' : '无'), ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '作业视频监控:', + isClean: widget.isEditable, + cleanText: '清除监控', + onTapClean: () { + setState(() { + pd['VIDEONAME'] = ''; + pd['VIDEOMANAGER_ID'] = ''; + }); + }, + isRequired: false, + isEditable: widget.isEditable, + onTap: widget.onChooseVideoManager ?? () {}, + text: pd['VIDEONAME'] ?? '', + ), ], ), ); diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart index aad20d6..d1bae90 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/BlindboardFormBaseWork.dart @@ -5,7 +5,7 @@ import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/mbcd_work/Bli import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; class BlindboardFormBaseWork extends StatelessWidget { /// 基础数据 @@ -231,6 +231,7 @@ class BlindboardFormBaseWork extends StatelessWidget { pd: pd, isEditable: isEditable, onChooseLevel: onChooseLevel, + signs: signs, ), // 2. 安全防护措施 @@ -265,134 +266,44 @@ class BlindboardFormBaseWork extends StatelessWidget { ), ), - // 4. 各环节签字及意见 - if (FormUtils.hasValue(signs, 'GUARDIAN')) - signItemWidget('GUARDIAN', 'GUARDIAN_USER_NAME', '监护人', context), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFESS', + nameKey: 'CONFESS_USER_NAME', + headerTitle: '安全交底人', + roleTitle: '安全交底人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'ACCEPT_CONFESS', + nameKey: 'ACCEPT_CONFESS_USER_NAME', + headerTitle: '接受交底人', + roleTitle: '', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'CONFIRM', + nameKey: 'CONFIRM_USER_NAME', + headerTitle: '作业负责人意见', + roleTitle: '作业负责人', + ), + ConfirmWithSignWidget( + signs: signs, + pd: pd, + baseImgPath: baseImgPath, + sectionKey: 'LEADER', + nameKey: 'LEADER_USER_NAME', + headerTitle: '所在单位负责人意见', + roleTitle: '所在单位负责人', + ), - if (FormUtils.hasValue(signs, 'CONFESS')) - signItemWidget('CONFESS', 'CONFESS_USER_NAME', '安全交底人', context), - if (FormUtils.hasValue(signs, 'ACCEPT_CONFESS')) - signItemWidget('ACCEPT_CONFESS', 'ACCEPT_CONFESS_USER_NAME', '接受交底人', context), - - // 作业负责人意见 - if (FormUtils.hasValue(signs, 'CONFIRM')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('作业负责人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['CONFIRM'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('CONFIRM', 'CONFIRM_USER_NAME', '作业负责人', context), - ], - ) - - ], - - // 所在单位负责人意见 - if (FormUtils.hasValue(signs, 'LEADER')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('所在单位意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['LEADER'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('LEADER', 'LEADER_USER_NAME', '所在单位负责人', context), - ], - ) - ], - - // 安全管理部门负责人意见 - if (FormUtils.hasValue(signs, 'AUDIT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('安全管理部门意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['AUDIT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('AUDIT', 'AUDIT_USER_NAME', '安全管理部门负责人', context), - ], - ) - ], - - // 审批人意见 - if (FormUtils.hasValue(signs, 'APPROVE')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('审批人意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['APPROVE'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('APPROVE', 'APPROVE_USER_NAME', '审批负责人', context), - ], - ) - ], - - // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), - - // 完工验收意见和签字 - if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ - Column( - children: [ - _itemContainer( - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: ListItemFactory.headerTitle('完工验收意见'),), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(signs['ACCEPT'][0]['DESCR'] ?? ''), - ), - ], - ), - ), - Divider(height: 1,), - signItemWidget('ACCEPT', 'ACCEPT_USER_NAME', '验收部门负责人', context), - ], - ) - ], ], ); } 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 4033a41..d233c10 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 @@ -59,7 +59,6 @@ class _BlindboardListPageState extends State { void initState() { super.initState(); _fetchSteps(); - _fetchData(); _scrollController.addListener(_onScroll); } @@ -83,12 +82,12 @@ class _BlindboardListPageState extends State { Future _fetchSteps() async { try { final response = await ApiService.searchGetTaskSetps(13); - setState(() { - stepList = [ - {'STEP_NAME': '全部', 'STEP_ID': ''}, - ...response['list'] ?? [], - ]; - }); + stepList = [ + {'STEP_NAME': '全部', 'STEP_ID': ''}, + ...response['list'] ?? [], + ]; + _fetchData(); + } catch (e) { print('Error fetching steps: $e'); } @@ -97,7 +96,12 @@ class _BlindboardListPageState extends State { Future _fetchData() async { if (isLoading) return; setState(() => isLoading = true); - + int code = 0; + for (Map item in stepList) { + if (item['STEP_NAME'] == widget.flow) { + code = item['STEP_ID'] ?? ''; + } + } try { final data = { 'CREATOR': @@ -106,6 +110,7 @@ class _BlindboardListPageState extends State { widget.flow == '气体检测' ? SessionService.instance.loginUserId : '', 'STEP_NAME': (widget.flow == '提交申请' || widget.flow == '气体检测') ? '' : widget.flow, + 'STEP_CODE': (widget.flow == '提交申请' || widget.flow == '气体检测') ? '' : code, 'STEP_ID': sindex > 0 ? stepList[sindex]['STEP_ID'] : '', 'KEYWORDS': searchKeywords, 'WORK_STATE': '0', @@ -177,7 +182,7 @@ class _BlindboardListPageState extends State { case '提交申请': await pushPage(BlindboardApplyDetail(BLINDBOARD_ID: item['BLINDBOARD_ID'], flow: widget.flow), context); break; - case '车间人员签字': + case '盲板抽堵位置图负责人': await pushPage(BlindboardCjryDetail(BLINDBOARD_ID: item['BLINDBOARD_ID'], flow: widget.flow), context); break; case '设置安全措施确认人': @@ -225,7 +230,6 @@ class _BlindboardListPageState extends State { } setState(() { _fetchSteps(); - _fetchData(); }); // Navigator.pushNamed( // context, diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/cjry_work_detail/blindboard_cjry_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/cjry_work_detail/blindboard_cjry_detail.dart index a395a57..9375e57 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/cjry_work_detail/blindboard_cjry_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/cjry_work_detail/blindboard_cjry_detail.dart @@ -16,6 +16,7 @@ import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/CutroadFormBaseWork.dart'; + /// 本地路径 + 线上路径模型 class ImageData { String localPath; @@ -23,7 +24,8 @@ class ImageData { ImageData({required this.localPath, required this.serverPath}); } -///车间人员签字 + +///盲板抽堵位置图负责人 class BlindboardCjryDetail extends StatefulWidget { const BlindboardCjryDetail({ super.key, @@ -48,6 +50,7 @@ class _BlindboardCjryDetailState extends State { // final TextEditingController _contentController = TextEditingController(); late List imgList = []; + /// 安全防护措施列表 late List> measuresList = []; late Map signs = {}; @@ -70,7 +73,7 @@ class _BlindboardCjryDetailState extends State { await NativeOrientation.setPortrait(); if (path != null) { final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); -setState(() { + setState(() { signImages.add(path); signTimes.add(now); }); @@ -144,21 +147,22 @@ setState(() { String reasonText = ''; if (status == '1') { - // if (_contentController.text.trim().isEmpty) { - // ToastUtil.showNormal(context, '盲板抽堵位置及安全措施'); - // return; - // } if (imgList.isEmpty) { ToastUtil.showNormal(context, '请上传盲板抽堵位置图'); return; } + if (!FormUtils.hasValue(pd, 'BOARD_PATH_NO')) { + ToastUtil.showNormal(context, '请输入盲板抽堵位置图编号'); + return; + } + } else { reasonText = await CustomAlertDialog.showInput( context, title: '作废原因', hintText: '请输入作废原因', cancelText: '取消', - confirmText: '确定' + confirmText: '确定', ); if (reasonText.isEmpty) { ToastUtil.showNormal(context, '请填写作废原因'); @@ -168,7 +172,7 @@ setState(() { final serverPathString = imgList .map((e) => e.serverPath) .where((s) => s.isNotEmpty) - .map((s) => s) // 将 String? 转回 String + .map((s) => s) // 将 String? 转回 String .join(','); // 存回 measures final Map formData = {}; @@ -176,12 +180,13 @@ setState(() { // formData['WORK_CONTENT'] = _contentController.text.trim(); formData['CONIMG_PATH'] = serverPathString; - formData['DESCR'] = FormUtils.hasValue(pd, 'DESCR') ?pd['DESCR']: '无'; + formData['DESCR'] = FormUtils.hasValue(pd, 'DESCR') ? pd['DESCR'] : '无'; formData['BLINDBOARD_ID'] = pd['BLINDBOARD_ID'] ?? widget.BLINDBOARD_ID; formData['SIGNTIME'] = signTimes.join(','); formData['USER_ID'] = SessionService.instance.loginUserId; formData['APPLY_STATUS'] = status; formData['STEP_REASON'] = reasonText; + formData['BOARD_PATH_NO'] = pd['BOARD_PATH_NO']; final confirmed = await CustomAlertDialog.showConfirm( context, @@ -192,30 +197,32 @@ setState(() { barrierDismissible: false, ); if (confirmed) { - LoadingDialogHelper.show(); - try { - final result = await ApiService.saveSafeFunctionSure( -'blindboard', - formData, - signImages, - ); - LoadingDialogHelper.hide(); - if (result['result'] == 'success') { - ToastUtil.showSuccess(context, '保存成功'); - Navigator.of(context).pop(true); - } - } catch (e) { - LoadingDialogHelper.hide(); - ToastUtil.showNormal(context, '操作失败:$e'); - } - + LoadingDialogHelper.show(); + try { + final result = await ApiService.saveSafeFunctionSure( + 'blindboard', + formData, + signImages, + ); + LoadingDialogHelper.hide(); + if (result['result'] == 'success') { + ToastUtil.showSuccess(context, '保存成功'); + Navigator.of(context).pop(true); + } + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '操作失败:$e'); + } } } /// 初始化拉取数据 Future _getData() async { LoadingDialogHelper.show(); - final data = await ApiService.getHomeworkFindById('blindboard', widget.BLINDBOARD_ID); + final data = await ApiService.getHomeworkFindById( + 'blindboard', + widget.BLINDBOARD_ID, + ); setState(() { pd = data['pd']; boardList = data['boardList']; @@ -224,10 +231,11 @@ setState(() { _getMeasures(pd['BLINDBOARD_ID'] ?? ''); }); LoadingDialogHelper.hide(); - } + Future _getMeasures(String homework_id) async { - final data = await ApiService.listSignFinishMeasures('blindboard', + final data = await ApiService.listSignFinishMeasures( + 'blindboard', homework_id.length > 0 ? homework_id : widget.BLINDBOARD_ID, ); setState(() { @@ -238,13 +246,15 @@ setState(() { } Future _getSigns(String homework_id) async { - final data = await ApiService.listSignFinished('blindboard', + final data = await ApiService.listSignFinished( + 'blindboard', homework_id.length > 0 ? homework_id : widget.BLINDBOARD_ID, ); setState(() { signs = data['signs'] ?? {}; }); } + /// 拍照或选图后的回调 Future _onImageAdded(String localPath) async { // 上传到服务器 @@ -266,6 +276,7 @@ setState(() { imgList.remove(item); }); } + /// 底部按钮 Widget _bottomButtons() { return Row( @@ -300,7 +311,7 @@ setState(() { @override Widget build(BuildContext context) { return Scaffold( - appBar: MyAppbar(title: '车间人员签字'), + appBar: MyAppbar(title: '盲板抽堵位置图负责人'), body: SafeArea( child: SingleChildScrollView( padding: EdgeInsets.all(12), @@ -311,46 +322,63 @@ setState(() { pd: pd, boardList: boardList, isEditable: false, - onChooseLevel: (){}, + onChooseLevel: () {}, ), ItemListWidget.itemContainer( + horizontal: 0, Column( children: [ - ListItemFactory.headerTitle('盲板抽堵位置及安全措施'), - Divider(), RepairedPhotoSection( - title: '断路地段示意图:', + title: '盲板抽堵位置图:', maxCount: 100, mediaType: MediaType.image, onChanged: (paths) {}, isShowNum: false, - horizontalPadding: 0, + horizontalPadding: 12, isRequired: true, onMediaAdded: _onImageAdded, onMediaRemoved: (path) { - final item = imgList.firstWhere((e) => e.localPath == path); + final item = imgList.firstWhere( + (e) => e.localPath == path, + ); _onImageRemoved(item); }, onAiIdentify: () {}, ), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('车间人员'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], + const Divider(), + ItemListWidget.singleLineTitleText( + label: '盲板抽堵位置图编号:', + isEditable: true, + isRequired: true, + text: pd['BOARD_PATH_NO'], + onChanged: (val) { + setState(() { + pd['BOARD_PATH_NO'] = val; + }); + }, + hintText: '请输入盲板抽堵位置图编号', + ), + const Divider(), + ItemListWidget.itemContainer( + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ListItemFactory.headerTitle('盲板抽堵位置图负责人'), + CustomButton( + text: '新增手写签字', + height: 36, + backgroundColor: Colors.green, + onPressed: () { + _sign(); + }, + ), + ], + ), + if (signImages.isNotEmpty) _signListWidget(), + ], + ), ) ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/jszy_work_detail/blindboard_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/jszy_work_detail/blindboard_jszy_detail.dart index 29fb902..48f88e5 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/jszy_work_detail/blindboard_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/jszy_work_detail/blindboard_jszy_detail.dart @@ -51,82 +51,6 @@ class _BlindboardJszyDetailState extends State { super.initState(); _getData(); } - - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -144,10 +68,7 @@ class _BlindboardJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -287,7 +208,6 @@ class _BlindboardJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), BlindboardFormBaseWork( @@ -325,30 +245,10 @@ class _BlindboardJszyDetailState extends State { } }, ), - - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/kszy_work_detail/blindboard_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/kszy_work_detail/blindboard_kszy_detail.dart index b3418c4..9129d76 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/kszy_work_detail/blindboard_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/kszy_work_detail/blindboard_kszy_detail.dart @@ -53,87 +53,9 @@ class _BlindboardKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -270,7 +192,6 @@ class _BlindboardKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), BlindboardFormBaseWork( @@ -314,34 +235,10 @@ class _BlindboardKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text('* ', style: TextStyle(color: Colors.red)), - ListItemFactory.headerTitle('作业开始时间负责人'), - ], - ), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), 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 82c1ad8..103b74b 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 @@ -20,7 +20,7 @@ import 'package:qhd_prevention/pages/home/tap/workArea_picker.dart'; import 'package:qhd_prevention/customWidget/BaiDuMap/Map_page.dart'; enum EditUserType { - WORKSHOP('车间人员单位', '车间人员', true), + WORKSHOP('盲板抽堵位置图负责单位', '盲板抽堵位置图负责人', true), GUARDIAN('监护人单位', '监护人', true), CONFESS('安全交底人单位', '安全交底人', true), ACCEPT_CONFESS('接受交底人单位', '接受交底人', true), @@ -28,7 +28,7 @@ enum EditUserType { CONFIRM('作业负责人单位', '作业负责人', true), LEADER('所在单位', '所在单位负责人', true), WORK_START('实际作业开始负责人单位', '实际作业开始负责人', true), - WORK_END('作业结束负责人单位', '作业结束负责人', true), + WORK_END('实际作业结束负责人单位', '实际作业结束负责人', true), ACCEPT('验收部门', '验收部门负责人', true); /// 对应的单位显示名 @@ -71,7 +71,7 @@ class _BlindboardApplyDetailState extends State { /// 承包商列表 late List unitAllList = []; /// 作业区域列表 - late List> workAreaList = []; + late List workAreaList = []; /// -------------------------------------- late Map signs = {}; late List> measuresList = []; diff --git a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/szaq_work_detail/blindboard_set_safe_detail.dart b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/szaq_work_detail/blindboard_set_safe_detail.dart index 0ed1532..70e9eed 100644 --- a/lib/pages/home/tap/tabList/special_wrok/mbcd_work/szaq_work_detail/blindboard_set_safe_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/mbcd_work/szaq_work_detail/blindboard_set_safe_detail.dart @@ -47,13 +47,23 @@ class _BlindboardSetSafeDetailState extends State { late List measuresListCopy = []; List imagePaths = []; List signTimes = []; // 签字时间列表 + late Map signs = {}; + @override void initState() { super.initState(); _getData(); addMeasuresListCopy(); } - + Future _getSigns(String homework_id) async { + final data = await ApiService.listSignFinished( + 'blindboard', + homework_id.length > 0 ? homework_id : widget.BLINDBOARD_ID, + ); + setState(() { + signs = data['signs'] ?? {}; + }); + } String measuresListToJson() { final List> jsonList = measuresListCopy.map((item) => item.toJson()).toList(); @@ -345,8 +355,10 @@ class _BlindboardSetSafeDetailState extends State { setState(() { pd = data['pd']; boardList = data['boardList']; + _getSigns(widget.BLINDBOARD_ID); _getMeasures(); }); + } Future _getMeasures() async { @@ -564,6 +576,7 @@ class _BlindboardSetSafeDetailState extends State { pd: pd, isEditable: false, onChooseLevel: () {}, + signs: signs, ), SizedBox(height: 20), _setSafeDetailWidget(), 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 27d1108..de9469f 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 @@ -4,7 +4,7 @@ import 'package:intl/intl.dart'; import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import '../../../../../../tools/tools.dart'; import '../../../item_list_widget.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; /// 通用明细表单组件(支持编辑/只读) class SpaceWorkDetailFormWidget extends StatefulWidget { @@ -86,7 +86,7 @@ class _SpaceWorkDetailFormWidgetState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ ItemListWidget.singleLineTitleText( - label: '申请单位:', + label: '作业申请单位:', isEditable: false, text: pd['APPLY_DEPARTMENT_NAME'] ?? '', ), @@ -297,7 +297,7 @@ class _SpaceWorkDetailFormWidgetState extends State { const Divider(), ListItemFactory.createYesNoSection( verticalPadding: 0, - horizontalPadding: 0, + horizontalPadding: 2, title: '是否承包商作业', isEdit: widget.isEditable, text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '是' : '否', diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart index 59f53f7..432d394 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/SpecialWorkFormBaseWork.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../../../../../../customWidget/ItemWidgetFactory.dart'; import '../../../../../../customWidget/single_image_viewer.dart'; import '../../../../../../tools/tools.dart'; -import '../../special_Wrok/MeasuresListWidget.dart'; +import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/MeasuresListWidget.dart'; import 'SpaceWorkDetailFormWidget.dart'; class SpecialWorkFormBaseWork extends StatelessWidget { @@ -363,17 +363,16 @@ class SpecialWorkFormBaseWork extends StatelessWidget { ) ], - // 作业开始负责人签字 if (FormUtils.hasValue(signs, 'MONITOR')) signItemWidget('MONITOR', 'MONITOR_USER_NAME', '动火前在岗班长', context), // 作业开始负责人签字 - if (FormUtils.hasValue(signs, 'WORK_START')) - signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), - - // 作业结束负责人签字 - if (FormUtils.hasValue(signs, 'WORK_END')) - signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), + // if (FormUtils.hasValue(signs, 'WORK_START')) + // signItemWidget('WORK_START', 'WORK_START_USER_NAME', '作业开始负责人', context), + // + // // 作业结束负责人签字 + // if (FormUtils.hasValue(signs, 'WORK_END')) + // signItemWidget('WORK_END', 'WORK_END_USER_NAME', '作业结束负责人', context), // 完工验收意见和签字 if (FormUtils.hasValue(signs, 'ACCEPT')) ...[ diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/jszy_work_detail/spacework_jszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/jszy_work_detail/spacework_jszy_detail.dart index 9b6df78..efa5071 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/jszy_work_detail/spacework_jszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/jszy_work_detail/spacework_jszy_detail.dart @@ -51,82 +51,6 @@ class _SpaceworkJszyDetailState extends State { super.initState(); _getData(); } - - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - bool checkWorkTime(Map pd, BuildContext context) { // 解析开始和结束时间 final start = DateTime.parse(pd['WORK_START_DATE'] as String); @@ -144,10 +68,6 @@ class _SpaceworkJszyDetailState extends State { /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } String reasonText = ''; if (status == '1') { if (endTime.isEmpty) { @@ -286,7 +206,6 @@ class _SpaceworkJszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -332,30 +251,10 @@ class _SpaceworkJszyDetailState extends State { } }, ), - - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业结束时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/kszy_work_detail/spacework_kszy_detail.dart b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/kszy_work_detail/spacework_kszy_detail.dart index f84bdcd..0040579 100644 --- a/lib/pages/home/tap/tabList/special_wrok/sxkj_work/kszy_work_detail/spacework_kszy_detail.dart +++ b/lib/pages/home/tap/tabList/special_wrok/sxkj_work/kszy_work_detail/spacework_kszy_detail.dart @@ -54,87 +54,9 @@ class _SpaceworkKszyDetailState extends State { _getData(); } - /// 签字 - Future _sign() async { - await NativeOrientation.setLandscape(); - final path = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => MineSignPage()), - ); - await NativeOrientation.setPortrait(); - if (path != null) { - final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now()); - setState(() { - signImages.add(path); - signTimes.add(now); - }); - } - } - - Widget _signListWidget() { - return Column( - children: - signImages.map((path) { - return Column( - children: [ - const SizedBox(height: 10), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - 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( - 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(() { - signImages.remove(path); - }); - }, - ), - ), - const SizedBox(height: 80), - ], - ), - ], - ), - ], - ); - }).toList(), - ); - } - /// 作废 -1 通过 1 Future _submit(String status) async { - if (signImages.isEmpty) { - ToastUtil.showNormal(context, '请签字'); - return; - } + String reasonText = ''; if (status == '1') { if (startTime.isEmpty) { @@ -279,7 +201,6 @@ class _SpaceworkKszyDetailState extends State { child: SingleChildScrollView( padding: EdgeInsets.all(12), child: Column( - spacing: 12, children: [ // _setSafeDetailWidget(), SpecialWorkFormBaseWork( @@ -325,29 +246,10 @@ class _SpaceworkKszyDetailState extends State { }, ), - Divider(), - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('作业开始时间负责人'), - CustomButton( - text: '新增手写签字', - height: 36, - backgroundColor: Colors.green, - onPressed: () { - _sign(); - }, - ), - ], - ), - if (signImages.isNotEmpty) _signListWidget(), - ], - ), ], ), ), + const SizedBox(height: 12,), _bottomButtons(), ], ), diff --git a/lib/pages/home/tap/tabList/work_tab_mbcd_list.dart b/lib/pages/home/tap/tabList/work_tab_mbcd_list.dart index cfd5b76..c8dab2d 100644 --- a/lib/pages/home/tap/tabList/work_tab_mbcd_list.dart +++ b/lib/pages/home/tap/tabList/work_tab_mbcd_list.dart @@ -37,7 +37,7 @@ class _WorkTabMbcdListState extends State { }, { "icon": "assets/icon-apps/icon-yh-1.png", - "title": "车间人员\n签字", + "title": "盲板抽堵位置图\n负责人意见", "unreadCount": eight_work_count['WORKSHOP'] ?? '0', }, { @@ -105,7 +105,7 @@ class _WorkTabMbcdListState extends State { String title = ''; switch (index) { case 0: title = '提交申请'; break; - case 1: title = '车间人员签字'; break; + case 1: title = '盲板抽堵位置图负责人'; break; case 2: title = '设置安全措施确认人'; break; case 3: title = '安全措施确认'; break; case 4: title = '监护人签字'; break; diff --git a/lib/tools/h_colors.dart b/lib/tools/h_colors.dart index 5553432..ede82a1 100644 --- a/lib/tools/h_colors.dart +++ b/lib/tools/h_colors.dart @@ -1,7 +1,10 @@ import 'dart:ffi'; import 'dart:ui'; +import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart'; + Color h_backGroundColor() => Color(0xFFF1F1F1); + List riskLevelTextColors() { return [Color(0xFFE54D42),Color(0xFFF37B1D),Color(0xFFF9BD08),Color(0xFF3281FF)]; } diff --git a/lib/tools/tools.dart b/lib/tools/tools.dart index 15ea21e..031a6b9 100644 --- a/lib/tools/tools.dart +++ b/lib/tools/tools.dart @@ -445,7 +445,7 @@ class FormUtils { /// - String:去掉首尾空白后非空 -> true /// - Iterable / Map:非空 -> true /// - 其它类型(int、double、bool 等)只要不为 null 就算有值 -> true - static bool hasValue(Map data, String key) { + static bool hasValue(Map data, String key) { if (!data.containsKey(key)) return false; final val = data[key]; if (val == null) return false;