| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- import 'package:flutter/material.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:flutter/services.dart';
- import 'package:go_router/go_router.dart';
- import '../../core/theme/app_colors.dart';
- import '../../core/utils/responsive.dart';
- import 'home_controller.dart';
- class HomePage extends ConsumerWidget {
- const HomePage({super.key});
- @override
- Widget build(BuildContext context, WidgetRef ref) {
- final summaryAsync = ref.watch(homeSummaryProvider);
- final canPop = Navigator.of(context).canPop();
- return Scaffold(
- appBar: AppBar(
- leading: canPop
- ? null
- : IconButton(
- icon: const Icon(Icons.close),
- onPressed: () => SystemNavigator.pop(),
- ),
- title: const Text('TBOSS · 工作台'),
- ),
- body: summaryAsync.when(
- loading: () =>
- const Center(child: CircularProgressIndicator()),
- error: (_, __) => const Center(child: Text('加载失败')),
- data: (summary) => LayoutBuilder(
- builder: (context, constraints) {
- final r = ResponsiveHelper(
- width: constraints.maxWidth,
- height: constraints.maxHeight,
- isLandscape: constraints.maxWidth > constraints.maxHeight,
- isWide: constraints.maxWidth > 600,
- );
- return _buildContent(context, summary, r);
- },
- ),
- ),
- );
- }
- Widget _buildContent(
- BuildContext context, HomeSummary summary, ResponsiveHelper r) {
- return SingleChildScrollView(
- padding: const EdgeInsets.all(12),
- child: Column(
- children: [
- _buildSection(
- title: '我的审批',
- r: r,
- items: [
- _EntryItem(
- icon: Icons.receipt_long,
- label: '报销',
- badge: '${summary.expensePending}待办',
- color: AppColors.primary,
- onTap: () => context.go('/expense/list'),
- ),
- _EntryItem(
- icon: Icons.access_time,
- label: '加班',
- badge: '${summary.overtimePending}待办',
- color: AppColors.primary,
- onTap: () => context.go('/overtime/list'),
- ),
- _EntryItem(
- icon: Icons.directions_car,
- label: '用车',
- badge: '${summary.vehiclePending}待办',
- color: AppColors.warning,
- onTap: () => context.go('/vehicle/list'),
- ),
- ],
- ),
- const SizedBox(height: 12),
- _buildSection(
- title: '我的数据',
- r: r,
- items: [
- _EntryItem(
- icon: Icons.edit_note,
- label: '外出日志',
- badge: '${summary.logCount}条',
- color: AppColors.success,
- onTap: () => context.go('/outing-log/list'),
- ),
- _EntryItem(
- icon: Icons.campaign,
- label: '公告通知',
- badge: summary.announcementUnread > 0
- ? '${summary.announcementUnread}未读'
- : '${summary.announcementCount}条',
- color: const Color(0xFF722ED1),
- onTap: () => context.go('/announcement/list'),
- ),
- _EntryItem(
- icon: Icons.description,
- label: '全部单据',
- badge: '${summary.totalCount}条',
- color: const Color(0xFFEB2F96),
- onTap: () {},
- ),
- ],
- ),
- ],
- ),
- );
- }
- Widget _buildSection({
- required String title,
- required ResponsiveHelper r,
- required List<_EntryItem> items,
- }) {
- return Container(
- padding: const EdgeInsets.all(16),
- decoration: BoxDecoration(
- color: AppColors.cardWhite,
- borderRadius: BorderRadius.circular(12),
- boxShadow: [
- BoxShadow(
- color: Colors.black.withValues(alpha: 0.04),
- blurRadius: 4,
- offset: const Offset(0, 1),
- ),
- ],
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- title,
- style: const TextStyle(
- fontSize: 15,
- fontWeight: FontWeight.w600,
- color: AppColors.textPrimary,
- ),
- ),
- const SizedBox(height: 14),
- if (r.isLandscape)
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: items
- .map((item) => Expanded(child: _buildEntry(item)))
- .toList(),
- )
- else
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: items.map((item) => _buildEntry(item)).toList(),
- ),
- ],
- ),
- );
- }
- Widget _buildEntry(_EntryItem item) {
- return GestureDetector(
- onTap: item.onTap,
- child: Column(
- children: [
- Container(
- width: 48,
- height: 48,
- decoration: BoxDecoration(
- color: item.color,
- borderRadius: BorderRadius.circular(24),
- ),
- child: Icon(item.icon, color: Colors.white, size: 24),
- ),
- const SizedBox(height: 8),
- Text(
- item.label,
- style: const TextStyle(
- fontSize: 12,
- color: AppColors.textSecondary,
- ),
- ),
- const SizedBox(height: 2),
- Text(
- item.badge,
- style: TextStyle(
- fontSize: 10,
- color: item.badge.contains('0')
- ? AppColors.textHint
- : AppColors.error,
- ),
- ),
- ],
- ),
- );
- }
- }
- class _EntryItem {
- final IconData icon;
- final String label;
- final String badge;
- final Color color;
- final VoidCallback onTap;
- const _EntryItem({
- required this.icon,
- required this.label,
- required this.badge,
- required this.color,
- required this.onTap,
- });
- }
|