11
This commit is contained in:
1 parent
58a8a1ffde
commit
fdec7bed06
16 files changed
+637
-118
No files matched your search
@@ -135,6 +135,56 @@ abstract class FaceDao {
|
||||
''')
|
||||
Future<List<FaceEntity>> getAll();
|
||||
|
||||
/// 查询同步比对所需的轻量档案,faceModel 以哨兵占位避免全表特征反序列化。
|
||||
///
|
||||
/// 占位规则:特征非空返回 `[1]`(非空列表),特征为空或 NULL 返回 `[]`。
|
||||
/// 返回的实体仅用于内存比对,禁止直接回写数据库;需要完整行时按 sampleId
|
||||
/// 单条回读 [findBySampleId]。
|
||||
@Query('''
|
||||
SELECT id, userId, sampleId, userName, deptId, deptName, imagePath, path,
|
||||
CASE WHEN faceModel IS NULL OR faceModel = '' THEN '[]' ELSE '[1]' END AS faceModel,
|
||||
createTime, updateTime, qualityScore, qualityStatus, qualityCheckedAt,
|
||||
qualityErrorCode, qualityReportedAt
|
||||
FROM face ORDER BY sampleId ASC
|
||||
''')
|
||||
Future<List<FaceEntity>> getSyncProfiles();
|
||||
|
||||
/// 只更新服务端元数据字段,不触碰 faceModel 大字段和质量检测结果。
|
||||
///
|
||||
/// Floor 的 @Query 生成器只产出位置参数,参数顺序固定为:
|
||||
/// sampleId、userId、userName、deptId、deptName、imagePath、updateTime。
|
||||
/// 可空字段以空串传入并由 NULLIF 归一为 NULL;[updateTime] 为空串时保留本地
|
||||
/// 旧值,与快照合并时"服务端版本缺失则回退本地"一致。
|
||||
@Query('''
|
||||
UPDATE face
|
||||
SET userId = :userId,
|
||||
userName = :userName,
|
||||
deptId = NULLIF(:deptId, ''),
|
||||
deptName = NULLIF(:deptName, ''),
|
||||
imagePath = :imagePath,
|
||||
updateTime = COALESCE(NULLIF(:updateTime, ''), updateTime)
|
||||
WHERE sampleId = :sampleId
|
||||
''')
|
||||
Future<void> editMetadataBySampleId(
|
||||
String sampleId,
|
||||
String userId,
|
||||
String userName,
|
||||
String deptId,
|
||||
String deptName,
|
||||
String imagePath,
|
||||
String updateTime,
|
||||
);
|
||||
|
||||
/// 批量标记质量结果已被服务端确认,未确认样本保持旧标记供下次补报。
|
||||
@Query('''
|
||||
UPDATE face SET qualityReportedAt = :reportedAt
|
||||
WHERE sampleId IN (:sampleIds)
|
||||
''')
|
||||
Future<void> markQualityReported(
|
||||
List<String> sampleIds,
|
||||
DateTime reportedAt,
|
||||
);
|
||||
|
||||
@Query('''
|
||||
SELECT DISTINCT a.deptId FROM face a WHERE a.deptId IS NOT NULL
|
||||
''')
|
||||
|
||||
@@ -44,7 +44,10 @@ const typeConverters = <Type>[
|
||||
BoolConverter,
|
||||
];
|
||||
|
||||
@Database(version: 10, entities: entities)
|
||||
// 版本必须与原生 DatabaseHelper.DATABASE_VERSION 同步修改
|
||||
// (android/.../facediscern/database/DatabaseHelper.java)。
|
||||
// 11-13 区间曾被原生历史版本以 13 提前盖章 user_version 占用,Flutter 侧从 10 直接跳到 14。
|
||||
@Database(version: 14, entities: entities)
|
||||
@TypeConverters(typeConverters)
|
||||
abstract class AppDatabase extends FloorDatabase {
|
||||
BroadcastDao get getBroadcastDao;
|
||||
|
||||
@@ -112,7 +112,7 @@ class _$AppDatabase extends AppDatabase {
|
||||
Callback? callback,
|
||||
]) async {
|
||||
final databaseOptions = sqflite.OpenDatabaseOptions(
|
||||
version: 10,
|
||||
version: 14,
|
||||
onConfigure: (database) async {
|
||||
await database.execute('PRAGMA foreign_keys = ON');
|
||||
await callback?.onConfigure?.call(database);
|
||||
@@ -150,7 +150,7 @@ class _$AppDatabase extends AppDatabase {
|
||||
await database.execute(
|
||||
'CREATE TABLE IF NOT EXISTS `user_record` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `userId` TEXT NOT NULL, `nickname` TEXT NOT NULL, `mobile` TEXT, `avatar` TEXT, `walletCardNumber` TEXT, `walletId` TEXT, `walletTypeId` TEXT, `walletBalance` INTEGER, `canteenId` TEXT, `discountsList` TEXT, `discountsUpdateTime` TEXT, `createTime` TEXT, `updateTime` TEXT)');
|
||||
await database.execute(
|
||||
'CREATE TABLE IF NOT EXISTS `face` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `userId` TEXT NOT NULL, `sampleId` TEXT NOT NULL, `userName` TEXT NOT NULL, `deptId` TEXT, `deptName` TEXT, `imagePath` TEXT NOT NULL, `path` TEXT, `faceModel` TEXT, `createTime` TEXT, `updateTime` TEXT, `qualityScore` REAL, `qualityStatus` TEXT NOT NULL, `qualityCheckedAt` TEXT, `qualityErrorCode` INTEGER)');
|
||||
'CREATE TABLE IF NOT EXISTS `face` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `userId` TEXT NOT NULL, `sampleId` TEXT NOT NULL, `userName` TEXT NOT NULL, `deptId` TEXT, `deptName` TEXT, `imagePath` TEXT NOT NULL, `path` TEXT, `faceModel` TEXT, `createTime` TEXT, `updateTime` TEXT, `qualityScore` REAL, `qualityStatus` TEXT NOT NULL, `qualityCheckedAt` TEXT, `qualityErrorCode` INTEGER, `qualityReportedAt` TEXT)');
|
||||
await database.execute(
|
||||
'CREATE TABLE IF NOT EXISTS `setting` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `userJson` TEXT NOT NULL, `sysJson` TEXT NOT NULL, `canteenExtraPriceConfigJson` TEXT)');
|
||||
await database.execute(
|
||||
@@ -1885,7 +1885,9 @@ class _$FaceDao extends FaceDao {
|
||||
'qualityStatus': item.qualityStatus,
|
||||
'qualityCheckedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityCheckedAt),
|
||||
'qualityErrorCode': item.qualityErrorCode
|
||||
'qualityErrorCode': item.qualityErrorCode,
|
||||
'qualityReportedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityReportedAt)
|
||||
}),
|
||||
_faceEntityUpdateAdapter = UpdateAdapter(
|
||||
database,
|
||||
@@ -1907,7 +1909,9 @@ class _$FaceDao extends FaceDao {
|
||||
'qualityStatus': item.qualityStatus,
|
||||
'qualityCheckedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityCheckedAt),
|
||||
'qualityErrorCode': item.qualityErrorCode
|
||||
'qualityErrorCode': item.qualityErrorCode,
|
||||
'qualityReportedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityReportedAt)
|
||||
}),
|
||||
_faceEntityDeletionAdapter = DeletionAdapter(
|
||||
database,
|
||||
@@ -1929,7 +1933,9 @@ class _$FaceDao extends FaceDao {
|
||||
'qualityStatus': item.qualityStatus,
|
||||
'qualityCheckedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityCheckedAt),
|
||||
'qualityErrorCode': item.qualityErrorCode
|
||||
'qualityErrorCode': item.qualityErrorCode,
|
||||
'qualityReportedAt':
|
||||
_dateTimeEmptyConverter.encode(item.qualityReportedAt)
|
||||
});
|
||||
|
||||
final sqflite.DatabaseExecutor database;
|
||||
@@ -1995,7 +2001,7 @@ class _$FaceDao extends FaceDao {
|
||||
) async {
|
||||
return _queryAdapter.queryList(
|
||||
'SELECT * FROM face WHERE qualityStatus = \'detected\' AND qualityScore IS NOT NULL AND qualityScore < ?2 AND (?1 = \'-1\' OR userName LIKE \'%\' || ?1 || \'%\') ORDER BY id ASC LIMIT ?3 OFFSET ?4',
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?, qualityReportedAt: _dateTimeEmptyConverter.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [userName, threshold, pageSize, offset]);
|
||||
}
|
||||
|
||||
@@ -2003,7 +2009,7 @@ class _$FaceDao extends FaceDao {
|
||||
Future<List<FaceEntity>> findAllLowQuality(double threshold) async {
|
||||
return _queryAdapter.queryList(
|
||||
'SELECT * FROM face WHERE qualityStatus = \'detected\' AND qualityScore IS NOT NULL AND qualityScore < ?1 ORDER BY id ASC',
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?, qualityReportedAt: _dateTimeEmptyConverter.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [threshold]);
|
||||
}
|
||||
|
||||
@@ -2043,7 +2049,9 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?));
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2067,7 +2075,9 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [id]);
|
||||
}
|
||||
|
||||
@@ -2092,7 +2102,9 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [sampleId]);
|
||||
}
|
||||
|
||||
@@ -2117,7 +2129,9 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [userId]);
|
||||
}
|
||||
|
||||
@@ -2129,7 +2143,7 @@ class _$FaceDao extends FaceDao {
|
||||
) async {
|
||||
return _queryAdapter.queryList(
|
||||
'SELECT * FROM face WHERE (?1 = \'-1\' OR userName LIKE \'%\' || ?1 || \'%\') LIMIT ?2 OFFSET ?3',
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?),
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(id: row['id'] as int?, userId: row['userId'] as String, sampleId: row['sampleId'] as String, userName: row['userName'] as String, deptId: row['deptId'] as String?, deptName: row['deptName'] as String?, imagePath: row['imagePath'] as String, path: row['path'] as String?, faceModel: _listIntConverter.decode(row['faceModel'] as String), createTime: _dateTimeEmptyConverter.decode(row['createTime'] as String?), updateTime: _dateTimeEmptyConverter.decode(row['updateTime'] as String?), qualityScore: row['qualityScore'] as double?, qualityStatus: row['qualityStatus'] as String, qualityCheckedAt: _dateTimeEmptyConverter.decode(row['qualityCheckedAt'] as String?), qualityErrorCode: row['qualityErrorCode'] as int?, qualityReportedAt: _dateTimeEmptyConverter.decode(row['qualityReportedAt'] as String?)),
|
||||
arguments: [userName, pageSize, offset]);
|
||||
}
|
||||
|
||||
@@ -2154,7 +2168,75 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?));
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<FaceEntity>> getSyncProfiles() async {
|
||||
return _queryAdapter.queryList(
|
||||
'SELECT id, userId, sampleId, userName, deptId, deptName, imagePath, path, CASE WHEN faceModel IS NULL OR faceModel = \'\' THEN \'[]\' ELSE \'[1]\' END AS faceModel, createTime, updateTime, qualityScore, qualityStatus, qualityCheckedAt, qualityErrorCode, qualityReportedAt FROM face ORDER BY sampleId ASC',
|
||||
mapper: (Map<String, Object?> row) => FaceEntity(
|
||||
id: row['id'] as int?,
|
||||
userId: row['userId'] as String,
|
||||
sampleId: row['sampleId'] as String,
|
||||
userName: row['userName'] as String,
|
||||
deptId: row['deptId'] as String?,
|
||||
deptName: row['deptName'] as String?,
|
||||
imagePath: row['imagePath'] as String,
|
||||
path: row['path'] as String?,
|
||||
faceModel: _listIntConverter.decode(row['faceModel'] as String),
|
||||
createTime:
|
||||
_dateTimeEmptyConverter.decode(row['createTime'] as String?),
|
||||
updateTime:
|
||||
_dateTimeEmptyConverter.decode(row['updateTime'] as String?),
|
||||
qualityScore: row['qualityScore'] as double?,
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> editMetadataBySampleId(
|
||||
String sampleId,
|
||||
String userId,
|
||||
String userName,
|
||||
String deptId,
|
||||
String deptName,
|
||||
String imagePath,
|
||||
String updateTime,
|
||||
) async {
|
||||
await _queryAdapter.queryNoReturn(
|
||||
'UPDATE face SET userId = ?2, userName = ?3, deptId = NULLIF(?4, \'\'), deptName = NULLIF(?5, \'\'), imagePath = ?6, updateTime = COALESCE(NULLIF(?7, \'\'), updateTime) WHERE sampleId = ?1',
|
||||
arguments: [
|
||||
sampleId,
|
||||
userId,
|
||||
userName,
|
||||
deptId,
|
||||
deptName,
|
||||
imagePath,
|
||||
updateTime
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> markQualityReported(
|
||||
List<String> sampleIds,
|
||||
DateTime reportedAt,
|
||||
) async {
|
||||
const offset = 2;
|
||||
final _sqliteVariablesForSampleIds =
|
||||
Iterable<String>.generate(sampleIds.length, (i) => '?${i + offset}')
|
||||
.join(',');
|
||||
await _queryAdapter.queryNoReturn(
|
||||
'UPDATE face SET qualityReportedAt = ?1 WHERE sampleId IN (' +
|
||||
_sqliteVariablesForSampleIds +
|
||||
')',
|
||||
arguments: [_dateTimeConverter.encode(reportedAt), ...sampleIds]);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -2186,7 +2268,9 @@ class _$FaceDao extends FaceDao {
|
||||
qualityStatus: row['qualityStatus'] as String,
|
||||
qualityCheckedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityCheckedAt'] as String?),
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?));
|
||||
qualityErrorCode: row['qualityErrorCode'] as int?,
|
||||
qualityReportedAt: _dateTimeEmptyConverter
|
||||
.decode(row['qualityReportedAt'] as String?)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:floor/floor.dart';
|
||||
import 'package:sqflite/sqflite.dart' as sqflite;
|
||||
|
||||
abstract class DatabaseMigration {
|
||||
/// 从版本1到版本2的迁移:添加productNamePy字段
|
||||
@@ -423,6 +424,37 @@ abstract class DatabaseMigration {
|
||||
);
|
||||
});
|
||||
|
||||
/// 从版本10到版本14的迁移(跨过 11-13):face 表补充质量上报确认列。
|
||||
///
|
||||
/// 11-13 区间曾被原生 DatabaseHelper 以 SQLiteOpenHelper 版本 13 提前盖章
|
||||
/// user_version,Floor 对更高版本只会静默跳过升级,因此 Flutter 侧直接跳到 14;
|
||||
/// 被盖章 13 的设备由 [migration13To14] 修复。
|
||||
static Migration migration10To14 = Migration(10, 14, (database) async {
|
||||
await _upgradeFaceQualityReport(database);
|
||||
});
|
||||
|
||||
/// 从版本13到版本14的迁移:修复被原生提前盖章 13 但 schema 仍停留在版本10的设备。
|
||||
static Migration migration13To14 = Migration(13, 14, (database) async {
|
||||
await _upgradeFaceQualityReport(database);
|
||||
});
|
||||
|
||||
/// 补齐质量上报确认列并规范化 NULL 特征;全部操作幂等,可被多条迁移重复执行。
|
||||
static Future<void> _upgradeFaceQualityReport(
|
||||
sqflite.Database database,
|
||||
) async {
|
||||
final columns = await database.rawQuery('PRAGMA table_info(face)');
|
||||
final names = columns.map((column) => column['name']).toSet();
|
||||
if (!names.contains('qualityReportedAt')) {
|
||||
await database.execute(
|
||||
'ALTER TABLE face ADD COLUMN qualityReportedAt TEXT',
|
||||
);
|
||||
}
|
||||
// 历史脏行可能存在 NULL 特征;Floor 读取 faceModel 使用非空强转,规范化为空串。
|
||||
await database.execute(
|
||||
"UPDATE face SET faceModel = '' WHERE faceModel IS NULL",
|
||||
);
|
||||
}
|
||||
|
||||
static List<Migration> getDatabaseMigrations() {
|
||||
return [
|
||||
migration1To2,
|
||||
@@ -434,6 +466,8 @@ abstract class DatabaseMigration {
|
||||
migration7To8,
|
||||
migration8To9,
|
||||
migration9To10,
|
||||
migration10To14,
|
||||
migration13To14,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,9 @@ class FaceEntity extends Equatable {
|
||||
/// 最近一次质量检测的虹软或插件错误码;成功时为空。
|
||||
int? qualityErrorCode;
|
||||
|
||||
/// 质量结果最近一次被服务端确认的时间;为空或早于检测时间时需要补报。
|
||||
DateTime? qualityReportedAt;
|
||||
|
||||
FaceEntity({
|
||||
this.id,
|
||||
required this.userId,
|
||||
@@ -69,6 +72,7 @@ class FaceEntity extends Equatable {
|
||||
this.qualityStatus = 'pending',
|
||||
this.qualityCheckedAt,
|
||||
this.qualityErrorCode,
|
||||
this.qualityReportedAt,
|
||||
});
|
||||
|
||||
factory FaceEntity.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -28,6 +28,9 @@ FaceEntity _$FaceEntityFromJson(Map<String, dynamic> json) => FaceEntity(
|
||||
? null
|
||||
: DateTime.parse(json['qualityCheckedAt'] as String),
|
||||
qualityErrorCode: (json['qualityErrorCode'] as num?)?.toInt(),
|
||||
qualityReportedAt: json['qualityReportedAt'] == null
|
||||
? null
|
||||
: DateTime.parse(json['qualityReportedAt'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$FaceEntityToJson(FaceEntity instance) =>
|
||||
@@ -47,4 +50,5 @@ Map<String, dynamic> _$FaceEntityToJson(FaceEntity instance) =>
|
||||
'qualityStatus': instance.qualityStatus,
|
||||
'qualityCheckedAt': instance.qualityCheckedAt?.toIso8601String(),
|
||||
'qualityErrorCode': instance.qualityErrorCode,
|
||||
'qualityReportedAt': instance.qualityReportedAt?.toIso8601String(),
|
||||
};
|
||||
Reference in new issue
Block a user