import 'dart:async'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/pages/home/NFC/home_nfc_list_page.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 '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 { int _eight_work_count = 0; int _safetyEnvironmentalInspection = 0; /// 按钮信息 List> 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> 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> 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> hiddenList = []; bool _initialLoadingHidden = true; final List> tagLabels = [ ['我', '的'], ['部', '门'], ['监', '管'], ]; @override void initState() { super.initState(); _onRefresh(); } Future _onRefresh() async { await Future.wait([ _fetchData(), _fetchHiddenList(showLoading: false), ]); } Future _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>(); setState(() { hiddenList = list; _initialLoadingHidden = false; }); } catch (e) { // 超时或失败且已有数据,则不处理 if (hiddenList.isEmpty) { setState(() { _initialLoadingHidden = false; }); } } } Future _fetchData() async { try { final data = await ApiService.getWork(); final hidCount = data['hidCount'] as Map? ?? {}; setState(() { workInfos = [ {...workInfos[0], 'num': (hidCount['dpc'] ?? 0).toString()}, {...workInfos[1], 'num': (hidCount['dzg'] ?? 0).toString()}, {...workInfos[2], 'num': (hidCount['ycq'] ?? 0).toString()}, {...workInfos[3], 'num': (hidCount['dys'] ?? 0).toString()}, {...workInfos[4], 'num': (hidCount['yys'] ?? 0).toString()}, ]; }); final results = await Future.wait([ ApiService.getSafetyEnvironmentalInspectionCount(), ApiService.getRedPoint(), ApiService.getUserData(), ApiService.getDeptData(), ApiService.getSuperviseDeptData(), ]); final checkJson = results[0]; final redPointJson = results[1]; final myData = results[2]; final deptData = results[3]; final superDeptData = results[4]; setState(() { int confirmCount = checkJson['confirmCount']?['confirmCount'] ?? 0; int repulseCount = checkJson['repulseCount']?['repulseCount'] ?? 0; int repulseAndCheckCount = checkJson['repulseAndCheckCount']?['repulseAndCheckCount'] ?? 0; _safetyEnvironmentalInspection = confirmCount + repulseCount + repulseAndCheckCount; _eight_work_count = 0; final countMap = redPointJson['count'] as Map? ?? {}; for (var item in countMap.values) { _eight_work_count += (item ?? 0) as int; } 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": _eight_work_count}, {"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": _safetyEnvironmentalInspection}, {"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}, ]; pcData = [ {"index": 1, "detail": { "jiancha": myData['pd']?['check_count']?.toString() ?? '0', "yinhuan": myData['pd']?['hidden_count']?.toString() ?? '0', "yanshou": myData['pd']?['rectify_count']?.toString() ?? '0', }}, {"index": 2, "detail": { "jiancha": deptData['pd']?['check_count']?.toString() ?? '0', "yinhuan": deptData['pd']?['hidden_count']?.toString() ?? '0', "yanshou": deptData['pd']?['rectify_count']?.toString() ?? '0', }}, {"index": 3, "detail": { "jiancha": superDeptData['pd']?['check_count']?.toString() ?? '0', "yinhuan": superDeptData['pd']?['hidden_count']?.toString() ?? '0', "yanshou": superDeptData['pd']?['rectify_count']?.toString() ?? '0', }}, ]; }); } catch (e) { print('加载首页数据失败:$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), ListItemFactory.createBuildSimpleSection("隐患播报"), Container( color: Colors.white, child: _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: () { 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: pushPage(WorkTabListPage(), context); break; case 7: pushPage(StudyGardenPage(), context); break; case 11: pushPage(HomeNfcListPage(), context); break; } }, ); }).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 item) { final detail = item["detail"] as Map; 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), ], ), ), ], ), ), ); } }