危险作业需求变更
parent
85624e1cfd
commit
3c4e30bc88
|
|
@ -476,6 +476,11 @@ enum UploadFileType {
|
|||
'410',
|
||||
'special_operation_special_apply_involved_signature',
|
||||
),
|
||||
// 进出有限空间记录 - 类型: '411',
|
||||
specialOperationInAndOutRecord(
|
||||
'411',
|
||||
'special_operation_in_and_out_record',
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,10 @@ class SafeProtectionController extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void ensureAtLeastOneGroup() {
|
||||
if (_groups.isEmpty) {
|
||||
addGroup();
|
||||
|
|
@ -359,6 +363,7 @@ class SafeProtectionModule extends StatefulWidget {
|
|||
this.title = '安全防护措施',
|
||||
this.otherTitle = '其他安全措施',
|
||||
this.showOtherSection = false,
|
||||
this.showAddButton = false,
|
||||
this.onChanged,
|
||||
});
|
||||
|
||||
|
|
@ -372,6 +377,7 @@ class SafeProtectionModule extends StatefulWidget {
|
|||
final String title;
|
||||
final String otherTitle;
|
||||
final bool showOtherSection;
|
||||
final bool showAddButton;
|
||||
final SafeMeasuresChanged? onChanged;
|
||||
|
||||
@override
|
||||
|
|
@ -451,18 +457,24 @@ class _SafeProtectionModuleState extends State<SafeProtectionModule> {
|
|||
onSelectedWithData: (updateId, name, data) {
|
||||
setState(() {
|
||||
for (SafeMeasureGroup g in widget.controller.groups) {
|
||||
// 判重updateId
|
||||
if (g.updateId == updateId && widget.controller.groups.length > 1) {
|
||||
if (widget.controller.groups.length > 1 &&
|
||||
g != group &&
|
||||
g.updateId == updateId) {
|
||||
ToastUtil.showNormal(context, '确认人不能重复');
|
||||
return;
|
||||
}
|
||||
}
|
||||
group.updateId = updateId;
|
||||
group.updateName = name;
|
||||
group.actUser = data['actUserId'] ?? '';
|
||||
group.actUser = updateId;
|
||||
group.actUserName = name;
|
||||
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();
|
||||
},
|
||||
);
|
||||
|
|
@ -537,16 +549,17 @@ class _SafeProtectionModuleState extends State<SafeProtectionModule> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ListItemFactory.createBuildSimpleSection(widget.title),
|
||||
CustomButton(
|
||||
text: '添加',
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
backgroundColor: Colors.blue,
|
||||
height: 32,
|
||||
onPressed:
|
||||
widget.isEditable
|
||||
? () => setState(() => widget.controller.addGroup())
|
||||
: null,
|
||||
),
|
||||
if (widget.showAddButton)
|
||||
CustomButton(
|
||||
text: '添加',
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
backgroundColor: Colors.blue,
|
||||
height: 32,
|
||||
onPressed:
|
||||
widget.isEditable
|
||||
? () => setState(() => widget.controller.addGroup())
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
...widget.controller.groups.asMap().entries.map((entry) {
|
||||
|
|
@ -669,4 +682,4 @@ class _SafeProtectionModuleState extends State<SafeProtectionModule> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
|
|||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请日期:',
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
|
|
|
|||
|
|
@ -143,9 +143,9 @@ class _HotWorkApplyPageState extends SpecialWorkApplyBaseState<HotWorkApplyPage>
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
// 申请日期
|
||||
// 申请时间
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请日期:',
|
||||
label: '申请时间:',
|
||||
isEditable: isEditable,
|
||||
onTap: () async {
|
||||
final picked = await BottomDateTimePicker.showDate(
|
||||
|
|
@ -507,4 +507,4 @@ class _HotWorkApplyPageState extends SpecialWorkApplyBaseState<HotWorkApplyPage>
|
|||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,13 @@ class _BreakgroundDetailFormWidgetState extends State<BreakgroundDetailFormWidge
|
|||
isEditable: false,
|
||||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
|
|
|
|||
|
|
@ -158,6 +158,27 @@ class _DlApplyPageState extends SpecialWorkApplyBaseState<DlApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -360,7 +381,7 @@ class _DlApplyPageState extends SpecialWorkApplyBaseState<DlApplyPage> {
|
|||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -433,4 +454,4 @@ class _DlApplyPageState extends SpecialWorkApplyBaseState<DlApplyPage> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,13 @@ class _CutRoadDetailFormWidgetState extends State<CutRoadDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
|
|
|
|||
|
|
@ -157,6 +157,27 @@ class _DtApplyPageState extends SpecialWorkApplyBaseState<DtApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -346,7 +367,7 @@ class _DtApplyPageState extends SpecialWorkApplyBaseState<DtApplyPage> {
|
|||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -417,4 +438,4 @@ class _DtApplyPageState extends SpecialWorkApplyBaseState<DtApplyPage> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,6 +152,27 @@ class _DzApplyPageState extends SpecialWorkApplyBaseState<DzApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -357,7 +378,7 @@ class _DzApplyPageState extends SpecialWorkApplyBaseState<DzApplyPage> {
|
|||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -418,4 +439,4 @@ class _DzApplyPageState extends SpecialWorkApplyBaseState<DzApplyPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,13 @@ class _HoistingDetailFormWidgetState extends State<HoistingDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
|
|
|
|||
|
|
@ -140,7 +140,13 @@ class _HeighWorkDetailFormWidgetState extends State<HeighWorkDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
|
|
|
|||
|
|
@ -149,6 +149,27 @@ class _GcApplyPageState extends SpecialWorkApplyBaseState<GcApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -330,7 +351,7 @@ class _GcApplyPageState extends SpecialWorkApplyBaseState<GcApplyPage> {
|
|||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -390,4 +411,4 @@ class _GcApplyPageState extends SpecialWorkApplyBaseState<GcApplyPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,13 @@ class _LsydWorkDetailFormWidgetState extends State<LsydWorkDetailFormWidget> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
isEditable: false,
|
||||
|
|
|
|||
|
|
@ -158,6 +158,27 @@ class _LsydApplyPageState extends SpecialWorkApplyBaseState<LsydApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -382,7 +403,7 @@ class _LsydApplyPageState extends SpecialWorkApplyBaseState<LsydApplyPage> {
|
|||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -435,4 +456,4 @@ class _LsydApplyPageState extends SpecialWorkApplyBaseState<LsydApplyPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,7 +194,13 @@ class _MbcdDetailFormWidgetState extends State<MbcdDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '作业类型:',
|
||||
|
|
|
|||
|
|
@ -199,6 +199,27 @@ class _MbcdApplyPageState extends SpecialWorkApplyBaseState<MbcdApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
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) ...[
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
|
|
@ -584,4 +605,4 @@ class _MbcdApplyPageState extends SpecialWorkApplyBaseState<MbcdApplyPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class _SxkjWorkDetailFormWidgetState extends State<SxkjWorkDetailFormWidget> {
|
|||
),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请日期:',
|
||||
label: '申请时间:',
|
||||
text: pd['applyTime'] ?? '',
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {},
|
||||
|
|
@ -176,12 +176,12 @@ class _SxkjWorkDetailFormWidgetState extends State<SxkjWorkDetailFormWidget> {
|
|||
isRequired: true,
|
||||
),
|
||||
],
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '管理单位:',
|
||||
isEditable: widget.isEditable,
|
||||
text: chooseLimitedSpace['manageDeptName'] ?? '',
|
||||
),
|
||||
// const Divider(),
|
||||
// ItemListWidget.selectableLineTitleTextRightButton(
|
||||
// label: '管理单位:',
|
||||
// isEditable: widget.isEditable,
|
||||
// text: chooseLimitedSpace['manageDeptName'] ?? '',
|
||||
// ),
|
||||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '有限空间名称及编号:',
|
||||
|
|
|
|||
|
|
@ -75,39 +75,40 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
|
||||
@override
|
||||
Future<void> loadExtraData() async {
|
||||
|
||||
final data = {
|
||||
"eqWorkType": SpecialWorkTypeEnum.confinedspaceWork.code,
|
||||
"pageSize": 999,
|
||||
"pageIndex": 1,
|
||||
"eqCorpinfoId": pd['projectExecutionLocationCorpId'] ?? '',
|
||||
};
|
||||
final limitedSpaceRes = await SpecialWorkApi.specialWorkLimitedSpaceList(data);
|
||||
final limitedSpaceRes = await SpecialWorkApi.specialWorkLimitedSpaceList(
|
||||
data,
|
||||
);
|
||||
if (limitedSpaceRes['success'] == true) {
|
||||
limitedSpaceList = limitedSpaceRes['data'] ?? [];
|
||||
}
|
||||
// 清空有限空间台账选择的数据
|
||||
_clearRelatedParties();
|
||||
}
|
||||
|
||||
Future<void> _clearRelatedParties() async {
|
||||
setState(() {
|
||||
pd['limitedSpaceNameAndCode'] = '';
|
||||
pd['chooseLimitedSpace'] = {};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> afterInitDataLoaded() async {
|
||||
// 初始化允许选择的人员列表(作业负责人和监护人)
|
||||
allowChoosePerson = {
|
||||
'1' : {
|
||||
'1': {
|
||||
"actUser": pd['workGuardianUser'] ?? pd['workGuardianUserId'] ?? '',
|
||||
"actUserDepartment": pd['workGuardianUserDepartment'] ?? '',
|
||||
"actUserDepartmentName": pd['workGuardianUserDepartmentName'] ?? '',
|
||||
"actUserName": pd['workGuardianUserName'] ?? '',
|
||||
},
|
||||
'2' : {
|
||||
'2': {
|
||||
"actUserDepartment": pd['workChargeUserDepartment'] ?? '',
|
||||
"actUserDepartmentName": pd['workChargeUserDepartmentName'] ?? '',
|
||||
"actUser": pd['workChargeUser'] ?? pd['workChargeUserId'] ?? '',
|
||||
|
|
@ -145,9 +146,10 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
Future<Map<String, dynamic>> buildExtraPayload() async {
|
||||
final preparers = safeController.buildPreparers();
|
||||
return {
|
||||
'others': {'measures': preparers}
|
||||
'others': {'measures': preparers},
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildFormContent() {
|
||||
final chooseLimitedSpace = (pd['chooseLimitedSpace'] as Map?) ?? {};
|
||||
|
|
@ -204,9 +206,9 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
text: pd['applyUser'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
// 申请日期
|
||||
// 申请时间
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '申请日期:',
|
||||
label: '申请时间:',
|
||||
isEditable: isEditable,
|
||||
onTap: () async {
|
||||
final picked = await BottomDateTimePicker.showDate(
|
||||
|
|
@ -217,7 +219,9 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
);
|
||||
if (picked != null) {
|
||||
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,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
isInnerWork = value;
|
||||
pd['internalOperationFlag'] = value ? 1 : 2;
|
||||
});
|
||||
},
|
||||
|
|
@ -266,15 +269,15 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
onTap: _chooseFromLedger,
|
||||
text: pd['limitedSpaceNameAndCode'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
// 管理单位(只读,来自台账)
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '管理单位:',
|
||||
isEditable: false,
|
||||
isTextFont: false,
|
||||
strongRequired: true,
|
||||
text: chooseLimitedSpace['manageDeptName'] ?? '',
|
||||
),
|
||||
// const Divider(),
|
||||
// // 管理单位(只读,来自台账)
|
||||
// ItemListWidget.singleLineTitleText(
|
||||
// label: '管理单位:',
|
||||
// isEditable: false,
|
||||
// isTextFont: false,
|
||||
// strongRequired: true,
|
||||
// text: chooseLimitedSpace['manageDeptName'] ?? '',
|
||||
// ),
|
||||
const Divider(),
|
||||
// 主要介质(只读)
|
||||
ItemListWidget.singleLineTitleText(
|
||||
|
|
@ -333,7 +336,8 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
isTextFont: false,
|
||||
isRequired: isEditable,
|
||||
text: pd['emergencyEquipment'] ?? '',
|
||||
onChanged: (value) => setState(() => pd['emergencyEquipment'] = value),
|
||||
onChanged:
|
||||
(value) => setState(() => pd['emergencyEquipment'] = value),
|
||||
),
|
||||
// 重新编辑时展示详情组件
|
||||
if (widget.isReEdit && FormUtils.hasValue(form, 'id')) ...[
|
||||
|
|
@ -372,7 +376,8 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
label: '作业监护人',
|
||||
isEditable: isEditable,
|
||||
text: pd['workGuardianUserName'] ?? '请选择',
|
||||
onTap: () => _chooseAlonePersonHandle(SelectPersonType.workGuardian),
|
||||
onTap:
|
||||
() => _chooseAlonePersonHandle(SelectPersonType.workGuardian),
|
||||
),
|
||||
const Divider(),
|
||||
// 签字流程组(基类提供,但 stepId=3 会被隐藏,因为 shouldHideGroup 已重写)
|
||||
|
|
@ -405,22 +410,24 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
// 区分出两个数组、企业和相关方
|
||||
if (item['userType'] == 2) {
|
||||
firmList.add(item);
|
||||
}else{
|
||||
} else {
|
||||
xgfList.add(item);
|
||||
}
|
||||
}
|
||||
//0610修改,作业负责人和作业监护人需与选择的作业单位关联;作业单位肯定是相关方端,所以不考虑企业端
|
||||
DepartmentAllPersonPicker.show(
|
||||
context,
|
||||
allowXgfFlag: xgfList.isNotEmpty,
|
||||
personsData: firmList,
|
||||
serverData: xgfList,
|
||||
allowXgfFlag: false,
|
||||
personsData: [...firmList,...xgfList],
|
||||
serverData: [],
|
||||
onSelectedWithData: (userId, name, data) {
|
||||
setState(() {
|
||||
groups[index]['actUser'] = userId;
|
||||
groups[index]['actUserName'] = name;
|
||||
groups[index]['actUserDepartment'] = data['departmentId'] ?? '';
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'] ?? '';
|
||||
|
||||
groups[index]['actUserDepartmentName'] =
|
||||
data['departmentName'] ?? '';
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -441,13 +448,17 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
style: BottomPickerStyle.list,
|
||||
title: '有限空间名称及编号',
|
||||
height: MediaQuery.of(context).size.height - 120,
|
||||
items: limitedSpaceList.map((item) => '${item['name']}(${item['code']})').toList(),
|
||||
itemBuilder: (item) => Text(
|
||||
item,
|
||||
softWrap: true,
|
||||
maxLines: 10,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
items:
|
||||
limitedSpaceList
|
||||
.map((item) => '${item['name']}(${item['code']})')
|
||||
.toList(),
|
||||
itemBuilder:
|
||||
(item) => Text(
|
||||
item,
|
||||
softWrap: true,
|
||||
maxLines: 10,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
initialIndex: 0,
|
||||
withIndex: true,
|
||||
);
|
||||
|
|
@ -469,32 +480,40 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
isScrollControlled: true,
|
||||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (_) => DepartmentPicker(
|
||||
onSelected: (id, name, data) async {
|
||||
setState(() {
|
||||
pd['workDepartment'] = id;
|
||||
pd['workDepartmentName'] = name;
|
||||
// 清空作业人(如果有联动需要)
|
||||
});
|
||||
await _getPersonListForUnitId(id);
|
||||
},
|
||||
data: {'corpinfoId': pd['projectExecutionLocationCorpId'] ?? ''},
|
||||
),
|
||||
builder:
|
||||
(_) => DepartmentPicker(
|
||||
onSelected: (id, name, data) async {
|
||||
setState(() {
|
||||
pd['workDepartment'] = id;
|
||||
pd['workDepartmentName'] = name;
|
||||
// 清空作业人(如果有联动需要)
|
||||
});
|
||||
await _getPersonListForUnitId(id);
|
||||
},
|
||||
data: {'eqCorpinfoId': pd['xgfId'] ?? ''},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 单独选择作业负责人或监护人
|
||||
void _chooseAlonePersonHandle(SelectPersonType type) {
|
||||
List<dynamic> personList = allPersonList;
|
||||
List<dynamic> xgfList = relatedPartiesPersonList;
|
||||
// if (pd['xgfFlag'] == 1 && relatedPartiesPersonList.isNotEmpty) {
|
||||
// personList = [...personList, ...relatedPartiesPersonList];
|
||||
// }
|
||||
List<dynamic> personList = [];
|
||||
// List<dynamic> xgfList = relatedPartiesPersonList;
|
||||
final String workDepartmentId = (pd['workDepartment'] ?? '').toString();
|
||||
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;
|
||||
}
|
||||
|
||||
DepartmentAllPersonPicker.show(
|
||||
context,
|
||||
allowXgfFlag: pd['xgfFlag'] == 1,
|
||||
personsData: personList,
|
||||
serverData: xgfList,
|
||||
allowXgfFlag: false,
|
||||
personsData: xgfList,
|
||||
serverData: [],
|
||||
onSelectedWithData: (userId, name, data) {
|
||||
setState(() {
|
||||
if (type == SelectPersonType.workCharge) {
|
||||
|
|
@ -503,7 +522,6 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
pd['workChargeUserDepartment'] = data['departmentId'];
|
||||
pd['workChargeUserDepartmentName'] = data['departmentName'];
|
||||
allowChoosePerson['1'] = data;
|
||||
|
||||
} else {
|
||||
pd['workGuardianUserId'] = userId;
|
||||
pd['workGuardianUserName'] = name;
|
||||
|
|
@ -546,4 +564,4 @@ class _SxkjApplyPageState extends SpecialWorkApplyBaseState<SxkjApplyPage> {
|
|||
return <String, dynamic>{};
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.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_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/sxkj_work/special_work_gas_list.dart';
|
||||
import 'package:qhd_prevention/pages/home/Tap/special_work/sxkj_work/sxkj_apply_page.dart';
|
||||
|
|
@ -39,22 +40,24 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
|
|||
|
||||
@override
|
||||
Future<void> onOpenDetail(
|
||||
BuildContext context,
|
||||
Map<String, dynamic> item,
|
||||
bool isEdit,
|
||||
) async {
|
||||
BuildContext context,
|
||||
Map<String, dynamic> item,
|
||||
bool isEdit,
|
||||
) async {
|
||||
final hotworkId = item['id'] ?? '';
|
||||
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 status = '${hotworkInfo['status'] ?? ''}';
|
||||
|
||||
final String statusName = isEdit
|
||||
? (listType == SpecialListType.task
|
||||
? '${item['stepName'] ?? ''}'
|
||||
: '${hotworkInfo['currentStep'] ?? ''}')
|
||||
: '查看';
|
||||
final String statusName =
|
||||
isEdit
|
||||
? (listType == SpecialListType.task
|
||||
? '${item['stepName'] ?? ''}'
|
||||
: '${hotworkInfo['currentStep'] ?? ''}')
|
||||
: '查看';
|
||||
|
||||
Future<void> openTaskPage({required bool editable}) async {
|
||||
await pushPage(
|
||||
|
|
@ -70,6 +73,10 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
|
|||
}
|
||||
|
||||
if (listType == SpecialListType.task) {
|
||||
if (stepId == '30') {
|
||||
await pushPage(SxkjRecordAddPage(data: item), context);
|
||||
return;
|
||||
}
|
||||
if (stepId == '2') {
|
||||
if (isEdit) {
|
||||
await pushPage(
|
||||
|
|
@ -85,11 +92,7 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
|
|||
if (status == '0' || status == '2') {
|
||||
if (isEdit) {
|
||||
await pushPage(
|
||||
SxkjApplyPage(
|
||||
isReEdit: true,
|
||||
workId: hotworkId,
|
||||
status: status,
|
||||
),
|
||||
SxkjApplyPage(isReEdit: true, workId: hotworkId, status: status),
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
|
|
@ -107,13 +110,12 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
|
|||
|
||||
@override
|
||||
Widget buildCardBody(
|
||||
BuildContext context,
|
||||
Map<String, dynamic> item,
|
||||
Map<String, dynamic> workInfo,
|
||||
Map<String, dynamic> info,
|
||||
String statusName,
|
||||
) {
|
||||
|
||||
BuildContext context,
|
||||
Map<String, dynamic> item,
|
||||
Map<String, dynamic> workInfo,
|
||||
Map<String, dynamic> info,
|
||||
String statusName,
|
||||
) {
|
||||
final chooseLimitedSpace = Map<String, dynamic>.from(
|
||||
info['chooseLimitedSpace'] ?? {},
|
||||
);
|
||||
|
|
@ -161,10 +163,10 @@ class SxkjWaitPage extends SpecialWorkWaitPageBase {
|
|||
),
|
||||
],
|
||||
),
|
||||
buildWrapPairRow(
|
||||
'管理单位: ${chooseLimitedSpace['manageDeptName'] ?? ''}',
|
||||
'作业单位: ${info['workDepartmentName'] ?? ''}',
|
||||
),
|
||||
// buildWrapPairRow(
|
||||
// '管理单位: ${chooseLimitedSpace['manageDeptName'] ?? ''}',
|
||||
// '作业单位: ${info['workDepartmentName'] ?? ''}',
|
||||
// ),
|
||||
Text(
|
||||
'有限空间名称及编号: ${info['limitedSpaceNameAndCode'] ?? ''}',
|
||||
softWrap: true,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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()),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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/http/modules/special_work_api.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/work_tab_list_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
|
||||
/// 安全防护措施控制器
|
||||
final SafeProtectionController safeController = SafeProtectionController();
|
||||
bool _isSyncingGasAndSafe = false;
|
||||
|
||||
/// 初始化完成标志
|
||||
bool loadingInitDone = false;
|
||||
|
|
@ -190,9 +191,16 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
safeController.addListener(_handleSafeControllerChanged);
|
||||
_loadPage();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
safeController.removeListener(_handleSafeControllerChanged);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _loadPage() async {
|
||||
LoadingDialogHelper.show();
|
||||
try {
|
||||
|
|
@ -224,7 +232,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
pd['signStepFlag'] = 2;
|
||||
pd['gasFlag'] = pd['gasFlag'] ?? 2;
|
||||
levelList = List<dynamic>.from(pd['taskWorkLevels'] ?? []);
|
||||
|
||||
pd['applyTime'] = DateFormat(
|
||||
'yyyy-MM-dd HH:mm:ss',
|
||||
).format(DateTime.now());
|
||||
if (enableSafeProtection) {
|
||||
await safeController.loadFromRaw(
|
||||
pd['preparers'] ?? pd['PREPARERS'] ?? [],
|
||||
|
|
@ -478,7 +488,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
}
|
||||
|
||||
/// 选择部门单位
|
||||
void chooseUnitHandle(int index) {
|
||||
void chooseUnitHandle(int index, bool ischoosePerson) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
|
|
@ -493,9 +503,11 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
groups[index]['actUser'] = '';
|
||||
groups[index]['actUserName'] = '';
|
||||
});
|
||||
await _getPersonListForUnitId(id);
|
||||
if (ischoosePerson) {
|
||||
await _getPersonListForUnitId(id);
|
||||
}
|
||||
},
|
||||
data: {'corpinfoId': pd['projectExecutionLocationCorpId'] ?? ''},
|
||||
data: {'eqCorpinfoId': pd['projectExecutionLocationCorpId'] ?? ''},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -538,7 +550,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
});
|
||||
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]['actUserDepartment'] = data['departmentId'];
|
||||
groups[index]['actUserDepartmentName'] = data['departmentName'];
|
||||
if (stepId == '2') {
|
||||
syncSafeMeasureConfirmersWithGasAnalyzer(data);
|
||||
}
|
||||
// 同步更新允许列表,用于安全措施确认人、气体分析人
|
||||
if (stepId == '20') {
|
||||
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() {
|
||||
setState(() {
|
||||
|
|
@ -744,6 +827,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
final canSkip = (item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0;
|
||||
final skipCondition = (item['skipCondition'] ?? '').toString();
|
||||
final allowXgfFlag = item['allowXgfFlag'] ?? 0;
|
||||
final showSignFlag = item['showSignFlag'];
|
||||
|
||||
final deptLabel = actorField.isNotEmpty ? '$actorField 部门' : '单位';
|
||||
final personLabel = actorField.isNotEmpty ? actorField : '人员';
|
||||
|
|
@ -760,7 +844,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
skipCondition.isNotEmpty &&
|
||||
skipCondition.contains('gas_flag') &&
|
||||
pd['gasFlag'] == 1;
|
||||
|
||||
if (showSignFlag == 2) {
|
||||
return SizedBox();
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
if (item['selectLevel'] == 1) ...[
|
||||
|
|
@ -784,11 +870,23 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
(item['actUserDepartmentName'] as String?)?.isNotEmpty == true
|
||||
? item['actUserDepartmentName']
|
||||
: '请选择',
|
||||
onTap: () => chooseUnitHandle(index),
|
||||
onTap: () => chooseUnitHandle(index, true),
|
||||
),
|
||||
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) ...[
|
||||
ListItemFactory.createYesNoSection(
|
||||
horizontalPadding: 2,
|
||||
|
|
@ -832,9 +930,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
label: personLabel,
|
||||
isEditable: isEditable,
|
||||
text:
|
||||
(item['actUserName'] as String?)?.isNotEmpty == true
|
||||
? item['actUserName']
|
||||
: '请选择',
|
||||
(item['actUserName'] as String?)?.isNotEmpty == true
|
||||
? item['actUserName']
|
||||
: '请选择',
|
||||
onTap: () => choosePersonHandle(index, allowXgfFlag == 1),
|
||||
),
|
||||
const Divider(),
|
||||
|
|
@ -845,13 +943,14 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
label: personLabel,
|
||||
isEditable: isEditable,
|
||||
text:
|
||||
(item['actUserName'] as String?)?.isNotEmpty == true
|
||||
? item['actUserName']
|
||||
: '请选择',
|
||||
(item['actUserName'] as String?)?.isNotEmpty == true
|
||||
? item['actUserName']
|
||||
: '请选择',
|
||||
onTap: () => choosePersonHandle(index, allowXgfFlag == 1),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
],],
|
||||
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
@ -945,6 +1044,14 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
'xgfId' : info['xgfId'] ?? ''
|
||||
};
|
||||
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') {
|
||||
payload.remove('checkNo');
|
||||
|
|
@ -1011,7 +1118,9 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
|
|||
}
|
||||
|
||||
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 =
|
||||
(item['canSkip'] ?? 0) is int ? (item['canSkip'] ?? 0) : 0;
|
||||
final stepId = item['stepId'] ?? '';
|
||||
|
|
|
|||
|
|
@ -372,7 +372,24 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (pd['componentName'] == 'personAnderRecordFile') {
|
||||
// 判断是否上传了应急响应记录 spaceRecordFile、limitSpaceWorkNum
|
||||
if (!FormUtils.hasValue(other, 'limitSpaceWorkNum')) {
|
||||
ToastUtil.showNormal(
|
||||
context,
|
||||
'请输入有限空间作业人数',
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!FormUtils.hasValue(other, 'spaceRecordFile')) {
|
||||
ToastUtil.showNormal(
|
||||
context,
|
||||
'请上传应急响应记录',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
// 5) 签字必填
|
||||
if (signImages.isEmpty) {
|
||||
if (!FormUtils.hasValue(other, 'isCompleteWork')) {
|
||||
|
|
@ -1030,7 +1047,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
|
|||
|
||||
final info = Map<String, dynamic>.from(raw);
|
||||
final signPath = (info['signPath'] ?? '').toString().trim();
|
||||
return signPath.isNotEmpty;
|
||||
return signPath.isNotEmpty || _getSpaceRecordFiles(info).isNotEmpty;
|
||||
}).toList();
|
||||
|
||||
validEntries.sort((a, b) {
|
||||
|
|
@ -1121,12 +1138,12 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
|
|||
final info = Map<String, dynamic>.from(raw);
|
||||
final stepName = (info['stepName'] ?? '').toString();
|
||||
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 spaceRecordFiles = _getSpaceRecordFiles(info);
|
||||
|
||||
if (signPath.isEmpty) continue;
|
||||
|
||||
final imageUrl = '${ApiService.baseImgPath}$signPath';
|
||||
if (signPath.isEmpty && spaceRecordFiles.isEmpty) continue;
|
||||
|
||||
widgets.add(
|
||||
Container(
|
||||
|
|
@ -1167,27 +1184,35 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
|
|||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
presentOpaque(SingleImageViewer(imageUrl: imageUrl), context);
|
||||
},
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 220,
|
||||
maxHeight: 140,
|
||||
),
|
||||
child: Image.network(
|
||||
imageUrl,
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return const Text('签字图片加载失败');
|
||||
},
|
||||
if (spaceRecordFiles.isNotEmpty) ...[
|
||||
_buildSpaceRecordFiles(spaceRecordFiles),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
if (signPath.isNotEmpty)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
presentOpaque(
|
||||
SingleImageViewer(imageUrl: _fullFileUrl(signPath)),
|
||||
context,
|
||||
);
|
||||
},
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 220,
|
||||
maxHeight: 140,
|
||||
),
|
||||
child: Image.network(
|
||||
_fullFileUrl(signPath),
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return const Text('签字图片加载失败');
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
|
|
@ -1205,6 +1230,113 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
|
|||
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() {
|
||||
if (_otherMeasuresList.isNotEmpty) {
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ class HomePageState extends RouteAwareState<HomePage>
|
|||
final routeService = RouteService();
|
||||
final mainTabs = routeService.mainTabs;
|
||||
if (mainTabs.isEmpty) {
|
||||
// 路由未加载,保持全隐藏
|
||||
// 路由未加载,保持全隐藏ƒ
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue