重点安全 部分
parent
a2f1e1fdef
commit
4e0bad563d
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 -------------–-------------------- 我的 -------------–--------------------
|
||||
|
||||
/// 问题反馈
|
||||
|
|
|
|||
|
|
@ -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 // 允许用户交互(系统指示器不阻止交互)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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¤tPage=$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()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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¤tPage=$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()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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¤tPage=$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()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
292
pubspec.lock
292
pubspec.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue