2026.3.6 智能门禁

master
xufei 2026-03-06 17:59:44 +08:00
parent 0b5f169a91
commit 192d24cea5
15 changed files with 3400 additions and 9 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/images/door_ico9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -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,

View File

@ -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<DoorareaCarAddPage> createState() => _DoorareaCarAddPageState();
}
class _DoorareaCarAddPageState extends State<DoorareaCarAddPage> {
Map<String, dynamic> pd = {};
bool _agreed = false;
//
List<dynamic> _deptList = [];
List<Map> _personList = [];
List<String> signImages = [];
late bool _isMyCompanyArea = false;
late bool _isSelectCar = false;
List<String> _vehicleImages = [];
List<String> _vehicleLicenseImages = [];
@override
void initState() {
super.initState();
_getDept();
}
//
Future<void> _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<void> _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<File> 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<File> files) {
// files
_vehicleImages.clear();
for(int i=0;i<files.length;i++){
_vehicleImages.add(files[i].path);
}
},
onAiIdentify: () {
},
),),
const Divider(),
Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: RepairedPhotoSection(
isRequired:true,
title: "行驶证照片",
maxCount: 2,
mediaType: MediaType.image,
isShowAI: false,
onChanged: (List<File> files) {
// files
_vehicleLicenseImages.clear();
for(int i=0;i<files.length;i++){
_vehicleLicenseImages.add(files[i].path);
}
},
onAiIdentify: () {
},
),),
const SizedBox(height: 10),
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);
});
});
}
// 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(),
);
}
}

View File

@ -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<CarApplicationRecord> createState() => _CarApplicationRecordState();
}
class _CarApplicationRecordState extends State<CarApplicationRecord> {
//
final Map<String, String> applicationInfo = {
'mingcheng': '项目名称',
'bumen': '审核人员部门',
'renyuan': '审核人员',
'shijian': '2024-01-01 至 2024-12-31',
'gangqu': '访问港区',
'diqu': '访问地区',
};
//
final Map<String, String> 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), // 使widthheight
//
Expanded(
child: CustomButton(
height: 35,
onPressed: () {
},
backgroundColor: h_AppBarColor(),
textStyle: const TextStyle(color: Colors.white),
buttonStyle: ButtonStyleType.primary,
text: '审核通过')
),
],
);
}
}

View File

@ -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<OnlylookDoorareaCar> createState() => _OnlylookDoorareaCarState();
}
class _OnlylookDoorareaCarState extends State<OnlylookDoorareaCar> {
//
final Map<String, String> applicationInfo = {
'mingcheng': '项目名称',
'bumen': '审核人员部门',
'renyuan': '审核人员',
'shijian': '2024-01-01 至 2024-12-31',
'gangqu': '访问港区',
'diqu': '访问地区',
};
//
final Map<String, String> 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), // 使widthheight
//
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<void> _getTypeTitle() async {
String text= await _getString('selectedRole');
setState(() {
if(text=='fgszd'||text=='FGSZD'){//
isJGD=false;
}else{//
isJGD=true;
}
});
}
Future<String> _getString(String key) async {
final prefs = await SharedPreferences.getInstance();
String text=prefs.getString(key)??'';
return text;
}
}

View File

@ -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<DoorareaTypePage> createState() => _DoorareaTypePageState();
}
class _DoorareaTypePageState extends State<DoorareaTypePage> {
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(),
],
),
),
);
}
}

View File

@ -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<AppSectionItem> items;
AppSection({
required this.title,
required this.items,
});
}
class DoorcarTabPage extends StatefulWidget {
const DoorcarTabPage({super.key});
@override
State<DoorcarTabPage> createState() => _DoorcarTabPageState();
}
class _DoorcarTabPageState extends State<DoorcarTabPage> {
final String bannerAsset = 'assets/images/door_banner.png';
late List<AppSection> 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<void> _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<AppSection> 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<Widget>((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,
),
],
),
),
);
}
}

View File

@ -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<DoorareaPersonApplyPage> createState() =>
_DoorareaPersonApplyPageState();
}
class _DoorareaPersonApplyPageState extends State<DoorareaPersonApplyPage> {
Map<String, dynamic> pd = {};
bool _agreed = false;
//
List<dynamic> _deptList = [];
List<Map> _personList = [];
List<String> signImages = [];
@override
void initState() {
super.initState();
_getDept();
}
//
Future<void> _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<void> _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<File> 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<void> _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);
// });
// }
// }
}

View File

@ -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<DoorareaPersonRecordPage> {
// Data and state variables
// List<dynamic> list = [];
final List<Map<String, dynamic>> 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<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
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<void> _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<String, dynamic> 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<String, dynamic> 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()),
],
),
);
}
}

View File

@ -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<OnlylookDoorareaPerson> createState() => _OnlylookDoorareaPersonState();
}
class _OnlylookDoorareaPersonState extends State<OnlylookDoorareaPerson> {
//
final Map<String, String> applicationInfo = {
'mingcheng': '项目名称',
'bumen': '审核人员部门',
'renyuan': '审核人员',
'shijian': '2024-01-01 至 2024-12-31',
'gangqu': '访问港区',
'diqu': '访问地区',
};
//
final List<Map<String, String>> 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), // 使widthheight
//
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<String, String> 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: '删除')
// ],
// ),
],
),
),
);
}
}

View File

@ -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<OnlylookPersonApplication> createState() => _OnlylookPersonApplicationState();
}
class _OnlylookPersonApplicationState extends State<OnlylookPersonApplication> {
//
final Map<String, String> applicationInfo = {
'mingcheng': '项目名称',
'bumen': '审核人员部门',
'renyuan': '审核人员',
'shijian': '2024-01-01 至 2024-12-31',
'gangqu': '访问港区',
'diqu': '访问地区',
};
//
final List<Map<String, String>> 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), // 使widthheight
//
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<String, String> 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,
),
),
],
),
);
}
}

View File

@ -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<SignInstructionsWebview> createState() => _SignInstructionsWebviewState(name);
// _SignInstructionsWebviewState(this.name);
}
class _SignInstructionsWebviewState extends State<SignInstructionsWebview> {
late final WebViewController _controller;
final String name;
ValueNotifier<double> loadingProgress = ValueNotifier(0.0);
ValueNotifier<bool> isLoading = ValueNotifier(true);
_SignInstructionsWebviewState(this.name);
List<String> 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<bool>(
// 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<void> _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);
});
}
}
}

View File

@ -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<HomePage>
int _currentPage = 0;
bool _isMobileSelected = true; //
void startScan() async {
final result = await pushPage(
@ -750,6 +753,7 @@ class HomePageState extends RouteAwareState<HomePage>
case "安环检查":
break;
case "口门门禁":
pushPage(DoorcarTabPage(), context);
break;
case "入港培训":
pushPage(StudyTabListPage(), context);