// sqlite_provider.dart import 'package:get/get.dart'; import 'package:problem_check_system/data/models/sync_status.dart'; import 'package:problem_check_system/data/models/problem_model.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; import 'package:uuid/uuid.dart'; /// `SQLiteProvider` 是一个 GetxService,负责管理本地 SQLite 数据库。 /// 作为一个单例服务,它在整个应用生命周期中只会被创建一次。 class SQLiteProvider extends GetxService { static const String _dbName = 'problems.db'; static const String _tableName = 'problems'; /// 数据库版本号,用于处理表结构升级。 static const int _dbVersion = 1; /// 私有数据库实例,仅在服务内部访问。 late Database _database; /// 在服务首次初始化时调用,用于执行异步设置。 @override void onInit() { super.onInit(); _initDatabase(); } /// 异步初始化数据库连接。如果数据库不存在,则会创建它;如果版本过旧,则会升级。 Future _initDatabase() async { try { final databasePath = await getDatabasesPath(); final path = join(databasePath, _dbName); _database = await openDatabase( path, version: _dbVersion, onCreate: _onCreate, onUpgrade: _onUpgrade, // 新增:处理数据库版本升级 ); } catch (e) { // 在这里添加日志记录,例如 Get.log('数据库初始化失败:$e'); Get.log('数据库初始化失败:$e', isError: true); rethrow; } } /// 数据库创建时的回调函数,用于定义表结构。 Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE $_tableName( id TEXT PRIMARY KEY, description TEXT NOT NULL, location TEXT NOT NULL, imageUrls TEXT NOT NULL, creationTime INTEGER NOT NULL, syncStatus INTEGER NOT NULL, operation INTEGER NOT NULL, censorTaskId TEXT, bindData TEXT, isChecked INTEGER NOT NULL ) '''); } /// 数据库版本升级时的回调函数。 /// 用于在应用更新后,向现有数据库中添加新的列,而不会丢失数据。 Future _onUpgrade(Database db, int oldVersion, int newVersion) async { Get.log('正在将数据库从版本 $oldVersion 升级到 $newVersion...'); if (oldVersion < 2) { // 示例:从版本 1 升级到版本 2,添加一个新的列 'newColumn' // await db.execute('ALTER TABLE $_tableName ADD COLUMN newColumn TEXT;'); // Get.log('已添加新列: newColumn'); } // if (oldVersion < 3) { // ... // } Get.log('数据库升级完成。'); } // --- /// **数据操作 (CRUD) 方法** /// 向数据库中插入一个新问题。 /// 如果 `problem` 没有 `id`,会自动生成一个唯一的 UUID。 /// /// 返回:`Future`,表示插入的行ID。如果失败,会返回 0。 Future insertProblem(Problem problem) async { try { final problemToInsert = problem.copyWith( id: problem.id ?? const Uuid().v4(), ); return await _database.insert( _tableName, problemToInsert.toMap(), conflictAlgorithm: ConflictAlgorithm.replace, ); } catch (e) { Get.log('插入问题失败:$e', isError: true); return 0; // 返回 0 表示插入失败 } } /// 根据 ID 从数据库中删除一个问题。 /// /// 参数:`id` - 要删除的问题ID。 /// 返回:`Future`,表示被删除的行数。 Future deleteProblem(String id) async { try { return await _database.delete( _tableName, where: 'id = ?', whereArgs: [id], ); } catch (e) { Get.log('删除问题(ID: $id)失败:$e', isError: true); return 0; } } /// 更新数据库中已存在的问题。 /// /// 参数:`problem` - 包含更新数据的 `Problem` 对象。 /// 返回:`Future`,表示被更新的行数。 Future updateProblem(Problem problem) async { try { return await _database.update( _tableName, problem.toMap(), where: 'id = ?', whereArgs: [problem.id], ); } catch (e) { Get.log('更新问题(ID: ${problem.id})失败:$e', isError: true); return 0; } } /// 根据 ID 获取单个问题。 /// /// 参数:`id` - 要获取的问题ID。 /// 返回:`Future`,如果找到则返回 `Problem` 对象,否则返回 `null`。 Future getProblemById(String id) async { try { final List> maps = await _database.query( _tableName, where: 'id = ?', whereArgs: [id], limit: 1, ); if (maps.isNotEmpty) { return Problem.fromMap(maps.first); } return null; } catch (e) { Get.log('获取问题(ID: $id)失败:$e', isError: true); return null; } } /// 获取所有问题,支持按筛选条件查询。 /// /// 可选参数: /// - `startDate`: 创建时间范围的开始时间。 /// - `endDate`: 创建时间范围的结束时间。 /// - `syncStatus`: 同步状态。 /// /// 返回:`Future>`,返回符合条件的问题列表。如果查询失败,返回空列表。 Future> getProblems({ DateTime? startDate, DateTime? endDate, SyncStatus? syncStatus, }) async { try { final List whereClauses = []; final List whereArgs = []; if (startDate != null) { whereClauses.add('creationTime >= ?'); whereArgs.add(startDate.millisecondsSinceEpoch); } if (endDate != null) { whereClauses.add('creationTime <= ?'); whereArgs.add(endDate.millisecondsSinceEpoch); } if (syncStatus != null) { whereClauses.add('syncStatus = ?'); whereArgs.add(syncStatus.index); } final String? whereString = whereClauses.isNotEmpty ? whereClauses.join(' AND ') : null; final List> maps = await _database.query( _tableName, where: whereString, whereArgs: whereArgs.isEmpty ? null : whereArgs, orderBy: 'creationTime DESC', ); return maps.map((json) => Problem.fromMap(json)).toList(); } catch (e) { Get.log('获取问题列表失败:$e', isError: true); return []; } } // --- /// `GetxService` 生命周期方法,在服务被销毁前调用, /// 用于关闭数据库连接,防止资源泄漏。 @override void onClose() { _database.close(); super.onClose(); } }