Files
AI-Health/health_app/lib/widgets/app_future_view.dart
MingNian b57d0d16f4 feat: 引入 EF Core Migrations + 后台任务/校验修复 + 前端四态
后端
- 改用 EF Core Migrations(InitialCreate),Program.cs 用 MigrateAsync + AUTO_MIGRATE 开关 + 显式 MigrationsAssembly;移除 EnsureCreated、删除手写 DatabaseSchemaMigrator
- 修复后台任务永久卡 Processing:三个队列对超时且达上限的任务原子标记 Failed
- 修复报告重试失效:基础设施异常向上抛激活 RetryAsync,停机取消不计失败
- 修复 AI 用药天数 off-by-one(结束日为包含式)
- AI 报告日志不再记录 VLM 健康正文
- 新增统一输入校验(ValidationException + 中间件映射 400):血压/心率/血糖/血氧/体重范围、药名/日期/服药时间去重、饮食热量与评分、运动时长上限
- 删除健康数据 AI 录入的影子直写路径,统一走 Service 校验

前端
- 新增 AppErrorState / AppFutureView,用药列表、服药打卡、运动计划、随访列表改为 加载/失败/空/数据 四态,失败可重试

瘦身
- 删除过时的 DataSeeder / DevDataSeeder 及调用
- 删除依赖实时服务的 ai_agent_tests 集成测试
2026-06-21 21:04:40 +08:00

55 lines
1.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import '../core/app_colors.dart';
import 'app_error_state.dart';
/// 基于 FutureBuilder 的四态封装:统一处理"加载中 / 失败"
/// "空数据 / 有数据"交由 onData 自行判断(不同页面空态文案不同)。
///
/// onData 拿到非空数据后,自行判断 isEmpty 决定显示空态还是列表。
class AppFutureView<T> extends StatelessWidget {
final Future<T>? future;
final Widget Function(BuildContext context, T data) onData;
final VoidCallback? onRetry;
final Widget? loading;
final String? errorTitle;
const AppFutureView({
super.key,
required this.future,
required this.onData,
this.onRetry,
this.loading,
this.errorTitle,
});
@override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: future,
builder: (ctx, snap) {
// 失败优先于其它判断,避免把错误显示成"暂无数据"
if (snap.hasError) {
return AppErrorState(
title: errorTitle ?? '加载失败',
onRetry: onRetry,
);
}
// 首次加载、尚无数据 → 转圈
if (snap.connectionState == ConnectionState.waiting && !snap.hasData) {
return loading ??
const Center(
child: CircularProgressIndicator(color: AppColors.primary),
);
}
if (!snap.hasData) {
return loading ??
const Center(
child: CircularProgressIndicator(color: AppColors.primary),
);
}
return onData(ctx, snap.data as T);
},
);
}
}