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

@@ -9,7 +9,7 @@ const String baseUrl = String.fromEnvironment(
'API_BASE_URL',
defaultValue: kReleaseMode
? 'https://erpapi.datalumina.cn/xiaomai'
: 'http://192.168.1.34:5000',
: 'http://10.4.178.175:5000',
);
class ApiException implements Exception {

View File

@@ -11,6 +11,7 @@ import '../pages/report/report_pages.dart';
import '../pages/report/ai_analysis_page.dart';
import '../pages/consultation/consultation_pages.dart';
import '../pages/settings/settings_pages.dart';
import '../pages/settings/elder_mode_page.dart';
import '../pages/settings/notification_prefs_page.dart';
import '../pages/notifications/notification_center_page.dart';
import '../pages/history/conversation_history_page.dart';
@@ -127,6 +128,8 @@ Widget buildPage(RouteInfo route, WidgetRef ref) {
return const FollowUpListPage();
case 'settings':
return const SettingsPage();
case 'elderMode':
return const ElderModePage();
case 'notificationPrefs':
return const NotificationPrefsPage();
case 'notifications':

View File

@@ -776,6 +776,74 @@ class AppTheme {
),
);
/// 长辈模式只在已登录的患者端启用。这里提高主题级控件尺寸,页面中写死的
/// 字号再由 ElderModeScope 提供的文本缩放统一兜底。
static ThemeData get elderLightTheme {
final base = lightTheme;
return base.copyWith(
appBarTheme: base.appBarTheme.copyWith(
toolbarHeight: 60,
titleTextStyle: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
color: text,
),
iconTheme: const IconThemeData(size: 28, color: text),
),
textTheme: base.textTheme.copyWith(
headlineLarge: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
color: text,
),
titleLarge: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w700,
color: text,
),
titleMedium: const TextStyle(
fontSize: 19,
fontWeight: FontWeight.w600,
color: text,
),
bodyLarge: const TextStyle(fontSize: 18, color: text, height: 1.5),
bodyMedium: const TextStyle(fontSize: 16, color: textSub, height: 1.45),
labelMedium: const TextStyle(fontSize: 16, color: textSub),
labelSmall: const TextStyle(fontSize: 15, color: textHint),
),
inputDecorationTheme: base.inputDecorationTheme.copyWith(
contentPadding: const EdgeInsets.symmetric(
horizontal: 18,
vertical: 16,
),
hintStyle: const TextStyle(color: textHint, fontSize: 17),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: primary,
foregroundColor: Colors.white,
minimumSize: const Size(double.infinity, 56),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(rLg),
),
textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
elevation: 0,
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: text,
minimumSize: const Size(52, 56),
side: const BorderSide(color: border),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(rMd),
),
textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
),
),
);
}
static ShadThemeData get shadTheme => ShadThemeData(
brightness: Brightness.light,
colorScheme: ShadVioletColorScheme.light(

View File

@@ -0,0 +1,42 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
class ElderModeScope extends InheritedWidget {
final bool enabled;
final bool largeTextEnabled;
const ElderModeScope({
super.key,
required this.enabled,
required this.largeTextEnabled,
required super.child,
});
static ElderModeScope? maybeOf(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<ElderModeScope>();
}
static bool enabledOf(BuildContext context) {
return maybeOf(context)?.enabled == true;
}
static bool largeTextOf(BuildContext context) {
final scope = maybeOf(context);
return scope?.enabled == true && scope?.largeTextEnabled == true;
}
static TextScaler textScalerFor(BuildContext context) {
final systemScaler = MediaQuery.textScalerOf(context);
if (!largeTextOf(context)) return systemScaler;
final systemFactor = systemScaler.scale(1);
final factor = math.max(systemFactor, 1.18).clamp(1.0, 1.6).toDouble();
return TextScaler.linear(factor);
}
@override
bool updateShouldNotify(ElderModeScope oldWidget) {
return enabled != oldWidget.enabled ||
largeTextEnabled != oldWidget.largeTextEnabled;
}
}