Compare commits

..

No commits in common. "76d0fdbd16fa7e939792b6ec0846a1bbcec54bd5" and "70ac141fb7a279e5c42ef15fae292414e5d2b63c" have entirely different histories.

62 changed files with 671 additions and 718 deletions

View File

@ -1,4 +1,3 @@
// <your_file_name>.dart
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
@ -67,13 +66,12 @@ bool _isNetworkPath(String? p) {
} }
/// File /// File
/// ****访existsSync build()
List<File> _localFilesFromPaths(List<String>? paths) { List<File> _localFilesFromPaths(List<String>? paths) {
if (paths == null) return <File>[]; if (paths == null) return <File>[];
return paths return paths
.map((e) => (e ?? '').toString().trim()) .map((e) => (e ?? '').toString().trim())
.where((s) => s.isNotEmpty && !_isNetworkPath(s)) .where((s) => s.isNotEmpty && !_isNetworkPath(s))
.where((s) => File(s).existsSync()) .where((s) => File(s).existsSync()) //
.map((s) => File(s)) .map((s) => File(s))
.toList(); .toList();
} }
@ -84,6 +82,7 @@ List<String> _normalizePaths(List<String>? src) {
return src.map((e) => (e ?? '').toString().trim()).where((s) => s.isNotEmpty).toList(); return src.map((e) => (e ?? '').toString().trim()).where((s) => s.isNotEmpty).toList();
} }
/// ---------- MediaPickerRow ----------
/// ---------- MediaPickerRow ---------- /// ---------- MediaPickerRow ----------
class MediaPickerRow extends StatefulWidget { class MediaPickerRow extends StatefulWidget {
final int maxCount; final int maxCount;
@ -121,29 +120,12 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
late List<String> _mediaPaths; late List<String> _mediaPaths;
bool _isProcessing = false; bool _isProcessing = false;
/// build IO
final Map<String, bool> _localExistsCache = {};
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// //
_mediaPaths = _normalizePaths(widget.initialMediaPaths).take(widget.maxCount).toList(); _mediaPaths = _normalizePaths(widget.initialMediaPaths).take(widget.maxCount).toList();
// init
for (final pth in _mediaPaths) {
final t = pth.trim();
if (!_isNetworkPath(t)) {
try {
_localExistsCache[t] = File(t).existsSync();
} catch (_) {
_localExistsCache[t] = false;
}
} else {
_localExistsCache[pth] = false;
}
}
// File // File
final initialLocalFiles = _localFilesFromPaths(_mediaPaths); final initialLocalFiles = _localFilesFromPaths(_mediaPaths);
if (initialLocalFiles.isNotEmpty) { if (initialLocalFiles.isNotEmpty) {
@ -163,23 +145,6 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
if (!listEquals(oldList, newList)) { if (!listEquals(oldList, newList)) {
_mediaPaths = newList.take(widget.maxCount).toList(); _mediaPaths = newList.take(widget.maxCount).toList();
//
for (final pth in _mediaPaths) {
final t = pth.trim();
if (!_localExistsCache.containsKey(t)) {
if (!_isNetworkPath(t)) {
try {
_localExistsCache[t] = File(t).existsSync();
} catch (_) {
_localExistsCache[t] = false;
}
} else {
_localExistsCache[t] = false;
}
}
}
if (mounted) setState(() {}); if (mounted) setState(() {});
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
widget.onChanged(_localFilesFromPaths(_mediaPaths)); widget.onChanged(_localFilesFromPaths(_mediaPaths));
@ -225,18 +190,6 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
if (_mediaPaths.length < widget.maxCount) { if (_mediaPaths.length < widget.maxCount) {
setState(() => _mediaPaths.add(finalPath)); setState(() => _mediaPaths.add(finalPath));
//
if (!_isNetworkPath(finalPath)) {
try {
_localExistsCache[finalPath] = File(finalPath).existsSync();
} catch (_) {
_localExistsCache[finalPath] = false;
}
} else {
_localExistsCache[finalPath] = false;
}
// //
widget.onChanged(_localFilesFromPaths(_mediaPaths)); widget.onChanged(_localFilesFromPaths(_mediaPaths));
widget.onMediaAdded?.call(finalPath); widget.onMediaAdded?.call(finalPath);
@ -295,14 +248,6 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
if (picked != null) { if (picked != null) {
final path = picked.path; final path = picked.path;
setState(() => _mediaPaths.add(path)); setState(() => _mediaPaths.add(path));
//
try {
_localExistsCache[path] = File(path).existsSync();
} catch (_) {
_localExistsCache[path] = false;
}
widget.onChanged(_localFilesFromPaths(_mediaPaths)); widget.onChanged(_localFilesFromPaths(_mediaPaths));
widget.onMediaAdded?.call(path); widget.onMediaAdded?.call(path);
} }
@ -449,11 +394,6 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
if (picked != null) { if (picked != null) {
final path = picked.path; final path = picked.path;
setState(() => _mediaPaths.add(path)); setState(() => _mediaPaths.add(path));
try {
_localExistsCache[path] = File(path).existsSync();
} catch (_) {
_localExistsCache[path] = false;
}
widget.onChanged(_localFilesFromPaths(_mediaPaths)); widget.onChanged(_localFilesFromPaths(_mediaPaths));
widget.onMediaAdded?.call(path); widget.onMediaAdded?.call(path);
} }
@ -481,12 +421,10 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
if (!ok) return; if (!ok) return;
final removed = _mediaPaths[index]; final removed = _mediaPaths[index];
final wasNetwork = _isNetworkPath(removed);
setState(() => _mediaPaths.removeAt(index)); setState(() => _mediaPaths.removeAt(index));
//
_localExistsCache.remove(removed);
// onMediaRemoved // onMediaRemoved
widget.onMediaRemoved?.call(removed); widget.onMediaRemoved?.call(removed);
@ -500,10 +438,6 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
final showAddButton = widget.isEdit && _mediaPaths.length < widget.maxCount; final showAddButton = widget.isEdit && _mediaPaths.length < widget.maxCount;
final itemCount = _mediaPaths.length + (showAddButton ? 1 : 0); final itemCount = _mediaPaths.length + (showAddButton ? 1 : 0);
//
final tileLogicalW = (MediaQuery.of(context).size.width / 4).round();
final cacheWidth = (tileLogicalW * MediaQuery.of(context).devicePixelRatio).round();
return Stack( return Stack(
children: [ children: [
GridView.builder( GridView.builder(
@ -538,27 +472,24 @@ class _MediaPickerGridState extends State<MediaPickerRow> {
? Image.network( ? Image.network(
raw, raw,
fit: BoxFit.cover, fit: BoxFit.cover,
// request a scaled decode to reduce memory
width: tileLogicalW.toDouble(),
height: tileLogicalW.toDouble(),
// errorBuilder for network errors
errorBuilder: (_, __, ___) => Container( errorBuilder: (_, __, ___) => Container(
color: Colors.grey.shade200, color: Colors.grey.shade200,
child: const Center(child: Icon(Icons.broken_image)), child: const Center(child: Icon(Icons.broken_image)),
), ),
) )
: Image.file( : (File(raw).existsSync()
? Image.file(
File(raw), File(raw),
fit: BoxFit.cover, fit: BoxFit.cover,
width: tileLogicalW.toDouble(),
height: tileLogicalW.toDouble(),
// Use cacheWidth to ask the engine to decode a smaller bitmap (reduces memory).
cacheWidth: cacheWidth,
errorBuilder: (_, __, ___) => Container( errorBuilder: (_, __, ___) => Container(
color: Colors.grey.shade200, color: Colors.grey.shade200,
child: const Center(child: Icon(Icons.broken_image)), child: const Center(child: Icon(Icons.broken_image)),
), ),
)) )
: Container(
color: Colors.grey.shade200,
child: const Center(child: Icon(Icons.broken_image)),
)))
: Container( : Container(
color: Colors.black12, color: Colors.black12,
child: const Center( child: const Center(

View File

@ -352,13 +352,6 @@ setState(() {
} }
Widget _mainWidget() { Widget _mainWidget() {
bool isShowCheck = false;
if (FormUtils.hasValue(inspectedForm, 'hiddenList')) {
List list = inspectedForm['hiddenList'];
if (list.isEmpty) {
isShowCheck = true;
}
}
return ListView( return ListView(
children: [ children: [
Column( Column(
@ -387,9 +380,8 @@ setState(() {
: false, : false,
yesLabel: '同意', yesLabel: '同意',
noLabel: '申辩', noLabel: '申辩',
isEdit: isShowCheck ? true : false, isEdit: true,
isRequired: false, isRequired: false,
text: inspectedForm['INSPECTION_STATUS'] == '3' ? '同意' : '申辩',
horizontalPadding: 3, horizontalPadding: 3,
verticalPadding: 0, verticalPadding: 0,
onChanged: (val) { onChanged: (val) {

View File

@ -563,6 +563,7 @@ class HomePageState extends State<HomePage> {
break; break;
} }
_onRefresh();
}, },
); );
}).toList(), }).toList(),

View File

@ -16,7 +16,6 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
late List<dynamic> _list = []; late List<dynamic> _list = [];
late String _classId = ''; late String _classId = '';
late String _post_id = ''; late String _post_id = '';
late Map _classInfo = {};
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -33,7 +32,6 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
final result = await ApiService.getClassList(_classId, _post_id); final result = await ApiService.getClassList(_classId, _post_id);
if (result['result'] == 'success') { if (result['result'] == 'success') {
final List<dynamic> newList = result['varList'] ?? []; final List<dynamic> newList = result['varList'] ?? [];
_classInfo = result['classInfo'] ?? {};
setState(() { setState(() {
_list.addAll(newList); _list.addAll(newList);
}); });
@ -48,7 +46,7 @@ class _StudyClassListPageState extends State<StudyClassListPage> {
final result = await ApiService.getVideoPermissions(); final result = await ApiService.getVideoPermissions();
if (result['result'] == 'success') { if (result['result'] == 'success') {
SessionService.instance.setStudyToken(result['token'] ?? ''); SessionService.instance.setStudyToken(result['token'] ?? '');
pushPage(StudyDetailPage(_classInfo, item, widget.studyData['STUDENT_ID'],widget.studyData), context); pushPage(StudyDetailPage(item, widget.studyData['STUDENT_ID'],widget.studyData), context);
} }
} }
@override @override

View File

@ -24,17 +24,10 @@ enum TakeExamType { video_study, strengththen, list }
class StudyDetailPage extends StatefulWidget { class StudyDetailPage extends StatefulWidget {
final Map studyDetailDetail; final Map studyDetailDetail;
final Map classInfo;
final String studentId; final String studentId;
final Map studyData; final Map studyData;
const StudyDetailPage( const StudyDetailPage(this.studyDetailDetail, this.studentId, this.studyData,{super.key});
this.classInfo,
this.studyDetailDetail,
this.studentId,
this.studyData, {
super.key,
});
@override @override
State<StudyDetailPage> createState() => _StudyDetailPageState(); State<StudyDetailPage> createState() => _StudyDetailPageState();
@ -61,7 +54,6 @@ class _StudyDetailPageState extends State<StudyDetailPage>
int _currentNodeIndex = 0; int _currentNodeIndex = 0;
bool _hasNodes = false; bool _hasNodes = false;
Duration _lastReported = Duration.zero; Duration _lastReported = Duration.zero;
bool _isFace = false;
// //
bool _endReported = false; // bool _endReported = false; //
@ -77,7 +69,6 @@ class _StudyDetailPageState extends State<StudyDetailPage>
WakelockPlus.enable(); WakelockPlus.enable();
_classId = widget.studyDetailDetail['CLASS_ID'] ?? ''; _classId = widget.studyDetailDetail['CLASS_ID'] ?? '';
_classCurriculumId = widget.studyDetailDetail['CLASSCURRICULUM_ID'] ?? ''; _classCurriculumId = widget.studyDetailDetail['CLASSCURRICULUM_ID'] ?? '';
_isFace = widget.classInfo['ISFACE'] == '1' ? true : false;
_tabController = TabController(length: 2, vsync: this); _tabController = TabController(length: 2, vsync: this);
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_showFaceIntro(); _showFaceIntro();
@ -108,19 +99,16 @@ class _StudyDetailPageState extends State<StudyDetailPage>
} }
Future<void> _showFaceIntro() async { Future<void> _showFaceIntro() async {
if (_isFace) { final ok = await CustomAlertDialog.showConfirm(
final ok = await CustomAlertDialog.showConfirm( context,
context, title: '温馨提示',
title: '温馨提示', content: '重要提醒:尊敬的用户,根据规定我们会在您学习过程中多次进行人脸识别认证,为了保护您的隐私请您在摄像设备视野内确保衣冠整齐。',
content: cancelText: '取消',
'重要提醒:尊敬的用户,根据规定我们会在您学习过程中多次进行人脸识别认证,为了保护您的隐私请您在摄像设备视野内确保衣冠整齐。', confirmText: '同意并继续',
cancelText: '取消', );
confirmText: '同意并继续', if (!ok) {
); Navigator.of(context).pop();
if (!ok) { return;
Navigator.of(context).pop();
return;
}
} }
} }
@ -191,6 +179,8 @@ class _StudyDetailPageState extends State<StudyDetailPage>
return '$s%'; return '$s%';
} }
Future<void> _onVideoTap( Future<void> _onVideoTap(
Map<String, dynamic> data, Map<String, dynamic> data,
bool hasNodes, bool hasNodes,
@ -201,15 +191,10 @@ class _StudyDetailPageState extends State<StudyDetailPage>
debugPrint('_onVideoTap ignored because a video is loading'); debugPrint('_onVideoTap ignored because a video is loading');
return; return;
} }
if (_isFace) {
try { //
await ApiService.fnClearUserFaceTime(); await ApiService.fnClearUserFaceTime();
} catch (e, st) { _faceTimer?.cancel();
debugPrint('fnClearUserFaceTime error: $e\n$st');
}
_faceTimer?.cancel();
_faceTimer = null;
}
// //
if (_currentVideoData != null && _lastReported > Duration.zero) { if (_currentVideoData != null && _lastReported > Duration.zero) {
@ -229,6 +214,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
); );
} }
// //
try { try {
if (_videoController != null && _videoController!.value.isPlaying) { if (_videoController != null && _videoController!.value.isPlaying) {
@ -268,6 +254,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
seconds: int.parse('${data['VIDEOTIME'] ?? '0'}'), seconds: int.parse('${data['VIDEOTIME'] ?? '0'}'),
); );
} }
} else { } else {
ToastUtil.showNormal(context, '课件文件资源已失效,请联系管理员'); ToastUtil.showNormal(context, '课件文件资源已失效,请联系管理员');
} }
@ -282,69 +269,59 @@ class _StudyDetailPageState extends State<StudyDetailPage>
// //
await _getVideoPlayInfo(data['VIDEOCOURSEWARE_ID']); await _getVideoPlayInfo(data['VIDEOCOURSEWARE_ID']);
LoadingDialogHelper.hide(); LoadingDialogHelper.hide();
if (_isFace) { _startFaceTimer();
_startFaceTimer();
}
} }
}); });
} }
Future<void> _navigateFaceIfNeeded(FutureOr<void> Function() onPass) async { Future<void> _navigateFaceIfNeeded(FutureOr<void> Function() onPass) async {
if (!_isFace) { if (_info?['ISFACE'] == '1') {
await onPass(); LoadingDialogHelper.show();
return; final resData = await ApiService.fnGetUserFace();
} LoadingDialogHelper.hide();
LoadingDialogHelper.show(); final pd_data = resData['pd'];
final resData = await ApiService.fnGetUserFace(); if (FormUtils.hasValue(pd_data, 'USERAVATARURL')) {
LoadingDialogHelper.hide(); // 退
final pd_data = resData['pd'];
if (FormUtils.hasValue(pd_data, 'USERAVATARURL')) {
// 退
await _exitTopRouteAndWait();
await _lockPortrait();
final passed = await pushPage<bool>(
FaceRecognitionPage(
studentId: widget.studentId,
VIDEOCOURSEWARE_ID: "",
CURRICULUM_ID: "",
CHAPTER_ID: "",
CLASS_ID: "",
mode: FaceMode.auto,
),
context,
);
await _restoreDefaultOrientations();
if (passed == true) {
LoadingDialogHelper.show();
await ApiService.fnSetUserFaceTime(_faceTime);
await onPass();
} else {
ToastUtil.showError(context, '人脸验证未通过,无法继续');
}
} else {
final ok = await CustomAlertDialog.showConfirm(
context,
title: '温馨提示',
content: '您当前还未进行人脸认证,请先进行认证',
cancelText: '取消',
);
if (ok) {
await _exitTopRouteAndWait(); await _exitTopRouteAndWait();
await _lockPortrait(); await _lockPortrait();
await pushPage( final passed = await pushPage<bool>(
const FaceRecognitionPage( FaceRecognitionPage(studentId: widget.studentId,
studentId: '', VIDEOCOURSEWARE_ID:"",CURRICULUM_ID:"",
VIDEOCOURSEWARE_ID: '', CHAPTER_ID: "",CLASS_ID: "",
CURRICULUM_ID: '', mode: FaceMode.auto),
CHAPTER_ID: '',
CLASS_ID: '',
mode: FaceMode.manual,
),
context, context,
); );
await _restoreDefaultOrientations(); await _restoreDefaultOrientations();
if (passed == true) {
LoadingDialogHelper.show();
await ApiService.fnSetUserFaceTime(_faceTime);
await onPass();
} else {
ToastUtil.showError(context, '人脸验证未通过,无法继续');
}
} else {
final ok = await CustomAlertDialog.showConfirm(
context,
title: '温馨提示',
content: '您当前还未进行人脸认证,请先进行认证',
cancelText: '取消',
);
if (ok) {
await _exitTopRouteAndWait();
await _lockPortrait();
await pushPage(
const FaceRecognitionPage(studentId: '',
VIDEOCOURSEWARE_ID: '',CURRICULUM_ID: '',
CHAPTER_ID: '',CLASS_ID: '',
mode: FaceMode.manual),
context,
);
await _restoreDefaultOrientations();
}
} }
} else {
await onPass();
} }
} }
@ -496,16 +473,8 @@ class _StudyDetailPageState extends State<StudyDetailPage>
_exitTopRouteIfPresent(); _exitTopRouteIfPresent();
}); });
// ApiService.fnClearUserFaceTime();
if (_isFace) { _faceTimer?.cancel();
try {
ApiService.fnClearUserFaceTime();
} catch (e, st) {
debugPrint('fnClearUserFaceTime error on end: $e\n$st');
}
_faceTimer?.cancel();
_faceTimer = null;
}
} }
} }
} }
@ -517,8 +486,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
}) async { }) async {
// snapshot VIDEOCOURSEWARE_ID // snapshot VIDEOCOURSEWARE_ID
if (snapshot['VIDEOCOURSEWARE_ID'] == null || if (snapshot['VIDEOCOURSEWARE_ID'] == null ||
snapshot['VIDEOCOURSEWARE_ID'] == '') snapshot['VIDEOCOURSEWARE_ID'] == '') return;
return;
// //
if (_endReported && !end) return; if (_endReported && !end) return;
@ -538,9 +506,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
// snapshot['IS_VIDEO']==1 // snapshot['IS_VIDEO']==1
// 100% UI 100% // 100% UI 100%
final isNonVideo = final isNonVideo = (snapshot['IS_VIDEO'] != null && snapshot['IS_VIDEO'].toString() == '1');
(snapshot['IS_VIDEO'] != null &&
snapshot['IS_VIDEO'].toString() == '1');
const int maxRetries = 2; const int maxRetries = 2;
int attempt = 0; int attempt = 0;
@ -556,8 +522,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
if (mounted) { if (mounted) {
setState(() { setState(() {
if (snapshot['IS_NODE'] == true) { if (snapshot['IS_NODE'] == true) {
final fi = final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex; final ni = snapshot['NODE_INDEX'] as int? ?? _currentNodeIndex;
if (fi >= 0 && fi < _videoList.length) { if (fi >= 0 && fi < _videoList.length) {
final nodes = _videoList[fi]['nodes'] as List<dynamic>?; final nodes = _videoList[fi]['nodes'] as List<dynamic>?;
@ -566,8 +531,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
} }
} }
} else { } else {
final fi = final fi = snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
snapshot['FIRST_INDEX'] as int? ?? _currentFirstIndex;
if (fi >= 0 && fi < _videoList.length) { if (fi >= 0 && fi < _videoList.length) {
_videoList[fi]['percent'] = str; _videoList[fi]['percent'] = str;
} }
@ -596,20 +560,15 @@ class _StudyDetailPageState extends State<StudyDetailPage>
// //
final resTraw = pd['RESOURCETIME']; final resTraw = pd['RESOURCETIME'];
final resT = final resT = (resTraw is num) ? resTraw.toDouble() : double.tryParse('$resTraw') ?? seconds.toDouble();
(resTraw is num)
? resTraw.toDouble()
: double.tryParse('$resTraw') ?? seconds.toDouble();
final videoTimeRaw = snapshot['VIDEOTIME']; final videoTimeRaw = snapshot['VIDEOTIME'];
final videoTime = final videoTime = (videoTimeRaw is String)
(videoTimeRaw is String) ? double.tryParse(videoTimeRaw) ?? 1.0
? double.tryParse(videoTimeRaw) ?? 1.0 : (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0);
: (videoTimeRaw is num ? videoTimeRaw.toDouble() : 1.0);
final comp = pd['PLAYCOUNT'] != null && pd['PLAYCOUNT'] > 0; final comp = pd['PLAYCOUNT'] != null && pd['PLAYCOUNT'] > 0;
final pctDouble = final pctDouble = comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0);
comp ? 100.0 : ((resT / (videoTime > 0 ? videoTime : 1.0)) * 100.0);
// //
double pctClamped = pctDouble.clamp(0.00, 100.00); double pctClamped = pctDouble.clamp(0.00, 100.00);
// 2 // 2
@ -664,10 +623,83 @@ class _StudyDetailPageState extends State<StudyDetailPage>
} }
} }
void _startFaceTimer() {
//
if (!_isFace) return;
///
Future<void> _startExam(Map resData) async {
Map pd = resData['pd'] ?? {};
Map paper = resData['paper'] ?? {};
setState(() {
_loading = true;
});
final arguments = {
'STAGEEXAMPAPERINPUT_ID': paper['STAGEEXAMPAPERINPUT_ID'] ?? '',
'STAGEEXAMPAPER_ID': paper['STAGEEXAMPAPER_ID'] ?? '',
'CLASS_ID': _classId,
'POST_ID': pd['POST_ID'] ?? '',
'STUDENT_ID': widget.studentId,
'NUMBEROFEXAMS': pd['NUMBEROFEXAMS'] ?? '',
};
print('--_startExam data---$arguments');
final data = await ApiService.getStartExam(arguments);
setState(() {
_loading = false;
});
if (data['result'] == 'success') {
pushPage(
TakeExamPage(
examInfo: {
'CLASS_ID': _classId,
'POST_ID': pd['POST_ID'] ?? '',
'STUDENT_ID': widget.studentId,
'STRENGTHEN_PAPER_QUESTION_ID':
paper['STAGEEXAMPAPERINPUT_ID'] ?? '',
...data,
},
examType: TakeExamType.video_study, jumpType: 2,
),
context,
);
} else {
ToastUtil.showError(context, '请求错误');
}
}
void _exitTopRouteIfPresent() {
final route = ModalRoute.of(context);
if (route == null) return;
// route
if (!route.isCurrent) {
// pop
try {
Navigator.of(context).maybePop();
} catch (_) {
//
}
}
}
/// 退退
Future<void> _exitTopRouteAndWait({int waitMs = 300}) async {
_exitTopRouteIfPresent();
await Future.delayed(Duration(milliseconds: waitMs));
}
///
Future<void> _lockPortrait() async {
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
///
Future<void> _restoreDefaultOrientations() async {
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}
void _startFaceTimer() {
_faceTimer = Timer.periodic(Duration(seconds: _faceTime), (_) async { _faceTimer = Timer.periodic(Duration(seconds: _faceTime), (_) async {
final res = await ApiService.fnGetUserFaceTime(); final res = await ApiService.fnGetUserFaceTime();
final isPlaying = _videoController?.value.isPlaying == true; final isPlaying = _videoController?.value.isPlaying == true;
@ -684,8 +716,6 @@ class _StudyDetailPageState extends State<StudyDetailPage>
} }
Future<void> _showFaceAuthOnce() async { Future<void> _showFaceAuthOnce() async {
//
if (!_isFace) return;
// cancel // cancel
_faceTimer?.cancel(); _faceTimer?.cancel();
_faceTimer = null; _faceTimer = null;
@ -695,14 +725,10 @@ class _StudyDetailPageState extends State<StudyDetailPage>
await _lockPortrait(); await _lockPortrait();
final passed = await pushPage<bool>( final passed = await pushPage<bool>(
FaceRecognitionPage( FaceRecognitionPage(studentId: widget.studentId,
studentId: widget.studentId, VIDEOCOURSEWARE_ID: "",CURRICULUM_ID: "",
VIDEOCOURSEWARE_ID: "", CHAPTER_ID: "",CLASS_ID: "",
CURRICULUM_ID: "", mode: FaceMode.auto),
CHAPTER_ID: "",
CLASS_ID: "",
mode: FaceMode.auto,
),
context, context,
); );
@ -744,9 +770,7 @@ class _StudyDetailPageState extends State<StudyDetailPage>
debugPrint('Error resuming playback after face auth: $e\n$st'); debugPrint('Error resuming playback after face auth: $e\n$st');
} }
// //
if (_isFace) { _startFaceTimer();
_startFaceTimer();
}
} else { } else {
ToastUtil.showError(context, '人脸验证未通过,无法继续'); ToastUtil.showError(context, '人脸验证未通过,无法继续');
if (_videoController != null) { if (_videoController != null) {
@ -763,82 +787,6 @@ class _StudyDetailPageState extends State<StudyDetailPage>
} }
} }
///
Future<void> _startExam(Map resData) async {
Map pd = resData['pd'] ?? {};
Map paper = resData['paper'] ?? {};
setState(() {
_loading = true;
});
final arguments = {
'STAGEEXAMPAPERINPUT_ID': paper['STAGEEXAMPAPERINPUT_ID'] ?? '',
'STAGEEXAMPAPER_ID': paper['STAGEEXAMPAPER_ID'] ?? '',
'CLASS_ID': _classId,
'POST_ID': pd['POST_ID'] ?? '',
'STUDENT_ID': widget.studentId,
'NUMBEROFEXAMS': pd['NUMBEROFEXAMS'] ?? '',
};
print('--_startExam data---$arguments');
final data = await ApiService.getStartExam(arguments);
setState(() {
_loading = false;
});
if (data['result'] == 'success') {
pushPage(
TakeExamPage(
examInfo: {
'CLASS_ID': _classId,
'POST_ID': pd['POST_ID'] ?? '',
'STUDENT_ID': widget.studentId,
'STRENGTHEN_PAPER_QUESTION_ID':
paper['STAGEEXAMPAPERINPUT_ID'] ?? '',
...data,
},
examType: TakeExamType.video_study,
jumpType: 3,
),
context,
);
} else {
ToastUtil.showError(context, '请求错误');
}
}
void _exitTopRouteIfPresent() {
final route = ModalRoute.of(context);
if (route == null) return;
// route
if (!route.isCurrent) {
// pop
try {
Navigator.of(context).maybePop();
} catch (_) {
//
}
}
}
/// 退退
Future<void> _exitTopRouteAndWait({int waitMs = 300}) async {
_exitTopRouteIfPresent();
await Future.delayed(Duration(milliseconds: waitMs));
}
///
Future<void> _lockPortrait() async {
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
///
Future<void> _restoreDefaultOrientations() async {
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}
Widget _buildVideoOrCover(double containerW, double containerH) { Widget _buildVideoOrCover(double containerW, double containerH) {
final c = _videoController; final c = _videoController;
if (c != null && c.value.isInitialized) { if (c != null && c.value.isInitialized) {
@ -950,7 +898,9 @@ class _StudyDetailPageState extends State<StudyDetailPage>
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
(item['NAME'] ?? '').toString(), (item['NAME'] ?? '').toString(),
style: const TextStyle(fontSize: 15), style: const TextStyle(
fontSize: 15,
),
), ),
], ],
), ),

View File

@ -116,6 +116,9 @@ class _TakeExamPageState extends State<TakeExamPage> {
content: '您无考试次数!', content: '您无考试次数!',
); );
if (ok) { if (ok) {
if (widget.jumpType == 2) {
Navigator.pop(context);
}
Navigator.pop(context); Navigator.pop(context);
}; };
} }
@ -232,17 +235,10 @@ class _TakeExamPageState extends State<TakeExamPage> {
content: content:
passed passed
? '您的成绩为 $score 分,恭喜您通过本次考试,请继续保持!' ? '您的成绩为 $score 分,恭喜您通过本次考试,请继续保持!'
: '您的成绩为 $score 分,很遗憾您没有通过本次考试,请再接再 厉!', : '您的成绩为 $score 分,很遗憾您没有通过本次考试,请再接再厉!',
cancelText: '', cancelText: '',
confirmText: '确定', confirmText: '确定',
); );
if (widget.jumpType == 2) {
Navigator.pop(context);
}
if (widget.jumpType == 3) {
Navigator.pop(context);
Navigator.pop(context);
}
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
} }

View File

@ -68,8 +68,8 @@ class MeasuresListWidget extends StatelessWidget {
// //
double col0Fixed = 40; // double col0Fixed = 40; //
double col2Fixed = 70; // double col2Fixed = 60; //
double col3Fixed = 60; // double col3Fixed = 80; //
// 4isAllowEdit == true40 // 4isAllowEdit == true40
final showCol3 = !isAllowEdit; final showCol3 = !isAllowEdit;
@ -112,8 +112,7 @@ class MeasuresListWidget extends StatelessWidget {
} }
return Table( return Table(
// top defaultVerticalAlignment: TableCellVerticalAlignment.middle,
defaultVerticalAlignment: TableCellVerticalAlignment.top,
columnWidths: columnWidths, columnWidths: columnWidths,
border: TableBorder( border: TableBorder(
horizontalInside: BorderSide(color: Colors.grey.shade300), horizontalInside: BorderSide(color: Colors.grey.shade300),
@ -124,8 +123,8 @@ class MeasuresListWidget extends StatelessWidget {
TableRow( TableRow(
decoration: BoxDecoration(color: Colors.grey.shade100), decoration: BoxDecoration(color: Colors.grey.shade100),
children: [ children: [
Padding( const Padding(
padding: const EdgeInsets.all(6), padding: EdgeInsets.all(2),
child: Center( child: Center(
child: Text( child: Text(
'序号', '序号',
@ -133,8 +132,8 @@ class MeasuresListWidget extends StatelessWidget {
), ),
), ),
), ),
Padding( const Padding(
padding: const EdgeInsets.all(8), padding: EdgeInsets.all(8),
child: Center( child: Center(
child: Text( child: Text(
'安全措施', '安全措施',
@ -143,14 +142,13 @@ class MeasuresListWidget extends StatelessWidget {
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(2),
child: Center( child: Center(
child: Text( child: Text(
isAllowEdit ? '操作' : '是否\n涉及', isAllowEdit ? '操作' : '是否\n涉及',
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
textAlign: TextAlign.center,
), ),
), ),
), ),
@ -170,48 +168,41 @@ class MeasuresListWidget extends StatelessWidget {
for (var item in measuresList) for (var item in measuresList)
TableRow( TableRow(
children: [ children: [
//
Padding( Padding(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(8),
child: Center( child: Center(
child: child: Text('${measuresList.indexOf(item) + 1}'),
Text('${measuresList.indexOf(item) + 1}'),
), ),
), ),
// + + // + +
Padding( Padding(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// //
Text( Text(
item['PROTECTIVE_MEASURES'] as String? ?? '', item['PROTECTIVE_MEASURES'] as String? ?? '',
softWrap: true,
), ),
// 14 + // 14 +
for (var i = 1; i <= 4; i++) for (var i = 1; i <= 4; i++)
if ((item['QUESTION$i'] as String?) if ((item['QUESTION$i'] as String?)
?.isNotEmpty ?? ?.isNotEmpty ??
false) false)
_buildQnA(item, i), _buildQnA(item, i),
// //
if (item.containsKey('IMG_PATH') && if (item.containsKey('IMG_PATH') &&
(item['IMG_PATH'] as String).isNotEmpty && (item['IMG_PATH'] as String).isNotEmpty &&
isShowSign) isShowSign)
Padding( Row(
padding: const EdgeInsets.only(top: 6), children: [
child: Row( ..._buildImageRows(
children: [ context,
..._buildImageRows( (item['IMG_PATH'] as String).split(','),
context, '',
(item['IMG_PATH'] as String).split(','), 8,
'', ),
8, ],
),
],
),
), ),
], ],
), ),
@ -219,93 +210,92 @@ class MeasuresListWidget extends StatelessWidget {
// / + // / +
Padding( Padding(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(8),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// //
isAllowEdit isAllowEdit
? TextButton( ? TextButton(
onPressed: () { onPressed: () {
onSign?.call(item); onSign?.call(item);
}, },
child: Text( child: Text(
(item['SIGN_ITEM'] ?? '') (item['SIGN_ITEM'] ?? '')
.toString() .toString()
.isNotEmpty .isNotEmpty
? '已签字' ? '已签字'
: '签字', : '签字',
style: TextStyle( style: TextStyle(
color: (item['SIGN_ITEM'] ?? '') color:
.toString() (item['SIGN_ITEM'] ?? '')
.isNotEmpty .toString()
? Colors.grey.shade600 .isNotEmpty
: Colors.blue, ? Colors.grey.shade600
), : Colors.blue,
), ),
) ),
)
: Text( : Text(
(item['STATUS'] as String?) == '-1' (item['STATUS'] as String?) == '-1'
? '不涉及' ? '不涉及'
: '涉及', : '涉及',
style: const TextStyle( style: TextStyle(
color: Colors.black, color:
), (item['STATUS'] as String?) == '-1'
), ? Colors.black
: Colors.black,
),
),
], ],
), ),
), ),
// //
if (!isAllowEdit) if (!isAllowEdit)
Padding( Column(
padding: const EdgeInsets.all(6), crossAxisAlignment: CrossAxisAlignment.center,
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.center, if (item.containsKey('SIGN_PATH') &&
children: [ (item['SIGN_PATH'] as String).isNotEmpty)
if (item.containsKey('SIGN_PATH') && ...((item['SIGN_PATH'] as String)
(item['SIGN_PATH'] as String).isNotEmpty) .split(',')
...((item['SIGN_PATH'] as String) .map((s) => s.trim())
.split(',') .where((s) => s.isNotEmpty)).map((path) {
.map((s) => s.trim()) final imageUrl = '$baseImgPath$path';
.where((s) => s.isNotEmpty)).map((path) { return Padding(
final imageUrl = '$baseImgPath$path'; padding: const EdgeInsets.only(top: 5),
return Padding( child: Center(
padding: const EdgeInsets.only(top: 5), child: GestureDetector(
child: Center( onTap: () {
child: GestureDetector( presentOpaque(
onTap: () { SingleImageViewer(
presentOpaque( imageUrl: imageUrl,
SingleImageViewer( ),
imageUrl: imageUrl, context,
), );
context, },
); child: Image.network(
}, imageUrl,
child: Image.network( width: 40,
imageUrl, height: 40,
width: 40, fit: BoxFit.fill,
height: 40, errorBuilder:
fit: BoxFit.fill, (_, __, ___) => Container(
errorBuilder: width: 40,
(_, __, ___) => height: 40,
Container( color: Colors.grey.shade200,
width: 40, child: const Icon(
height: 40, Icons.broken_image,
color: Colors.grey.shade200, size: 18,
child: const Icon( color: Colors.grey,
Icons.broken_image,
size: 18,
color: Colors.grey,
),
), ),
), ),
), ),
), ),
); ),
}).toList(), );
], }).toList(),
), ],
), ),
], ],
), ),
@ -329,46 +319,39 @@ class MeasuresListWidget extends StatelessWidget {
return Padding( return Padding(
padding: const EdgeInsets.only(top: 8), padding: const EdgeInsets.only(top: 8),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, //
children: [ children: [
Expanded( Expanded(
flex: 2, flex: 2,
child: Container( child: Text(
padding: const EdgeInsets.only(right: 8), // '$question:',
child: Text( style: const TextStyle(fontWeight: FontWeight.w800),
'$question:',
softWrap: true,
maxLines: 2,
overflow: TextOverflow.ellipsis, // visible null
style: const TextStyle(fontWeight: FontWeight.w800),
),
), ),
), ),
Expanded( Expanded(
flex: 1, flex: 1,
child: SizedBox( child: TextFormField(
child: TextFormField( initialValue: answer,
initialValue: answer, textAlign: TextAlign.center,
textAlign: TextAlign.center, //
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly], inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: InputDecoration( decoration: InputDecoration(
isDense: true, isDense: true,
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(
vertical: 8, vertical: 8,
horizontal: 4, horizontal: 4,
), ),
enabledBorder: OutlineInputBorder( //
borderSide: BorderSide(color: Colors.grey.shade300), enabledBorder: OutlineInputBorder(
), borderSide: BorderSide(color: Colors.grey.shade300),
focusedBorder: OutlineInputBorder( ),
borderSide: BorderSide(color: Colors.grey.shade300), focusedBorder: OutlineInputBorder(
), borderSide: BorderSide(color: Colors.grey.shade300),
), ),
onChanged: (val) {
item[key] = val;
},
), ),
onChanged: (val) {
item[key] = val;
},
), ),
), ),
], ],
@ -376,27 +359,25 @@ class MeasuresListWidget extends StatelessWidget {
); );
} }
// //
return Padding( return Padding(
padding: const EdgeInsets.only(top: 8, bottom: 6), padding: const EdgeInsets.only(top: 8),
child: Row( child: Column(
children: [ children: [
Expanded( Padding(
flex: 3, padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text( child: Row(
'$question:', mainAxisAlignment: MainAxisAlignment.spaceBetween,
style: const TextStyle(fontWeight: FontWeight.w800), children: [
softWrap: true, Text(
), '$question:',
), style: const TextStyle(fontWeight: FontWeight.w800),
const SizedBox(width: 12), ),
Expanded( Text(answer.isNotEmpty ? answer : '0'),
flex: 1, ],
child: Text(
answer.isNotEmpty ? answer : '0',
textAlign: TextAlign.right,
), ),
), ),
const Divider(),
], ],
), ),
); );
@ -404,11 +385,11 @@ class MeasuresListWidget extends StatelessWidget {
/// + /// +
List<Widget> _buildImageRows( List<Widget> _buildImageRows(
BuildContext context, BuildContext context,
List<String> paths, List<String> paths,
String time, String time,
double right, double right,
) { ) {
if (paths.isEmpty) return []; if (paths.isEmpty) return [];
const int imagesPerRow = 4; const int imagesPerRow = 4;
@ -439,22 +420,24 @@ class MeasuresListWidget extends StatelessWidget {
'$baseImgPath${rowPaths[i]}', '$baseImgPath${rowPaths[i]}',
width: imageSize, width: imageSize,
height: imageSize, height: imageSize,
fit: BoxFit.fill, fit: BoxFit.cover,
errorBuilder: errorBuilder:
(_, __, ___) => Container( (_, __, ___) => Container(
width: imageSize, width: imageSize,
height: imageSize, height: imageSize,
color: Colors.grey.shade200, color: Colors.grey.shade200,
child: const Icon( child: const Icon(
Icons.broken_image, Icons.broken_image,
size: 18, size: 18,
color: Colors.grey, color: Colors.grey,
), ),
), ),
), ),
), ),
if (i != rowPaths.length - 1) SizedBox(width: spacing), if (i != rowPaths.length - 1) SizedBox(width: spacing),
], ],
// 使 Expanded
// Expanded(child: SizedBox()),
], ],
), ),
); );
@ -462,7 +445,6 @@ class MeasuresListWidget extends StatelessWidget {
} }
} }
/// ///
class OtherMeasuresWidget extends StatelessWidget { class OtherMeasuresWidget extends StatelessWidget {
/// ///
@ -786,7 +768,7 @@ class SignaturesListWidget extends StatelessWidget {
fullUrl, fullUrl,
width: 50, width: 50,
height: 50, height: 50,
fit: BoxFit.fill, fit: BoxFit.cover,
errorBuilder: errorBuilder:
(ctx, err, st) => Container( (ctx, err, st) => Container(
width: 50, width: 50,
@ -872,7 +854,7 @@ class SignaturesListWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.all(5), padding: const EdgeInsets.all(8),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -880,7 +862,7 @@ class SignaturesListWidget extends StatelessWidget {
label, label,
style: const TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 2), const SizedBox(height: 4),
TextField( TextField(
controller: TextEditingController(text: descr), controller: TextEditingController(text: descr),
maxLines: null, maxLines: null,
@ -891,7 +873,7 @@ class SignaturesListWidget extends StatelessWidget {
), ),
), ),
Padding( Padding(
padding: const EdgeInsets.all(5), padding: const EdgeInsets.all(8),
child: Text('$personDes: $name'), child: Text('$personDes: $name'),
), ),
for (var i = 0; i < signPaths.length; i++) for (var i = 0; i < signPaths.length; i++)
@ -915,7 +897,7 @@ class SignaturesListWidget extends StatelessWidget {
(_, __, ___) => const Icon(Icons.broken_image), (_, __, ___) => const Icon(Icons.broken_image),
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 16),
Expanded( Expanded(
child: Text(i < signTimes.length ? signTimes[i] : ''), child: Text(i < signTimes.length ? signTimes[i] : ''),
), ),
@ -1461,7 +1443,7 @@ class SignItemWidget extends StatelessWidget {
fullUrl, fullUrl,
width: smallThumbSize, width: smallThumbSize,
height: smallThumbSize, height: smallThumbSize,
fit: BoxFit.fill, fit: BoxFit.cover,
errorBuilder: errorBuilder:
(_, __, ___) => Container( (_, __, ___) => Container(
width: smallThumbSize, width: smallThumbSize,
@ -1915,7 +1897,7 @@ class SignRowImageTitle extends StatelessWidget {
fullUrl, fullUrl,
width: imageSize, width: imageSize,
height: imageSize, height: imageSize,
fit: BoxFit.fill, fit: BoxFit.cover,
errorBuilder: errorBuilder:
(_, __, ___) => Container( (_, __, ___) => Container(
width: imageSize, width: imageSize,

View File

@ -93,6 +93,7 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> {
/// ///
Future<void> _onImageAdded(String localPath) async { Future<void> _onImageAdded(String localPath) async {
if (!mounted) return;
LoadingDialogHelper.show(); LoadingDialogHelper.show();
try { try {
@ -100,6 +101,8 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> {
final res = await ApiService.uploadSaveFile(localPath).timeout(const Duration(seconds: 30)); final res = await ApiService.uploadSaveFile(localPath).timeout(const Duration(seconds: 30));
LoadingDialogHelper.hide(); LoadingDialogHelper.hide();
if (!mounted) return;
if (res['result'] == 'success') { if (res['result'] == 'success') {
final url = res['FILE_PATH'] as String; final url = res['FILE_PATH'] as String;
setState(() { setState(() {
@ -441,6 +444,7 @@ class _DangerousOptionsPageState extends State<DangerousOptionsPage> {
onChanged: (paths) {}, onChanged: (paths) {},
onMediaAdded: _onImageAdded, onMediaAdded: _onImageAdded,
onMediaRemoved: (path) { onMediaRemoved: (path) {
// localPath
try { try {
final item = imgList.firstWhere((e) => path.contains(e.localPath)); final item = imgList.firstWhere((e) => path.contains(e.localPath));
_onImageRemoved(item); _onImageRemoved(item);

View File

@ -167,13 +167,13 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
hintText: '请选择动火人及证书编号', hintText: '请选择动火人及证书编号',
onTap: widget.onChooseHotworkUser, onTap: widget.onChooseHotworkUser,
), ),
if (FormUtils.hasValue(pd, 'UNIT_NAME') && if (FormUtils.hasValue(pd, 'WORK_USER_DEPARTMENT_NAME') &&
!widget.isEditable) ...[ !widget.isEditable) ...[
const Divider(), const Divider(),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
label: '作业单位:', label: '作业单位:',
isEditable: false, isEditable: false,
text: pd['UNIT_NAME'] ?? '', text: pd['WORK_USER_DEPARTMENT_NAME'] ?? '',
), ),
], ],
if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') && if (FormUtils.hasValue(pd, 'CONFIRM_USER_NAME') &&
@ -186,14 +186,6 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
text: pd['CONFIRM_USER_NAME'] ?? '', text: pd['CONFIRM_USER_NAME'] ?? '',
), ),
], ],
if (FormUtils.hasValue(pd, 'ANALYZE_TIME') && !widget.isEditable) ...[
const Divider(),
ItemListWidget.OneRowStartButtonTitle(
label: '气体分析信息:',
text: pd['ANALYZE_USER_NAME'] ?? '',
onTap: widget.onAnalyzeTap,
),
],
const Divider(), const Divider(),
ItemListWidget.twoRowButtonTitleText( ItemListWidget.twoRowButtonTitleText(
label: '关联其他特殊作业及安全作业票编号', label: '关联其他特殊作业及安全作业票编号',
@ -396,7 +388,14 @@ class _HotWorkDetailFormWidgetState extends State<HotWorkDetailFormWidget> {
text: pd['VIDEONAME'] ?? '', text: pd['VIDEONAME'] ?? '',
), ),
if (FormUtils.hasValue(pd, 'ANALYZE_TIME') && !widget.isEditable) ...[
const Divider(),
ItemListWidget.OneRowStartButtonTitle(
label: '气体分析信息:',
text: pd['ANALYZE_USER_NAME'] ?? '',
onTap: widget.onAnalyzeTap,
),
],
], ],
), ),
); );

View File

@ -371,7 +371,7 @@ class _HotworkSafeFuncSureState extends State<HotworkSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -132,12 +132,11 @@ class _HotworkAqglDetailState extends State<HotworkAqglDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -134,12 +134,11 @@ class _HotworkDbbzDetailState extends State<HotworkDbbzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
class HotSafeWorkChoosePage extends StatefulWidget {
const HotSafeWorkChoosePage({super.key});
@override
State<HotSafeWorkChoosePage> createState() => _HotSafeWorkChoosePageState();
}
class _HotSafeWorkChoosePageState extends State<HotSafeWorkChoosePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: 'dong'),
);
}
}

View File

@ -132,12 +132,11 @@ class _HotworkDhspDetailState extends State<HotworkDhspDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -364,33 +364,35 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
overflow: TextOverflow.visible, 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( Expanded(
child: Text( child: Text(
"安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}", "安全交底人: ${item['CONFESS_USER_NAME'] ?? ''}",
softWrap: true, softWrap: true,
maxLines: null, maxLines: null,
textAlign: TextAlign.right,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
), ),
), ),
], const SizedBox(width: 8),
),
Row(
children: [
Expanded( Expanded(
child: Text( child: Text(
"接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}", "接受交底人: ${item['ACCEPT_CONFESS_USER_NAME'] ?? ''}",
softWrap: true,
maxLines: null,
overflow: TextOverflow.visible,
),
),
Expanded(
child: Text(
"作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",
textAlign: TextAlign.right, textAlign: TextAlign.right,
softWrap: true, softWrap: true,
maxLines: null, maxLines: null,
@ -402,10 +404,19 @@ class _HotWorkListPageState extends State<HotWorkListPage> {
Row( Row(
children: [ children: [
Expanded(
child: Text(
"作业负责人: ${item['CONFIRM_USER_NAME'] ?? ''}",
softWrap: true,
maxLines: null,
overflow: TextOverflow.visible,
),
),
const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
"所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}", "所在单位负责人: ${item['LEADER_USER_NAME'] ?? ''}",
textAlign: TextAlign.left, textAlign: TextAlign.right,
softWrap: true, softWrap: true,
maxLines: null, maxLines: null,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,

View File

@ -161,6 +161,82 @@ class _HotworkSetSafeDetailState extends State<HotworkSetSafeDetail> {
).then((_) {}); ).then((_) {});
} }
///
Future<void> _sign() async {
await NativeOrientation.setLandscape();
final path = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => MineSignPage()),
);
await NativeOrientation.setPortrait();
if (path != null) {
final now = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
setState(() {
imagePaths.add(path);
signTimes.add(now);
});
}
}
Widget _signListWidget() {
return Column(
children:
imagePaths.map((path) {
return Column(
children: [
const SizedBox(height: 10),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: // ConstrainedBox BoxFit.contain
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 200,
maxHeight: 150,
),
child: Image.file(
File(path),
//
fit: BoxFit.contain,
),
),
onTap: () {
presentOpaque(
SingleImageViewer(imageUrl: path),
context,
);
},
),
Column(
children: [
Container(
padding: const EdgeInsets.only(right: 5),
child: CustomButton(
text: 'X',
height: 30,
padding: const EdgeInsets.symmetric(horizontal: 10),
backgroundColor: Colors.red,
onPressed: () {
setState(() {
imagePaths.remove(path);
});
},
),
),
const SizedBox(height: 80),
],
),
],
),
],
);
}).toList(),
);
}
/// -1 1 /// -1 1
Future<void> _submit(String status) async { Future<void> _submit(String status) async {
List<Map<String, dynamic>> signers = []; List<Map<String, dynamic>> signers = [];

View File

@ -132,11 +132,11 @@ class _HotworkSzdwDetailState extends State<HotworkSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -185,12 +185,12 @@ class _HotworkYsgdDetailState extends State<HotworkYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,11 +132,11 @@ class _HotworkZyfzDetailState extends State<HotworkZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -424,7 +424,7 @@ class _CutroadSafeFuncSureState extends State<CutroadSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -383,7 +383,7 @@ class _BreakgroundSafeFuncSureState extends State<BreakgroundSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -131,11 +131,12 @@ class _BreakgroundDzzhDetailState extends State<BreakgroundDzzhDetail> {
} }
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -130,11 +130,12 @@ class _BreakgroundShbmDetailState extends State<BreakgroundShbmDetail> {
} }
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -130,11 +130,12 @@ class _BreakgroundSpbmDetailState extends State<BreakgroundSpbmDetail> {
} }
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -132,11 +132,11 @@ class _BreakgroundSzdwDetailState extends State<BreakgroundSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -185,12 +185,12 @@ class _BreakgroundYsgdDetailState extends State<BreakgroundYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,11 +132,11 @@ class _BreakgroundZyfzDetailState extends State<BreakgroundZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -427,6 +427,18 @@ class _HoistworkDetailFormWidgetState extends State<HoistWorkDetailFormWidget> {
onTap: widget.onChooseVideoManager ?? () {}, onTap: widget.onChooseVideoManager ?? () {},
text: pd['VIDEONAME'] ?? '', text: pd['VIDEONAME'] ?? '',
), ),
if (FormUtils.hasValue(widget.signs, 'SISUO')) ...[
const Divider(),
ConfirmWithSignWidget(
signs: widget.signs,
pd: pd,
baseImgPath: ApiService.baseImgPath,
sectionKey: 'SISUO',
nameKey: 'SISUO_USER_NAME',
headerTitle: '司索人',
roleTitle: '司索人',
),
]
], ],
), ),

View File

@ -382,7 +382,7 @@ class _HoistworkSafeFuncSureState extends State<HoistworkSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -132,11 +132,11 @@ class _HoistworkDzzhDetailState extends State<HoistworkDzzhDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -404,7 +404,7 @@ class _HoistworkListPageState extends State<HoistworkListPage> {
), ),
Expanded( Expanded(
child: Text( child: Text(
"吊装作业人: ${item['WORK_USER_USER_NAME'] ?? ''}", "作业人: ${item['WORK_USER_USER_NAME'] ?? ''}",
softWrap: true, softWrap: true,
textAlign: TextAlign.right, textAlign: TextAlign.right,
maxLines: null, // maxLines: null, //

View File

@ -131,11 +131,11 @@ class _HoistworkShbmDetailState extends State<HoistworkShbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -131,11 +131,11 @@ class _HoistworkSpbmDetailState extends State<HoistworkSpbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -132,11 +132,11 @@ class _HoistworkSzdwDetailState extends State<HoistworkSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -185,12 +185,12 @@ class _HoistworkYsgdDetailState extends State<HoistworkYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,18 +132,18 @@ class _HoistworkZyfzDetailState extends State<HoistworkZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,
title: '作废原因', title: '作废原因',
hintText: '请输入作废原因', hintText: '请输入作废原因',
cancelText: '取消', cancelText: '取消',
confirmText: '确定', confirmText: '确定'
); );
if (reasonText.isEmpty) { if (reasonText.isEmpty) {
ToastUtil.showNormal(context, '请填写作废原因'); ToastUtil.showNormal(context, '请填写作废原因');
@ -181,7 +181,7 @@ class _HoistworkZyfzDetailState extends State<HoistworkZyfzDetail> {
if (result['result'] == 'success') { if (result['result'] == 'success') {
ToastUtil.showSuccess(context, '保存成功'); ToastUtil.showSuccess(context, '保存成功');
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
} else { }else{
ToastUtil.showNormal(context, '操作失败:${result['msg'] ?? '未知错误'}'); ToastUtil.showNormal(context, '操作失败:${result['msg'] ?? '未知错误'}');
} }
} catch (e) { } catch (e) {

View File

@ -370,7 +370,7 @@ class _HighworkSafeFuncSureState extends State<HighworkSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -131,11 +131,11 @@ class _HighworkShbmDetailState extends State<HighworkShbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -188,11 +188,11 @@ class _HighworkSpbmDetailState extends State<HighworkSpbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -132,11 +132,11 @@ class _HighworkSzdwDetailState extends State<HighworkSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -185,12 +185,12 @@ class _HighworkYsgdDetailState extends State<HighworkYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,6 +132,10 @@ class _HighworkZyfzDetailState extends State<HighworkZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(

View File

@ -372,7 +372,7 @@ class _ElectricitySafeFuncSureState extends State<ElectricitySafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -132,11 +132,11 @@ class _ElectricityPsdwDetailState extends State<ElectricityPsdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -132,11 +132,11 @@ class _ElectricityYddwDetailState extends State<ElectricityYddwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入用电单位意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入用电单位意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -185,12 +185,12 @@ class _ElectricityYsgdDetailState extends State<ElectricityYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,18 +132,18 @@ class _ElectricityZyfzDetailState extends State<ElectricityZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,
title: '作废原因', title: '作废原因',
hintText: '请输入作废原因', hintText: '请输入作废原因',
cancelText: '取消', cancelText: '取消',
confirmText: '确定', confirmText: '确定'
); );
if (reasonText.isEmpty) { if (reasonText.isEmpty) {
ToastUtil.showNormal(context, '请填写作废原因'); ToastUtil.showNormal(context, '请填写作废原因');
@ -181,7 +181,7 @@ class _ElectricityZyfzDetailState extends State<ElectricityZyfzDetail> {
if (result['result'] == 'success') { if (result['result'] == 'success') {
ToastUtil.showSuccess(context, '保存成功'); ToastUtil.showSuccess(context, '保存成功');
Navigator.of(context).pop(true); Navigator.of(context).pop(true);
} else { }else{
ToastUtil.showNormal(context, '操作失败:${result['msg'] ?? '未知错误'}'); ToastUtil.showNormal(context, '操作失败:${result['msg'] ?? '未知错误'}');
} }
} catch (e) { } catch (e) {

View File

@ -385,7 +385,7 @@ class _BlindboardSafeFuncSureState extends State<BlindboardSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -65,17 +65,13 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
late List<dynamic> boardList = [ late List<dynamic> boardList = [
{'BOARD_MATERIAL': '', 'BOARD_SPECIFICATION': '', 'BOARD_NO': ''}, {'BOARD_MATERIAL': '', 'BOARD_SPECIFICATION': '', 'BOARD_NO': ''},
]; ];
/// ------------------- ------------------- /// ------------------- -------------------
/// ///
late List<dynamic> videoMonitoringList = []; late List<dynamic> videoMonitoringList = [];
/// ///
late List<dynamic> unitAllList = []; late List<dynamic> unitAllList = [];
/// ///
late List<dynamic> workAreaList = []; late List<dynamic> workAreaList = [];
/// -------------------------------------- /// --------------------------------------
late Map<String, dynamic> signs = {}; late Map<String, dynamic> signs = {};
late List<Map<String, dynamic>> measuresList = []; late List<Map<String, dynamic>> measuresList = [];
@ -90,6 +86,8 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
final TextEditingController _relatedController = TextEditingController(); final TextEditingController _relatedController = TextEditingController();
final TextEditingController _riskController = TextEditingController(); final TextEditingController _riskController = TextEditingController();
// //
final Map<EditUserType, List<Map<String, dynamic>>> _personCache = {}; final Map<EditUserType, List<Map<String, dynamic>>> _personCache = {};
@ -107,6 +105,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
pd['APPLY_USER_ID'] = SessionService.instance.loginUserId; pd['APPLY_USER_ID'] = SessionService.instance.loginUserId;
pd['APPLY_USER_NAME'] = SessionService.instance.username; pd['APPLY_USER_NAME'] = SessionService.instance.username;
pd['IS_CONTRACTOR_WORK'] = '0'; pd['IS_CONTRACTOR_WORK'] = '0';
} }
_getVideoList(); _getVideoList();
@ -133,16 +132,15 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
pd['RISK_IDENTIFICATION'] = _riskController.text.trim(); pd['RISK_IDENTIFICATION'] = _riskController.text.trim();
}); });
} }
/// ---------------------------- -------------------------------- /// ---------------------------- --------------------------------
/// ///
Future<void> _chooseVideoManager() async { Future<void> _chooseVideoManager() async {
final choice = await BottomPicker.show<String>( final choice = await BottomPicker.show<String>(
context, context,
items: items:
videoMonitoringList videoMonitoringList
.map((item) => item['VIDEONAME'] as String) .map((item) => item['VIDEONAME'] as String)
.toList(), .toList(),
itemBuilder: (item) => Text(item, textAlign: TextAlign.center), itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
initialIndex: 0, initialIndex: 0,
); );
@ -151,7 +149,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
pd['VIDEONAME'] = choice; pd['VIDEONAME'] = choice;
Map<String, dynamic> result = videoMonitoringList.firstWhere( Map<String, dynamic> result = videoMonitoringList.firstWhere(
(item) => item['VIDEONAME'] == choice, (item) => item['VIDEONAME'] == choice,
orElse: () => {}, // orElse: () => {}, //
); );
if (FormUtils.hasValue(result, 'VIDEOMANAGER_ID')) { if (FormUtils.hasValue(result, 'VIDEOMANAGER_ID')) {
@ -161,7 +159,6 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
}); });
} }
} }
/// ///
Future<void> _chooseUnitManager() async { Future<void> _chooseUnitManager() async {
final choice = await BottomPicker.show<String>( final choice = await BottomPicker.show<String>(
@ -175,7 +172,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
pd['UNITS_NAME'] = choice; pd['UNITS_NAME'] = choice;
Map<String, dynamic> result = unitAllList.firstWhere( Map<String, dynamic> result = unitAllList.firstWhere(
(item) => item['UNITS_NAME'] == choice, (item) => item['UNITS_NAME'] == choice,
orElse: () => {}, // orElse: () => {}, //
); );
if (FormUtils.hasValue(result, 'UNITS_ID')) { if (FormUtils.hasValue(result, 'UNITS_ID')) {
@ -186,8 +183,9 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
} }
} }
/// ///
Future<void> _showLocationHandle() async { Future<void> _showLocationHandle() async{
if (!FormUtils.hasValue(pd, 'ELECTRONIC_FENCE_AREA_ID')) { if (!FormUtils.hasValue(pd, 'ELECTRONIC_FENCE_AREA_ID')) {
ToastUtil.showNormal(context, '请选择作业区域'); ToastUtil.showNormal(context, '请选择作业区域');
return; return;
@ -196,11 +194,10 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
setState(() { setState(() {
pd['LONGITUDE'] = mapData['longitue'] ?? ''; pd['LONGITUDE'] = mapData['longitue'] ?? '';
pd['LATITUDE'] = mapData['latitude'] ?? ''; pd['LATITUDE'] = mapData['latitude'] ?? '';
pd['LATITUDE_LONGITUDE'] = pd['LATITUDE_LONGITUDE'] = '${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}';
'${mapData['longitue'] ?? ''},${mapData['latitude'] ?? ''}';
}); });
}
}
/// ///
Future<void> _getWorkArea() async { Future<void> _getWorkArea() async {
//FocusHelper.clearFocus(context); //FocusHelper.clearFocus(context);
@ -211,19 +208,18 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
builder: builder:
(_) => WorkAreaPicker( (_) => WorkAreaPicker(
onSelected: (String id, String POSITIONS, String name) { onSelected: (String id, String POSITIONS, String name) {
setState(() { setState(() {
pd['ELECTRONIC_FENCE_AREA_ID'] = id; pd['ELECTRONIC_FENCE_AREA_ID'] = id;
pd['POSITIONS'] = POSITIONS; pd['POSITIONS'] = POSITIONS;
pd['PLS_NAME'] = name; pd['PLS_NAME'] = name;
}); });
}, },
), ),
).then((_) { ).then((_) {
//FocusHelper.clearFocus(context); //FocusHelper.clearFocus(context);
}); });
} }
/// ///
Future<void> _getVideoList() async { Future<void> _getVideoList() async {
final result = await ApiService.getVideomanagerList(); final result = await ApiService.getVideomanagerList();
@ -231,7 +227,6 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
videoMonitoringList = result['varList'] ?? []; videoMonitoringList = result['varList'] ?? [];
}); });
} }
/// ///
Future<void> _getUnitListAll() async { Future<void> _getUnitListAll() async {
final result = await ApiService.getUnitListAll(); final result = await ApiService.getUnitListAll();
@ -321,7 +316,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
isEditable: isEditable, isEditable: isEditable,
isClean: isClean, isClean: isClean,
onTapClean: () { onTapClean: () {
ToastUtil.showNormal(context, '已清除'); ToastUtil.showNormal(context, '已清除');
setState(() { setState(() {
set_pd_USER_ID(type, ''); set_pd_USER_ID(type, '');
set_pd_USER_Name(type, ''); set_pd_USER_Name(type, '');
@ -445,22 +440,6 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
]; ];
final level = pd['WORK_TYPE'] ?? ''; final level = pd['WORK_TYPE'] ?? '';
print('---level-$level'); print('---level-$level');
int index = 0;
for (Map item in boardList) {
if (!FormUtils.hasValue(item, 'BOARD_MATERIAL')) {
ToastUtil.showNormal(context, '请填写盲板抽堵参数第${index+1}项材质');
return;
}
if (!FormUtils.hasValue(item, 'BOARD_SPECIFICATION')) {
ToastUtil.showNormal(context, '请填写盲板抽堵参数第${index+1}项规格');
return;
}
if (!FormUtils.hasValue(item, 'BOARD_NO')) {
ToastUtil.showNormal(context, '请填写盲板抽堵参数第${index+1}项编号');
return;
}
index += 1;
}
/// ///
final unitRules = <EditUserType>[ final unitRules = <EditUserType>[
@ -497,8 +476,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
return; return;
} }
if (pd['IS_CONTRACTOR_WORK'] == '1' && if (pd['IS_CONTRACTOR_WORK'] == '1' && !FormUtils.hasValue(pd, 'UNITS_ID')) {
!FormUtils.hasValue(pd, 'UNITS_ID')) {
ToastUtil.showNormal(context, '请选择承包商'); ToastUtil.showNormal(context, '请选择承包商');
return; return;
} }
@ -530,8 +508,7 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
pd['ACTION_USER'] = SessionService.instance.username; pd['ACTION_USER'] = SessionService.instance.username;
pd['APPLY_STATUS'] = status; pd['APPLY_STATUS'] = status;
pd['boardList'] = jsonEncode(boardList).toString(); pd['boardList'] = jsonEncode(boardList).toString();
pd['SPECIAL_WORK'] = pd['SPECIAL_WORK'] = FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '';
FormUtils.hasValue(pd, 'SPECIAL_WORK') ? pd['SPECIAL_WORK'] : '';
// //
if (msg == 'add') { if (msg == 'add') {
pd['STEP_ID'] = status; pd['STEP_ID'] = status;
@ -569,6 +546,8 @@ class _BlindboardApplyDetailState extends State<BlindboardApplyDetail> {
} }
} }
/// ///
Future<void> _getData() async { Future<void> _getData() async {
final data = await ApiService.getHomeworkFindById( final data = await ApiService.getHomeworkFindById(

View File

@ -132,11 +132,11 @@ class _BlindboardShbmDetailState extends State<BlindboardShbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -132,11 +132,11 @@ class _BlindboardSpbmDetailState extends State<BlindboardSpbmDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -133,11 +133,11 @@ class _BlindboardSzdwDetailState extends State<BlindboardSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -186,12 +186,12 @@ class _BlindboardYsgdDetailState extends State<BlindboardYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -133,11 +133,11 @@ class _BlindboardZyfzDetailState extends State<BlindboardZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -370,7 +370,7 @@ class _SpaceworkSafeFuncSureState extends State<SpaceworkSafeFuncSure> {
], ],
), ),
ItemListWidget.singleLineTitleText( ItemListWidget.singleLineTitleText(
isNumericInput: true,
label: '其他安全措施:', label: '其他安全措施:',
isEditable: true, isEditable: true,
hintText: '请输入其他安全措施', hintText: '请输入其他安全措施',

View File

@ -135,11 +135,11 @@ class _SpaceworkDbbzDetailState extends State<SpaceworkDbbzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -133,11 +133,11 @@ class _SpaceworkDhspDetailState extends State<SpaceworkDhspDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -133,11 +133,11 @@ class _SpaceworkSzdwDetailState extends State<SpaceworkSzdwDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入所在单位负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -186,12 +186,12 @@ class _SpaceworkYsgdDetailState extends State<SpaceworkYsgdDetail> {
} }
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
String reasonText = ''; String reasonText = '';
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (startTime.isEmpty) { if (startTime.isEmpty) {
ToastUtil.showNormal(context, '请选择验收时间'); ToastUtil.showNormal(context, '请选择验收时间');
return; return;

View File

@ -132,11 +132,11 @@ class _SpaceworkZyfzDetailState extends State<SpaceworkZyfzDetail> {
String reasonText = ''; String reasonText = '';
String DESCR = _contentController.text.trim(); String DESCR = _contentController.text.trim();
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
if (status == '1') { if (status == '1') {
if (DESCR.isEmpty) {
ToastUtil.showNormal(context, '请输入负责人意见');
return;
}
} else { } else {
reasonText = await CustomAlertDialog.showInput( reasonText = await CustomAlertDialog.showInput(
context, context,

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 2.1.2+10 version: 2.1.2+9
environment: environment:
sdk: ^3.7.0 sdk: ^3.7.0