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 '../../device/providers/run_state_provider.dart'; /// 运行状态监控面板 - 暗色工业风格 /// 显示当前孔位、步骤、倒计时、进度条、参数详情 class RunStatusMonitor extends ConsumerWidget { const RunStatusMonitor({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final l10n = AppLocalizations.of(context); final runState = ref.watch(runStateProvider); if (runState.status == RunStatus.idle) { return const SizedBox.shrink(); } return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppTheme.cardBg, borderRadius: BorderRadius.circular(8), border: Border.all(color: AppTheme.borderSubtle, width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 + 程序名 Row( children: [ Text( l10n?.runningMonitor ?? '运行状态监控', style: const TextStyle( color: AppTheme.textHeading, fontSize: 15, fontWeight: FontWeight.w600, ), ), const Spacer(), Text( runState.currentProgram?.name ?? '', style: const TextStyle( color: AppTheme.accentPrimary, fontSize: 18, fontWeight: FontWeight.w700, ), ), ], ), const SizedBox(height: 14), // 进度信息横排 (孔位 / 步骤 / 剩余时间) Row( children: [ // 当前孔位 _buildInfoBlock( label: l10n?.currentHole ?? '当前孔位', value: runState.currentWell ?? '--', valueColor: AppTheme.textHeading, ), const SizedBox(width: 20), // 当前步骤 _buildInfoBlock( label: l10n?.currentStep ?? '当前步骤', value: '${l10n?.stepNo ?? '步骤'} ${runState.currentStepIndex + 1}', subValue: runState.currentStep?.name ?? '--', valueColor: AppTheme.accentInfo, ), const SizedBox(width: 20), // 剩余时间 _buildInfoBlock( label: l10n?.remainingTime ?? '剩余时间', value: runState.formattedRemainingTime, valueColor: AppTheme.textHeading, valueSize: 20, ), ], ), const SizedBox(height: 14), // 总进度条 _buildProgressBar(l10n, runState), const SizedBox(height: 14), // 步骤参数 if (runState.currentStep != null) _buildStepParams(l10n, runState.currentStep!), ], ), ); } /// 信息块 Widget _buildInfoBlock({ required String label, required String value, String? subValue, Color valueColor = AppTheme.textHeading, double valueSize = 16, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( color: AppTheme.textTertiary, fontSize: 11, ), ), const SizedBox(height: 2), Text( value, style: TextStyle( color: valueColor, fontSize: valueSize, fontWeight: FontWeight.w600, fontFamily: 'monospace', ), ), if (subValue != null) ...[ const SizedBox(height: 2), Text( subValue, style: const TextStyle( color: AppTheme.textSecondary, fontSize: 11, ), ), ], ], ); } /// 进度条 Widget _buildProgressBar(AppLocalizations? l10n, RunState runState) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( l10n?.progress ?? '总进度', style: const TextStyle( color: AppTheme.textTertiary, fontSize: 11, ), ), const Spacer(), Text( runState.formattedProgress, style: const TextStyle( color: AppTheme.accentPrimary, fontSize: 12, fontWeight: FontWeight.w600, fontFamily: 'monospace', ), ), ], ), const SizedBox(height: 6), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: runState.progress, minHeight: 8, backgroundColor: const Color(0xFF1E293B), valueColor: AlwaysStoppedAnimation(AppTheme.accentPrimary), ), ), ], ); } /// 步骤参数详情 Widget _buildStepParams(AppLocalizations? l10n, dynamic step) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n?.stepParams ?? '步骤参数', style: const TextStyle( color: AppTheme.textTertiary, fontSize: 11, ), ), const SizedBox(height: 2), if (step.mixTime > 0) _buildParamRow( l10n?.speed ?? '转速', '${step.speed} 档', ), if (step.magnetTime > 0) _buildParamRow( l10n?.temperature ?? '温度', '65.0 °C', ), _buildParamRow( l10n?.duration ?? '持续时间', step.mixTime > 0 ? '${step.mixTime} min' : '--', ), _buildParamRow( l10n?.sampleVolume ?? '样品体积', '10.0 mL', ), ], ); } /// 参数行 Widget _buildParamRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Row( children: [ Text( label, style: const TextStyle( color: AppTheme.textTertiary, fontSize: 11, ), ), const Spacer(), Text( value, style: const TextStyle( color: AppTheme.textPrimary, fontSize: 11, fontFamily: 'monospace', ), ), ], ), ); } }