import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../core/theme/app_colors.dart'; import '../../core/utils/date_utils.dart' as du; import '../../shared/models/user_model.dart'; import '../../shared/widgets/app_card.dart'; import '../../shared/widgets/approval_timeline.dart'; import '../../shared/widgets/approval_actions.dart'; import 'overtime_model.dart'; import 'overtime_list_controller.dart'; class OvertimeDetailPage extends ConsumerWidget { final String id; const OvertimeDetailPage({super.key, required this.id}); @override Widget build(BuildContext context, WidgetRef ref) { final overtime = mockOvertimes.firstWhere((e) => e.id == id, orElse: () => mockOvertimes.first); return Scaffold( appBar: TDNavBar( title: '加班详情', titleColor: Colors.white, backgroundColor: const Color(0xFF00ABF3), centerTitle: false, ), body: Column(children: [ Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(12), child: Column(children: [ _buildStatusHeader(overtime), const SizedBox(height: 12), _buildInfoSection(overtime), const SizedBox(height: 12), if (overtime.approvalRecords.isNotEmpty || overtime.approvalChain.isNotEmpty) AppCard( child: ApprovalTimeline( records: overtime.approvalRecords, chain: overtime.approvalChain, currentApproverId: overtime.currentApproverId, ), ), ]), ), ), ApprovalActions( status: overtime.status, userRole: UserRole.employee, onApprove: () {}, onReject: () {}, onEdit: () => context.push('/overtime/apply?id=${overtime.id}'), onWithdraw: () {}, ), ]), ); } Widget _buildStatusHeader(OvertimeModel overtime) { final (icon, color, text) = switch (overtime.status) { 'approved' => (Icons.check_circle, AppColors.success, '已通过'), 'rejected' => (Icons.cancel, AppColors.error, '已拒绝'), 'draft' => (Icons.edit, AppColors.textHint, '草稿'), _ => (Icons.schedule, AppColors.warning, '待审批'), }; return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: color.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(12)), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: color, size: 36), const SizedBox(width: 10), Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(text, style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: color)), if (overtime.status == 'pending') Text('当前审批人:${overtime.currentApproverId}', style: const TextStyle(fontSize: 12, color: AppColors.textSecondary)), ]), ]), ); } Widget _buildInfoSection(OvertimeModel overtime) { return _buildDetailCard('加班信息', [ TDCell(title: '申请单号', note: overtime.applicationNo, showBottomBorder: true), TDCell(title: '申请人', note: '${overtime.applicantName} · ${overtime.deptName}', showBottomBorder: true), TDCell(title: '加班日期', note: du.DateUtils.formatDate(overtime.otDate), showBottomBorder: true), TDCell(title: '加班时段', note: '${du.DateUtils.formatTime(overtime.startTime)} - ${du.DateUtils.formatTime(overtime.endTime)}', showBottomBorder: true), TDCell(title: '加班时长', note: '${overtime.otHours.toStringAsFixed(1)}h', showBottomBorder: true), TDCell(title: '加班类型', note: overtime.otType, showBottomBorder: true), TDCell(title: '补偿方式', note: overtime.compensationType, showBottomBorder: true), TDCell(title: '加班原因', note: overtime.reason.isEmpty ? '-' : overtime.reason, showBottomBorder: overtime.remark.isNotEmpty), if (overtime.remark.isNotEmpty) TDCell(title: '备注', note: overtime.remark, showBottomBorder: false), ]); } Widget _buildDetailCard(String title, List cells) { return Container( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: AppColors.cardWhite, borderRadius: BorderRadius.circular(10), boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.04), blurRadius: 4, offset: const Offset(0, 1))], ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(14, 12, 14, 8), child: Text(title, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: AppColors.textPrimary)), ), ...cells, ]), ); } }