架构治理: - Feature Flag 落地: Cargo.toml [features] default=["diary"] + main.rs cfg 条件编译 - 环境配置统一: AppConfig 类 + --dart-define 注入 + SSE 端口 8080→3000 修复 搜索替代方案 (无 FTS): - SearchBloc + 标签/心情筛选接入后端 API - JournalRepository 扩展 mood/tag 筛选参数 - 搜索页 UI 接入实际数据(替换占位文本) 家长中心最小集 (PIPL 合规): - 后端: parent_service (绑定/查看/导出/删除/解绑) + parent_handler (6 个 API 端点) - 前端: ParentBloc + ParentPage 功能完整实现 - 绑定孩子、只读查看日记、导出数据、删除数据、解绑 Docker 部署: - verify.sh 健康检查脚本 (Axum/PG/Redis/OpenAPI 四项检查) 测试修复: - home_bloc_test / calendar_bloc_test 适配 JournalRepository 新参数 验证: flutter test 84/84 pass, cargo test 76/76 pass, cargo check pass
80 lines
1.8 KiB
Dart
80 lines
1.8 KiB
Dart
// 家长中心状态 — ParentBloc 输出的 UI 状态
|
|
|
|
part of 'parent_bloc.dart';
|
|
|
|
/// 家长中心状态基类
|
|
sealed class ParentState {
|
|
const ParentState();
|
|
}
|
|
|
|
/// 初始状态
|
|
final class ParentInitial extends ParentState {
|
|
const ParentInitial();
|
|
}
|
|
|
|
/// 加载中
|
|
final class ParentLoading extends ParentState {
|
|
const ParentLoading();
|
|
}
|
|
|
|
/// 孩子列表已加载
|
|
final class ParentChildrenLoaded extends ParentState {
|
|
final List<ChildBinding> children;
|
|
const ParentChildrenLoaded(this.children);
|
|
}
|
|
|
|
/// 孩子日记已加载(只读)
|
|
final class ParentJournalsLoaded extends ParentState {
|
|
final String childId;
|
|
final List<Map<String, dynamic>> journals;
|
|
const ParentJournalsLoaded({
|
|
required this.childId,
|
|
required this.journals,
|
|
});
|
|
}
|
|
|
|
/// 数据已导出
|
|
final class ParentDataExported extends ParentState {
|
|
final String childId;
|
|
final Map<String, dynamic> data;
|
|
const ParentDataExported({
|
|
required this.childId,
|
|
required this.data,
|
|
});
|
|
}
|
|
|
|
/// 数据已删除
|
|
final class ParentDataDeleted extends ParentState {
|
|
final String childId;
|
|
const ParentDataDeleted(this.childId);
|
|
}
|
|
|
|
/// 出错
|
|
final class ParentError extends ParentState {
|
|
final String message;
|
|
const ParentError(this.message);
|
|
}
|
|
|
|
// ===== 模型 =====
|
|
|
|
/// 家长-孩子绑定关系
|
|
class ChildBinding {
|
|
final String bindingId;
|
|
final String childId;
|
|
final DateTime? verifiedAt;
|
|
|
|
const ChildBinding({
|
|
required this.bindingId,
|
|
required this.childId,
|
|
this.verifiedAt,
|
|
});
|
|
|
|
factory ChildBinding.fromJson(Map<String, dynamic> json) => ChildBinding(
|
|
bindingId: json['binding_id'] as String,
|
|
childId: json['child_id'] as String,
|
|
verifiedAt: json['verified_at'] != null
|
|
? DateTime.tryParse(json['verified_at'] as String)
|
|
: null,
|
|
);
|
|
}
|