feat: 长辈模式(大字大按钮 + 偏好按账号隔离)+ 语音输入(按住说话 + 实时转写 + 后端代理 DashScope ASR + 患者端专用)+ 健康仪表盘背景渐变

This commit is contained in:
MingNian
2026-07-21 10:53:16 +08:00
parent 0cb5b8e85a
commit 28f704c98e
25 changed files with 2214 additions and 131 deletions

View File

@@ -5,10 +5,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'core/app_router.dart';
import 'core/app_theme.dart';
import 'core/elder_mode_scope.dart';
import 'core/navigation_provider.dart';
import 'pages/splash_page.dart';
import 'providers/auth_provider.dart';
import 'providers/data_providers.dart';
import 'providers/elder_mode_provider.dart';
/// 健康管家 App 根组件
class HealthApp extends ConsumerWidget {
@@ -16,10 +18,16 @@ class HealthApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final auth = ref.watch(authProvider);
final elderMode = ref.watch(elderModeProvider);
final isPatient = auth.isLoggedIn && auth.user?.role == 'User';
final useElderMode = isPatient && elderMode.isEnabled;
final useLargeText = useElderMode && elderMode.preferences.largeTextEnabled;
return MaterialApp(
title: '小脉健康',
debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme,
theme: useElderMode ? AppTheme.elderLightTheme : AppTheme.lightTheme,
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
@@ -30,12 +38,23 @@ class HealthApp extends ConsumerWidget {
home: const _RootNavigator(),
// 注入 ShadTheme + 启动闸门Splash 盖在最上层,直到首页今日健康卡数据就绪
// 外层包一层 GestureDetector点击任意空白处取消输入框焦点全 app 生效)
builder: (context, child) => ShadTheme(
data: AppTheme.shadTheme,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: _BootGate(child: child!),
builder: (context, child) => ElderModeScope(
enabled: useElderMode,
largeTextEnabled: useLargeText,
child: Builder(
builder: (scopeContext) => MediaQuery(
data: MediaQuery.of(
scopeContext,
).copyWith(textScaler: ElderModeScope.textScalerFor(scopeContext)),
child: ShadTheme(
data: AppTheme.shadTheme,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: _BootGate(child: child!),
),
),
),
),
),
);
@@ -52,6 +71,7 @@ final appReadyProvider = Provider<bool>((ref) {
if (currentRoute == 'login') return false; // 等根导航切到已登录首页后再撤 Splash
final role = auth.user?.role ?? 'User';
if (role != 'User') return true; // 医生/管理员首页不依赖今日健康卡
if (!ref.watch(elderModeProvider).isLoaded) return false;
// 普通用户:等今日健康卡片数据(成功或失败都算就绪,避免卡死)
final health = ref.watch(latestHealthProvider);
return health.hasValue || health.hasError;