feat(device): 添加USB设备通信支持和程序参数优化

- 在AndroidManifest.xml中添加USB Host权限和设备过滤器配置
- 新增设备控制国际化词条包括速度档位、吹气时间等
- 重构数据库结构将速度相关字段统一为档位数值存储
- 添加通用KV存储方法用于settings表数据读写
- 优化首页导航实现tab间跳转和状态保持功能
- 更新程序详情页面布局和参数表单界面
- 移除模拟运行器相关测试代码
- 添加USB串口通信依赖包usb_serial
This commit is contained in:
Developer
2026-06-04 15:13:36 +08:00
parent 67e2c7c76c
commit d53c41c300
24 changed files with 795 additions and 635 deletions

View File

@@ -5,6 +5,8 @@ class Program {
final String name;
final String createdAt;
final int status; // 1: 启用, 0: 停用
final int temperature;
final int airflowTime;
Program({
this.id,
@@ -12,6 +14,8 @@ class Program {
required this.name,
required this.createdAt,
this.status = 1,
this.temperature = 50,
this.airflowTime = 60,
});
Map<String, dynamic> toMap() {
@@ -21,6 +25,8 @@ class Program {
'name': name,
'created_at': createdAt,
'status': status,
'temperature': temperature,
'airflow_time': airflowTime,
};
}
@@ -31,6 +37,8 @@ class Program {
name: map['name'] as String,
createdAt: map['created_at'] as String,
status: map['status'] as int? ?? 1,
temperature: map['temperature'] as int? ?? 50,
airflowTime: map['airflow_time'] as int? ?? 60,
);
}
@@ -40,6 +48,8 @@ class Program {
String? name,
String? createdAt,
int? status,
int? temperature,
int? airflowTime,
}) {
return Program(
id: id ?? this.id,
@@ -47,6 +57,8 @@ class Program {
name: name ?? this.name,
createdAt: createdAt ?? this.createdAt,
status: status ?? this.status,
temperature: temperature ?? this.temperature,
airflowTime: airflowTime ?? this.airflowTime,
);
}
}
}

View File

@@ -8,10 +8,8 @@ class Step {
final int mixTime;
final int magnetTime;
final int volume;
final String mixSpeed;
final String blowSpeed;
final int blowTime;
final int needleSpeed;
final int speed;
Step({
this.id,
@@ -22,10 +20,8 @@ class Step {
this.mixTime = 0,
this.magnetTime = 0,
this.volume = 0,
this.mixSpeed = '中速',
this.blowSpeed = '中速',
this.blowTime = 0,
this.needleSpeed = 5,
this.speed = 5,
});
Map<String, dynamic> toMap() {
@@ -38,10 +34,8 @@ class Step {
'mix_time': mixTime,
'magnet_time': magnetTime,
'volume': volume,
'mix_speed': mixSpeed,
'blow_speed': blowSpeed,
'blow_time': blowTime,
'needle_speed': needleSpeed,
'speed': speed,
};
}
@@ -55,10 +49,8 @@ class Step {
mixTime: map['mix_time'] as int? ?? 0,
magnetTime: map['magnet_time'] as int? ?? 0,
volume: map['volume'] as int? ?? 0,
mixSpeed: map['mix_speed'] as String? ?? '中速',
blowSpeed: map['blow_speed'] as String? ?? '中速',
blowTime: map['blow_time'] as int? ?? 0,
needleSpeed: map['needle_speed'] as int? ?? 5,
speed: map['speed'] as int? ?? 5,
);
}
@@ -71,10 +63,8 @@ class Step {
int? mixTime,
int? magnetTime,
int? volume,
String? mixSpeed,
String? blowSpeed,
int? blowTime,
int? needleSpeed,
int? speed,
}) {
return Step(
id: id ?? this.id,
@@ -85,10 +75,8 @@ class Step {
mixTime: mixTime ?? this.mixTime,
magnetTime: magnetTime ?? this.magnetTime,
volume: volume ?? this.volume,
mixSpeed: mixSpeed ?? this.mixSpeed,
blowSpeed: blowSpeed ?? this.blowSpeed,
blowTime: blowTime ?? this.blowTime,
needleSpeed: needleSpeed ?? this.needleSpeed,
speed: speed ?? this.speed,
);
}
}
}

View File

@@ -48,12 +48,6 @@ class _ProgramsPageState extends ConsumerState<ProgramsPage> {
),
child: Row(
children: [
// 返回按钮
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => context.go('/'),
),
const SizedBox(width: 16),
Text(
l10n?.programs ?? '程序管理',
style: const TextStyle(

View File

@@ -48,6 +48,8 @@ class ProgramImportService {
name: programData['name'] as String,
createdAt: programData['createdAt'] ?? DateTime.now().toString().split('.')[0],
status: programData['status'] ?? 1,
temperature: programData['temperature'] as int? ?? 50,
airflowTime: programData['airflowTime'] as int? ?? 60,
);
final programId = await _programService.addProgram(program);
@@ -65,10 +67,8 @@ class ProgramImportService {
mixTime: stepData['mixTime'] as int? ?? 0,
magnetTime: stepData['magnetTime'] as int? ?? 0,
volume: stepData['volume'] as int? ?? 0,
mixSpeed: stepData['mixSpeed'] as String? ?? '中速',
blowSpeed: stepData['blowSpeed'] as String? ?? '中速',
blowTime: stepData['blowTime'] as int? ?? 0,
needleSpeed: stepData['needleSpeed'] as int? ?? 5,
speed: stepData['speed'] as int? ?? 5,
);
await _programService.addStep(step);
}
@@ -107,16 +107,16 @@ class ProgramImportService {
'name': program.name,
'createdAt': program.createdAt,
'status': program.status,
'temperature': program.temperature,
'airflowTime': program.airflowTime,
'steps': steps.map((s) => {
'position': s.position,
'name': s.name,
'mixTime': s.mixTime,
'magnetTime': s.magnetTime,
'volume': s.volume,
'mixSpeed': s.mixSpeed,
'blowSpeed': s.blowSpeed,
'blowTime': s.blowTime,
'needleSpeed': s.needleSpeed,
'speed': s.speed,
}).toList(),
});
}

View File

@@ -2,6 +2,7 @@ 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/utils/constants.dart';
import '../../../shared/widgets/common_button.dart';
import '../models/program.dart';
import '../providers/programs_provider.dart';
@@ -21,6 +22,8 @@ class _ProgramFormDialogState extends ConsumerState<ProgramFormDialog> {
final _formKey = GlobalKey<FormState>();
late TextEditingController _codeController;
late TextEditingController _nameController;
late TextEditingController _temperatureController;
late TextEditingController _airflowTimeController;
bool _isEnabled = true;
bool _isSaving = false;
@@ -29,6 +32,10 @@ class _ProgramFormDialogState extends ConsumerState<ProgramFormDialog> {
super.initState();
_codeController = TextEditingController(text: widget.program?.code ?? '');
_nameController = TextEditingController(text: widget.program?.name ?? '');
_temperatureController =
TextEditingController(text: '${widget.program?.temperature ?? 50}');
_airflowTimeController =
TextEditingController(text: '${widget.program?.airflowTime ?? 60}');
_isEnabled = widget.program?.status == 1;
}
@@ -36,6 +43,8 @@ class _ProgramFormDialogState extends ConsumerState<ProgramFormDialog> {
void dispose() {
_codeController.dispose();
_nameController.dispose();
_temperatureController.dispose();
_airflowTimeController.dispose();
super.dispose();
}
@@ -95,6 +104,38 @@ class _ProgramFormDialogState extends ConsumerState<ProgramFormDialog> {
),
const SizedBox(height: 16),
// 温度和吹气时间
Row(
children: [
Expanded(
child: TextFormField(
controller: _temperatureController,
decoration: InputDecoration(
labelText: '${l10n?.temperature ?? '温度'} (°C)',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
keyboardType: TextInputType.number,
),
),
const SizedBox(width: 12),
Expanded(
child: TextFormField(
controller: _airflowTimeController,
decoration: InputDecoration(
labelText: '${l10n?.airflowTime ?? '吹气时间'} (${Constants.timeUnitSeconds})',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
keyboardType: TextInputType.number,
),
),
],
),
const SizedBox(height: 16),
// 状态开关
Row(
children: [
@@ -161,6 +202,8 @@ class _ProgramFormDialogState extends ConsumerState<ProgramFormDialog> {
name: _nameController.text.trim(),
createdAt: widget.program?.createdAt ?? now,
status: _isEnabled ? 1 : 0,
temperature: int.tryParse(_temperatureController.text) ?? 50,
airflowTime: int.tryParse(_airflowTimeController.text) ?? 60,
);
bool success;