chore(project): 初始化项目基础配置文件
- 添加 CodeGraph、Android 和通用 gitignore 配置 - 创建项目元数据文件跟踪 Flutter 项目属性 - 添加 Codex AI 指导文档 AGENTS.md 说明项目架构 - 配置代码分析选项 analysis_options.yaml - 设置 Android 应用清单权限和 Kiosk 模式配置 - 实现中英文国际化支持 AppLocalizations - 配置 GoRouter 应用路由导航 - 创建明亮工业控制风格的主题配置 AppTheme
This commit is contained in:
164
lib/core/database/database_service.dart
Normal file
164
lib/core/database/database_service.dart
Normal file
@@ -0,0 +1,164 @@
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
/// 数据库服务
|
||||
class DatabaseService {
|
||||
static final DatabaseService instance = DatabaseService._internal();
|
||||
static Database? _database;
|
||||
|
||||
DatabaseService._internal();
|
||||
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDatabase();
|
||||
return _database!;
|
||||
}
|
||||
|
||||
Future<Database> _initDatabase() async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = join(dbPath, 'kuaishai.db');
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 2,
|
||||
onCreate: _onCreate,
|
||||
onUpgrade: _onUpgrade,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onCreate(Database db, int version) async {
|
||||
// 程序表
|
||||
await db.execute('''
|
||||
CREATE TABLE programs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
status INTEGER DEFAULT 1
|
||||
)
|
||||
''');
|
||||
|
||||
// 步骤表
|
||||
await db.execute('''
|
||||
CREATE TABLE steps (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
program_id INTEGER NOT NULL,
|
||||
step_no INTEGER NOT NULL,
|
||||
position TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
mix_time INTEGER DEFAULT 0,
|
||||
magnet_time INTEGER DEFAULT 0,
|
||||
volume INTEGER DEFAULT 0,
|
||||
mix_speed TEXT DEFAULT '中速',
|
||||
blow_speed TEXT DEFAULT '中速',
|
||||
blow_time INTEGER DEFAULT 0,
|
||||
needle_speed INTEGER DEFAULT 5,
|
||||
FOREIGN KEY (program_id) REFERENCES programs(id) ON DELETE CASCADE
|
||||
)
|
||||
''');
|
||||
|
||||
// 设置表(密码存储)
|
||||
await db.execute('''
|
||||
CREATE TABLE settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
)
|
||||
''');
|
||||
|
||||
// 初始化默认密码
|
||||
await db.insert('settings', {'key': 'password', 'value': '123456'});
|
||||
}
|
||||
|
||||
/// 数据库升级
|
||||
Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
|
||||
if (oldVersion < 2) {
|
||||
// 添加 settings 表
|
||||
await db.execute('''
|
||||
CREATE TABLE settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
)
|
||||
''');
|
||||
// 初始化默认密码
|
||||
await db.insert('settings', {'key': 'password', 'value': '123456'});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> close() async {
|
||||
if (_database != null) {
|
||||
await _database!.close();
|
||||
_database = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化测试数据(仅调试模式使用)
|
||||
Future<void> initTestData() async {
|
||||
final db = await database;
|
||||
|
||||
// 检查是否已有数据
|
||||
final count = Sqflite.firstIntValue(
|
||||
await db.rawQuery('SELECT COUNT(*) FROM programs'),
|
||||
);
|
||||
if (count != null && count > 0) return;
|
||||
|
||||
// 插入测试程序并添加步骤
|
||||
final testPrograms = [
|
||||
{'code': 'P001', 'name': '标准检测程序', 'created_at': '2026-05-19', 'status': 1},
|
||||
{'code': 'P002', 'name': '快速检测程序', 'created_at': '2026-05-18', 'status': 1},
|
||||
{'code': 'P003', 'name': '深度检测程序', 'created_at': '2026-05-17', 'status': 1},
|
||||
{'code': 'P004', 'name': '样本预处理程序', 'created_at': '2026-05-16', 'status': 0},
|
||||
{'code': 'P005', 'name': '磁珠分离程序', 'created_at': '2026-05-15', 'status': 1},
|
||||
];
|
||||
|
||||
for (final program in testPrograms) {
|
||||
final programId = await db.insert('programs', program);
|
||||
|
||||
// 为每个程序添加测试步骤
|
||||
final testSteps = [
|
||||
{
|
||||
'program_id': programId,
|
||||
'step_no': 1,
|
||||
'position': 'A1',
|
||||
'name': '混合',
|
||||
'mix_time': 60,
|
||||
'magnet_time': 0,
|
||||
'volume': 100,
|
||||
'mix_speed': '中速',
|
||||
'blow_speed': '中速',
|
||||
'blow_time': 0,
|
||||
'needle_speed': 5,
|
||||
},
|
||||
{
|
||||
'program_id': programId,
|
||||
'step_no': 2,
|
||||
'position': 'A1',
|
||||
'name': '吸磁',
|
||||
'mix_time': 0,
|
||||
'magnet_time': 30,
|
||||
'volume': 0,
|
||||
'mix_speed': '中速',
|
||||
'blow_speed': '中速',
|
||||
'blow_time': 0,
|
||||
'needle_speed': 5,
|
||||
},
|
||||
{
|
||||
'program_id': programId,
|
||||
'step_no': 3,
|
||||
'position': 'A2',
|
||||
'name': '吹气',
|
||||
'mix_time': 0,
|
||||
'magnet_time': 0,
|
||||
'volume': 0,
|
||||
'mix_speed': '中速',
|
||||
'blow_speed': '高速',
|
||||
'blow_time': 10,
|
||||
'needle_speed': 8,
|
||||
},
|
||||
];
|
||||
|
||||
for (final step in testSteps) {
|
||||
await db.insert('steps', step);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
366
lib/core/localization/app_localizations.dart
Normal file
366
lib/core/localization/app_localizations.dart
Normal file
@@ -0,0 +1,366 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 应用国际化配置
|
||||
class AppLocalizations {
|
||||
final Locale locale;
|
||||
|
||||
AppLocalizations(this.locale);
|
||||
|
||||
static AppLocalizations? of(BuildContext context) {
|
||||
return Localizations.of<AppLocalizations>(context, AppLocalizations);
|
||||
}
|
||||
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||
_AppLocalizationsDelegate();
|
||||
|
||||
// 状态栏
|
||||
String get deviceName => _localizedValues[locale.languageCode]?['deviceName'] ?? '污水毒品前处理一体机';
|
||||
String get running => _localizedValues[locale.languageCode]?['running'] ?? '运行中';
|
||||
String get idle => _localizedValues[locale.languageCode]?['idle'] ?? '未运行';
|
||||
String get lighting => _localizedValues[locale.languageCode]?['lighting'] ?? '照明';
|
||||
|
||||
// 程序管理
|
||||
String get programs => _localizedValues[locale.languageCode]?['programs'] ?? '程序管理';
|
||||
String get programList => _localizedValues[locale.languageCode]?['programList'] ?? '程序列表';
|
||||
String get programName => _localizedValues[locale.languageCode]?['programName'] ?? '程序名称';
|
||||
String get programCode => _localizedValues[locale.languageCode]?['programCode'] ?? '程序编号';
|
||||
String get createTime => _localizedValues[locale.languageCode]?['createTime'] ?? '创建时间';
|
||||
String get addProgram => _localizedValues[locale.languageCode]?['addProgram'] ?? '新增程序';
|
||||
String get editProgram => _localizedValues[locale.languageCode]?['editProgram'] ?? '编辑程序';
|
||||
String get deleteProgram => _localizedValues[locale.languageCode]?['deleteProgram'] ?? '删除程序';
|
||||
String get importProgram => _localizedValues[locale.languageCode]?['importProgram'] ?? '导入程序';
|
||||
String get viewDetails => _localizedValues[locale.languageCode]?['viewDetails'] ?? '查看详情';
|
||||
String get selectedProgram => _localizedValues[locale.languageCode]?['selectedProgram'] ?? '当前选中程序';
|
||||
String get selectedProgramLabel => _localizedValues[locale.languageCode]?['selectedProgramLabel'] ?? '当前选中';
|
||||
String get availablePrograms => _localizedValues[locale.languageCode]?['availablePrograms'] ?? '可用程序';
|
||||
String get ceramicNotInstalled => _localizedValues[locale.languageCode]?['ceramicNotInstalled'] ?? '瓷套棒: 未安装 — 禁止启动';
|
||||
String get ceramicInstalled => _localizedValues[locale.languageCode]?['ceramicInstalled'] ?? '瓷套棒: 已安装';
|
||||
String get runningMonitor => _localizedValues[locale.languageCode]?['runningMonitor'] ?? '运行状态监控';
|
||||
String get currentHole => _localizedValues[locale.languageCode]?['currentHole'] ?? '当前孔位';
|
||||
String get stepParams => _localizedValues[locale.languageCode]?['stepParams'] ?? '步骤参数';
|
||||
String get speed => _localizedValues[locale.languageCode]?['speed'] ?? '转速';
|
||||
String get temperature => _localizedValues[locale.languageCode]?['temperature'] ?? '温度';
|
||||
String get duration => _localizedValues[locale.languageCode]?['duration'] ?? '持续时间';
|
||||
String get sampleVolume => _localizedValues[locale.languageCode]?['sampleVolume'] ?? '样品体积';
|
||||
String get pleaseSelectProgram => _localizedValues[locale.languageCode]?['pleaseSelectProgram'] ?? '请选择要运行的程序';
|
||||
|
||||
// 运行控制
|
||||
String get run => _localizedValues[locale.languageCode]?['run'] ?? '运行';
|
||||
String get pause => _localizedValues[locale.languageCode]?['pause'] ?? '暂停';
|
||||
String get continue_ => _localizedValues[locale.languageCode]?['continue'] ?? '继续';
|
||||
String get stop => _localizedValues[locale.languageCode]?['stop'] ?? '停止';
|
||||
String get startRun => _localizedValues[locale.languageCode]?['startRun'] ?? '开始运行';
|
||||
String get currentStep => _localizedValues[locale.languageCode]?['currentStep'] ?? '当前步骤';
|
||||
String get remainingTime => _localizedValues[locale.languageCode]?['remainingTime'] ?? '剩余时间';
|
||||
String get progress => _localizedValues[locale.languageCode]?['progress'] ?? '进度';
|
||||
String get ceramicSleeveConfirm => _localizedValues[locale.languageCode]?['ceramicSleeveConfirm'] ?? '运行前请确认已安装瓷套棒';
|
||||
String get paused => _localizedValues[locale.languageCode]?['paused'] ?? '已暂停';
|
||||
String get stopConfirm => _localizedValues[locale.languageCode]?['stopConfirm'] ?? '确定要停止当前运行的程序吗?';
|
||||
String get currentProgram => _localizedValues[locale.languageCode]?['currentProgram'] ?? '当前程序';
|
||||
String get backToHome => _localizedValues[locale.languageCode]?['backToHome'] ?? '返回首页';
|
||||
String get runAgain => _localizedValues[locale.languageCode]?['runAgain'] ?? '重新运行';
|
||||
String get deleteConfirm => _localizedValues[locale.languageCode]?['deleteConfirm'] ?? '确定要删除此程序吗?';
|
||||
|
||||
// 步骤参数
|
||||
String get stepNo => _localizedValues[locale.languageCode]?['stepNo'] ?? '步骤编号';
|
||||
String get position => _localizedValues[locale.languageCode]?['position'] ?? '孔位';
|
||||
String get stepName => _localizedValues[locale.languageCode]?['stepName'] ?? '步骤名称';
|
||||
String get mixTime => _localizedValues[locale.languageCode]?['mixTime'] ?? '混合时间';
|
||||
String get magnetTime => _localizedValues[locale.languageCode]?['magnetTime'] ?? '吸磁时间';
|
||||
String get volume => _localizedValues[locale.languageCode]?['volume'] ?? '容积';
|
||||
String get mixSpeed => _localizedValues[locale.languageCode]?['mixSpeed'] ?? '混合速度';
|
||||
String get blowSpeed => _localizedValues[locale.languageCode]?['blowSpeed'] ?? '吹气速度';
|
||||
String get blowTime => _localizedValues[locale.languageCode]?['blowTime'] ?? '吹气时间';
|
||||
String get needleSpeed => _localizedValues[locale.languageCode]?['needleSpeed'] ?? '下针速度';
|
||||
|
||||
// 速度选项
|
||||
String get lowSpeed => _localizedValues[locale.languageCode]?['lowSpeed'] ?? '低速';
|
||||
String get mediumSpeed => _localizedValues[locale.languageCode]?['mediumSpeed'] ?? '中速';
|
||||
String get highSpeed => _localizedValues[locale.languageCode]?['highSpeed'] ?? '高速';
|
||||
|
||||
// 设置
|
||||
String get settings => _localizedValues[locale.languageCode]?['settings'] ?? '系统设置';
|
||||
String get language => _localizedValues[locale.languageCode]?['language'] ?? '语言设置';
|
||||
String get password => _localizedValues[locale.languageCode]?['password'] ?? '密码修改';
|
||||
String get upgrade => _localizedValues[locale.languageCode]?['upgrade'] ?? '软件升级';
|
||||
String get usbImport => _localizedValues[locale.languageCode]?['usbImport'] ?? 'U盘导入';
|
||||
|
||||
// 通用
|
||||
String get confirm => _localizedValues[locale.languageCode]?['confirm'] ?? '确认';
|
||||
String get cancel => _localizedValues[locale.languageCode]?['cancel'] ?? '取消';
|
||||
String get save => _localizedValues[locale.languageCode]?['save'] ?? '保存';
|
||||
String get delete => _localizedValues[locale.languageCode]?['delete'] ?? '删除';
|
||||
String get select => _localizedValues[locale.languageCode]?['select'] ?? '选择';
|
||||
String get selected => _localizedValues[locale.languageCode]?['selected'] ?? '已选择';
|
||||
String get detail => _localizedValues[locale.languageCode]?['detail'] ?? '详情';
|
||||
String get noData => _localizedValues[locale.languageCode]?['noData'] ?? '暂无数据';
|
||||
|
||||
// 完成提示
|
||||
String get runComplete => _localizedValues[locale.languageCode]?['runComplete'] ?? '运行完成';
|
||||
String get sampleDropGuide => _localizedValues[locale.languageCode]?['sampleDropGuide'] ?? '请将样本滴入检测卡';
|
||||
|
||||
// 补充缺失的翻译
|
||||
String get lightOn => _localizedValues[locale.languageCode]?['lightOn'] ?? '亮';
|
||||
String get lightOff => _localizedValues[locale.languageCode]?['lightOff'] ?? '暗';
|
||||
String get enabled => _localizedValues[locale.languageCode]?['enabled'] ?? '启用';
|
||||
String get disabled => _localizedValues[locale.languageCode]?['disabled'] ?? '停用';
|
||||
String get stepList => _localizedValues[locale.languageCode]?['stepList'] ?? '步骤列表';
|
||||
String get operationSteps => _localizedValues[locale.languageCode]?['operationSteps'] ?? '操作步骤';
|
||||
String get addStep => _localizedValues[locale.languageCode]?['addStep'] ?? '添加步骤';
|
||||
String get editStep => _localizedValues[locale.languageCode]?['editStep'] ?? '编辑步骤';
|
||||
String get deleteStep => _localizedValues[locale.languageCode]?['deleteStep'] ?? '删除步骤';
|
||||
String get deleteStepConfirm => _localizedValues[locale.languageCode]?['deleteStepConfirm'] ?? '确定要删除此步骤吗?';
|
||||
String get stepsCount => _localizedValues[locale.languageCode]?['stepsCount'] ?? '步';
|
||||
String get noSteps => _localizedValues[locale.languageCode]?['noSteps'] ?? '暂无步骤';
|
||||
String get selectStepFirst => _localizedValues[locale.languageCode]?['selectStepFirst'] ?? '请选择或添加步骤';
|
||||
String get oldPassword => _localizedValues[locale.languageCode]?['oldPassword'] ?? '原密码';
|
||||
String get newPassword => _localizedValues[locale.languageCode]?['newPassword'] ?? '新密码';
|
||||
String get confirmPassword => _localizedValues[locale.languageCode]?['confirmPassword'] ?? '确认新密码';
|
||||
String get passwordMinLength => _localizedValues[locale.languageCode]?['passwordMinLength'] ?? '至少6位字符';
|
||||
String get passwordChanged => _localizedValues[locale.languageCode]?['passwordChanged'] ?? '密码已修改';
|
||||
String get passwordChangeFailed => _localizedValues[locale.languageCode]?['passwordChangeFailed'] ?? '密码修改失败';
|
||||
String get oldPasswordError => _localizedValues[locale.languageCode]?['oldPasswordError'] ?? '原密码错误';
|
||||
String get passwordMismatch => _localizedValues[locale.languageCode]?['passwordMismatch'] ?? '两次输入的新密码不一致';
|
||||
String get fillAllFields => _localizedValues[locale.languageCode]?['fillAllFields'] ?? '请填写所有字段';
|
||||
String get importSuccess => _localizedValues[locale.languageCode]?['importSuccess'] ?? '成功导入';
|
||||
String get importFailed => _localizedValues[locale.languageCode]?['importFailed'] ?? '导入失败';
|
||||
String get programsImported => _localizedValues[locale.languageCode]?['programsImported'] ?? '个程序';
|
||||
String get usbDetected => _localizedValues[locale.languageCode]?['usbDetected'] ?? '检测到U盘';
|
||||
String get usbNotDetected => _localizedValues[locale.languageCode]?['usbNotDetected'] ?? '未检测到U盘';
|
||||
String get insertUsb => _localizedValues[locale.languageCode]?['insertUsb'] ?? '请插入U盘后重试';
|
||||
String get detectingUsb => _localizedValues[locale.languageCode]?['detectingUsb'] ?? '正在检测U盘...';
|
||||
String get currentVersion => _localizedValues[locale.languageCode]?['currentVersion'] ?? '当前版本';
|
||||
String get latestVersion => _localizedValues[locale.languageCode]?['latestVersion'] ?? '已是最新版本';
|
||||
String get updateAvailable => _localizedValues[locale.languageCode]?['updateAvailable'] ?? '有新版本可用';
|
||||
String get checkUpdate => _localizedValues[locale.languageCode]?['checkUpdate'] ?? '检查更新';
|
||||
|
||||
static final Map<String, Map<String, String>> _localizedValues = {
|
||||
'zh': {
|
||||
'deviceName': '污水毒品前处理一体机',
|
||||
'running': '运行中',
|
||||
'idle': '未运行',
|
||||
'lighting': '照明',
|
||||
'programs': '程序管理',
|
||||
'programList': '程序列表',
|
||||
'programName': '程序名称',
|
||||
'programCode': '程序编号',
|
||||
'createTime': '创建时间',
|
||||
'addProgram': '新增程序',
|
||||
'editProgram': '编辑程序',
|
||||
'deleteProgram': '删除程序',
|
||||
'importProgram': '导入程序',
|
||||
'viewDetails': '查看详情',
|
||||
'selectedProgram': '当前选中程序',
|
||||
'selectedProgramLabel': '当前选中',
|
||||
'availablePrograms': '可用程序',
|
||||
'ceramicNotInstalled': '瓷套棒: 未安装 — 禁止启动',
|
||||
'ceramicInstalled': '瓷套棒: 已安装',
|
||||
'runningMonitor': '运行状态监控',
|
||||
'currentHole': '当前孔位',
|
||||
'stepParams': '步骤参数',
|
||||
'speed': '转速',
|
||||
'temperature': '温度',
|
||||
'duration': '持续时间',
|
||||
'sampleVolume': '样品体积',
|
||||
'pleaseSelectProgram': '请选择要运行的程序',
|
||||
'run': '运行',
|
||||
'pause': '暂停',
|
||||
'continue': '继续',
|
||||
'stop': '停止',
|
||||
'startRun': '开始运行',
|
||||
'currentStep': '当前步骤',
|
||||
'remainingTime': '剩余时间',
|
||||
'progress': '进度',
|
||||
'ceramicSleeveConfirm': '运行前请确认已安装瓷套棒',
|
||||
'paused': '已暂停',
|
||||
'stopConfirm': '确定要停止当前运行的程序吗?',
|
||||
'currentProgram': '当前程序',
|
||||
'backToHome': '返回首页',
|
||||
'runAgain': '重新运行',
|
||||
'deleteConfirm': '确定要删除此程序吗?',
|
||||
'stepNo': '步骤编号',
|
||||
'position': '孔位',
|
||||
'stepName': '步骤名称',
|
||||
'mixTime': '混合时间',
|
||||
'magnetTime': '吸磁时间',
|
||||
'volume': '容积',
|
||||
'mixSpeed': '混合速度',
|
||||
'blowSpeed': '吹气速度',
|
||||
'blowTime': '吹气时间',
|
||||
'needleSpeed': '下针速度',
|
||||
'lowSpeed': '低速',
|
||||
'mediumSpeed': '中速',
|
||||
'highSpeed': '高速',
|
||||
'settings': '系统设置',
|
||||
'language': '语言设置',
|
||||
'password': '密码修改',
|
||||
'upgrade': '软件升级',
|
||||
'usbImport': 'U盘导入',
|
||||
'confirm': '确认',
|
||||
'cancel': '取消',
|
||||
'save': '保存',
|
||||
'delete': '删除',
|
||||
'select': '选择',
|
||||
'selected': '已选择',
|
||||
'detail': '详情',
|
||||
'noData': '暂无数据',
|
||||
'runComplete': '运行完成',
|
||||
'sampleDropGuide': '请将样本滴入检测卡',
|
||||
'lightOn': '亮',
|
||||
'lightOff': '暗',
|
||||
'enabled': '启用',
|
||||
'disabled': '停用',
|
||||
'stepList': '步骤列表',
|
||||
'operationSteps': '操作步骤',
|
||||
'addStep': '添加步骤',
|
||||
'editStep': '编辑步骤',
|
||||
'deleteStep': '删除步骤',
|
||||
'deleteStepConfirm': '确定要删除此步骤吗?',
|
||||
'stepsCount': '步',
|
||||
'noSteps': '暂无步骤',
|
||||
'selectStepFirst': '请选择或添加步骤',
|
||||
'oldPassword': '原密码',
|
||||
'newPassword': '新密码',
|
||||
'confirmPassword': '确认新密码',
|
||||
'passwordMinLength': '至少6位字符',
|
||||
'passwordChanged': '密码已修改',
|
||||
'passwordChangeFailed': '密码修改失败',
|
||||
'oldPasswordError': '原密码错误',
|
||||
'passwordMismatch': '两次输入的新密码不一致',
|
||||
'fillAllFields': '请填写所有字段',
|
||||
'importSuccess': '成功导入',
|
||||
'importFailed': '导入失败',
|
||||
'programsImported': '个程序',
|
||||
'usbDetected': '检测到U盘',
|
||||
'usbNotDetected': '未检测到U盘',
|
||||
'insertUsb': '请插入U盘后重试',
|
||||
'detectingUsb': '正在检测U盘...',
|
||||
'currentVersion': '当前版本',
|
||||
'latestVersion': '已是最新版本',
|
||||
'updateAvailable': '有新版本可用',
|
||||
'checkUpdate': '检查更新',
|
||||
},
|
||||
'en': {
|
||||
'deviceName': 'Wastewater Drug Pretreatment System',
|
||||
'running': 'Running',
|
||||
'idle': 'Idle',
|
||||
'lighting': 'Lighting',
|
||||
'programs': 'Programs',
|
||||
'programList': 'Program List',
|
||||
'programName': 'Program Name',
|
||||
'programCode': 'Program Code',
|
||||
'createTime': 'Create Time',
|
||||
'addProgram': 'Add Program',
|
||||
'editProgram': 'Edit Program',
|
||||
'deleteProgram': 'Delete Program',
|
||||
'importProgram': 'Import Program',
|
||||
'viewDetails': 'View Details',
|
||||
'selectedProgram': 'Selected Program',
|
||||
'selectedProgramLabel': 'Selected',
|
||||
'availablePrograms': 'Available Programs',
|
||||
'ceramicNotInstalled': 'Ceramic sleeve: Not installed — Cannot start',
|
||||
'ceramicInstalled': 'Ceramic sleeve: Installed',
|
||||
'runningMonitor': 'Running Status Monitor',
|
||||
'currentHole': 'Current Position',
|
||||
'stepParams': 'Step Parameters',
|
||||
'speed': 'Speed',
|
||||
'temperature': 'Temperature',
|
||||
'duration': 'Duration',
|
||||
'sampleVolume': 'Sample Volume',
|
||||
'pleaseSelectProgram': 'Please select a program',
|
||||
'run': 'Run',
|
||||
'pause': 'Pause',
|
||||
'continue': 'Continue',
|
||||
'stop': 'Stop',
|
||||
'startRun': 'Start Run',
|
||||
'currentStep': 'Current Step',
|
||||
'remainingTime': 'Remaining',
|
||||
'progress': 'Progress',
|
||||
'ceramicSleeveConfirm': 'Please confirm ceramic sleeve is installed',
|
||||
'paused': 'Paused',
|
||||
'stopConfirm': 'Are you sure to stop the running program?',
|
||||
'currentProgram': 'Current Program',
|
||||
'backToHome': 'Back to Home',
|
||||
'runAgain': 'Run Again',
|
||||
'deleteConfirm': 'Are you sure to delete this program?',
|
||||
'stepNo': 'Step No.',
|
||||
'position': 'Position',
|
||||
'stepName': 'Step Name',
|
||||
'mixTime': 'Mix Time',
|
||||
'magnetTime': 'Magnet Time',
|
||||
'volume': 'Volume',
|
||||
'mixSpeed': 'Mix Speed',
|
||||
'blowSpeed': 'Blow Speed',
|
||||
'blowTime': 'Blow Time',
|
||||
'needleSpeed': 'Needle Speed',
|
||||
'lowSpeed': 'Low',
|
||||
'mediumSpeed': 'Medium',
|
||||
'highSpeed': 'High',
|
||||
'settings': 'Settings',
|
||||
'language': 'Language',
|
||||
'password': 'Password',
|
||||
'upgrade': 'Upgrade',
|
||||
'usbImport': 'USB Import',
|
||||
'confirm': 'Confirm',
|
||||
'cancel': 'Cancel',
|
||||
'save': 'Save',
|
||||
'delete': 'Delete',
|
||||
'select': 'Select',
|
||||
'selected': 'Selected',
|
||||
'detail': 'Detail',
|
||||
'noData': 'No Data',
|
||||
'runComplete': 'Complete',
|
||||
'sampleDropGuide': 'Drop sample to test card',
|
||||
'lightOn': 'On',
|
||||
'lightOff': 'Off',
|
||||
'enabled': 'Enabled',
|
||||
'disabled': 'Disabled',
|
||||
'stepList': 'Step List',
|
||||
'operationSteps': 'Operation Steps',
|
||||
'addStep': 'Add Step',
|
||||
'editStep': 'Edit Step',
|
||||
'deleteStep': 'Delete Step',
|
||||
'deleteStepConfirm': 'Are you sure to delete this step?',
|
||||
'stepsCount': 'steps',
|
||||
'noSteps': 'No steps',
|
||||
'selectStepFirst': 'Please select or add a step',
|
||||
'oldPassword': 'Old Password',
|
||||
'newPassword': 'New Password',
|
||||
'confirmPassword': 'Confirm Password',
|
||||
'passwordMinLength': 'At least 6 characters',
|
||||
'passwordChanged': 'Password changed',
|
||||
'passwordChangeFailed': 'Password change failed',
|
||||
'oldPasswordError': 'Old password incorrect',
|
||||
'passwordMismatch': 'Passwords do not match',
|
||||
'fillAllFields': 'Please fill all fields',
|
||||
'importSuccess': 'Successfully imported',
|
||||
'importFailed': 'Import failed',
|
||||
'programsImported': 'programs',
|
||||
'usbDetected': 'USB detected',
|
||||
'usbNotDetected': 'USB not detected',
|
||||
'insertUsb': 'Please insert USB and try again',
|
||||
'detectingUsb': 'Detecting USB...',
|
||||
'currentVersion': 'Current Version',
|
||||
'latestVersion': 'Already latest version',
|
||||
'updateAvailable': 'Update available',
|
||||
'checkUpdate': 'Check Update',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
const _AppLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) {
|
||||
return ['zh', 'en'].contains(locale.languageCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AppLocalizations> load(Locale locale) async {
|
||||
return AppLocalizations(locale);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
}
|
||||
48
lib/core/localization/locale_provider.dart
Normal file
48
lib/core/localization/locale_provider.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// Locale 状态 Notifier
|
||||
class LocaleNotifier extends StateNotifier<Locale> {
|
||||
static const String _key = 'app_locale';
|
||||
|
||||
LocaleNotifier() : super(const Locale('zh', 'CN')) {
|
||||
_loadLocale();
|
||||
}
|
||||
|
||||
/// 从本地存储加载语言设置
|
||||
Future<void> _loadLocale() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final localeCode = prefs.getString(_key);
|
||||
if (localeCode != null) {
|
||||
state = Locale(localeCode, localeCode == 'zh' ? 'CN' : 'US');
|
||||
}
|
||||
}
|
||||
|
||||
/// 切换语言
|
||||
Future<void> setLocale(Locale locale) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_key, locale.languageCode);
|
||||
state = locale;
|
||||
}
|
||||
|
||||
/// 切换为中文
|
||||
Future<void> setChinese() async {
|
||||
await setLocale(const Locale('zh', 'CN'));
|
||||
}
|
||||
|
||||
/// 切换为英文
|
||||
Future<void> setEnglish() async {
|
||||
await setLocale(const Locale('en', 'US'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Locale Provider
|
||||
final localeProvider = StateNotifierProvider<LocaleNotifier, Locale>((ref) {
|
||||
return LocaleNotifier();
|
||||
});
|
||||
|
||||
/// 当前语言是否为中文
|
||||
final isChineseProvider = Provider<bool>((ref) {
|
||||
return ref.watch(localeProvider).languageCode == 'zh';
|
||||
});
|
||||
45
lib/core/router/app_router.dart
Normal file
45
lib/core/router/app_router.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../features/home/pages/home_page.dart';
|
||||
import '../../features/programs/pages/programs_page.dart';
|
||||
import '../../features/program_detail/pages/program_detail_page.dart';
|
||||
import '../../features/settings/pages/settings_page.dart';
|
||||
import '../../features/home/pages/complete_page.dart';
|
||||
|
||||
/// 应用路由配置
|
||||
final goRouterProvider = Provider<GoRouter>((ref) {
|
||||
return GoRouter(
|
||||
initialLocation: '/',
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/',
|
||||
name: 'home',
|
||||
builder: (context, state) => const HomePage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/programs',
|
||||
name: 'programs',
|
||||
builder: (context, state) => const ProgramsPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/programs/:id',
|
||||
name: 'programDetail',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id'];
|
||||
return ProgramDetailPage(programId: id ?? '');
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/settings',
|
||||
name: 'settings',
|
||||
builder: (context, state) => const SettingsPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/complete',
|
||||
name: 'complete',
|
||||
builder: (context, state) => const CompletePage(),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
179
lib/core/theme/app_theme.dart
Normal file
179
lib/core/theme/app_theme.dart
Normal file
@@ -0,0 +1,179 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 应用主题配置 - 明亮工业控制风格
|
||||
/// 主色 #2196F3,圆角 4px,明亮背景,适配 1920x1080 横屏
|
||||
class AppTheme {
|
||||
// ========== 主色 ==========
|
||||
static const Color primaryColor = Color(0xFF2196F3);
|
||||
static const Color primaryDark = Color(0xFF1976D2);
|
||||
static const Color primaryLight = Color(0xFFBBDEFB);
|
||||
|
||||
// ========== 功能色 ==========
|
||||
static const Color successColor = Color(0xFF4CAF50);
|
||||
static const Color warningColor = Color(0xFFFF9800);
|
||||
static const Color errorColor = Color(0xFFF44336);
|
||||
static const Color infoColor = Color(0xFF00BCD4);
|
||||
|
||||
// ========== 背景色(明亮) ==========
|
||||
static const Color bgPage = Color(0xFFF5F7FA);
|
||||
static const Color bgDeep = Color(0xFFE8ECF0);
|
||||
static const Color bgSurface = Color(0xFFFFFFFF);
|
||||
static const Color bgCard = Color(0xFFFFFFFF);
|
||||
static const Color bgCardHover = Color(0xFFF0F7FF);
|
||||
static const Color bgSidebar = Color(0xFFF0F2F5);
|
||||
|
||||
// ========== 文本色 ==========
|
||||
static const Color textHeading = Color(0xFF1A1A2E);
|
||||
static const Color textPrimary = Color(0xFF333344);
|
||||
static const Color textSecondary = Color(0xFF6B7280);
|
||||
static const Color textTertiary = Color(0xFF9CA3AF);
|
||||
static const Color textOnPrimary = Colors.white;
|
||||
|
||||
// ========== 状态色 ==========
|
||||
static const Color statusRunning = Color(0xFF4CAF50);
|
||||
static const Color statusStopped = Color(0xFF9CA3AF);
|
||||
static const Color statusPaused = Color(0xFFFF9800);
|
||||
static const Color statusError = Color(0xFFF44336);
|
||||
|
||||
// ========== 卡片背景 ==========
|
||||
static const Color cardBg = Color(0xFFFFFFFF);
|
||||
static const Color cardSelectedBg = Color(0xFFE3F2FD);
|
||||
|
||||
// ========== 功能色(accent) ==========
|
||||
static const Color accentPrimary = primaryColor;
|
||||
static const Color accentInfo = infoColor;
|
||||
static const Color accentWarning = warningColor;
|
||||
static const Color accentCritical = errorColor;
|
||||
|
||||
// ========== 边框色 ==========
|
||||
static const Color borderLight = Color(0xFFE5E7EB);
|
||||
static const Color borderMedium = Color(0xFFD1D5DB);
|
||||
static const Color borderSubtle = borderLight;
|
||||
static const Color borderFocus = primaryColor;
|
||||
|
||||
// ========== 圆角 ==========
|
||||
static const double radiusSm = 4.0;
|
||||
static const double radiusMd = 8.0;
|
||||
static const double radiusLg = 12.0;
|
||||
|
||||
// ========== 阴影 ==========
|
||||
static const List<BoxShadow> shadowCard = [
|
||||
BoxShadow(
|
||||
color: Color(0x0A000000),
|
||||
blurRadius: 8,
|
||||
offset: Offset(0, 2),
|
||||
),
|
||||
];
|
||||
|
||||
static const List<BoxShadow> shadowCardHover = [
|
||||
BoxShadow(
|
||||
color: Color(0x14000000),
|
||||
blurRadius: 12,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
];
|
||||
|
||||
// ========== 兼容旧代码的颜色别名 ==========
|
||||
static const Color runningColor = statusRunning;
|
||||
static const Color idleColor = statusStopped;
|
||||
static const Color backgroundColor = bgPage;
|
||||
static const Color cardColor = bgCard;
|
||||
|
||||
/// 亮色主题 - 明亮工业风格
|
||||
static ThemeData lightTheme() {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: primaryColor,
|
||||
brightness: Brightness.light,
|
||||
),
|
||||
scaffoldBackgroundColor: bgPage,
|
||||
fontFamily: 'Inter',
|
||||
cardTheme: CardThemeData(
|
||||
color: bgCard,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radiusMd),
|
||||
side: const BorderSide(color: borderLight, width: 1),
|
||||
),
|
||||
margin: EdgeInsets.zero,
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: bgSurface,
|
||||
foregroundColor: textHeading,
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
scrolledUnderElevation: 1,
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: textOnPrimary,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radiusSm),
|
||||
),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(radiusSm),
|
||||
borderSide: const BorderSide(color: borderMedium),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(radiusSm),
|
||||
borderSide: const BorderSide(color: borderMedium),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(radiusSm),
|
||||
borderSide: const BorderSide(color: primaryColor, width: 2),
|
||||
),
|
||||
filled: true,
|
||||
fillColor: bgSurface,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||
),
|
||||
dialogTheme: DialogThemeData(
|
||||
backgroundColor: bgSurface,
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radiusMd),
|
||||
),
|
||||
),
|
||||
snackBarTheme: SnackBarThemeData(
|
||||
backgroundColor: textHeading,
|
||||
contentTextStyle: const TextStyle(color: Colors.white, fontSize: 14),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radiusSm),
|
||||
),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
listTileTheme: const ListTileThemeData(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(radiusSm)),
|
||||
),
|
||||
),
|
||||
dataTableTheme: DataTableThemeData(
|
||||
headingRowColor: WidgetStateProperty.all(bgSidebar),
|
||||
dividerThickness: 1,
|
||||
),
|
||||
dividerTheme: const DividerThemeData(
|
||||
color: borderLight,
|
||||
thickness: 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 暗色主题(与亮色主题风格一致的暗色模式)
|
||||
static ThemeData darkTheme() {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: primaryColor,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
scaffoldBackgroundColor: const Color(0xFF121212),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user