QinGang_interested/lib/pages/home/home_page.dart

947 lines
32 KiB
Dart
Raw Normal View History

2026-03-12 10:23:21 +08:00
// home_page.dart (适配新菜单配置)
2025-12-12 09:11:30 +08:00
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:qhd_prevention/common/route_aware_state.dart';
import 'package:qhd_prevention/common/route_service.dart';
2026-02-28 14:38:07 +08:00
import 'package:qhd_prevention/customWidget/custom_alert_dialog.dart';
2025-12-12 09:11:30 +08:00
import 'package:qhd_prevention/customWidget/custom_button.dart';
2026-03-12 10:23:21 +08:00
import 'package:qhd_prevention/customWidget/toast_util.dart';
2026-02-28 14:38:07 +08:00
import 'package:qhd_prevention/http/ApiService.dart';
import 'package:qhd_prevention/pages/home/Study/study_tab_list_page.dart';
2026-03-25 16:09:17 +08:00
import 'package:qhd_prevention/pages/home/doorAndCar/doorCar_tab_page.dart';
2025-12-12 09:11:30 +08:00
import 'package:qhd_prevention/pages/home/scan_page.dart';
import 'package:qhd_prevention/pages/home/unit/unit_tab_page.dart';
import 'package:qhd_prevention/pages/main_tab.dart';
2026-02-28 14:38:07 +08:00
import 'package:qhd_prevention/pages/mine/onboarding_full_page.dart';
2025-12-24 16:07:53 +08:00
import 'package:qhd_prevention/pages/user/choose_userFirm_page.dart';
2025-12-12 09:11:30 +08:00
import 'package:qhd_prevention/pages/user/firm_list_page.dart';
2026-02-28 14:38:07 +08:00
import 'package:qhd_prevention/services/auth_service.dart';
2026-03-12 10:23:21 +08:00
import 'package:qhd_prevention/services/scan_service.dart';
2025-12-12 09:11:30 +08:00
import 'package:qhd_prevention/tools/h_colors.dart';
import 'package:qhd_prevention/tools/tools.dart';
import 'package:shared_preferences/shared_preferences.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.isChooseFirm}) : super(key: key);
final bool isChooseFirm;
@override
HomePageState createState() => HomePageState();
}
class HomePageState extends RouteAwareState<HomePage>
with WidgetsBindingObserver, SingleTickerProviderStateMixin {
final PageController _pageController = PageController();
final ScrollController _scrollController = ScrollController();
2026-03-12 10:23:21 +08:00
bool _isShowCheckLogin = false;
2025-12-12 09:11:30 +08:00
int _currentPage = 0;
2026-03-12 10:23:21 +08:00
bool _isMobileSelected = true;
2025-12-12 09:11:30 +08:00
2026-02-28 14:38:07 +08:00
void startScan() async {
final result = await pushPage(
ScanPage(type: ScanType.Onboarding),
2025-12-12 09:11:30 +08:00
context,
);
2026-03-12 10:23:21 +08:00
if (result == null) return;
ScanService.scan(context, result);
2025-12-12 09:11:30 +08:00
}
static const String _hiddenCacheKey = 'hidden_roll_cache';
2026-03-12 10:23:21 +08:00
// 上面按钮显示状态(与 buttonInfos 顺序对应)
2025-12-12 09:11:30 +08:00
List<bool> _buttonVisibility = [];
2026-03-12 10:23:21 +08:00
// 页面模块可见性(由路由驱动)
bool _showNotificationBar = true;
bool _showWorkStats = true;
bool _showCheckList = true;
2025-12-12 09:11:30 +08:00
List totalList = [];
2026-03-25 16:09:17 +08:00
// 工作统计(示例)
Map<String, int> workStats = {'total': 0, 'processed': 0, 'pending': 0};
// 检查清单示例
List<dynamic> checkLists = [];
// List<Map<String, dynamic>> checkLists = [
// {
// "title": "电工班车间清单",
// "type": "隐患排查",
// "time": "2025-11-17",
// "color": Color(0xFF4CAF50),
// },
// {
// "title": "工地区消防点检清单",
// "type": "消防点检",
// "time": "2025-11-17",
// "color": Color(0xFF2196F3),
// },
// {
// "title": "消防专项检查清单",
// "type": "安环检查",
// "time": "2025-11-17",
// "color": Color(0xFFFF9800),
// },
// ];
2025-12-12 09:11:30 +08:00
final List<String> _notifications = [
"系统通知今晚20:00 将进行系统维护,请提前保存数据。",
"安全提示:施工区请佩戴安全帽并系好安全带。",
"公告本周五集团例会在多功能厅召开9:00准时开始。",
"提醒:请尽快完成隐患整改清单中的待办项。",
];
int _notifIndex = 0;
late final PageController _notifPageController;
Timer? _notifTimer;
2026-03-12 10:23:21 +08:00
// 图标按钮定义(顺序固定)
2025-12-12 09:11:30 +08:00
List<Map<String, dynamic>> buttonInfos = [
{"icon": "assets/images/ico1.png", "title": "单位管理", "unreadCount": 0},
{"icon": "assets/images/ico2.png", "title": "现场监管", "unreadCount": 0},
{"icon": "assets/images/ico3.png", "title": "危险作业", "unreadCount": 0},
2026-03-12 10:23:21 +08:00
{"icon": "assets/images/ico4.png", "title": "隐患治理", "unreadCount": 0}, // 原“隐患处理”改为“隐患治理”
{"icon": "assets/images/ico5.png", "title": "重点作业", "unreadCount": 0},
2025-12-12 09:11:30 +08:00
{"icon": "assets/images/ico6.png", "title": "口门门禁", "unreadCount": 0},
{"icon": "assets/images/ico7.png", "title": "入港培训", "unreadCount": 0},
];
2026-03-12 10:23:21 +08:00
// 浮动 AppBar
2025-12-12 09:11:30 +08:00
bool _showFloatingAppBar = false;
2026-03-12 10:23:21 +08:00
static const double _triggerOffset = 30.0;
2025-12-12 09:11:30 +08:00
static const double _floatingBarHeight = 56.0;
2026-03-12 10:23:21 +08:00
// 按钮标题 -> 权限标识映射(基于新菜单配置)
final Map<String, String> _titleToPerm = {
"单位管理": "dashboard-Unit-Management",
"现场监管": "dashboard-Site-Supervision",
"危险作业": "dashboard-Hazardous-Work",
"隐患治理": "dashboard-Hazard-Management",
"重点作业": "", // 无对应,暂时留空
"口门门禁": "dashboard-Gate-Access-Control",
"入港培训": "dashboard-Study-Training",
};
// 模块权限映射(基于新菜单配置)
final Map<String, String> _modulePerms = {
"notification": "dashboard-roll-notice",
"todoStats": "dashboard-todo-sort",
"checklist": "dashboard-todo-list",
"scan": "dashboard-scan",
2026-04-01 17:53:42 +08:00
"joinFirm": "dashboard-start-work",
2026-03-12 10:23:21 +08:00
};
2026-02-28 14:38:07 +08:00
2026-03-25 16:09:17 +08:00
int pcType=1;
2025-12-12 09:11:30 +08:00
@override
void initState() {
super.initState();
2026-02-28 14:38:07 +08:00
_isShowCheckLogin = widget.isChooseFirm;
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
// 初始按钮全隐藏,避免闪烁
_buttonVisibility = List<bool>.filled(buttonInfos.length, false);
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
_notifPageController = PageController(initialPage: 0);
2025-12-12 09:11:30 +08:00
_notifTimer = Timer.periodic(const Duration(seconds: 3), (timer) {
if (!mounted) return;
final next = (_notifIndex + 1) % _notifications.length;
_notifIndex = next;
try {
_notifPageController.animateToPage(
next,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
} catch (_) {}
2026-02-28 14:38:07 +08:00
_getNeedSafetyCommitment();
2025-12-12 09:11:30 +08:00
setState(() {});
});
_scrollController.addListener(_onScroll);
WidgetsBinding.instance.addObserver(this);
2026-03-12 10:23:21 +08:00
RouteService().addListener(onRouteConfigLoaded);
Future.microtask(() {
_updateModuleAndButtonVisibility();
2025-12-12 09:11:30 +08:00
});
2026-03-25 16:09:17 +08:00
if(_isShowCheckLogin){
_getToDoWorkList(pcType);
}
2026-03-12 10:23:21 +08:00
}
@override
void dispose() {
_notifTimer?.cancel();
_notifPageController.dispose();
_pageController.dispose();
_scrollController.removeListener(_onScroll);
_scrollController.dispose();
WidgetsBinding.instance.removeObserver(this);
try {
RouteService().removeListener(onRouteConfigLoaded);
} catch (_) {}
super.dispose();
}
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
void onRouteConfigLoaded() {
if (!mounted) return;
_updateModuleAndButtonVisibility();
2026-03-05 16:12:47 +08:00
}
2026-03-06 16:15:20 +08:00
2026-03-12 10:23:21 +08:00
/// 根据路由配置更新按钮和模块可见性
void _updateModuleAndButtonVisibility() {
final routeService = RouteService();
final mainTabs = routeService.mainTabs;
if (mainTabs.isEmpty) {
// 路由未加载,保持全隐藏
2026-02-28 14:38:07 +08:00
return;
}
2026-03-12 10:23:21 +08:00
// 更新按钮可见性
final List<bool> newVisibility = List<bool>.filled(buttonInfos.length, false);
for (int i = 0; i < buttonInfos.length; i++) {
final title = buttonInfos[i]['title'] as String;
final perm = _titleToPerm[title];
if (perm == null || perm.isEmpty) continue;
try {
newVisibility[i] = routeService.hasPerm(perm);
} catch (e) {
debugPrint('权限检查异常: $perm, $e');
}
}
// 更新模块可见性
final bool showNotif = routeService.hasPerm(_modulePerms['notification']!);
final bool showTodo = routeService.hasPerm(_modulePerms['todoStats']!);
final bool showChecklist = routeService.hasPerm(_modulePerms['checklist']!);
setState(() {
_buttonVisibility = newVisibility;
_showNotificationBar = showNotif;
_showWorkStats = showTodo;
_showCheckList = showChecklist;
});
}
Future<void> _getNeedSafetyCommitment() async {
if (_isShowCheckLogin) return;
2026-02-28 14:38:07 +08:00
final prefs = await SharedPreferences.getInstance();
final phone = prefs.getString('savePhone') ?? '';
final pwd = prefs.getString('savePass') ?? '';
final result = await AuthApi.userLoginCheckFirm({'phone': phone});
if (result['success']) {
final resData = result['data'];
List firmList = resData['userCorpInfoCOList'] ?? [];
if (firmList.isNotEmpty) {
_isShowCheckLogin = true;
CustomAlertDialog.showAlert(
context,
title: '温馨提示',
content: '您的入职申请已通过',
confirmText: '立即入职',
onConfirm: () async {
Map data = {'unitId': firmList.first['corpinfoId'] ?? ''};
final res = await AuthService.gbsLogin(phone, pwd, data);
LoadingDialogHelper.hide();
if (res['success'] == true) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const MainPage(isChooseFirm: true),
),
);
}
},
);
} else {
_isShowCheckLogin = false;
}
}
}
2025-12-12 09:11:30 +08:00
void _onScroll() {
2026-03-12 10:23:21 +08:00
final offset = _scrollController.hasClients ? _scrollController.offset : 0.0;
2025-12-12 09:11:30 +08:00
final shouldShow = offset >= _triggerOffset;
if (shouldShow != _showFloatingAppBar) {
2026-03-12 10:23:21 +08:00
setState(() => _showFloatingAppBar = shouldShow);
2025-12-12 09:11:30 +08:00
}
}
@override
Future<void> onVisible() async {
final current = CurrentTabNotifier.of(context)?.currentIndex ?? 0;
const myIndex = 0;
2026-03-12 10:23:21 +08:00
if (current != myIndex) return;
// 可在此刷新角标等
2025-12-12 09:11:30 +08:00
}
2026-03-12 10:23:21 +08:00
Future<void> _onRefresh() async {
await Future.delayed(const Duration(seconds: 1));
2025-12-12 09:11:30 +08:00
}
@override
2026-03-12 10:23:21 +08:00
Widget build(BuildContext context) {
const double notificationHeightConst = 60.0;
double bannerHeight = 738 / 1125 * screenWidth(context);
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
// 计算可见按钮列表
final visibleButtons = <Map<String, dynamic>>[];
for (int i = 0; i < buttonInfos.length; i++) {
if (i < _buttonVisibility.length && _buttonVisibility[i]) {
visibleButtons.add(buttonInfos[i]);
2025-12-12 09:11:30 +08:00
}
}
2026-03-12 10:23:21 +08:00
final double iconSectionHeight =
visibleButtons.isEmpty ? 0.0 : (visibleButtons.length <= 4 ? 120.0 : 220.0);
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
final double notificationHeight =
(_showNotificationBar && iconSectionHeight >= 0) ? notificationHeightConst : 0.0;
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
final double extraSpacing = _showNotificationBar ? 60.0 : 12.0;
2025-12-12 09:11:30 +08:00
final double stackBottom =
2026-03-12 10:23:21 +08:00
bannerHeight - (iconSectionHeight * 0.4) + iconSectionHeight + extraSpacing;
2025-12-12 09:11:30 +08:00
final double statusBar = MediaQuery.of(context).padding.top;
2026-03-12 10:23:21 +08:00
final topPadding = Platform.isIOS ? 0 : 14;
2025-12-12 09:11:30 +08:00
return PopScope(
canPop: false,
child: Scaffold(
extendBodyBehindAppBar: true,
body: Stack(
children: [
RefreshIndicator(
2026-03-12 10:23:21 +08:00
backgroundColor: Colors.white,
color: Colors.blue,
2025-12-12 09:11:30 +08:00
onRefresh: _onRefresh,
child: ListView(
controller: _scrollController,
physics: const AlwaysScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
children: [
SizedBox(
height: stackBottom,
child: Stack(
clipBehavior: Clip.none,
children: [
2026-03-12 10:23:21 +08:00
// Banner
2025-12-12 09:11:30 +08:00
Positioned(
top: 0,
left: 0,
right: 0,
height: bannerHeight,
child: _buildBannerSection(bannerHeight),
),
2026-03-12 10:23:21 +08:00
// 通知栏
if (_showNotificationBar)
Positioned(
left: 10,
right: 10,
top: (bannerHeight - (iconSectionHeight * 0.4)) + iconSectionHeight - 10,
height: notificationHeight,
child: _buildNotificationBar(notificationHeight - 2),
),
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
// 图标区
2025-12-12 09:11:30 +08:00
Positioned(
left: 10,
right: 10,
2026-03-12 10:23:21 +08:00
top: bannerHeight - (iconSectionHeight * 0.4),
2025-12-12 09:11:30 +08:00
height: iconSectionHeight,
2026-03-12 10:23:21 +08:00
child: _buildIconSection(context, visibleButtons, iconSectionHeight),
2025-12-12 09:11:30 +08:00
),
],
),
),
2026-03-12 10:23:21 +08:00
if (widget.isChooseFirm && _showWorkStats) ...[
2025-12-12 09:11:30 +08:00
Padding(
2026-03-12 10:23:21 +08:00
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
2025-12-12 09:11:30 +08:00
child: _buildWorkStatsSection(),
),
2026-03-12 10:23:21 +08:00
],
2025-12-12 09:11:30 +08:00
2026-03-12 10:23:21 +08:00
if (widget.isChooseFirm && _showCheckList) ...[
2025-12-12 09:11:30 +08:00
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: _buildCheckListSection(),
),
const SizedBox(height: 20),
2026-02-28 14:38:07 +08:00
],
2025-12-12 09:11:30 +08:00
],
),
),
2026-03-12 10:23:21 +08:00
// 浮动 AppBar
2025-12-12 09:11:30 +08:00
Positioned(
top: 0,
left: 0,
right: 0,
child: AnimatedContainer(
duration: const Duration(milliseconds: 0),
2026-03-12 10:23:21 +08:00
height: _showFloatingAppBar ? (statusBar + _floatingBarHeight) : 0,
2025-12-12 09:11:30 +08:00
decoration: BoxDecoration(
2026-03-12 10:23:21 +08:00
color: _showFloatingAppBar ? h_AppBarColor() : Colors.transparent,
boxShadow: _showFloatingAppBar
? [BoxShadow(color: Colors.black.withOpacity(0.08), blurRadius: 6)]
: [],
2025-12-12 09:11:30 +08:00
),
child: SafeArea(
bottom: false,
child: Opacity(
opacity: _showFloatingAppBar ? 1.0 : 0.0,
2026-03-12 10:23:21 +08:00
child: SizedBox(height: _floatingBarHeight, child: const SizedBox()),
2025-12-12 09:11:30 +08:00
),
),
),
),
2026-03-12 10:23:21 +08:00
// 顶部中央标题
2025-12-12 09:11:30 +08:00
Positioned(
2026-03-12 10:23:21 +08:00
top: statusBar + topPadding,
2025-12-12 09:11:30 +08:00
width: screenWidth(context),
2026-02-28 14:38:07 +08:00
child: Center(
child: Text(
'秦港-相关方安全管理',
2026-03-12 10:23:21 +08:00
style: TextStyle(fontSize: 19, fontWeight: FontWeight.w600, color: Colors.white),
2025-12-12 09:11:30 +08:00
),
2026-02-28 14:38:07 +08:00
),
2025-12-12 09:11:30 +08:00
),
2026-03-12 10:23:21 +08:00
// 右上角图标(扫码、加入企业)
2025-12-12 09:11:30 +08:00
_buildFixedTopIcons(context),
],
),
),
);
}
2025-12-24 16:07:53 +08:00
Future<void> _joinFirm() async {
2026-02-28 14:38:07 +08:00
pushPage(FirmListPage(isBack: true), context);
2025-12-24 16:07:53 +08:00
}
2025-12-12 09:11:30 +08:00
Widget _buildFixedTopIcons(BuildContext context) {
final double statusBar = MediaQuery.of(context).padding.top;
final double topOffset = statusBar + 12;
2026-03-12 10:23:21 +08:00
final routeService = RouteService();
final bool showScan = routeService.hasPerm(_modulePerms['scan']!);
2026-04-01 17:53:42 +08:00
final bool showJoin = routeService.hasPerm(_modulePerms['joinFirm']!);
2026-03-12 10:23:21 +08:00
final List<Widget> children = [];
if (showScan) {
children.add(
GestureDetector(
onTap: startScan,
child: Container(
width: 30,
height: 30,
alignment: Alignment.center,
child: Image.asset("assets/icon-apps/home_saoyisao.png", width: 20, height: 20),
),
),
);
}
if (showJoin) {
if (children.isNotEmpty) children.add(const SizedBox(width: 8));
children.add(
GestureDetector(
onTap: _joinFirm,
child: Container(
width: 30,
height: 30,
alignment: Alignment.center,
child: Image.asset("assets/icon-apps/home_add.png", width: 20, height: 20),
),
),
);
}
2025-12-12 09:11:30 +08:00
return Positioned(
top: topOffset,
2026-02-28 14:38:07 +08:00
right: 8,
2026-03-12 10:23:21 +08:00
child: Row(children: children),
2025-12-12 09:11:30 +08:00
);
}
Widget _buildNotificationBar(double notificationHeight) {
return Material(
color: Colors.transparent,
child: Container(
height: notificationHeight,
decoration: BoxDecoration(
2026-03-12 10:23:21 +08:00
color: const Color(0xFFE6F5FF),
2025-12-12 09:11:30 +08:00
borderRadius: BorderRadius.circular(5),
2026-03-12 10:23:21 +08:00
border: Border.all(color: Colors.white, width: 1),
2025-12-12 09:11:30 +08:00
boxShadow: [
2026-03-12 10:23:21 +08:00
BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 6, offset: const Offset(0, 2)),
2025-12-12 09:11:30 +08:00
],
),
2026-03-12 10:23:21 +08:00
child: Row(
2025-12-12 09:11:30 +08:00
children: [
2026-03-12 10:23:21 +08:00
const SizedBox(width: 12),
Image.asset('assets/images/ico8.png', width: 30, height: 25),
const SizedBox(width: 12),
Expanded(
child: SizedBox(
height: notificationHeight,
child: PageView.builder(
controller: _notifPageController,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
itemCount: _notifications.length,
itemBuilder: (context, index) {
return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Text(
_notifications[index],
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(color: Colors.black87, fontSize: 14),
),
),
);
},
2025-12-12 09:11:30 +08:00
),
2026-03-12 10:23:21 +08:00
),
2025-12-12 09:11:30 +08:00
),
2026-03-12 10:23:21 +08:00
const Icon(Icons.chevron_right, color: Colors.black26),
const SizedBox(width: 8),
2025-12-12 09:11:30 +08:00
],
),
),
);
}
Widget _buildBannerSection(double bannerHeight) {
2026-03-12 10:23:21 +08:00
return Image.asset(
"assets/images/banner.png",
width: MediaQuery.of(context).size.width,
height: bannerHeight,
fit: BoxFit.cover,
2025-12-12 09:11:30 +08:00
);
}
2026-03-12 10:23:21 +08:00
Widget _buildIconSection(BuildContext context, List<Map<String, dynamic>> visibleButtons, double height) {
if (RouteService().mainTabs.isNotEmpty && visibleButtons.isEmpty) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
),
child: const Center(child: Text('暂无权限访问的功能')),
);
}
final hasSecondRow = visibleButtons.length > 4;
final double containerMinHeight = height > 0 ? height : 120.0;
2025-12-12 09:11:30 +08:00
return Container(
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 5),
2026-03-12 10:23:21 +08:00
constraints: BoxConstraints(minHeight: containerMinHeight),
2025-12-12 09:11:30 +08:00
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
2026-03-12 10:23:21 +08:00
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
),
child: widget.isChooseFirm
? Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: List.generate(4, (i) {
if (i < visibleButtons.length) {
return Expanded(child: Center(child: _buildIconButton(visibleButtons[i], context)));
} else {
return const Expanded(child: SizedBox());
}
}),
),
if (hasSecondRow) const SizedBox(height: 20),
if (hasSecondRow)
Row(
children: List.generate(4, (i) {
final idx = 4 + i;
if (idx < visibleButtons.length) {
return Expanded(child: Center(child: _buildIconButton(visibleButtons[idx], context)));
} else {
return const Expanded(child: SizedBox());
}
}),
),
2025-12-12 09:11:30 +08:00
],
2026-03-12 10:23:21 +08:00
)
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/ico1.png', width: 100, height: 100),
const SizedBox(height: 10),
CustomButton(
text: '点击入职企业',
onPressed: () => pushPage(FirmListPage(isBack: true), context),
),
],
),
2025-12-12 09:11:30 +08:00
),
);
}
Widget _buildIconButton(Map<String, dynamic> info, BuildContext context) {
return GestureDetector(
2026-03-12 10:23:21 +08:00
onTap: () => _handleIconTap(info['title']),
2025-12-12 09:11:30 +08:00
child: Column(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: const Color(0xFFE8F4FD),
borderRadius: BorderRadius.circular(25),
),
2026-03-12 10:23:21 +08:00
child: Center(child: Image.asset(info['icon'], width: 30, height: 30)),
2025-12-12 09:11:30 +08:00
),
const SizedBox(height: 6),
SizedBox(
width: 70,
child: Text(
info['title'],
style: const TextStyle(fontSize: 12, color: Colors.black87),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
),
);
}
void _handleIconTap(String title) {
switch (title) {
case "单位管理":
pushPage(UnitTabPage(), context);
break;
case "入港培训":
2026-02-28 14:38:07 +08:00
pushPage(StudyTabListPage(), context);
2025-12-12 09:11:30 +08:00
break;
2026-03-25 16:09:17 +08:00
case "口门门禁":
pushPage(DoorcarTabPage(), context);
break;
2025-12-12 09:11:30 +08:00
default:
2026-03-12 10:23:21 +08:00
ToastUtil.showNormal(context, '功能开发中...');
2025-12-12 09:11:30 +08:00
break;
}
}
Widget _buildWorkStatsSection() {
return Container(
2026-03-25 16:09:17 +08:00
padding: const EdgeInsets.all(15),
2025-12-12 09:11:30 +08:00
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
2026-03-25 16:09:17 +08:00
boxShadow: const [
BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2)),
],
2025-12-12 09:11:30 +08:00
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2026-03-25 16:09:17 +08:00
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 0),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "今日有工作项",
style: TextStyle(fontSize: 16, color: Colors.black87),
),
TextSpan(
text: " ${workStats['total']}",
style: const TextStyle(
fontSize: 16,
color: Color(0xFF2A75F8),
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: "",
style: TextStyle(fontSize: 16, color: Colors.black87),
),
],
),
),
),
const SizedBox(height: 15),
2025-12-12 09:11:30 +08:00
Container(
width: screenWidth(context),
2026-03-25 16:09:17 +08:00
height: 36,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.grey[300]!, width: 1),
),
2025-12-12 09:11:30 +08:00
child: Row(
children: [
Expanded(
child: GestureDetector(
2026-03-25 16:09:17 +08:00
onTap: () {
setState(() {
_isMobileSelected = true;
});
pcType=1;
_getToDoWorkList(pcType);
},
2025-12-12 09:11:30 +08:00
child: Container(
decoration: BoxDecoration(
2026-03-25 16:09:17 +08:00
color:
_isMobileSelected ? const Color(0xFF2A75F8) : Colors.white,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
bottomLeft: Radius.circular(20),
),
2025-12-12 09:11:30 +08:00
),
child: Center(
child: Text(
"手机端",
style: TextStyle(
fontSize: 14,
2026-03-25 16:09:17 +08:00
color: _isMobileSelected ? Colors.white : Colors.black87,
2025-12-12 09:11:30 +08:00
fontWeight: FontWeight.w500,
),
),
),
),
),
),
Expanded(
child: GestureDetector(
2026-03-25 16:09:17 +08:00
onTap: () {
setState(() {
_isMobileSelected = false;
});
pcType=2;
_getToDoWorkList(pcType);
},
2025-12-12 09:11:30 +08:00
child: Container(
decoration: BoxDecoration(
2026-03-25 16:09:17 +08:00
color: !_isMobileSelected ? const Color(0xFF2A75F8) : Colors.white,
borderRadius: const BorderRadius.only(
topRight: Radius.circular(20),
bottomRight: Radius.circular(20),
),
2025-12-12 09:11:30 +08:00
),
child: Center(
child: Text(
"电脑端",
style: TextStyle(
2026-03-25 16:09:17 +08:00
fontSize: 14,
color: !_isMobileSelected ? Colors.white : Colors.black87,
2025-12-12 09:11:30 +08:00
fontWeight: FontWeight.w500,
),
),
),
),
),
),
],
),
),
2026-03-25 16:09:17 +08:00
// const SizedBox(height: 15),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// RichText(
// text: TextSpan(
// children: [
// TextSpan(
// text: "已处理工作项:",
// style: TextStyle(fontSize: 14, color: Colors.black87),
// ),
// TextSpan(
// text: " ${workStats['processed']}",
// style: const TextStyle(
// fontSize: 14,
// color: Colors.greenAccent,
// fontWeight: FontWeight.bold,
// ),
// ),
// TextSpan(
// text: "个",
// style: TextStyle(fontSize: 14, color: Colors.black87),
// ),
// ],
// ),
// ),
// RichText(
// text: TextSpan(
// children: [
// TextSpan(
// text: "待处理工作项:",
// style: TextStyle(fontSize: 14, color: Colors.black87),
// ),
// TextSpan(
// text: " ${workStats['processed']}",
// style: const TextStyle(
// fontSize: 14,
// color: Colors.orange,
// fontWeight: FontWeight.bold,
// ),
// ),
// TextSpan(
// text: "个",
// style: TextStyle(fontSize: 14, color: Colors.black87),
// ),
// ],
// ),
// ),
// ],
// ),
2025-12-12 09:11:30 +08:00
],
),
);
}
2026-03-25 16:09:17 +08:00
// Widget _buildCheckListSection() {
// return Column(
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: const [
// Text(' 待办清单', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
// SizedBox(),
// ],
// ),
// const SizedBox(height: 8),
// Container(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(12),
// boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2))],
// ),
// child: Column(children: [...checkLists.map((item) => _buildCheckListItem(item))]),
// ),
// ],
// );
// }
2025-12-12 09:11:30 +08:00
Widget _buildCheckListSection() {
2026-03-25 16:09:17 +08:00
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [
BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2)),
],
),
child: Column(
children: checkLists.map((item) => _buildCheckListItem(item)).toList(),
),
2025-12-12 09:11:30 +08:00
);
}
Widget _buildCheckListItem(Map<String, dynamic> item) {
2026-03-25 16:09:17 +08:00
return GestureDetector(
onTap: () async {
if(pcType==2){
return;
}
2026-03-30 16:21:06 +08:00
switch(item['appName']){
case "隐患治理":
case "隐患管理":
case "风险管控应用":
// await pushPage(ApplicationPageTwo(), context);
break;
case "消防检查":
// await pushPage(FireManagementTabPage(), context);
break;
case "一级口门管理":
await pushPage(DoorcarTabPage(), context);
break;
case "安全环保检查":
// await pushPage(SafecheckTabList(), context);
break;
}
2026-03-25 16:09:17 +08:00
_getToDoWorkList(pcType);
// _getHiddenIssuesNum();
},
child: Container(
padding: const EdgeInsets.all(15),
decoration:
BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey[200]!, width: 1))),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
2025-12-12 09:11:30 +08:00
item['title'],
2026-03-12 10:23:21 +08:00
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black87),
2025-12-12 09:11:30 +08:00
),
2026-03-25 16:09:17 +08:00
Text(item['content'], style: TextStyle(fontSize: 12, color: Colors.grey[500])),
],
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Image.asset('assets/images/mine1.png', width: 15, height: 15),
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(color: Colors.grey[100], borderRadius: BorderRadius.circular(4)),
child: Text("类型:${item['appName']}", style: const TextStyle(fontSize: 12, color: Colors.blue)),
),
],
2025-12-12 09:11:30 +08:00
),
2026-03-25 16:09:17 +08:00
Text("时间:${item['createTime']}", style: const TextStyle(fontSize: 12, color: Colors.grey)),
],
),
],
),
2025-12-12 09:11:30 +08:00
),
2026-03-25 16:09:17 +08:00
],
),
2025-12-12 09:11:30 +08:00
),
);
}
2026-03-25 16:09:17 +08:00
// 获取待办事项
void _getToDoWorkList(int type) async {
Map data = {
"eqAppFlag": type==1?"1":"",
"eqPcFlag": type==1?"":"1",
"eqStatus": "1",
"pageIndex": '1',
"pageSize": '999',
};
final result = await TodoApi.getTodoList(data);
if (result['success']) {
setState(() {
workStats['total'] =result['totalCount'] ;
checkLists=result['data'];
// checkLists = result['data'];
int m= checkLists.length;
});
}
}
2026-03-12 10:23:21 +08:00
}