feat:购买失败修改
fix:购买副屏展示用户余额
This commit is contained in:
1 parent
3c11805958
commit
c6f9ffb998
20 files changed
+1357
-289
No files matched your search
@@ -276,19 +276,6 @@ abstract class SyncFaceTool {
|
||||
return byRowId.values.toList();
|
||||
}
|
||||
|
||||
/// 供调试清理入口读取完整部门树,空部门也属于设备同步范围。
|
||||
static Future<Set<String>> getDepartmentScopeDeptIds() async {
|
||||
if (!AppNetworkTool.isAutoNetwork()) {
|
||||
throw const FaceSyncSnapshotException('网络不可用,无法获取部门范围');
|
||||
}
|
||||
final setting = await AppSettingTool.getSysSetting();
|
||||
final merchantDeptId = setting.merchantDeptId?.trim();
|
||||
if (merchantDeptId == null || merchantDeptId.isEmpty) {
|
||||
throw const FaceSyncSnapshotException('终端尚未绑定商户部门');
|
||||
}
|
||||
return UserApi.getFaceDepartmentScope(merchantDeptId);
|
||||
}
|
||||
|
||||
/// 拉取 V3 固定上界游标快照并校验页面连续性、记录唯一性和字段有效性。
|
||||
///
|
||||
/// [onProgress] 在每页合并后上报当前已获取条数;分页总数未知,回调总数为空。
|
||||
@@ -848,23 +835,6 @@ abstract class SyncFaceTool {
|
||||
_deleteLocalFace(face, Get.find<AppControl>().dataBase.getFaceDao),
|
||||
);
|
||||
|
||||
/// 按批量管线清理一组本地人脸(不触碰服务端数据),返回成功删除数。
|
||||
///
|
||||
/// 供人脸管理页的调试清理入口使用;同步孤儿删除走同一条 [_deleteFacesInBulk] 管线。
|
||||
static Future<int> deleteLocalFaces(
|
||||
List<FaceEntity> faces, {
|
||||
void Function(int processed, int? total)? onProgress,
|
||||
}) async {
|
||||
final result = await AppFaceTool.runLibraryMutation(
|
||||
() => _deleteFacesInBulk(
|
||||
faces,
|
||||
Get.find<AppControl>().dataBase.getFaceDao,
|
||||
onProgress: onProgress,
|
||||
),
|
||||
);
|
||||
return result.deleted;
|
||||
}
|
||||
|
||||
/// 批量删除本地人脸的统一管线:并行改名 → 原生批量移除 → SQL 批量删除 → 并行清理文件。
|
||||
///
|
||||
/// 逐条删除实测约 664ms/条(每条包含独立的原生通道往返、SQLite 提交和多次
|
||||
@@ -1366,12 +1336,6 @@ abstract class SyncFaceTool {
|
||||
/// 只处理目录顶层文件:修改时间超过一小时、不属于任何本地记录且扩展名为
|
||||
/// 图片的文件视为历史孤儿删除;`.pending-delete` 残留同样清理。跳过全部
|
||||
/// 子目录(同步临时目录与原生头像目录都不在顶层规则覆盖范围内)。
|
||||
static Future<int> sweepFaceStorage() async {
|
||||
final storagePath = await AppFileTool.getFacePath();
|
||||
if (storagePath == null || storagePath.isEmpty) return 0;
|
||||
return _sweepFaceDirectory(storagePath);
|
||||
}
|
||||
|
||||
static Future<int> _sweepFaceDirectory(String storagePath) async {
|
||||
try {
|
||||
final directory = Directory(storagePath);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:pj_supermarket_cloud/common/index.dart';
|
||||
import 'package:sqflite/sqflite.dart' as sqflite;
|
||||
|
||||
enum _UserCacheWrite { added, updated, unchanged }
|
||||
|
||||
/// 一次离线人员同步的不可变结果汇总。
|
||||
class OfflineUserSyncSummary {
|
||||
@@ -46,35 +49,23 @@ abstract class SyncUserTool {
|
||||
/// 存储用户
|
||||
static Future<void> storageUser({required ServiceUser user}) async {
|
||||
try {
|
||||
final app = Get.find<AppControl>();
|
||||
final userDao = app.dataBase.getUserDao;
|
||||
final detail = await userDao.findByUserId(user.userId!);
|
||||
if (detail == null) {
|
||||
final obj = _parseStorageUser(user: user, createDate: true);
|
||||
await userDao.save(obj);
|
||||
logger.i("|$_tag|,存储用户,新增成功|${obj.toJson()}|");
|
||||
} else {
|
||||
final obj = _parseStorageUser(user: user, updateDate: true);
|
||||
obj.id = detail.id;
|
||||
if (obj == detail) return;
|
||||
// 规则查询可能与人员刷新并发,不能用旧快照整行回写覆盖新规则。
|
||||
await app.dataBase.database.update(
|
||||
'user_record',
|
||||
{
|
||||
'nickname': obj.nickname,
|
||||
'mobile': obj.mobile,
|
||||
'avatar': obj.avatar,
|
||||
'walletCardNumber': obj.walletCardNumber,
|
||||
'walletId': obj.walletId,
|
||||
'walletTypeId': obj.walletTypeId,
|
||||
'walletBalance': obj.walletBalance,
|
||||
'canteenId': obj.canteenId,
|
||||
'updateTime': DateTimeConverter().encode(obj.updateTime!),
|
||||
},
|
||||
where: 'id = ?',
|
||||
whereArgs: [detail.id],
|
||||
);
|
||||
logger.i("|$_tag|,存储用户,修改成功|${obj.toJson()}|");
|
||||
final userId = user.userId?.trim();
|
||||
if (userId == null || userId.isEmpty) {
|
||||
throw ArgumentError('不能缓存缺少用户编号的人员');
|
||||
}
|
||||
final result = await _storeUserSnapshot(UserEntity(
|
||||
userId: userId,
|
||||
nickname: user.username ?? '未知',
|
||||
mobile: user.userMobile,
|
||||
avatar: user.userAvatar,
|
||||
walletCardNumber: user.walletCardNumber,
|
||||
walletId: user.walletId,
|
||||
walletTypeId: user.walletTypeId,
|
||||
walletBalance: user.walletBalance,
|
||||
canteenId: user.canteenId,
|
||||
));
|
||||
if (result != _UserCacheWrite.unchanged) {
|
||||
logger.i('|$_tag|存储用户成功|userId:$userId|${result.name}|');
|
||||
}
|
||||
} catch (e, stack) {
|
||||
logger.e("|$_tag|,存储用户失败意外的错误error:|$e|stack:|$stack|");
|
||||
@@ -99,29 +90,67 @@ abstract class SyncUserTool {
|
||||
);
|
||||
}
|
||||
|
||||
static UserEntity _parseStorageUser({
|
||||
required ServiceUser user,
|
||||
bool createDate = false,
|
||||
bool updateDate = false,
|
||||
/// 所有人员缓存入口共用同一事务,首次缓存的查询与插入不可交错。
|
||||
/// 数据库唯一索引兜底限制一人一条;更新仅触碰当前快照拥有的字段,
|
||||
/// 不回写优惠列,也不让脱敏同步覆盖消费时取得的完整身份信息。
|
||||
static Future<_UserCacheWrite> _storeUserSnapshot(
|
||||
UserEntity user, {
|
||||
bool preserveIdentity = false,
|
||||
}) {
|
||||
final userEntity = UserEntity(
|
||||
userId: user.userId ?? "-1",
|
||||
nickname: user.username ?? "未知",
|
||||
mobile: user.userMobile,
|
||||
avatar: user.userAvatar,
|
||||
walletCardNumber: user.walletCardNumber,
|
||||
walletId: user.walletId,
|
||||
walletTypeId: user.walletTypeId,
|
||||
walletBalance: user.walletBalance,
|
||||
canteenId: user.canteenId,
|
||||
);
|
||||
if (createDate) {
|
||||
userEntity.createTime = DateTime.now();
|
||||
}
|
||||
if (updateDate) {
|
||||
userEntity.updateTime = DateTime.now();
|
||||
}
|
||||
return userEntity;
|
||||
final database =
|
||||
Get.find<AppControl>().dataBase.database as sqflite.Database;
|
||||
return database.transaction((transaction) async {
|
||||
final rows = await transaction.query(
|
||||
'user_record',
|
||||
where: 'userId = ?',
|
||||
whereArgs: [user.userId],
|
||||
);
|
||||
if (rows.length > 1) {
|
||||
throw StateError('人员缓存存在重复,请重启应用完成数据库修复');
|
||||
}
|
||||
final now = DateTimeConverter().encode(DateTime.now());
|
||||
final wallet = <String, Object?>{
|
||||
'walletCardNumber': user.walletCardNumber,
|
||||
'walletId': user.walletId,
|
||||
'walletTypeId': user.walletTypeId,
|
||||
'walletBalance': user.walletBalance,
|
||||
'canteenId': user.canteenId,
|
||||
};
|
||||
final identity = <String, Object?>{
|
||||
'nickname': user.nickname,
|
||||
'mobile': user.mobile,
|
||||
'avatar': user.avatar,
|
||||
};
|
||||
if (rows.isEmpty) {
|
||||
await transaction.insert('user_record', {
|
||||
'userId': user.userId,
|
||||
...identity,
|
||||
...wallet,
|
||||
'createTime': now,
|
||||
'updateTime': now,
|
||||
});
|
||||
return _UserCacheWrite.added;
|
||||
}
|
||||
final existing = rows.single;
|
||||
final changes = <String, Object?>{
|
||||
if (!preserveIdentity) ...identity,
|
||||
...wallet,
|
||||
};
|
||||
if (preserveIdentity && user.canteenId == null) {
|
||||
changes.remove('canteenId');
|
||||
}
|
||||
if (changes.entries
|
||||
.every((entry) => existing[entry.key] == entry.value)) {
|
||||
return _UserCacheWrite.unchanged;
|
||||
}
|
||||
await transaction.update(
|
||||
'user_record',
|
||||
{...changes, 'updateTime': now},
|
||||
where: 'userId = ?',
|
||||
whereArgs: [user.userId],
|
||||
);
|
||||
return _UserCacheWrite.updated;
|
||||
});
|
||||
}
|
||||
|
||||
/// 按设备绑定部门树(或全租户)同步脱敏后的离线人员到本机缓存。
|
||||
@@ -130,12 +159,11 @@ abstract class SyncUserTool {
|
||||
/// 服务端返回的记录姓名已脱敏且不含手机号头像;本地已有的完整消费缓存
|
||||
/// (真实姓名、手机号)优先保留,同步只补齐缺失人员和刷新钱包快照字段。
|
||||
/// 分页期间快照上界变化会立即中断,已写入的本地数据保持有效。
|
||||
static Future<OfflineUserSyncSummary> syncOfflineUsers({bool isAll = false}) async {
|
||||
static Future<OfflineUserSyncSummary> syncOfflineUsers(
|
||||
{bool isAll = false}) async {
|
||||
if (!AppNetworkTool.isAutoNetwork()) {
|
||||
throw StateError('网络不可用,无法同步离线人员');
|
||||
}
|
||||
final app = Get.find<AppControl>();
|
||||
final userDao = app.dataBase.getUserDao;
|
||||
var afterId = '0';
|
||||
String? snapshotMaxId;
|
||||
var added = 0;
|
||||
@@ -153,48 +181,25 @@ abstract class SyncUserTool {
|
||||
throw StateError('离线人员快照上界在分页期间发生变化');
|
||||
}
|
||||
for (final record in snapshot.records) {
|
||||
final existing = await userDao.findByUserId(record.userId);
|
||||
if (existing == null) {
|
||||
final now = DateTime.now();
|
||||
await userDao.save(
|
||||
UserEntity(
|
||||
userId: record.userId,
|
||||
nickname: record.username,
|
||||
walletCardNumber: record.walletCardNumber,
|
||||
walletId: record.walletId,
|
||||
walletTypeId: record.walletTypeId,
|
||||
walletBalance: record.walletBalance,
|
||||
canteenId: record.canteenId?.toString(),
|
||||
createTime: now,
|
||||
updateTime: now,
|
||||
),
|
||||
);
|
||||
added++;
|
||||
continue;
|
||||
}
|
||||
// 姓名、手机号、头像和优惠保留本地消费缓存的真实数据,仅刷新钱包快照。
|
||||
final merged = UserEntity(
|
||||
id: existing.id,
|
||||
userId: existing.userId,
|
||||
nickname: existing.nickname,
|
||||
mobile: existing.mobile,
|
||||
avatar: existing.avatar,
|
||||
walletCardNumber: record.walletCardNumber,
|
||||
walletId: record.walletId,
|
||||
walletTypeId: record.walletTypeId,
|
||||
walletBalance: record.walletBalance,
|
||||
canteenId: record.canteenId?.toString() ?? existing.canteenId,
|
||||
discountsList: existing.discountsList,
|
||||
discountsUpdateTime: existing.discountsUpdateTime,
|
||||
createTime: existing.createTime,
|
||||
updateTime: DateTime.now(),
|
||||
final result = await _storeUserSnapshot(
|
||||
UserEntity(
|
||||
userId: record.userId,
|
||||
nickname: record.username,
|
||||
walletCardNumber: record.walletCardNumber,
|
||||
walletId: record.walletId,
|
||||
walletTypeId: record.walletTypeId,
|
||||
walletBalance: record.walletBalance,
|
||||
canteenId: record.canteenId?.toString(),
|
||||
),
|
||||
preserveIdentity: true,
|
||||
);
|
||||
// UserEntity 等值比较不含时间戳;完全一致时避免无谓写库。
|
||||
if (merged == existing) {
|
||||
unchanged++;
|
||||
} else {
|
||||
await userDao.edit(merged);
|
||||
updated++;
|
||||
switch (result) {
|
||||
case _UserCacheWrite.added:
|
||||
added++;
|
||||
case _UserCacheWrite.updated:
|
||||
updated++;
|
||||
case _UserCacheWrite.unchanged:
|
||||
unchanged++;
|
||||
}
|
||||
}
|
||||
if (!snapshot.hasMore) break;
|
||||
|
||||
Reference in new issue
Block a user