// lib/pages/application_template.dart import 'dart:ffi'; import 'package:flutter/material.dart'; import 'package:qhd_prevention/common/route_service.dart'; import 'package:qhd_prevention/http/modules/key_tasks_api.dart'; import 'package:qhd_prevention/pages/home/doorAndCar/doorCar_tab_page.dart'; import 'package:qhd_prevention/pages/home/keyTasks/keyTasksDetail/keyTasksHiddenDanger/key_tasks_hidden_danger_list.dart'; import 'package:qhd_prevention/pages/home/keyTasks/key_tasks_check_list_page.dart'; import 'package:qhd_prevention/pages/home/keyTasks/key_tasks_confirm_list_page.dart'; import 'package:qhd_prevention/pages/my_appbar.dart'; import 'package:qhd_prevention/services/SessionService.dart'; import 'package:qhd_prevention/tools/tools.dart'; class KeyTasksTabPage extends StatefulWidget { const KeyTasksTabPage({super.key}); @override State createState() => _DoorcarTabPageState(); } class _DoorcarTabPageState extends State { final String bannerAsset = 'assets/images/key_tasks_banner.jpg'; late List defaultSections; @override void initState() { // TODO: implement initState super.initState(); _initSections(); // 初始化 sections _getDoorCarCount(); } // 初始化 sections 的方法 void _initSections() { defaultSections = [ AppSection(title: '重点作业管理', items: [ AppSectionItem( title: '重点作业申请', icon: 'assets/images/key_tasks_ico2.png', menuPerms:'dashboard:Key-assignment:Key-Task-Application', badge: 0, onTap: () async { await pushPage(KeyTasksConfirmListPage(), context); _getDoorCarCount(); }, ), AppSectionItem( title: '被检查确认', icon: 'assets/images/key_tasks_ico3.png', menuPerms:'dashboard:Key-assignment:Key-Task-Application', badge: 0, onTap: () async { await pushPage(KeyTasksCheckListPage(), context); _getDoorCarCount(); }, ), AppSectionItem( title: '隐患整改', icon: 'assets/images/key_tasks_ico6.png', menuPerms:'dashboard:Key-assignment:Hidden-danger-rectification', badge: 0, onTap: () async { await pushPage(KeyTasksHiddenDangerList(1), context); _getDoorCarCount(); }, ), AppSectionItem( title: '隐患记录', icon: 'assets/images/key_tasks_ico7.png', menuPerms:'dashboard:Key-assignment:Hidden-Hazard-Record', badge: 0, onTap: () async { await pushPage(KeyTasksHiddenDangerList(2), context); _getDoorCarCount(); }, ), ]), ]; } Future _getDoorCarCount() async { try { String userId= SessionService.instance.accountId??''; final result = await KeyTasksApi.getKeyTasksToDoCount(userId); if (result['success'] ) { dynamic data = result['data']?? {} ; setState(() { // 重点作业管理 final gateSection = defaultSections[0]; // // 重点作业申请 gateSection.items[0].badge = int.parse(data['zdzysqCount']??0); // 确认 gateSection.items[1].badge = int.parse(data['bjcrqrCount']??0); // 整改 gateSection.items[2].badge = int.parse(data['yhdzgCount']??0); }); } // else { // ToastUtil.showNormal(context, result['errMessage'] ?? "加载数据失败"); // } } catch (e) { LoadingDialogHelper.hide(); print('加载数据失败:$e'); } } @override Widget build(BuildContext context) { final double bannerHeight = (730.0 / 1125.0) * MediaQuery.of(context).size.width; final double iconSectionHeight = MediaQuery.of(context).size.height - bannerHeight - 30.0; const double iconOverlapBanner = 30.0; // 过滤掉没有可见 items 的分组 // final visibleSections = defaultSections // .map((s) => AppSection( // title: s.title, // items: s.items.where((it) => it.visible).toList())) // .where((s) => s.items.isNotEmpty) // .toList(); final routeService = RouteService(); return AnimatedBuilder( animation: routeService, builder: (context, _) { final rebuiltVisibleSections = defaultSections.map((section) { final visibleItems = section.items.where((item) { return item.visible && routeService.hasPerm(item.menuPerms); }).toList(); return AppSection( title: section.title, items: visibleItems, ); }).where((section) => section.items.isNotEmpty).toList(); return Scaffold( extendBodyBehindAppBar: true, appBar: MyAppbar(title: '重点作业', backgroundColor: Colors.transparent,), body: ListView( physics: const AlwaysScrollableScrollPhysics(), padding: EdgeInsets.zero, children: [ SizedBox( height: bannerHeight + iconSectionHeight, child: Stack( clipBehavior: Clip.none, children: [ Positioned( top: 0, left: 0, right: 0, height: bannerHeight, child: _buildBannerSection(bannerHeight, context), ), Positioned( left: 10, right: 10, top: bannerHeight - iconOverlapBanner, height: iconSectionHeight, child: _buildIconSection(context, rebuiltVisibleSections), ), ], ), ), ], ), ); }, ); } Widget _buildBannerSection(double bannerHeight, BuildContext context) { return Stack( children: [ Image.asset( bannerAsset, width: MediaQuery.of(context).size.width, height: bannerHeight, fit: BoxFit.fitWidth, errorBuilder: (c, e, s) { return Container( color: Colors.blueGrey, height: bannerHeight, alignment: Alignment.center, child: const Text('Banner', style: TextStyle(color: Colors.white)), ); }, ), ], ); } Widget _buildIconSection(BuildContext context, List buttonInfos) { return Container( padding: const EdgeInsets.symmetric(horizontal: 0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: const [ BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 2)), ], ), child: ListView.builder( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(0), itemCount: buttonInfos.length, itemBuilder: (context, index) { final section = buttonInfos[index]; final items = section.items; if (items.isEmpty) return const SizedBox.shrink(); return Padding( padding: const EdgeInsets.only(top: 10, left: 10, right: 10), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 Padding( padding: const EdgeInsets.fromLTRB(10, 10, 10, 5), child: Row( children: [ Container(width: 2, height: 10, color: Colors.blue), const SizedBox(width: 5), Text(section.title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold)), ], ), ), // icons Padding( padding: const EdgeInsets.all(10), child: LayoutBuilder( builder: (context, constraints) { const spacing = 20.0; final totalWidth = constraints.maxWidth; final itemWidth = (totalWidth - spacing * 2) / 3; return Wrap( spacing: spacing, runSpacing: spacing, children: items.map((item) { return SizedBox( width: itemWidth, child: _buildItem( item, onTap: item.onTap ?? () => debugPrint('Tapped ${item.title}'), ), ); }).toList(), ); }, ), ), ], ), ), ); }, ), ); } Widget _buildItem(AppSectionItem item, {VoidCallback? onTap}) { const double iconSize = 30; final int badgeNum = item.badge; final String title = item.title; final String iconPath = item.icon; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(8), child: SizedBox( width: double.infinity, child: Column( mainAxisSize: MainAxisSize.min, children: [ Stack( clipBehavior: Clip.none, children: [ SizedBox( width: iconSize, height: iconSize, child: Image.asset( iconPath, fit: BoxFit.contain, errorBuilder: (c, e, s) { return Container( color: Colors.grey.shade200, child: const Center(child: Icon(Icons.image, size: 18)), ); }, ), ), if (badgeNum > 0) Positioned( top: -6, right: -6, child: Container( padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), decoration: const BoxDecoration(color: Colors.red, shape: BoxShape.circle), constraints: const BoxConstraints(minWidth: 16, minHeight: 16), child: Center( child: Text( badgeNum > 99 ? '99+' : badgeNum.toString(), style: const TextStyle(color: Colors.white, fontSize: 10, height: 1), textAlign: TextAlign.center, ), ), ), ), ], ), const SizedBox(height: 4), Text( title, style: const TextStyle(fontSize: 13), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ), ), ); } }