重点安全 部分

main
hs 2025-08-12 10:57:07 +08:00
parent a2f1e1fdef
commit 4e0bad563d
12 changed files with 1688 additions and 184 deletions

View File

@ -249,10 +249,13 @@ class ListItemFactory {
required String title,
String yesLabel = '',
String noLabel = '',
required bool groupValue,
required bool? groupValue,
required ValueChanged<bool> onChanged,
double verticalPadding = 15,
double horizontalPadding = 10,
bool isEdit = true,
String text = '',
}) {
return Padding(
padding: EdgeInsets.only(
@ -279,33 +282,36 @@ class ListItemFactory {
),
),
),
Row(
children: [
Row(
children: [
Radio<bool>(
activeColor: Colors.blue,
value: true,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(yesLabel),
],
),
const SizedBox(width: 16),
Row(
children: [
Radio<bool>(
activeColor: Colors.blue,
value: false,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(noLabel),
],
),
],
),
if (isEdit)
Row(
children: [
Row(
children: [
Radio<bool>(
activeColor: Colors.blue,
value: true,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(yesLabel),
],
),
const SizedBox(width: 16),
Row(
children: [
Radio<bool>(
activeColor: Colors.blue,
value: false,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(noLabel),
],
),
],
),
if (!isEdit)
Text(text, style: TextStyle(),)
],
),
),
@ -313,8 +319,10 @@ class ListItemFactory {
}
/// +
static Widget createBuildSimpleSection(String title, {double horPadding = 10}) {
static Widget createBuildSimpleSection(
String title, {
double horPadding = 10,
}) {
return Container(
decoration: BoxDecoration(
color: Colors.white,

View File

@ -929,6 +929,138 @@ U6Hzm1ninpWeE+awIDAQAB
);
}
///TODO --------------------------------- ---------------------------------
static Future<Map<String, dynamic>> getKeyProjectCount() {
return HttpManager().request(
basePath,
'/app/keyprojectcheck/keyProjectCount',
method: Method.post,
data: {
"CORPINFO_ID":SessionService.instance.corpinfoId,
"loginUserId":SessionService.instance.loginUserId,
},
);
}
///
static Future<Map<String, dynamic>> getKeyProjectList(Map data, String url) {
return HttpManager().request(
basePath,
url,
method: Method.post,
data: {
"CORPINFO_ID":SessionService.instance.corpinfoId,
"UserId":SessionService.instance.loginUserId,
...data
},
);
}
///
static Future<Map<String, dynamic>> getKeyProjectDeatail(String OUTSOURCED_ID) {
return HttpManager().request(
basePath,
'/app/keyProjects/getOutsourced',
method: Method.post,
data: {
"OUTSOURCED_ID":OUTSOURCED_ID,
},
);
}
///
static Future<Map<String, dynamic>> sureKeyProjectState(String OUTSOURCED_ID, String State) {
return HttpManager().request(
basePath,
'/app/keyProjects/updateState',
method: Method.post,
data: {
"OUTSOURCED_ID":OUTSOURCED_ID,
'OPERATOR' : SessionService.instance.loginUserId,
'STATE':State
},
);
}
///
static Future<Map<String, dynamic>> getSafeCheckList(Map data, String url) {
return HttpManager().request(
basePath,
url,
method: Method.post,
data: {
"CORPINFO_ID":SessionService.instance.corpinfoId,
"UserId":SessionService.instance.loginUserId,
...data
},
);
}
///
static Future<Map<String, dynamic>> getSafeCheckReciordList(Map data, String url) {
return HttpManager().request(
basePath,
url,
method: Method.post,
data: {
"CORPINFO_ID":SessionService.instance.corpinfoId,
"UserId":SessionService.instance.loginUserId,
...data
},
);
}
///
static Future<Map<String, dynamic>> addSafeCheckReciord(String OUTSOURCED_ID) {
return HttpManager().request(
basePath,
'/app/keyProjects/goEdit',
method: Method.post,
data: {
"OUTSOURCED_ID":OUTSOURCED_ID,
"tm":DateTime.now().millisecondsSinceEpoch.toString(),
},
);
}
///
static Future<Map<String, dynamic>> getSafeCheckPersonList(String UNITS_ID, String NOMAIN) {
return HttpManager().request(
basePath,
'/app/keyProjects/listAllPersonnel',
method: Method.post,
data: {
"UNITS_ID":UNITS_ID,
'NOMAIN':NOMAIN,
"tm":DateTime.now().millisecondsSinceEpoch.toString(),
},
);
}
///
static Future<Map<String, dynamic>> getSafeCheckTypeList() {
return HttpManager().request(
basePath,
'/dictionaries/listSelectTreeByTkiTree?tm=${DateTime.now().millisecondsSinceEpoch.toString()}',
method: Method.post,
data: {
"DICTIONARIES_ID":'60e6481d96e44a5390ff5c347c4d1ffe',
"tm":DateTime.now().millisecondsSinceEpoch.toString(),
},
);
}
///
static Future<Map<String, dynamic>> getSafeCheckToUnitList(String OUTSOURCED_ID) {
return HttpManager().request(
basePath,
'/app/keyProjects/listAllUnits',
method: Method.post,
data: {
"CORPINFO_ID": SessionService.instance.corpinfoId,
"OUTSOURCED_ID":OUTSOURCED_ID,
},
);
}
///TODO --------------------------------- ---------------------------------
///

View File

@ -39,7 +39,7 @@ void main() async {
..indicatorSize = 36.0 //
..radius = 0 //
..progressColor = Colors.blue //
..backgroundColor = Colors.grey.shade100
..backgroundColor = Colors.grey.shade300
..indicatorColor = Colors.blue //
..textColor = Colors.black //
..userInteractions = false //

View File

@ -0,0 +1,212 @@
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/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart';
class KeyprojectDetail extends StatefulWidget {
const KeyprojectDetail({super.key, required this.OUTSOURCED_ID});
final String OUTSOURCED_ID;
@override
State<KeyprojectDetail> createState() => _KeyprojectDetailState();
}
class _KeyprojectDetailState extends State<KeyprojectDetail> {
late Map<String, dynamic> info = {};
@override
void initState() {
// TODO: implement initState
super.initState();
_getData();
}
Future<void> _getData() async {
LoadingDialogHelper.show();
final result = await ApiService.getKeyProjectDeatail(widget.OUTSOURCED_ID);
try {
setState(() {
info = result['pd'] ?? {};
});
} catch (e) {
print('加载数据失败:$e');
ToastUtil.showNormal(context, '加载数据失败:$e');
}
LoadingDialogHelper.hide();
}
Future<void> onUpdateState(String state) async {
//
String content = '';
if (state == '1') {
content = '确定同意开工吗?';
} else if (state == '2') {
content = '确定同意结束吗?';
} else {
content = '确定操作吗?';
}
final bool confirmed =
await showDialog<bool>(
context: context,
builder:
(ctx) => CustomAlertDialog(
title: '提示',
content: content,
onConfirm: () => Navigator.of(ctx).pop(false),
),
) ??
false;
if (!confirmed) return;
LoadingDialogHelper.show();
try {
final response = await ApiService.sureKeyProjectState(
widget.OUTSOURCED_ID,
state,
);
LoadingDialogHelper.hide();
if (response['result'] == 'success') {
Navigator.of(context).pop();
} else {
ToastUtil.showNormal(context, '请求失败');
}
} catch (e) {
ToastUtil.showNormal(context, '请求异常:$e');
}
}
Widget lineItem({
required String label,
required bool isEditable,
String? text,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ItemListWidget.singleLineTitleText(
label: label,
isEditable: isEditable,
text: text ?? '',
),
const Divider(height: 1, thickness: 1),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: "重点工程信息"),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
child: Column(
children: [
ItemListWidget.itemContainer(
Column(
children: [
ItemListWidget.singleLineTitleText(
label: '重点工程名称:',
isEditable: false,
text: info['OUTSOURCED_NAME'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '计划工期:',
isEditable: false,
text:
'${info['STARTTIME'] ?? ''}${info['ENDTIME'] ?? ''}',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '合同号:',
isEditable: false,
text: info['CONTRACT_NUM'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '施工相关方:',
isEditable: false,
text: info['UNITS_NAME'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '相关方单位工程负责人:',
isEditable: false,
text: info['UNITS_PIC_NAME'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '相关方单位负责人手机:',
isEditable: false,
text: info['UNITS_PHONE'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '经度:',
isEditable: false,
text: info['WORK_LONGITUDE'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '纬度:',
isEditable: false,
text: info['WORK_LATITUDE'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '具体位置:',
isEditable: false,
text: info['LOCATION'] ?? '',
),
],
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (info['STATE'] == '-1') ...[
SizedBox(
width: 140,
child: CustomButton(
text: '工程开始',
backgroundColor: Colors.blue,
onPressed: () => onUpdateState('1'),
),
),
const SizedBox(width: 12),
],
if (info['STATE'] == '-2') ...[
SizedBox(
width: 140,
child: CustomButton(
text: '工程结束',
backgroundColor: Colors.blue,
onPressed: () => onUpdateState('2'),
),
),
const SizedBox(width: 12),
],
SizedBox(
width: 140,
child: CustomButton(
text: '返回',
backgroundColor: Colors.blue,
onPressed: () => Navigator.pop(context),
),
),
],
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,291 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/pages/KeyProjects/KeyProject/keyProject_detail.dart';
import 'package:qhd_prevention/pages/my_appbar.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';
import 'package:qhd_prevention/http/ApiService.dart';
class KeyprojectListPage extends StatefulWidget {
final String flow;
const KeyprojectListPage({Key? key, required this.flow}) : super(key: key);
@override
_KeyprojectListPageState createState() => _KeyprojectListPageState();
}
class _KeyprojectListPageState extends State<KeyprojectListPage> {
// Data and state variables
List<dynamic> list = [];
int currentPage = 1;
int rows = 10;
int totalPage = 1;
bool isLoading = false;
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> stepList = [];
int sindex = 0;
String searchKeywords = '';
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_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 = {'KEYWORDS': searchKeywords};
final url =
'/app/keyProjects/outSouceslistPage?showCount=10&currentPage=$currentPage';
final response = await ApiService.getKeyProjectList(data, url);
setState(() {
if (currentPage == 1) {
list = response['varList'];
} else {
list.addAll(response['varList']);
}
Map<String, dynamic> page = response['page'];
totalPage = page['totalPage'] ?? 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) async {
pushPage(KeyprojectDetail(OUTSOURCED_ID: item['OUTSOURCED_ID']), context);
}
Widget _buildListItem(Map<String, dynamic> item) {
bool showBadge =
(item['STATE'] == '-1' || item['STATE'] == '-2') &&
(item['CREATOR'] != null &&
item['CREATOR'].toString() == SessionService.instance.loginUserId);
return Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () => _goToDetail(item),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// +
Row(
children: [
Expanded(
child: Text(
"${item['OUTSOURCED_NAME'] ?? ''}",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
if (showBadge)
Container(
margin: const EdgeInsets.only(left: 8.0),
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 2.0,
),
height: 18,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xFFdd514c),
borderRadius: BorderRadius.circular(96),
),
child: const Text(
'1',
style: TextStyle(color: Colors.white, fontSize: 10),
),
),
],
),
const SizedBox(height: 8),
// IS_CORP_TYPE / vue
if (item['IS_CORP_TYPE'] == '1') ...[
Text("主管部门:${item['Q_COMPETENT_DEPT_NAME'] ?? ''}"),
const SizedBox(height: 6),
Text("监督部门:${item['DEPARTMENT_NAME'] ?? ''}"),
] else if (item['IS_CORP_TYPE'] == '0') ...[
Text("主管部门:${item['MANAGER_DEPARTMENT_NAME'] ?? ''}"),
const SizedBox(height: 6),
Text("监管部门:${item['DEPARTMENT_NAME'] ?? ''}"),
],
const SizedBox(height: 8),
// +
Row(
children: [
Expanded(
child: Text(
"相关方单位负责人:${item['UNITS_PIC_NAME'] ?? ''}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
"电话:${item['UNITS_PHONE'] ?? ''}",
textAlign: TextAlign.right,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 8),
//
Text(
"定位坐标:${(item['WORK_LONGITUDE'] != null && item['WORK_LATITUDE'] != null && item['WORK_LONGITUDE'].toString().isNotEmpty) ? '${item['WORK_LONGITUDE']}*${item['WORK_LATITUDE']}' : ''}",
),
const SizedBox(height: 6),
// vue
InkWell(
onTap: () {},
child: Text(
"状态:${item['STATE'] == '-1'
? '开工申请中'
: item['STATE'] == '-2'
? '结束申请中'
: item['STATE'] == '0'
? '未开工'
: item['STATE'] == '1'
? '进行中'
: '已结束'}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(),
CustomButton(
onPressed: () { _goToDetail(item);},
text: '查看',
height: 30,
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
textStyle: TextStyle(fontSize: 13, color: Colors.white),
backgroundColor: Colors.blue,
),
],
),
],
),
),
),
);
}
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]);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: MyAppbar(title: widget.flow),
body: Column(
children: [
// Filter bar
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8),
child: Row(
children: [
Expanded(
flex: 2,
child: SearchBarWidget(
showResetButton: false,
hintText: "请输入关键字",
// isClickableOnly: true,
onSearch: (text) {
_search();
},
controller: _searchController,
),
),
],
),
),
const Divider(height: 1),
// List
Expanded(child: _buildListContent()),
],
),
);
}
}

View File

@ -0,0 +1,237 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/pages/KeyProjects/KeyProject/keyProject_detail.dart';
import 'package:qhd_prevention/pages/KeyProjects/SafeCheck/safeCheck_detail.dart';
import 'package:qhd_prevention/pages/my_appbar.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';
import 'package:qhd_prevention/http/ApiService.dart';
class CheckListPage extends StatefulWidget {
const CheckListPage({super.key, required this.OUTSOURCED_ID});
final String OUTSOURCED_ID;
@override
_CheckListPageState createState() => _CheckListPageState();
}
class _CheckListPageState extends State<CheckListPage> {
// Data and state variables
List<dynamic> list = [];
int currentPage = 1;
int rows = 10;
int totalPage = 1;
bool isLoading = false;
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> stepList = [];
int sindex = 0;
String searchKeywords = '';
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_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 = {'KEYWORDS': searchKeywords, 'OUTSOURCED_ID':widget.OUTSOURCED_ID};
final url =
'/app/keyprojectcheck/list?showCount=10&currentPage=$currentPage';
final response = await ApiService.getSafeCheckReciordList(data, url);
setState(() {
if (currentPage == 1) {
list = response['varList'];
} else {
list.addAll(response['varList']);
}
Map<String, dynamic> page = response['page'];
totalPage = page['totalPage'] ?? 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) async {
pushPage(SafecheckDetail(OUTSOURCED_ID: widget.OUTSOURCED_ID,KEYPROJECTCHECK_ID: item['KEYPROJECTCHECK_ID'], isEdit: false,), context);
}
Widget _buildListItem(Map<String, dynamic> item) {
bool showBadge =
(item['STATE'] == '-1' || item['STATE'] == '-2') &&
(item['CREATOR'] != null &&
item['CREATOR'].toString() == SessionService.instance.loginUserId);
return Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () => _goToDetail(item),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// +
Row(
children: [
Expanded(
child: Text(
"${item['INSPECTION_PLACE'] ?? ''}",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 8),
Text(
"检查状态:${item['INSPECTION_STATUS']}",
),
Text(
"检查类型:${item['INSPECTION_TYPE_NAME']}",
),
Text(
"检查人:${item['INSPECTION_USERS']}",
),
Text(
"被检查人:${item['PERSON_NAME']}",
),
Text(
"检查时间:${item['INSPECTION_TIME_START']}-${item['INSPECTION_TIME_END']}",
),
Text(
"检查隐患数:${item['HIDDEN_COUNT']}",
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(),
CustomButton(
onPressed: () { _goToDetail(item);},
text: '查看',
height: 30,
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
textStyle: TextStyle(fontSize: 13, color: Colors.white),
backgroundColor: Colors.blue,
),
],
),
],
),
),
),
);
}
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]);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: MyAppbar(title: '安全检查记录', actions: [
TextButton(onPressed: () {
pushPage(SafecheckDetail(OUTSOURCED_ID: widget.OUTSOURCED_ID,KEYPROJECTCHECK_ID: '', isEdit: true,), context);
}, child: Text('发起', style: TextStyle(color: Colors.white, fontSize: 16),))
],),
body: Column(
children: [
// Filter bar
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8),
child: Row(
children: [
Expanded(
flex: 2,
child: SearchBarWidget(
showResetButton: false,
hintText: "请输入关键字",
// isClickableOnly: true,
onSearch: (text) {
_search();
},
controller: _searchController,
),
),
],
),
),
const Divider(height: 1),
// List
Expanded(child: _buildListContent()),
],
),
);
}
}

View File

@ -0,0 +1,246 @@
import 'dart:convert';
import 'package:flutter/material.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/toast_util.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/home/tap/item_list_widget.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart';
class SafecheckDetail extends StatefulWidget {
const SafecheckDetail({
super.key,
required this.OUTSOURCED_ID,
required this.KEYPROJECTCHECK_ID,
required this.isEdit,
});
final String OUTSOURCED_ID;
final String KEYPROJECTCHECK_ID;
final bool isEdit;
@override
State<SafecheckDetail> createState() => _SafecheckDetailState();
}
class _SafecheckDetailState extends State<SafecheckDetail> {
late Map<String, dynamic> info = {};
///
late List<dynamic> personList = [];
///
late List<dynamic> typeList = [];
///
late List<dynamic> toCheckUnitList = [];
bool? chooseTitleType = null;
final TextEditingController _unitController = TextEditingController();
final TextEditingController _locationController = TextEditingController();
final TextEditingController _personController = TextEditingController();
@override
void initState() {
// TODO: implement initState
super.initState();
_getData();
}
Future<void> _getData() async {
LoadingDialogHelper.show();
final result = await ApiService.addSafeCheckReciord(widget.OUTSOURCED_ID);
final personData = await ApiService.getSafeCheckPersonList(info['UNITS_ID']??'', '1');
final typeListData = await ApiService.getSafeCheckTypeList();
final toUnitListData = await ApiService.getSafeCheckToUnitList(widget.OUTSOURCED_ID);
try {
setState(() {
info = result['pd'] ?? {};
personList = personData['varList'];
typeList = jsonDecode(typeListData['zTreeNodes']);
toCheckUnitList = toUnitListData['varList'];
if (!FormUtils.hasValue(info, 'UNITS_NAME') && toCheckUnitList.isNotEmpty) {
info['UNITS_NAME'] = toCheckUnitList.first['UNITS_NAME'];
}
if (!FormUtils.hasValue(info, 'UNITS_ID') && toCheckUnitList.isNotEmpty) {
info['UNITS_ID'] = toCheckUnitList.first['UNITS_ID'];
}
});
} catch (e) {
print('加载数据失败:$e');
ToastUtil.showNormal(context, '加载数据失败:$e');
}
LoadingDialogHelper.hide();
}
Future<void> onUpdateState(String state) async {
//
String content = '';
if (state == '1') {
content = '确定同意开工吗?';
} else if (state == '2') {
content = '确定同意结束吗?';
} else {
content = '确定操作吗?';
}
final bool confirmed =
await showDialog<bool>(
context: context,
builder:
(ctx) => CustomAlertDialog(
title: '提示',
content: content,
onConfirm: () => Navigator.of(ctx).pop(false),
),
) ??
false;
if (!confirmed) return;
LoadingDialogHelper.show();
try {
final response = await ApiService.sureKeyProjectState(
widget.OUTSOURCED_ID,
state,
);
LoadingDialogHelper.hide();
if (response['result'] == 'success') {
Navigator.of(context).pop();
} else {
ToastUtil.showNormal(context, '请求失败');
}
} catch (e) {
ToastUtil.showNormal(context, '请求异常:$e');
}
}
Widget lineItem({
required String label,
required bool isEditable,
String? text,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ItemListWidget.singleLineTitleText(
label: label,
isEditable: isEditable,
text: text ?? '',
),
const Divider(height: 1, thickness: 1),
],
);
}
Future<void> _choosePerson() async {
final choice = await BottomPicker.show<String>(
context,
items: personList.map((val) => val['NAME'] as String).toList(),
itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
initialIndex: 0,
);
if (choice != null) {
// choice
setState(() {
info['PERSON_NAME'] = choice;
FocusHelper.clearFocus(context);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: "安全检查发起"),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
child: Column(
children: [
ItemListWidget.itemContainer(
horizontal: 0,
Column(
children: [
ListItemFactory.createYesNoSection(
title: '检查题目:',
groupValue: chooseTitleType,
yesLabel: '安全',
noLabel: '综合',
horizontalPadding: 5,
verticalPadding: 0,
onChanged: (val) {
setState(() {
chooseTitleType = val;
});
},
isEdit: true,
text: info['INSPECTION_CATEGORY'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '被检查单位:',
isEditable: false,
text: info['UNITS_NAME'],
controller: _unitController,
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '被检查单位现场负责人:',
isEditable: widget.isEdit,
onTap: () {
_choosePerson();
},
text: info['PERSON_NAME'] ?? '',
),
const Divider(),
ItemListWidget.singleLineTitleText(
label: '检查场所:',
isEditable: widget.isEdit,
text: info['INSPECTION_PLACE'],
hintText: '请输入检查场所',
controller: _locationController,
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '检查类型:',
isEditable: widget.isEdit,
text: info['INSPECTION_TYPE_NAME'] ?? '',
),
const Divider(),
ItemListWidget.selectableLineTitleTextRightButton(
label: '检查开始时间:',
isEditable: widget.isEdit,
text: info['INSPECTION_TIME_START'] ?? '',
),
],
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 200,
child: CustomButton(
text: '提交',
textStyle: TextStyle(color: Colors.white, fontSize: 17),
backgroundColor: Colors.blue,
onPressed: () => Navigator.pop(context),
),
),
],
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,255 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/pages/KeyProjects/KeyProject/keyProject_detail.dart';
import 'package:qhd_prevention/pages/KeyProjects/SafeCheck/check_list_page.dart';
import 'package:qhd_prevention/pages/my_appbar.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';
import 'package:qhd_prevention/http/ApiService.dart';
class SafecheckListPage extends StatefulWidget {
final String flow;
const SafecheckListPage({Key? key, required this.flow}) : super(key: key);
@override
_SafecheckListPageState createState() => _SafecheckListPageState();
}
class _SafecheckListPageState extends State<SafecheckListPage> {
// Data and state variables
List<dynamic> list = [];
int currentPage = 1;
int rows = 10;
int totalPage = 1;
bool isLoading = false;
final TextEditingController _searchController = TextEditingController();
List<Map<String, dynamic>> stepList = [];
int sindex = 0;
String searchKeywords = '';
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_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 = {'KEYWORDS': searchKeywords};
final url =
'/app/keyProjects/listOutsourced?showCount=10&currentPage=$currentPage';
final response = await ApiService.getKeyProjectList(data, url);
setState(() {
if (currentPage == 1) {
list = response['varList'];
} else {
list.addAll(response['varList']);
}
Map<String, dynamic> page = response['page'];
totalPage = page['totalPage'] ?? 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) async {
pushPage(CheckListPage(OUTSOURCED_ID: item['OUTSOURCED_ID']), context);
}
Widget _buildListItem(Map<String, dynamic> item) {
bool showBadge =
(item['STATE'] == '-1' || item['STATE'] == '-2') &&
(item['CREATOR'] != null &&
item['CREATOR'].toString() == SessionService.instance.loginUserId);
return Card(
color: Colors.white,
margin: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () => _goToDetail(item),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// +
Row(
children: [
Expanded(
child: Text(
"${item['OUTSOURCED_NAME'] ?? ''}",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 8),
// IS_CORP_TYPE / vue
if (item['IS_CORP_TYPE'] == '1') ...[
Text("主管部门:${item['Q_COMPETENT_DEPT_NAME'] ?? ''}"),
const SizedBox(height: 6),
Text("监督部门:${item['DEPARTMENT_NAME'] ?? ''}"),
] else if (item['IS_CORP_TYPE'] == '0') ...[
Text("主管部门:${item['MANAGER_DEPARTMENT_NAME'] ?? ''}"),
const SizedBox(height: 6),
Text("监管部门:${item['DEPARTMENT_NAME'] ?? ''}"),
],
const SizedBox(height: 8),
// +
Row(
children: [
Expanded(
child: Text(
"相关方单位负责人:${item['UNITS_PIC_NAME'] ?? ''}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 12),
Expanded(
child: Text(
"电话:${item['UNITS_PHONE'] ?? ''}",
textAlign: TextAlign.right,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
const SizedBox(height: 8),
//
Text(
"安全检查次数:${item['CHECK_COUNT']}",
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(),
CustomButton(
onPressed: () { _goToDetail(item);},
text: '进入',
height: 30,
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
textStyle: TextStyle(fontSize: 13, color: Colors.white),
backgroundColor: Colors.blue,
),
],
),
],
),
),
),
);
}
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]);
},
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: MyAppbar(title: widget.flow),
body: Column(
children: [
// Filter bar
Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 8),
child: Row(
children: [
Expanded(
flex: 2,
child: SearchBarWidget(
showResetButton: false,
hintText: "请输入关键字",
// isClickableOnly: true,
onSearch: (text) {
_search();
},
controller: _searchController,
),
),
],
),
),
const Divider(height: 1),
// List
Expanded(child: _buildListContent()),
],
),
);
}
}

View File

@ -0,0 +1,118 @@
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/KeyProjects/KeyProject/keyProject_list_page.dart';
import 'package:qhd_prevention/pages/KeyProjects/SafeCheck/safeCheck_list_page.dart';
import 'package:qhd_prevention/pages/home/tap/tabList/work_tab_icon_grid.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
import 'package:qhd_prevention/tools/tools.dart';
class KeyprojectsTabList extends StatefulWidget {
const KeyprojectsTabList({super.key});
@override
State<KeyprojectsTabList> createState() => _KeyprojectsTabListState();
}
class _KeyprojectsTabListState extends State<KeyprojectsTabList> {
late List<Map<String, dynamic>> buttonInfos = [
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "重点工程管理",
"unreadCount": '0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "安全检查管理",
"unreadCount": '0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "隐患管理",
"unreadCount":'0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "处罚管理",
"unreadCount":'0',
},
];
@override
void initState() {
super.initState();
_getData();
}
Future<void> _getData() async {
LoadingDialogHelper.show();
final data = await ApiService.getKeyProjectCount();
LoadingDialogHelper.hide();
setState(() {
final eight_work_count = data['pd'] ?? {};
buttonInfos = [
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "重点工程管理",
"unreadCount": eight_work_count['GC_COUNT'] ?? '0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "安全检查管理",
"unreadCount": '0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "隐患管理",
"unreadCount": eight_work_count['CF_COUNT'] ?? '0',
},
{
"icon": "assets/icon-apps/icon-yxkj-1.png",
"title": "处罚管理",
"unreadCount": eight_work_count['HIDDEN_COUNT'] ?? '0',
},
];
});
}
void _handleItemPressed(int index) async {
//
String title = '';
switch (index) {
case 0: {
title = '重点工程管理';
await pushPage(KeyprojectListPage(flow: title), context);
} break;
case 1: {
title = '安全检查管理';
await pushPage(SafecheckListPage(flow: title), context);
} break;
case 2: title = '隐患管理'; break;
case 3: title = '处罚管理'; break;
default:
print("按钮 $index 被点击");
}
_getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppbar(title: '重点工程管理'),
body: SafeArea(
child: Column(
children: [
ListItemFactory.createBuildSimpleSection('重点工程管理'),
WorkTabIconGrid(
buttonInfos: buttonInfos,
onItemPressed: _handleItemPressed,
),
],
)
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart';
import 'package:qhd_prevention/pages/KeyProjects/keyProjects_tab_list.dart';
import 'package:qhd_prevention/pages/badge_manager.dart';
import 'package:qhd_prevention/pages/home/NFC/home_nfc_list_page.dart';
import 'package:qhd_prevention/pages/home/home_danger_page.dart';
@ -320,21 +321,24 @@ class _HomePageState extends State<HomePage> {
unreadCount: info["unreadCount"] as int,
onPressed: () async {
switch (idx) {
case 0:
case 0://
pushPage(UserinfoPage(), context);
break;
case 1:
case 1://
pushPage(WorkSetPage(), context);
break;
case 2:
case 2://
pushPage(RiskControlPage(), context);
break;
case 3:
case 3://
pushPage(LawsRegulationsPage(), context);
break;
case 4:
case 4://
await pushPage(WorkTabListPage(), context);
break;
case 5: //
await pushPage(KeyprojectsTabList(), context);
break;
case 7:
pushPage(StudyGardenPage(), context);
break;

View File

@ -708,13 +708,14 @@ class ItemListWidget {
);
}
static Widget itemContainer(Widget child) {
static Widget itemContainer(Widget child, {double horizontal = 12}) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: 8),
child: child,
);
}

File diff suppressed because it is too large Load Diff