diff --git a/assets/images/door_banner.png b/assets/images/door_banner.png new file mode 100644 index 0000000..5d5e4b3 Binary files /dev/null and b/assets/images/door_banner.png differ diff --git a/assets/images/door_ico10.png b/assets/images/door_ico10.png new file mode 100644 index 0000000..a1d07e6 Binary files /dev/null and b/assets/images/door_ico10.png differ diff --git a/assets/images/door_ico9.png b/assets/images/door_ico9.png new file mode 100644 index 0000000..64b3934 Binary files /dev/null and b/assets/images/door_ico9.png differ diff --git a/lib/customWidget/item_list_widget.dart b/lib/customWidget/item_list_widget.dart index d9a725a..7f9154d 100644 --- a/lib/customWidget/item_list_widget.dart +++ b/lib/customWidget/item_list_widget.dart @@ -910,11 +910,13 @@ class ItemListWidget { bool isRequired = false, String text = '', void Function(String)? onTapCallBack, + double verticalInset = vertical_inset, + double horizontalInset = horizontal_inset, }) { return Container( - padding: const EdgeInsets.symmetric( - vertical: vertical_inset, - horizontal: horizontal_inset, + padding: EdgeInsets.symmetric( + vertical: verticalInset, + horizontal: horizontalInset, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -994,6 +996,8 @@ class ItemListWidget { double fontSize = 14, // 字体大小 void Function(String)? onTapCallBack, bool isRequired = true, + double verticalInset = vertical_inset, + double horizontalInset = horizontal_inset, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -1002,9 +1006,9 @@ class ItemListWidget { // 标题部分 if (title.isNotEmpty) Padding( - padding: const EdgeInsets.symmetric( - vertical: vertical_inset, - horizontal: horizontal_inset, + padding: EdgeInsets.symmetric( + vertical: verticalInset, + horizontal: horizontalInset, ), child: Text( title, @@ -1263,11 +1267,13 @@ class ItemListWidget { required String text, // 显示内容或提示 double fontSize = 14, // 字体大小 bool isRequired = true, + double verticalInset = vertical_inset, + double horizontalInset = horizontal_inset, }) { return Container( - padding: const EdgeInsets.symmetric( - vertical: vertical_inset, - horizontal: horizontal_inset, + padding: EdgeInsets.symmetric( + vertical: verticalInset, + horizontal: horizontalInset, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/home/doorAndCar/car/doorArea_car_add_page.dart b/lib/pages/home/doorAndCar/car/doorArea_car_add_page.dart new file mode 100644 index 0000000..3f38319 --- /dev/null +++ b/lib/pages/home/doorAndCar/car/doorArea_car_add_page.dart @@ -0,0 +1,559 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/bottom_picker.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/customWidget/photo_picker_row.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/basic_info_api.dart'; + +import 'package:qhd_prevention/pages/home/doorAndCar/sign_instructions_webView.dart'; +import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; +import 'package:qhd_prevention/pages/mine/webViewPage.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/services/SessionService.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:flutter/gestures.dart'; + +class DoorareaCarAddPage extends StatefulWidget { + const DoorareaCarAddPage({super.key}); + + @override + State createState() => _DoorareaCarAddPageState(); +} + +class _DoorareaCarAddPageState extends State { + Map pd = {}; + bool _agreed = false; + + // 部门列表 + List _deptList = []; + List _personList = []; + List signImages = []; + + late bool _isMyCompanyArea = false; + late bool _isSelectCar = false; + + + List _vehicleImages = []; + List _vehicleLicenseImages = []; + + @override + void initState() { + super.initState(); + _getDept(); + } + + // 获取部门 + Future _getDept() async { + // try { + // final data = { + // 'eqCorpinfoId': widget.scanData['id'], + // // 'eqParentId': widget.scanData['corpinfoId'], + // }; + // final result = await BasicInfoApi.getDeptTree(data); + // if (result['success'] == true) { + // final list = result['data'] ?? []; + // if (list.length > 0) { + // setState(() { + // _deptList = list[0]['childrenList'] ?? []; + // }); + // } + // } + // } catch (e) {} + } + + // 提交 + Future _saveSuccess() async { + if (!FormUtils.hasValue(pd, 'corpinfoId')) { + ToastUtil.showNormal(context, '请选择部门'); + return; + } + if (!FormUtils.hasValue(pd, 'postName')) { + ToastUtil.showNormal(context, '请输入岗位'); + return; + } + // try { + // final result = await BasicInfoApi.userFirmEntry(pd); + // LoadingDialogHelper.hide(); + // if (result['success'] == true) { + // ToastUtil.showNormal(context, '申请成功'); + // _relogin(); + // } else { + // ToastUtil.showNormal(context, result['errMessage']); + // } + // } catch (e) { + // LoadingDialogHelper.hide(); + // ToastUtil.showNormal(context, '操作失败,请重试'); + // } + } + + Widget _addPersonWight(Map personData) { + return Stack( + children: [ + Padding(padding: const EdgeInsets.only(top: 5),child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12), + // padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + // 边框 + border: Border.all( + color: Colors.grey.shade300, + width: 1.0, + style: BorderStyle.solid, + ), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + children: [ + const SizedBox(height: 10), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择部门:', + isEditable: true, + text: personData['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择人员:', + isEditable: true, + text: personData['postName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.itemContainer(RepairedPhotoSection( + isRequired: true, + title: "人员照片", + maxCount: 1, + horizontalPadding: 0, + mediaType: MediaType.image, + isShowAI: false, + onChanged: (List files) {}, + onAiIdentify: () {}, + ),), + const SizedBox(height: 10) + ], + ) + ),), + Positioned( + top: 0, + right: 2, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + + child: GestureDetector( + child: const Icon(Icons.close, size: 14, color: Colors.white,), + onTap: () { + setState(() { + _personList.remove(personData); + }); + }, + ), + ), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '车辆申请'), + body: SafeArea( + child: ItemListWidget.itemContainer( + horizontal: 5, + vertical: 12, + ListView( + children: [ + + + ListItemFactory.createBuildSimpleSection('申请信息'), + + + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择管辖单位:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async { + if (_deptList.isEmpty) { + ToastUtil.showNormal(context, '暂无部门信息'); + return; + } + final found = await BottomPicker.show( + context, + items: _deptList, + itemBuilder: + (i) => Text(i['name']!, textAlign: TextAlign.center), + initialIndex: 0, + ); + //FocusHelper.clearFocus(context); + + if (found != null) { + setState(() { + pd['departmentId'] = found['id']; + pd['departmentName'] = found['name']; + pd['corpinfoId'] = found['corpinfoId']; + pd['corpinfoName'] = found['corpinfoName']; + }); + } + }, + ), + + + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择管辖区域:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择项目:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择时间:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.multiLineTitleTextField( + label: '申请原因', + isEditable: true, + ), + + + + + ///车辆信息 + ListItemFactory.createBuildSimpleSection('车辆信息'), + + const Divider(), + + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: ItemListWidget.selectableLineTitleTextRightButton( + label: '驾驶人部门', + isEditable: !_isSelectCar, + onTap: () { + + }, + text: '', + ), + ), + const Divider(height: 1,), + + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: ItemListWidget.selectableLineTitleTextRightButton( + label: '驾驶人', + isEditable: !_isSelectCar, + onTap: () { + + }, + text: '', + ), + ), + const Divider(height: 1,), + + + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌类型', + isEditable: !_isSelectCar, + onTap: () { + + }, + text: '', + ), + ), + + const Divider(height: 1,), + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: ItemListWidget.selectableLineTitleTextRightButton( + label: '车辆类型', + isEditable: !_isSelectCar, + onTap: () { + + }, + text: '', + ), + ), + + const Divider(height: 1,), + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌号', + isEditable: !_isSelectCar, + onTap: () { + + }, + text: '', + ), + ), + // ItemListWidget.singleLineTitleText( + // label: '车牌号', + // isEditable: !_isSelectCar, + // text: '', + // onChanged: (value) { + // + // }, + // ), + + + const Divider(), + Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: RepairedPhotoSection( + isRequired:true, + title: "车辆照片", + maxCount: 4, + mediaType: MediaType.image, + isShowAI: false, + onChanged: (List files) { + // 上传图片 files + _vehicleImages.clear(); + for(int i=0;i files) { + // 上传图片 files + _vehicleLicenseImages.clear(); + for(int i=0;i SignInstructionsWebview( + name: "安全进港须知", + url: + 'http://47.92.102.56:7811/file/xieyi/zsyhxy.htm', + )), + ); + await NativeOrientation.setPortrait(); + if (path != null) { + setState(() { + setState(() { + _agreed = true; + signImages = []; + signImages.add(path); + }); + }); + } + + // pushPage( + // const SignInstructionsWebview( + // name: "安全进港须知", + // url: + // 'http://47.92.102.56:7811/file/xieyi/zsyhxy.htm', + // ), + // context, + // ); + }, + ), + ], + ), + ), + ), + ], + ), + + + // Container( + // padding: EdgeInsets.symmetric(horizontal: 12), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // ListItemFactory.headerTitle('签字:', isRequired: true), + // CustomButton( + // text: signImages.isNotEmpty ? '重新签字' : '手写签字', + // height: 36, + // backgroundColor: Colors.blue, + // onPressed: _sign, + // ), + // ], + // ), + // ), + if (signImages.isNotEmpty) _signListWidget(), + + SizedBox(height: 10,), + + CustomButton( + text: '提交申请', + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), + height: 40, + backgroundColor: Colors.blue, + onPressed: () { + _saveSuccess(); + }, + ), + ], + ), + ), + ), + ); + } + + + + 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(), + ); + } + + + + + +} diff --git a/lib/pages/home/doorAndCar/car/onlyLook_car_application.dart b/lib/pages/home/doorAndCar/car/onlyLook_car_application.dart new file mode 100644 index 0000000..5d0efb8 --- /dev/null +++ b/lib/pages/home/doorAndCar/car/onlyLook_car_application.dart @@ -0,0 +1,320 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.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/ApiService.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class CarApplicationRecord extends StatefulWidget { + const CarApplicationRecord(this.type, {super.key}); + + final int type;//1 一级口门人员审核 2 一级口门车辆审核 3 审批记录(人员) 4 审批记录(车辆) + + @override + State createState() => _CarApplicationRecordState(); +} + +class _CarApplicationRecordState extends State { + // 申请信息数据 + final Map applicationInfo = { + 'mingcheng': '项目名称', + 'bumen': '审核人员部门', + 'renyuan': '审核人员', + 'shijian': '2024-01-01 至 2024-12-31', + 'gangqu': '访问港区', + 'diqu': '访问地区', + }; + + // 车辆信息数据 + final Map vehicleInfo = { + 'name': '驾驶人姓名', + 'type': '车辆类型', + 'licenseType': '车牌号类型', + 'license': '车牌号',}; + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '车辆审核记录'), + body: + Container( + color: Colors.white, + child: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 申请信息标题 + _buildSectionTitle('申请信息'), + SizedBox(height: 12), + + // 申请信息卡片 + _buildInfoCard(applicationInfo), + SizedBox(height: 24), + + // 车辆信息标题 + _buildSectionTitle('车辆信息'), + SizedBox(height: 12), + + // 车辆信息卡片 + _buildCarCard(vehicleInfo), + SizedBox(height: 16), + + + // SizedBox(height: 10), + + // 底部按钮 + if(widget.type==2) + _buildActionButtons(), + + if(widget.type==4) + CustomButton( + height: 35, + onPressed: () { + Navigator.of(context).pop(); + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle: ButtonStyleType.primary, + text: '关闭') + + ], + ), + ), + ), + + ); + } + + Widget _buildSectionTitle(String title) { + return Text( + title, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ); + } + + Widget _buildInfoCard(info) { + return Padding( + padding: EdgeInsets.only(top: 0), + child: Column( + children: [ + + ItemListWidget.selectableLineTitleTextRightButton( + label: '项目名称:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['mingcheng'] ?? '', + onTap: () {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '访问港区:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['gangqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '区域范围:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['diqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['bumen'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['renyuan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '所属项目:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['mingcheng'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择时间:', + isEditable: false, + horizontalnum: 0, + text: applicationInfo['shijian'] ?? '', + onTap: () {}, + ), + const Divider(), + + ], + ), + + ); + } + + Widget _buildCarCard(info) { + return Padding( + padding: EdgeInsets.only(top: 0), + child: Column( + children: [ + + ItemListWidget.selectableLineTitleTextRightButton( + label: '驾驶人姓名:', + isEditable: false, + horizontalnum: 0, + text: info['name'] ?? '', + onTap: () {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '车辆类型:', + isEditable: false, + horizontalnum: 0, + text: info['type'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌号类型:', + isEditable: false, + horizontalnum: 0, + text: info['licenseType'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌号:', + isEditable: false, + horizontalnum: 0, + text: info['license'] ?? '', + onTap: () {}, + ), + const Divider(), + + // 照片信息 + _buildPhotoItem(1), + const Divider(), + _buildPhotoItem(2), + const Divider(), + // _buildPhotoItem(3), + Container( + height: 150, + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Image.network('${ApiService.baseImgPath}1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'), + ), + // const Divider(), + + ], + ), + + ); + } + + Widget _buildPhotoItem(int witch) { + String labelName=''; + switch(witch){ + case 1: + labelName='车辆照片'; + break; + case 2: + labelName='行驶证照片'; + break; + case 3: + labelName='机动车登记证书'; + break; + } + return Padding( + padding: EdgeInsets.only(bottom: 12), + child: + ItemListWidget.twoRowTitleAndImages( + title: labelName, + horizontalInset:0, + onTapCallBack: (path) { + presentOpaque(SingleImageViewer(imageUrl: path), context); + }, + imageUrls: ['1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg','1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'], + ), + // ItemListWidget.OneRowImageTitle( + // label: labelName, + // text: '', + // onTapCallBack: (path) { + // presentOpaque(SingleImageViewer(imageUrl: path), context); + // }, + // imgPath: '1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg', + // ), + ); + } + + Widget _buildActionButtons() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 验收按钮 + + Expanded( + child: CustomButton( + height: 35, + onPressed: () async { + final confirmed = await CustomAlertDialog.showInput( + context, + title: "驳回原因", + hintText: '输入内容', + cancelText: '关闭', + confirmText: '确定', + ); + if (confirmed != null) { + ToastUtil.showNormal(context, confirmed); + } + }, + backgroundColor: h_backGroundColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle: ButtonStyleType.secondary, + text: '驳回') + ), + + SizedBox(width: 10), // 使用width而不是height + // 查看详情按钮 + Expanded( + child: CustomButton( + height: 35, + onPressed: () { + + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle: ButtonStyleType.primary, + text: '审核通过') + ), + + ], + ); + } +} diff --git a/lib/pages/home/doorAndCar/car/onlyLook_doorarea_car.dart b/lib/pages/home/doorAndCar/car/onlyLook_doorarea_car.dart new file mode 100644 index 0000000..1b1232d --- /dev/null +++ b/lib/pages/home/doorAndCar/car/onlyLook_doorarea_car.dart @@ -0,0 +1,383 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.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/ApiService.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + + +class OnlylookDoorareaCar extends StatefulWidget { + const OnlylookDoorareaCar(this.type, {super.key}); + + final int type;//1 审核 2 查看 + + @override + State createState() => _OnlylookDoorareaCarState(); +} + +class _OnlylookDoorareaCarState extends State { + + // 模拟申请信息数据 + final Map applicationInfo = { + 'mingcheng': '项目名称', + 'bumen': '审核人员部门', + 'renyuan': '审核人员', + 'shijian': '2024-01-01 至 2024-12-31', + 'gangqu': '访问港区', + 'diqu': '访问地区', + }; + + // 模拟人员列表数据 + final Map personnelList = + { + 'name': '张三', + 'bumen': '技术部', + 'isPei': '是', + 'wan': 'A区、B区', + }; + + /// 是否是监管端 + bool isJGD = false; + + + @override + void initState() { + super.initState(); + + _getTypeTitle(); + + } + + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '车辆审核'), + body: + Container( + color: Colors.white, + child: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + // 申请信息卡片 + _buildInfoCard(), + SizedBox(height: 10), + + // 人员列表 + _buildPersonCard(), + + SizedBox(height: 10,), + if(widget.type==1) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 验收按钮 + + Expanded( + child:CustomButton( + height: 35, + onPressed: () async { + + final confirmed = await CustomAlertDialog.showInput( + context, + title: "驳回原因", + hintText: '输入内容', + cancelText: '关闭', + confirmText: '确定', + ); + if (confirmed!=null) { + ToastUtil.showNormal(context, confirmed); + } + + }, + backgroundColor: h_backGroundColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle:ButtonStyleType.secondary, + text: '驳回') + ), + + SizedBox(width: 10), // 使用width而不是height + // 查看详情按钮 + Expanded( + child:CustomButton( + height: 35, + onPressed: () { + + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle:ButtonStyleType.primary, + text: '审核通过') + ), + + ], + ), + + if(widget.type==2) + CustomButton( + height: 35, + onPressed: () { + Navigator.of(context).pop(); + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle:ButtonStyleType.primary, + text: '关闭'), + + + ], + ), + ), + ), + + ); + } + + Widget _buildInfoCard() { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Container( + width: double.infinity, + padding: EdgeInsets.only(bottom: 10), + child: Text( + '申请信息', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + + // 信息列表 + ItemListWidget.selectableLineTitleTextRightButton( + label: '管辖单位:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['mingcheng'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '管辖区域:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['bumen'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['renyuan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['diqu'] ?? '', + onTap: () {}, + ), + + // if((applicationInfo['gangqu'] ?? '').isNotEmpty) + const Divider(), + // if((applicationInfo['gangqu'] ?? '').isNotEmpty) + ItemListWidget.selectableLineTitleTextRightButton( + label: '所属项目:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['gangqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '时间范围:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['shijian'] ?? '', + onTap: () {}, + ), + const Divider(), + + + ItemListWidget.twoRowTitleText( + label: '申请原因:', + text: applicationInfo['shijian']??'', + horizontalInset:0, + ), + const Divider(), + + ], + ), + ); + } + + Widget _buildPersonCard() { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Container( + width: double.infinity, + padding: EdgeInsets.only(bottom: 10), + child: Text( + '车辆信息', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + + // 信息列表 + ItemListWidget.selectableLineTitleTextRightButton( + label: '驾驶人部门:', + isEditable: false, + horizontalnum:0, + text: personnelList['name'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '驾驶人:', + isEditable: false, + horizontalnum:0, + text: personnelList['bumen'] ?? '', + onTap: () {}, + ), + const Divider(), + + // ItemListWidget.selectableLineTitleTextRightButton( + // label: '手机号:', + // isEditable: false, + // horizontalnum:0, + // text: personnelList['wan'] ?? '', + // onTap: () {}, + // ), + // const Divider(), + // + // ItemListWidget.selectableLineTitleTextRightButton( + // label: '部门:', + // isEditable: false, + // horizontalnum:0, + // text: personnelList['wan'] ?? '', + // onTap: () {}, + // ), + // const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '车辆类型:', + isEditable: false, + horizontalnum:0, + text: personnelList['wan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌类型:', + isEditable: false, + horizontalnum:0, + text: personnelList['wan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '车牌号:', + isEditable: false, + horizontalnum:0, + text: personnelList['wan'] ?? '', + onTap: () {}, + ), + const Divider(), + + + ItemListWidget.twoRowTitleAndImages( + title: '车辆照片', + horizontalInset:0, + onTapCallBack: (path) { + presentOpaque(SingleImageViewer(imageUrl: path), context); + }, + imageUrls: ['1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg','1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'], + ), + // ItemListWidget.OneRowImageTitle( + // label: '车辆照片:', + // imgPath: '1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg', + // horizontalInset:0, + // onTapCallBack: (imgUrl) { + // presentOpaque(SingleImageViewer(imageUrl: imgUrl), context); + // }, + // ), + const Divider(), + + ItemListWidget.twoRowTitleAndImages( + title: '行驶证照片', + horizontalInset:0, + onTapCallBack: (path) { + presentOpaque(SingleImageViewer(imageUrl: path), context); + }, + imageUrls: ['1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg','1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'], + ), + const Divider(), + + Container( + height: 150, + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Image.network('${ApiService.baseImgPath}1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'), + ), + + + ], + ), + ); + } + + + + Future _getTypeTitle() async { + String text= await _getString('selectedRole'); + setState(() { + if(text=='fgszd'||text=='FGSZD'){//分公司 + isJGD=false; + }else{//监管端 + isJGD=true; + } + }); + } + + Future _getString(String key) async { + final prefs = await SharedPreferences.getInstance(); + String text=prefs.getString(key)??''; + return text; + } + + +} diff --git a/lib/pages/home/doorAndCar/doorArea_type_page.dart b/lib/pages/home/doorAndCar/doorArea_type_page.dart new file mode 100644 index 0000000..2dfe43e --- /dev/null +++ b/lib/pages/home/doorAndCar/doorArea_type_page.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/person/doorArea_person_record_page.dart'; + + +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +class DoorareaTypePage extends StatefulWidget { + const DoorareaTypePage(this.type, {super.key}); + + final int type;//1 进港口门申请 2 进港口门申请记录 3 封闭区域口门申请 4 封闭区域口门申请记录 + + @override + State createState() => _DoorareaTypePageState(); +} + +class _DoorareaTypePageState extends State { + + String labelOne=''; + String labelTwo=''; + + @override + void initState() { + // TODO: implement initState + super.initState(); + switch(widget.type){ + case 1: + labelOne='人员申请'; + labelTwo='车辆申请'; + break; + case 2: + labelOne='人员申请记录'; + labelTwo='车辆申请记录'; + break; + case 3: + labelOne='人员申请'; + labelTwo='车辆申请'; + break; + case 4: + labelOne='人员申请记录'; + labelTwo='车辆申请记录'; + break; + } + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: MyAppbar(title: '查看'), + body: SafeArea( + child: Column( + children: [ + const SizedBox(height: 10), + ItemListWidget.selectableLineTitleTextRightButton( + label: labelOne, + isEditable: true, + isRequired: false, + onTap: () async { + if(widget.type==1){ + await pushPage(DoorareaPersonRecordPage(1), context); + }else if(widget.type==2){ + await pushPage(DoorareaPersonRecordPage(2), context); + }else if(widget.type==3){ + await pushPage(DoorareaPersonRecordPage(3), context); + }else if(widget.type==4){ + await pushPage(DoorareaPersonRecordPage(4), context); + } + + }, + text: '', + + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: labelTwo, + isEditable: true, + isRequired: false, + onTap: () async { + if(widget.type==1){ + await pushPage(DoorareaPersonRecordPage(5), context); + }else if(widget.type==2){ + await pushPage(DoorareaPersonRecordPage(6), context); + }else if(widget.type==3){ + await pushPage(DoorareaPersonRecordPage(7), context); + }else if(widget.type==4){ + await pushPage(DoorareaPersonRecordPage(8), context); + } + + }, + text: '', + + ), + const Divider(), + ], + ), + ), + ); + } +} diff --git a/lib/pages/home/doorAndCar/doorCar_tab_page.dart b/lib/pages/home/doorAndCar/doorCar_tab_page.dart new file mode 100644 index 0000000..1e28098 --- /dev/null +++ b/lib/pages/home/doorAndCar/doorCar_tab_page.dart @@ -0,0 +1,317 @@ +// lib/pages/application_template.dart +import 'dart:ffi'; + +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/doorArea_type_page.dart'; + +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/tools.dart'; + +typedef ItemTapCallback = void Function(); + +class AppSectionItem { + final String title; + final String icon; // asset path + final int badge; + final bool visible; + final ItemTapCallback? onTap; + + AppSectionItem({ + required this.title, + required this.icon, + this.badge = 0, + this.visible = true, + this.onTap, + }); +} + +class AppSection { + final String title; + final List items; + + AppSection({ + required this.title, + required this.items, + }); +} +class DoorcarTabPage extends StatefulWidget { + const DoorcarTabPage({super.key}); + + @override + State createState() => _DoorcarTabPageState(); +} + +class _DoorcarTabPageState extends State { + + final String bannerAsset = 'assets/images/door_banner.png'; + late List defaultSections = [ + + AppSection(title: '口门门禁申请', items: [ + AppSectionItem( + title: '进港口门申请', + icon: 'assets/images/door_ico9.png', + badge: 0, + onTap: () async { + await pushPage(DoorareaTypePage(1), context); + _fetchData(); + }, + ), + AppSectionItem( + title: '进港口门申请记录', + icon: 'assets/images/door_ico10.png', + badge: 0, + onTap: () async { + await pushPage(DoorareaTypePage(2), context); + _fetchData(); + }, + ), + + + + AppSectionItem( + title: '封闭区域口门申请', + icon: 'assets/images/door_ico9.png', + badge: 0, + onTap: () async { + await pushPage(DoorareaTypePage(3), context); + _fetchData(); + }, + ), + AppSectionItem( + title: '封闭区域口门申请记录', + icon: 'assets/images/door_ico10.png', + badge: 0, + onTap: () async { + await pushPage(DoorareaTypePage(4), context); + _fetchData(); + }, + ), + + ]), + + + + ]; + + @override + void initState() { + // TODO: implement initState + super.initState(); + _fetchData(); + } + + Future _fetchData() async { + } + + @override + Widget build(BuildContext context) { + final double bannerHeight = (730.0 / 1125.0) * MediaQuery.of(context).size.width; + final double iconSectionHeight = + MediaQuery.of(context).size.height - bannerHeight - 30.0; + const double iconOverlapBanner = 30.0; + + // 过滤掉没有可见 items 的分组 + final visibleSections = defaultSections + .map((s) => AppSection( + title: s.title, + items: s.items.where((it) => it.visible).toList())) + .where((s) => s.items.isNotEmpty) + .toList(); + + return Scaffold( + extendBodyBehindAppBar: true, + appBar: MyAppbar(title: '智能门禁', backgroundColor: Colors.transparent,), + body: ListView( + physics: const AlwaysScrollableScrollPhysics(), + padding: EdgeInsets.zero, + children: [ + SizedBox( + height: bannerHeight + iconSectionHeight, + child: Stack( + clipBehavior: Clip.none, + children: [ + Positioned( + top: 0, + left: 0, + right: 0, + height: bannerHeight, + child: _buildBannerSection(bannerHeight, context), + ), + Positioned( + left: 10, + right: 10, + top: bannerHeight - iconOverlapBanner, + height: iconSectionHeight, + child: _buildIconSection(context, visibleSections), + ), + ], + ), + ), + ], + ), + ); + } + + Widget _buildBannerSection(double bannerHeight, BuildContext context) { + return Stack( + children: [ + Image.asset( + bannerAsset, + width: MediaQuery.of(context).size.width, + height: bannerHeight, + fit: BoxFit.fitWidth, + errorBuilder: (c, e, s) { + return Container( + color: Colors.blueGrey, + height: bannerHeight, + alignment: Alignment.center, + child: const Text('Banner', style: TextStyle(color: Colors.white)), + ); + }, + ), + ], + ); + } + + Widget _buildIconSection(BuildContext context, List buttonInfos) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: const [ + BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2)), + ], + ), + child: ListView.builder( + physics: const AlwaysScrollableScrollPhysics(), + padding: const EdgeInsets.all(0), + itemCount: buttonInfos.length, + itemBuilder: (context, index) { + final section = buttonInfos[index]; + final items = section.items; + if (items.isEmpty) return const SizedBox.shrink(); + + return Padding( + padding: const EdgeInsets.only(top: 10, left: 10, right: 10), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Padding( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 5), + child: Row( + children: [ + Container(width: 2, height: 10, color: Colors.blue), + const SizedBox(width: 5), + Text(section.title, + style: const TextStyle( + fontSize: 14, fontWeight: FontWeight.bold)), + ], + ), + ), + // icons + Padding( + padding: const EdgeInsets.all(10), + child: LayoutBuilder( + builder: (context, constraints) { + const spacing = 20.0; + final totalWidth = constraints.maxWidth; + final itemWidth = (totalWidth - spacing * 2) / 3; + return Wrap( + spacing: spacing, + runSpacing: spacing, + children: items.map((item) { + return SizedBox( + width: itemWidth, + child: _buildItem( + item, + onTap: item.onTap ?? + () => debugPrint('Tapped ${item.title}'), + ), + ); + }).toList(), + ); + }, + ), + ), + ], + ), + ), + ); + }, + ), + ); + } + + Widget _buildItem(AppSectionItem item, {VoidCallback? onTap}) { + const double iconSize = 30; + final int badgeNum = item.badge; + final String title = item.title; + final String iconPath = item.icon; + + return InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(8), + child: SizedBox( + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Stack( + clipBehavior: Clip.none, + children: [ + SizedBox( + width: iconSize, + height: iconSize, + child: Image.asset( + iconPath, + fit: BoxFit.contain, + errorBuilder: (c, e, s) { + return Container( + color: Colors.grey.shade200, + child: const Center(child: Icon(Icons.image, size: 18)), + ); + }, + ), + ), + if (badgeNum > 0) + Positioned( + top: -6, + right: -6, + child: Container( + padding: + const EdgeInsets.symmetric(horizontal: 4, vertical: 2), + decoration: + const BoxDecoration(color: Colors.red, shape: BoxShape.circle), + constraints: const BoxConstraints(minWidth: 16, minHeight: 16), + child: Center( + child: Text( + badgeNum > 99 ? '99+' : badgeNum.toString(), + style: const TextStyle(color: Colors.white, fontSize: 10, height: 1), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ), + const SizedBox(height: 4), + Text( + title, + style: const TextStyle(fontSize: 13), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/home/doorAndCar/person/doorArea_person_add_page.dart b/lib/pages/home/doorAndCar/person/doorArea_person_add_page.dart new file mode 100644 index 0000000..9ee0ae3 --- /dev/null +++ b/lib/pages/home/doorAndCar/person/doorArea_person_add_page.dart @@ -0,0 +1,458 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/bottom_picker.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/customWidget/photo_picker_row.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/basic_info_api.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/sign_instructions_webView.dart'; + + +import 'package:qhd_prevention/pages/mine/mine_sign_page.dart'; +import 'package:qhd_prevention/pages/mine/webViewPage.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/services/SessionService.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:flutter/gestures.dart'; + +class DoorareaPersonApplyPage extends StatefulWidget { + const DoorareaPersonApplyPage({super.key}); + + @override + State createState() => + _DoorareaPersonApplyPageState(); +} + +class _DoorareaPersonApplyPageState extends State { + Map pd = {}; + bool _agreed = false; + + // 部门列表 + List _deptList = []; + List _personList = []; + List signImages = []; + + @override + void initState() { + super.initState(); + _getDept(); + } + + // 获取部门 + Future _getDept() async { + // try { + // final data = { + // 'eqCorpinfoId': widget.scanData['id'], + // // 'eqParentId': widget.scanData['corpinfoId'], + // }; + // final result = await BasicInfoApi.getDeptTree(data); + // if (result['success'] == true) { + // final list = result['data'] ?? []; + // if (list.length > 0) { + // setState(() { + // _deptList = list[0]['childrenList'] ?? []; + // }); + // } + // } + // } catch (e) {} + } + + // 提交 + Future _saveSuccess() async { + if (!FormUtils.hasValue(pd, 'corpinfoId')) { + ToastUtil.showNormal(context, '请选择部门'); + return; + } + if (!FormUtils.hasValue(pd, 'postName')) { + ToastUtil.showNormal(context, '请输入岗位'); + return; + } + // try { + // final result = await BasicInfoApi.userFirmEntry(pd); + // LoadingDialogHelper.hide(); + // if (result['success'] == true) { + // ToastUtil.showNormal(context, '申请成功'); + // _relogin(); + // } else { + // ToastUtil.showNormal(context, result['errMessage']); + // } + // } catch (e) { + // LoadingDialogHelper.hide(); + // ToastUtil.showNormal(context, '操作失败,请重试'); + // } + } + + Widget _addPersonWight(Map personData) { + return Stack( + children: [ + Padding(padding: const EdgeInsets.only(top: 5),child: Container( + margin: const EdgeInsets.symmetric(horizontal: 12), + // padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: Colors.white, + // 边框 + border: Border.all( + color: Colors.grey.shade300, + width: 1.0, + style: BorderStyle.solid, + ), + borderRadius: BorderRadius.circular(5), + ), + child: Column( + children: [ + const SizedBox(height: 10), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择部门:', + isEditable: true, + text: personData['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择人员:', + isEditable: true, + text: personData['postName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.itemContainer(RepairedPhotoSection( + isRequired: true, + title: "人员照片", + maxCount: 1, + horizontalPadding: 0, + mediaType: MediaType.image, + isShowAI: false, + onChanged: (List files) {}, + onAiIdentify: () {}, + ),), + const SizedBox(height: 10) + ], + ) + ),), + Positioned( + top: 0, + right: 2, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.red, + ), + + child: GestureDetector( + child: const Icon(Icons.close, size: 14, color: Colors.white,), + onTap: () { + setState(() { + _personList.remove(personData); + }); + }, + ), + ), + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '人员申请'), + body: SafeArea( + child: ItemListWidget.itemContainer( + horizontal: 5, + vertical: 12, + ListView( + children: [ + ListItemFactory.createBuildSimpleSection('申请信息'), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择管辖单位:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async { + if (_deptList.isEmpty) { + ToastUtil.showNormal(context, '暂无部门信息'); + return; + } + final found = await BottomPicker.show( + context, + items: _deptList, + itemBuilder: + (i) => Text(i['name']!, textAlign: TextAlign.center), + initialIndex: 0, + ); + //FocusHelper.clearFocus(context); + + if (found != null) { + setState(() { + pd['departmentId'] = found['id']; + pd['departmentName'] = found['name']; + pd['corpinfoId'] = found['corpinfoId']; + pd['corpinfoName'] = found['corpinfoName']; + }); + } + }, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择管辖区域:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择项目:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.selectableLineTitleTextRightButton( + label: '选择时间:', + isEditable: true, + text: pd['departmentName'] ?? '请选择', + isRequired: true, + onTap: () async {}, + ), + const Divider(), + ItemListWidget.multiLineTitleTextField( + label: '申请原因', + isEditable: true, + ), + + const Divider(), + if (_personList.isNotEmpty) + ...[ + ListItemFactory.createBuildSimpleSection('人员信息'), + // const Divider(), + for (var i = 0; i < _personList.length; i++) + _addPersonWight(_personList[i]), + ], + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomButton( + text: '添加人员', + padding: const EdgeInsets.symmetric(horizontal: 20), + height: 35, + backgroundColor: Colors.blue, + onPressed: () { + setState(() { + _personList.add({}); + _addPersonWight({}); + }); + }, + ), + const SizedBox(width: 10), + ], + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Checkbox( + value: _agreed, + activeColor: Colors.blue, + checkColor: Colors.white, + side: const BorderSide(color: Colors.grey), + onChanged: (value) { + setState(() { + _agreed = value ?? false; + }); + }, + ), + Flexible( + child: RichText( + text: TextSpan( + children: [ + const TextSpan( + text: '我已阅读并同意', + style: TextStyle(color: Colors.black, fontSize: 12), + ), + TextSpan( + text: '《安全进港须知》', + style: const TextStyle( + color: Colors.blue, + fontSize: 12, + ), + recognizer: + TapGestureRecognizer() + ..onTap = () async { + final path = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => SignInstructionsWebview( + name: "安全进港须知", + url: + 'http://47.92.102.56:7811/file/xieyi/zsyhxy.htm', + )), + ); + await NativeOrientation.setPortrait(); + if (path != null) { + setState(() { + setState(() { + _agreed = true; + signImages = []; + signImages.add(path); + }); + }); + } + + }, + ), + ], + ), + ), + ), + ], + ), + + + // Container( + // padding: EdgeInsets.symmetric(horizontal: 12), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // ListItemFactory.headerTitle('签字:', isRequired: true), + // CustomButton( + // text: signImages.isNotEmpty ? '重新签字' : '手写签字', + // height: 36, + // backgroundColor: Colors.blue, + // onPressed: _sign, + // ), + // ], + // ), + // ), + if (signImages.isNotEmpty) _signListWidget(), + + SizedBox(height: 10,), + + CustomButton( + text: '提交申请', + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), + height: 40, + backgroundColor: Colors.blue, + onPressed: () { + _saveSuccess(); + }, + ), + ], + ), + ), + ), + ); + } + + + + 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(), + ); + } + + /// 签字 + // Future _sign() async { + // final name = SessionService.instance.name ?? ''; + // await NativeOrientation.setLandscape(); + // final path = await Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => MineSignPage(personName: name,)), + // ); + // await NativeOrientation.setPortrait(); + // if (path != null) { + // setState(() { + // signImages = []; + // signImages.add(path); + // }); + // } + // } + + + +} diff --git a/lib/pages/home/doorAndCar/person/doorArea_person_record_page.dart b/lib/pages/home/doorAndCar/person/doorArea_person_record_page.dart new file mode 100644 index 0000000..dc84ceb --- /dev/null +++ b/lib/pages/home/doorAndCar/person/doorArea_person_record_page.dart @@ -0,0 +1,356 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/car/doorArea_car_add_page.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/car/onlyLook_car_application.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/car/onlyLook_doorarea_car.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/person/doorArea_person_add_page.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/person/onlyLook_doorarea_person.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/person/onlyLook_person_application.dart'; + + +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/search_bar_widget.dart'; + + +class DoorareaPersonRecordPage extends StatefulWidget { + const DoorareaPersonRecordPage(this.type, {Key? key}) : super(key: key); + + final int type;//1 进港口门申请(人) 2 进港口门申请记录(人) 3 封闭区域口门申请(人) 4 封闭区域口门申请记录(人) + //5 进港口门申请(车) 6 进港口门申请记录(车) 7 封闭区域口门申请(车) 8 封闭区域口门申请记录(车) + + @override + _DoorareaPersonRecordPageState createState() => _DoorareaPersonRecordPageState(); +} + +class _DoorareaPersonRecordPageState extends State { + // Data and state variables + // List list = []; + final List> list = [ + { + 'applicant': '封闭区域申请', + 'region': '申请人', + 'people': '人数', + 'startTime': '2025-10-29 00:00', + 'endTime': '2025-10-31 00:00', + 'license': '申请区域', + 'status': '待审核', + 'statusColor': Colors.orange, + }, + { + 'applicant': '封闭区域申请', + 'region': '申请人', + 'people': '人数', + 'startTime': '2025-10-29 00:00', + 'endTime': '2025-10-31 00:00', + 'license': '申请区域', + 'status': '待审核', + 'statusColor': Colors.orange, + }, + { + 'applicant': '封闭区域申请', + 'region': '申请人', + 'people': '人数', + 'startTime': '2025-10-29 00:00', + 'endTime': '2025-10-31 00:00', + 'license': '申请区域', + 'status': '待审核', + 'statusColor': Colors.orange, + }, + + ]; + + + Map pd = {}; + + int currentPage = 1; + int rows = 10; + int totalPage = 1; + bool isLoading = false; + final TextEditingController _searchController = TextEditingController(); + + int sindex = 0; + String searchKeywords = ''; + + final GlobalKey _scaffoldKey = GlobalKey(); + + final ScrollController _scrollController = ScrollController(); + + /// 是否是监管端 + + String titleName=''; + String buttonName=''; + + bool isAdd = false; + + @override + void initState() { + super.initState(); + + switch(widget.type){ + case 1: + case 3: + titleName='人员审核'; + buttonName='查看'; + isAdd=true; + break; + case 2: + case 4: + titleName='人员审核记录'; + buttonName='查看'; + isAdd=false; + break; + case 5: + case 7: + titleName='车辆审核'; + buttonName='查看'; + isAdd=true; + break; + case 6: + case 8: + titleName='车辆审核记录'; + buttonName='查看'; + isAdd=false; + break; + } + + _fetchData(); + _scrollController.addListener(_onScroll); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + void _onScroll() { + if (_scrollController.position.pixels >= + _scrollController.position.maxScrollExtent && + !isLoading) { + if (currentPage < totalPage) { + currentPage++; + _fetchData(); + } + } + } + + + + Future _fetchData() async { + + // if (isLoading) return; + // setState(() => isLoading = true); + // + // try { + // final data = { + // "likeCorpName": searchKeywords, + // "pageSize": rows, + // "pageIndex": currentPage, + // }; + // final response = await RiskwarningApi.getCorpRiskStatement(); + // final firmRes = await RiskwarningApi.getCorpRiskList(data); + // setState(() { + // pd = response['data']; + // if (currentPage == 1) { + // list = firmRes['data']; + // } else { + // list.addAll(firmRes['data']); + // } + // totalPage = firmRes['totalPages'] ?? 1; + // isLoading = false; + // }); + // } catch (e) { + // print('Error fetching data: $e'); + // setState(() => isLoading = false); + // } + } + + void _search() { + searchKeywords = _searchController.text.trim(); + currentPage = 1; + list.clear(); + _fetchData(); + } + + void _goToDetail(Map item,int index) async { + switch(widget.type){ + case 1: + case 2: + await pushPage(OnlylookDoorareaPerson(2), context); + break; + case 3: + case 4: + await pushPage(OnlylookPersonApplication(3), context); + break; + case 5: + case 6: + await pushPage(OnlylookDoorareaCar(2), context); + break; + case 7: + case 8: + await pushPage(CarApplicationRecord(4), context); + break; + } + _fetchData(); + } + + Widget _buildListItem(Map item,int index) { + return InkWell( + onTap: () { + + }, + child: Container( + padding: const EdgeInsets.all(20), + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item['applicant'], + // '${item['name']??''}', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + + + const SizedBox(height: 8), + Text('申请人:${item['region']??""}',), + if(widget.type==5||widget.type==6||widget.type==7||widget.type==8)...[ + const SizedBox(height: 8), + Text('车牌号:${item['region']??""}',), + ], + const SizedBox(height: 8), + Text('申请区域:${item['license']??""}',), + const SizedBox(height: 8), + Text('时间范围:自${item['startTime']??""}至${item['endTime']??""}止'), + const SizedBox(height: 8), + Text('审核状态:${item['status']??""}',), + if(widget.type==2||widget.type==4||widget.type==6||widget.type==8)...[ + const SizedBox(height: 8), + Text('驳回原因:${item['status']??""}',), + ], + + + const SizedBox(height: 12), + CustomButton( + height: 35, + onPressed: () { + _goToDetail(item,index); + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle:ButtonStyleType.primary, + text: buttonName), + + ], + ), + ), + + ); + } + + + Widget _buildListContent() { + if (isLoading && list.isEmpty) { + // 初始加载时显示居中的加载指示器 + return 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 Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Center(child: CircularProgressIndicator()), + ); + } + return _buildListItem(list[index],index); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + + return Scaffold( + key: _scaffoldKey, + appBar: MyAppbar(title: titleName, actions: [ + + if(isAdd) + IconButton( + icon: const Icon(Icons.add, color: Colors.white, size: 30), + onPressed: () async { + switch(widget.type){ + case 1: + await pushPage(DoorareaPersonApplyPage(), context); + break; + case 3: + + break; + case 5: + await pushPage(DoorareaCarAddPage(), context); + break; + case 7: + + break; + } + _fetchData(); + + }, + ), + + ],), + body: Column( + children: [ + // Filter bar + Container( + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8), + child: SearchBarWidget( + showResetButton: true, + hintText: '请输入关键字', + resetButtonText: '重置', + onReset: () { + FocusScope.of(context).unfocus(); + _searchController.text = ''; + _search(); + }, + onSearch: (text) { + FocusScope.of(context).unfocus(); + _search(); + }, + controller: _searchController, + ), + ), + const Divider(height: 1), + // List + Expanded(child: _buildListContent()), + ], + ), + ); + } +} diff --git a/lib/pages/home/doorAndCar/person/onlyLook_doorarea_person.dart b/lib/pages/home/doorAndCar/person/onlyLook_doorarea_person.dart new file mode 100644 index 0000000..8d1a88e --- /dev/null +++ b/lib/pages/home/doorAndCar/person/onlyLook_doorarea_person.dart @@ -0,0 +1,351 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.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/ApiService.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; +import 'package:qhd_prevention/tools/tools.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + + +class OnlylookDoorareaPerson extends StatefulWidget { + const OnlylookDoorareaPerson(this.type, {super.key}); + + final int type;//1 审核 2 查看 + + @override + State createState() => _OnlylookDoorareaPersonState(); +} + +class _OnlylookDoorareaPersonState extends State { + + // 模拟申请信息数据 + final Map applicationInfo = { + 'mingcheng': '项目名称', + 'bumen': '审核人员部门', + 'renyuan': '审核人员', + 'shijian': '2024-01-01 至 2024-12-31', + 'gangqu': '访问港区', + 'diqu': '访问地区', + }; + + // 模拟人员列表数据 + final List> personnelList = [ + { + 'name': '张三', + 'bumen': '技术部', + 'isPei': '是', + 'wan': 'A区、B区', + }, + { + 'name': '李四', + 'bumen': '安全部', + 'isPei': '否', + 'wan': 'C区', + }, + { + 'name': '王五', + 'bumen': '运营部', + 'isPei': '是', + 'wan': 'A区、C区、D区', + }, + ]; + + + @override + void initState() { + super.initState(); + + + + } + + + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '人员审核'), + body: + Container( + color: Colors.white, + child: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + // 申请信息卡片 + _buildInfoCard(), + SizedBox(height: 10), + + // 人员列表 + _buildPersonWidget(), + + SizedBox(height: 10,), + if(widget.type==1) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 验收按钮 + + Expanded( + child:CustomButton( + height: 35, + onPressed: () async { + + final confirmed = await CustomAlertDialog.showInput( + context, + title: "驳回原因", + hintText: '输入内容', + cancelText: '关闭', + confirmText: '确定', + ); + if (confirmed!=null) { + ToastUtil.showNormal(context, confirmed); + } + + }, + backgroundColor: h_backGroundColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle:ButtonStyleType.secondary, + text: '驳回') + ), + + SizedBox(width: 10), // 使用width而不是height + // 查看详情按钮 + Expanded( + child:CustomButton( + height: 35, + onPressed: () { + + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle:ButtonStyleType.primary, + text: '审核通过') + ), + + ], + ), + + if(widget.type==2) + CustomButton( + height: 35, + onPressed: () { + Navigator.of(context).pop(); + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle:ButtonStyleType.primary, + text: '关闭'), + + + ], + ), + ), + ), + + ); + } + + Widget _buildInfoCard() { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Container( + width: double.infinity, + padding: EdgeInsets.only(bottom: 10), + child: Text( + '申请信息', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + + // 信息列表 + ItemListWidget.selectableLineTitleTextRightButton( + label: '管辖单位:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['mingcheng'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '管辖区域:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['bumen'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['renyuan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['diqu'] ?? '', + onTap: () {}, + ), + + // if((applicationInfo['gangqu'] ?? '').isNotEmpty) + const Divider(), + // if((applicationInfo['gangqu'] ?? '').isNotEmpty) + ItemListWidget.selectableLineTitleTextRightButton( + label: '所属项目:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['gangqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '时间范围:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['shijian'] ?? '', + onTap: () {}, + ), + const Divider(), + + + ItemListWidget.twoRowTitleText( + label: '申请原因:', + text: applicationInfo['shijian']??'', + horizontalInset:0, + ), + const Divider(), + + ], + ), + ); + } + + Widget _buildPersonWidget() { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题 + Container( + width: double.infinity, + padding: EdgeInsets.only(bottom: 10), + child: Text( + '人员信息', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + + // 人员列表 + ...personnelList.map((person) => _buildPersonCard(person)), + + Container( + height: 150, + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Image.network('${ApiService.baseImgPath}1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'), + ), + + + ], + ), + ); + } + + + Widget _buildPersonCard(Map person) { + return Card( + margin: EdgeInsets.only(bottom: 12), + color: Colors.white, + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: EdgeInsets.all(16), + child: Column( + children: [ + // 第一行:姓名和部门 + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + '姓名: ${person['name']}', + style: TextStyle( + fontSize: 14, + color: Colors.grey[700], + ), + ), + ), + // _buildInfoItem('姓名:', person['姓名'] ?? '',), + SizedBox(width: 24), + Expanded( + child: Text( + '部门: ${person['bumen']}', + style: TextStyle( + fontSize: 14, + color: Colors.grey[700], + ), + ), + ), + + // _buildInfoItem('部门:', person['部门'] ?? ''), + ], + ), + // SizedBox(height: 8), + + // 第二行:删除 + // Row( + // mainAxisAlignment: MainAxisAlignment.end, + // children: [ + // CustomButton( + // height: 35, + // onPressed: () async { + // + // }, + // backgroundColor: Colors.red, + // textStyle: const TextStyle(color: Colors.black), + // buttonStyle:ButtonStyleType.primary, + // text: '删除') + // ], + // ), + ], + ), + ), + ); + } + + + + + +} diff --git a/lib/pages/home/doorAndCar/person/onlyLook_person_application.dart b/lib/pages/home/doorAndCar/person/onlyLook_person_application.dart new file mode 100644 index 0000000..5b4ee0b --- /dev/null +++ b/lib/pages/home/doorAndCar/person/onlyLook_person_application.dart @@ -0,0 +1,329 @@ +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/item_list_widget.dart'; +import 'package:qhd_prevention/customWidget/toast_util.dart'; +import 'package:qhd_prevention/http/ApiService.dart'; +import 'package:qhd_prevention/pages/my_appbar.dart'; +import 'package:qhd_prevention/tools/h_colors.dart'; + + +class OnlylookPersonApplication extends StatefulWidget { + const OnlylookPersonApplication(this.type, {super.key}); + + final int type;//1 一级口门人员审核 2 一级口门车辆审核 3 审批记录(人员) 4 审批记录(车辆) + + @override + State createState() => _OnlylookPersonApplicationState(); +} + +class _OnlylookPersonApplicationState extends State { + + // 模拟申请信息数据 + final Map applicationInfo = { + 'mingcheng': '项目名称', + 'bumen': '审核人员部门', + 'renyuan': '审核人员', + 'shijian': '2024-01-01 至 2024-12-31', + 'gangqu': '访问港区', + 'diqu': '访问地区', + }; + + // 模拟人员列表数据 + final List> personnelList = [ + { + 'name': '张三', + 'bumen': '技术部', + 'isPei': '是', + 'wan': 'A区、B区', + }, + { + 'name': '李四', + 'bumen': '安全部', + 'isPei': '否', + 'wan': 'C区', + }, + { + 'name': '王五', + 'bumen': '运营部', + 'isPei': '是', + 'wan': 'A区、C区、D区', + }, + ]; + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppbar(title: '申请记录'), + body: + Container( + color: Colors.white, + child: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 申请信息卡片 + _buildInfoCard(), + SizedBox(height: 10), + + + // 人员列表 + ...personnelList.map((person) => _buildPersonCard(person)), + + Container( + height: 150, + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Image.network('${ApiService.baseImgPath}1983773013086048256/202601/ai_recognition_images/a9c8e701f773470d8a8485ccb6fb35b7.jpg'), + ), + + SizedBox(height: 10,), + if(widget.type==1) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 验收按钮 + + Expanded( + child:CustomButton( + height: 35, + onPressed: () async { + + final confirmed = await CustomAlertDialog.showInput( + context, + title: "驳回原因", + hintText: '输入内容', + cancelText: '关闭', + confirmText: '确定', + ); + if (confirmed!=null) { + ToastUtil.showNormal(context, confirmed); + } + + }, + backgroundColor: h_backGroundColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle:ButtonStyleType.secondary, + text: '驳回') + ), + + SizedBox(width: 10), // 使用width而不是height + // 查看详情按钮 + Expanded( + child:CustomButton( + height: 35, + onPressed: () { + + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.white), + buttonStyle:ButtonStyleType.primary, + text: '审核通过') + ), + + ], + ), + + if(widget.type==3) + CustomButton( + height: 35, + onPressed: () { + Navigator.of(context).pop(); + }, + backgroundColor: h_AppBarColor(), + textStyle: const TextStyle(color: Colors.black), + buttonStyle:ButtonStyleType.primary, + text: '关闭'), + + + ], + ), + ), + ), + + ); + } + + Widget _buildInfoCard() { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + // 标题 + Container( + width: double.infinity, + padding: EdgeInsets.only(bottom: 10), + child: Text( + '申请信息', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + + // 信息列表 + ItemListWidget.selectableLineTitleTextRightButton( + label: '项目名称:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['mingcheng'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员部门:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['bumen'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '审核人员:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['renyuan'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '时间范围:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['shijian'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '访问港区:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['gangqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ItemListWidget.selectableLineTitleTextRightButton( + label: '区域范围:', + isEditable: false, + horizontalnum:0, + text: applicationInfo['diqu'] ?? '', + onTap: () {}, + ), + const Divider(), + + ], + ), + ); + } + + Widget _buildPersonCard(Map person) { + return Card( + margin: EdgeInsets.only(bottom: 12), + color: Colors.white, + elevation: 2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: EdgeInsets.all(16), + child: Column( + children: [ + // 第一行:姓名和部门 + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + '姓名: ${person['name']}', + style: TextStyle( + fontSize: 14, + color: Colors.grey[700], + ), + ), + ), + // _buildInfoItem('姓名:', person['姓名'] ?? '',), + SizedBox(width: 24), + Expanded( + child: Text( + '部门: ${person['bumen']}', + style: TextStyle( + fontSize: 14, + color: Colors.grey[700], + ), + ), + ), + + // _buildInfoItem('部门:', person['部门'] ?? ''), + ], + ), + SizedBox(height: 12), + + // 第二行:是否培训和权限范围 + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildInfoItem('是否培训:', person['isPei'] ?? ''), // 改为 'isPei' + SizedBox(width: 24), + Expanded( + child: _buildInfoItem( + '现口门权限范围:', + person['wan'] ?? '', // 改为 'wan' + isExpanded: true, + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildInfoItem(String label, String value, {bool isExpanded = false}) { + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: TextStyle( + fontSize: 14, + color: Colors.grey[700], + ), + ), + SizedBox(height: 4), + Container( + padding: EdgeInsets.symmetric(horizontal: 0, vertical: 8), + // decoration: BoxDecoration( + // color: Colors.grey[50], + // borderRadius: BorderRadius.circular(6), + // border: Border.all( + // color: Colors.grey[300]!, + // width: 1, + // ), + // ), + child: Text( + value, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + maxLines: isExpanded ? null : 1, + overflow: isExpanded ? null : TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/doorAndCar/sign_instructions_webView.dart b/lib/pages/home/doorAndCar/sign_instructions_webView.dart new file mode 100644 index 0000000..fa4574c --- /dev/null +++ b/lib/pages/home/doorAndCar/sign_instructions_webView.dart @@ -0,0 +1,206 @@ + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; +import 'package:qhd_prevention/customWidget/custom_button.dart'; +import 'package:qhd_prevention/customWidget/single_image_viewer.dart'; +import 'package:qhd_prevention/customWidget/toast_util.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'; +import 'package:webview_flutter/webview_flutter.dart'; + + +class SignInstructionsWebview extends StatefulWidget { + final String url; + final String name; + + const SignInstructionsWebview({Key? key, required this.url, required this.name,}) : super(key: key); + + @override + State createState() => _SignInstructionsWebviewState(name); + + // _SignInstructionsWebviewState(this.name); +} + +class _SignInstructionsWebviewState extends State { + late final WebViewController _controller; + final String name; + ValueNotifier loadingProgress = ValueNotifier(0.0); + ValueNotifier isLoading = ValueNotifier(true); + + _SignInstructionsWebviewState(this.name); + + List signImages = []; + + + + @override + void initState() { + super.initState(); + _controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate(NavigationDelegate( + onProgress: (progress) { + loadingProgress.value = progress / 100; + if (progress == 100) isLoading.value = false; + }, + onPageStarted: (url) => isLoading.value = true, + onPageFinished: (url) => isLoading.value = false, + )) + ..loadRequest(Uri.parse(widget.url)); + } + + @override + Widget build(BuildContext context) { + return + Container( + color: Colors.white, + padding: EdgeInsets.only(bottom: 10), + child: Column( + children: [ + MyAppbar(title: name,onBackPressed: () async { + if (await _controller.canGoBack()) { + _controller.goBack(); + } else{ + Navigator.of(context).pop(); + } + },), + Expanded( child: WebViewWidget(controller: _controller),), + // ValueListenableBuilder( + // valueListenable: isLoading, + // builder: (context, loading, _) { + // return loading + // ? const Center(child: CircularProgressIndicator()) + // : const SizedBox(); + // }, + // ), + + SizedBox(height: 5,), + + Container( + padding: EdgeInsets.symmetric(horizontal: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ListItemFactory.headerTitle('签字:', isRequired: true), + CustomButton( + text: signImages.isNotEmpty ? '重新签字' : '手写签字', + height: 36, + backgroundColor: Colors.blue, + onPressed: _sign, + ), + ], + ), + ), + + if (signImages.isNotEmpty) _signListWidget(), + + SizedBox(height: 10,), + CustomButton( + text: '完成', + margin: EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric( + vertical: 10, + horizontal: 10, + ), + height: 40, + backgroundColor: Colors.blue, + onPressed: () { + if( signImages.isEmpty){ + ToastUtil.showNormal(context, '请先签字'); + } + + Navigator.pop(context, signImages[0]); + }, + ), + + ], + + ), + ); + + + } + + + 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(), + ); + } + + + /// 签字 + Future _sign() async { + + await NativeOrientation.setLandscape(); + final path = await Navigator.push( + context, + MaterialPageRoute(builder: (context) => MineSignPage()), + ); + await NativeOrientation.setPortrait(); + if (path != null) { + setState(() { + signImages = []; + signImages.add(path); + }); + } + } + + +} \ No newline at end of file diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index 9b3a946..41b4aa0 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -9,6 +9,7 @@ import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart'; import 'package:qhd_prevention/customWidget/custom_button.dart'; import 'package:qhd_prevention/http/ApiService.dart'; import 'package:qhd_prevention/pages/home/Study/study_tab_list_page.dart'; +import 'package:qhd_prevention/pages/home/doorAndCar/doorCar_tab_page.dart'; import 'package:qhd_prevention/pages/home/scan_page.dart'; import 'package:qhd_prevention/pages/home/unit/unit_tab_page.dart'; import 'package:qhd_prevention/pages/main_tab.dart'; @@ -36,6 +37,8 @@ class HomePageState extends RouteAwareState int _currentPage = 0; bool _isMobileSelected = true; // 切换按钮状态 + + void startScan() async { final result = await pushPage( @@ -750,6 +753,7 @@ class HomePageState extends RouteAwareState case "安环检查": break; case "口门门禁": + pushPage(DoorcarTabPage(), context); break; case "入港培训": pushPage(StudyTabListPage(), context);