// 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'; /// 私有数据库实例,仅在服务内部访问。 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: 1, onCreate: _onCreate); } catch (e) { // 在这里添加日志记录,例如 Get.log('数据库初始化失败:$e'); rethrow; } } /// 数据库创建时的回调函数,用于定义表结构。 /// **注意**:这里新增了 `operation` 和 `isChecked` 两个字段。 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 -- 新增:问题是否已检查(SQLite 用 INTEGER 表示布尔值) ) '''); } // --- /// **数据操作 (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) { // 可以添加日志记录 return 0; // 返回 0 表示插入失败 } } /// 根据 ID 从数据库中删除一个问题。 /// /// 参数:`id` - 要删除的问题ID。 /// 返回:`Future`,表示被删除的行数。 Future deleteProblem(String id) async { try { return await _database.delete( _tableName, where: 'id = ?', whereArgs: [id], ); } catch (e) { // 可以添加日志记录 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) { // 可以添加日志记录 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) { // 可以添加日志记录 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) { // 可以添加日志记录 return []; } } // --- /// `GetxService` 生命周期方法,在服务被销毁前调用, /// 用于关闭数据库连接,防止资源泄漏。 @override void onClose() { _database.close(); super.onClose(); } }