2026.4.15 重点作业
parent
627ef2201f
commit
9376cb6acd
Binary file not shown.
|
After Width: | Height: | Size: 235 B |
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String>? imageUrls;
|
||||
/// 可选:初始显示页(默认 0)
|
||||
final int initialIndex;
|
||||
|
||||
const SingleImagesViewer({
|
||||
Key? key,
|
||||
required this.imageUrl,
|
||||
this.imageUrls,
|
||||
this.initialIndex = 0,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SingleImagesViewer> createState() => _SingleImagesViewerState();
|
||||
}
|
||||
|
||||
class _SingleImagesViewerState extends State<SingleImagesViewer> {
|
||||
late final List<String> _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),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,4 +56,43 @@ class KeyTasksApi {
|
|||
}
|
||||
|
||||
|
||||
/// 安全环保检查分页
|
||||
static Future<Map<String, dynamic>> getKeyTasksSafetyEnvironmentalInspectionList(Map data) {
|
||||
return HttpManager().request(
|
||||
'${ApiService.basePath}/keyProject',
|
||||
'/safetyEnvironmentalInspection/list',
|
||||
method: Method.post,
|
||||
data: {
|
||||
...data
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 安全环保检查详情.
|
||||
static Future<Map<String, dynamic>> getKeyTasksSafetyEnvironmentalInspectionDetail(String id) {
|
||||
return HttpManager().request(
|
||||
'${ApiService.basePath}/keyProject',
|
||||
'/safetyEnvironmentalInspection/$id',
|
||||
method: Method.get,
|
||||
data: {
|
||||
// ...data
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// 安全环保检查确认
|
||||
static Future<Map<String, dynamic>> setKeyTasksCheckConfirm(Map data) {
|
||||
return HttpManager().request(
|
||||
'${ApiService.basePath}/keyProject',
|
||||
'/safetyEnvironmentalInspectionDefend/affirm',
|
||||
method: Method.post,
|
||||
data: {
|
||||
...data
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<KeyTaskesCheckConfirmPage> createState() => _KeyTaskesCheckConfirmPageState();
|
||||
}
|
||||
|
||||
class _KeyTaskesCheckConfirmPageState extends State<KeyTaskesCheckConfirmPage> {
|
||||
bool _isEdit = false; // 禁止修改
|
||||
/// 被检查单位相关信息
|
||||
Map<String, dynamic> personUnderInspection = {
|
||||
'departmentId': '',
|
||||
'departmentName': '',
|
||||
'userName': '',
|
||||
'userId': '',
|
||||
};
|
||||
|
||||
// 被检查确认的人员
|
||||
late Map inspectedPartyConfirmation = {};
|
||||
|
||||
List<String> signImages = [];
|
||||
List<String> 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<SelectedFile> 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<Widget> buttons = [];
|
||||
final List<Widget> 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<void> _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<void> _sign() async {
|
||||
await NativeOrientation.setLandscape();
|
||||
final path = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => MineSignPage()),
|
||||
);
|
||||
await NativeOrientation.setPortrait();
|
||||
if (path != null) {
|
||||
final now = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
|
||||
setState(() {
|
||||
signImages = [];
|
||||
signTimes = [];
|
||||
signImages.add(path);
|
||||
signTimes.add(now);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 检查人核实提交
|
||||
Future<void> _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<bool> _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<bool> _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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<KeyTaskesDangerPage> createState() => _KeyTaskesDangerPageState();
|
||||
}
|
||||
|
||||
class _KeyTaskesDangerPageState extends State<KeyTaskesDangerPage> {
|
||||
/// 隐患确认人
|
||||
Map<String, dynamic> 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<dynamic> _HazardPersonlist = [];
|
||||
|
||||
/// 隐患确认人信息
|
||||
Map _hazarder = {};
|
||||
|
||||
// 存储各单位的人员列表
|
||||
List<Map<String, dynamic>> _personCache = [];
|
||||
|
||||
List<String> _dangerImages = [];
|
||||
List<String> _dangerVideos = [];
|
||||
List<Map> _initFileList = [];
|
||||
List<String> _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<void> _getHazardPersonlist() async {
|
||||
try {
|
||||
LoadingDialogHelper.show();
|
||||
final raw = await HiddenDangerApi.getHazardPersonlist();
|
||||
if (raw['success']) {
|
||||
setState(() {
|
||||
_HazardPersonlist = raw['data'] as List<dynamic>;
|
||||
print(_HazardPersonlist);
|
||||
});
|
||||
LoadingDialogHelper.hide();
|
||||
} else {
|
||||
ToastUtil.showNormal(context, "获取列表失败");
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载首页数据失败:$e');
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _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<void> _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<void> _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<void> _getDiscoverPersonList() async {
|
||||
String choice = await BottomPickerTwo.show<String>(
|
||||
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<File> 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<File> 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<Map<String, dynamic>>.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<String> 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<String> 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<int> initialIndices = [];
|
||||
for (final selectedItem in selectedList) {
|
||||
final int index = result.indexOf(selectedItem);
|
||||
if (index != -1) {
|
||||
initialIndices.add(index);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示选择器
|
||||
final selectedItems = await CenterMultiPicker.show<String>(
|
||||
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<dynamic> 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<void> _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<String> 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<void> _identifyImg(String imagePath) async {
|
||||
try {} catch (e) {
|
||||
// 出错时可以 Toast 或者在页面上显示错误状态
|
||||
print('加载首页数据失败:$e');
|
||||
// return "";
|
||||
LoadingDialogHelper.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Future<void> _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<void> _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<void> _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<void> _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,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<String, dynamic>? initialInitiator;
|
||||
|
||||
@override
|
||||
State<KeyTaskesDetailWidget> createState() => KeyTaskesDetailWidgetState();
|
||||
State<KeyTaskesDetailWidget> createState() => keyTaskesDetailWidgetState();
|
||||
}
|
||||
|
||||
/// 注意:状态类为公有,外部可以通过 GlobalKey<SafecheckDetailWidgetState> 访问 setDetailData(...)
|
||||
class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
||||
class keyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
||||
// 固定只读
|
||||
bool _isEdit = false;
|
||||
|
||||
|
|
@ -122,6 +125,8 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
// 检查来源(4-监管端 5-企业端)
|
||||
};
|
||||
|
||||
bool _showReviewStatus=false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
|
@ -129,10 +134,10 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
_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<KeyTaskesDetailWidget> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@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<Map<String, dynamic>> 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<String, dynamic> 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<KeyTaskesDetailWidget> {
|
|||
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<String> images =[];
|
||||
final List<dynamic> data = result['data'];
|
||||
for(int i=0;i<data.length;i++){
|
||||
final filePath = data[i]['filePath'] ?? '';
|
||||
images.add( filePath);
|
||||
}
|
||||
item['imgPaths']=images;
|
||||
situationList[idex] = item;
|
||||
|
||||
|
||||
})
|
||||
.catchError((_) {
|
||||
// 单项失败不影响整体
|
||||
|
|
@ -206,26 +465,42 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
Future<void> _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<inspectorList.length;i++){
|
||||
inspectorList[i]['userName']=inspectorList[i]['name'];
|
||||
if (FormUtils.hasValue(inspectorList[i], 'signature')){
|
||||
_showReviewStatus=true;
|
||||
}
|
||||
}
|
||||
personUnderInspection = data['inspectedPartyConfirmation'] ?? {};
|
||||
inspectorList = data['inspectorVerificationList'] ?? [];
|
||||
initiator = data['initiator'] ?? {};
|
||||
inspectorVerifyList = data['inspectorVerifyList'] ?? [];
|
||||
toCheckUnitList = data['toCheckUnitList'] ?? [];
|
||||
situationList = data['content'] ?? [];
|
||||
situationList=form['inspectionContentList']??[];//检查项列表
|
||||
dangerList=form['hiddenList']??[];
|
||||
_getAllFiles();
|
||||
_getDangerList();
|
||||
_getAppealList(form['traceId'] ??'');
|
||||
|
||||
|
||||
|
||||
|
||||
// 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();
|
||||
// _getAppealList(form['traceId'] ??'');
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -233,66 +508,24 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
ToastUtil.showNormal(context, '详情获取失败');
|
||||
}
|
||||
}
|
||||
/// 获取申辩列表
|
||||
Future<void> _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<void> _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<void> _openDrawer(Map<String, dynamic> 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<T?> openCustomDrawer<T>(BuildContext context, Widget child) {
|
||||
|
|
@ -407,6 +640,7 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
children: [
|
||||
const SizedBox(width: 10),
|
||||
Text('签字时间: ${item['signatureTime'] ?? ''}'),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
@ -484,233 +718,9 @@ class KeyTaskesDetailWidgetState extends State<KeyTaskesDetailWidget> {
|
|||
});
|
||||
}
|
||||
|
||||
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<Map<String, dynamic>> 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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<KeyTaskesOnlylookDetailPage> createState() => _KeyTaskesOnlylookDetailPageState();
|
||||
|
|
@ -28,7 +29,7 @@ class _KeyTaskesOnlylookDetailPageState extends State<KeyTaskesOnlylookDetailPag
|
|||
color: Colors.white,
|
||||
child: KeyTaskesDetailWidget(
|
||||
inspectionId: widget.inspectionId,
|
||||
handleType: SafeCheckDetailMode.detail,
|
||||
handleType: widget.handleType,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,387 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:qhd_prevention/common/route_model.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
|
||||
import 'package:qhd_prevention/customWidget/item_list_widget.dart';
|
||||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||||
import 'package:qhd_prevention/http/modules/doorAndCar_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_check_confirm_page.dart';
|
||||
import 'package:qhd_prevention/pages/home/keyTasks/keyTasksDetail/key_taskes_detail_widget.dart';
|
||||
import 'package:qhd_prevention/pages/home/keyTasks/keyTasksDetail/key_taskes_onlylook_detail_page.dart';
|
||||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||||
import 'package:qhd_prevention/tools/tools.dart';
|
||||
import 'package:qhd_prevention/customWidget/bottom_picker.dart';
|
||||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||||
import 'package:qhd_prevention/customWidget/search_bar_widget.dart';
|
||||
import 'package:qhd_prevention/common/route_service.dart';
|
||||
|
||||
|
||||
class KeyTasksCheckListPage extends StatefulWidget {
|
||||
const KeyTasksCheckListPage( {Key? key,}) : super(key: key);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
_KeyTasksCheckListPageState createState() => _KeyTasksCheckListPageState();
|
||||
}
|
||||
|
||||
class _KeyTasksCheckListPageState extends State<KeyTasksCheckListPage> {
|
||||
// 列表数据与分页
|
||||
List<dynamic> list = [];
|
||||
|
||||
int currentPage = 1;
|
||||
int totalPage = 1;
|
||||
bool isLoading = false;
|
||||
late var searchData = {};
|
||||
|
||||
// 步骤列表(用于筛选)
|
||||
int sindex = 0; // 筛选索引(只有发起模式可见)
|
||||
String searchKey = '';
|
||||
Map flowData = {};
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
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<Widget> _buildActionButtons(Map<String, dynamic> item) {
|
||||
final List<Widget> 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<String, dynamic> item) {
|
||||
final actionButtons = _buildActionButtons(item);
|
||||
|
||||
// 构建一行内均分按钮并在按钮间插入间距 10
|
||||
List<Widget> 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<void> _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<void> _handleVerify(Map<String, dynamic> 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<Map<String, dynamic>> getStepList() {
|
||||
List<Map<String, dynamic>> 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<void> _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<dynamic>? ?? [];
|
||||
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<String, dynamic> keyTasksInspectionListData={
|
||||
"place": "",
|
||||
"createName": "",
|
||||
"inspectionDepartmentId": "",
|
||||
"timeStart": "",
|
||||
"timeEnd": "",
|
||||
"inspectedCorpinfoName": "",
|
||||
"projectName": "",
|
||||
"inspectionUserName": "",
|
||||
"statusList": [],
|
||||
"year":"",
|
||||
"pageSize": 20,
|
||||
"pageIndex": 1
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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<KeyTasksTabPage> {
|
|||
icon: 'assets/images/door_ico9.png',
|
||||
badge: 0,
|
||||
onTap: () async {
|
||||
// await pushPage(KeyTasksCheckListPage(1, widget.isLoginJGD), context);
|
||||
await pushPage(KeyTasksCheckListPage(), context);
|
||||
_getDoorCarCount();
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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<List<Map<String, dynamic>>> 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,
|
||||
});
|
||||
|
||||
|
|
@ -324,7 +327,7 @@ class _MultiTextFieldWithTitleState extends State<MultiTextFieldWithTitle> {
|
|||
? '检查情况${index + 1}'
|
||||
: '其他安全措施${index + 1}';
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
margin: const EdgeInsets.only(bottom: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -392,7 +395,7 @@ class _MultiTextFieldWithTitleState extends State<MultiTextFieldWithTitle> {
|
|||
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<MultiTextFieldWithTitle> {
|
|||
),
|
||||
|
||||
// 非编辑态显示只读图片
|
||||
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<MultiTextFieldWithTitle> {
|
|||
);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue