feat: 全面UI改造 — 报告/饮食/运动/用药/侧边栏/对话流/胶囊
- 报告模块:重写AI解读页,统一白色卡片+三栏布局(指标→解读→医生审核);加删除功能+后端删接口;VLM自动识别报告类型生成中文标题;去五颜六色
- 饮食分析:全面重设计,暖橙主题配色,图片自适应,餐次emoji选择器,去紫色
- 运动确认卡片:修复duration_minutes JSON类型转换,支持中文数字识别(三十分钟/半小时→30);主区域只显示运动名,字段行改为横向排列
- 流式输出:简化为最基础逐字追加,去buffer+Timer+淡入动画
- 欢迎卡片:每智能体独立渐变色(青/橙/蓝/紫/绿/粉),加卡片入场滑入+淡入动画(600ms)
- 确认卡片:头部去紫色背景改浅灰白,字段行去图标改纯信息横排,编辑框去双重边框
- 用药管理:胶囊改TabBar,添加按钮改右下FAB;打卡按钮改对号圆圈形式;药丸图标白底
- 侧边栏:加VIP服务/保险栏+图标,标题字体放大;服务包去查看更多+去VIP金色标签
- 胶囊:首页智能体胶囊白底深色字; side胶囊加阴影
- 对话流:reverse=false,今日健康出现在顶部; 对话页input bar匹配主页面样式
- 其他:个人资料去紫色+去多余入口;设置页白底图标;蓝牙页加返回按钮;报告管理改名
- 后端:加DELETE /api/reports/{id}; 修复manage_exercise数据类型转换;AI提示优化中文数字
This commit is contained in:
@@ -135,8 +135,9 @@ public sealed class PromptManager
|
||||
运动计划参数格式(manage_exercise):
|
||||
- action="create", week_start_date="今天日期(YYYY-MM-DD)"
|
||||
- items: [{"day_of_week":0-6(周日=0),"exercise_type":"散步","duration_minutes":30,"is_rest_day":false}, ...]
|
||||
- 未说持续多久则默认创建7天
|
||||
- 用户说"坚持10天"则创建10天,说"到6月20日"则算天数
|
||||
- 时长必须识别中文数字:半小时=30 一小时=60 三十分钟=30 一个半小时=90 一小时二十分钟=80,中文数字必须转为阿拉伯数字
|
||||
- 天数:"一个月"=30天 "一周"=7天 "10天"=10天,必须识别中文,默认7天
|
||||
- 用户说"坚持X天/月/周"则创建对应天数
|
||||
- items 数量必须等于持续天数
|
||||
|
||||
用药管理参数格式(manage_medication):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Text.Json;
|
||||
using Health.Infrastructure.AI;
|
||||
using Health.Infrastructure.AI.AgentHandlers;
|
||||
|
||||
@@ -402,6 +403,22 @@ public static class AiChatEndpoints
|
||||
_ => "—"
|
||||
};
|
||||
|
||||
// ── JSON 类型安全转换 ──
|
||||
private static int _ToInt(object? v) => v switch
|
||||
{
|
||||
JsonElement je => je.ValueKind == JsonValueKind.Number ? je.GetInt32() : (int.TryParse(je.GetRawText().Trim('"'), out var i) ? i : 0),
|
||||
int i => i,
|
||||
long l => (int)l,
|
||||
string s => int.TryParse(s, out var si) ? si : 0,
|
||||
_ => 0
|
||||
};
|
||||
private static bool _ToBool(object? v) => v switch
|
||||
{
|
||||
JsonElement je => je.ValueKind == JsonValueKind.True || je.ValueKind == JsonValueKind.False ? je.GetBoolean() : false,
|
||||
bool b => b,
|
||||
_ => false
|
||||
};
|
||||
|
||||
// ── 消息类型判断 ──
|
||||
|
||||
private static void _UpdateMessageTypeAndMetadata(string toolName, object toolResult, ref string messageType, ref Dictionary<string, object> metadata)
|
||||
@@ -455,15 +472,14 @@ public static class AiChatEndpoints
|
||||
if (resultDict != null)
|
||||
{
|
||||
metadata["type"] = "exercise";
|
||||
metadata["value"] = "";
|
||||
if (resultDict.TryGetValue("exercise_type", out var et))
|
||||
metadata["value"] = et.ToString();
|
||||
if (resultDict.TryGetValue("duration_minutes", out var dm) && dm is int mins)
|
||||
metadata["unit"] = $"每天{mins}分钟";
|
||||
if (resultDict.TryGetValue("day_count", out var dc) && dc is int days)
|
||||
metadata["durationDays"] = days;
|
||||
if (resultDict.TryGetValue("success", out var es) && es is bool eb && eb)
|
||||
metadata["success"] = true;
|
||||
resultDict.TryGetValue("exercise_type", out var et);
|
||||
metadata["value"] = et?.ToString() ?? "";
|
||||
resultDict.TryGetValue("duration_minutes", out var dm);
|
||||
metadata["unit"] = dm != null ? $"每天{dm}分钟" : "";
|
||||
resultDict.TryGetValue("day_count", out var dc);
|
||||
if (dc != null) metadata["durationDays"] = dc.ToString();
|
||||
resultDict.TryGetValue("success", out var ok);
|
||||
metadata["success"] = ok?.ToString() == "True";
|
||||
metadata["recordTime"] = DateTime.UtcNow.AddHours(8).ToString("MM月dd日 HH:mm");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -16,6 +16,23 @@ public static class ReportEndpoints
|
||||
return Results.Ok(new { code = 0, data = reports, message = (string?)null });
|
||||
});
|
||||
|
||||
// 删除
|
||||
group.MapDelete("/{id:guid}", async (Guid id, HttpContext http, AppDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
var userId = GetUserId(http);
|
||||
var report = await db.Reports.FirstOrDefaultAsync(r => r.Id == id && r.UserId == userId, ct);
|
||||
if (report == null) return Results.Ok(new { code = 40004, message = "不存在" });
|
||||
// 删除本地文件
|
||||
if (!string.IsNullOrEmpty(report.FileUrl))
|
||||
{
|
||||
var filePath = Path.Combine(Directory.GetCurrentDirectory(), report.FileUrl.TrimStart('/'));
|
||||
if (File.Exists(filePath)) File.Delete(filePath);
|
||||
}
|
||||
db.Reports.Remove(report);
|
||||
await db.SaveChangesAsync(ct);
|
||||
return Results.Ok(new { code = 0, message = "已删除" });
|
||||
});
|
||||
|
||||
// 详情
|
||||
group.MapGet("/{id:guid}", async (Guid id, HttpContext http, AppDbContext db, CancellationToken ct) =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user