fix: improve transfer recognition and local data safety
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:miaoji_zhang/shared/api/api_client.dart';
|
||||
import 'package:miaoji_zhang/shared/services/guest_merge_service.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
import 'package:miaoji_zhang/shared/widgets/app_controls.dart';
|
||||
|
||||
Future<void> offerLocalDataRecovery(
|
||||
BuildContext context, {
|
||||
Map<String, dynamic>? guestSnapshot,
|
||||
}) async {
|
||||
final session = SessionStore.instance;
|
||||
Map<String, dynamic>? accountSnapshot;
|
||||
try {
|
||||
accountSnapshot = await session.pendingAccountSnapshot();
|
||||
} catch (error) {
|
||||
if (context.mounted) {
|
||||
_showMessage(context, '本机历史数据读取失败:${apiErrorMessage(error)}');
|
||||
}
|
||||
}
|
||||
if (accountSnapshot != null && context.mounted) {
|
||||
final shouldMerge = await showJzConfirmSheet(
|
||||
context,
|
||||
title: '发现本机历史数据',
|
||||
message:
|
||||
'检测到旧账号或旧后端留下的本地账单。为防止不同服务器的数据互相覆盖,这些数据已单独保留。是否导入当前账号的“本机历史数据”账本?',
|
||||
confirmLabel: '导入数据',
|
||||
);
|
||||
if (shouldMerge) {
|
||||
try {
|
||||
final result = await GuestMergeService.merge(
|
||||
accountSnapshot,
|
||||
ledgerName: '本机历史数据',
|
||||
);
|
||||
await session.clearPendingAccountSnapshot();
|
||||
if (context.mounted) {
|
||||
_showMessage(context, '已导入 ${result.transactionCount} 笔本机历史账单');
|
||||
}
|
||||
} catch (error) {
|
||||
if (context.mounted) {
|
||||
_showMessage(context, '本机历史数据暂未导入:${apiErrorMessage(error)}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (guestSnapshot?['hasData'] == true && context.mounted) {
|
||||
final shouldMerge = await showJzConfirmSheet(
|
||||
context,
|
||||
title: '发现游客数据',
|
||||
message: '是否将本机游客账单、分类和预算导入当前账号?数据会放入独立的“游客数据”账本,原游客数据仍保留在本机。',
|
||||
confirmLabel: '导入数据',
|
||||
);
|
||||
if (shouldMerge) {
|
||||
try {
|
||||
final result = await GuestMergeService.merge(guestSnapshot!);
|
||||
if (context.mounted) {
|
||||
_showMessage(context, '已导入 ${result.transactionCount} 笔游客账单');
|
||||
}
|
||||
} catch (error) {
|
||||
if (context.mounted) {
|
||||
_showMessage(context, '游客数据暂未导入:${apiErrorMessage(error)}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _showMessage(BuildContext context, String message) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
|
||||
}
|
||||
@@ -3,8 +3,8 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:miaoji_zhang/shared/api/api_client.dart';
|
||||
import 'package:miaoji_zhang/shared/api/auth_api.dart';
|
||||
import 'package:miaoji_zhang/shared/api/config_api.dart';
|
||||
import 'package:miaoji_zhang/features/auth/local_data_recovery.dart';
|
||||
import 'package:miaoji_zhang/shared/services/current_ledger_store.dart';
|
||||
import 'package:miaoji_zhang/shared/services/guest_merge_service.dart';
|
||||
import 'package:miaoji_zhang/shared/services/local_database.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
import 'package:miaoji_zhang/shared/services/push_service.dart';
|
||||
@@ -59,36 +59,14 @@ class _LoginPageState extends State<LoginPage> {
|
||||
: null;
|
||||
setState(() => _loading = true);
|
||||
try {
|
||||
final closureCancelled = await AuthApi.login(
|
||||
_user.text.trim(),
|
||||
_pass.text,
|
||||
);
|
||||
final profile = await AuthApi.me();
|
||||
final result = await AuthApi.login(_user.text.trim(), _pass.text);
|
||||
final profile = result.profile;
|
||||
await PushService.instance.refresh();
|
||||
await CurrentLedgerStore.instance.ensureLoaded(force: true);
|
||||
if (!mounted) return;
|
||||
if (guestSnapshot?['hasData'] == true) {
|
||||
final shouldMerge = await showJzConfirmSheet(
|
||||
context,
|
||||
title: '发现游客数据',
|
||||
message: '是否将本机游客账单、分类和预算导入当前账号?数据会放入独立的“游客数据”账本,原游客数据仍保留在本机。',
|
||||
confirmLabel: '导入数据',
|
||||
);
|
||||
if (shouldMerge) {
|
||||
try {
|
||||
final result = await GuestMergeService.merge(guestSnapshot!);
|
||||
if (mounted) {
|
||||
_showMessage('已导入 ${result.transactionCount} 笔游客账单');
|
||||
}
|
||||
} catch (error) {
|
||||
if (mounted) {
|
||||
_showMessage('游客数据暂未导入:${apiErrorMessage(error)}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await offerLocalDataRecovery(context, guestSnapshot: guestSnapshot);
|
||||
if (!mounted) return;
|
||||
if (closureCancelled) _showMessage('已取消账号注销,欢迎回来');
|
||||
if (result.accountClosureCancelled) _showMessage('已取消账号注销,欢迎回来');
|
||||
final destination = !profile.onboardingDone
|
||||
? '/onboarding'
|
||||
: profile.appMode == 'ai'
|
||||
|
||||
@@ -2,6 +2,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:miaoji_zhang/shared/api/api_client.dart';
|
||||
import 'package:miaoji_zhang/shared/api/auth_api.dart';
|
||||
import 'package:miaoji_zhang/features/auth/local_data_recovery.dart';
|
||||
import 'package:miaoji_zhang/shared/services/current_ledger_store.dart';
|
||||
import 'package:miaoji_zhang/shared/services/local_database.dart';
|
||||
import 'package:miaoji_zhang/shared/services/push_service.dart';
|
||||
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
||||
import 'package:miaoji_zhang/shared/theme/app_theme.dart';
|
||||
|
||||
class RegisterPage extends StatefulWidget {
|
||||
@@ -40,9 +45,26 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||
}
|
||||
setState(() => _loading = true);
|
||||
try {
|
||||
await AuthApi.register(username, _pass.text, agreedToTerms: _agreed);
|
||||
final guestSnapshot = SessionStore.instance.isGuest
|
||||
? LocalDatabase.instance.guestSnapshot()
|
||||
: null;
|
||||
final profile = await AuthApi.register(
|
||||
username,
|
||||
_pass.text,
|
||||
agreedToTerms: _agreed,
|
||||
);
|
||||
await PushService.instance.refresh();
|
||||
await CurrentLedgerStore.instance.ensureLoaded(force: true);
|
||||
if (!mounted) return;
|
||||
context.go('/onboarding');
|
||||
await offerLocalDataRecovery(context, guestSnapshot: guestSnapshot);
|
||||
if (!mounted) return;
|
||||
context.go(
|
||||
!profile.onboardingDone
|
||||
? '/onboarding'
|
||||
: profile.appMode == 'ai'
|
||||
? '/ai-mode'
|
||||
: '/home',
|
||||
);
|
||||
} catch (error) {
|
||||
if (!mounted) return;
|
||||
_message(apiErrorMessage(error));
|
||||
|
||||
Reference in New Issue
Block a user