144 lines
4.9 KiB
Dart
144 lines
4.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:miaoji_zhang/shared/services/session_store.dart';
|
|
import 'package:miaoji_zhang/shared/services/sync_service.dart';
|
|
import 'package:miaoji_zhang/shared/theme/app_theme.dart';
|
|
import 'package:miaoji_zhang/shared/widgets/app_controls.dart';
|
|
import 'package:miaoji_zhang/shared/widgets/app_icons.dart';
|
|
|
|
enum AiAccessState { guest, reauthenticate, cloudDisabled }
|
|
|
|
AiAccessState? currentAiAccessState() {
|
|
final session = SessionStore.instance;
|
|
if (session.isGuest) return AiAccessState.guest;
|
|
if (session.needsReauth) return AiAccessState.reauthenticate;
|
|
if (!session.cloudSyncEnabled) return AiAccessState.cloudDisabled;
|
|
return null;
|
|
}
|
|
|
|
class AiAccessGate extends StatefulWidget {
|
|
final AiAccessState state;
|
|
final Future<void> Function()? onAction;
|
|
|
|
const AiAccessGate({super.key, required this.state, this.onAction});
|
|
|
|
@override
|
|
State<AiAccessGate> createState() => _AiAccessGateState();
|
|
}
|
|
|
|
class _AiAccessGateState extends State<AiAccessGate> {
|
|
bool _busy = false;
|
|
|
|
String get _title => switch (widget.state) {
|
|
AiAccessState.guest => '登录后使用 AI 助手',
|
|
AiAccessState.reauthenticate => '登录状态已过期',
|
|
AiAccessState.cloudDisabled => 'AI 功能需要云连接',
|
|
};
|
|
|
|
String get _message => switch (widget.state) {
|
|
AiAccessState.guest => '游客账单会继续安全保存在本机。登录后即可使用 AI 聊天、语音解析和图片识别。',
|
|
AiAccessState.reauthenticate => '本地记账不受影响。重新登录后可以继续使用 AI 和云同步。',
|
|
AiAccessState.cloudDisabled => '当前账号仅使用本地数据。开启云同步后才能发送 AI 消息。',
|
|
};
|
|
|
|
String get _actionLabel => switch (widget.state) {
|
|
AiAccessState.guest => '登录后使用',
|
|
AiAccessState.reauthenticate => '重新登录',
|
|
AiAccessState.cloudDisabled => '开启云同步',
|
|
};
|
|
|
|
Future<void> _act() async {
|
|
if (_busy) return;
|
|
if (widget.onAction != null) {
|
|
await widget.onAction!();
|
|
return;
|
|
}
|
|
if (widget.state != AiAccessState.cloudDisabled) {
|
|
if (mounted) {
|
|
context.go(
|
|
Uri(path: '/login', queryParameters: {'notice': _title}).toString(),
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
setState(() => _busy = true);
|
|
try {
|
|
await SessionStore.instance.setCloudSyncEnabled(true);
|
|
await SyncService.instance.run();
|
|
} finally {
|
|
if (mounted) setState(() => _busy = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Center(
|
|
child: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(28),
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 420),
|
|
child: Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(24, 28, 24, 24),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Container(
|
|
width: 62,
|
|
height: 62,
|
|
decoration: BoxDecoration(
|
|
color: context.jz.aiBackground,
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Center(
|
|
child: AppIcons.icon(
|
|
AppIcons.sparkle,
|
|
size: 29,
|
|
color: AppTheme.ai,
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 18),
|
|
Text(
|
|
_title,
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w800),
|
|
),
|
|
SizedBox(height: 9),
|
|
Text(
|
|
_message,
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
color: context.jz.text2,
|
|
fontSize: 12.5,
|
|
height: 1.6,
|
|
),
|
|
),
|
|
SizedBox(height: 22),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: JzActionButton(
|
|
label: _actionLabel,
|
|
loading: _busy,
|
|
onPressed: _busy ? null : _act,
|
|
),
|
|
),
|
|
if (widget.state == AiAccessState.guest) ...[
|
|
SizedBox(height: 12),
|
|
Text(
|
|
'无需登录也可以继续手动记账、管理预算和查看统计',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(fontSize: 10.5, color: context.jz.text3),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|