import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; /// 数据库服务 class DatabaseService { static final DatabaseService instance = DatabaseService._internal(); static Database? _database; DatabaseService._internal(); Future get database async { if (_database != null) return _database!; _database = await _initDatabase(); return _database!; } Future _initDatabase() async { final dbPath = await getDatabasesPath(); final path = join(dbPath, 'kuaishai.db'); return await openDatabase( path, version: 3, onCreate: _onCreate, onUpgrade: _onUpgrade, ); } Future _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, temperature INTEGER DEFAULT 50, airflow_time INTEGER DEFAULT 60 ) '''); // 步骤表 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, blow_time INTEGER DEFAULT 0, 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 _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'}); } if (oldVersion < 3) { // v3: 重构字段 // programs 增加 temperature, airflow_time await db.execute('ALTER TABLE programs ADD COLUMN temperature INTEGER DEFAULT 50'); await db.execute('ALTER TABLE programs ADD COLUMN airflow_time INTEGER DEFAULT 60'); // steps 删除 mix_speed, blow_speed, needle_speed;增加 speed // sqflite 不支持 DROP COLUMN,旧字段保留但不再使用 await db.execute('ALTER TABLE steps ADD COLUMN speed INTEGER DEFAULT 5'); } } Future close() async { if (_database != null) { await _database!.close(); _database = null; } } /// 通用 KV 读:读取 settings 表中 [key] 对应的 value;不存在返回 null Future readSetting(String key) async { final db = await database; final rows = await db.query( 'settings', columns: ['value'], where: 'key = ?', whereArgs: [key], limit: 1, ); if (rows.isEmpty) return null; return rows.first['value'] as String?; } /// 通用 KV 写:以 INSERT OR REPLACE 写入 settings 表 Future writeSetting(String key, String value) async { final db = await database; await db.insert( 'settings', {'key': key, 'value': value}, conflictAlgorithm: ConflictAlgorithm.replace, ); } /// 初始化测试数据(仅调试模式使用) Future 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, 'temperature': 50, 'airflow_time': 60}, {'code': 'P002', 'name': '快速检测程序', 'created_at': '2026-05-18', 'status': 1, 'temperature': 45, 'airflow_time': 30}, {'code': 'P003', 'name': '深度检测程序', 'created_at': '2026-05-17', 'status': 1, 'temperature': 60, 'airflow_time': 90}, {'code': 'P004', 'name': '样本预处理程序', 'created_at': '2026-05-16', 'status': 0, 'temperature': 50, 'airflow_time': 60}, {'code': 'P005', 'name': '磁珠分离程序', 'created_at': '2026-05-15', 'status': 1, 'temperature': 55, 'airflow_time': 60}, ]; 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, 'blow_time': 0, 'speed': 5, }, { 'program_id': programId, 'step_no': 2, 'position': 'A1', 'name': '吸磁', 'mix_time': 0, 'magnet_time': 30, 'volume': 0, 'blow_time': 0, 'speed': 5, }, { 'program_id': programId, 'step_no': 3, 'position': 'A2', 'name': '吹气', 'mix_time': 0, 'magnet_time': 0, 'volume': 0, 'blow_time': 10, 'speed': 8, }, ]; for (final step in testSteps) { await db.insert('steps', step); } } } }