Files
kuaishai2/lib/features/home/widgets/run_status_monitor.dart
Developer 5d28bf631b chore(project): 初始化项目基础配置文件
- 添加 CodeGraph、Android 和通用 gitignore 配置
- 创建项目元数据文件跟踪 Flutter 项目属性
- 添加 Codex AI 指导文档 AGENTS.md 说明项目架构
- 配置代码分析选项 analysis_options.yaml
- 设置 Android 应用清单权限和 Kiosk 模式配置
- 实现中英文国际化支持 AppLocalizations
- 配置 GoRouter 应用路由导航
- 创建明亮工业控制风格的主题配置 AppTheme
2026-06-04 11:19:44 +08:00

243 lines
6.7 KiB
Dart

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<Color>(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.mixSpeed}',
),
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',
),
),
],
),
);
}
}