特殊作业修改0602

master
hs 2026-06-03 15:00:26 +08:00
parent 7f21c22d66
commit 7191c4f42f
4 changed files with 222 additions and 37 deletions

View File

@ -0,0 +1,152 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/tools/click_util.dart';
class GuardedGestureDetector extends StatelessWidget {
final Widget child;
final GuardedTapCallback? onTap;
final Object? guardKey;
final int delayMs;
final bool lockDuringExecution;
final HitTestBehavior? behavior;
const GuardedGestureDetector({
super.key,
required this.child,
this.onTap,
this.guardKey,
this.delayMs = ClickUtil.defaultDelayMs,
this.lockDuringExecution = true,
this.behavior,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: behavior,
onTap: ClickUtil.wrap(
onTap,
key: guardKey,
delayMs: delayMs,
lockDuringExecution: lockDuringExecution,
),
child: child,
);
}
}
class GuardedInkWell extends StatelessWidget {
final Widget child;
final GuardedTapCallback? onTap;
final Object? guardKey;
final int delayMs;
final bool lockDuringExecution;
final BorderRadius? borderRadius;
final Color? splashColor;
final Color? highlightColor;
const GuardedInkWell({
super.key,
required this.child,
this.onTap,
this.guardKey,
this.delayMs = ClickUtil.defaultDelayMs,
this.lockDuringExecution = true,
this.borderRadius,
this.splashColor,
this.highlightColor,
});
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: borderRadius,
splashColor: splashColor,
highlightColor: highlightColor,
onTap: ClickUtil.wrap(
onTap,
key: guardKey,
delayMs: delayMs,
lockDuringExecution: lockDuringExecution,
),
child: child,
);
}
}
class GuardedTextButton extends StatelessWidget {
final Widget child;
final GuardedTapCallback? onPressed;
final Object? guardKey;
final int delayMs;
final bool lockDuringExecution;
final ButtonStyle? style;
const GuardedTextButton({
super.key,
required this.child,
this.onPressed,
this.guardKey,
this.delayMs = ClickUtil.defaultDelayMs,
this.lockDuringExecution = true,
this.style,
});
@override
Widget build(BuildContext context) {
return TextButton(
style: style,
onPressed: ClickUtil.wrap(
onPressed,
key: guardKey,
delayMs: delayMs,
lockDuringExecution: lockDuringExecution,
),
child: child,
);
}
}
class GuardedIconButton extends StatelessWidget {
final Widget icon;
final GuardedTapCallback? onPressed;
final Object? guardKey;
final int delayMs;
final bool lockDuringExecution;
final EdgeInsetsGeometry? padding;
final BoxConstraints? constraints;
final double? iconSize;
final String? tooltip;
final Color? color;
const GuardedIconButton({
super.key,
required this.icon,
this.onPressed,
this.guardKey,
this.delayMs = ClickUtil.defaultDelayMs,
this.lockDuringExecution = true,
this.padding,
this.constraints,
this.iconSize,
this.tooltip,
this.color,
});
@override
Widget build(BuildContext context) {
return IconButton(
icon: icon,
padding: padding,
constraints: constraints,
iconSize: iconSize,
tooltip: tooltip,
color: color,
onPressed: ClickUtil.wrap(
onPressed,
key: guardKey,
delayMs: delayMs,
lockDuringExecution: lockDuringExecution,
),
);
}
}

View File

@ -48,6 +48,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
extends State<T> { extends State<T> {
bool isEditable = true; bool isEditable = true;
bool loadingInit = false; bool loadingInit = false;
bool _isSubmitting = false;
List<dynamic> levelList = []; List<dynamic> levelList = [];
final List<String> workTypeList = const ["内部作业", "相关方作业"]; final List<String> workTypeList = const ["内部作业", "相关方作业"];
@ -856,6 +857,12 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
/// ///
Future<void> submit(String status) async { Future<void> submit(String status) async {
if (_isSubmitting) return;
_isSubmitting = true;
LoadingDialogHelper.show();
try {
await beforeSubmit(status); await beforeSubmit(status);
if (!FormUtils.hasValue(pd, 'workLevel')) { if (!FormUtils.hasValue(pd, 'workLevel')) {
ToastUtil.showNormal(context, '请选择作业等级'); ToastUtil.showNormal(context, '请选择作业等级');
@ -892,8 +899,6 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
final payload = await buildSubmitPayload(status, newGroups); final payload = await buildSubmitPayload(status, newGroups);
LoadingDialogHelper.show();
try {
final result = final result =
status == '1' status == '1'
? await SpecialWorkApi.specialWorkSave(payload, workType) ? await SpecialWorkApi.specialWorkSave(payload, workType)
@ -909,6 +914,7 @@ abstract class SpecialWorkApplyBaseState<T extends SpecialWorkApplyBasePage>
ToastUtil.showNormal(context, '作业提交失败:$e'); ToastUtil.showNormal(context, '作业提交失败:$e');
} finally { } finally {
LoadingDialogHelper.dismiss(); LoadingDialogHelper.dismiss();
_isSubmitting = false;
} }
} }

View File

@ -86,7 +86,7 @@ abstract class SpecialWorkTaskPageBase extends StatefulWidget {
/// ///
/// ///
void onSubmitSuccess(BuildContext context) { void onSubmitSuccess(BuildContext context) {
Navigator.of(context).pop(); Navigator.of(context).pop(true);
} }
@override @override
@ -132,6 +132,8 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
/// / /// /
final TextEditingController _contentController = TextEditingController(); final TextEditingController _contentController = TextEditingController();
bool _isSubmitting = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -273,11 +275,22 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
/// - /// -
/// - // /// - //
Future<void> _submit(String status) async { Future<void> _submit(String status) async {
if (_isSubmitting) return;
_isSubmitting = true;
LoadingDialogHelper.show();
void finishSubmit() {
LoadingDialogHelper.hide();
_isSubmitting = false;
}
final Map<String, dynamic> others = {}; final Map<String, dynamic> others = {};
bool isDelayTime = true; bool isDelayTime = true;
if (pd['componentName'] == 'completeDelayTime' && other['isCompleteWork'] == 1) { if (pd['componentName'] == 'completeDelayTime' && other['isCompleteWork'] == 1) {
if (other['isDelayWork'] == 1 && !FormUtils.hasValue(other, 'hotTime')) { if (other['isDelayWork'] == 1 && !FormUtils.hasValue(other, 'hotTime')) {
finishSubmit();
ToastUtil.showNormal(context, '请选择动火日期'); ToastUtil.showNormal(context, '请选择动火日期');
return; return;
} }
@ -299,6 +312,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
context, context,
'$stepName】未完成,当前填写$currentFilllTimes次,应填写$minFillTimes次,无法流转到下一步', '$stepName】未完成,当前填写$currentFilllTimes次,应填写$minFillTimes次,无法流转到下一步',
); );
finishSubmit();
return; return;
} }
} }
@ -314,6 +328,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
if (qNumber.isNotEmpty) { if (qNumber.isNotEmpty) {
for (var i = 0; i < qNumber.length; i++) { for (var i = 0; i < qNumber.length; i++) {
if (qNumber[i].isNotEmpty && (i >= aNumber.length || aNumber[i].isEmpty)) { if (qNumber[i].isNotEmpty && (i >= aNumber.length || aNumber[i].isEmpty)) {
finishSubmit();
ToastUtil.showNormal(context, '安全防护措施第${index + 1}项未填写内容'); ToastUtil.showNormal(context, '安全防护措施第${index + 1}项未填写内容');
return; return;
} }
@ -321,11 +336,13 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
} }
if ('${measure['status']}' == '-1' && widget.mesureText.isNotEmpty) { if ('${measure['status']}' == '-1' && widget.mesureText.isNotEmpty) {
finishSubmit();
ToastUtil.showNormal(context, '存在不合格的安全措施,请打回'); ToastUtil.showNormal(context, '存在不合格的安全措施,请打回');
return; return;
} }
if (!FormUtils.hasValue(measure, 'signPath')) { if (!FormUtils.hasValue(measure, 'signPath')) {
finishSubmit();
ToastUtil.showNormal(context, '安全防护措施第${index + 1}项请签字'); ToastUtil.showNormal(context, '安全防护措施第${index + 1}项请签字');
return; return;
} }
@ -336,6 +353,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
// 3) // 3)
if (FormUtils.hasValue(pd, 'locateStepFlag') && pd['locateStepFlag'] == 1) { if (FormUtils.hasValue(pd, 'locateStepFlag') && pd['locateStepFlag'] == 1) {
if (pd['longitude'] == null || pd['latitude'] == null) { if (pd['longitude'] == null || pd['latitude'] == null) {
finishSubmit();
ToastUtil.showNormal(context, '请定位'); ToastUtil.showNormal(context, '请定位');
return; return;
} }
@ -347,6 +365,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
final selectLevel = group['selectLevel']; final selectLevel = group['selectLevel'];
if (selectLevel != 1 && other['isCompleteWork'] != 998) { if (selectLevel != 1 && other['isCompleteWork'] != 998) {
if (!(FormUtils.hasValue(other, 'isDelayWork') && other['isDelayWork'] == 1)) { if (!(FormUtils.hasValue(other, 'isDelayWork') && other['isDelayWork'] == 1)) {
finishSubmit();
ToastUtil.showNormal(context, '请选择${group['actorField'] ?? '处理人'}'); ToastUtil.showNormal(context, '请选择${group['actorField'] ?? '处理人'}');
return; return;
} }
@ -357,9 +376,11 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
// 5) // 5)
if (signImages.isEmpty) { if (signImages.isEmpty) {
if (!FormUtils.hasValue(other, 'isCompleteWork')) { if (!FormUtils.hasValue(other, 'isCompleteWork')) {
finishSubmit();
ToastUtil.showNormal(context, '请签字'); ToastUtil.showNormal(context, '请签字');
return; return;
} else if (other['isCompleteWork'] == 1) { } else if (other['isCompleteWork'] == 1) {
finishSubmit();
ToastUtil.showNormal(context, '请签字'); ToastUtil.showNormal(context, '请签字');
return; return;
} }
@ -404,17 +425,16 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
form['signLogs'] = _groups; form['signLogs'] = _groups;
} }
LoadingDialogHelper.show();
final signResult = await _checkSignature(); final signResult = await _checkSignature();
if (!signResult) { if (!signResult) {
LoadingDialogHelper.hide(); finishSubmit();
ToastUtil.showNormal(context, '作业提交失败'); ToastUtil.showNormal(context, '作业提交失败');
return; return;
} }
try { try {
final res = await SpecialWorkApi.specialWorkNextStep(form); final res = await SpecialWorkApi.specialWorkNextStep(form);
LoadingDialogHelper.hide(); finishSubmit();
if (res['success'] == true) { if (res['success'] == true) {
ToastUtil.showNormal(context, '提交成功'); ToastUtil.showNormal(context, '提交成功');
widget.onSubmitSuccess(context); widget.onSubmitSuccess(context);
@ -422,7 +442,7 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
ToastUtil.showNormal(context, res['errMessage'] ?? '作业提交失败'); ToastUtil.showNormal(context, res['errMessage'] ?? '作业提交失败');
} }
} catch (e) { } catch (e) {
LoadingDialogHelper.hide(); finishSubmit();
ToastUtil.showNormal(context, '作业提交失败'); ToastUtil.showNormal(context, '作业提交失败');
} }
} }
@ -666,11 +686,12 @@ class _SpecialWorkTaskPageBaseState extends State<SpecialWorkTaskPageBase> {
barrierDismissible:false, barrierDismissible:false,
); );
if (confirmed != null) { if (confirmed != null) {
if (confirmed.trim().isNotEmpty) { if (!mounted) return;
final rejectText = confirmed.trim();
if (rejectText.isNotEmpty) {
setState(() { setState(() {
rejectReason = '${confirmed}'; rejectReason = rejectText;
}); });
Navigator.pop(context);
_submit('2'); _submit('2');
}else{ }else{
ToastUtil.showError(context, '请输入打回原因'); ToastUtil.showError(context, '请输入打回原因');

View File

@ -449,6 +449,12 @@ class _SpecialWorkWaitPageBaseState extends State<SpecialWorkWaitPageBase> {
} }
} }
Future<void> _handleOpenDetail(Map<String, dynamic> item, bool isEdit) async {
await widget.onOpenDetail(context, item, isEdit);
if (!mounted) return;
_refreshList();
}
Widget _buildListItem(Map<String, dynamic> item) { Widget _buildListItem(Map<String, dynamic> item) {
final workInfo = widget.getWorkInfo(item); final workInfo = widget.getWorkInfo(item);
final info = widget.getInfo(workInfo); final info = widget.getInfo(workInfo);
@ -456,12 +462,12 @@ class _SpecialWorkWaitPageBaseState extends State<SpecialWorkWaitPageBase> {
// //
final onFlowTap = () => _openFlowDrawer(item); final onFlowTap = () => _openFlowDrawer(item);
final onViewTap = () => widget.onOpenDetail(context, item, false); final onViewTap = () => _handleOpenDetail(item, false);
final onWithdrawTap = widget.canWithdraw(item, workInfo) ? () => _handleWithdraw(item) : null; final onWithdrawTap = widget.canWithdraw(item, workInfo) ? () => _handleWithdraw(item) : null;
final onDeleteTap = widget.canDeleteAndEdit(item, workInfo) ? () => _handleDelete(item) : null; final onDeleteTap = widget.canDeleteAndEdit(item, workInfo) ? () => _handleDelete(item) : null;
final onEditTap = widget.canDeleteAndEdit(item, workInfo) ? () => widget.onOpenDetail(context, item, true) : null; final onEditTap = widget.canDeleteAndEdit(item, workInfo) ? () => _handleOpenDetail(item, true) : null;
final onApproveTap = widget.canApprove(item, workInfo) ? () => widget.onOpenDetail(context, item, true) : null; final onApproveTap = widget.canApprove(item, workInfo) ? () => _handleOpenDetail(item, true) : null;
final onGasAnalysisTap = widget.isGasStep(item) ? () => widget.onOpenDetail(context, item, true) : null; final onGasAnalysisTap = widget.isGasStep(item) ? () => _handleOpenDetail(item, true) : null;
return Card( return Card(
color: Colors.white, color: Colors.white,