flutter_integrated_whb/lib/pages/home/home_page.dart

496 lines
17 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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/SafeCheck/safeCheck_tab_list.dart';
import 'package:qhd_prevention/pages/home/home_danger_page.dart';
import 'package:qhd_prevention/pages/home/low_page.dart';
import 'package:qhd_prevention/pages/home/risk/riskControl_page.dart';
import 'package:qhd_prevention/pages/home/study/study_garden_page.dart';
import 'package:qhd_prevention/pages/home/tap/tabList/work_tab_list_page.dart';
import 'package:qhd_prevention/pages/home/userInfo_page.dart';
import 'package:qhd_prevention/pages/home/work/danger_page.dart';
import 'package:qhd_prevention/pages/app/danger_wait_list_page.dart';
import 'package:qhd_prevention/pages/home/work/laws_regulations_page.dart';
import 'package:qhd_prevention/pages/home/workSet_page.dart';
import 'Safetymeeting/safety_meeting_list_page.dart';
import 'hidden_roll_widget.dart';
import '../../http/ApiService.dart';
import '../../tools/tools.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _eight_work_count = 0;
int _safetyEnvironmentalInspection = 0;
String _workKey(int idx) {
switch (idx) {
case 1:
return 'dpc'; // 待排查
case 2:
return 'dzg'; // 待整改
case 3:
return 'ycq'; // 已超期
case 4:
return 'dys'; // 待验收
case 5:
return 'yys'; // 已验收
default:
return '';
}
}
/// 按钮信息
List<Map<String, dynamic>> buttonInfos = [
{"icon": "assets/icon-apps/home-base.png", "title": "人员信息", "unreadCount": 0},
{"icon": "assets/icon-apps/home-rili.png", "title": "工作安排", "unreadCount": 0},
{"icon": "assets/icon-apps/home-risk.png", "title": "风险布控", "unreadCount": 0},
{"icon": "assets/icon-apps/home-fl.png", "title": "法律法规", "unreadCount": 0},
{"icon": "assets/icon-apps/home-gw.png", "title": "特殊作业", "unreadCount": 0},
{"icon": "assets/icon-apps/home-zdgcgl.jpg", "title": "重点工程管理", "unreadCount": 0},
{"icon": "assets/icon-apps/home-cns.png", "title": "安全承诺", "unreadCount": 0},
{"icon": "assets/icon-apps/home-study.png", "title": "学习园地", "unreadCount": 0},
{"icon": "assets/icon-apps/home-base.png", "title": "安全检查", "unreadCount": 0},
{"icon": "assets/icon-apps/home-speEquip.jpg", "title": "设备巡检", "unreadCount": 0},
{"icon": "assets/icon-apps/safetymeeting.png", "title": "安全例会", "unreadCount": 0},
{"icon": "assets/icon-apps/home-xj.png", "title": "燃气巡检", "unreadCount": 0},
];
/// 我的工作
List<Map<String, dynamic>> workInfos = [
{"icon": "assets/icon-apps/jobico1.png", "index": 1, "detail": "待排查", "num": '0'},
{"icon": "assets/icon-apps/jobico2.png", "index": 2, "detail": "待整改", "num": '0'},
{"icon": "assets/icon-apps/jobico3.png", "index": 3, "detail": "已超期", "num": '0'},
{"icon": "assets/icon-apps/jobico4.png", "index": 4, "detail": "待验收", "num": '0'},
{"icon": "assets/icon-apps/jobico5.png", "index": 5, "detail": "已验收", "num": '0'},
];
/// 排查数据
List<Map<String, dynamic>> pcData = [
{"index": 1, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}},
{"index": 2, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}},
{"index": 3, "detail": {"jiancha": '0', "yinhuan": '0', "yanshou": '0'}},
];
/// 隐患播报列表及状态
List<Map<String, dynamic>> hiddenList = [];
bool _initialLoadingHidden = true;
final List<List<String>> tagLabels = [
['', ''],
['', ''],
['', ''],
];
@override
void initState() {
super.initState();
_onRefresh();
}
Future<void> _onRefresh() async {
await BadgeManager().initAllModules();
await Future.wait([
_fetchData(),
_fetchHiddenList(showLoading: false),
]);
}
Future<void> _fetchHiddenList({bool showLoading = true}) async {
// 保留已有列表仅首次显示loading
if (showLoading && hiddenList.isEmpty) setState(() {});
try {
final res = await ApiService.getHiddenRoll().timeout(Duration(seconds: 10));
final list = (res['hiddenList'] as List).cast<Map<String, dynamic>>();
setState(() {
hiddenList = list;
_initialLoadingHidden = false;
});
} catch (e) {
// 超时或失败且已有数据,则不处理
if (hiddenList.isEmpty) {
setState(() {
_initialLoadingHidden = false;
});
}
}
}
Future<void> _fetchData() async {
try {
// “我的工作”数据
final data = await ApiService.getWork();
final hidCount = data['hidCount'] as Map<String, dynamic>? ?? {};
// 告知BadgeManager去更新“安全巡检”和“八项作业”角标
BadgeManager().updateEnvInspectCount();
BadgeManager().updateEightWorkCount();
// 拉取其他数据
final results = await Future.wait([
ApiService.getUserData(),
ApiService.getDeptData(),
ApiService.getSuperviseDeptData(),
]);
final myData = results[0];
final deptData = results[1];
final superDeptData= results[2];
//更新页面状态
setState(() {
// ———— 更新 workInfos ————
workInfos = workInfos.map((info) {
final idx = info['index'] as int;
final key = _workKey(idx);
final num = (hidCount[key] ?? 0).toString();
return {...info, 'num': num};
}).toList();
// ———— 从 BadgeManager 拿最新的本页角标 ————
_safetyEnvironmentalInspection = BadgeManager().envInspectCount;
_eight_work_count = BadgeManager().eightWorkCount;
// ———— 更新 buttonInfos 中两个角标位置 ————
buttonInfos = buttonInfos.map((info) {
switch (info['title'] as String) {
case '特殊作业':
info['unreadCount'] = _eight_work_count;
break;
case '安全检查':
info['unreadCount'] = _safetyEnvironmentalInspection;
break;
default:
// 其它保持原样
break;
}
return info;
}).toList();
// ———— 更新排查数据 pcData ————
pcData = [
myData,
deptData,
superDeptData,
].asMap().entries.map((entry) {
final idx = entry.key;
final pdMap = (entry.value['pd'] as Map<String, dynamic>? ) ?? {};
return {
'index': idx + 1,
'detail': {
'jiancha': pdMap['check_count']?.toString() ?? '0',
'yinhuan': pdMap['hidden_count']?.toString() ?? '0',
'yanshou': pdMap['rectify_count']?.toString() ?? '0',
},
};
}).toList();
});
} catch (e) {
debugPrint('加载首页数据失败:$e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: _onRefresh,
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.all(10),
children: [
ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Image.asset('assets/images/banner.jpg', fit: BoxFit.cover),
),
const SizedBox(height: 10),
_buildIconSection(context),
const SizedBox(height: 10),
_buildWorkSection(context),
const SizedBox(height: 10),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.white,
),
child: Column(
children: [
ListItemFactory.createBuildSimpleSection("隐患播报"),
_initialLoadingHidden && hiddenList.isEmpty
? SizedBox(
height: 150,
child: Center(child: CircularProgressIndicator()),
)
: HiddenRollWidget(hiddenList: hiddenList),
],
)
),
const SizedBox(height: 10),
_buildPCDataSection(),
SizedBox(height: 20),
],
),
),
);
}
Widget _buildWorkSection(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListItemFactory.createBuildSimpleSection("我的工作"),
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 10),
child: LayoutBuilder(
builder: (context, constraints) {
const spacing = 10.0;
final totalWidth = constraints.maxWidth;
final itemWidth = (totalWidth - spacing * 2) / 3;
return Wrap(
spacing: spacing,
runSpacing: spacing,
children: workInfos.map((info) {
return SizedBox(
width: itemWidth,
child: _buildGridItem(
context,
icon: info["icon"]!,
title: info["num"]!,
subtitle: info["detail"]!,
index: info["index"]!,
),
);
}).toList(),
);
},
),
),
],
),
);
}
Widget _buildPCDataSection() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListItemFactory.createBuildSimpleSection("排查数据"),
...pcData.map(_widgetPCDataItem),
],
),
);
}
double _itemWidth(BuildContext context) => (MediaQuery.of(context).size.width - 20) / 4;
Widget _buildIconSection(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Wrap(
runSpacing: 16,
children: buttonInfos.asMap().entries.map((entry) {
final idx = entry.key;
final info = entry.value;
return _buildIconButton(
context: context,
iconPath: info["icon"] as String,
label: info["title"] as String,
unreadCount: info["unreadCount"] as int,
onPressed: () async {
switch (idx) {
case 0:// 人员信息
pushPage(UserinfoPage(), context);
break;
case 1:// 法律法规
pushPage(WorkSetPage(), context);
break;
case 2:// 风险布控
pushPage(RiskControlPage(), context);
break;
case 3:// 法律法规
pushPage(LawsRegulationsPage(), context);
break;
case 4:// 八项作业
await pushPage(WorkTabListPage(), context);
break;
case 5: // 重点工程管理
await pushPage(KeyprojectsTabList(), context);
break;
case 7:
pushPage(StudyGardenPage(), context);
break;
case 8: // 安全检查
await pushPage(SafecheckTabList(), context);
break;
case 10:
pushPage(SafetyMeetingListPage(), context);
break;
case 11:
pushPage(HomeNfcListPage(), context);
break;
}
_onRefresh();
},
);
}).toList(),
),
);
}
Widget _buildIconButton({
required BuildContext context,
required String iconPath,
required String label,
required VoidCallback onPressed,
int unreadCount = 0,
}) {
final w = _itemWidth(context);
return InkWell(
onTap: onPressed,
borderRadius: BorderRadius.circular(8),
child: SizedBox(
width: w,
child: Stack(
clipBehavior: Clip.none,
children: [
Align(
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(iconPath, width: 40, height: 40),
const SizedBox(height: 5),
Text(label, style: const TextStyle(fontSize: 14)),
],
),
),
if (unreadCount > 0)
Positioned(
right: 20,
top: -5,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
decoration: BoxDecoration(color: Colors.red, borderRadius: BorderRadius.circular(10)),
constraints: const BoxConstraints(minWidth: 16, minHeight: 16),
child: Center(
child: Text(
unreadCount > 99 ? '99+' : '$unreadCount',
style: const TextStyle(color: Colors.white, fontSize: 11, height: 1),
textAlign: TextAlign.center,
),
)
),
),
],
),
),
);
}
Widget _widgetPCDataItem(Map<String, dynamic> item) {
final detail = item["detail"] as Map<String, String>;
final values = [detail["jiancha"]!, detail["yinhuan"]!, detail["yanshou"]!];
const labels = ["检查数", "发现隐患数", "已验收隐患数"];
const colors = [Color(0xFF3283FF), Color(0xFFF37B1D), Color(0xFF41B852)];
final idx = int.tryParse(item["index"].toString())! - 1;
return Padding(
padding: const EdgeInsets.fromLTRB(15, 0, 10, 15),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
for (var i = 0; i < 3; i++)
Column(
children: [
Text(values[i], style: TextStyle(color: colors[i], fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 4),
Text(labels[i], style: TextStyle(color: Colors.black38, fontSize: 15)),
],
),
Container(
color: idx == 0 ? Colors.red : Colors.blue,
width: 20,
height: 40,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(tagLabels[idx][0], style: TextStyle(color: Colors.white, fontSize: 12)),
Text(tagLabels[idx][1], style: TextStyle(color: Colors.white, fontSize: 12)),
],
),
),
],
),
SizedBox(height: 10),
Divider(height: 1, color: Colors.black12),
],
),
);
}
Widget _buildGridItem(BuildContext context, {required String icon, required String title, required String subtitle, required int index}) {
return GestureDetector(
onTap: () {
if (index == 1) {
pushPage(HomeDangerPage(), context);
} else if (index == 2) {
pushPage(DangerWaitListPage(DangerType.wait, 2), context);
} else if (index == 3) {
pushPage(DangerWaitListPage(DangerType.expired, 3), context);
} else if (index == 4) {
pushPage(DangerWaitListPage(DangerType.waitAcceptance, 4), context);
} else if (index == 5) {
pushPage(DangerWaitListPage(DangerType.acceptance, 5), context);
}
},
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(color: const Color(0xfbf9f9ff), borderRadius: BorderRadius.circular(6)),
child: Row(
children: [
Image.asset(icon, width: 35, height: 35),
const SizedBox(width: 5),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), maxLines: 1, overflow: TextOverflow.ellipsis),
const SizedBox(height: 4),
Text(subtitle, style: const TextStyle(fontSize: 14, color: Colors.black), maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
),
],
),
),
);
}
}