diff --git a/assets/images/upload.png b/assets/images/upload.png new file mode 100644 index 0000000..fcb982b Binary files /dev/null and b/assets/images/upload.png differ diff --git a/lib/constants/app_enums.dart b/lib/constants/app_enums.dart index 4fa2317..c8ec46b 100644 --- a/lib/constants/app_enums.dart +++ b/lib/constants/app_enums.dart @@ -383,6 +383,28 @@ enum UploadFileType { /// 在线学习考试签字 - 类型: '166', 路径: 'online_learning_exam_signature' onlineLearningExamSignature('166', 'online_learning_exam_signature'), + + /// 重点工程安全管理协议 - 类型: '168', 路径: 'key_project_safety_management_agreement' + keyProjectSafetyManagementAgreement('168', 'key_project_safety_management_agreement'), + + /// 重点工程发起情况图片 - 类型: '169', 路径: 'key_project_initiation_image' + keyProjectInitiationImage('169', 'key_project_initiation_image'), + + /// 重点工程隐患图片 - 类型: '172', 路径: 'key_projects_hidden_dangers_Pictures' + keyProjectsHiddenDangersPictures('172', 'key_projects_hidden_dangers_pictures'), + + /// 重点工程隐患视频 - 类型: '173', 路径: 'key_projects_hidden_dangers_video' + keyProjectsHiddenDangersVideo('173', 'key_projects_hidden_dangers_video'), + + /// 重点工程签字 - 类型: '175', 路径: 'key_homework_signature_inspector' + keyHomeworkSignatureInspector('175', 'key_homework_signature_inspector'), + + /// 重点工程确认签字 - 类型: '176', 路径: 'key_homework_defendant' + keyHomeworkDefendant('176', 'key_homework_defendant'), + + /// 重点工程确认附件 - 类型: '177', 路径: 'key_homework_confirmer' + keyHomeworkConfirmer('177', 'key_homework_confirmer'), + /// 人脸识别图片上传 - 类型: '300', 路径: 'facial_recognition_images' facialRecognitionImages('300', 'facial_recognition_images'), @@ -477,10 +499,9 @@ enum UploadFileType { /// 封闭区域人员申请人签字 - 类型: '609', 路径: 'enclosed_area_personnel_applicant_signature' enclosedAreaPersonnelApplicantSignature('609', 'enclosed_area_personnel_applicant_signature'), /// 封闭区域车辆申请人签字 - 类型: '610', 路径: 'enclosed_area_vehicle_applicant_signature' - enclosedAreaVehicleApplicantSignature('610', 'enclosed_area_vehicle_applicant_signature'), + enclosedAreaVehicleApplicantSignature('610', 'enclosed_area_vehicle_applicant_signature'); + - /// 重点工程安全管理协议 - 类型: '168', 路径: 'key_project_safety_management_agreement' - keyProjectSafetyManagementAgreement('168', 'key_project_safety_management_agreement'); const UploadFileType(this.type, this.path); diff --git a/lib/customWidget/single_images_viewer.dart b/lib/customWidget/single_images_viewer.dart new file mode 100644 index 0000000..218fc01 --- /dev/null +++ b/lib/customWidget/single_images_viewer.dart @@ -0,0 +1,147 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:photo_view/photo_view_gallery.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; + + +class SingleImagesViewer extends StatefulWidget { + final String imageUrl; + /// 可选:多张图片列表。如果需要列表的话,imageUrl可以传空 + final List? imageUrls; + /// 可选:初始显示页(默认 0) + final int initialIndex; + + const SingleImagesViewer({ + Key? key, + required this.imageUrl, + this.imageUrls, + this.initialIndex = 0, + }) : super(key: key); + + @override + State createState() => _SingleImagesViewerState(); +} + +class _SingleImagesViewerState extends State { + late final List _urls; + late final PageController _pageController; + int _currentIndex = 0; + + @override + void initState() { + super.initState(); + // 优先使用 imageUrls + if (widget.imageUrls != null && widget.imageUrls!.isNotEmpty) { + _urls = widget.imageUrls!; + } else { + _urls = [widget.imageUrl]; + } + + _currentIndex = (widget.initialIndex >= 0 && widget.initialIndex < _urls.length) + ? widget.initialIndex + : 0; + _pageController = PageController(initialPage: _currentIndex); + } + + ImageProvider _providerFromUrl(String imageUrl) { + final lower = imageUrl.toLowerCase(); + if (lower.startsWith('http')) { + return NetworkImage(imageUrl); + } else if (imageUrl.startsWith('assets/') || + imageUrl.startsWith('package:') || + imageUrl.startsWith('packages/')) { + return AssetImage(imageUrl); + } else { + if (!kIsWeb) { + try { + final file = File(imageUrl); + if (file.existsSync()) { + return FileImage(file); + } else { + return AssetImage(imageUrl); + } + } catch (e) { + return AssetImage(imageUrl); + } + } else { + return AssetImage(imageUrl); + } + } + } + + @override + void dispose() { + _pageController.dispose(); + super.dispose(); + } + + Color _bgColor() => Colors.black.withOpacity(0.9); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: _bgColor(), + appBar: MyAppbar( + isBack: false, + actions: [ + IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon( + Icons.close, + color: Colors.white, + size: 40, + ), + ), + ], + backgroundColor: _bgColor(), + title: '', + ), + body: Stack( + children: [ + PhotoViewGallery.builder( + pageController: _pageController, + itemCount: _urls.length, + onPageChanged: (index) => setState(() => _currentIndex = index), + builder: (context, index) { + final url = _urls[index]; + return PhotoViewGalleryPageOptions( + imageProvider: _providerFromUrl(url), + minScale: PhotoViewComputedScale.contained, + maxScale: PhotoViewComputedScale.covered * 2, + onTapUp: (context, details, controllerValue) { + Navigator.of(context).pop(); + }, + ); + }, + backgroundDecoration: BoxDecoration(color: _bgColor()), + // enableRotation: false, // 如果需要可打开旋转 + loadingBuilder: (context, progress) => const Center( + child: CircularProgressIndicator(), + ), + ), + + // 页码指示 + if (_urls.length > 1) + Positioned( + right: 12, + top: 12 + MediaQuery.of(context).padding.top, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.45), + borderRadius: BorderRadius.circular(16), + ), + child: Text( + '${_currentIndex + 1} / ${_urls.length}', + style: const TextStyle(color: Colors.white, fontSize: 14), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/http/modules/key_tasks_api.dart b/lib/http/modules/key_tasks_api.dart index 9921a2d..cbacb68 100644 --- a/lib/http/modules/key_tasks_api.dart +++ b/lib/http/modules/key_tasks_api.dart @@ -56,4 +56,43 @@ class KeyTasksApi { } + /// 安全环保检查分页 + static Future> getKeyTasksSafetyEnvironmentalInspectionList(Map data) { + return HttpManager().request( + '${ApiService.basePath}/keyProject', + '/safetyEnvironmentalInspection/list', + method: Method.post, + data: { + ...data + }, + ); + } + + /// 安全环保检查详情. + static Future> getKeyTasksSafetyEnvironmentalInspectionDetail(String id) { + return HttpManager().request( + '${ApiService.basePath}/keyProject', + '/safetyEnvironmentalInspection/$id', + method: Method.get, + data: { + // ...data + }, + ); + } + + + /// 安全环保检查确认 + static Future> setKeyTasksCheckConfirm(Map data) { + return HttpManager().request( + '${ApiService.basePath}/keyProject', + '/safetyEnvironmentalInspectionDefend/affirm', + method: Method.post, + data: { + ...data + }, + ); + } + + + } \ No newline at end of file diff --git a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_check_confirm_page.dart b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_check_confirm_page.dart new file mode 100644 index 0000000..80ff2a1 --- /dev/null +++ b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_check_confirm_page.dart @@ -0,0 +1,533 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:qhd_prevention/constants/app_enums.dart'; +import 'package:qhd_prevention/customWidget/DocumentPicker.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/http/modules/file_api.dart'; +import 'package:qhd_prevention/http/modules/key_tasks_api.dart'; +import 'package:qhd_prevention/http/modules/safety_check_api.dart'; +import 'package:qhd_prevention/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart'; +import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/services/SessionService.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class KeyTaskesCheckConfirmPage extends StatefulWidget { + const KeyTaskesCheckConfirmPage({ + super.key, + required this.id, + required this.inspectionId, + required this.handleType, + }); + + final String id; + final String inspectionId; + final SafeCheckDetailMode handleType; + + @override + State createState() => _KeyTaskesCheckConfirmPageState(); +} + +class _KeyTaskesCheckConfirmPageState extends State { + bool _isEdit = false; // 禁止修改 + /// 被检查单位相关信息 + Map personUnderInspection = { + 'departmentId': '', + 'departmentName': '', + 'userName': '', + 'userId': '', + }; + + // 被检查确认的人员 + late Map inspectedPartyConfirmation = {}; + + List signImages = []; + List signTimes = []; // 签字时间列表 +/// 附件 + late SelectedFile? choosefile = null; + /// 检查人员核实/被检查人申辩 + late bool chooseCheckType = false; + Map checkData = {}; + late var form = null; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _getDetail(); + } + + + + /// 检查人核实编辑 + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: "被检查人确认/申辩", actions: []), + body: SafeArea( + child: ListView( + children: [ + Container( + color: Colors.white, + child: Column( + children: [ + // if (form != null) + KeyTaskesDetailWidget( + inspectionId: widget.inspectionId, + handleType: widget.handleType, + ), + _personUnderInspectionConfirmWidget(), + + const Divider(), + const SizedBox(height: 20), + _statusButtons(), + const SizedBox(height: 20), + ], + ), + ), + + + ], + ), + ), + ); + } + + Widget _personSignItem(Map item, int index) { + return SizedBox( + child: Column( + children: [ + Column( + children: [ + ItemListWidget.multiLineTitleTextField( + label: '检查人意见:', + isEditable: false, + text: item['userRemarks'] ?? '', + ), + const Divider(), + if (FormUtils.hasValue(item, 'signature')) + ItemListWidget.OneRowImageTitle( + label: '检查人签字', + onTapCallBack: (path) { + presentOpaque(SingleImageViewer(imageUrl: path), context); + }, + imgPath: item['signature'], + ), + ], + ), + ], + ), + ); + } + + Widget _personUnderInspectionConfirmWidget() { + return Column( + children: [ + Column( + children: [ + const Divider(), + ListItemFactory.createBuildSimpleSection('被检查单位现场负责人情况'), + // if (form != null && int.parse('${form['hiddenNumber'] ?? '0'}') > 0) ...[ + ListItemFactory.createYesNoSection( + title: '是否申辩:', + groupValue: !chooseCheckType, + yesLabel: '否', + noLabel: '是', + isEdit: true, + isRequired: true, + horizontalPadding: 0, + verticalPadding: 0, + text: '', + onChanged: (val) { + setState(() { + chooseCheckType = !val; + }); + }, + ), + const Divider(), + if (chooseCheckType) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ItemListWidget.multiLineTitleTextField( + label: '申辩说明', + isEditable: true, + hintText: '请输入申辩说明', + onChanged: (val) { + setState(() { + checkData['content'] = val; + }); + }, + ), + const Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ItemListWidget.itemContainer( + ListItemFactory.headerTitle('申辩附件:', isRequired: false), + ), + Padding( + padding: const EdgeInsets.only(right: 15), + child: uploadFileButton(), + ) + ], + ), + + if (choosefile != null) + ...[ + Padding(padding: EdgeInsetsGeometry.only(left: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: 10), + Icon(Icons.file_copy_outlined, color: Colors.grey,size: 50,), + SizedBox(height: 5), + Text(choosefile!.name), + SizedBox(height: 10), + ], + ),), + ], + const Divider(), + + // const Divider(), + ], + ), + // ], + + ItemListWidget.itemContainer( + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ListItemFactory.headerTitle('签字', isRequired: true), + CustomButton( + text: '手写签字', + height: 36, + backgroundColor: Colors.blue, + onPressed: () { + _sign(); + }, + ), + ], + ), + ), + if (signImages.isNotEmpty) _signListWidget(), + ], + ), + ], + ); + } + + /// 被检查人选择上传附件 + Widget uploadFileButton() { + return GestureDetector( + onTap: () async{ + final List picked = await DocumentPicker.showPickerModal( + context, + maxAssets: 1, + maxSizeInBytes: 20 * 1024 * 1024, + allowedExtensions: ['pdf'], + allowMultipleFiles: false, + // showPhotoSelect: false, + ); + + if (picked.isNotEmpty && picked.first.path != null) { + setState(() { + choosefile = picked.first; + }); + } + + }, + child: Container( + width: choosefile != null ? 120 : 100, + height: 30, + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(4), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('assets/images/upload.png', width: 15, height: 15), + const SizedBox(width: 5), + Text( + choosefile != null ? '重新选择附件' : '上传附件', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ); + } + + /// 检查人核实编辑 + Widget _signListWidget() { + return Column( + children: + signImages.map((path) { + return Column( + children: [ + const SizedBox(height: 15), + // 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(() { + signImages.remove(path); + }); + }, + ), + ), + const SizedBox(height: 80), + ], + ), + ], + ), + ], + ); + }).toList(), + ); + } + + Widget _statusButtons() { + final List buttons = []; + final List buttonRowChildren = []; + + // buttons.add( + // CustomButton( + // text: '取消', + // buttonStyle: ButtonStyleType.secondary, + // backgroundColor: Colors.blue, + // onPressed: () { + // Navigator.pop(context); + // }, + // ), + // ); + buttons.add( + CustomButton( + text: '确定', + backgroundColor: Colors.blue, + onPressed: _checkPersonSubmit, + ), + ); + for (int i = 0; i < buttons.length; i++) { + buttonRowChildren.add( + Expanded(child: SizedBox(height: 40, child: buttons[i])), + ); + if (i != buttons.length - 1) { + buttonRowChildren.add(const SizedBox(width: 10)); + } + } + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: buttonRowChildren, + ); + } + + + Widget _detailWidget() { + return Column( + children: [ + if (inspectedPartyConfirmation.isNotEmpty) + Column( + children: [ + const Divider(), + ListItemFactory.createBuildSimpleSection('检查人员意见'), + SizedBox(height: 5), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: inspectedPartyConfirmation.length, + itemBuilder: (context, index) { + return _personSignItem(inspectedPartyConfirmation[index], index); + }, + ), + ], + ), + ], + ); + } + + Future _getDetail() async { + // try { + // LoadingDialogHelper.show(); + // final result = await SafetyCheckApi.safeCheckDetail(widget.inspectionId); + // LoadingDialogHelper.hide(); + // if (result != null) { + // setState(() { + // final data = result['data']; + // form = data; + // checkData = data['inspectedPartyConfirmation'] ?? {}; + // }); + // } + // } catch (e) { + // LoadingDialogHelper.hide(); + // ToastUtil.showNormal(context, '详情获取失败'); + // } + } + + /// 签字 + Future _sign() async { + await NativeOrientation.setLandscape(); + final path = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => MineSignPage()), + ); + await NativeOrientation.setPortrait(); + if (path != null) { + final now = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now()); + setState(() { + signImages = []; + signTimes = []; + signImages.add(path); + signTimes.add(now); + }); + } + } + + // 检查人核实提交 + Future _checkPersonSubmit() async { + if (chooseCheckType) { + if (!FormUtils.hasValue(checkData, 'content')) { + ToastUtil.showNormal(context, '请输入申辩说明'); + return; + } + } + if (signImages.isEmpty) { + ToastUtil.showNormal(context, '请签字'); + return; + } + LoadingDialogHelper.show(); + + printLongString(jsonEncode(SessionService.instance.accountId)); + final checkSign = await _checkSignature(); + final checkFile = await _checkFileUpload(); + + if (checkSign && checkFile) { + + // checkData['status'] = 1; + checkData['signatureTime'] = signTimes.first; + checkData['isDefend'] = chooseCheckType ? 0 : 1; + checkData['inspectionId'] = widget.inspectionId; + try { + final result = await KeyTasksApi.setKeyTasksCheckConfirm(checkData); + if (result['success']) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '提交成功'); + Navigator.of(context).pop(); + } else { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '提交失败:${result['errMessage']}'); + } + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '提交异常:$e'); + } + } + } + + /// 校验是否有签字需要上传 + Future _checkSignature() async { + UploadFileType fileType = + UploadFileType.keyHomeworkDefendant; + late bool isSuccess = true; + if (signImages.isNotEmpty) { + try { + await FileApi.uploadFile(signImages.first, fileType, '').then((result) { + if (result['success']) { + // 检查人签字 + checkData['defendantSign'] = result['data']['filePath'] ?? ''; + checkData['signatureTime'] = signTimes.first; + isSuccess = true; + } else { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '签名上传失败'); + isSuccess = false; + } + }); + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '签名上传失败'); + isSuccess = false; + } + } + + return isSuccess; + } + + /// 校验是否有文件需要上传 + Future _checkFileUpload() async { + UploadFileType fileType = + UploadFileType.keyHomeworkConfirmer; + late bool isSuccess = true; + final choosefile = this.choosefile; + if (choosefile != null) { + try { + await FileApi.uploadFiles([choosefile.path ?? ''], fileType, checkData['inspectionId'] ?? '').then((result) { + if (result['success']) { + // 检查人签字 + checkData['fileUrl'] = result['data']['filePath'] ?? ''; + isSuccess = true; + } else { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '签名上传失败'); + isSuccess = false; + } + }); + } catch (e) { + LoadingDialogHelper.hide(); + ToastUtil.showNormal(context, '签名上传失败'); + isSuccess = false; + } + }else{ + isSuccess = true; + } + + return isSuccess; + } + + + + + + + +} diff --git a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_danger_page.dart b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_danger_page.dart new file mode 100644 index 0000000..2ebe0ab --- /dev/null +++ b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_danger_page.dart @@ -0,0 +1,914 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:intl/intl.dart'; +import 'package:qhd_prevention/constants/app_enums.dart'; +import 'package:qhd_prevention/customWidget/BaiDuMap/map_webview_page.dart'; +import 'package:qhd_prevention/customWidget/DangerPartsPicker.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/MultiDictValuesPicker.dart'; +import 'package:qhd_prevention/customWidget/bottom_picker_two.dart'; +import 'package:qhd_prevention/customWidget/center_multi_picker.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/department_person_picker.dart'; +import 'package:qhd_prevention/customWidget/department_picker_two.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/customWidget/photo_picker_row.dart'; +import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/http/modules/auth_api.dart'; +import 'package:qhd_prevention/http/modules/hidden_danger_api.dart'; +import 'package:qhd_prevention/http/modules/safety_check_api.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/services/SessionService.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class KeyTaskesDangerPage extends StatefulWidget { + const KeyTaskesDangerPage({ + super.key, + required this.initData, + required this.inspectionId, + required this.isEdit, + this.isAssignment = false, + required this.personList, + this.autoSaveTime = 0, + this.corpId = '', + + }); + final String inspectionId; + final bool isEdit; + final dynamic initData; + /// 被检查人单位Id + final String corpId; + // 是否指派 + final bool isAssignment; + // 隐患发现人(包括自己和检查人员) + final List personList; + final int autoSaveTime; + + @override + State createState() => _KeyTaskesDangerPageState(); +} + +class _KeyTaskesDangerPageState extends State { + /// 隐患确认人 + Map addData = { + "hiddenId": "", + "source": 5, + "foreignKey": "", + "isRelated": '0', //是否相关方 + "corpId": "", + "corpName": "", + "hiddenDesc": "", //隐患描述 + "hiddenPart": "", //隐患部位 + "hiddenLevel": "", //隐患级别 + "hiddenLevelName": "", //隐患级别名称 + "hiddenType": "", //隐患类型 + "hiddenTypeName": "", //隐患类型名称 + "hiddenType2": "", //隐患类型2 + "hiddenType2Name": "", //隐患类型2翻译 + "longitude": "", + "latitude": "", + "positionDesc": "", //隐患位置描述 + "creatorId": "", //发现人(主) + "creatorName": "", //发现人名称(主) + "hiddenFindDept": "", //隐患发现部门(主) + "hiddenFindDeptName": "", //隐患发现部门名称(主) + "hiddenFindTime": "", //隐患发现时间 + "confirmDeptId": "", //确认人部门 + "confirmDeptName": "", //确认人部门名称 + "confirmUserId": "", //确认人 + "confirmUserName": "", //确认人名称 + "rectificationType": "2", //整改类型 1立即整改 2延期整改 + "rectificationDeadline": "", //整改期限(整改截至日期) + "rectificationDescr": "", //描述 + "rectificationDeptId": "", //隐患整改部门 + "rectificationDeptName": "", //隐患整改部门名称 + "rectificationUserId": "", //整改人 + "rectificationUserName": "", //整改人名称 + "checkUserId": "", //验收人 + "checkUserName": "", //验收人名称 + "checkDeptId": "", //验收部门 + "checkDeptName": "", //验收部门名称 + + "hiddenJson": SessionService.instance.hiddenJson, //隐患流程JSON + "isAi": 0, //是否AI识别 ai确认 0否1是 + "legalBasis": "", //法律依据 + "projectId": "", //项目id + "projectName": "", //项目名称 + + "aiBatch": "", //AI批次 + "hiddenImgAddCmds": [], + + "hiddenUserId": "", //整改id(整改图片反的id) + "hiddenPartName": "", //隐患部位名称 + + 'hiddenFindUserdList':[],//隐患发现人多选 + 'hiddenFindUserdName':'',//隐患发现人多选名字 + + }; + + + + // 是否是修改 + late bool _isRevise = false; + late bool _isLoading = true; + late bool _showRectification = true; + late List _HazardPersonlist = []; + + /// 隐患确认人信息 + Map _hazarder = {}; + + // 存储各单位的人员列表 + List> _personCache = []; + + List _dangerImages = []; + List _dangerVideos = []; + List _initFileList = []; + List _removeFileList = []; + + String buMenId = ""; + String buMenName = ""; + String responsibleId = ""; + String responsibleName = ""; + + @override + void initState() { + // TODO: implement initState + super.initState(); + if (widget.initData != null) { + addData = widget.initData; + _dangerImages = addData['imgs'] ?? []; + _dangerVideos = addData['videos'] ?? []; + } else { + addData['hiddenFindTime'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(DateTime.now()); + } + if (widget.isEdit) { + _getUserData(); + } + _isRevise = FormUtils.hasValue(addData, 'id'); + if (_isRevise) { + _getHiddenDetail(); + } else { + setState(() { + _isLoading = false; + }); + } + if (widget.isAssignment) { + _getHazardPersonlist(); + } + } + + Future _getHazardPersonlist() async { + try { + LoadingDialogHelper.show(); + final raw = await HiddenDangerApi.getHazardPersonlist(); + if (raw['success']) { + setState(() { + _HazardPersonlist = raw['data'] as List; + print(_HazardPersonlist); + }); + LoadingDialogHelper.hide(); + } else { + ToastUtil.showNormal(context, "获取列表失败"); + LoadingDialogHelper.hide(); + } + } catch (e) { + // 出错时可以 Toast 或者在页面上显示错误状态 + print('加载首页数据失败:$e'); + LoadingDialogHelper.hide(); + } + } + + Future _getHiddenDetail() async { + // LoadingDialogHelper.show(); + // final result = await HiddenDangerApi.getDangerDetail(widget.initData['id']); + // LoadingDialogHelper.hide(); + // if (result['success']) { + // final data = result['data']; + // setState(() { + // addData = data; + _getHiddenImages(); + // }); + // } + } + + /// 获取隐患照片 + Future _getHiddenImages() async { + final result = await FileApi.getImagePathWithType( + addData['hiddenId'] ?? '', + '', + UploadFileType.keyProjectsHiddenDangersPictures, + ); + if (result['success']) { + final data = result['data']; + for (Map item in data) { + final filePath = item['filePath'] ?? ''; + _initFileList.add(item); + _dangerImages.add(ApiService.baseImgPath + filePath); + } + } + final resultVideo = await FileApi.getImagePathWithType( + addData['hiddenId'] ?? '', + '', + UploadFileType.keyProjectsHiddenDangersVideo, + ); + if (resultVideo['success']) { + final data = resultVideo['data']; + for (Map item in data) { + final filePath = item['filePath'] ?? ''; + _initFileList.add(item); + _dangerVideos.add(ApiService.baseImgPath + filePath); + } + } + setState(() { + _isLoading = false; + }); + } + + /// 选择隐患发起人,只能在安全环保检查发起人和检查人中选择 + Future _getDepartmentPersonList() async { + String choice = await BottomPickerTwo.show( + context, + items: widget.personList, + itemName: "userName", + itemBuilder: + (item) => Text(item["userName"], textAlign: TextAlign.center), + initialIndex: 0, + ); + if (choice != null) { + for (int i = 0; i < widget.personList.length; i++) { + final item = widget.personList[i]; + if (choice == item["userName"]) { + setState(() { + addData['creatorId'] = item['userId']; + addData['creatorName'] = item['userName']; + }); + } + } + } + + } + + Future _getDiscoverPersonList() async { + String choice = await BottomPickerTwo.show( + context, + items: _HazardPersonlist, + itemName: "userName", + itemBuilder: + (item) => Text(item["userName"], textAlign: TextAlign.center), + initialIndex: 0, + ); + if (choice != null) { + for (int i = 0; i < _HazardPersonlist.length; i++) { + if (choice == _HazardPersonlist[i]["userName"]) { + setState(() { + _hazarder = _HazardPersonlist[i]; + }); + } + } + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: widget.isAssignment ? "隐患信息维护" : "隐患信息维护"), + backgroundColor: Colors.white, + body: Column( + children: [ + // 详情滚动区域 + _pageDetail(), + ], + ), + ); + } + + Widget _pageDetail() { + return Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.only(bottom: 20, left: 10, right: 10), + child: + _isLoading + ? NoDataWidget.show() + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RepairedPhotoSection( + isRequired: widget.isEdit, + isEdit: widget.isEdit, + title: "隐患照片", + maxCount: 4, + mediaType: MediaType.image, + isShowAI: false, + followInitialUpdates: true, + initialMediaPaths: _dangerImages, + onChanged: (List files){}, + onMediaAdded: (value) { + _dangerImages.add(value); + }, + onMediaRemoved: (value) { + _dangerImages.remove(value); + _removeFileList.add(value); + }, + onAiIdentify: () { + }, + ), + const Divider(), + RepairedPhotoSection( + title: "隐患视频", + isRequired: false, + isEdit: widget.isEdit, + maxCount: 1, + followInitialUpdates: true, + mediaType: MediaType.video, + initialMediaPaths: _dangerVideos.length > 0 ? [_dangerVideos.last] : [], + onChanged: (List files) { + // _dangerVideos=files[0].path; + }, + onMediaRemoved: (value) { + _dangerVideos.remove(value); + _removeFileList.add(value); + }, + onMediaAdded: (value) { + // 上传视频 files + try { + _dangerVideos.clear(); + _dangerVideos.add(value); + } catch (e) { + print("获取视频失败:${e.toString()}"); + } + }, + onAiIdentify: () {}, + ), + const Divider(), + ItemListWidget.multiLineTitleTextField( + label: '隐患描述', + isEditable: widget.isEdit, + isRequired: widget.isEdit, + + text: addData['hiddenDesc'] ?? '', + hintText: '请输入隐患描述', + onChanged: (value) { + setState(() { + addData['hiddenDesc'] = value; + }); + }, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "隐患级别", + text: + FormUtils.hasValue(addData, 'hiddenLevelName') + ? addData['hiddenLevelName'] + : "请选择", + isEditable: widget.isEdit, + onTap: () { + _getHazardLevel(); + }, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "隐患类型", + text: + FormUtils.hasValue(addData, 'hiddenTypeName') + ? addData['hiddenTypeName'] + : "请选择", + isEditable: widget.isEdit, + onTap: () { + _getHiddenDangerType(); + }, + ), + // const Divider(), + // ListItemFactory.createMultiOptionSection( + // title: '是否相关方:', + // selectedValue: '否', + // options: ['是', '否'], + // isEdit: widget.isEdit, + // isRequired: true, + // horizontalPadding: 3, + // verticalPadding: 10, + // text: '${addData['isRelated'] == '1' ? '是' : '否'}', + // onChanged: (val) { + // setState(() { + // val == '是' ? addData['isRelated'] = '1' : '0'; + // }); + // }, + // ), + + + // const Divider(), + // ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: false, + // label: '隐患部位', + // isEditable: widget.isEdit, + // text: + // FormUtils.hasValue(addData, 'hiddenPartName') + // ? addData['hiddenPartName'] + // : "请选择", + // onTap: () { + // _getHiddenDangerAreas(); + // }, + // ), + const Divider(), + ItemListWidget.multiLineTitleTextField( + label: '隐患位置描述', + isEditable: widget.isEdit, + isRequired: false, + text: addData['positionDesc'] ?? '', + hintText: '请对隐患位置进行详细描述', + onChanged: (value) { + setState(() { + addData['positionDesc'] = value; + }); + }, + ), + // const Divider(), + // ItemListWidget.OneRowButtonTitleText( + // label: '隐患上报位置', + // buttonText: '定位', + // isEdit: widget.isEdit, + // text: '', + // onTap: () async { + // final result = await pushPage( + // MapWebViewPage(), + // context, + // ); + // print(result); + // if (result != null) { + // setState(() { + // addData['longitude'] = + // result['longitude'].toString(); + // addData['latitude'] = result['latitude'].toString(); + // }); + // } + // }, + // ), + // Container( + // padding: EdgeInsets.symmetric(horizontal: 15), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(5), + // ), + // child: ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: false, + // label: "经度", + // text: addData['longitude'] ?? '', + // isEditable: false, + // ), + // ), + // const Divider(), + // Container( + // padding: EdgeInsets.symmetric(horizontal: 15), + // decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(5), + // ), + // child: ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: false, + // label: "纬度", + // text: addData['latitude'] ?? '', + // isEditable: false, + // ), + // ), + + const Divider(), + _buildInfoItem( + '整改类型', + '限期整改', + ), + + if(_showRectification)...[ + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "整改期限", + text: + FormUtils.hasValue(addData, 'rectificationDeadline') ? addData['rectificationDeadline'] : "请选择", + isEditable: widget.isEdit, + onTap: () async { + DateTime? picked = await BottomDateTimePicker.showDate( + context, + allowPast: false, + allowFuture: true, + mode: BottomPickerMode.dateTimeWithSeconds, + ); + if (picked != null) { + setState(() { + addData['rectificationDeadline'] = DateFormat( + 'yyyy-MM-dd HH:mm:ss', + ).format(picked); + }); + //FocusHelper.clearFocus(context); + } + }, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "整改部门", + text: FormUtils.hasValue(addData, 'rectificationDeptName') ? addData['rectificationDeptName'] : "请选择", + isEditable: widget.isEdit, + onTap: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + barrierColor: Colors.black54, + backgroundColor: Colors.transparent, + builder: + (ctx) => DepartmentPickerTwo( + onSelected: (id, name,pdId) async { + setState(() { + + addData['rectificationDeptId']= id; + addData['rectificationDeptName']= name; + + addData['rectificationUserId']= ""; + addData['rectificationUserName']= ""; + + + }); + // 拉取该单位的人员列表并缓存 + final result = await HiddenDangerApi.getListTreePersonList(id); + _personCache=List>.from( + result['data'] as List, + ); + }, + ), + ); + }, + ), + + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "整改人", + text: FormUtils.hasValue(addData, 'rectificationUserName') ? addData['rectificationUserName'] : "请选择", + isEditable: widget.isEdit, + onTap: () async { + if ( addData['rectificationDeptName'].isEmpty) { + ToastUtil.showNormal(context, '请先选择部门'); + return; + } + DepartmentPersonPicker.show( + context, + personsData: _personCache, + onSelected: (userId, name) { + setState(() { + + addData['rectificationUserId']= userId; + addData['rectificationUserName']= name; + + }); + + }, + ); + }, + ), + + ], + + + + const Divider(), + Column( + children: [ + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: widget.isEdit, + label: "隐患发现人", + text: FormUtils.hasValue(addData, 'hiddenFindUserdName') ? addData['hiddenFindUserdName'] : "请选择", + isEditable: widget.isEdit, + onTap: () async { + final List result = []; + final dynamic coList = widget.personList; + + if (coList is List) { + for (final item in coList) { + if (item is Map) { + final dynamic standardItem = item['userName']; + if (standardItem is String && standardItem.isNotEmpty) { + result.add(standardItem); + } + } + } + } + + // 获取当前已选择的项目 + final dynamic currentSelected = addData['hiddenFindUserdList'] ?? []; + List selectedList = []; + + if (currentSelected is List) { + for (final item in currentSelected) { + if (item is Map) { + final dynamic standardItem = item['userName']; + if (standardItem is String && standardItem.isNotEmpty) { + selectedList.add(standardItem); + } + } + } + } + + + // 计算预选索引 + final List initialIndices = []; + for (final selectedItem in selectedList) { + final int index = result.indexOf(selectedItem); + if (index != -1) { + initialIndices.add(index); + } + } + + // 显示选择器 + final selectedItems = await CenterMultiPicker.show( + context, + items: result, + itemBuilder: (item) => Text( + item, + style: const TextStyle(fontSize: 16), + ), + initialSelectedIndices: initialIndices, // 设置预选索引 + maxSelection: null, // 不限制选择数量 + allowEmpty: true, + title: '隐患发现人', + ); + + // 处理选择结果 + if (selectedItems != null) { + setState(() { + addData['hiddenFindUserdName'] = selectedItems.join(','); + + List result = widget.personList.where((person) { + String userName = person['userName']?.toString() ?? ''; + return selectedItems.contains(userName); + }).toList(); + addData['hiddenFindUserdList'] = result; + + }); + } + // onTap: () { + // _getDepartmentPersonList(); + }, + ), + SizedBox(height: 1), + ], + ), + + + + + + + const Divider(), + + SizedBox(height: 20), + if (widget.isEdit) + CustomButton( + onPressed: () { + _riskListCheckAppAdd(); + }, + text: "保存", + padding: EdgeInsets.symmetric(horizontal: 30), + backgroundColor: Colors.blue, + ), + ], + ), + ), + ); + } + + + Future _riskListCheckAppAdd() async { + if (_dangerImages.isEmpty) { + ToastUtil.showNormal(context, "请上传隐患图片"); + return; + } + + if (!FormUtils.hasValue(addData, 'hiddenDesc')) { + ToastUtil.showNormal(context, "请输入隐患描述"); + return; + } + + if (!FormUtils.hasValue(addData, 'hiddenLevelName')) { + ToastUtil.showNormal(context, "请选择隐患级别"); + return; + } + + if (!FormUtils.hasValue(addData, 'hiddenType')) { + ToastUtil.showNormal(context, "请选择隐患类型"); + return; + } + + if(_showRectification){ + if (!FormUtils.hasValue(addData, 'rectificationDeadline')) { + ToastUtil.showNormal(context, "请选择整改期限"); + return; + } + if (!FormUtils.hasValue(addData, 'rectificationDeptId')) { + ToastUtil.showNormal(context, "请选择整改部门"); + return; + } + if (!FormUtils.hasValue(addData, 'rectificationUserId')) { + ToastUtil.showNormal(context, "请选择整改人"); + return; + } + } + + // if (!FormUtils.hasValue(addData, 'positionDesc')) { + // ToastUtil.showNormal(context, "隐患位置描述不能为空"); + // return; + // } + /// 删除服务器保存的图片 + List ids = []; + for (var item in _initFileList) { + final serverPath = item['filePath']; + for (String path in _removeFileList) { + if (path.contains(serverPath)) { + if (FormUtils.hasValue(item, 'id')) { + ids.add(item['id']); + } + } + } + } + if (ids.isNotEmpty) { + LoadingDialogHelper.show(); + await FileApi.deleteImages(ids); + LoadingDialogHelper.dismiss(); + } + + + addData['imgs'] = _dangerImages; + addData['videos'] = _dangerVideos; + Navigator.pop(context, addData); + // try { + // final raw = await HiddenDangerApi.addRiskListCheckApp(addData); + // if (raw['success']) { + // setState(() { + // LoadingDialogHelper.hide(); + // ToastUtil.showNormal(context, "提交成功"); + // Navigator.pop(context); + // }); + // } else { + // LoadingDialogHelper.hide(); + // ToastUtil.showNormal(context, "提交失败"); + // } + // } catch (e) { + // LoadingDialogHelper.hide(); + // print('Error fetching data: $e'); + // } + } + + Future _identifyImg(String imagePath) async { + try {} catch (e) { + // 出错时可以 Toast 或者在页面上显示错误状态 + print('加载首页数据失败:$e'); + // return ""; + LoadingDialogHelper.hide(); + } + } + + // Future _getHiddenDangerAreas() async { + // showModalBottomSheet( + // context: context, + // isScrollControlled: true, + // barrierColor: Colors.black54, + // backgroundColor: Colors.transparent, + // builder: + // (_) => DangerPartsPicker( + // title: '隐患部位', + // requestData: {'eqCorpinfoId' : widget.corpId}, + // onSelected: (id, name, extraData) { + // setState(() { + // addData['hiddenPartName'] = name; + // addData['hiddenPart'] = id; + // }); + // }, + // ), + // ).then((_) { + // // 可选:FocusHelper.clearFocus(context); + // }); + // } + + Future _getHazardLevel() async { + showModalBottomSheet( + context: context, + isScrollControlled: true, + barrierColor: Colors.black54, + backgroundColor: Colors.transparent, + builder: + (_) => MultiDictValuesPicker( + dictType: 'hiddenLevel', + allowSelectParent: false, + isSafeChekDangerLevel: false, + onSelected: (id, name, extraData) { + setState(() { + print(json.encode(extraData)); + addData['hiddenLevel'] = extraData?['dictValue'] ?? ''; + addData['hiddenLevelName'] = name; + if('轻微隐患'==name||'一般隐患'==name){ + _showRectification=true; + }else{ + _showRectification=false; + } + + }); + }, + ), + ).then((_) { + // 可选:FocusHelper.clearFocus(context); + }); + } + + Future _getHiddenDangerType() async { + showModalBottomSheet( + context: context, + isScrollControlled: true, + barrierColor: Colors.black54, + backgroundColor: Colors.transparent, + builder: + (_) => MultiDictValuesPicker( + title: '检查类型', + dictType: 'hiddenType', + allowSelectParent: false, + onSelected: (id, name, extraData) { + print(json.encode(extraData)); + setState(() { + addData['hiddenType'] = extraData?['dictValue'] ?? ''; + addData['hiddenTypeName'] = name; + + //顶层 + addData['hiddenType2'] = extraData?['dingValue'] ?? ''; + addData['hiddenType2Name'] = extraData?['dingName'] ?? ''; + }); + }, + ), + ).then((_) { + // 可选:FocusHelper.clearFocus(context); + }); + } + + Future _getUserData() async { + try { + final raw = await AuthApi.getUserData(); + if (raw['success']) { + setState(() { + addData['creatorId'] = raw['data']['id']; + addData['creatorName'] = raw['data']['name']; + addData['hiddenFindDept'] = raw['data']['departmentId']; + addData['hiddenFindDeptName'] = raw['data']['departmentName']; + + responsibleId = raw['data']['id']; + responsibleName = raw['data']['name']; + buMenId = raw['data']['departmentId']; + buMenName = raw['data']['departmentName']; + }); + } else { + ToastUtil.showNormal(context, "获取个人信息失败"); + } + } catch (e) { + // 出错时可以 Toast 或者在页面上显示错误状态 + print('加载首页数据失败:$e'); + } + } + + Widget _buildInfoItem(String title, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 120, + child: Text( + title, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ), + Expanded(child: Text(value, textAlign: TextAlign.right)), + ], + ), + ); + } + + Widget _buildSectionContainer({required Widget child}) { + return Container( + margin: const EdgeInsets.only(top: 1), + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), + child: child, + ); + } + +} diff --git a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart index 945246a..4ed501c 100644 --- a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart +++ b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart @@ -18,7 +18,9 @@ import 'package:qhd_prevention/customWidget/picker/CupertinoDatePicker.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/http/modules/key_tasks_api.dart'; import 'package:qhd_prevention/http/modules/safety_check_api.dart'; +import 'package:qhd_prevention/pages/home/keyTasks/keyTasksDetail/key_taskes_danger_page.dart'; import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; @@ -34,6 +36,7 @@ enum SafeCheckDetailMode { detail, // 详情 } + /// 只读展示版 SafecheckDetailWidget/// 外部负责 push 页面并在页面 pop 时返回可能修改或新增的隐患对象(若无修改返回 null 即可)。 class KeyTaskesDetailWidget extends StatefulWidget { const KeyTaskesDetailWidget({ @@ -69,11 +72,11 @@ class KeyTaskesDetailWidget extends StatefulWidget { final Map? initialInitiator; @override - State createState() => KeyTaskesDetailWidgetState(); + State createState() => keyTaskesDetailWidgetState(); } /// 注意:状态类为公有,外部可以通过 GlobalKey 访问 setDetailData(...) -class KeyTaskesDetailWidgetState extends State { +class keyTaskesDetailWidgetState extends State { // 固定只读 bool _isEdit = false; @@ -122,6 +125,8 @@ class KeyTaskesDetailWidgetState extends State { // 检查来源(4-监管端 5-企业端) }; + bool _showReviewStatus=false; + @override void initState() { super.initState(); @@ -129,10 +134,10 @@ class KeyTaskesDetailWidgetState extends State { _isEdit = false; // 优先:如果外部传了 initialData(完整的 data),直接用它 - if (widget.initialData != null) { - setDetailData(widget.initialData!); - return; - } + // if (widget.initialData != null) { + // setDetailData(widget.initialData!); + // return; + // } // 如果 inspectionId 非空 且 autoFetch 为 true,则组件内部请求接口 if (widget.inspectionId.isNotEmpty && widget.autoFetch) { @@ -151,24 +156,270 @@ class KeyTaskesDetailWidgetState extends State { } } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0, vertical: 12), + child: form.isNotEmpty ? _mainWidget() : SizedBox(), + ); + } + + Widget _mainWidget() { + if (!FormUtils.hasValue(form, 'inspectionId')) { + return SizedBox(height: 500, child: NoDataWidget.show(),); + } + + String subjectShow = form['subject'] ?? ''; + if (widget.handleType == SafeCheckDetailMode.add) { + for (var item in subjectList) { + if (item['bianma'] == form['subject']) { + form['subject'] = item['id']; + subjectShow = item['name'] ?? ''; + break; + } + } + } + bool isPlan = form['planType'] == 1; + + return (widget.handleType == SafeCheckDetailMode.add) || + (widget.handleType == SafeCheckDetailMode.edit && + FormUtils.hasValue(form, 'inspectionId') || + widget.handleType == SafeCheckDetailMode.detail) + ? Column( + children: [ + // ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: _isEdit, + // label: '检查题目', + // isEditable: _isEdit, + // text: '${form['subject'] ?? ''}', + // onTap: () {}, + // ), + // const Divider(), + // ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: _isEdit, + // label: '计划属性', + // isEditable: _isEdit, + // text: isPlan ? '计划内' : '计划外', + // onTap: () {}, + // ), + // if (isPlan) ...[ + // const Divider(), + // ItemListWidget.selectableLineTitleTextRightButton( + // isRequired: _isEdit, + // label: '计划名称', + // isEditable: _isEdit, + // text: form['planName'] ?? '', + // onTap: () {}, + // ), + // ], + // const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: _isEdit, + label: '辖区单位', + isEditable: _isEdit, + text: form['corpName'] ?? '', + onTap: () {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: _isEdit, + label: '被检查单位', + isEditable: _isEdit, + text: form['inspectedCorpinfoName'] ?? '', + onTap: () {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: _isEdit, + label: '被检查单位现场负责人', + isEditable: _isEdit, + text: form['xgfMasterUserName'] ?? '', + onTap: () {}, + ), + + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + isRequired: _isEdit, + label: '重点作业名称', + isEditable: _isEdit, + text: form['projectName'] ?? '', + onTap: () {} + ), + + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '检查类型:', + onTap: () {}, + isEditable: _isEdit, + text: form['typeName'] ?? '', + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '检查开始时间:', + isEditable: _isEdit, + text: form['timeStart'] ?? '', + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '检查结束时间:', + isEditable: _isEdit, + text: form['timeEnd'] ?? '', + onTap: () async {}, + ), + // if (!_isEdit) + // Column( + // children: [ + // const Divider(), + // ItemListWidget.selectableLineTitleTextRightButton( + // label: '记录填写时间:', + // isEditable: _isEdit, + // text: form['createTime'] ?? '', + // ), + // ], + // ), + + const Divider(), + ItemListWidget.singleLineTitleText( + label: '检查场所:', + isEditable: _isEdit, + text: form['place'] ?? '', + hintText: '请输入检查场所', + onChanged: (val) { + // 只读 + }, + ), + + const Divider(), + ItemListWidget.itemContainer( + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ListItemFactory.headerTitle('检查人员'), + // _isEdit == false 时不显示添加按钮 + ], + ), + SizedBox(height: 10), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: inspectorList.length, + itemBuilder: (context, index) { + return _personUnitItem(inspectorList[index], index); + }, + ), + ], + ), + ), + + const Divider(), + MultiTextFieldWithTitle( + label: "检查情况:", + isEditable: _isEdit, + items: situationList, + imageCount: 4, + hintText: "请输入检查情况...", + onItemsChanged: (List> value) { + situationList = value; + }, + ), + + + const Divider(), + ItemListWidget.itemContainer( + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ListItemFactory.headerTitle('发现问题'), + // 添加按钮仅在编辑模式显示(此处不显示) + ], + ), + ], + ), + ), + HiddenListTable( + hiddenList: dangerList, + forbidEdit: _isEdit, + baseImgPath: ApiService.baseImgPath, + personSignImg: '', + personSignTime: '', + showHidden: (item, idx) { + // 打开隐患详情/编辑页的 push 由外部处理 + _openDrawer(item, idx); + }, + removeHidden: (item, idx) { + _delHiddenForm(item, idx); + }, + context: context, + ), + if (widget.handleType == SafeCheckDetailMode.detail) + _detailWidget(), + + SizedBox(height: 15,), + ], + ) + : SizedBox(); + } + + Widget _detailWidget() { + return Column( + children: [ + if (inspectorList.isNotEmpty&&_showReviewStatus) + Column( + children: [ + // const Divider(), + SizedBox(height: 5), + ListItemFactory.createBuildSimpleSection('检查人员审核情况'), + SizedBox(height: 5), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: inspectorList.length, + itemBuilder: (context, index) { + return _personSignItem(inspectorList[index], index); + }, + ), + ], + ), + // if (personUnderInspection.isNotEmpty && FormUtils.hasValue(personUnderInspection, 'signature')) + // Column( + // children: [ + // const Divider(), + // ListItemFactory.createBuildSimpleSection('被检查单位现场负责人确认情况'), + // SizedBox(height: 5), + // _unitSignItem(personUnderInspection) + // + // ], + // ), + ], + ); + } + + /// 公开方法:外部在拿到接口返回的 data 后,直接调用这个方法注入数据 void setDetailData(Map data) { setState(() { form = data; - for (Map subject in subjectList) { - if (subject['bianma'] == form['subject']) { - form['subject'] = subject['name']; - } - } - personUnderInspection = data['inspectedPartyConfirmation'] ?? {}; - inspectorList = data['inspectorVerificationList'] ?? []; - initiator = data['initiator'] ?? {}; - inspectorVerifyList = data['inspectorVerifyList'] ?? []; - toCheckUnitList = data['toCheckUnitList'] ?? []; - situationList = data['content'] ?? []; + // for (Map subject in subjectList) { + // if (subject['bianma'] == form['subject']) { + // form['subject'] = subject['name']; + // } + // } + // personUnderInspection = data['inspectedPartyConfirmation'] ?? {}; + // inspectorList = data['inspectorVerificationList'] ?? []; + // initiator = data['initiator'] ?? {}; + // inspectorVerifyList = data['inspectorVerifyList'] ?? []; + // toCheckUnitList = data['toCheckUnitList'] ?? []; + // situationList = data['content'] ?? []; // 异步填充图片/隐患 _getAllFiles(); - _getDangerList(); + // _getDangerList(); }); } @@ -183,16 +434,24 @@ class KeyTaskesDetailWidgetState extends State { await FileApi.getImagePathWithType( contentId, '', - UploadFileType.safetyEnvironmentalInspectionInspectionSituation, + UploadFileType.keyProjectInitiationImage, ) .then((result) { - final data = result['data']; - final filePath = - (data is List && data.isNotEmpty) - ? data.first['filePath'] ?? '' - : ''; - item['imgPath'] = ApiService.baseImgPath + filePath; + // final data = result['data']; + // final filePath = (data is List && data.isNotEmpty) ? data.first['filePath'] ?? '' : ''; + // item['imgPath'] = ApiService.baseImgPath + filePath; + // situationList[idex] = item; + + List images =[]; + final List data = result['data']; + for(int i=0;i { Future _getDetail() async { try { LoadingDialogHelper.show(); - final result = await SafetyCheckApi.safeCheckDetail(widget.inspectionId); + final result = await KeyTasksApi.getKeyTasksSafetyEnvironmentalInspectionDetail(widget.inspectionId); LoadingDialogHelper.hide(); - if (result != null) { + if (result['success']) { setState(() { final data = result['data']; form = data; - for (Map subject in subjectList) { - if (subject['bianma'] == form['subject']) { - form['subject'] = subject['name']; + + // form['departmentName'] = form['corpName']; + inspectorList=form['inspectionUserList']??[];//检查人列表 + for(int i=0;i { ToastUtil.showNormal(context, '详情获取失败'); } } - /// 获取申辩列表 - Future _getAppealList(String traceId) async { - try { - // final parentPerm = 'dashboard:safety-env-inspection:plea-manage'; - // final targetPerm = ''; - // final menuPath = await RouteService.getMenuPath(parentPerm, targetPerm); - // final result = await SafetyCheckApi.safeCheckAppealList( - // traceId, - // { - // "pageIndex": 1, - // "pageSize": 100, - // "menuPath" : menuPath - // }, - // ); - // if (result != null && result['success']) { - // final dynamic data = result['data']; - // List fetched = []; - // if (data is List) { - // fetched = data; - // } else if (data is Map && data['list'] is List) { - // // 如果后端返回了 { list: [...], total: x } 之类的结构,尝试兼容 - // fetched = data['list']; - // } - // personUnderInspection['content'] = fetched.last['content']; - // - // } - }catch(e){ - } - } - - /// 获取隐患列表 - Future _getDangerList() async { - try { - LoadingDialogHelper.show(); - final data = { - 'foreignKey': form['traceId'], - 'pageSize': 100, - 'pageIndex': 1, - }; - final result = await HiddenDangerApi.getHiddenDangerListByforeignKeyId( - data, - ); - LoadingDialogHelper.hide(); - if (result != null && result['success']) { - setState(() { - dangerList = result['data']; - }); - } else { - ToastUtil.showNormal(context, '获取隐患失败'); - } - } catch (e) { - LoadingDialogHelper.hide(); - ToastUtil.showNormal(context, '获取隐患失败'); - } - } /// 打开隐患 Future _openDrawer(Map hiddenForm, int index) async { // pushPage(HiddenRecordDetailPage(DangerType.ristRecord,7,hiddenForm['id'],hiddenForm['hiddenId'],false), context); + // pushPage(HiddenRecordDetailPage(widget.dangerType,widget.appItem,pageData['id'],pageData['hiddenId'],false), context); + List personList = []; + pushPage( + KeyTaskesDangerPage( + initData: hiddenForm, + inspectionId: widget.inspectionId, + isEdit: _isEdit, + corpId: personUnderInspection['corpId'] ?? '', + personList: personList, + autoSaveTime: 999999999, + ), + context, + ); } Future openCustomDrawer(BuildContext context, Widget child) { @@ -407,6 +640,7 @@ class KeyTaskesDetailWidgetState extends State { children: [ const SizedBox(width: 10), Text('签字时间: ${item['signatureTime'] ?? ''}'), + const SizedBox(width: 10), ], ), ], @@ -484,233 +718,9 @@ class KeyTaskesDetailWidgetState extends State { }); } - Widget _mainWidget() { - if (!FormUtils.hasValue(form, 'inspectionId')) { - return SizedBox(height: 500, child: NoDataWidget.show(),); - } - - String subjectShow = form['subject'] ?? ''; - if (widget.handleType == SafeCheckDetailMode.add) { - for (var item in subjectList) { - if (item['bianma'] == form['subject']) { - form['subject'] = item['id']; - subjectShow = item['name'] ?? ''; - break; - } - } - } - bool isPlan = form['planType'] == 1; - - return (widget.handleType == SafeCheckDetailMode.add) || - (widget.handleType == SafeCheckDetailMode.edit && - FormUtils.hasValue(form, 'inspectionId') || - widget.handleType == SafeCheckDetailMode.detail) - ? Column( - children: [ - // ItemListWidget.selectableLineTitleTextRightButton( - // isRequired: _isEdit, - // label: '检查题目', - // isEditable: _isEdit, - // text: '${form['subject'] ?? ''}', - // onTap: () {}, - // ), - // const Divider(), - // ItemListWidget.selectableLineTitleTextRightButton( - // isRequired: _isEdit, - // label: '计划属性', - // isEditable: _isEdit, - // text: isPlan ? '计划内' : '计划外', - // onTap: () {}, - // ), - // if (isPlan) ...[ - // const Divider(), - // ItemListWidget.selectableLineTitleTextRightButton( - // isRequired: _isEdit, - // label: '计划名称', - // isEditable: _isEdit, - // text: form['planName'] ?? '', - // onTap: () {}, - // ), - // ], - - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - isRequired: _isEdit, - label: '辖区单位', - isEditable: _isEdit, - text: personUnderInspection['departmentName'] ?? '', - onTap: () {}, - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - isRequired: _isEdit, - label: '被检查单位', - isEditable: _isEdit, - text: personUnderInspection['departmentName'] ?? '', - onTap: () {}, - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - isRequired: _isEdit, - label: '被检查单位现场负责人', - isEditable: _isEdit, - text: personUnderInspection['userName'] ?? '', - onTap: () {}, - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '检查类型:', - onTap: () {}, - isEditable: _isEdit, - text: form['typeName'] ?? '', - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '检查开始时间:', - isEditable: _isEdit, - text: form['timeStart'] ?? '', - onTap: () async {}, - ), - const Divider(), - ItemListWidget.selectableLineTitleTextRightButton( - label: '检查结束时间:', - isEditable: _isEdit, - text: form['timeEnd'] ?? '', - onTap: () async {}, - ), - // if (!_isEdit) - // Column( - // children: [ - // const Divider(), - // ItemListWidget.selectableLineTitleTextRightButton( - // label: '记录填写时间:', - // isEditable: _isEdit, - // text: form['createTime'] ?? '', - // ), - // ], - // ), - - const Divider(), - ItemListWidget.singleLineTitleText( - label: '检查场所:', - isEditable: _isEdit, - text: form['place'] ?? '', - hintText: '请输入检查场所', - onChanged: (val) { - // 只读 - }, - ), - - const Divider(), - ItemListWidget.itemContainer( - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('检查人员'), - // _isEdit == false 时不显示添加按钮 - ], - ), - SizedBox(height: 10), - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: inspectorList.length, - itemBuilder: (context, index) { - return _personUnitItem(inspectorList[index], index); - }, - ), - ], - ), - ), - - const Divider(), - MultiTextFieldWithTitle( - label: "检查情况:", - isEditable: _isEdit, - items: situationList, - hintText: "请输入检查情况...", - onItemsChanged: (List> value) { - situationList = value; - }, - ), - const Divider(), - ItemListWidget.itemContainer( - Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ListItemFactory.headerTitle('发现问题'), - // 添加按钮仅在编辑模式显示(此处不显示) - ], - ), - ], - ), - ), - HiddenListTable( - hiddenList: dangerList, - forbidEdit: _isEdit, - baseImgPath: ApiService.baseImgPath, - personSignImg: '', - personSignTime: '', - showHidden: (item, idx) { - // 打开隐患详情/编辑页的 push 由外部处理 - _openDrawer(item, idx); - }, - removeHidden: (item, idx) { - _delHiddenForm(item, idx); - }, - context: context, - ), - if (widget.handleType == SafeCheckDetailMode.detail) - _detailWidget(), - ], - ) - : SizedBox(); - } - Widget _detailWidget() { - return Column( - children: [ - if (inspectorList.isNotEmpty) - Column( - children: [ - const Divider(), - ListItemFactory.createBuildSimpleSection('检查人员审核情况'), - SizedBox(height: 5), - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: inspectorList.length, - itemBuilder: (context, index) { - return _personSignItem(inspectorList[index], index); - }, - ), - ], - ), - if (personUnderInspection.isNotEmpty && FormUtils.hasValue(personUnderInspection, 'signature')) - Column( - children: [ - const Divider(), - ListItemFactory.createBuildSimpleSection('被检查单位现场负责人确认情况'), - SizedBox(height: 5), - _unitSignItem(personUnderInspection) - ], - ), - ], - ); - } - @override - Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12), - child: form.isNotEmpty ? _mainWidget() : SizedBox(), - ); - } } diff --git a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_onlylook_detail_page.dart b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_onlylook_detail_page.dart index 67256c3..f914aa3 100644 --- a/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_onlylook_detail_page.dart +++ b/lib/pages/home/keyTasks/keyTasksDetail/key_taskes_onlylook_detail_page.dart @@ -7,10 +7,11 @@ class KeyTaskesOnlylookDetailPage extends StatefulWidget { const KeyTaskesOnlylookDetailPage({ super.key, required this.inspectionId, + required this.handleType, }); final String inspectionId; - + final SafeCheckDetailMode handleType; @override State createState() => _KeyTaskesOnlylookDetailPageState(); @@ -28,7 +29,7 @@ class _KeyTaskesOnlylookDetailPageState extends State _KeyTasksCheckListPageState(); +} + +class _KeyTasksCheckListPageState extends State { + // 列表数据与分页 + List list = []; + + int currentPage = 1; + int totalPage = 1; + bool isLoading = false; + late var searchData = {}; + + // 步骤列表(用于筛选) + int sindex = 0; // 筛选索引(只有发起模式可见) + String searchKey = ''; + Map flowData = {}; + final GlobalKey _scaffoldKey = GlobalKey(); + final ScrollController _scrollController = ScrollController(); + + + final TextEditingController _searchController = TextEditingController(); + String searchHintText='请输入检查场所'; + + String title=""; + + @override + void initState() { + super.initState(); + + + title='检查发起'; + keyTasksInspectionListData['statusList']=[2]; + + + _fetchData(); + _scrollController.addListener(_onScroll); + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + key: _scaffoldKey, + appBar: MyAppbar( + title: title, + ), + + body: SafeArea( + child: Column( + children: [ + Container( + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(10), + child: SearchBarWidget( + controller: _searchController, + hintText: searchHintText, + showResetButton:true, + onSearch: (keyboard) { + // 输入请求接口 + currentPage=1; + searchKey=keyboard; + _fetchData(); + }, + ), + ), + ), + + const Divider(height: 1), + // List + Expanded(child: _buildListContent()), + ], + ), + ), + ); + } + + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + void _onScroll() { + if (_scrollController.position.pixels >= + _scrollController.position.maxScrollExtent && + !isLoading) { + if (currentPage < totalPage) { + currentPage++; + _fetchData(); + } + } + } + + + + /// 根据当前页面模式返回对应的操作按钮 + List _buildActionButtons(Map item) { + final List buttons = []; + + // 检查人确认:查看、核实 + buttons.addAll([ + CustomButton( + text: '查看', + height: 35, + buttonStyle: ButtonStyleType.secondary, + backgroundColor: Colors.blue, + onPressed: () => _goToDetail(item,SafeCheckDetailMode.detail), + ), + CustomButton( + text: '确认', + height: 35, + backgroundColor: Colors.blue, + onPressed: () => _handleVerify(item), + ), + ]); + + + return buttons; + } + + Widget _buildListItem(Map item) { + final actionButtons = _buildActionButtons(item); + + // 构建一行内均分按钮并在按钮间插入间距 10 + List buttonRowChildren = []; + for (int i = 0; i < actionButtons.length; i++) { + // 将按钮包在 SizedBox 以保证高度一致,同时用 Expanded 占满剩余宽度 + buttonRowChildren.add( + Expanded(child: SizedBox(height: 35, child: actionButtons[i])), + ); + if (i != actionButtons.length - 1) { + buttonRowChildren.add(const SizedBox(width: 10)); + } + } + + return Card( + color: Colors.white, + margin: const EdgeInsets.all(8.0), + child: InkWell( + onTap:() { + + }, + // () => _goToDetail(item), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "${item['subject'] ?? ''}现场安全检查记录", + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + ], + ), + Text("检查发起人: ${item['corpName'] ?? ''}"), + Text("检查类型: ${item['typeName'] ?? ''}"), + Text("被检查单位: ${item['inspectedCorpinfoName'] ?? ''}"), + Text("被检查单位现场负责人: ${item['xgfMasterUserName'] ?? ''}"), + Text( + "检查时间: 自${item['timeStart'] ?? ''}至${item['timeEnd'] ?? ''}", + ), + Text("发现隐患数: ${item['hiddenNumber'] ?? ''}"), + Text("检查状态: ${_checkStatusWithId(item)}"), + + ], + ), + + const SizedBox(height: 8), + // 按钮行:如果只有一个按钮,不需要间距;多个按钮均分占满行,间距为 10 + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: buttonRowChildren, + ), + ], + ), + ), + ), + ); + } + + Widget _buildListContent() { + if (isLoading && list.isEmpty) { + return const Center(child: CircularProgressIndicator()); + } else if (list.isEmpty) { + return NoDataWidget.show(); + } else { + return ListView.builder( + padding: EdgeInsets.zero, + controller: _scrollController, + itemCount: list.length + (isLoading ? 1 : 0), + itemBuilder: (context, index) { + if (index >= list.length) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Center(child: CircularProgressIndicator()), + ); + } + return _buildListItem(list[index]); + }, + ); + } + } + + + + /// 跳转到详情 + Future _goToDetail( item ,SafeCheckDetailMode type,) async { + // if (type == SafeCheckDetailMode.detail) { + await pushPage( + KeyTaskesOnlylookDetailPage(inspectionId: item['inspectionId'] ?? '', handleType: type), + context, + ); + // 完成后刷新列表 + currentPage = 1; + _fetchData(); + // } else { + // + // await pushPage( + // KeyTasksStartDetail( + // inspectionId: item['inspectionId'] ?? '', + // type: SafeCheckMode.Initiate, + // handleType: type, + // isInPlan: false, + // isAutoSave: true, + // ), + // context, + // ); + // // 完成后刷新列表 + // currentPage = 1; + // _fetchData(); + // } + + } + + + + /// 确认 + Future _handleVerify(Map item) async { + await pushPage( + KeyTaskesCheckConfirmPage( + id: item['id'] ?? '', + inspectionId: item['inspectionId'] ?? '', + handleType: SafeCheckDetailMode.detail, + ), + context, + ); + _fetchData(); + } + + + + + + String _checkStatusWithId(item) { + //状态 (0-暂存,1-待核实,2-待确认,3-待隐患整改,4-待隐患验收,5-检查归档,6-核实打回,7-被检查申辩) + String typeName=''; + int type=item['status']??10; + switch(type){ + case 0: + typeName='暂存'; + break; + case 1: + typeName='待核实'; + break; + case 2: + typeName='待确认'; + break; + case 3: + typeName='待隐患整改'; + break; + case 4: + typeName='待隐患验收'; + break; + case 5: + typeName='检查归档'; + break; + case 6: + typeName='核实打回'; + break; + case 7: + typeName='被检查申辩'; + break; + } + return typeName; + } + + /// 状态 + static List> getStepList() { + List> stepList = [ + {'id': '200', 'name': '待核实'}, + {'id': '300', 'name': '待确认'}, + {'id': '301', 'name': '待指派'}, + {'id': '400', 'name': '待验收'}, + {'id': '500', 'name': '检查归档'}, + {'id': '600', 'name': '检查核实打回'}, + {'id': '700', 'name': '被检查人申辩'}, + ]; + return stepList; + } + + + + Future _fetchData() async { + if (isLoading) return; + setState(() => isLoading = true); + + try { + keyTasksInspectionListData['pageIndex']=currentPage; + keyTasksInspectionListData['place']=searchKey; + + final response = await KeyTasksApi.getKeyTasksSafetyEnvironmentalInspectionList(keyTasksInspectionListData); + + if(response['success']){ + setState(() { + final newData = response['data'] as List? ?? []; + if (currentPage == 1) { + list = newData; + } else { + list.addAll(newData); + } + totalPage = response['totalPages'] ?? 1; + isLoading = false; + }); + } + } catch (e) { + debugPrint('Error fetching data: $e'); + setState(() => isLoading = false); + ToastUtil.showNormal(context, '获取列表失败'); + } + } + + Map keyTasksInspectionListData={ + "place": "", + "createName": "", + "inspectionDepartmentId": "", + "timeStart": "", + "timeEnd": "", + "inspectedCorpinfoName": "", + "projectName": "", + "inspectionUserName": "", + "statusList": [], + "year":"", + "pageSize": 20, + "pageIndex": 1 + }; + + +} + + diff --git a/lib/pages/home/keyTasks/key_tasks_tab_page.dart b/lib/pages/home/keyTasks/key_tasks_tab_page.dart index 07c9659..b75c9a2 100644 --- a/lib/pages/home/keyTasks/key_tasks_tab_page.dart +++ b/lib/pages/home/keyTasks/key_tasks_tab_page.dart @@ -3,6 +3,7 @@ import 'dart:ffi'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/pages/home/doorAndCar/doorCar_tab_page.dart'; +import 'package:qhd_prevention/pages/home/keyTasks/key_tasks_check_list_page.dart'; import 'package:qhd_prevention/pages/home/keyTasks/key_tasks_confirm_list_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; import 'package:qhd_prevention/tools/tools.dart'; @@ -50,7 +51,7 @@ class _DoorcarTabPageState extends State { icon: 'assets/images/door_ico9.png', badge: 0, onTap: () async { - // await pushPage(KeyTasksCheckListPage(1, widget.isLoginJGD), context); + await pushPage(KeyTasksCheckListPage(), context); _getDoorCarCount(); }, ), diff --git a/lib/services/SessionService.dart b/lib/services/SessionService.dart index f1add70..abc8ac1 100644 --- a/lib/services/SessionService.dart +++ b/lib/services/SessionService.dart @@ -262,6 +262,7 @@ class SessionService { // 自加字段 String? loginPhone; String? loginPass; + String? hiddenJson= "{confirm:1,rectify:1,check:1,special:1,extension:1,}"; // 内部:Prefs key static const String _prefsKey = 'session_service_v2'; diff --git a/lib/tools/MultiTextFieldWithTitle.dart b/lib/tools/MultiTextFieldWithTitle.dart index 51edd94..a2d8747 100644 --- a/lib/tools/MultiTextFieldWithTitle.dart +++ b/lib/tools/MultiTextFieldWithTitle.dart @@ -6,6 +6,7 @@ import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/customWidget/dotted_border_box.dart'; import 'package:qhd_prevention/customWidget/photo_picker_row.dart'; import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; +import 'package:qhd_prevention/customWidget/single_images_viewer.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:qhd_prevention/tools/tools.dart'; @@ -26,6 +27,7 @@ class MultiTextFieldWithTitle extends StatefulWidget { final double fontSize; final bool isRequired; final bool isDeletFirst; + final int imageCount; final OperationType operationType; final ValueChanged>> onItemsChanged; @@ -41,6 +43,7 @@ class MultiTextFieldWithTitle extends StatefulWidget { this.isRequired = true, this.isAddImage = true, this.isDeletFirst = false, + this.imageCount = 1, this.operationType = OperationType.check, }); @@ -320,11 +323,11 @@ class _MultiTextFieldWithTitleState extends State { final text = _controllers[index].text; final imageList = _getImageListForIndex(index); final itemTitle = - widget.operationType == OperationType.check - ? '检查情况${index + 1}' - : '其他安全措施${index + 1}'; + widget.operationType == OperationType.check + ? '检查情况${index + 1}' + : '其他安全措施${index + 1}'; return Container( - margin: const EdgeInsets.only(bottom: 16), + margin: const EdgeInsets.only(bottom: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -363,27 +366,27 @@ class _MultiTextFieldWithTitleState extends State { width: double.maxFinite, child: DottedBorderBox( child: - widget.isEditable - ? TextField( - controller: _controllers[index], - decoration: InputDecoration( - hintText: widget.hintText, - ), - focusNode: _focusNodes[index], - keyboardType: TextInputType.multiline, - maxLines: 3, - style: TextStyle(fontSize: widget.fontSize), - ) - : Padding( - padding: const EdgeInsets.all(12), - child: Text( - text.isEmpty ? '暂无内容' : text, - style: TextStyle( - fontSize: widget.fontSize, - color: text.isEmpty ? Colors.grey : Colors.black, - ), - ), - ), + widget.isEditable + ? TextField( + controller: _controllers[index], + decoration: InputDecoration( + hintText: widget.hintText, + ), + focusNode: _focusNodes[index], + keyboardType: TextInputType.multiline, + maxLines: 3, + style: TextStyle(fontSize: widget.fontSize), + ) + : Padding( + padding: const EdgeInsets.all(12), + child: Text( + text.isEmpty ? '暂无内容' : text, + style: TextStyle( + fontSize: widget.fontSize, + color: text.isEmpty ? Colors.grey : Colors.black, + ), + ), + ), ), ), ), @@ -392,7 +395,7 @@ class _MultiTextFieldWithTitleState extends State { if (widget.isEditable && widget.isAddImage) RepairedPhotoSection( title: '图片', - maxCount: 1, + maxCount: widget.imageCount, isEdit: widget.isEditable, followInitialUpdates: true, // 关键:只传当前条目的图片数组 @@ -432,8 +435,12 @@ class _MultiTextFieldWithTitleState extends State { ), // 非编辑态显示只读图片 - if (!widget.isEditable && imageList.isNotEmpty) + if (!widget.isEditable && imageList.isNotEmpty&&widget.imageCount==1) _buildReadOnlyImage(imageList.first), + + if (!widget.isEditable && imageList.isNotEmpty&&widget.imageCount==4) + _buildReadOnlyFourImage(imageList), + ], ), ); @@ -475,6 +482,67 @@ class _MultiTextFieldWithTitleState extends State { ); } + Widget _buildReadOnlyFourImage( imagePath) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 7), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + Text( + '图片:', + style: TextStyle( + fontSize: widget.fontSize - 1, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 10), + Wrap( + spacing: 8, // 水平间距 + runSpacing: 8, // 垂直间距 + children: List.generate(imagePath.length, (i) { + final url = ApiService.baseImgPath + imagePath[i]; + Widget img; + if (url.startsWith('http')) { + img = Image.network( + url, + height: 90, + width: 90 , + fit: BoxFit.fill, + ); + } else { + img = Image.asset( + url, + height: 90, + width: 90 , + fit: BoxFit.fill, + ); + } + return GestureDetector( + onTap: () { + presentOpaque( + SingleImagesViewer( + imageUrl: '', + imageUrls: imagePath, + initialIndex: i, + ), + context, + ); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: img, + ), + ); + }), + ), + + + ], + ), + ); + } + ImageProvider _getImageProvider(String imagePath) { if (imagePath.startsWith('http')) { return NetworkImage(imagePath);