flutter_integrated_whb/lib/pages/home/home_page.dart

520 lines
16 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 '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<HomePage> {
late int _eight_work_count = 0;
late int _safetyEnvironmentalInspection = 0;
late final List<Map<String, dynamic>> buttonInfos;
/// 我的工作
List<Map<String, dynamic>> workInfos = [];
final List<Map<String, dynamic>> 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<List<String>> tagLabels = [
['', ''],
['', ''],
['', ''],
];
Future<void> _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<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 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), context);
} else if (index == 3) {
pushPage(DangerWaitListPage(DangerType.expired), context);
} else if (index == 4) {
pushPage(DangerWaitListPage(DangerType.waitAcceptance), context);
} else if (index == 5) {
pushPage(DangerWaitListPage(DangerType.acceptance), 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<void> _fetchData() async {
try {
// “我的工作” 数量
final raw = await ApiService.getWork();
// 如果拿到的是 String就 decode如果本来就是 Map就直接用
final Map<String, dynamic> data = raw is String
? json.decode(raw as String) as Map<String, dynamic>
: raw;
final hidCount = data['hidCount'] as Map<String, dynamic>;
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<String, dynamic>;
for (var item in countMap.values) {
_eight_work_count += (item ?? 0) as int;
}
});
} catch (e) {
// 出错时可以 Toast 或者在页面上显示错误状态
print('加载首页数据失败:$e');
}
}
}