You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
7.8 KiB
285 lines
7.8 KiB
// 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'; |
|
|
|
/// `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<void> _initDatabase() async { |
|
try { |
|
final databasePath = await getDatabasesPath(); |
|
final path = join(databasePath, _dbName); |
|
|
|
_database = await openDatabase( |
|
path, |
|
version: _dbVersion, |
|
onCreate: _onCreate, |
|
onUpgrade: _onUpgrade, |
|
); |
|
|
|
Get.log('数据库初始化成功'); |
|
} catch (e) { |
|
Get.log('数据库初始化失败:$e', isError: true); |
|
rethrow; |
|
} |
|
} |
|
|
|
/// 数据库创建时的回调函数 |
|
Future<void> _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, |
|
isDeleted INTEGER NOT NULL, |
|
censorTaskId TEXT, |
|
bindData TEXT, |
|
isChecked INTEGER NOT NULL |
|
) |
|
'''); |
|
|
|
Get.log('数据库表创建成功'); |
|
} |
|
|
|
/// 数据库版本升级处理 |
|
Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async { |
|
Get.log('正在将数据库从版本 $oldVersion 升级到 $newVersion...'); |
|
|
|
// 版本升级迁移逻辑 |
|
for (int version = oldVersion + 1; version <= newVersion; version++) { |
|
await _runMigration(db, version); |
|
} |
|
|
|
Get.log('数据库升级完成'); |
|
} |
|
|
|
/// 执行特定版本的数据库迁移 |
|
Future<void> _runMigration(Database db, int version) async { |
|
switch (version) { |
|
case 2: |
|
// 版本2迁移逻辑 |
|
// await db.execute('ALTER TABLE $_tableName ADD COLUMN newColumn TEXT;'); |
|
break; |
|
// 添加更多版本迁移逻辑 |
|
default: |
|
Get.log('没有找到版本 $version 的迁移脚本'); |
|
} |
|
} |
|
|
|
/// 插入问题记录,并设置同步状态为未同步 |
|
Future<int> insertProblem(Problem problem) async { |
|
try { |
|
// 确保插入的问题同步状态为未同步 |
|
final problemToInsert = problem.copyWith( |
|
syncStatus: SyncStatus.notSynced, |
|
); |
|
|
|
final result = await _database.insert( |
|
_tableName, |
|
problemToInsert.toMap(), |
|
conflictAlgorithm: ConflictAlgorithm.replace, |
|
); |
|
|
|
Get.log('问题记录插入成功,ID: ${problem.id}'); |
|
return result; |
|
} catch (e) { |
|
Get.log('插入问题失败(ID: ${problem.id}):$e', isError: true); |
|
return 0; |
|
} |
|
} |
|
|
|
/// 逻辑删除问题记录,并设置同步状态为未同步 |
|
Future<int> deleteProblem(String id) async { |
|
try { |
|
final result = await _database.update( |
|
_tableName, |
|
{ |
|
'isDeleted': 1, |
|
'syncStatus': SyncStatus.notSynced.index, // 设置为未同步 |
|
}, |
|
where: 'id = ?', |
|
whereArgs: [id], |
|
); |
|
|
|
if (result > 0) { |
|
Get.log('问题逻辑删除成功,ID: $id'); |
|
} |
|
|
|
return result; |
|
} catch (e) { |
|
Get.log('逻辑删除问题失败(ID: $id):$e', isError: true); |
|
return 0; |
|
} |
|
} |
|
|
|
/// 更新问题记录,并设置同步状态为未同步 |
|
Future<int> updateProblem(Problem problem) async { |
|
try { |
|
// 确保更新后同步状态为未同步 |
|
final problemToUpdate = problem.copyWith( |
|
syncStatus: SyncStatus.notSynced, |
|
); |
|
|
|
final result = await _database.update( |
|
_tableName, |
|
problemToUpdate.toMap(), |
|
where: 'id = ?', |
|
whereArgs: [problem.id], |
|
); |
|
|
|
if (result > 0) { |
|
Get.log('问题更新成功,ID: ${problem.id}'); |
|
} |
|
|
|
return result; |
|
} catch (e) { |
|
Get.log('更新问题失败(ID: ${problem.id}):$e', isError: true); |
|
return 0; |
|
} |
|
} |
|
|
|
/// 获取需要同步的问题记录(所有同步状态为未同步的记录) |
|
Future<List<Problem>> getProblemsForSync() async { |
|
try { |
|
final results = await _database.query( |
|
_tableName, |
|
where: 'syncStatus = ?', |
|
whereArgs: [SyncStatus.notSynced.index], |
|
orderBy: 'creationTime ASC', |
|
); |
|
|
|
Get.log('找到 ${results.length} 条需要同步的记录'); |
|
return results.map((json) => Problem.fromMap(json)).toList(); |
|
} catch (e) { |
|
Get.log('获取待同步问题失败:$e', isError: true); |
|
return []; |
|
} |
|
} |
|
|
|
/// 标记问题为已同步(在同步成功后调用) |
|
Future<int> markAsSynced(String id) async { |
|
try { |
|
final result = await _database.update( |
|
_tableName, |
|
{'syncStatus': SyncStatus.synced.index}, |
|
where: 'id = ? AND syncStatus = ?', |
|
whereArgs: [id, SyncStatus.notSynced.index], |
|
); |
|
|
|
if (result > 0) { |
|
Get.log('问题标记为已同步,ID: $id'); |
|
} |
|
|
|
return result; |
|
} catch (e) { |
|
Get.log('标记同步状态失败(ID: $id):$e', isError: true); |
|
return 0; |
|
} |
|
} |
|
|
|
/// 根据ID获取问题记录 |
|
Future<Problem?> getProblemById(String id) async { |
|
try { |
|
final results = await _database.query( |
|
_tableName, |
|
where: 'id = ? AND isDeleted = 0', |
|
whereArgs: [id], |
|
limit: 1, |
|
); |
|
|
|
return results.isNotEmpty ? Problem.fromMap(results.first) : null; |
|
} catch (e) { |
|
Get.log('获取问题失败(ID: $id):$e', isError: true); |
|
return null; |
|
} |
|
} |
|
|
|
/// 获取问题列表(支持多种筛选条件) |
|
Future<List<Problem>> getProblems({ |
|
DateTime? startDate, |
|
DateTime? endDate, |
|
String? syncStatus, |
|
String? bindStatus, |
|
bool includeDeleted = false, |
|
}) async { |
|
try { |
|
final whereClauses = <String>[]; |
|
final whereArgs = <dynamic>[]; |
|
|
|
// 删除状态筛选 |
|
if (!includeDeleted) { |
|
whereClauses.add('isDeleted = 0'); |
|
} |
|
|
|
// 时间范围筛选 |
|
if (startDate != null) { |
|
whereClauses.add('creationTime >= ?'); |
|
whereArgs.add(startDate.millisecondsSinceEpoch); |
|
} |
|
|
|
if (endDate != null) { |
|
whereClauses.add('creationTime <= ?'); |
|
whereArgs.add(endDate.millisecondsSinceEpoch); |
|
} |
|
|
|
// 同步状态筛选 |
|
if (syncStatus != null && syncStatus != '全部') { |
|
final statusValue = syncStatus == '已上传' |
|
? SyncStatus.synced.index |
|
: SyncStatus.notSynced.index; |
|
|
|
whereClauses.add('syncStatus = ?'); |
|
whereArgs.add(statusValue); |
|
} |
|
|
|
// 绑定状态筛选 |
|
if (bindStatus != null && bindStatus != '全部') { |
|
if (bindStatus == '已绑定') { |
|
whereClauses.add('bindData IS NOT NULL AND bindData != ""'); |
|
} else { |
|
whereClauses.add('(bindData IS NULL OR bindData = "")'); |
|
} |
|
} |
|
|
|
final results = await _database.query( |
|
_tableName, |
|
where: whereClauses.isNotEmpty ? whereClauses.join(' AND ') : null, |
|
whereArgs: whereArgs.isEmpty ? null : whereArgs, |
|
orderBy: 'creationTime DESC', |
|
); |
|
|
|
return results.map((json) => Problem.fromMap(json)).toList(); |
|
} catch (e) { |
|
Get.log('获取问题列表失败:$e', isError: true); |
|
return []; |
|
} |
|
} |
|
|
|
@override |
|
void onClose() { |
|
_database.close(); |
|
Get.log('数据库连接已关闭'); |
|
super.onClose(); |
|
} |
|
}
|
|
|