Compare commits

..

3 Commits

Author SHA1 Message Date
hs 5edff0f2e2 Merge remote-tracking branch 'origin/master' 2026-06-15 16:06:27 +08:00
hs 1362a301c0 危险作业需求变更bug 2026-06-15 16:06:22 +08:00
hs 3c4e30bc88 危险作业需求变更 2026-06-15 15:24:33 +08:00
27 changed files with 888 additions and 940 deletions

View File

@ -476,6 +476,11 @@ enum UploadFileType {
'410', '410',
'special_operation_special_apply_involved_signature', 'special_operation_special_apply_involved_signature',
), ),
// - : '411',
specialOperationInAndOutRecord(
'411',
'special_operation_in_and_out_record',
),

View File

@ -926,7 +926,7 @@ class ItemListWidget {
required VoidCallback? onTapFile, // required VoidCallback? onTapFile, //
double fontSize = 14, // double fontSize = 14, //
bool isEdit = true, bool isEdit = true,
String buttonText = '气体分析详情', String buttonText = '',
double horizontalnum = horizontal_inset, double horizontalnum = horizontal_inset,
bool isRequired = false, bool isRequired = false,
final String fileUrl = '', final String fileUrl = '',
@ -991,7 +991,7 @@ class ItemListWidget {
], ],
), ),
), ),
if (isEdit) if (isEdit && buttonText.isNotEmpty)
CustomButton( CustomButton(
text: buttonText, text: buttonText,
height: 30, height: 30,

View File

@ -169,6 +169,10 @@ class SafeProtectionController extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void refresh() {
notifyListeners();
}
void ensureAtLeastOneGroup() { void ensureAtLeastOneGroup() {
if (_groups.isEmpty) { if (_groups.isEmpty) {
addGroup(); addGroup();
@ -359,6 +363,7 @@ class SafeProtectionModule extends StatefulWidget {
this.title = '安全防护措施', this.title = '安全防护措施',
this.otherTitle = '其他安全措施', this.otherTitle = '其他安全措施',
this.showOtherSection = false, this.showOtherSection = false,
this.showAddButton = false,
this.onChanged, this.onChanged,
}); });
@ -372,6 +377,7 @@ class SafeProtectionModule extends StatefulWidget {
final String title; final String title;
final String otherTitle; final String otherTitle;
final bool showOtherSection; final bool showOtherSection;
final bool showAddButton;
final SafeMeasuresChanged? onChanged; final SafeMeasuresChanged? onChanged;
@override @override
@ -451,18 +457,24 @@ class _SafeProtectionModuleState extends State<SafeProtectionModule> {
onSelectedWithData: (updateId, name, data) { onSelectedWithData: (updateId, name, data) {
setState(() { setState(() {
for (SafeMeasureGroup g in widget.controller.groups) { for (SafeMeasureGroup g in widget.controller.groups) {
// updateId if (widget.controller.groups.length > 1 &&
if (g.updateId == updateId && widget.controller.groups.length > 1) { g != group &&
g.updateId == updateId) {
ToastUtil.showNormal(context, '确认人不能重复'); ToastUtil.showNormal(context, '确认人不能重复');
return; return;
} }
} }
group.updateId = updateId; group.updateId = updateId;
group.updateName = name; group.updateName = name;
group.actUser = data['actUserId'] ?? ''; group.actUser = updateId;
group.actUserName = name;
group.departmentId = data['departmentId'] ?? ''; group.departmentId = data['departmentId'] ?? '';
group.departmentName = data['departmentName'] ?? data['actUserDepartmentName'] ?? ''; group.departmentName =
data['departmentName'] ?? data['actUserDepartmentName'] ?? '';
group.actUserDepartment = group.departmentId;
group.actUserDepartmentName = group.departmentName;
}); });
widget.controller.refresh();
widget.onChanged?.call(); widget.onChanged?.call();
}, },
); );
@ -537,6 +549,7 @@ class _SafeProtectionModuleState extends State<SafeProtectionModule> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
ListItemFactory.createBuildSimpleSection(widget.title), ListItemFactory.createBuildSimpleSection(widget.title),
if (widget.showAddButton)
CustomButton( CustomButton(
text: '添加', text: '添加',
padding: const EdgeInsets.symmetric(horizontal: 15), padding: const EdgeInsets.symmetric(horizontal: 15),

View File

@ -155,7 +155,7 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '申请日期', label: '申请时间',
text: pd['applyTime'] ?? '', text: pd['applyTime'] ?? '',
isEditable: widget.isEditable, isEditable: widget.isEditable,
onTap: () async {}, onTap: () async {},

View File

@ -143,9 +143,9 @@ class _HotWorkApplyPageState extends SpecialWorkApplyBaseState<HotWorkApplyPage>
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
// //
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '申请日期', label: '申请时间',
isEditable: isEditable, isEditable: isEditable,
onTap: () async { onTap: () async {
final picked = await BottomDateTimePicker.showDate( final picked = await BottomDateTimePicker.showDate(

View File

@ -144,7 +144,13 @@ class _BreakgroundDetailFormWidgetState extends State<BreakgroundDetailFormWidge
isEditable: false, isEditable: false,
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',

View File

@ -158,6 +158,27 @@ class _DlApplyPageState extends SpecialWorkApplyBaseState<DlApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// / // /
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
@ -360,7 +381,7 @@ class _DlApplyPageState extends SpecialWorkApplyBaseState<DlApplyPage> {
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );

View File

@ -144,7 +144,13 @@ class _CutRoadDetailFormWidgetState extends State<CutRoadDetailFormWidget> {
isEditable: false, isEditable: false,
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',

View File

@ -157,6 +157,27 @@ class _DtApplyPageState extends SpecialWorkApplyBaseState<DtApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// / // /
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
@ -346,7 +367,7 @@ class _DtApplyPageState extends SpecialWorkApplyBaseState<DtApplyPage> {
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );

View File

@ -152,6 +152,27 @@ class _DzApplyPageState extends SpecialWorkApplyBaseState<DzApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// / // /
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
@ -357,7 +378,7 @@ class _DzApplyPageState extends SpecialWorkApplyBaseState<DzApplyPage> {
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );

View File

@ -143,7 +143,13 @@ class _HoistingDetailFormWidgetState extends State<HoistingDetailFormWidget> {
isEditable: false, isEditable: false,
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',

View File

@ -140,7 +140,13 @@ class _HeighWorkDetailFormWidgetState extends State<HeighWorkDetailFormWidget> {
isEditable: false, isEditable: false,
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',

View File

@ -149,6 +149,27 @@ class _GcApplyPageState extends SpecialWorkApplyBaseState<GcApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// //
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
@ -330,7 +351,7 @@ class _GcApplyPageState extends SpecialWorkApplyBaseState<GcApplyPage> {
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );

View File

@ -146,6 +146,13 @@ class _LsydWorkDetailFormWidgetState extends State<LsydWorkDetailFormWidget> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',
isEditable: false, isEditable: false,

View File

@ -158,6 +158,27 @@ class _LsydApplyPageState extends SpecialWorkApplyBaseState<LsydApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// //
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
@ -382,7 +403,7 @@ class _LsydApplyPageState extends SpecialWorkApplyBaseState<LsydApplyPage> {
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );

View File

@ -194,7 +194,13 @@ class _MbcdDetailFormWidgetState extends State<MbcdDetailFormWidget> {
isEditable: false, isEditable: false,
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
text: pd['applyTime'] ?? '',
isEditable: widget.isEditable,
onTap: () async {},
),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '作业类型:', label: '作业类型:',

View File

@ -199,6 +199,27 @@ class _MbcdApplyPageState extends SpecialWorkApplyBaseState<MbcdApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '申请时间:',
isEditable: isEditable,
onTap: () async {
final picked = await BottomDateTimePicker.showDate(
mode: BottomPickerMode.dateTimeWithSeconds,
context,
allowFuture: true,
allowPast: false,
);
if (picked != null) {
setState(() {
pd['applyTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(
picked,
);
});
}
},
text: pd['applyTime'] ?? '',
),
const Divider(),
// //
if (enableInnerWorkSwitch) ...[ if (enableInnerWorkSwitch) ...[
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(

View File

@ -143,7 +143,7 @@ class _SxkjWorkDetailFormWidgetState extends State<SxkjWorkDetailFormWidget> {
), ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '申请日期', label: '申请时间',
text: pd['applyTime'] ?? '', text: pd['applyTime'] ?? '',
isEditable: widget.isEditable, isEditable: widget.isEditable,
onTap: () async {}, onTap: () async {},
@ -176,12 +176,12 @@ class _SxkjWorkDetailFormWidgetState extends State<SxkjWorkDetailFormWidget> {
isRequired: true, isRequired: true,
), ),
], ],
const Divider(), // const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( // ItemListWidget.selectableLineTitleTextRightButton(
label: '管理单位:', // label: '管理单位:',
isEditable: widget.isEditable, // isEditable: widget.isEditable,
text: chooseLimitedSpace['manageDeptName'] ?? '', // text: chooseLimitedSpace['manageDeptName'] ?? '',
), // ),
const Divider(), const Divider(),
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '有限空间名称及编号:', label: '有限空间名称及编号:',

View File

@ -75,39 +75,40 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
@override @override
Future<void> loadExtraData() async { Future<void> loadExtraData() async {
final data = { final data = {
"eqWorkType": SpecialWorkTypeEnum.confinedspaceWork.code, "eqWorkType": SpecialWorkTypeEnum.confinedspaceWork.code,
"pageSize": 999, "pageSize": 999,
"pageIndex": 1, "pageIndex": 1,
"eqCorpinfoId": pd['projectExecutionLocationCorpId'] ?? '', "eqCorpinfoId": pd['projectExecutionLocationCorpId'] ?? '',
}; };
final limitedSpaceRes = await SpecialWorkApi.specialWorkLimitedSpaceList(data); final limitedSpaceRes = await SpecialWorkApi.specialWorkLimitedSpaceList(
data,
);
if (limitedSpaceRes['success'] == true) { if (limitedSpaceRes['success'] == true) {
limitedSpaceList = limitedSpaceRes['data'] ?? []; limitedSpaceList = limitedSpaceRes['data'] ?? [];
} }
// //
_clearRelatedParties(); _clearRelatedParties();
} }
Future<void> _clearRelatedParties() async { Future<void> _clearRelatedParties() async {
setState(() { setState(() {
pd['limitedSpaceNameAndCode'] = ''; pd['limitedSpaceNameAndCode'] = '';
pd['chooseLimitedSpace'] = {}; pd['chooseLimitedSpace'] = {};
}); });
} }
@override @override
Future<void> afterInitDataLoaded() async { Future<void> afterInitDataLoaded() async {
// //
allowChoosePerson = { allowChoosePerson = {
'1' : { '1': {
"actUser": pd['workGuardianUser'] ?? pd['workGuardianUserId'] ?? '', "actUser": pd['workGuardianUser'] ?? pd['workGuardianUserId'] ?? '',
"actUserDepartment": pd['workGuardianUserDepartment'] ?? '', "actUserDepartment": pd['workGuardianUserDepartment'] ?? '',
"actUserDepartmentName": pd['workGuardianUserDepartmentName'] ?? '', "actUserDepartmentName": pd['workGuardianUserDepartmentName'] ?? '',
"actUserName": pd['workGuardianUserName'] ?? '', "actUserName": pd['workGuardianUserName'] ?? '',
}, },
'2' : { '2': {
"actUserDepartment": pd['workChargeUserDepartment'] ?? '', "actUserDepartment": pd['workChargeUserDepartment'] ?? '',
"actUserDepartmentName": pd['workChargeUserDepartmentName'] ?? '', "actUserDepartmentName": pd['workChargeUserDepartmentName'] ?? '',
"actUser": pd['workChargeUser'] ?? pd['workChargeUserId'] ?? '', "actUser": pd['workChargeUser'] ?? pd['workChargeUserId'] ?? '',
@ -145,9 +146,10 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
Future<Map<String, dynamic>> buildExtraPayload() async { Future<Map<String, dynamic>> buildExtraPayload() async {
final preparers = safeController.buildPreparers(); final preparers = safeController.buildPreparers();
return { return {
'others': {'measures': preparers} 'others': {'measures': preparers},
}; };
} }
@override @override
Widget buildFormContent() { Widget buildFormContent() {
final chooseLimitedSpace = (pd['chooseLimitedSpace'] as Map?) ?? {}; final chooseLimitedSpace = (pd['chooseLimitedSpace'] as Map?) ?? {};
@ -204,9 +206,9 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
text: pd['applyUser'] ?? '', text: pd['applyUser'] ?? '',
), ),
const Divider(), const Divider(),
// //
ItemListWidget.selectableLineTitleTextRightButton( ItemListWidget.selectableLineTitleTextRightButton(
label: '申请日期', label: '申请时间',
isEditable: isEditable, isEditable: isEditable,
onTap: () async { onTap: () async {
final picked = await BottomDateTimePicker.showDate( final picked = await BottomDateTimePicker.showDate(
@ -217,7 +219,9 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
); );
if (picked != null) { if (picked != null) {
setState(() { setState(() {
pd['applyTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(picked); pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(picked);
}); });
} }
}, },
@ -244,7 +248,6 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
groupValue: pd['internalOperationFlag'] == 1, groupValue: pd['internalOperationFlag'] == 1,
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
isInnerWork = value;
pd['internalOperationFlag'] = value ? 1 : 2; pd['internalOperationFlag'] = value ? 1 : 2;
}); });
}, },
@ -266,15 +269,15 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
onTap: _chooseFromLedger, onTap: _chooseFromLedger,
text: pd['limitedSpaceNameAndCode'] ?? '', text: pd['limitedSpaceNameAndCode'] ?? '',
), ),
const Divider(), // const Divider(),
// // //
ItemListWidget.singleLineTitleText( // ItemListWidget.singleLineTitleText(
label: '管理单位:', // label: '管理单位:',
isEditable: false, // isEditable: false,
isTextFont: false, // isTextFont: false,
strongRequired: true, // strongRequired: true,
text: chooseLimitedSpace['manageDeptName'] ?? '', // text: chooseLimitedSpace['manageDeptName'] ?? '',
), // ),
const Divider(), const Divider(),
// //
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
@ -333,7 +336,8 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
isTextFont: false, isTextFont: false,
isRequired: isEditable, isRequired: isEditable,
text: pd['emergencyEquipment'] ?? '', text: pd['emergencyEquipment'] ?? '',
onChanged: (value) => setState(() => pd['emergencyEquipment'] = value), onChanged:
(value) => setState(() => pd['emergencyEquipment'] = value),
), ),
// //
if (widget.isReEdit && FormUtils.hasValue(form, 'id')) ...[ if (widget.isReEdit && FormUtils.hasValue(form, 'id')) ...[
@ -372,7 +376,8 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
label: '作业监护人', label: '作业监护人',
isEditable: isEditable, isEditable: isEditable,
text: pd['workGuardianUserName'] ?? '请选择', text: pd['workGuardianUserName'] ?? '请选择',
onTap: () => _chooseAlonePersonHandle(SelectPersonType.workGuardian), onTap:
() => _chooseAlonePersonHandle(SelectPersonType.workGuardian),
), ),
const Divider(), const Divider(),
// stepId=3 shouldHideGroup // stepId=3 shouldHideGroup
@ -405,22 +410,24 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
// //
if (item['userType'] == 2) { if (item['userType'] == 2) {
firmList.add(item); firmList.add(item);
}else{ } else {
xgfList.add(item); xgfList.add(item);
} }
} }
//0610
DepartmentAllPersonPicker.show( DepartmentAllPersonPicker.show(
context, context,
allowXgfFlag: xgfList.isNotEmpty, allowXgfFlag: false,
personsData: firmList, personsData: [...firmList,...xgfList],
serverData: xgfList, serverData: [],
onSelectedWithData: (userId, name, data) { onSelectedWithData: (userId, name, data) {
setState(() { setState(() {
groups[index]['actUser'] = userId; groups[index]['actUser'] = userId;
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId'] ?? ''; groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? ''; groups[index]['actUserDepartmentName'] =
data['departmentName'] ?? '';
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}); });
}, },
); );
@ -441,8 +448,12 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
style: BottomPickerStyle.list, style: BottomPickerStyle.list,
title: '有限空间名称及编号', title: '有限空间名称及编号',
height: MediaQuery.of(context).size.height - 120, height: MediaQuery.of(context).size.height - 120,
items: limitedSpaceList.map((item) => '${item['name']}(${item['code']})').toList(), items:
itemBuilder: (item) => Text( limitedSpaceList
.map((item) => '${item['name']}(${item['code']})')
.toList(),
itemBuilder:
(item) => Text(
item, item,
softWrap: true, softWrap: true,
maxLines: 10, maxLines: 10,
@ -469,7 +480,8 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
isScrollControlled: true, isScrollControlled: true,
barrierColor: Colors.black54, barrierColor: Colors.black54,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
builder: (_) => DepartmentPicker( builder:
(_) => DepartmentPicker(
onSelected: (id, name, data) async { onSelected: (id, name, data) async {
setState(() { setState(() {
pd['workDepartment'] = id; pd['workDepartment'] = id;
@ -478,23 +490,33 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
}); });
await _getPersonListForUnitId(id); await _getPersonListForUnitId(id);
}, },
data: {'corpinfoId': pd['projectExecutionLocationCorpId'] ?? ''}, data: {'eqCorpinfoId': pd['xgfId'] ?? ''},
), ),
); );
} }
/// ///
void _chooseAlonePersonHandle(SelectPersonType type) { void _chooseAlonePersonHandle(SelectPersonType type) {
List<dynamic> personList = allPersonList; List<dynamic> personList = [];
List<dynamic> xgfList = relatedPartiesPersonList; // List<dynamic> xgfList = relatedPartiesPersonList;
// if (pd['xgfFlag'] == 1 && relatedPartiesPersonList.isNotEmpty) { final String workDepartmentId = (pd['workDepartment'] ?? '').toString();
// personList = [...personList, ...relatedPartiesPersonList]; List<dynamic> xgfList =
// } relatedPartiesPersonList.where((item) {
if (item is! Map) return false;
return (item['departmentId'] ?? '').toString() == workDepartmentId;
}).toList();
if (!FormUtils.hasValue(pd, 'workDepartment')) {
personList = allPersonList;
}
if (personList.isEmpty) {
ToastUtil.showNormal(context, '暂无该部门人员');
return;
}
DepartmentAllPersonPicker.show( DepartmentAllPersonPicker.show(
context, context,
allowXgfFlag: pd['xgfFlag'] == 1, allowXgfFlag: false,
personsData: personList, personsData: xgfList,
serverData: xgfList, serverData: [],
onSelectedWithData: (userId, name, data) { onSelectedWithData: (userId, name, data) {
setState(() { setState(() {
if (type == SelectPersonType.workCharge) { if (type == SelectPersonType.workCharge) {
@ -503,7 +525,6 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
pd['workChargeUserDepartment'] = data['departmentId']; pd['workChargeUserDepartment'] = data['departmentId'];
pd['workChargeUserDepartmentName'] = data['departmentName']; pd['workChargeUserDepartmentName'] = data['departmentName'];
allowChoosePerson['1'] = data; allowChoosePerson['1'] = data;
} else { } else {
pd['workGuardianUserId'] = userId; pd['workGuardianUserId'] = userId;
pd['workGuardianUserName'] = name; pd['workGuardianUserName'] = name;

View File

@ -0,0 +1,277 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:qhd_prevention/constants/app_enums.dart';
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/photo_picker_row.dart';
import 'package:qhd_prevention/customWidget/single_image_viewer.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/http/modules/file_api.dart';
import 'package:qhd_prevention/http/modules/special_work_api.dart';
import 'package:qhd_prevention/pages/mine/mine_sign_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart';
class SxkjRecordAddPage extends StatefulWidget {
const SxkjRecordAddPage({super.key, required this.data});
final Map<String, dynamic> data;
@override
State<SxkjRecordAddPage> createState() => _SxkjRecordAddPageState();
}
class _SxkjRecordAddPageState extends State<SxkjRecordAddPage> {
final List<String> _images = [];
Map<String, dynamic> pd = {};
List<String> signImages = [];
List<String> signTimes = [];
bool _isSubmitting = false;
@override
void initState() {
super.initState();
pd = Map<String, dynamic>.from(widget.data);
}
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:ss').format(DateTime.now());
setState(() {
signImages = [path];
signTimes = [now];
});
}
}
String _extractUploadedPath(dynamic data) {
if (data is Map) {
final filePath = (data['filePath'] ?? '').toString();
if (filePath.isNotEmpty) return filePath;
final fileList = data['fileList'];
if (fileList is List && fileList.isNotEmpty) {
return fileList
.map(
(item) => item is Map ? (item['filePath'] ?? '').toString() : '',
)
.where((path) => path.isNotEmpty)
.join(',');
}
final foreignKey = (data['foreignKey'] ?? '').toString();
if (foreignKey.isNotEmpty) return foreignKey;
}
if (data is List && data.isNotEmpty) {
return data
.map((item) => item is Map ? (item['filePath'] ?? '').toString() : '')
.where((path) => path.isNotEmpty)
.join(',');
}
return '';
}
Future<String> _uploadRecordImages() async {
final result = await FileApi.uploadFiles(
_images,
UploadFileType.specialOperationInAndOutRecord,
'',
);
if (result['success'] == true) {
final filePath = _extractUploadedPath(result['data']);
if (filePath.isNotEmpty) return filePath;
}
throw Exception(result['errMessage'] ?? '记录图片上传失败');
}
Future<String> _uploadSignImages() async {
final paths = <String>[];
for (final signImage in signImages) {
final result = await FileApi.uploadFile(
signImage,
UploadFileType.specialOperationProcessSignaturePhoto,
'',
);
if (result['success'] == true) {
final filePath = _extractUploadedPath(result['data']);
if (filePath.isNotEmpty) {
paths.add(filePath);
continue;
}
}
throw Exception(result['errMessage'] ?? '签字上传失败');
}
return paths.join(',');
}
Future<void> _submit() async {
if (_isSubmitting) return;
if (_images.isEmpty) {
ToastUtil.showNormal(context, '请上传记录图片');
return;
}
if (signImages.isEmpty) {
ToastUtil.showNormal(context, '请签字');
return;
}
setState(() {
_isSubmitting = true;
});
LoadingDialogHelper.show();
try {
final recordFilePath = await _uploadRecordImages();
final signPath = await _uploadSignImages();
final other = {'spaceRecordFile': recordFilePath};
final params = {
'id': pd['id'],
'workId': pd['workId'],
'stepId': pd['stepId'],
'status': 1,
'specialStepCode': pd['specialStepCode'],
'signPath': signPath,
'signTime':
signTimes.isNotEmpty
? signTimes.first
: DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()),
'others': {'otherParams': jsonEncode(other)},
};
final res = await SpecialWorkApi.specialWorkNextStep(params);
if (res['success'] == true) {
ToastUtil.showNormal(context, '提交成功');
if (mounted) Navigator.pop(context, true);
} else {
ToastUtil.showNormal(context, res['errMessage'] ?? '作业提交失败');
}
} catch (e) {
ToastUtil.showNormal(
context,
e.toString().replaceFirst('Exception: ', ''),
);
} finally {
LoadingDialogHelper.hide();
if (mounted) {
setState(() {
_isSubmitting = false;
});
}
}
}
Widget _signListWidget() {
return Column(
children:
signImages.map((path) {
return Column(
children: [
const SizedBox(height: 15),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
onTap: () {
presentOpaque(
SingleImageViewer(imageUrl: path),
context,
);
},
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 200,
maxHeight: 150,
),
child: Image.file(File(path), fit: BoxFit.contain),
),
),
CustomButton(
text: 'X',
height: 30,
padding: const EdgeInsets.symmetric(horizontal: 10),
backgroundColor: Colors.red,
onPressed: () {
setState(() {
signImages.remove(path);
});
},
),
],
),
],
);
}).toList(),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: '记录上传'),
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(12),
child: Column(
children: [
RepairedPhotoSection(
isRequired: true,
title: '进出有限空间记录',
maxCount: 4,
horizontalPadding: 0,
mediaType: MediaType.image,
isShowAI: false,
onChanged: (List<File> files) {
_images.clear();
for (final file in files) {
_images.add(file.path);
}
},
onAiIdentify: () {},
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ListItemFactory.headerTitle(
'${pd['actorField'] ?? ''}签字',
isRequired: true,
),
CustomButton(
text: signImages.isNotEmpty ? '重签' : '签字',
height: 36,
padding: const EdgeInsets.symmetric(horizontal: 25),
backgroundColor: Colors.blue,
onPressed: _sign,
),
],
),
if (signImages.isNotEmpty) _signListWidget(),
const SizedBox(height: 30),
CustomButton(
text: _isSubmitting ? '提交中...' : '提交',
onPressed: _submit,
),
],
),
),
),
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:qhd_prevention/http/modules/special_work_api.dart'; import 'package:qhd_prevention/http/modules/special_work_api.dart';
import 'package:qhd_prevention/pages/home/Tap/special_header.dart'; import 'package:qhd_prevention/pages/home/Tap/special_header.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_record_add_page.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work_wait_scaffold.dart'; import 'package:qhd_prevention/pages/home/Tap/special_work_wait_scaffold.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/special_work_gas_list.dart'; import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/special_work_gas_list.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_apply_page.dart'; import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_apply_page.dart';
@ -45,12 +46,14 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
) async { ) async {
final hotworkId = item['id'] ?? ''; final hotworkId = item['id'] ?? '';
final hotworkCodeId = item['workId'] ?? ''; final hotworkCodeId = item['workId'] ?? '';
final hotworkInfo = listType == SpecialListType.task ? item['workInfo'] ?? {} : item; final hotworkInfo =
listType == SpecialListType.task ? item['workInfo'] ?? {} : item;
final stepId = '${item['stepId'] ?? ''}'; final stepId = '${item['stepId'] ?? ''}';
final status = '${hotworkInfo['status'] ?? ''}'; final status = '${hotworkInfo['status'] ?? ''}';
final String statusName = isEdit final String statusName =
isEdit
? (listType == SpecialListType.task ? (listType == SpecialListType.task
? '${item['stepName'] ?? ''}' ? '${item['stepName'] ?? ''}'
: '${hotworkInfo['currentStep'] ?? ''}') : '${hotworkInfo['currentStep'] ?? ''}')
@ -70,6 +73,10 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
} }
if (listType == SpecialListType.task) { if (listType == SpecialListType.task) {
if (stepId == '30') {
await pushPage(SxkjRecordAddPage(data: item), context);
return;
}
if (stepId == '2') { if (stepId == '2') {
if (isEdit) { if (isEdit) {
await pushPage( await pushPage(
@ -85,11 +92,7 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
if (status == '0' || status == '2') { if (status == '0' || status == '2') {
if (isEdit) { if (isEdit) {
await pushPage( await pushPage(
SxkjApplyPage( SxkjApplyPage(isReEdit: true, workId: hotworkId, status: status),
isReEdit: true,
workId: hotworkId,
status: status,
),
context, context,
); );
} else { } else {
@ -113,7 +116,6 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
Map<String, dynamic> info, Map<String, dynamic> info,
String statusName, String statusName,
) { ) {
final chooseLimitedSpace = Map<String, dynamic>.from( final chooseLimitedSpace = Map<String, dynamic>.from(
info['chooseLimitedSpace'] ?? {}, info['chooseLimitedSpace'] ?? {},
); );
@ -161,10 +163,10 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
), ),
], ],
), ),
buildWrapPairRow( // buildWrapPairRow(
'管理单位: ${chooseLimitedSpace['manageDeptName'] ?? ''}', // '管理单位: ${chooseLimitedSpace['manageDeptName'] ?? ''}',
'作业单位: ${info['workDepartmentName'] ?? ''}', // '作业单位: ${info['workDepartmentName'] ?? ''}',
), // ),
Text( Text(
'有限空间名称及编号: ${info['limitedSpaceNameAndCode'] ?? ''}', '有限空间名称及编号: ${info['limitedSpaceNameAndCode'] ?? ''}',
softWrap: true, softWrap: true,

View File

@ -1,448 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:qhd_prevention/constants/app_enums.dart';
import 'package:qhd_prevention/customWidget/BaiDuMap/Map_page.dart';
import 'package:qhd_prevention/customWidget/DocumentPicker.dart';
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
import 'package:qhd_prevention/customWidget/MultiDictValuesPicker.dart';
import 'package:qhd_prevention/customWidget/center_multi_picker.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/department_all_person_picker.dart';
import 'package:qhd_prevention/customWidget/department_person_picker.dart';
import 'package:qhd_prevention/customWidget/department_picker.dart';
import 'package:qhd_prevention/customWidget/department_picker_three.dart';
import 'package:qhd_prevention/customWidget/item_list_widget.dart';
import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart';
import 'package:qhd_prevention/customWidget/read_file_page.dart';
import 'package:qhd_prevention/customWidget/related_parties_picker.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/tools/h_colors.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/customWidget/bottom_picker.dart';
class SxkjTzApplyPage extends StatefulWidget {
const SxkjTzApplyPage({
super.key,
required this.isEdit,
required this.work_id,
required this.info,
});
///
final bool isEdit;
final String work_id;
final Map<String, dynamic> info;
@override
State<SxkjTzApplyPage> createState() => _SxkjTzApplyPageState();
}
class _SxkjTzApplyPageState extends State<SxkjTzApplyPage> {
bool _isEditable = true;
// pd
List<Map<String, String>> rules = [
{'name': 'manageDeptName', 'message': '请选择管理单位'},
{'name': 'name', 'message': '请填写有限空间名称'},
{'name': 'code', 'message': '请填写有限空间编号'},
{'name': 'type', 'message': '请选择有限空间类型'},
{'name': 'positionAndRange', 'message': '请填写位置及范围'},
{'name': 'mediumInfo', 'message': '请填写主要介质'},
{'name': 'hazards', 'message': '请填写主要危险及有害因素'},
{'name': 'riskLevel', 'message': '请选择风险等级'},
{'name': 'protectionRequirements', 'message': '请填写防护要求'},
{'name': 'separateSafetyMeasures', 'message': '请填写隔绝安全措施'},
{'name': 'maximumNumber', 'message': '请填写最大作业人数'},
];
///
Map<String, dynamic> pd = {'isEmergencyBook': 2};
//
List typeList = [];
@override
void initState() {
super.initState();
_isEditable = widget.isEdit;
if (!widget.isEdit) {
pd = widget.info;
}
}
//
Future<void> uploadFileHandle() async {
final List<SelectedFile> picked = await DocumentPicker.showPickerModal(
context,
maxAssets: 1,
maxSizeInBytes: 20 * 1024 * 1024,
allowedExtensions: ['pdf', 'doc', 'docx'],
allowMultipleFiles: false,
showPhotoSelect: false,
);
if (picked.isNotEmpty && picked.first.path != null) {
LoadingDialogHelper.show();
final raw = await FileApi.uploadFile(
picked.first.path!,
UploadFileType.specialOperationRestrictedSpaceLedgerAttachment,
'',
);
if (raw['success']) {
LoadingDialogHelper.hide();
setState(() {
pd['emergencyBookFile'] = raw['data']['filePath'];
ToastUtil.showNormal(context, "附件上传成功");
});
} else {
ToastUtil.showNormal(context, "附件上传失败");
LoadingDialogHelper.hide();
}
}
}
//
Future<void> chooseUnitHandle() async {
showModalBottomSheet(
context: context,
isScrollControlled: true,
barrierColor: Colors.black54,
backgroundColor: Colors.transparent,
builder:
(_) => DepartmentPicker(
onSelected: (id, name, data) async {
setState(() {
pd['manageDeptName'] = name;
pd['manageDeptId'] = id;
});
},
),
).then((_) {
// FocusHelper.clearFocus(context);
});
}
///
Future<void> chooseLevelHandle() async {
showModalBottomSheet(
context: context,
isScrollControlled: true,
barrierColor: Colors.black54,
backgroundColor: Colors.transparent,
builder:
(_) => MultiDictValuesPicker(
title: '有限空间类型',
dictType: 'finiteSpaceType',
onSelected: (id, name, extraData) {
setState(() {
pd['typeName'] = name;
pd['type'] = extraData?['dictValue'] ?? '';
});
},
),
).then((_) {});
}
//
Future<void> chooseRiskLevelHandle() async {
showModalBottomSheet(
context: context,
isScrollControlled: true,
barrierColor: Colors.black54,
backgroundColor: Colors.transparent,
builder:
(_) => MultiDictValuesPicker(
title: '风险等级',
dictType: 'riskGrade',
onSelected: (id, name, extraData) {
setState(() {
pd['riskLevelName'] = name;
pd['riskLevel'] = extraData?['dictValue'] ?? '';
});
},
),
);
}
//
Future<void> _submit() async {
if (_isEditable) {
// rules
for (var item in rules) {
if (pd[item['name']] == null || pd[item['name']] == '') {
ToastUtil.showNormal(context, item['message'] ?? "请填写必填项");
return;
}
}
//
if (pd['isEmergencyBook'] == 1) {
if (pd['emergencyBookFile'] == null || pd['emergencyBookFile'] == '') {
ToastUtil.showNormal(context, '请上传应急指导书');
return;
}
}
LoadingDialogHelper.show();
final res = await SpecialWorkApi.specialWorkLimitedSpaceSave(pd);
if (res['success'] == true) {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, "提交成功");
Navigator.of(context).pop();
} else {
LoadingDialogHelper.hide();
ToastUtil.showNormal(context, res['errMessage'] ?? "作业提交失败");
}
}
}
Widget _buildDetail() {
return Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ItemListWidget.selectableLineTitleTextRightButton(
label: '管理单位:',
isEditable: _isEditable,
onTap: chooseUnitHandle,
text: pd['manageDeptName'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '有限空间名称:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['name'] ?? '',
onChanged: (value) {
setState(() {
pd['name'] = value;
});
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '有限空间编号:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['code'] ?? '',
onChanged: (value) {
setState(() {
pd['code'] = value;
});
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '有限空间类型:',
isEditable: _isEditable,
onTap: chooseLevelHandle,
text: pd['typeName'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '位置及范围:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['positionAndRange'] ?? '',
onChanged: (value) {
setState(() {
pd['positionAndRange'] = value;
});
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '主要介质:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['mediumInfo'] ?? '',
onChanged: (value) {
setState(() {
pd['mediumInfo'] = value;
});
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '主要危险及有害因素:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['hazards'] ?? '',
onChanged: (value) {
setState(() {
pd['hazards'] = value;
});
},
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '风险等级:',
isEditable: _isEditable,
onTap: chooseRiskLevelHandle,
text: pd['riskLevelName'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '防护要求:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['protectionRequirements'] ?? '',
onChanged: (value) {
setState(() {
pd['protectionRequirements'] = value;
});
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '隔绝安全措施:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
text: pd['separateSafetyMeasures'] ?? '',
onChanged: (value) {
setState(() {
pd['separateSafetyMeasures'] = value;
});
},
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '最大作业人数:',
isEditable: _isEditable,
hintText: '请输入',
isTextFont: false,
isNumericInput: true,
text: '${pd['maximumNumber'] ?? ''}',
onChanged: (value) {
setState(() {
pd['maximumNumber'] = value;
});
},
),
const Divider(),
ListItemFactory.createYesNoSection(
horizontalPadding: 2,
verticalPadding: 5,
isEdit: _isEditable,
title: '是否有应急指导书',
isRequired: true,
text: pd['isEmergencyBook'] == 1 ? '' : '',
groupValue: pd['isEmergencyBook'] == 1,
onChanged: (value) {
setState(() {
pd['isEmergencyBook'] = value ? 1 : 2;
});
},
),
const Divider(),
if (pd['isEmergencyBook'] == 1)
ItemListWidget.OneRowButtonTitleTextFile(
horizontalnum: 10,
label: '应急指导书',
buttonText: _isEditable ? '上传文件' : '查看文件',
isRequired: _isEditable,
fileUrl: pd['emergencyBookFile'] ?? '',
text: '',
onTap: () async {
if (_isEditable) {
uploadFileHandle();
} else {
pushPage(
ReadFilePage(
fileUrl:
ApiService.baseImgPath + pd['emergencyBookFile'] ??
'',
),
context,
);
}
},
onTapFile: () async {
pushPage(
ReadFilePage(
fileUrl:
ApiService.baseImgPath + pd['emergencyBookFile'] ??
'',
),
context,
);
},
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: h_backGroundColor(),
appBar: MyAppbar(title: _isEditable ? '新增' : '查看'),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
_buildDetail(),
const SizedBox(height: 20),
_isEditable
? Row(
children: [
SizedBox(width: 50),
Expanded(
child: CustomButton(
height: 45,
textStyle: TextStyle(
fontSize: 16,
color: Colors.white,
),
text: '提交',
backgroundColor: Colors.green,
onPressed: _submit,
),
),
SizedBox(width: 50),
],
)
: Row(
children: [
SizedBox(width: 50),
Expanded(
child: CustomButton(
height: 45,
textStyle: TextStyle(
fontSize: 16,
color: Colors.white,
),
text: '返回',
onPressed: () {
Navigator.pop(context);
},
),
),
SizedBox(width: 50),
],
),
],
),
),
),
);
}
}

View File

@ -1,323 +0,0 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:qhd_prevention/common/route_service.dart';
import 'package:qhd_prevention/customWidget/item_list_widget.dart';
import 'package:qhd_prevention/pages/home/Tap/special_header.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/tz/sxkj_tz_apply_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/services/location_service.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:qhd_prevention/customWidget/bottom_picker.dart';
import 'package:qhd_prevention/customWidget/custom_button.dart';
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/dh_work/hot_task_page.dart';
class SxkjTzListPage extends StatefulWidget {
const SxkjTzListPage({Key? key}) : super(key: key);
@override
_SxkjTzListPageState createState() => _SxkjTzListPageState();
}
class _SxkjTzListPageState extends State<SxkjTzListPage> {
// Data and state variables
List<dynamic> list = [];
int currentPage = 1;
int rows = 10;
int totalPage = 1;
bool isLoading = false;
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> stepList = [];
int sindex = 0;
String searchKeywords = '';
List<Map<String, dynamic>> flowList = [];
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final ScrollController _scrollController = ScrollController();
Map searchData = {};
@override
void initState() {
super.initState();
_fetchData();
_scrollController.addListener(_onScroll);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _onScroll() {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent &&
!isLoading) {
if (currentPage < totalPage) {
currentPage++;
_fetchData();
}
}
}
Future<void> _fetchSteps() async {
try {} catch (e) {
print('Error fetching steps: $e');
}
}
Future<void> _fetchData() async {
if (isLoading) return;
setState(() => isLoading = true);
try {
var response = {};
final parentPerm =
'dashboard:hazardous:work:confined-space-operations:Confined-Space-Work-Ledger';
final targetPerm = '';
final menuPath = await RouteService.getMenuPath(parentPerm, targetPerm);
final data = {
"eqWorkType": SpecialWorkTypeEnum.confinedspaceWork.code,
"pageSize": rows,
"pageIndex": currentPage,
"menuPath": menuPath,
...searchData,
};
response = await SpecialWorkApi.specialWorkLimitedSpaceList(data);
setState(() {
if (currentPage == 1) {
list = response['data'];
} else {
list.addAll(response['data']);
}
totalPage = response['totalCount'] ?? 1;
isLoading = false;
});
} catch (e) {
print('Error fetching data: $e');
setState(() => isLoading = false);
}
}
void _search() {
searchKeywords = _searchController.text.trim();
currentPage = 1;
list.clear();
_fetchData();
}
///
void _handleApply() async {
await pushPage(
SxkjTzApplyPage(isEdit: true, work_id: '', info: {}),
context,
);
_fetchData();
}
void _goToDetail(Map<String, dynamic> item, bool isEdit) async {
pushPage(
SxkjTzApplyPage(isEdit: false, work_id: item['id'] ?? '', info: item),
context,
);
_fetchData();
}
Widget _buildListItem(Map<String, dynamic> item) {
// actUserName
return Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () => _goToDetail(item, false),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Row(
children: [
Expanded(
child: Text(
"有限空间名称: ${item['name'] ?? ''}",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
softWrap: true,
maxLines: null,
overflow: TextOverflow.visible,
),
),
],
),
Row(
children: [
Expanded(
child: Text(
"编号: ${item['code'] ?? ''}",
softWrap: true,
maxLines: null,
overflow: TextOverflow.visible,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"有限空间类型: ${item['typeName'] ?? ''}",
softWrap: true,
maxLines: null,
textAlign: TextAlign.right,
overflow: TextOverflow.visible,
),
Text(
"风险等级: ${item['riskLevelName'] ?? ''}",
softWrap: true,
maxLines: null,
overflow: TextOverflow.visible,
),
],
),
Text(
"位置及范围: ${item['positionAndRange'] ?? ''}",
softWrap: true,
maxLines: 30,
overflow: TextOverflow.visible,
),
Text(
"主要介质: ${item['mediumInfo'] ?? ''}",
softWrap: true,
maxLines: 30,
overflow: TextOverflow.visible,
),
_statusButtons(item),
],
),
),
),
);
}
Widget _statusButtons(Map<String, dynamic> item) {
final List<Widget> buttons = [];
final List<Widget> buttonRowChildren = [];
buttons.add(
CustomButton(
text: '查看',
buttonStyle: ButtonStyleType.primary,
backgroundColor: Colors.blue,
onPressed: () {
_goToDetail(item, false);
},
),
);
for (int i = 0; i < buttons.length; i++) {
buttonRowChildren.add(
Expanded(child: SizedBox(height: 40, child: buttons[i])),
);
if (i != buttons.length - 1) {
buttonRowChildren.add(const SizedBox(width: 10));
}
}
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: buttonRowChildren,
);
}
Widget _buildListContent() {
if (isLoading && list.isEmpty) {
//
return Center(child: CircularProgressIndicator());
} else if (list.isEmpty) {
//
return NoDataWidget.show();
} else {
//
return ListView.builder(
padding: EdgeInsets.zero,
controller: _scrollController,
itemCount: list.length + (isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index >= list.length) {
//
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Center(child: CircularProgressIndicator()),
);
}
return _buildListItem(list[index]);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: MyAppbar(
title: '有限空间管理台账',
actions: [
IconButton(
onPressed: _handleApply,
icon: const Icon(Icons.add, color: Colors.white, size: 30),
),
],
),
endDrawer: Drawer(
child: SafeArea(
child:
flowList.isEmpty
? Center(child: Text('暂无流程图数据'))
: ItemListWidget.specialBuildFlowStepItem(flowList: flowList),
),
),
body: SafeArea(
child: Column(
children: [
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8),
child: SearchBarWidget(
hintText: '请输入有限空间名称',
showResetButton: true,
onSearch: (val) {
searchData = {'likeName' : _searchController.text};
_fetchData();
},
onReset: () {
_searchController.text = '';
searchData = {};
_fetchData();
},
controller: _searchController,
),
),
const Divider(height: 1),
// List
Expanded(child: _buildListContent()),
],
),
),
);
}
}

View File

@ -5,10 +5,7 @@ import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/customWidget/work_tab_icon_grid.dart'; import 'package:qhd_prevention/customWidget/work_tab_icon_grid.dart';
import 'package:qhd_prevention/http/modules/special_work_api.dart'; import 'package:qhd_prevention/http/modules/special_work_api.dart';
import 'package:qhd_prevention/pages/home/Tap/special_header.dart'; import 'package:qhd_prevention/pages/home/Tap/special_header.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/dh_work/dh_wait_page.dart' hide SpecialListType;
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/tz/sxkj_tz_list_page.dart';
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_wait_page.dart'; import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_wait_page.dart';
import 'package:qhd_prevention/pages/home/Tap/work_tab_list_page.dart';
import 'package:qhd_prevention/pages/my_appbar.dart'; import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart'; import 'package:qhd_prevention/tools/tools.dart';

View File

@ -85,6 +85,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
/// ///
final SafeProtectionController safeController = SafeProtectionController(); final SafeProtectionController safeController = SafeProtectionController();
bool _isSyncingGasAndSafe = false;
/// ///
bool loadingInitDone = false; bool loadingInitDone = false;
@ -190,9 +191,16 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
safeController.addListener(_handleSafeControllerChanged);
_loadPage(); _loadPage();
} }
@override
void dispose() {
safeController.removeListener(_handleSafeControllerChanged);
super.dispose();
}
Future<void> _loadPage() async { Future<void> _loadPage() async {
LoadingDialogHelper.show(); LoadingDialogHelper.show();
try { try {
@ -224,7 +232,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
pd['signStepFlag'] = 2; pd['signStepFlag'] = 2;
pd['gasFlag'] = pd['gasFlag'] ?? 2; pd['gasFlag'] = pd['gasFlag'] ?? 2;
levelList = List<dynamic>.from(pd['taskWorkLevels'] ?? []); levelList = List<dynamic>.from(pd['taskWorkLevels'] ?? []);
pd['applyTime'] = DateFormat(
'yyyy-MM-dd HH:mm:ss',
).format(DateTime.now());
if (enableSafeProtection) { if (enableSafeProtection) {
await safeController.loadFromRaw( await safeController.loadFromRaw(
pd['preparers'] ?? pd['PREPARERS'] ?? [], pd['preparers'] ?? pd['PREPARERS'] ?? [],
@ -385,7 +395,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
/// initData /// initData
void _initGroupsFromInitData(bool isRefresh) { void _initGroupsFromInitData(bool isRefresh) {
_clearAllPerson(); if (!widget.isReEdit) _clearAllPerson();
final List steps = final List steps =
(initData['settingSignSteps'] is List) (initData['settingSignSteps'] is List)
? List.from(initData['settingSignSteps']) ? List.from(initData['settingSignSteps'])
@ -478,7 +488,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
} }
/// ///
void chooseUnitHandle(int index) { void chooseUnitHandle(int index, bool ischoosePerson) {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
@ -493,9 +503,11 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
groups[index]['actUser'] = ''; groups[index]['actUser'] = '';
groups[index]['actUserName'] = ''; groups[index]['actUserName'] = '';
}); });
if (ischoosePerson) {
await _getPersonListForUnitId(id); await _getPersonListForUnitId(id);
}
}, },
data: {'corpinfoId': pd['projectExecutionLocationCorpId'] ?? ''}, data: {'eqCorpinfoId': pd['projectExecutionLocationCorpId'] ?? ''},
), ),
); );
} }
@ -538,7 +550,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
}); });
await _getPersonListForUnitId(id); await _getPersonListForUnitId(id);
}, },
data: {'corpinfoId': pd['projectExecutionLocationCorpId'] ?? ''}, data: {'eqCorpinfoId': pd['xgfId'] ?? ''},
), ),
); );
@ -606,6 +618,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
groups[index]['actUserName'] = name; groups[index]['actUserName'] = name;
groups[index]['actUserDepartment'] = data['departmentId']; groups[index]['actUserDepartment'] = data['departmentId'];
groups[index]['actUserDepartmentName'] = data['departmentName']; groups[index]['actUserDepartmentName'] = data['departmentName'];
if (stepId == '2') {
syncSafeMeasureConfirmersWithGasAnalyzer(data);
}
// //
if (stepId == '20') { if (stepId == '20') {
allowChoosePerson['1'] = data; allowChoosePerson['1'] = data;
@ -619,6 +634,74 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
); );
} }
void _handleSafeControllerChanged() {
if (_isSyncingGasAndSafe) return;
Map<String, dynamic>? selectedPerson;
for (final group in safeController.groups) {
if (group.updateId.isNotEmpty) {
selectedPerson = {
'id': group.updateId,
'name': group.updateName,
'departmentId': group.departmentId,
'departmentName': group.departmentName,
};
break;
}
}
if (selectedPerson == null) return;
final gasItem = groups.cast<Map?>().firstWhere(
(item) => (item?['stepId'] ?? '').toString() == '2',
orElse: () => null,
);
if (gasItem == null) return;
final nextUserId = (selectedPerson['id'] ?? '').toString();
final currentUserId = (gasItem['actUser'] ?? '').toString();
if (nextUserId.isEmpty || currentUserId == nextUserId) return;
_isSyncingGasAndSafe = true;
try {
if (!mounted) return;
setState(() {
gasItem['actUser'] = nextUserId;
gasItem['actUserName'] = (selectedPerson?['name'] ?? '').toString();
gasItem['actUserDepartment'] =
(selectedPerson?['departmentId'] ?? '').toString();
gasItem['actUserDepartmentName'] =
(selectedPerson?['departmentName'] ?? '').toString();
});
} finally {
_isSyncingGasAndSafe = false;
}
}
void syncSafeMeasureConfirmersWithGasAnalyzer(Map<String, dynamic> data) {
if (_isSyncingGasAndSafe) return;
_isSyncingGasAndSafe = true;
try {
for (final group in safeController.groups) {
group.updateId = (data['id'] ?? data['actUser'] ?? '').toString();
group.updateName =
(data['name'] ?? data['actUserName'] ?? '').toString();
group.actUser = group.updateId;
group.actUserName = group.updateName;
group.departmentId = (data['departmentId'] ?? '').toString();
group.departmentName =
(data['departmentName'] ?? data['actUserDepartmentName'] ?? '')
.toString();
group.actUserDepartment = group.departmentId;
group.actUserDepartmentName = group.departmentName;
}
safeController.refresh();
} finally {
_isSyncingGasAndSafe = false;
}
}
// //
void clearRelatedPartiesPerson() { void clearRelatedPartiesPerson() {
setState(() { setState(() {
@ -744,6 +827,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
final canSkip = (item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0; final canSkip = (item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0;
final skipCondition = (item['skipCondition'] ?? '').toString(); final skipCondition = (item['skipCondition'] ?? '').toString();
final allowXgfFlag = item['allowXgfFlag'] ?? 0; final allowXgfFlag = item['allowXgfFlag'] ?? 0;
final showSignFlag = item['showSignFlag'];
final deptLabel = actorField.isNotEmpty ? '$actorField 部门' : '单位'; final deptLabel = actorField.isNotEmpty ? '$actorField 部门' : '单位';
final personLabel = actorField.isNotEmpty ? actorField : '人员'; final personLabel = actorField.isNotEmpty ? actorField : '人员';
@ -760,7 +844,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
skipCondition.isNotEmpty && skipCondition.isNotEmpty &&
skipCondition.contains('gas_flag') && skipCondition.contains('gas_flag') &&
pd['gasFlag'] == 1; pd['gasFlag'] == 1;
if (showSignFlag == 2) {
return SizedBox();
}
return Column( return Column(
children: [ children: [
if (item['selectLevel'] == 1) ...[ if (item['selectLevel'] == 1) ...[
@ -784,11 +870,23 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
(item['actUserDepartmentName'] as String?)?.isNotEmpty == true (item['actUserDepartmentName'] as String?)?.isNotEmpty == true
? item['actUserDepartmentName'] ? item['actUserDepartmentName']
: '请选择', : '请选择',
onTap: () => chooseUnitHandle(index), onTap: () => chooseUnitHandle(index, true),
), ),
const Divider(), const Divider(),
], ],
if (canSkip == 1) ...[ if (item['selectLevel'] == 3)...[ //
ItemListWidget.selectableLineTitleTextRightButton(
isRequired: !(canSkip == 1),
label: personLabel,
isEditable: isEditable,
text:
(item['actUserDepartmentName'] as String?)?.isNotEmpty == true
? item['actUserDepartmentName']
: '请选择',
onTap: () => chooseUnitHandle(index, false),
),
const Divider(),
]else...[if (canSkip == 1) ...[
if (skipCondition.isEmpty) ...[ if (skipCondition.isEmpty) ...[
ListItemFactory.createYesNoSection( ListItemFactory.createYesNoSection(
horizontalPadding: 2, horizontalPadding: 2,
@ -851,7 +949,8 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
onTap: () => choosePersonHandle(index, allowXgfFlag == 1), onTap: () => choosePersonHandle(index, allowXgfFlag == 1),
), ),
const Divider(), const Divider(),
], ],],
], ],
); );
} }
@ -945,6 +1044,14 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
'xgfId' : info['xgfId'] ?? '' 'xgfId' : info['xgfId'] ?? ''
}; };
payload.addAll(extraPayload); payload.addAll(extraPayload);
for (final item in signLogs) {
if (item['stepId'] == '30' && info['isInnerWork'] == 1) {
item['actUserDepartment'] = pd['workChargeUserDepartment'] ?? '';
item['actUserDepartmentName'] = pd['workChargeUserDepartmentName'] ?? '';
item['actUser'] = pd['workChargeUserId'] ?? '';
item['actUserName'] = pd['workChargeUserName'] ?? '';
}
}
if (FormUtils.hasValue(payload, 'workId') && widget.status == '2') { if (FormUtils.hasValue(payload, 'workId') && widget.status == '2') {
payload.remove('checkNo'); payload.remove('checkNo');
@ -1011,7 +1118,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
} }
for (final item in groupsToCheck) { for (final item in groupsToCheck) {
if (item['actUser'] == null || item['actUser'] == '') { int showSignFlag = item['showSignFlag'] ?? 1;
int selectLevel = item['selectLevel'] ?? 0;
if ((item['actUser'] == null || item['actUser'] == '') && showSignFlag == 1 && selectLevel != 3) {
final canSkip = final canSkip =
(item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0; (item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0;
final stepId = item['stepId'] ?? ''; final stepId = item['stepId'] ?? '';

View File

@ -372,7 +372,24 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
} }
} }
} }
if (pd['componentName'] == 'personAnderRecordFile') {
// spaceRecordFilelimitSpaceWorkNum
if (!FormUtils.hasValue(other, 'limitSpaceWorkNum')) {
ToastUtil.showNormal(
context,
'请输入有限空间作业人数',
);
return;
}
if (!FormUtils.hasValue(other, 'spaceRecordFile')) {
ToastUtil.showNormal(
context,
'请上传应急响应记录',
);
return;
}
}
// 5) // 5)
if (signImages.isEmpty) { if (signImages.isEmpty) {
if (!FormUtils.hasValue(other, 'isCompleteWork')) { if (!FormUtils.hasValue(other, 'isCompleteWork')) {
@ -1030,7 +1047,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
final info = Map<String, dynamic>.from(raw); final info = Map<String, dynamic>.from(raw);
final signPath = (info['signPath'] ?? '').toString().trim(); final signPath = (info['signPath'] ?? '').toString().trim();
return signPath.isNotEmpty; return signPath.isNotEmpty || _getSpaceRecordFiles(info).isNotEmpty;
}).toList(); }).toList();
validEntries.sort((a, b) { validEntries.sort((a, b) {
@ -1121,12 +1138,12 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
final info = Map<String, dynamic>.from(raw); final info = Map<String, dynamic>.from(raw);
final stepName = (info['stepName'] ?? '').toString(); final stepName = (info['stepName'] ?? '').toString();
final signPath = (info['signPath'] ?? '').toString().trim(); final signPath = (info['signPath'] ?? '').toString().trim();
final signTime = (info['signTime'] ?? info['signerTime'] ?? '').toString().trim(); final signTime =
(info['signTime'] ?? info['signerTime'] ?? '').toString().trim();
final remarks = (info['remarks'] ?? '').toString().trim(); final remarks = (info['remarks'] ?? '').toString().trim();
final spaceRecordFiles = _getSpaceRecordFiles(info);
if (signPath.isEmpty) continue; if (signPath.isEmpty && spaceRecordFiles.isEmpty) continue;
final imageUrl = '${ApiService.baseImgPath}$signPath';
widgets.add( widgets.add(
Container( Container(
@ -1167,9 +1184,17 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
), ),
), ),
), ),
if (spaceRecordFiles.isNotEmpty) ...[
_buildSpaceRecordFiles(spaceRecordFiles),
const SizedBox(height: 10),
],
if (signPath.isNotEmpty)
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
presentOpaque(SingleImageViewer(imageUrl: imageUrl), context); presentOpaque(
SingleImageViewer(imageUrl: _fullFileUrl(signPath)),
context,
);
}, },
child: Align( child: Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
@ -1179,7 +1204,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
maxHeight: 140, maxHeight: 140,
), ),
child: Image.network( child: Image.network(
imageUrl, _fullFileUrl(signPath),
fit: BoxFit.contain, fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) { errorBuilder: (context, error, stackTrace) {
return const Text('签字图片加载失败'); return const Text('签字图片加载失败');
@ -1205,6 +1230,113 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
return widgets; return widgets;
} }
List<String> _getSpaceRecordFiles(Map<String, dynamic> info) {
dynamic otherParams = info['otherParams'];
if (otherParams is String) {
try {
otherParams = jsonDecode(otherParams);
} catch (_) {
otherParams = null;
}
}
final raw =
otherParams is Map
? (otherParams['spaceRecordFile'] ?? '')
: (info['spaceRecordFile'] ?? '');
return raw
.toString()
.split(',')
.map((path) => path.trim())
.where((path) => path.isNotEmpty)
.toList();
}
String _fullFileUrl(String path) {
final value = path.trim();
if (value.startsWith('http://') || value.startsWith('https://')) {
return value;
}
return '${ApiService.baseImgPath}$value';
}
bool _isPreviewImage(String path) {
final lower = path.toLowerCase().split('?').first;
return lower.endsWith('.jpg') ||
lower.endsWith('.jpeg') ||
lower.endsWith('.png') ||
lower.endsWith('.webp') ||
lower.endsWith('.gif') ||
lower.endsWith('.bmp');
}
Widget _buildSpaceRecordFiles(List<String> files) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 10,
runSpacing: 10,
children:
files.map((path) {
final fileUrl = _fullFileUrl(path);
if (_isPreviewImage(path)) {
return GestureDetector(
onTap: () {
presentOpaque(
SingleImageViewer(imageUrl: fileUrl),
context,
);
},
child: ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 120,
maxHeight: 90,
),
child: Image.network(
fileUrl,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return const Text('');
},
),
),
);
}
final fileName = path.split('/').last;
return InkWell(
onTap: () {
pushPage(ReadFilePage(fileUrl: fileUrl), context);
},
child: Container(
constraints: const BoxConstraints(maxWidth: 220),
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 8,
),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(4),
border: Border.all(color: Colors.grey.shade300),
),
child: Text(
fileName.isNotEmpty ? fileName : '查看附件',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 12, color: Colors.blue),
),
),
);
}).toList(),
),
],
);
}
// //
Widget _otherMeasureWidgets() { Widget _otherMeasureWidgets() {
if (_otherMeasuresList.isNotEmpty) { if (_otherMeasuresList.isNotEmpty) {

View File

@ -199,7 +199,7 @@ class HomePageState extends RouteAwareState<HomePage>
final routeService = RouteService(); final routeService = RouteService();
final mainTabs = routeService.mainTabs; final mainTabs = routeService.mainTabs;
if (mainTabs.isEmpty) { if (mainTabs.isEmpty) {
// // ƒ
return; return;
} }