refactor: 移除 LiteLLM proxy 架构,后端直连 Provider API
- 移除 backend/scripts/build_litellm_proxy_config.py - 简化 LiteLLMService,移除 run_completion_with_cost 方法 - AgentScopeRunner 改为从 LlmFactory 获取 api_base 和 api_key - 部署配置移除 litellm/litellm-config-job 服务 - Flutter 新增 AuthBootScreen 引导页 - Android 添加通知权限 (POST_NOTIFICATIONS, RECEIVE_BOOT_COMPLETED, SCHEDULE_EXACT_ALARM) - 优化 LocalNotificationService 调度失败 fallback - 更新 manifest.json (version 3)
This commit is contained in:
@@ -76,16 +76,29 @@ class LocalNotificationService {
|
||||
),
|
||||
);
|
||||
|
||||
await _plugin.zonedSchedule(
|
||||
notificationId,
|
||||
event.title,
|
||||
_buildReminderBody(event, reminderMinutes),
|
||||
scheduledAt,
|
||||
details,
|
||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
);
|
||||
try {
|
||||
await _plugin.zonedSchedule(
|
||||
notificationId,
|
||||
event.title,
|
||||
_buildReminderBody(event, reminderMinutes),
|
||||
scheduledAt,
|
||||
details,
|
||||
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
);
|
||||
} catch (_) {
|
||||
await _plugin.zonedSchedule(
|
||||
notificationId,
|
||||
event.title,
|
||||
_buildReminderBody(event, reminderMinutes),
|
||||
scheduledAt,
|
||||
details,
|
||||
androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> cancelEventReminder(String eventId) async {
|
||||
|
||||
@@ -3,6 +3,7 @@ import '../../features/auth/presentation/bloc/auth_bloc.dart';
|
||||
import '../../features/auth/presentation/bloc/auth_state.dart';
|
||||
import 'go_router_refresh_stream.dart';
|
||||
import '../../features/auth/ui/screens/login_screen.dart';
|
||||
import '../../features/auth/ui/screens/auth_boot_screen.dart';
|
||||
import '../../features/auth/ui/screens/register_screen.dart';
|
||||
import '../../features/auth/ui/screens/register_verification_screen.dart';
|
||||
import '../../features/auth/ui/screens/reset_password_screen.dart';
|
||||
@@ -43,11 +44,14 @@ final _protectedRoutes = [
|
||||
|
||||
GoRouter createAppRouter(AuthBloc authBloc) {
|
||||
return GoRouter(
|
||||
initialLocation: '/',
|
||||
initialLocation: '/boot',
|
||||
refreshListenable: GoRouterRefreshStream(authBloc.stream),
|
||||
redirect: (context, state) {
|
||||
final authState = authBloc.state;
|
||||
final isAuthenticated = authState is AuthAuthenticated;
|
||||
final isAuthChecking =
|
||||
authState is AuthInitial || authState is AuthLoading;
|
||||
final isBootRoute = state.matchedLocation == '/boot';
|
||||
final isAuthRoute =
|
||||
state.matchedLocation == '/' ||
|
||||
state.matchedLocation.startsWith('/login') ||
|
||||
@@ -56,6 +60,12 @@ GoRouter createAppRouter(AuthBloc authBloc) {
|
||||
(route) => state.matchedLocation.startsWith(route),
|
||||
);
|
||||
|
||||
if (isAuthChecking && !isBootRoute) {
|
||||
return '/boot';
|
||||
}
|
||||
if (!isAuthChecking && isBootRoute) {
|
||||
return isAuthenticated ? '/home' : '/';
|
||||
}
|
||||
if (!isAuthenticated && isProtected) {
|
||||
return '/';
|
||||
}
|
||||
@@ -65,6 +75,10 @@ GoRouter createAppRouter(AuthBloc authBloc) {
|
||||
return null;
|
||||
},
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/boot',
|
||||
builder: (context, state) => const AuthBootScreen(),
|
||||
),
|
||||
GoRoute(path: '/', builder: (context, state) => const LoginScreen()),
|
||||
GoRoute(
|
||||
path: '/calendar/events/:id',
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../core/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/app_loading_indicator.dart';
|
||||
|
||||
class AuthBootScreen extends StatelessWidget {
|
||||
const AuthBootScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(
|
||||
backgroundColor: AppColors.authBackgroundTop,
|
||||
body: SafeArea(
|
||||
child: Center(
|
||||
child: AppLoadingIndicator(
|
||||
variant: AppLoadingVariant.surface,
|
||||
size: 28,
|
||||
strokeWidth: 2.5,
|
||||
color: AppColors.authPrimaryButton,
|
||||
trackColor: AppColors.authPrimaryButtonDisabled,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -638,7 +638,11 @@ class _CreateEventSheetState extends State<CreateEventSheet>
|
||||
try {
|
||||
final notificationService = sl<LocalNotificationService>();
|
||||
await notificationService.upsertEventReminder(saved);
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
if (mounted) {
|
||||
Toast.show(context, '提醒创建失败,请检查通知权限', type: ToastType.warning);
|
||||
}
|
||||
}
|
||||
|
||||
widget.onSaved?.call();
|
||||
if (mounted) {
|
||||
|
||||
Reference in New Issue
Block a user