import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/ItemWidgetFactory.dart'; import 'package:qhd_prevention/pages/home/danger_auto_scrollList.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/userInfo_page.dart'; import 'package:qhd_prevention/pages/home/work/danger_page.dart'; import 'package:qhd_prevention/pages/home/work/danger_wait_list_page.dart'; import 'package:qhd_prevention/pages/home/workSet_page.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 { late int _eight_work_count = 0; late int _safetyEnvironmentalInspection = 0; late final List> buttonInfos; /// 我的工作 List> workInfos = []; final List> pcData = [ { "index": 1, "detail": {"jiancha": "2", "yinhuan": "20", "yanshou": "4"}, }, { "index": 2, "detail": {"jiancha": "4", "yinhuan": "10", "yanshou": "5"}, }, { "index": 3, "detail": {"jiancha": "3", "yinhuan": "23", "yanshou": "3"}, }, ]; final List> tagLabels = [ ['我', '的'], ['部', '门'], ['监', '管'], ]; Future _onRefresh() async { // 模拟网络请求 await Future.delayed(const Duration(seconds: 2)); // 刷新数据逻辑,如 fetchData() setState(() { // TODO: 更新数据源 }); } @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("隐患播报"), const SizedBox(height: 10), _buildPCDataSection(), SizedBox(height: 50), ], ), ), ); } Widget _buildWorkSection(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // _widgetTopTip(title: "我的工作"), 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), ], ), ); } /// 定义 item 宽度 double _itemWidth(BuildContext context) { final screenW = MediaQuery.of(context).size.width; return (screenW - 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: () { final index = entry.key; // 你的导航逻辑 if (index == 0) { pushPage(UserinfoPage(), context); } else if (index == 1) { pushPage(WorkSetPage(), context); } else if (index == 2) { pushPage(RiskControlPage(), context); } else if (index == 3) { pushPage(LowPage(), context); } else if (index == 7) { pushPage(StudyGardenPage(), context); } }, ); }).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, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset(iconPath, width: 40, height: 40), const SizedBox(height: 5), Text(label, style: const TextStyle(fontSize: 14)), ], ), ), if (unreadCount > 0) Positioned( right: -4, top: -4, 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: Text( unreadCount > 99 ? '99+' : '$unreadCount', style: const TextStyle( color: Colors.white, fontSize: 10, height: 1, ), textAlign: TextAlign.center, ), ), ), ], ), ), ); } // 排查数据列表 item 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 int 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(DangerPage(), 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( crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset(icon, width: 35, height: 35), const SizedBox(width: 15), 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, ), ], ), ), ], ), ), ); } void initState() { super.initState(); 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, }, ]; _fetchData(); // 初始化时请求 } Future _fetchData() async { try { // “我的工作” 数量 final raw = await ApiService.getWork(); // 如果拿到的是 String,就 decode;如果本来就是 Map,就直接用 final Map data = raw is String ? json.decode(raw as String) as Map : raw; final hidCount = data['hidCount'] as Map; setState(() { workInfos = [ { "icon": "assets/icon-apps/jobico1.png", "index": 1, "detail": "待排查", "num": (hidCount['dpc'] ?? 0).toString(), }, { "icon": "assets/icon-apps/jobico2.png", "index": 2, "detail": "待整改", "num": (hidCount['dzg'] ?? 0).toString(), }, { "icon": "assets/icon-apps/jobico3.png", "index": 3, "detail": "已超期", "num": (hidCount['ycq'] ?? 0).toString(), }, { "icon": "assets/icon-apps/jobico4.png", "index": 4, "detail": "待验收", "num": (hidCount['dys'] ?? 0).toString(), }, { "icon": "assets/icon-apps/jobico5.png", "index": 5, "detail": "已验收", "num": (hidCount['yys'] ?? 0).toString(), }, ]; }); // 安全检查数 final checkJson = await ApiService.getSafetyEnvironmentalInspectionCount(); setState(() { int confirmCount = int.parse(checkJson['confirmCount']['confirmCount']); int repulseCount = int.parse(checkJson['repulseCount']['repulseCount']); int repulseAndCheckCount = int.parse(checkJson['repulseAndCheckCount']['repulseAndCheckCount']); _safetyEnvironmentalInspection = confirmCount + repulseCount + repulseAndCheckCount; }); // 特殊作业红点 final redPointJson = await ApiService.getRedPoint(); setState(() { final countMap = redPointJson['count'] as Map; for (var item in countMap.values) { _eight_work_count += (item ?? 0) as int; } }); } catch (e) { // 出错时可以 Toast 或者在页面上显示错误状态 print('加载首页数据失败:$e'); } } }