fix: 用药模块重做 + 运动计划不限7天 + 打卡可切换 + 删除修复
- 用药: 重写列表页(标签筛选+详情弹窗+打卡切换+滑动删除) - 用药: 重写编辑页(选择器替代输入+同列布局+频率改为每天几次) - 用药: 加Notes字段+DELETE端点+修复重复端点 - 运动: 不限7天, startDate+索引推算当天 - 打卡: 药/运动打卡可切换(点✓取消) - 删除: 修复滑动删除热区, 一次点击即删除 - 侧边栏: 一键清理历史对话 - 饮食/运动/用药/问诊 API路径加/api/前缀 - 通知时机修正: 新建计划不再提前弹窗
This commit is contained in:
@@ -175,11 +175,7 @@ class ChatMessagesView extends ConsumerWidget {
|
||||
Widget _agentActionBtn(_AgentAction a, double screenWidth, BuildContext context, WidgetRef ref, _AgentColors colors) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
if (a.action == 'createPlan') {
|
||||
_createExercisePlan(ref, context);
|
||||
} else if (a.action == 'checkIn') {
|
||||
_exerciseCheckIn(ref, context);
|
||||
} else if (a.label == '服药打卡') {
|
||||
if (a.label == '服药打卡') {
|
||||
_medicationCheckIn(ref, context);
|
||||
} else if (a.route != null) {
|
||||
if (a.route == 'camera' || a.route == 'gallery') {
|
||||
@@ -1200,73 +1196,6 @@ class ChatMessagesView extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
static void _createExercisePlan(WidgetRef ref, BuildContext context) async {
|
||||
try {
|
||||
final service = ref.read(exerciseServiceProvider);
|
||||
final today = DateTime.now();
|
||||
final monday = today.subtract(Duration(days: today.weekday - 1));
|
||||
final items = List.generate(7, (i) => {
|
||||
'dayOfWeek': i,
|
||||
'exerciseType': i == 2 || i == 5 ? '休息' : '散步',
|
||||
'durationMinutes': i == 2 || i == 5 ? 0 : 30,
|
||||
'isRestDay': i == 2 || i == 5,
|
||||
});
|
||||
await service.createPlan({
|
||||
'weekStartDate': '${monday.year}-${monday.month.toString().padLeft(2, '0')}-${monday.day.toString().padLeft(2, '0')}',
|
||||
'items': items,
|
||||
});
|
||||
ref.invalidate(currentExercisePlanProvider);
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('运动计划已创建'), backgroundColor: Color(0xFF43A047)),
|
||||
);
|
||||
pushRoute(ref, 'exercisePlan');
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('创建失败:$e'), backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void _exerciseCheckIn(WidgetRef ref, BuildContext context) async {
|
||||
try {
|
||||
final plan = await ref.read(currentExercisePlanProvider.future);
|
||||
if (plan == null || plan.isEmpty) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('请先创建运动计划'), backgroundColor: Color(0xFFFF9800)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final items = (plan['items'] as List?)?.cast<Map<String, dynamic>>() ?? [];
|
||||
final today = DateTime.now().weekday - 1;
|
||||
final todayItem = items.cast<Map<String, dynamic>?>().firstWhere(
|
||||
(i) => i?['dayOfWeek'] == today && i?['isRestDay'] != true,
|
||||
orElse: () => null,
|
||||
);
|
||||
if (todayItem == null) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('今天休息日'), backgroundColor: Color(0xFFFF9800)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final service = ref.read(exerciseServiceProvider);
|
||||
await service.checkIn(todayItem['id']?.toString() ?? '');
|
||||
ref.invalidate(currentExercisePlanProvider);
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('打卡成功'), backgroundColor: Color(0xFF43A047)),
|
||||
);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('打卡失败:$e'), backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static _AgentColors _agentColors(ActiveAgent agent) {
|
||||
return switch (agent) {
|
||||
ActiveAgent.consultation => _AgentColors(
|
||||
@@ -1401,13 +1330,27 @@ class ChatMessagesView extends ConsumerWidget {
|
||||
tasks.add(_taskRow(context, Icons.medication_rounded, '暂无用药提醒', status: 'pending'));
|
||||
}
|
||||
|
||||
// 3. 运动
|
||||
final exOverdue = now.hour >= 18;
|
||||
tasks.add(_taskRow(
|
||||
context, Icons.directions_run, '今日待运动:散步 30 分钟',
|
||||
status: exOverdue ? 'overdue' : 'pending',
|
||||
onTap: () => pushRoute(ref, 'exercisePlan'),
|
||||
));
|
||||
// 3. 运动 — 从所有计划中找今日待打卡项
|
||||
final plans = ref.read(exerciseServiceProvider).getPlans();
|
||||
plans.then((list) {
|
||||
for (final p in list) {
|
||||
final items = (p['items'] as List?)?.cast<Map<String, dynamic>>() ?? [];
|
||||
final today = now.weekday - 1;
|
||||
final todayItem = items.cast<Map<String, dynamic>?>().firstWhere(
|
||||
(i) => i?['dayOfWeek'] == today, orElse: () => null);
|
||||
if (todayItem != null) {
|
||||
final done = todayItem['isCompleted'] == true;
|
||||
final name = items.isNotEmpty ? (items.first['exerciseType']?.toString() ?? '运动') : '运动';
|
||||
final dur = items.isNotEmpty ? (items.first['durationMinutes']?.toString() ?? '30') : '30';
|
||||
tasks.add(_taskRow(context, Icons.directions_run,
|
||||
'$name $dur分钟',
|
||||
status: done ? 'done' : (now.hour >= 18 ? 'overdue' : 'pending'),
|
||||
onTap: () => pushRoute(ref, 'exercisePlan'),
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 4. 测量
|
||||
tasks.add(_taskRow(
|
||||
@@ -1529,8 +1472,7 @@ final _agentActions = <ActiveAgent, List<_AgentAction>>{
|
||||
],
|
||||
ActiveAgent.exercise: [
|
||||
_AgentAction(label: '查看计划', icon: Icons.calendar_month_outlined, isWide: true, route: 'exercisePlan'),
|
||||
_AgentAction(label: '新建计划', icon: Icons.add_task_outlined, isWide: true, action: 'createPlan'),
|
||||
_AgentAction(label: '今日打卡', icon: Icons.fact_check_outlined, isWide: true, action: 'checkIn'),
|
||||
_AgentAction(label: '新建计划', icon: Icons.add_task_outlined, isWide: true, route: 'exerciseCreate'),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user