xufei 2025-09-10 13:50:32 +08:00
commit e7d38f12aa
53 changed files with 3330 additions and 3318 deletions

View File

@ -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),

View File

@ -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<List<T>?> null
class CenterMultiPicker {
static Future<List<T>?> show<T>(
BuildContext context, {
required List<T> items,
required Widget Function(T item) itemBuilder,
List<int>? initialSelectedIndices,
int? maxSelection,
bool allowEmpty = false,
double itemHeight = 52,
double maxHeightFactor = 0.75, //
String? title,
}) {
if (items.isEmpty) return Future.value(null);
//
final initialSet = <int>{};
if (initialSelectedIndices != null) {
for (final i in initialSelectedIndices) {
// if (i >= 0 && i < items.length) initialSet.add(i);
}
}
return showDialog<List<T>?>(
context: context,
barrierDismissible: true,
builder: (ctx) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
insetPadding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 24,
),
child: _CenterMultiPickerBody<T>(
items: items,
itemBuilder: itemBuilder,
initialSelected: initialSet,
maxSelection: maxSelection,
allowEmpty: allowEmpty,
itemHeight: itemHeight,
maxHeightFactor: maxHeightFactor,
title: title,
),
);
},
);
}
}
class _CenterMultiPickerBody<T> 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<T> items;
final Widget Function(T item) itemBuilder;
final Set<int> initialSelected;
final int? maxSelection;
final bool allowEmpty;
final double itemHeight;
final double maxHeightFactor;
final String? title;
@override
State<_CenterMultiPickerBody<T>> createState() =>
_CenterMultiPickerBodyState<T>();
}
class _CenterMultiPickerBodyState<T> extends State<_CenterMultiPickerBody<T>> {
late Set<int> _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<int>.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);
},
),
),
],
),
),
],
),
);
}
}

View File

@ -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<Map<String, dynamic>> safeCheckDangerAcceptanceSubmit(Map data) {
return HttpManager().request(
basePath,
'/app/hidden/finalcheck',
method: Method.post,
data: {
...data,
},
);
}
static Future<Map<String, dynamic>> getUpdateInfo() {
return HttpManager().request(

View File

@ -256,6 +256,7 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
child: _section(
ListItemFactory.createRowSpaceBetweenItem(
leftText: '隐患级别',
isRequired: true,
rightText:
hiddenForm['HIDDENLEVEL_NAME']?.toString() ??
'请选择',
@ -270,6 +271,7 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
child: _section(
ListItemFactory.createRowSpaceBetweenItem(
leftText: '隐患类型',
isRequired: true,
rightText:
hiddenForm['HIDDENTYPE_NAME']?.toString() ??
'请选择',
@ -325,27 +327,11 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
),
),
] 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<SafeDrawerPage> {
),
child: ListItemFactory.createRowSpaceBetweenItem(
leftText: '整改人',
isRequired: true,
rightText:
hiddenForm['RECTIFICATIONOR_NAME']
?.toString() ??
@ -373,6 +360,7 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
child: _section(
ListItemFactory.createRowSpaceBetweenItem(
leftText: '整改期限',
isRequired: true,
rightText:
hiddenForm['RECTIFICATIONDEADLINE']
?.toString() ??
@ -510,8 +498,10 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
'1',
);
setState(
() =>
_personCache = List<Map<String, dynamic>>.from(res['varList'] ?? []),
() {
_personCache = List<Map<String, dynamic>>.from(res['varList'] ?? []);
}
);
}
@ -528,11 +518,12 @@ class _SafeDrawerPageState extends State<SafeDrawerPage> {
// choice
setState(() {
hiddenForm['RECTIFICATIONOR_NAME'] = choice;
Map<String, dynamic>? target = widget.toCheckUnitList.firstWhere(
(item) => item['RECTIFICATIONOR_NAME'] == choice,
Map<String, dynamic> 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);
});
}

View File

@ -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';
///
/// BadgeManagernotify 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<void> 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<T> _safe<T>(Future<T> 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<String, dynamic>? ?? {};
_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<String, dynamic>? ?? {}).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<void> initAllModules() async {
// await Future.wait使
try {
// _safe
final fWork = _safe<Map<String, dynamic>>(
ApiService.getWork().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 6),
);
final fNotif = _safe<Map<String, dynamic>>(
ApiService.getNotifRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 4),
);
final fCheck = _safe<Map<String, dynamic>>(
ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
final fRed = _safe<Map<String, dynamic>>(
ApiService.getRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
// progressive update
fWork.then((workJson) {
try {
final hid = (workJson['hidCount'] as Map<String, dynamic>?) ?? {};
_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<String, dynamic>?) ?? {};
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<String, dynamic>? ?? {};
_appDysCount = (hid['dys'] ?? 0) as int;
_appDzgCount = (hid['dzg'] ?? 0) as int;
final workJson = await _safe<Map<String, dynamic>>(
ApiService.getWork().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
final hid = (workJson['hidCount'] as Map<String, dynamic>?) ?? {};
_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<Map<String, dynamic>>(
ApiService.getNotifRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
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<Map<String, dynamic>>(
ApiService.getSafetyEnvironmentalInspectionCount().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
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<Map<String, dynamic>>(
ApiService.getRedPoint().then((r) => r as Map<String, dynamic>),
<String, dynamic>{},
timeout: const Duration(seconds: 5),
);
int sum = 0;
(redPointJson['count'] as Map<String, dynamic>? ?? {}).values.forEach((
v,
) {
sum += (v ?? 0) as int;
});
final m = (redPointJson['count'] as Map<String, dynamic>?) ?? {};
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();
}
}

View File

@ -334,9 +334,9 @@ class HomePageState extends State<HomePage> {
final data = await ApiService.getWork();
final hidCount = data['hidCount'] as Map<String, dynamic>? ?? {};
// BadgeManager
BadgeManager().updateEnvInspectCount();
BadgeManager().updateEightWorkCount();
// // BadgeManager
// BadgeManager().updateEnvInspectCount();
// BadgeManager().updateEightWorkCount();
//
final results = await Future.wait([

View File

@ -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<dynamic>? imageUrls,
required String text, //
required List<dynamic>? signUrls, ///
required List<dynamic>? 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,
);
}

View File

@ -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<Map<String, dynamic>> measuresList;
final List<dynamic> 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? ?? '',
// ),
// 14 +
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<String> 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 = <List<String>>[];
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<String>()
.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<String>().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<SelectionPopup> {
@override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5), //
@ -1010,7 +1124,7 @@ class _SelectionPopupState extends State<SelectionPopup> {
onPressed: _getData,
),
),
const SizedBox(width: 10,),
const SizedBox(width: 10),
//
Expanded(
child: CustomButton(
@ -1042,17 +1156,28 @@ class _SelectionPopupState extends State<SelectionPopup> {
: 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<SelectionPopup> {
});
},
);
},
),
),
@ -1102,3 +1226,606 @@ class _SelectionPopupState extends State<SelectionPopup> {
);
}
}
///
/// //
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<String, dynamic> pd;
/// signs SIGN_PATH / SIGN_TIME / IMG_PATH
final Map<String, dynamic> 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<Widget> _buildSignItems(BuildContext context) {
final list = <Widget>[];
final rawList = signs[signKey];
if (rawList is! List) {
return list;
}
//
final List<String> aggregatedSignPaths = [];
final List<String> aggregatedSignTimes = [];
// IMG_PATH
final List<Widget> smallThumbRows = [];
for (final raw in rawList) {
if (raw is! Map) continue;
final item = Map<String, dynamic>.from(raw);
// SIGN_PATH
List<String> 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<String>()
.map((s) => s.trim())
.where((s) => s.isNotEmpty)
.toList();
}
aggregatedSignPaths.addAll(signPaths);
// SIGN_TIME split trim
List<String> 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<String>();
}
aggregatedSignTimes.addAll(signTimes);
// IMG_PATH 2 widget list
final List<String> aggregatedImgPaths = [];
for (final raw in rawList) {
if (raw is! Map) continue;
final item = Map<String, dynamic>.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<String>()
.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<String, dynamic>? signs;
final Map<String, dynamic>? 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 ?? <String, dynamic>{};
final safePd = pd ?? <String, dynamic>{};
// 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<String, dynamic>? signs; // null
final double fontSize;
final String text;
final double imageSize;
final double gap;
List<String> _extractSignPaths() {
final List<String> imagePaths = [];
final safeSigns = signs ?? <String, dynamic>{};
final rawList = FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null;
if (rawList == null) return imagePaths;
// rawList ListString List
if (rawList is List) {
for (final raw in rawList) {
if (raw is! Map) continue;
final item = Map<String, dynamic>.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<dynamic>()
.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<dynamic>()
.where((e) => e != null)
.map((e) => e.toString().trim())
.where((s) => s.isNotEmpty),
);
}
}
//
final seen = <String>{};
final deduped = <String>[];
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(),
],
),
),
],
),
);
}
}

View File

@ -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<HotWorkDetailFormWidget> {
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<HotWorkDetailFormWidget> {
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<HotWorkDetailFormWidget> {
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<HotWorkDetailFormWidget> {
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<HotWorkDetailFormWidget> {
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<HotWorkDetailFormWidget> {
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(),

View File

@ -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<dynamic>)
.cast<Map<String, dynamic>>()
.map((item) {
// SIGN_PATH
List<String> 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<String>();
}
// SIGN_TIME
List<String> 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<String>();
}
final pairCount = math.min(signPaths.length, signTimes.length);
// IMG_PATH, 2
List<String> 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<String>().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),
],
)
],
],
);
}

View File

@ -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<HotworkApplyDetail> {
///
late Map<String, dynamic> pd = {};
late Map<String, dynamic> signs = {};
late List<Map<String, dynamic>> measuresList = [];
late List<dynamic> measuresList = [];
final TextEditingController _contentController = TextEditingController();
final TextEditingController _locationController = TextEditingController();
@ -83,10 +83,13 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
/// ------------------- -------------------
///
late List<dynamic> videoMonitoringList = [];
///
late List<dynamic> unitAllList = [];
///
late List<Map<String, dynamic>> workAreaList = [];
late List<dynamic> workAreaList = [];
/// --------------------------------------
//
@ -107,7 +110,6 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
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<HotworkApplyDetail> {
_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<HotworkApplyDetail> {
}
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<HotworkApplyDetail> {
}
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<HotworkApplyDetail> {
}
Future<void> _chooseHorkUser() async {
final choice = await BottomPicker.show<String>(
final res = await CenterMultiPicker.show<String>(
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<String>
setState(() {
pd['WORK_USER'] = choice;
_hotworkPersonController.text = choice;
Map<String, dynamic> result = workUserList.firstWhere(
(item) => item['NAME'] == choice,
orElse: () => {}, //
);
if (FormUtils.hasValue(result, 'USER_ID')) {
pd['WORK_USER_ID'] = result['USER_ID'];
List<String> names = [];
List<String> 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<HotworkApplyDetail> {
});
}
}
///
Future<void> _chooseUnitManager() async {
final choice = await BottomPicker.show<String>(
@ -267,7 +276,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
}
///
Future<void> _showLocationHandle() async{
Future<void> _showLocationHandle() async {
if (!FormUtils.hasValue(pd, 'ELECTRONIC_FENCE_AREA_ID')) {
ToastUtil.showNormal(context, '请选择作业区域');
return;
@ -276,11 +285,11 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
setState(() {
pd['LONGITUDE'] = mapData['longitue'] ?? '';
pd['LATITUDE'] = mapData['latitude'] ?? '';
pd['LATITUDE_LONGITUDE'] = '${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}';
pd['LATITUDE_LONGITUDE'] =
'${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}';
});
}
///
Future<void> _getWorkArea() async {
//FocusHelper.clearFocus(context);
@ -291,16 +300,17 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
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<void> _getVideoList() async {
final result = await ApiService.getVideomanagerList();
@ -308,6 +318,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
videoMonitoringList = result['varList'] ?? [];
});
}
///
Future<void> _getUnitListAll() async {
final result = await ApiService.getUnitListAll();
@ -315,6 +326,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
unitAllList = result['varList'] ?? [];
});
}
///
Future<void> _getPlsList() async {
final result = await ApiService.getWorkAreaList();
@ -323,8 +335,8 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
workAreaList = jsonDecode(zTreeNodes);
});
}
/// ------------------------------------------------------------
/// ------------------------------------------------------------
Widget _card(Widget child) {
return Container(
@ -476,11 +488,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
{'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<HotworkApplyDetail> {
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<HotworkApplyDetail> {
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<HotworkApplyDetail> {
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<HotworkApplyDetail> {
});
}
/// ---------------------------- --------------------------------
/// ---------------------------- --------------------------------
///
Future<void> _getData() async {
@ -632,12 +638,11 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
_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<void> _getSigns(String homework_id) async {
final data = await ApiService.listSignFinished(
'hotwork',
@ -647,13 +652,14 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
signs = data['signs'] ?? {};
});
}
Future<void> _getMeasures(String homework_id) async {
final data = await ApiService.listSignFinishMeasures(
'hotwork',
homework_id.length > 0 ? homework_id : widget.HOTWORK_ID,
);
setState(() {
measuresList = List<Map<String, dynamic>>.from(
measuresList = List<dynamic>.from(
data['finishMeasuresList'] ?? <Map<String, dynamic>>[],
);
});
@ -706,8 +712,6 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
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)),

View File

@ -51,81 +51,6 @@ class _HotworkJszyDetailState extends State<HotworkJszyDetail> {
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -163,10 +88,7 @@ class _HotworkJszyDetailState extends State<HotworkJszyDetail> {
/// -1 1
Future<void> _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<HotworkJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -349,29 +270,11 @@ class _HotworkJszyDetailState extends State<HotworkJszyDetail> {
},
),
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(),
],
),

View File

@ -52,87 +52,8 @@ class _HotworkKszyDetailState extends State<HotworkKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<HotworkKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -320,29 +240,10 @@ class _HotworkKszyDetailState extends State<HotworkKszyDetail> {
},
),
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(),
],
),

View File

@ -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<CutroadDetailFormWidget> createState() => _CutroadDetailFormWidgetState();
State<CutroadDetailFormWidget> createState() =>
_CutroadDetailFormWidgetState();
}
class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> {
@ -77,174 +82,184 @@ class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> {
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<dynamic>)
.cast<Map<String, dynamic>>()
.map((item) {
// SIGN_PATH
List<String> 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<String>();
}
// SIGN_PATH
List<String> 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<String>();
}
// SIGN_TIME
List<String> 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<String>();
}
// SIGN_TIME
List<String> 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<String>();
}
final pairCount = math.min(signPaths.length, signTimes.length);
final pairCount = math.min(
signPaths.length,
signTimes.length,
);
// IMG_PATH, 2
List<String> 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<String>().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<String> 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<String>().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<CutroadDetailFormWidget> {
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<CutroadDetailFormWidget> {
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<CutroadDetailFormWidget> {
onTap: () async {
final val = await showDialog<String>(
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<CutroadDetailFormWidget> {
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<String>(
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<CutroadDetailFormWidget> {
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<CutroadDetailFormWidget> {
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<CutroadDetailFormWidget> {
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),
],
)
],
),
);

View File

@ -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),
],
)
],
],
);
}

View File

@ -310,6 +310,7 @@ class _CutroadAqjdDetailState extends State<CutroadAqjdDetail> {
onAnalyzeTap: () {},
),
ItemListWidget.itemContainer(
horizontal: 5,
Column(
children: [
RepairedPhotoSection(
@ -327,6 +328,7 @@ class _CutroadAqjdDetailState extends State<CutroadAqjdDetail> {
onAiIdentify: () {},
),
ItemListWidget.itemContainer(
horizontal: 5,
Column(
children: [
Row(

View File

@ -101,7 +101,7 @@ class _CutroadListPageState extends State<CutroadListPage> {
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<CutroadListPage> {
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',

View File

@ -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),

View File

@ -51,80 +51,80 @@ class _CutroadJszyDetailState extends State<CutroadJszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<String, dynamic> pd, BuildContext context) {
//
@ -143,10 +143,10 @@ class _CutroadJszyDetailState extends State<CutroadJszyDetail> {
/// -1 1
Future<void> _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<CutroadJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
CutroadFormBaseWork(
@ -322,29 +321,30 @@ class _CutroadJszyDetailState extends State<CutroadJszyDetail> {
},
),
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(),
],
),

View File

@ -52,101 +52,22 @@ class _CutroadKszyDetailState extends State<CutroadKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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(),
],
),

View File

@ -344,7 +344,7 @@ class _CutroadYsgdDetailState extends State<CutroadYsgdDetail> {
Column(
children: [
ListItemFactory.createBuildMultilineInput(
'完工验收',
'完工验收意见',
'请输入意见',
_contentController,
isRequired: true,

View File

@ -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' ? '' : '',

View File

@ -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')) ...[

View File

@ -51,81 +51,6 @@ class _BreakgroundJszyDetailState extends State<BreakgroundJszyDetail> {
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -143,10 +68,7 @@ class _BreakgroundJszyDetailState extends State<BreakgroundJszyDetail> {
/// -1 1
Future<void> _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<BreakgroundJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -323,29 +244,10 @@ class _BreakgroundJszyDetailState extends State<BreakgroundJszyDetail> {
},
),
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(),
],
),

View File

@ -52,87 +52,9 @@ class _BreakgroundKszyDetailState extends State<BreakgroundKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<BreakgroundKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -311,34 +232,11 @@ class _BreakgroundKszyDetailState extends State<BreakgroundKszyDetail> {
},
),
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(),
],
),

View File

@ -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<HoistWorkDetailFormWidget> {
const Divider(),
ListItemFactory.createYesNoSection(
verticalPadding: 0,
horizontalPadding: 0,
horizontalPadding: 2,
title: '是否承包商作业',
isEdit: widget.isEditable,
text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '' : '',

View File

@ -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')) ...[

View File

@ -51,81 +51,6 @@ class _HoistworkJszyDetailState extends State<HoistworkJszyDetail> {
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -143,10 +68,7 @@ class _HoistworkJszyDetailState extends State<HoistworkJszyDetail> {
/// -1 1
Future<void> _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<HoistworkJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -322,30 +243,10 @@ class _HoistworkJszyDetailState extends State<HoistworkJszyDetail> {
}
},
),
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(),
],
),

View File

@ -51,88 +51,9 @@ class _HoistworkKszyDetailState extends State<HoistworkKszyDetail> {
super.initState();
_getData();
}
///
Future<void> _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<void> _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<HoistworkKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -311,34 +231,11 @@ class _HoistworkKszyDetailState extends State<HoistworkKszyDetail> {
},
),
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(),
],
),

View File

@ -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<HighWorkDetailFormWidget> {
const Divider(),
ListItemFactory.createYesNoSection(
verticalPadding: 0,
horizontalPadding: 0,
horizontalPadding: 2,
title: '是否承包商作业',
isEdit: widget.isEditable,
text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '' : '',

View File

@ -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')) ...[

View File

@ -51,81 +51,6 @@ class _HighworkJszyDetailState extends State<HighworkJszyDetail> {
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -143,10 +68,7 @@ class _HighworkJszyDetailState extends State<HighworkJszyDetail> {
/// -1 1
Future<void> _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<HighworkJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
HighWorkFormBaseWork(
@ -322,30 +243,10 @@ class _HighworkJszyDetailState extends State<HighworkJszyDetail> {
}
},
),
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(),
],
),

View File

@ -52,87 +52,9 @@ class _HighworkKszyDetailState extends State<HighworkKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<HighworkKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
HighWorkFormBaseWork(
@ -311,34 +232,11 @@ class _HighworkKszyDetailState extends State<HighworkKszyDetail> {
},
),
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(),
],
),

View File

@ -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<ElectricityDetailFormWidge
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ItemListWidget.singleLineTitleText(
label: '申请单位:',
label: '作业申请单位:',
isEditable: false,
text: pd['APPLY_DEPARTMENT_NAME'] ?? '',
),
@ -310,7 +310,7 @@ class _ElectricityDetailFormWidgetState extends State<ElectricityDetailFormWidge
const Divider(),
ListItemFactory.createYesNoSection(
verticalPadding: 0,
horizontalPadding: 0,
horizontalPadding: 2,
title: '是否承包商作业',
isEdit: widget.isEditable,
text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '' : '',

View File

@ -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 'ElectricityDetailFormWidget.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')) ...[

View File

@ -51,81 +51,6 @@ class _ElectricityJszyDetailState extends State<ElectricityJszyDetail> {
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -143,10 +68,7 @@ class _ElectricityJszyDetailState extends State<ElectricityJszyDetail> {
/// -1 1
Future<void> _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<ElectricityJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -329,29 +250,10 @@ class _ElectricityJszyDetailState extends State<ElectricityJszyDetail> {
},
),
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(),
],
),

View File

@ -51,88 +51,9 @@ class _ElectricityKszyDetailState extends State<ElectricityKszyDetail> {
super.initState();
_getData();
}
///
Future<void> _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<void> _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<ElectricityKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -323,29 +243,10 @@ class _ElectricityKszyDetailState extends State<ElectricityKszyDetail> {
},
),
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(),
],
),

View File

@ -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<dynamic>)
.cast<Map<String, dynamic>>()
.map((item) {
// SIGN_PATH
List<String> 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<String>();
}
// SIGN_TIME
List<String> 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<String>();
}
final pairCount = math.min(
signPaths.length,
signTimes.length,
);
// IMG_PATH, 2
List<String> 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<String>().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'] ?? '',
),
],
),
);

View File

@ -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),
],
)
],
],
);
}

View File

@ -59,7 +59,6 @@ class _BlindboardListPageState extends State<BlindboardListPage> {
void initState() {
super.initState();
_fetchSteps();
_fetchData();
_scrollController.addListener(_onScroll);
}
@ -83,12 +82,12 @@ class _BlindboardListPageState extends State<BlindboardListPage> {
Future<void> _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<BlindboardListPage> {
Future<void> _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<BlindboardListPage> {
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<BlindboardListPage> {
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<BlindboardListPage> {
}
setState(() {
_fetchSteps();
_fetchData();
});
// Navigator.pushNamed(
// context,

View File

@ -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<BlindboardCjryDetail> {
// final TextEditingController _contentController = TextEditingController();
late List<ImageData> imgList = [];
///
late List<Map<String, dynamic>> measuresList = [];
late Map<String, dynamic> signs = {};
@ -70,7 +73,7 @@ class _BlindboardCjryDetailState extends State<BlindboardCjryDetail> {
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<String, dynamic> 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<void> _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<void> _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<void> _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<void> _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(),
],
),
)
],
),

View File

@ -51,82 +51,6 @@ class _BlindboardJszyDetailState extends State<BlindboardJszyDetail> {
super.initState();
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -144,10 +68,7 @@ class _BlindboardJszyDetailState extends State<BlindboardJszyDetail> {
/// -1 1
Future<void> _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<BlindboardJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
BlindboardFormBaseWork(
@ -325,30 +245,10 @@ class _BlindboardJszyDetailState extends State<BlindboardJszyDetail> {
}
},
),
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(),
],
),

View File

@ -53,87 +53,9 @@ class _BlindboardKszyDetailState extends State<BlindboardKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<BlindboardKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
BlindboardFormBaseWork(
@ -314,34 +235,10 @@ class _BlindboardKszyDetailState extends State<BlindboardKszyDetail> {
},
),
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(),
],
),

View File

@ -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<BlindboardApplyDetail> {
///
late List<dynamic> unitAllList = [];
///
late List<Map<String, dynamic>> workAreaList = [];
late List<dynamic> workAreaList = [];
/// --------------------------------------
late Map<String, dynamic> signs = {};
late List<Map<String, dynamic>> measuresList = [];

View File

@ -47,13 +47,23 @@ class _BlindboardSetSafeDetailState extends State<BlindboardSetSafeDetail> {
late List<MeasureItem> measuresListCopy = [];
List<String> imagePaths = [];
List<String> signTimes = []; //
late Map<String, dynamic> signs = {};
@override
void initState() {
super.initState();
_getData();
addMeasuresListCopy();
}
Future<void> _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<Map<String, dynamic>> jsonList =
measuresListCopy.map((item) => item.toJson()).toList();
@ -345,8 +355,10 @@ class _BlindboardSetSafeDetailState extends State<BlindboardSetSafeDetail> {
setState(() {
pd = data['pd'];
boardList = data['boardList'];
_getSigns(widget.BLINDBOARD_ID);
_getMeasures();
});
}
Future<void> _getMeasures() async {
@ -564,6 +576,7 @@ class _BlindboardSetSafeDetailState extends State<BlindboardSetSafeDetail> {
pd: pd,
isEditable: false,
onChooseLevel: () {},
signs: signs,
),
SizedBox(height: 20),
_setSafeDetailWidget(),

View File

@ -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<SpaceWorkDetailFormWidget> {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ItemListWidget.singleLineTitleText(
label: '申请单位:',
label: '作业申请单位:',
isEditable: false,
text: pd['APPLY_DEPARTMENT_NAME'] ?? '',
),
@ -297,7 +297,7 @@ class _SpaceWorkDetailFormWidgetState extends State<SpaceWorkDetailFormWidget> {
const Divider(),
ListItemFactory.createYesNoSection(
verticalPadding: 0,
horizontalPadding: 0,
horizontalPadding: 2,
title: '是否承包商作业',
isEdit: widget.isEditable,
text: widget.pd['IS_CONTRACTOR_WORK'] == '1' ? '' : '',

View File

@ -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')) ...[

View File

@ -51,82 +51,6 @@ class _SpaceworkJszyDetailState extends State<SpaceworkJszyDetail> {
super.initState();
_getData();
}
///
Future<void> _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<String, dynamic> pd, BuildContext context) {
//
final start = DateTime.parse(pd['WORK_START_DATE'] as String);
@ -144,10 +68,6 @@ class _SpaceworkJszyDetailState extends State<SpaceworkJszyDetail> {
/// -1 1
Future<void> _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<SpaceworkJszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -332,30 +251,10 @@ class _SpaceworkJszyDetailState extends State<SpaceworkJszyDetail> {
}
},
),
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(),
],
),

View File

@ -54,87 +54,9 @@ class _SpaceworkKszyDetailState extends State<SpaceworkKszyDetail> {
_getData();
}
///
Future<void> _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<void> _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<SpaceworkKszyDetail> {
child: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Column(
spacing: 12,
children: [
// _setSafeDetailWidget(),
SpecialWorkFormBaseWork(
@ -325,29 +246,10 @@ class _SpaceworkKszyDetailState extends State<SpaceworkKszyDetail> {
},
),
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(),
],
),

View File

@ -37,7 +37,7 @@ class _WorkTabMbcdListState extends State<WorkTabMbcdList> {
},
{
"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<WorkTabMbcdList> {
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;

View File

@ -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<Color> riskLevelTextColors() {
return [Color(0xFFE54D42),Color(0xFFF37B1D),Color(0xFFF9BD08),Color(0xFF3281FF)];
}

View File

@ -445,7 +445,7 @@ class FormUtils {
/// - String -> true
/// - Iterable / Map -> true
/// - intdoublebool null -> true
static bool hasValue(Map<String, dynamic> data, String key) {
static bool hasValue(Map<dynamic, dynamic> data, String key) {
if (!data.containsKey(key)) return false;
final val = data[key];
if (val == null) return false;