import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/localization/app_localizations.dart'; import '../../../core/theme/app_theme.dart'; import '../../../shared/widgets/status_indicator.dart'; import '../../device/providers/device_info_provider.dart'; /// 状态栏标签项数据 class StatusBarTab { final IconData icon; final String label; const StatusBarTab({required this.icon, required this.label}); } /// 状态栏组件 - 明亮工业风格 /// 显示: 设备名称 | 导航标签 | 灯按钮 | 状态指示器 | 实时时钟 /// /// [tabs] 不为空时,会在设备名右侧渲染胶囊样式的导航标签按钮组, /// 由父组件通过 [currentTabIndex] 和 [onTabChanged] 控制切换。 class StatusBar extends ConsumerStatefulWidget { final bool isRunning; final VoidCallback? onLightToggle; final List tabs; final int currentTabIndex; final ValueChanged? onTabChanged; const StatusBar({ super.key, this.isRunning = false, this.onLightToggle, this.tabs = const [], this.currentTabIndex = 0, this.onTabChanged, }); @override ConsumerState createState() => _StatusBarState(); } class _StatusBarState extends ConsumerState { String _currentTime = ''; Timer? _timer; @override void initState() { super.initState(); _updateTime(); _timer = Timer.periodic(const Duration(seconds: 1), (_) => _updateTime()); } @override void dispose() { _timer?.cancel(); super.dispose(); } /// 更新当前时间显示 void _updateTime() { final now = DateTime.now(); _currentTime = '${now.year}-${_twoDigits(now.month)}-${_twoDigits(now.day)} ' '${_twoDigits(now.hour)}:${_twoDigits(now.minute)}:${_twoDigits(now.second)}'; if (mounted) setState(() {}); } String _twoDigits(int n) => n.toString().padLeft(2, '0'); /// 切换照明开关 Future _onLightTap() async { widget.onLightToggle?.call(); await ref.read(deviceInfoProvider.notifier).toggleLight(); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); final deviceInfo = ref.watch(deviceInfoProvider); return Container( height: 56, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8), decoration: BoxDecoration( color: AppTheme.primaryColor, boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.08), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Row( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.precision_manufacturing, color: Colors.white, size: 22), const SizedBox(width: 10), Text( l10n?.deviceName ?? '污水毒品前处理一体机', style: const TextStyle( color: Colors.white, fontSize: 17, fontWeight: FontWeight.w700, ), ), ], ), if (widget.tabs.isNotEmpty) ...[ const SizedBox(width: 32), _buildNavTabs(), ], const Spacer(), _LightToggleButton( isOn: deviceInfo.lightingOn, onTap: _onLightTap, ), const SizedBox(width: 20), StatusIndicator( text: widget.isRunning ? (l10n?.running ?? '运行中') : (l10n?.idle ?? '未运行'), status: widget.isRunning ? DeviceStatusType.running : DeviceStatusType.idle, ), const SizedBox(width: 20), Text( _currentTime, style: const TextStyle( color: Colors.white, fontSize: 13, fontFamily: 'monospace', fontWeight: FontWeight.normal, ), ), ], ), ); } /// 构建标题栏内嵌的导航标签按钮组(胶囊样式) Widget _buildNavTabs() { return Row( mainAxisSize: MainAxisSize.min, children: List.generate(widget.tabs.length, (index) { final tab = widget.tabs[index]; return Padding( padding: EdgeInsets.only(right: index == widget.tabs.length - 1 ? 0 : 6), child: _NavTabButton( icon: tab.icon, label: tab.label, selected: index == widget.currentTabIndex, onTap: () => widget.onTabChanged?.call(index), ), ); }), ); } } /// 标题栏内嵌的导航标签按钮(胶囊样式) /// 选中时使用半透明白色背景突出,未选中时仅显示文字 class _NavTabButton extends StatelessWidget { final IconData icon; final String label; final bool selected; final VoidCallback? onTap; const _NavTabButton({ required this.icon, required this.label, required this.selected, this.onTap, }); @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(18), child: AnimatedContainer( duration: const Duration(milliseconds: 180), height: 36, padding: const EdgeInsets.symmetric(horizontal: 14), decoration: BoxDecoration( color: selected ? Colors.white.withValues(alpha: 0.22) : Colors.transparent, borderRadius: BorderRadius.circular(18), border: Border.all( color: selected ? Colors.white.withValues(alpha: 0.35) : Colors.transparent, width: 1, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( icon, size: 16, color: selected ? Colors.white : Colors.white.withValues(alpha: 0.78), ), const SizedBox(width: 6), Text( label, style: TextStyle( color: selected ? Colors.white : Colors.white.withValues(alpha: 0.85), fontSize: 14, fontWeight: selected ? FontWeight.w600 : FontWeight.w500, ), ), ], ), ), ), ); } } class _LightToggleButton extends StatelessWidget { final bool isOn; final VoidCallback? onTap; const _LightToggleButton({this.isOn = false, this.onTap}); @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(20), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: isOn ? Colors.white.withValues(alpha: 0.25) : Colors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.white.withValues(alpha: 0.3), width: 1, ), ), child: Icon( isOn ? Icons.lightbulb : Icons.lightbulb_outline_rounded, color: isOn ? Colors.yellowAccent : Colors.white.withValues(alpha: 0.8), size: 20, ), ), ), ); } }