。。。。
parent
0923f27daa
commit
2bb1fae09b
|
|
@ -25,9 +25,9 @@ class ApiService {
|
|||
|
||||
/// 登录及其他管理后台接口
|
||||
// static const String basePath = "https://qaaqwh.qhdsafety.com/integrated_whb";
|
||||
// static const String basePath = "http://192.168.20.240:8500/integrated_whb";//测试服务器
|
||||
static const String basePath = "http://192.168.20.240:8500/integrated_whb";//测试服务器
|
||||
// static const String basePath = "http://192.168.0.25:28199";//王轩服务器
|
||||
static const String basePath = "http://192.168.0.45:28199";//长久服务器
|
||||
// static const String basePath = "http://192.168.0.45:28199";//长久服务器
|
||||
|
||||
/// 图片文件服务
|
||||
static const String baseImgPath = "https://file.zcloudchina.com/YTHFile";
|
||||
|
|
|
|||
|
|
@ -280,10 +280,7 @@ class _SafecheckAssignmentDetailPageState
|
|||
isEditable: _isEdit,
|
||||
isRequired: false,
|
||||
isClean: false,
|
||||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {});
|
||||
},
|
||||
onTapClean: () {},
|
||||
text: form['RECTIFICATIONDEPTNAME'] ?? '请选择',
|
||||
onTap: () => chooseUnitHandle('key'),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ class _StrengthenStudyPageState extends State<StrengthenStudyPage> {
|
|||
'STUDENT_ID': widget.studentId,
|
||||
'STRENGTHEN_PAPER_QUESTION_ID': _info['STRENGTHEN_STAGEEXAMPAPER_INPUT_ID'],
|
||||
...data
|
||||
}, examType: type), context);
|
||||
}, examType: type, jumpType: 2,), context);
|
||||
} else {
|
||||
ToastUtil.showError(context, '请求错误');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,12 +212,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
seconds: _lastReported.inSeconds,
|
||||
);
|
||||
}
|
||||
_lastReported = Duration.zero;
|
||||
|
||||
_currentVideoData = data;
|
||||
_hasNodes = hasNodes;
|
||||
_currentFirstIndex = fi;
|
||||
_currentNodeIndex = ni;
|
||||
|
||||
// 暂停已有播放器(安全)
|
||||
try {
|
||||
|
|
@ -250,6 +245,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
'IS_NODE': hasNodes,
|
||||
'FIRST_INDEX': fi,
|
||||
'NODE_INDEX': ni,
|
||||
'IS_VIDEO': 1,
|
||||
};
|
||||
await _submitPlayTime(
|
||||
snapshot: docSnapshot,
|
||||
|
|
@ -262,6 +258,12 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
ToastUtil.showNormal(context, '课件文件资源已失效,请联系管理员');
|
||||
}
|
||||
} else {
|
||||
_currentVideoData = data;
|
||||
_lastReported = Duration.zero;
|
||||
|
||||
_hasNodes = hasNodes;
|
||||
_currentFirstIndex = fi;
|
||||
_currentNodeIndex = ni;
|
||||
LoadingDialogHelper.show();
|
||||
// 视频
|
||||
await _getVideoPlayInfo(data['VIDEOCOURSEWARE_ID']);
|
||||
|
|
@ -475,14 +477,14 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
required bool end,
|
||||
required int seconds,
|
||||
}) async {
|
||||
// snapshot 中应该包含 VIDEOCOURSEWARE_ID, CURRICULUM_ID, CHAPTER_ID, VIDEOTIME, ...
|
||||
// snapshot 必须包含 VIDEOCOURSEWARE_ID
|
||||
if (snapshot['VIDEOCOURSEWARE_ID'] == null ||
|
||||
snapshot['VIDEOCOURSEWARE_ID'] == '')
|
||||
return;
|
||||
snapshot['VIDEOCOURSEWARE_ID'] == '') return;
|
||||
|
||||
// 如果已经上报结束并且当前不是结束上报,则跳过非结束上报
|
||||
// 如果已经上报结束并且当前不是结束上报,则跳过非结束上报(原逻辑)
|
||||
if (_endReported && !end) return;
|
||||
|
||||
// 构造要上报的参数
|
||||
Map data = {
|
||||
'VIDEOCOURSEWARE_ID': snapshot['VIDEOCOURSEWARE_ID'] ?? '',
|
||||
'CURRICULUM_ID': snapshot['CURRICULUM_ID'] ?? '',
|
||||
|
|
@ -495,6 +497,10 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
'loading': false,
|
||||
};
|
||||
|
||||
// 如果这是“非视频课件”(通过 snapshot['IS_VIDEO']==1 标记),
|
||||
// 则按照“学完即 100%”的规则单次上报并把 UI 设置为 100%。
|
||||
final isNonVideo = (snapshot['IS_VIDEO'] != null && snapshot['IS_VIDEO'].toString() == '1');
|
||||
|
||||
const int maxRetries = 2;
|
||||
int attempt = 0;
|
||||
while (true) {
|
||||
|
|
@ -503,32 +509,14 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
final resData = await ApiService.fnSubmitPlayTime(data);
|
||||
final pd = resData['pd'] ?? {};
|
||||
|
||||
// 解析后端返回的 RESOURCETIME(可能是数字或字符串)
|
||||
final resTraw = pd['RESOURCETIME'];
|
||||
final resT =
|
||||
(resTraw is num)
|
||||
? resTraw.toDouble()
|
||||
: double.tryParse('$resTraw') ?? seconds.toDouble();
|
||||
|
||||
final videoTimeRaw = snapshot['VIDEOTIME'];
|
||||
final videoTime =
|
||||
(videoTimeRaw is String)
|
||||
? double.tryParse(videoTimeRaw) ?? 1.0
|
||||
: (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0);
|
||||
|
||||
final comp = pd['PLAYCOUNT'] != null && pd['PLAYCOUNT'] > 0;
|
||||
|
||||
final pctDouble =
|
||||
comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0);
|
||||
final pct = (pctDouble.clamp(0.00, 100.00) * 100).round() / 100;
|
||||
final str = '${pct}%';
|
||||
|
||||
if (isNonVideo) {
|
||||
// 非视频课件:强制显示 100%,不依赖后端返回的 RESOURCETIME 比例
|
||||
final str = '100%';
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (snapshot['IS_NODE'] == true) {
|
||||
final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
|
||||
final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex;
|
||||
// 保护性检查,避免索引越界
|
||||
if (fi >= 0 && fi < _videoList.length) {
|
||||
final nodes = _videoList[fi]['nodes'] as List<dynamic>?;
|
||||
if (nodes != null && ni >= 0 && ni < nodes.length) {
|
||||
|
|
@ -544,7 +532,63 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
});
|
||||
}
|
||||
|
||||
// 如果是结束上报且后端标注可考试,则弹窗处理
|
||||
// 如果后端在 pd 中表明可以考试,按之前逻辑处理(和视频一致)
|
||||
if (end && pd['CANEXAM'] == '1') {
|
||||
_videoController?.pause();
|
||||
|
||||
final ok = await CustomAlertDialog.showConfirm(
|
||||
context,
|
||||
title: '温馨提示',
|
||||
content: '当前任务内所有课程均已学完,是否直接参加考试?',
|
||||
cancelText: '否',
|
||||
confirmText: '是',
|
||||
);
|
||||
if (ok) {
|
||||
_startExam(resData);
|
||||
}
|
||||
}
|
||||
|
||||
break; // 非视频已上报并处理完毕 -> 退出
|
||||
}
|
||||
|
||||
// 以下为视频上报原有逻辑:解析后端返回数据并更新进度
|
||||
final resTraw = pd['RESOURCETIME'];
|
||||
final resT = (resTraw is num) ? resTraw.toDouble() : double.tryParse('$resTraw') ?? seconds.toDouble();
|
||||
|
||||
final videoTimeRaw = snapshot['VIDEOTIME'];
|
||||
final videoTime = (videoTimeRaw is String)
|
||||
? double.tryParse(videoTimeRaw) ?? 1.0
|
||||
: (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0);
|
||||
|
||||
final comp = pd['PLAYCOUNT'] != null && pd['PLAYCOUNT'] > 0;
|
||||
final pctDouble = comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0);
|
||||
// 保留两位小数并去掉不必要末尾
|
||||
double pctClamped = pctDouble.clamp(0.00, 100.00);
|
||||
// 四舍五入到 2 位小数
|
||||
final pctRounded = (pctClamped * 100).round() / 100;
|
||||
final str = '${pctRounded}%';
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (snapshot['IS_NODE'] == true) {
|
||||
final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
|
||||
final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex;
|
||||
if (fi >= 0 && fi < _videoList.length) {
|
||||
final nodes = _videoList[fi]['nodes'] as List<dynamic>?;
|
||||
if (nodes != null && ni >= 0 && ni < nodes.length) {
|
||||
_videoList[fi]['nodes'][ni]['percent'] = str;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
|
||||
if (fi >= 0 && fi < _videoList.length) {
|
||||
_videoList[fi]['percent'] = str;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 如果是结束上报且后端标注可考试,则弹窗处理(原逻辑)
|
||||
if (end && pd['CANEXAM'] == '1') {
|
||||
_videoController?.pause();
|
||||
|
||||
|
|
@ -572,6 +616,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// 开始考试
|
||||
Future<void> _startExam(Map resData) async {
|
||||
Map pd = resData['pd'] ?? {};
|
||||
|
|
@ -604,7 +649,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
|
|||
paper['STAGEEXAMPAPERINPUT_ID'] ?? '',
|
||||
...data,
|
||||
},
|
||||
examType: TakeExamType.video_study,
|
||||
examType: TakeExamType.video_study, jumpType: 2,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ class _StudyMyTaskPageState extends State<StudyMyTaskPage>
|
|||
resData['STAGEEXAMPAPERINPUT_ID'] ?? '',
|
||||
...data
|
||||
},
|
||||
examType: TakeExamType.video_study),
|
||||
examType: TakeExamType.video_study, jumpType: 1,),
|
||||
context);
|
||||
} else {
|
||||
ToastUtil.showError(context, '请求错误');
|
||||
|
|
|
|||
|
|
@ -50,11 +50,14 @@ class TakeExamPage extends StatefulWidget {
|
|||
const TakeExamPage({
|
||||
required this.examInfo,
|
||||
required this.examType,
|
||||
required this.jumpType,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final Map<String, dynamic> examInfo;
|
||||
final TakeExamType examType;
|
||||
final int jumpType;
|
||||
|
||||
|
||||
@override
|
||||
State<TakeExamPage> createState() => _TakeExamPageState();
|
||||
|
|
@ -113,6 +116,9 @@ class _TakeExamPageState extends State<TakeExamPage> {
|
|||
content: '您无考试次数!',
|
||||
);
|
||||
if (ok) {
|
||||
if (widget.jumpType == 2) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,19 @@ class ItemListWidget {
|
|||
/// 强制必选 不受是否可以编译和是否必选影响
|
||||
}) {
|
||||
// 如果启用数字输入,使用数字键盘
|
||||
final actualKeyboardType = isNumericInput
|
||||
final actualKeyboardType =
|
||||
isNumericInput
|
||||
? const TextInputType.numberWithOptions(decimal: true)
|
||||
: keyboardType;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: isEditable
|
||||
mainAxisAlignment:
|
||||
isEditable
|
||||
? MainAxisAlignment.start
|
||||
: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -73,12 +78,18 @@ class ItemListWidget {
|
|||
style: TextStyle(fontSize: fontSize),
|
||||
maxLines: 1,
|
||||
// 添加输入格式化器(如果是数字输入)
|
||||
inputFormatters: isNumericInput
|
||||
inputFormatters:
|
||||
isNumericInput
|
||||
? [
|
||||
// 过滤非数字和小数点字符
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[\d\.]')),
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r'[\d\.]'),
|
||||
),
|
||||
// 自定义格式化器,限制小数位数
|
||||
TextInputFormatter.withFunction((oldValue, newValue) {
|
||||
TextInputFormatter.withFunction((
|
||||
oldValue,
|
||||
newValue,
|
||||
) {
|
||||
if (newValue.text.isEmpty) return newValue;
|
||||
|
||||
// 检查多个小数点的情况
|
||||
|
|
@ -87,8 +98,11 @@ class ItemListWidget {
|
|||
}
|
||||
|
||||
// 使用正则表达式匹配有效输入
|
||||
if (RegExp(r'^\d*\.?\d{0,' + maxDecimalPlaces.toString() + r'}$')
|
||||
.hasMatch(newValue.text)) {
|
||||
if (RegExp(
|
||||
r'^\d*\.?\d{0,' +
|
||||
maxDecimalPlaces.toString() +
|
||||
r'}$',
|
||||
).hasMatch(newValue.text)) {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +144,6 @@ class ItemListWidget {
|
|||
bool isRequired = true,
|
||||
String hintText = '请输入',
|
||||
ValueChanged<String>? onChanged,
|
||||
|
||||
}) {
|
||||
return Container(
|
||||
// 统一左右 padding,保证标题和内容在同一左侧基线
|
||||
|
|
@ -206,12 +219,15 @@ class ItemListWidget {
|
|||
VoidCallback? onTapTip, // 提醒回调
|
||||
bool isRequired = true,
|
||||
String cleanText = '清除',
|
||||
double horizontalnum= horizontal_inset,
|
||||
double horizontalnum = horizontal_inset,
|
||||
}) {
|
||||
return InkWell(
|
||||
onTap: isEditable ? onTap : null,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontalnum),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontalnum,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// 1. 标题
|
||||
|
|
@ -232,13 +248,19 @@ class ItemListWidget {
|
|||
if (isTip)
|
||||
Column(
|
||||
children: [
|
||||
IconButton(onPressed: onTapTip, icon: Icon(Icons.error_outline,color: Colors.blue,size: 20,)),
|
||||
const SizedBox()
|
||||
IconButton(
|
||||
onPressed: onTapTip,
|
||||
icon: Icon(
|
||||
Icons.error_outline,
|
||||
color: Colors.blue,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
const SizedBox(),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isClean)
|
||||
|
|
@ -270,7 +292,12 @@ class ItemListWidget {
|
|||
textAlign: TextAlign.right,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: isEditable ? (text == '请选择' ? Colors.black87 :Colors.black) : detailtextColor,
|
||||
color:
|
||||
isEditable
|
||||
? (text == '请选择'
|
||||
? Colors.black87
|
||||
: Colors.black)
|
||||
: detailtextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -306,7 +333,10 @@ class ItemListWidget {
|
|||
return InkWell(
|
||||
onTap: isEditable ? onTap : null,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
|
|
@ -390,7 +420,10 @@ class ItemListWidget {
|
|||
bool isRequired = true,
|
||||
}) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -482,7 +515,10 @@ class ItemListWidget {
|
|||
bool isRequired = true,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -519,7 +555,11 @@ class ItemListWidget {
|
|||
vertical: 2,
|
||||
horizontal: 10,
|
||||
),
|
||||
textStyle: TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold),
|
||||
textStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: Colors.green,
|
||||
onPressed: onTap,
|
||||
),
|
||||
|
|
@ -569,10 +609,13 @@ class ItemListWidget {
|
|||
required String text, // 显示内容或提示
|
||||
required VoidCallback? onTap, // 第一行点击回调
|
||||
double fontSize = 14, // 字体大小
|
||||
String buttonText = '分析详情'
|
||||
String buttonText = '气体分析详情',
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -604,11 +647,12 @@ class ItemListWidget {
|
|||
CustomButton(
|
||||
text: buttonText,
|
||||
height: 30,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 2,
|
||||
horizontal: 10,
|
||||
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 10),
|
||||
textStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textStyle: TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold),
|
||||
backgroundColor: Colors.green,
|
||||
onPressed: onTap,
|
||||
),
|
||||
|
|
@ -628,7 +672,10 @@ class ItemListWidget {
|
|||
bool isRequired = false,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -655,27 +702,28 @@ class ItemListWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 单行布局:
|
||||
/// 标题 + 按钮(挨着)
|
||||
static Widget OneRowStartButtonTitle({
|
||||
required String label, // 标题
|
||||
String buttonText = '分析详情', // 按钮文字
|
||||
String buttonText = '气体分析详情', // 按钮文字
|
||||
String text = '', // 标题
|
||||
required VoidCallback onTap, // 点击回调
|
||||
double fontSize = 14, // 字体大小
|
||||
Color btnColor = Colors.green,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
|
||||
),
|
||||
CustomButton(
|
||||
text: buttonText,
|
||||
|
|
@ -701,7 +749,10 @@ class ItemListWidget {
|
|||
void Function(String)? onTapCallBack,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -720,7 +771,8 @@ class ItemListWidget {
|
|||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}$imgPath');
|
||||
if (onTapCallBack != null)
|
||||
onTapCallBack('${ApiService.baseImgPath}$imgPath');
|
||||
},
|
||||
child:
|
||||
imgPath.isNotEmpty
|
||||
|
|
@ -731,10 +783,9 @@ class ItemListWidget {
|
|||
)
|
||||
: SizedBox(),
|
||||
),
|
||||
if (text.isNotEmpty)
|
||||
Text(text)
|
||||
if (text.isNotEmpty) Text(text),
|
||||
],
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -758,13 +809,13 @@ class ItemListWidget {
|
|||
// 标题部分
|
||||
if (title.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
@ -779,16 +830,20 @@ class ItemListWidget {
|
|||
return Container(
|
||||
margin: const EdgeInsets.only(right: 8), // 图片间距
|
||||
child: ClipRRect(
|
||||
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}${imageUrls![index] ?? ''}');
|
||||
if (onTapCallBack != null)
|
||||
onTapCallBack(
|
||||
'${ApiService.baseImgPath}${imageUrls![index] ?? ''}',
|
||||
);
|
||||
},
|
||||
child: Image.network(
|
||||
'${ApiService.baseImgPath}${imageUrls![index] ?? ''}',
|
||||
width: 80, // 图片宽度
|
||||
height: 80, // 图片高度
|
||||
width: 80,
|
||||
// 图片宽度
|
||||
height: 80,
|
||||
// 图片高度
|
||||
fit: BoxFit.fill,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
|
|
@ -796,7 +851,9 @@ class ItemListWidget {
|
|||
width: 80,
|
||||
height: 80,
|
||||
color: Colors.grey[200],
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
|
|
@ -808,7 +865,7 @@ class ItemListWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
@ -817,6 +874,7 @@ class ItemListWidget {
|
|||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 多行垂直布局:
|
||||
/// 标题+按钮
|
||||
/// 编辑框列表,多个编辑框可删除
|
||||
|
|
@ -832,7 +890,10 @@ class ItemListWidget {
|
|||
bool isRequired = true,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -910,15 +971,19 @@ class ItemListWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 多行垂直布局:
|
||||
/// 标题、图片、说明、签字信息
|
||||
static Widget mulColumnRowTitleAndImages({
|
||||
required String title, // 第一行标题
|
||||
required List<dynamic>? imageUrls,
|
||||
required String text, // 描述
|
||||
required List<dynamic>? signUrls, /// 签字
|
||||
required List<dynamic>? signTimes, /// 签字时间
|
||||
required List<dynamic>? signUrls,
|
||||
|
||||
/// 签字
|
||||
required List<dynamic>? signTimes,
|
||||
|
||||
/// 签字时间
|
||||
double row2Height = 80, // 第二行高度
|
||||
double fontSize = 14, // 字体大小
|
||||
void Function(String)? onTapCallBack,
|
||||
|
|
@ -930,13 +995,13 @@ class ItemListWidget {
|
|||
children: [
|
||||
// 标题部分
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
@ -954,12 +1019,17 @@ class ItemListWidget {
|
|||
borderRadius: BorderRadius.circular(8),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (onTapCallBack != null) onTapCallBack('${ApiService.baseImgPath}${imageUrls![index] ?? ''}');
|
||||
if (onTapCallBack != null)
|
||||
onTapCallBack(
|
||||
'${ApiService.baseImgPath}${imageUrls![index] ?? ''}',
|
||||
);
|
||||
},
|
||||
child: Image.network(
|
||||
'${ApiService.baseImgPath}${imageUrls![index] ?? ''}',
|
||||
width: 80, // 图片宽度
|
||||
height: 80, // 图片高度
|
||||
width: 80,
|
||||
// 图片宽度
|
||||
height: 80,
|
||||
// 图片高度
|
||||
fit: BoxFit.fill,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
|
|
@ -967,7 +1037,9 @@ class ItemListWidget {
|
|||
width: 80,
|
||||
height: 80,
|
||||
color: Colors.grey[200],
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
|
|
@ -979,13 +1051,13 @@ class ItemListWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Row()
|
||||
Row(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
@ -1000,17 +1072,17 @@ class ItemListWidget {
|
|||
bool isRequired = true,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: vertical_inset, horizontal: horizontal_inset),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: vertical_inset,
|
||||
horizontal: horizontal_inset,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 第一行:标题
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
|
@ -1019,17 +1091,18 @@ class ItemListWidget {
|
|||
text,
|
||||
maxLines: 5,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: detailtextColor,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, color: detailtextColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
static Widget itemContainer(Widget child, {double horizontal = horizontal_inset, double vertical = vertical_inset}) {
|
||||
|
||||
static Widget itemContainer(
|
||||
Widget child, {
|
||||
double horizontal = horizontal_inset,
|
||||
double vertical = vertical_inset,
|
||||
}) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
|
|
@ -1040,10 +1113,111 @@ class ItemListWidget {
|
|||
);
|
||||
}
|
||||
|
||||
// static Widget aaa({}){
|
||||
// return
|
||||
// }
|
||||
|
||||
static Widget buildFlowStepItem({
|
||||
required List<Map<String, dynamic>> flowList,
|
||||
}) {
|
||||
final int lastDoneIndex = flowList.lastIndexWhere((e) => e['STATUS'] == 1);
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1
|
||||
? Colors.green
|
||||
: (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1
|
||||
? Colors.green
|
||||
: (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(
|
||||
child: Container(width: 1, color: Colors.grey[300]),
|
||||
),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(
|
||||
child: Container(width: 1, color: Colors.grey[300]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null) ...[
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
] else if (item['FINISHED_SIGN_USER'] != null) ...[
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
] else if (item['ACT_USER_NAME'] != null) ...[
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,16 +61,59 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
// 可用宽度(减去外层 margin)
|
||||
final containerWidth = constraints.maxWidth;
|
||||
|
||||
// 或 .top / .bottom
|
||||
columnWidths: {
|
||||
0: FlexColumnWidth(10),
|
||||
1: FixedColumnWidth(210),
|
||||
2: FlexColumnWidth(20),
|
||||
if (!isAllowEdit) 3: FixedColumnWidth(60),
|
||||
},
|
||||
// 期望的固定列宽(可以根据需要微调)
|
||||
double col0Fixed = 40; // 第一列:序号(较窄)
|
||||
double col2Fixed = 60; // 第三列:操作(保留较宽以放按钮)
|
||||
double col3Fixed = 80; // 第四列:确认人(头像列)
|
||||
|
||||
// 如果不显示第4列(isAllowEdit == true),则第4列宽为0,不计入固定总和
|
||||
final showCol3 = !isAllowEdit;
|
||||
|
||||
// 计算固定列总和并在超窄屏下进行缩放保护
|
||||
double fixedTotal =
|
||||
col0Fixed + col2Fixed + (showCol3 ? col3Fixed : 0);
|
||||
// 保证至少留 10% 的空间给可伸缩列,避免其被压扁为 0
|
||||
final minFlexPortion = containerWidth * 0.10;
|
||||
if (fixedTotal + minFlexPortion > containerWidth &&
|
||||
fixedTotal > 0) {
|
||||
final availableForFixed = (containerWidth - minFlexPortion)
|
||||
.clamp(0.0, containerWidth);
|
||||
final scale = availableForFixed / fixedTotal;
|
||||
col0Fixed = (col0Fixed * scale).clamp(
|
||||
28.0,
|
||||
col0Fixed,
|
||||
); // 最小28px避免看不清
|
||||
col2Fixed = (col2Fixed * scale).clamp(
|
||||
60.0,
|
||||
col2Fixed,
|
||||
); // 最小60px给按钮留空间
|
||||
if (showCol3)
|
||||
col3Fixed = (col3Fixed * scale).clamp(
|
||||
36.0,
|
||||
col3Fixed,
|
||||
); // 头像最小36px
|
||||
fixedTotal =
|
||||
col0Fixed + col2Fixed + (showCol3 ? col3Fixed : 0);
|
||||
}
|
||||
|
||||
// 列宽分配:第一列、第三列、第四列为固定;第二列为弹性
|
||||
final columnWidths = <int, TableColumnWidth>{
|
||||
0: FixedColumnWidth(col0Fixed),
|
||||
1: const FlexColumnWidth(1),
|
||||
2: FixedColumnWidth(col2Fixed),
|
||||
};
|
||||
if (showCol3) {
|
||||
columnWidths[3] = FixedColumnWidth(col3Fixed);
|
||||
}
|
||||
|
||||
return Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
columnWidths: columnWidths,
|
||||
border: TableBorder(
|
||||
horizontalInside: BorderSide(color: Colors.grey.shade300),
|
||||
verticalInside: BorderSide(color: Colors.grey.shade300),
|
||||
|
|
@ -103,7 +146,9 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
child: Center(
|
||||
child: Text(
|
||||
isAllowEdit ? '操作' : '是否\n涉及',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -136,19 +181,13 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 主要安全措施
|
||||
Text(item['PROTECTIVE_MEASURES'] as String? ?? ''),
|
||||
// // 签名图片
|
||||
// if (item.containsKey('SIGN_PATH') &&
|
||||
// (item['SIGN_PATH'] as String).isNotEmpty)
|
||||
// ..._buildImageRows(
|
||||
// context,
|
||||
// (item['SIGN_PATH'] as String).split(','),
|
||||
// item['SIGN_TIME'] as String? ?? '',
|
||||
// ),
|
||||
|
||||
Text(
|
||||
item['PROTECTIVE_MEASURES'] as String? ?? '',
|
||||
),
|
||||
// 问题1~4 + 答案(可编辑或只读)
|
||||
for (var i = 1; i <= 4; i++)
|
||||
if ((item['QUESTION$i'] as String?)?.isNotEmpty ??
|
||||
if ((item['QUESTION$i'] as String?)
|
||||
?.isNotEmpty ??
|
||||
false)
|
||||
_buildQnA(item, i),
|
||||
// 操作图片
|
||||
|
|
@ -169,7 +208,7 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
|
||||
// 第二列:状态文字/按钮 + 操作图片
|
||||
// 第三列:状态文字/按钮 + 操作图片
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
|
|
@ -210,13 +249,14 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
|
||||
// 第四列:确认人(只在非编辑模式显示)
|
||||
if (!isAllowEdit)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (item.containsKey('SIGN_PATH') &&
|
||||
(item['SIGN_PATH'] as String).isNotEmpty)
|
||||
// 把 SIGN_PATH 切分为单张图片 path 列表,并去掉可能的空格
|
||||
...((item['SIGN_PATH'] as String)
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
|
|
@ -228,7 +268,9 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
child: GestureDetector(
|
||||
onTap: () {
|
||||
presentOpaque(
|
||||
SingleImageViewer(imageUrl: imageUrl),
|
||||
SingleImageViewer(
|
||||
imageUrl: imageUrl,
|
||||
),
|
||||
context,
|
||||
);
|
||||
},
|
||||
|
|
@ -237,7 +279,6 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
width: 40,
|
||||
height: 40,
|
||||
fit: BoxFit.fill,
|
||||
// 防止图片加载失败导致布局异常
|
||||
errorBuilder:
|
||||
(_, __, ___) => Container(
|
||||
width: 40,
|
||||
|
|
@ -259,6 +300,8 @@ class MeasuresListWidget extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -1144,12 +1187,17 @@ class _SelectionPopupState extends State<SelectionPopup> {
|
|||
),
|
||||
// 列表多选
|
||||
Expanded(
|
||||
child:
|
||||
ListTileTheme(
|
||||
child: ListTileTheme(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 0),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 0,
|
||||
horizontal: 0,
|
||||
),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
),
|
||||
itemCount: list.length,
|
||||
itemBuilder: (c, i) {
|
||||
final item = list[i];
|
||||
|
|
@ -1161,10 +1209,15 @@ class _SelectionPopupState extends State<SelectionPopup> {
|
|||
final checked = value.contains(key);
|
||||
return CheckboxListTile(
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 0, horizontal: 0),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 0,
|
||||
horizontal: 0,
|
||||
),
|
||||
activeColor: Colors.blue,
|
||||
dense: true, // 更紧凑
|
||||
visualDensity: const VisualDensity(vertical: -4), // 调整垂直密度:-1..-4
|
||||
dense: true,
|
||||
// 更紧凑
|
||||
visualDensity: const VisualDensity(vertical: -4),
|
||||
// 调整垂直密度:-1..-4
|
||||
title: Column(
|
||||
mainAxisSize: MainAxisSize.min, // 避免 Column 占用多余高度
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
|
@ -1199,12 +1252,10 @@ class _SelectionPopupState extends State<SelectionPopup> {
|
|||
selectValue.remove(key);
|
||||
});
|
||||
},
|
||||
)
|
||||
;
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
),
|
||||
),
|
||||
// 确定/关闭
|
||||
Padding(
|
||||
|
|
@ -1317,13 +1368,15 @@ class SignItemWidget extends StatelessWidget {
|
|||
final rawSP =
|
||||
FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null;
|
||||
if (rawSP is String && rawSP.isNotEmpty) {
|
||||
signPaths = rawSP
|
||||
signPaths =
|
||||
rawSP
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty)
|
||||
.toList();
|
||||
} else if (rawSP is List) {
|
||||
signPaths = rawSP
|
||||
signPaths =
|
||||
rawSP
|
||||
.cast<String>()
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty)
|
||||
|
|
@ -1353,13 +1406,12 @@ class SignItemWidget extends StatelessWidget {
|
|||
FormUtils.hasValue(item, 'IMG_PATH') ? item['IMG_PATH'] : null;
|
||||
if (rawIP is String && rawIP.isNotEmpty) {
|
||||
aggregatedImgPaths.addAll(
|
||||
rawIP.split(',')
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty),
|
||||
rawIP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty),
|
||||
);
|
||||
} else if (rawIP is List) {
|
||||
aggregatedImgPaths.addAll(
|
||||
rawIP.cast<String>()
|
||||
rawIP
|
||||
.cast<String>()
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty),
|
||||
);
|
||||
|
|
@ -1374,10 +1426,12 @@ class SignItemWidget extends StatelessWidget {
|
|||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: displayImgPaths.map((p) {
|
||||
children:
|
||||
displayImgPaths.map((p) {
|
||||
final fullUrl = '$baseImgPath$p';
|
||||
return GestureDetector(
|
||||
onTap: () => presentOpaque(
|
||||
onTap:
|
||||
() => presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
),
|
||||
|
|
@ -1390,11 +1444,15 @@ class SignItemWidget extends StatelessWidget {
|
|||
width: smallThumbSize,
|
||||
height: smallThumbSize,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => Container(
|
||||
errorBuilder:
|
||||
(_, __, ___) => Container(
|
||||
width: smallThumbSize,
|
||||
height: smallThumbSize,
|
||||
color: Colors.grey.shade200,
|
||||
child: const Icon(Icons.broken_image, size: 24),
|
||||
child: const Icon(
|
||||
Icons.broken_image,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -1415,9 +1473,8 @@ class SignItemWidget extends StatelessWidget {
|
|||
}
|
||||
|
||||
// 聚合后的最后一个签名时间(如果没有则为空串)
|
||||
final lastTime = aggregatedSignTimes.isNotEmpty
|
||||
? aggregatedSignTimes.last.trim()
|
||||
: '';
|
||||
final lastTime =
|
||||
aggregatedSignTimes.isNotEmpty ? aggregatedSignTimes.last.trim() : '';
|
||||
|
||||
// 每张图片的尺寸与间距(保持你原来的数值)
|
||||
const double thumbSize = 60.0;
|
||||
|
|
@ -1433,8 +1490,9 @@ class SignItemWidget extends StatelessWidget {
|
|||
child: LayoutBuilder(
|
||||
builder: (ctx, constraints) {
|
||||
// 图片区域最大宽度 = 可用宽度 - 时间宽度 - 间隔
|
||||
final double maxImageAreaWidth =
|
||||
(constraints.maxWidth - timeBoxWidth - 8)
|
||||
final double maxImageAreaWidth = (constraints.maxWidth -
|
||||
timeBoxWidth -
|
||||
8)
|
||||
.clamp(0.0, constraints.maxWidth);
|
||||
|
||||
return Align(
|
||||
|
|
@ -1448,7 +1506,9 @@ class SignItemWidget extends StatelessWidget {
|
|||
// 图片区域(限制最大宽度,使用 Wrap 自动换行,不滚动)
|
||||
if (aggregatedSignPaths.isNotEmpty)
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: maxImageAreaWidth),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: maxImageAreaWidth,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 6.0),
|
||||
child: Wrap(
|
||||
|
|
@ -1456,10 +1516,12 @@ class SignItemWidget extends StatelessWidget {
|
|||
runSpacing: 6.0,
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.end,
|
||||
children: aggregatedSignPaths.map((imgPath) {
|
||||
children:
|
||||
aggregatedSignPaths.map((imgPath) {
|
||||
final fullUrl = '$baseImgPath$imgPath';
|
||||
return GestureDetector(
|
||||
onTap: () => presentOpaque(
|
||||
onTap:
|
||||
() => presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
),
|
||||
|
|
@ -1470,7 +1532,8 @@ class SignItemWidget extends StatelessWidget {
|
|||
width: thumbSize,
|
||||
height: thumbSize,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (_, __, ___) => Container(
|
||||
errorBuilder:
|
||||
(_, __, ___) => Container(
|
||||
width: thumbSize,
|
||||
height: thumbSize,
|
||||
color: Colors.grey.shade200,
|
||||
|
|
@ -1488,9 +1551,8 @@ class SignItemWidget extends StatelessWidget {
|
|||
),
|
||||
|
||||
// 图片与时间之间的小间隔(仅在有图片时展示)
|
||||
if (aggregatedSignPaths.isNotEmpty) const SizedBox(width: 8),
|
||||
|
||||
|
||||
if (aggregatedSignPaths.isNotEmpty)
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -1500,8 +1562,9 @@ class SignItemWidget extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
// 时间文本(始终固定在最右侧并底部对齐)
|
||||
list.add(const SizedBox(height: 10,));
|
||||
list.add(Row(
|
||||
list.add(const SizedBox(height: 10));
|
||||
list.add(
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const SizedBox(),
|
||||
|
|
@ -1509,18 +1572,16 @@ class SignItemWidget extends StatelessWidget {
|
|||
lastTime,
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.black87,
|
||||
style: const TextStyle(fontSize: 13, color: Colors.black87),
|
||||
),
|
||||
)
|
||||
],
|
||||
));
|
||||
|
||||
),
|
||||
);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// 签名意见回显
|
||||
class ConfirmWithSignWidget extends StatelessWidget {
|
||||
const ConfirmWithSignWidget({
|
||||
|
|
@ -1571,14 +1632,16 @@ class ConfirmWithSignWidget extends StatelessWidget {
|
|||
final safePd = pd ?? <String, dynamic>{};
|
||||
|
||||
// 如果没有该 section 则不渲染
|
||||
if (!FormUtils.hasValue(safeSigns, sectionKey)) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
// if (!FormUtils.hasValue(safeSigns, sectionKey)) {
|
||||
// return const SizedBox.shrink();
|
||||
// }
|
||||
|
||||
// 从 signs 中取第一个意见(保持与你原来逻辑一致)
|
||||
final sectionList = safeSigns[sectionKey];
|
||||
String descrText = '';
|
||||
if (sectionList is List && sectionList.isNotEmpty && sectionList[0] is Map) {
|
||||
if (sectionList is List &&
|
||||
sectionList.isNotEmpty &&
|
||||
sectionList[0] is Map) {
|
||||
final first = sectionList[0] as Map;
|
||||
final dynamic ds = first[descrField];
|
||||
if (ds != null) {
|
||||
|
|
@ -1607,7 +1670,17 @@ class ConfirmWithSignWidget extends StatelessWidget {
|
|||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: ListItemFactory.headerTitle('$headerTitle')),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$headerTitle',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 5,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(),
|
||||
// 仅当 pd 中存在 nameKey 且不为空时显示
|
||||
// if (FormUtils.hasValue(safePd, nameKey))
|
||||
|
|
@ -1622,7 +1695,10 @@ class ConfirmWithSignWidget extends StatelessWidget {
|
|||
// 描述内容(当 descrText 有意义才显示)
|
||||
if (descrText.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Text(
|
||||
descrText,
|
||||
maxLines: 100,
|
||||
|
|
@ -1633,14 +1709,18 @@ class ConfirmWithSignWidget extends StatelessWidget {
|
|||
|
||||
// 如果 imgsKey 有值并且 safePd 中有对应图片数据则显示(ItemListWidget.twoRowTitleAndImages 期望的 imageUrls)
|
||||
if (imgsKey.isNotEmpty && FormUtils.hasValue(safePd, imgsKey))
|
||||
Builder(builder: (ctx) {
|
||||
Builder(
|
||||
builder: (ctx) {
|
||||
final dynamic rawImgs = safePd[imgsKey];
|
||||
// 传给 ItemListWidget 的 imageUrls 需要类型兼容,这里仅在 rawImgs 非空时才调用
|
||||
if (rawImgs != null) {
|
||||
return ItemListWidget.twoRowTitleAndImages(
|
||||
onTapCallBack: (val) {
|
||||
// 使用传入的 context 打开预览
|
||||
presentOpaque(SingleImageViewer(imageUrl: val), context);
|
||||
presentOpaque(
|
||||
SingleImageViewer(imageUrl: val),
|
||||
context,
|
||||
);
|
||||
},
|
||||
title: '',
|
||||
imageUrls: rawImgs,
|
||||
|
|
@ -1648,10 +1728,12 @@ class ConfirmWithSignWidget extends StatelessWidget {
|
|||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
},
|
||||
),
|
||||
|
||||
// 如果 contentKey 有值并且 pd 中存在则显示(类型转换为字符串以防出错)
|
||||
if (contentKey.isNotEmpty && FormUtils.hasValue(safePd, contentKey))
|
||||
if (contentKey.isNotEmpty &&
|
||||
FormUtils.hasValue(safePd, contentKey))
|
||||
ItemListWidget.itemContainer(
|
||||
Text(
|
||||
(safePd[contentKey] ?? '').toString(),
|
||||
|
|
@ -1701,7 +1783,8 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
final List<String> imagePaths = [];
|
||||
final safeSigns = signs ?? <String, dynamic>{};
|
||||
|
||||
final rawList = FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null;
|
||||
final rawList =
|
||||
FormUtils.hasValue(safeSigns, signKey) ? safeSigns[signKey] : null;
|
||||
|
||||
if (rawList == null) return imagePaths;
|
||||
|
||||
|
|
@ -1711,14 +1794,16 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
if (raw is! Map) continue;
|
||||
final item = Map<String, dynamic>.from(raw);
|
||||
|
||||
final rawSP = FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null;
|
||||
final rawSP =
|
||||
FormUtils.hasValue(item, 'SIGN_PATH') ? item['SIGN_PATH'] : null;
|
||||
if (rawSP is String && rawSP.isNotEmpty) {
|
||||
imagePaths.addAll(
|
||||
rawSP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty),
|
||||
);
|
||||
} else if (rawSP is List) {
|
||||
imagePaths.addAll(
|
||||
rawSP.cast<dynamic>()
|
||||
rawSP
|
||||
.cast<dynamic>()
|
||||
.where((e) => e != null)
|
||||
.map((e) => e.toString().trim())
|
||||
.where((s) => s.isNotEmpty),
|
||||
|
|
@ -1732,14 +1817,18 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
);
|
||||
} else if (rawList is Map) {
|
||||
// 若误传了单条 Map,也尝试从中抽取 SIGN_PATH
|
||||
final rawSP = FormUtils.hasValue(rawList, 'SIGN_PATH') ? rawList['SIGN_PATH'] : null;
|
||||
final rawSP =
|
||||
FormUtils.hasValue(rawList, 'SIGN_PATH')
|
||||
? rawList['SIGN_PATH']
|
||||
: null;
|
||||
if (rawSP is String && rawSP.isNotEmpty) {
|
||||
imagePaths.addAll(
|
||||
rawSP.split(',').map((s) => s.trim()).where((s) => s.isNotEmpty),
|
||||
);
|
||||
} else if (rawSP is List) {
|
||||
imagePaths.addAll(
|
||||
rawSP.cast<dynamic>()
|
||||
rawSP
|
||||
.cast<dynamic>()
|
||||
.where((e) => e != null)
|
||||
.map((e) => e.toString().trim())
|
||||
.where((s) => s.isNotEmpty),
|
||||
|
|
@ -1764,8 +1853,7 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
try {
|
||||
presentOpaque(SingleImageViewer(imageUrl: fullUrl), context);
|
||||
return;
|
||||
} catch (_) {
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -1773,10 +1861,7 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
final imagePaths = _extractSignPaths();
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 5,
|
||||
horizontal: 12,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
|
@ -1784,10 +1869,7 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
// 左侧标题
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
|
||||
),
|
||||
|
||||
// const SizedBox(width: 12),
|
||||
|
|
@ -1804,7 +1886,8 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
runSpacing: gap,
|
||||
alignment: WrapAlignment.end,
|
||||
crossAxisAlignment: WrapCrossAlignment.end,
|
||||
children: imagePaths.map((p) {
|
||||
children:
|
||||
imagePaths.map((p) {
|
||||
final fullUrl = '${ApiService.baseImgPath}$p';
|
||||
return GestureDetector(
|
||||
onTap: () => _openPreview(context, fullUrl),
|
||||
|
|
@ -1815,11 +1898,15 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
width: imageSize,
|
||||
height: imageSize,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, __, ___) => Container(
|
||||
errorBuilder:
|
||||
(_, __, ___) => Container(
|
||||
width: imageSize,
|
||||
height: imageSize,
|
||||
color: Colors.grey.shade200,
|
||||
child: const Icon(Icons.broken_image, size: 24),
|
||||
child: const Icon(
|
||||
Icons.broken_image,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -1843,5 +1930,3 @@ class SignRowImageTitle extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -167,13 +167,13 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
|
|||
hintText: '请选择动火人及证书编号',
|
||||
onTap: widget.onChooseHotworkUser,
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'UNIT_NAME') &&
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME') &&
|
||||
!widget.isEditable) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['UNIT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') &&
|
||||
|
|
@ -252,6 +252,7 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -303,6 +304,7 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -187,10 +187,7 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -201,6 +198,10 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -242,7 +243,7 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -370,6 +371,7 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ class _HotworkDbbzDetailState extends State<HotworkDbbzDetail> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: MyAppbar(title: '班长验票'),
|
||||
appBar: MyAppbar(title: '动火前,岗位当班班长验票情况'),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(12),
|
||||
|
|
@ -290,7 +290,7 @@ class _HotworkDbbzDetailState extends State<HotworkDbbzDetail> {
|
|||
Column(
|
||||
children: [
|
||||
ListItemFactory.createBuildMultilineInput(
|
||||
'动火前在岗班长意见',
|
||||
'动火前,岗位当班班长意见',
|
||||
'请输入意见',
|
||||
_contentController,
|
||||
isRequired: true,
|
||||
|
|
@ -301,7 +301,7 @@ class _HotworkDbbzDetailState extends State<HotworkDbbzDetail> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
ListItemFactory.headerTitle('动火前在岗班长'),
|
||||
ListItemFactory.headerTitle('动火前,岗位当班班长'),
|
||||
CustomButton(
|
||||
text: '新增手写签字',
|
||||
height: 36,
|
||||
|
|
|
|||
|
|
@ -379,8 +379,10 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -579,7 +581,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
pd['TASK_ID'] = taskId;
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['HOTWORK_ID'] = widget.HOTWORK_ID;
|
||||
|
|
@ -598,7 +600,7 @@ class _HotworkApplyDetailState extends State<HotworkApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
ToastUtil.showError(context, result['msg'] ?? '提交失败');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/dh_work_detai/hotwork_apply_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/aqcs_work_detail/hotwork_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dh_work/aqgl_work_detail/hotwork_aqgl_detail.dart';
|
||||
|
|
@ -137,9 +138,12 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
}
|
||||
|
||||
/// 申请
|
||||
void _handleApply() async{
|
||||
void _handleApply() async {
|
||||
// 处理申请按钮点击逻辑
|
||||
await pushPage(HotworkApplyDetail(HOTWORK_ID: '', flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HotworkApplyDetail(HOTWORK_ID: '', flow: widget.flow),
|
||||
context,
|
||||
);
|
||||
_fetchData();
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
|
@ -286,78 +290,10 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
await _fetchData();
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListItem(Map<String, dynamic> item) {
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
|
|
@ -368,107 +304,196 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
padding: const EdgeInsets.all(12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"编号: ${item['CHECK_NO'] ?? ''}",
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
"作业级别: ${item['WORK_LEVEL'] ?? ''}",
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("申请人: ${item['APPLY_USER_NAME'] ?? ''}"),
|
||||
Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"),
|
||||
Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}"),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("动火点负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (item['AUDIT_USER_NAME'] != null)
|
||||
Text("安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}"),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text("动火前在岗班长: ${item['MONITOR_USER_NAME'] ?? ''}")],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}"),
|
||||
child: Text(
|
||||
"编号: ${item['CHECK_NO'] ?? ''}",
|
||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"作业级别: ${item['WORK_LEVEL'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"申请人: ${item['APPLY_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"分析人: ${item['ANALYZE_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: item['APPROVE_USER_NAME'] != null
|
||||
? Text(
|
||||
"审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (item['AUDIT_USER_NAME'] != null)
|
||||
Text(
|
||||
"安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'APPROVE_USER_NAME'))
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"动火审批负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
textAlign: TextAlign.left,
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"动火前在岗班长: ${item['MONITOR_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.left,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",
|
||||
textAlign: TextAlign.right,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审核状态: ${_getStatusText(item)}",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
maxLines: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
CustomButton(
|
||||
text: '查看流程图',
|
||||
height: 35,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
margin: const EdgeInsets.only(left: 0),
|
||||
backgroundColor: Colors.blue,
|
||||
onPressed: () => _openFlowDrawer(item['HOTWORK_ID']),
|
||||
),
|
||||
SizedBox(width: 1),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -581,48 +606,7 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -380,6 +380,7 @@ class _HotworkYsgdDetailState extends State<HotworkYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -121,12 +121,12 @@ class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['APPLY_USER_NAME'] ?? '',
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') &&
|
||||
|
|
@ -247,6 +247,7 @@ class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -299,6 +300,7 @@ class _CutroadDetailFormWidgetState extends State<CutroadDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
/// 其他安全措施
|
||||
final TextEditingController _otherController = TextEditingController();
|
||||
|
||||
|
||||
|
||||
/// 安全防护措施列表
|
||||
List<String> imagePaths = [];
|
||||
List<String> signTimes = []; // 签字时间列表
|
||||
|
|
@ -48,8 +46,8 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
void initState() {
|
||||
super.initState();
|
||||
_getData();
|
||||
|
||||
}
|
||||
|
||||
late Map<String, dynamic> pd = {};
|
||||
late Map<String, dynamic> signs = {};
|
||||
late List<Map<String, dynamic>> measuresList = [];
|
||||
|
|
@ -60,34 +58,51 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
|
||||
try {
|
||||
// 并行发起三个请求,并在出错时返回安全的默认值(避免 Future.wait 因一个失败而中断)
|
||||
final futurePd = ApiService.getHomeworkFindById('cutroad', widget.CUTROAD_ID)
|
||||
.catchError((e) {
|
||||
final futurePd = ApiService.getHomeworkFindById(
|
||||
'cutroad',
|
||||
widget.CUTROAD_ID,
|
||||
).catchError((e) {
|
||||
// 可加入日志记录 e
|
||||
return <String, dynamic>{}; // 回退为空 map
|
||||
});
|
||||
|
||||
final futureSigns = ApiService.listSignFinished('cutroad', widget.CUTROAD_ID)
|
||||
.catchError((e) {
|
||||
final futureSigns = ApiService.listSignFinished(
|
||||
'cutroad',
|
||||
widget.CUTROAD_ID,
|
||||
).catchError((e) {
|
||||
return <String, dynamic>{'signs': <String, dynamic>{}};
|
||||
});
|
||||
|
||||
final futureMeasures = ApiService.listSignSureAllMeasures('cutroad', widget.CUTROAD_ID)
|
||||
.catchError((e) {
|
||||
return <String, dynamic>{'measuresForSignList': <Map<String, dynamic>>[]};
|
||||
final futureMeasures = ApiService.listSignSureAllMeasures(
|
||||
'cutroad',
|
||||
widget.CUTROAD_ID,
|
||||
).catchError((e) {
|
||||
return <String, dynamic>{
|
||||
'measuresForSignList': <Map<String, dynamic>>[],
|
||||
};
|
||||
});
|
||||
|
||||
final results = await Future.wait([futurePd, futureSigns, futureMeasures]);
|
||||
final results = await Future.wait([
|
||||
futurePd,
|
||||
futureSigns,
|
||||
futureMeasures,
|
||||
]);
|
||||
|
||||
final pdResult = results[0] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
final signsResult = results[1] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
final measuresResult = results[2] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
final pdResult =
|
||||
results[0] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
final signsResult =
|
||||
results[1] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
final measuresResult =
|
||||
results[2] as Map<String, dynamic>? ?? <String, dynamic>{};
|
||||
|
||||
// 从各自的结果里提取需要的字段,使用默认值以防字段缺失或类型不对
|
||||
final newPd = (pdResult['pd'] is Map<String, dynamic>)
|
||||
final newPd =
|
||||
(pdResult['pd'] is Map<String, dynamic>)
|
||||
? Map<String, dynamic>.from(pdResult['pd'])
|
||||
: <String, dynamic>{};
|
||||
|
||||
final newSigns = (signsResult['signs'] is Map<String, dynamic>)
|
||||
final newSigns =
|
||||
(signsResult['signs'] is Map<String, dynamic>)
|
||||
? Map<String, dynamic>.from(signsResult['signs'])
|
||||
: <String, dynamic>{};
|
||||
|
||||
|
|
@ -114,6 +129,7 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// 弹出单位选择
|
||||
void chooseUnitHandle(MeasureItem item) {
|
||||
showModalBottomSheet(
|
||||
|
|
@ -122,8 +138,7 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
barrierColor: Colors.black54,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder:
|
||||
(_) =>
|
||||
DepartmentPicker(
|
||||
(_) => DepartmentPicker(
|
||||
onSelected: (id, name) async {
|
||||
setState(() {
|
||||
item.DEPARTMENT_ID = id;
|
||||
|
|
@ -145,8 +160,6 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 签字
|
||||
Future<void> _sign() async {
|
||||
await NativeOrientation.setLandscape();
|
||||
|
|
@ -155,7 +168,7 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
|
|||
MaterialPageRoute(builder: (context) => MineSignPage()),
|
||||
);
|
||||
await NativeOrientation.setPortrait();
|
||||
if (path != null) {
|
||||
if (path != null) {
|
||||
final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
|
||||
setState(() {
|
||||
imagePaths.add(path);
|
||||
|
|
@ -221,6 +234,7 @@ if (path != null) {
|
|||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
bool _validateAndProceed(BuildContext context) {
|
||||
for (var i = 0; i < measuresList.length; i++) {
|
||||
final m = measuresList[i];
|
||||
|
|
@ -234,10 +248,9 @@ if (path != null) {
|
|||
// 只有 STATUS == '1' 时才检查后续 ANSWER
|
||||
if (m['STATUS'] == '1') {
|
||||
for (var j = 1; j <= 4; j++) {
|
||||
if (FormUtils.hasValue(m, 'QUESTION${j}')
|
||||
) {
|
||||
if (!FormUtils.hasValue(m, 'ANSWER${j}')
|
||||
|| (m['ANSWER${j}'] as String?)!.length == 0) {
|
||||
if (FormUtils.hasValue(m, 'QUESTION${j}')) {
|
||||
if (!FormUtils.hasValue(m, 'ANSWER${j}') ||
|
||||
(m['ANSWER${j}'] as String?)!.length == 0) {
|
||||
ToastUtil.showNormal(context, '第${i + 1}项未填写第${j}项');
|
||||
return false;
|
||||
}
|
||||
|
|
@ -247,12 +260,10 @@ if (path != null) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -263,13 +274,17 @@ if (path != null) {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
title: '作废原因',
|
||||
hintText: '请输入作废原因',
|
||||
cancelText: '取消',
|
||||
confirmText: '确定'
|
||||
confirmText: '确定',
|
||||
);
|
||||
if (reasonText.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请填写作废原因');
|
||||
|
|
@ -304,17 +319,13 @@ if (path != null) {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(
|
||||
context,
|
||||
status == '1' ? '提交成功' : '已暂存',
|
||||
);
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
LoadingDialogHelper.hide();
|
||||
ToastUtil.showNormal(context, '操作失败:$e');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,20 +344,29 @@ if (path != null) {
|
|||
final List<ImageData> imgList = [];
|
||||
if ((measures['IMG_PATH'] as String?)?.isNotEmpty ?? false) {
|
||||
for (var path in (measures['IMG_PATH'] as String).split(',')) {
|
||||
imgList.add(ImageData(localPath:path, serverPath: path));
|
||||
imgList.add(ImageData(localPath: path, serverPath: path));
|
||||
}
|
||||
}
|
||||
//measures['STATUS']
|
||||
final result = await pushPage(DangerousOptionsPage(index: index,status: int.parse(FormUtils.hasValue(measures, 'STATUS') ? measures['STATUS'] : '1'),
|
||||
final result = await pushPage(
|
||||
DangerousOptionsPage(
|
||||
index: index,
|
||||
status: int.parse(
|
||||
FormUtils.hasValue(measures, 'STATUS') ? measures['STATUS'] : '1',
|
||||
),
|
||||
measures: measures['PROTECTIVE_MEASURES'] ?? '',
|
||||
imgList: imgList,
|
||||
signImgList: signImgList), context);
|
||||
signImgList: signImgList,
|
||||
),
|
||||
context,
|
||||
);
|
||||
if (result != null) {
|
||||
setState(() {
|
||||
// 更新返回的图片列表(local + remote)
|
||||
final returned = result['imgList'] as List<dynamic>;
|
||||
// 先映射成 ImageData 列表
|
||||
final imgDataList = returned.map((m) {
|
||||
final imgDataList =
|
||||
returned.map((m) {
|
||||
return ImageData(
|
||||
localPath: m['local'] as String,
|
||||
serverPath: m['remote'] as String,
|
||||
|
|
@ -364,14 +384,15 @@ if (path != null) {
|
|||
measures['IMG_PATH'] = serverPathString;
|
||||
|
||||
// 更新签字列表
|
||||
measures['SIGN_ITEM'] = List<Map<String,dynamic>>.from(result['signImgList'] as List);
|
||||
measures['SIGN_ITEM'] = List<Map<String, dynamic>>.from(
|
||||
result['signImgList'] as List,
|
||||
);
|
||||
// 更新状态、序号等
|
||||
measures['STATUS'] = result['status'].toString();
|
||||
index = result['index'] as int;
|
||||
//FocusHelper.clearFocus(context);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// 安全防护措施
|
||||
|
|
@ -392,8 +413,7 @@ if (path != null) {
|
|||
Container(
|
||||
color: Colors.white,
|
||||
child: MeasuresListWidget(
|
||||
measuresList:
|
||||
measuresList, // List<Map<String, dynamic>>
|
||||
measuresList: measuresList, // List<Map<String, dynamic>>
|
||||
baseImgPath: ApiService.baseImgPath,
|
||||
isAllowEdit: true,
|
||||
onSign: (item) {
|
||||
|
|
@ -403,11 +423,13 @@ if (path != null) {
|
|||
),
|
||||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(label: '其他安全措施:',
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
controller
|
||||
:_otherController),
|
||||
controller: _otherController,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
|
||||
Row(
|
||||
|
|
@ -508,8 +530,7 @@ class MeasureItem {
|
|||
List<Map<String, dynamic>>? userList,
|
||||
this.userIndex = -1,
|
||||
List<Map<String, dynamic>>? selectMeasures,
|
||||
})
|
||||
: userList = userList ?? [],
|
||||
}) : userList = userList ?? [],
|
||||
selectMeasures = selectMeasures ?? [];
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/dl_work_detai/cutroad_apply_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/aqcs_work_detail/cutroad_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dl_work/aqjd_work_detail/cutroad_aqjd_detail.dart';
|
||||
|
|
@ -237,72 +238,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -371,8 +307,14 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("消防、安全管理部门: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("消防、安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
|
|
@ -528,48 +470,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -178,8 +178,10 @@ class _CutroadApplyDetailState extends State<CutroadApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -356,8 +358,7 @@ class _CutroadApplyDetailState extends State<CutroadApplyDetail> {
|
|||
pd['CREATOR'] = SessionService.instance.loginUserId;
|
||||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
|
||||
// 提交参数
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
if (msg == 'add') {
|
||||
pd['STEP_ID'] = status;
|
||||
pd['TASK_ID'] = taskId;
|
||||
|
|
@ -368,8 +369,7 @@ class _CutroadApplyDetailState extends State<CutroadApplyDetail> {
|
|||
pd['APPLY_USER_ID'] = SessionService.instance.loginUserId;
|
||||
pd['APPLY_USER_NAME'] = SessionService.instance.username;
|
||||
pd['USER_ID'] = SessionService.instance.loginUserId;
|
||||
pd['SPECIAL_WORK'] =
|
||||
FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
|
||||
}
|
||||
|
||||
LoadingDialogHelper.show();
|
||||
|
|
@ -380,7 +380,7 @@ class _CutroadApplyDetailState extends State<CutroadApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -371,6 +371,7 @@ class _CutroadYsgdDetailState extends State<CutroadYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ class _CutroadZyrDetailState extends State<CutroadZyrDetail> {
|
|||
formData['WORK_CONTENT'] = _contentController.text.trim();
|
||||
formData['CONIMG_PATH'] = serverPathString;
|
||||
|
||||
formData['DESCR'] = FormUtils.hasValue(pd, 'DESCR') ? pd['DESCR'] : '无';
|
||||
formData['DESCR'] = pd['DESCR'] ?? '';
|
||||
formData['CUTROAD_ID'] = widget.CUTROAD_ID;
|
||||
formData['SIGNTIME'] = signTimes.join(',');
|
||||
formData['USER_ID'] = SessionService.instance.loginUserId;
|
||||
|
|
|
|||
|
|
@ -117,12 +117,12 @@ class _BreakgroundDetailFormWidgetState
|
|||
text: pd['CREATTIME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
const Divider(),
|
||||
|
|
@ -190,49 +190,24 @@ class _BreakgroundDetailFormWidgetState
|
|||
controller: widget.relatedController,
|
||||
text: pd['SPECIAL_WORK'] ?? '无',
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
const Divider(),
|
||||
if (FormUtils.hasValue(pd, 'WORK_CONTENT')) ...[
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业内容、范围、方式:',
|
||||
isEditable: false,
|
||||
text: pd['WORK_CONTENT'] ?? '',
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CONTENT_IMG_PATH')) ...[
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业内容、范围、方式简图:',
|
||||
isEditable: false,
|
||||
text: '',
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end, // 对齐到底部
|
||||
children: List.generate(pd['CONTENT_IMG_PATH'].length, (index) {
|
||||
final fullUrl =
|
||||
ApiService.baseImgPath + pd['CONTENT_IMG_PATH'][index];
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(right: 20), // 右侧 20px 间隔
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
presentOpaque(
|
||||
SingleImageViewer(imageUrl: fullUrl),
|
||||
context,
|
||||
);
|
||||
},
|
||||
child: Image.network(fullUrl, fit: BoxFit.fill),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONTENT_IMG_PATH') &&
|
||||
!widget.isEditable) ...[
|
||||
ConfirmWithSignWidget(
|
||||
signs: widget.signs,
|
||||
pd: pd,
|
||||
baseImgPath: ApiService.baseImgPath,
|
||||
sectionKey: 'WORK_USER',
|
||||
nameKey: 'WORK_CONTENT',
|
||||
headerTitle: '作业范围、内容、方式(包括深度、面积,并附简图):',
|
||||
imgsKey: 'CONTENT_IMG_PATH',
|
||||
contentKey: 'WORK_CONTENT',
|
||||
roleTitle: '',
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
|
||||
ItemListWidget.twoRowButtonTitleText(
|
||||
label: '风险辨识结果',
|
||||
isEditable: widget.isEditable,
|
||||
|
|
@ -270,6 +245,7 @@ class _BreakgroundDetailFormWidgetState
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -321,6 +297,7 @@ class _BreakgroundDetailFormWidgetState
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -402,18 +379,7 @@ class _BreakgroundDetailFormWidgetState
|
|||
text: pd['VIDEONAME'] ?? '',
|
||||
),
|
||||
|
||||
if (FormUtils.hasValue(widget.signs, 'WORK_USER')) ...[
|
||||
const Divider(),
|
||||
ConfirmWithSignWidget(
|
||||
signs: widget.signs,
|
||||
pd: pd,
|
||||
baseImgPath: ApiService.baseImgPath,
|
||||
sectionKey: 'WORK_USER',
|
||||
nameKey: 'WORK_USER_USER_NAME',
|
||||
headerTitle: '作业人签字',
|
||||
roleTitle: '',
|
||||
),
|
||||
],
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -187,10 +187,7 @@ class _BreakgroundSafeFuncSureState extends State<BreakgroundSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -201,6 +198,10 @@ class _BreakgroundSafeFuncSureState extends State<BreakgroundSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -242,7 +243,7 @@ class _BreakgroundSafeFuncSureState extends State<BreakgroundSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -382,6 +383,7 @@ class _BreakgroundSafeFuncSureState extends State<BreakgroundSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/aqcs_work_detail/breakground_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/aqjd_work_detail/breakground_aqjd_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dt_work/dt_work_detai/breakground_apply_detail.dart';
|
||||
|
|
@ -320,72 +321,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getWorkLevelText(dynamic level) {
|
||||
switch (level?.toString()) {
|
||||
|
|
@ -478,28 +414,25 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"有关水、电、汽、工艺、设备、消防安全等部门: ${item['SAFETY_USER_NAME'] ?? ''}",
|
||||
"有关部门负责人: ${item['SAFETY_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'APPROVE_USER_NAME'))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -642,48 +575,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -320,8 +320,10 @@ class _BreakgroundApplyDetailState extends State<BreakgroundApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -494,7 +496,7 @@ class _BreakgroundApplyDetailState extends State<BreakgroundApplyDetail> {
|
|||
pd['CREATOR'] = SessionService.instance.loginUserId;
|
||||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['TASK_ID'] = taskId;
|
||||
|
|
@ -513,7 +515,7 @@ class _BreakgroundApplyDetailState extends State<BreakgroundApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ class _BreakgroundYsgdDetailState extends State<BreakgroundYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ class _BreakgroundZyrDetailState extends State<BreakgroundZyrDetail> {
|
|||
.toList()
|
||||
.join(',');
|
||||
formData['WORK_CONTENT'] = _contentController.text;
|
||||
formData['DESCR'] = pd['DESCR'] ?? '无';
|
||||
formData['DESCR'] = pd['DESCR'] ?? '';
|
||||
final confirmed = await CustomAlertDialog.showConfirm(
|
||||
context,
|
||||
title: '提示',
|
||||
|
|
|
|||
|
|
@ -115,12 +115,13 @@ class _HoistworkDetailFormWidgetState extends State<HoistWorkDetailFormWidget> {
|
|||
isEditable: false,
|
||||
text: pd['APPLY_USER_NAME'] ?? '',
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CREATTIME') && !widget.isEditable) ...[
|
||||
|
|
@ -294,6 +295,7 @@ class _HoistworkDetailFormWidgetState extends State<HoistWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -345,6 +347,7 @@ class _HoistworkDetailFormWidgetState extends State<HoistWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -186,10 +186,7 @@ class _HoistworkSafeFuncSureState extends State<HoistworkSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -200,6 +197,10 @@ class _HoistworkSafeFuncSureState extends State<HoistworkSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -241,7 +242,7 @@ class _HoistworkSafeFuncSureState extends State<HoistworkSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -381,6 +382,7 @@ class _HoistworkSafeFuncSureState extends State<HoistworkSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -320,8 +320,10 @@ class _HoistworkApplyDetailState extends State<HoistworkApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -505,7 +507,7 @@ class _HoistworkApplyDetailState extends State<HoistworkApplyDetail> {
|
|||
pd['CREATOR'] = SessionService.instance.loginUserId;
|
||||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['STEP_ID'] = status;
|
||||
|
|
@ -526,7 +528,7 @@ class _HoistworkApplyDetailState extends State<HoistworkApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/aqcs_work_detail/hoistwork_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/aqjd_work_detail/hoistwork_aqjd_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/dz_work/dz_work_detai/hoistwork_apply_detail.dart';
|
||||
|
|
@ -24,7 +25,6 @@ import 'package:qhd_prevention/customWidget/custom_button.dart';
|
|||
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
|
||||
import 'package:qhd_prevention/http/ApiService.dart';
|
||||
|
||||
|
||||
class HoistworkListPage extends StatefulWidget {
|
||||
final String flow;
|
||||
final String workTypeTitle;
|
||||
|
|
@ -88,7 +88,6 @@ class _HoistworkListPageState extends State<HoistworkListPage> {
|
|||
stepList = [
|
||||
{'STEP_NAME': '全部', 'STEP_ID': ''},
|
||||
...response['list'] ?? [],
|
||||
|
||||
];
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
@ -139,9 +138,12 @@ class _HoistworkListPageState extends State<HoistworkListPage> {
|
|||
}
|
||||
|
||||
/// 申请
|
||||
void _handleApply() async{
|
||||
void _handleApply() async {
|
||||
// 处理申请按钮点击逻辑
|
||||
await pushPage(HoistworkApplyDetail(HOISTING_ID: '', flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkApplyDetail(HOISTING_ID: '', flow: widget.flow),
|
||||
context,
|
||||
);
|
||||
_fetchData();
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
|
@ -165,7 +167,7 @@ class _HoistworkListPageState extends State<HoistworkListPage> {
|
|||
} catch (e) {
|
||||
print('Error fetching flow data: $e');
|
||||
|
||||
ToastUtil.showNormal(context, '获取流程图失败');
|
||||
ToastUtil.showNormal(context, '获取流程图失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,132 +180,154 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
if (!allowed) return;
|
||||
switch (widget.flow) {
|
||||
case '提交申请':
|
||||
await pushPage(HoistworkApplyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkApplyDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '司索人签字':
|
||||
await pushPage(HoistworkSsrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkSsrDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '设置安全措施确认人':
|
||||
await pushPage(HoistworkSetSafeDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkSetSafeDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '安全措施确认':
|
||||
await pushPage(HoistworkSafeFuncSure(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkSafeFuncSure(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '监护人签字':
|
||||
await pushPage(HoistworkJhrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkJhrDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '安全交底人签字':
|
||||
await pushPage(HoistworkAqjdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkAqjdDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '接受交底人签字':
|
||||
await pushPage(HoistworkJsjdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkJsjdDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '作业人签字':
|
||||
await pushPage(HoistworkZyrDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkZyrDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
// case '作业负责人签字':
|
||||
// await pushPage(HoistworkZyfzDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
// break;
|
||||
case '吊装指挥人签字':
|
||||
await pushPage(HoistworkDzzhDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkDzzhDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '所在单位签字':
|
||||
await pushPage(HoistworkSzdwDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkSzdwDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '审核人签字':
|
||||
await pushPage(HoistworkShbmDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkShbmDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '审批人签字':
|
||||
await pushPage(HoistworkSpbmDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkSpbmDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
break;
|
||||
case '开始作业':
|
||||
await pushPage(HoistworkKszyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkKszyDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
||||
break;
|
||||
case '结束作业':
|
||||
await pushPage(HoistworkJszyDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkJszyDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
||||
break;
|
||||
case '验收签字':
|
||||
await pushPage(HoistworkYsgdDetail(HOISTING_ID: item['HOISTING_ID'], flow: widget.flow), context);
|
||||
await pushPage(
|
||||
HoistworkYsgdDetail(
|
||||
HOISTING_ID: item['HOISTING_ID'],
|
||||
flow: widget.flow,
|
||||
),
|
||||
context,
|
||||
);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
await _fetchData();
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getWorkLevelText(dynamic level) {
|
||||
switch (level?.toString()) {
|
||||
case '1':
|
||||
|
|
@ -346,52 +370,103 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("申请人: ${item['APPLY_USER_NAME'] ?? ''}"),
|
||||
Text("司索人: ${item['SISUO_USER_NAME'] ?? ''}"),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"),
|
||||
|
||||
Expanded(
|
||||
child: Text(
|
||||
"安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(
|
||||
child: Text(
|
||||
"接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(
|
||||
child: Text(
|
||||
"作业指挥负责人: ${item['PROJECT_MANAGER_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (FormUtils.hasValue(item, 'AUDIT_USER_NAME'))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
Expanded(child: Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true,
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'APPROVE_USER_NAME'))
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}"),
|
||||
SizedBox()
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
|
|
@ -528,48 +603,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ class _HoistworkYsgdDetailState extends State<HoistworkYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -174,12 +174,12 @@ class _HighWorkDetailFormWidgetState extends State<HighWorkDetailFormWidget> {
|
|||
},
|
||||
text: _getWorkLevelText(pd['WORK_LEVEL']),
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_USER_NAME') &&
|
||||
|
|
@ -277,6 +277,7 @@ class _HighWorkDetailFormWidgetState extends State<HighWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -328,6 +329,7 @@ class _HighWorkDetailFormWidgetState extends State<HighWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -185,10 +185,7 @@ class _HighworkSafeFuncSureState extends State<HighworkSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -199,6 +196,10 @@ class _HighworkSafeFuncSureState extends State<HighworkSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -240,7 +241,7 @@ class _HighworkSafeFuncSureState extends State<HighworkSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -369,6 +370,7 @@ class _HighworkSafeFuncSureState extends State<HighworkSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -336,8 +336,10 @@ class _HighworkApplyDetailState extends State<HighworkApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -525,7 +527,7 @@ class _HighworkApplyDetailState extends State<HighworkApplyDetail> {
|
|||
pd['CREATOR'] = SessionService.instance.loginUserId;
|
||||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['STEP_ID'] = status;
|
||||
|
|
@ -547,7 +549,7 @@ class _HighworkApplyDetailState extends State<HighworkApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
}else{
|
||||
ToastUtil.showError(context, result['msg'] ?? '提交失败');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/gc_work_detai/highwork_apply_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/aqcs_work_detail/highwork_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/gc_work/aqjd_work_detail/highwork_aqjd_detail.dart';
|
||||
|
|
@ -233,72 +234,7 @@ class _HighworkListPageState extends State<HighworkListPage> {
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getWorkLevelText(dynamic level) {
|
||||
switch (level?.toString()) {
|
||||
|
|
@ -362,31 +298,64 @@ class _HighworkListPageState extends State<HighworkListPage> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'AUDIT_USER_NAME'))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审核部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
if (FormUtils.hasValue(item, 'APPROVE_USER_NAME'))
|
||||
Expanded(
|
||||
child: Text(
|
||||
"审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (item['AUDIT_USER_NAME'] != null)
|
||||
Text("安全管理部门负责人: ${item['AUDIT_USER_NAME'] ?? ''}"),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (item['APPROVE_USER_NAME'] != null)
|
||||
Expanded(child: Text("审批部门负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
textAlign: TextAlign.right,
|
||||
textAlign: TextAlign.left,
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
|
|
@ -525,48 +494,7 @@ class _HighworkListPageState extends State<HighworkListPage> {
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ class _HighworkYsgdDetailState extends State<HighworkYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ class _ElectricityDetailFormWidgetState extends State<ElectricityDetailFormWidge
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -329,6 +330,7 @@ class _ElectricityDetailFormWidgetState extends State<ElectricityDetailFormWidge
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -188,10 +188,7 @@ class _ElectricitySafeFuncSureState extends State<ElectricitySafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -202,6 +199,10 @@ class _ElectricitySafeFuncSureState extends State<ElectricitySafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -243,7 +244,7 @@ class _ElectricitySafeFuncSureState extends State<ElectricitySafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -371,6 +372,7 @@ class _ElectricitySafeFuncSureState extends State<ElectricitySafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/lsyd_work_detai/electricity_apply_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/aqcs_work_detail/electricity_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/lsyd_work/aqjd_work_detail/electricity_aqjd_detail.dart';
|
||||
|
|
@ -323,72 +324,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListItem(Map<String, dynamic> item) {
|
||||
return Card(
|
||||
|
|
@ -399,6 +335,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
|
|
@ -410,7 +347,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -419,54 +356,68 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("监护人: ${item['GUARDIAN_USER_NAME'] ?? ''}"),
|
||||
Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("用电人: ${item['ELECTRICITY_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("用电单位负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("用电负责人: ${item['AUDIT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("配送电单位负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Expanded(child: Text("配送电单位负责人: ${item['APPROVE_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}")],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -478,7 +429,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
CustomButton(
|
||||
|
|
@ -602,48 +553,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -308,8 +308,10 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -518,7 +520,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> {
|
|||
pd['ISANALYZE'] = _isGasAnalyze ? 1 : 0;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
pd['TASK_ID'] = taskId;
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['ELECTRICITY_ID'] = widget.ELECTRICITY_ID;
|
||||
|
|
@ -537,7 +539,7 @@ class _ElectricityApplyDetailState extends State<ElectricityApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
ToastUtil.showSuccess(context, '提交失败');
|
||||
|
|
|
|||
|
|
@ -380,6 +380,7 @@ class _ElectricityYsgdDetailState extends State<ElectricityYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -346,12 +346,12 @@ class _BlindboardDetailFormWidgetState
|
|||
isEditable: false,
|
||||
text: pd['APPLY_USER_NAME'] ?? '',
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
const Divider(),
|
||||
|
|
@ -499,6 +499,7 @@ class _BlindboardDetailFormWidgetState
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -551,6 +552,7 @@ class _BlindboardDetailFormWidgetState
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -197,10 +197,7 @@ class _BlindboardSafeFuncSureState extends State<BlindboardSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -211,6 +208,10 @@ class _BlindboardSafeFuncSureState extends State<BlindboardSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -252,7 +253,7 @@ class _BlindboardSafeFuncSureState extends State<BlindboardSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -384,6 +385,7 @@ class _BlindboardSafeFuncSureState extends State<BlindboardSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ 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/item_list_widget.dart';
|
||||
|
||||
|
||||
class BlindboardListPage extends StatefulWidget {
|
||||
final String flow;
|
||||
|
|
@ -235,72 +237,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getWorkLevelText(dynamic level) {
|
||||
switch (level?.toString()) {
|
||||
|
|
@ -503,48 +440,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -318,8 +318,10 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -506,7 +508,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
|
|||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
pd['boardList'] = jsonEncode(boardList).toString();
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['STEP_ID'] = status;
|
||||
|
|
@ -528,7 +530,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -367,6 +367,7 @@ class _BlindboardYsgdDetailState extends State<BlindboardYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -186,12 +186,12 @@ class _SpaceWorkDetailFormWidgetState extends State<SpaceWorkDetailFormWidget> {
|
|||
controller: widget.contentController,
|
||||
text: pd['WORK_CONTENT'] ?? '',
|
||||
),
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_DEPARTMENT_NAME')) ...[
|
||||
if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME')) ...[
|
||||
const Divider(),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
label: '作业单位:',
|
||||
isEditable: false,
|
||||
text: pd['CONFIRM_DEPARTMENT_NAME'] ?? '',
|
||||
text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
|
||||
),
|
||||
],
|
||||
if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') &&
|
||||
|
|
@ -297,6 +297,7 @@ class _SpaceWorkDetailFormWidgetState extends State<SpaceWorkDetailFormWidget> {
|
|||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
@ -345,9 +346,11 @@ class _SpaceWorkDetailFormWidgetState extends State<SpaceWorkDetailFormWidget> {
|
|||
const Divider(),
|
||||
ItemListWidget.selectableLineTitleTextRightButton(
|
||||
label: '预计作业结束时间:',
|
||||
|
||||
isEditable: widget.isEditable,
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
minTimeStr: pd['WORK_EXPECTED_START_TIME'] ?? '',
|
||||
allowFuture: true,
|
||||
|
|
|
|||
|
|
@ -186,10 +186,7 @@ class _SpaceworkSafeFuncSureState extends State<SpaceworkSafeFuncSure> {
|
|||
|
||||
/// 提交 1 提交 0暂存
|
||||
Future<void> _submit(String status) async {
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
|
||||
if (imagePaths.isEmpty) {
|
||||
ToastUtil.showNormal(context, '请签字');
|
||||
return;
|
||||
|
|
@ -200,6 +197,10 @@ class _SpaceworkSafeFuncSureState extends State<SpaceworkSafeFuncSure> {
|
|||
if (!_validateAndProceed(context)) {
|
||||
return;
|
||||
}
|
||||
if (_otherController.text.trim().isEmpty) {
|
||||
ToastUtil.showNormal(context, '请输入其他安全措施,没有请填“无”');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reasonText = await CustomAlertDialog.showInput(
|
||||
context,
|
||||
|
|
@ -241,7 +242,7 @@ class _SpaceworkSafeFuncSureState extends State<SpaceworkSafeFuncSure> {
|
|||
);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true); // 传 true 表示成功(可选)
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -369,6 +370,7 @@ class _SpaceworkSafeFuncSureState extends State<SpaceworkSafeFuncSure> {
|
|||
],
|
||||
),
|
||||
ItemListWidget.singleLineTitleText(
|
||||
isNumericInput: true,
|
||||
label: '其他安全措施:',
|
||||
isEditable: true,
|
||||
hintText: '请输入其他安全措施',
|
||||
|
|
|
|||
|
|
@ -329,8 +329,10 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> {
|
|||
onTapClean: () {
|
||||
ToastUtil.showNormal(context, '已清除');
|
||||
setState(() {
|
||||
pd['${type.name}_DEPARTMENT_NAME'] = '';
|
||||
pd['${type.name}_USER_NAME'] = '';
|
||||
set_pd_USER_ID(type, '');
|
||||
set_pd_USER_Name(type, '');
|
||||
set_pd_DEPARTMENT_NAME(type, '');
|
||||
set_pd_DEPARTMENT_ID(type, '');
|
||||
_personCache.remove(type);
|
||||
});
|
||||
},
|
||||
|
|
@ -503,7 +505,7 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> {
|
|||
pd['ACTION_USER'] = SessionService.instance.username;
|
||||
pd['APPLY_STATUS'] = status;
|
||||
pd['TASK_ID'] = '4';
|
||||
|
||||
pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '无';
|
||||
// 提交参数
|
||||
if (msg == 'add') {
|
||||
pd['APPLY_DEPARTMENT_ID'] = SessionService.instance.deptId;
|
||||
|
|
@ -521,7 +523,7 @@ class _SpaceworkApplyDetailState extends State<SpaceworkApplyDetail> {
|
|||
final result = await ApiService.submitHomework(url, pd);
|
||||
LoadingDialogHelper.hide();
|
||||
if (result['result'] == 'success') {
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '已暂存');
|
||||
ToastUtil.showSuccess(context, status == '1' ? '提交成功' : '操作成功');
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
ToastUtil.showError(context, result['msg'] ?? '提交失败');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/space_work_detai/spacework_apply_detail.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/aqcs_work_detail/spacework_safe_func_sure.dart';
|
||||
import 'package:qhd_prevention/pages/home/tap/tabList/special_wrok/sxkj_work/aqgl_work_detail/spacework_aqgl_detail.dart';
|
||||
|
|
@ -345,72 +346,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
LoadingDialogHelper.hide();
|
||||
}
|
||||
|
||||
Widget _buildFlowStepItem({
|
||||
required Map<String, dynamic> item,
|
||||
required bool isFirst,
|
||||
required bool isLast,
|
||||
required int status, // 1 = 完成, 0 = 进行中, -1 = 未到达
|
||||
}) {
|
||||
// 依据状态设色
|
||||
final Color dotColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.grey);
|
||||
final Color textColor =
|
||||
status == 1 ? Colors.green : (status == 0 ? Colors.blue : Colors.black);
|
||||
|
||||
return ListTile(
|
||||
visualDensity: VisualDensity(vertical: -4),
|
||||
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// 上方线段或占位
|
||||
isFirst
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
// 圆点
|
||||
CircleAvatar(radius: 6, backgroundColor: dotColor),
|
||||
// 下方线段或占位
|
||||
isLast
|
||||
? SizedBox(height: 6 + 5)
|
||||
: Expanded(child: Container(width: 1, color: Colors.grey[300])),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item['STEP_NAME'] ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: 15),
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item['SIGN_USER'] != null)
|
||||
Text(
|
||||
item['SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['FINISHED_SIGN_USER'] != null)
|
||||
Text(
|
||||
item['FINISHED_SIGN_USER'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_USER_NAME'] != null)
|
||||
Text(
|
||||
item['ACT_USER_NAME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
if (item['ACT_TIME'] != null)
|
||||
Text(
|
||||
item['ACT_TIME'],
|
||||
style: TextStyle(color: textColor, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListItem(Map<String, dynamic> item) {
|
||||
return Card(
|
||||
|
|
@ -421,6 +357,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Column(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
|
|
@ -432,7 +369,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -440,7 +377,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
Text("分析人: ${item['ANALYZE_USER_NAME'] ?? ''}"),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -452,7 +389,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -460,29 +397,32 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",softWrap: true,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
Expanded(child: Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
Expanded(child: Text("所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,)
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text("验收部门负责人: ${item['ACCEPT_USER_NAME'] ?? ''}",softWrap: true,
|
||||
textAlign: TextAlign.right,
|
||||
maxLines: null, // 不限制行数
|
||||
overflow: TextOverflow.visible,),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -494,7 +434,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Row(
|
||||
children: [
|
||||
CustomButton(
|
||||
|
|
@ -618,48 +558,7 @@ ToastUtil.showNormal(context, '获取流程图失败');
|
|||
child:
|
||||
flowList.isEmpty
|
||||
? Center(child: Text('暂无流程图数据'))
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
itemCount: flowList.length + 1, // +1 用来放标题
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Text(
|
||||
'查看流程图',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final idx = i - 1;
|
||||
final item = flowList[idx];
|
||||
final bool isFirst = idx == 0;
|
||||
final bool isLast = idx == flowList.length - 1;
|
||||
|
||||
// 根据 lastDoneIndex 自动计算“进行中”
|
||||
final int status;
|
||||
if (idx <= lastDoneIndex) {
|
||||
status = 1; // 已完成
|
||||
} else if (idx == lastDoneIndex + 1) {
|
||||
status = 0; // 进行中
|
||||
} else {
|
||||
status = -1; // 未到达
|
||||
}
|
||||
|
||||
return _buildFlowStepItem(
|
||||
item: item,
|
||||
isFirst: isFirst,
|
||||
isLast: isLast,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
),
|
||||
: ItemListWidget.buildFlowStepItem(flowList: flowList),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -384,6 +384,7 @@ class _SpaceworkYsgdDetailState extends State<SpaceworkYsgdDetail> {
|
|||
),
|
||||
onTap: () async {
|
||||
DateTime? picked = await BottomDateTimePicker.showDate(
|
||||
allowPast:false,
|
||||
mode: BottomPickerMode.dateTimeWithSeconds,
|
||||
context,
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue