- 核心业务拆分为 Endpoint → Application Service → Repository 三层 - AI写入操作必须用户确认后才写库(确认卡片机制) - 报告/饮食/用药分析改为持久化任务队列(原子领取/重试/重启恢复) - 运动计划修复: 连续真实日期替代周模板 - 用药提醒去重 + 通知Outbox预留 - 认证收拢到AuthService, 管理员收拢到AdminService - AI会话加用户归属校验防串号 - 提示词调整为患者视角 - 开发假数据已关闭 - 21/21测试通过, 0警告0错误
112 lines
4.4 KiB
C#
112 lines
4.4 KiB
C#
using Health.Domain.Entities;
|
|
|
|
namespace Health.Application.HealthArchives;
|
|
|
|
public sealed class HealthArchiveService(IHealthArchiveRepository archives) : IHealthArchiveService
|
|
{
|
|
private readonly IHealthArchiveRepository _archives = archives;
|
|
|
|
public async Task<HealthArchiveDto?> GetAsync(Guid userId, CancellationToken ct)
|
|
{
|
|
var archive = await _archives.GetByUserIdAsync(userId, ct);
|
|
return archive == null ? null : ToDto(archive);
|
|
}
|
|
|
|
public async Task<HealthArchiveDto> GetOrCreateAsync(Guid userId, CancellationToken ct)
|
|
{
|
|
var archive = await GetOrCreateEntityAsync(userId, ct);
|
|
await _archives.SaveChangesAsync(ct);
|
|
return ToDto(archive);
|
|
}
|
|
|
|
public async Task<HealthArchiveDto> UpdateAsync(Guid userId, HealthArchiveUpdateRequest request, CancellationToken ct)
|
|
{
|
|
var archive = await GetOrCreateEntityAsync(userId, ct);
|
|
Apply(archive, request);
|
|
archive.UpdatedAt = DateTime.UtcNow;
|
|
await _archives.SaveChangesAsync(ct);
|
|
return ToDto(archive);
|
|
}
|
|
|
|
public async Task<object> ExecuteAiActionAsync(Guid userId, string action, HealthArchiveUpdateRequest request, CancellationToken ct)
|
|
{
|
|
if (action == "query")
|
|
{
|
|
var archive = await GetAsync(userId, ct);
|
|
return archive == null ? new { found = false } : ToAiResult(archive);
|
|
}
|
|
|
|
var current = await GetOrCreateEntityAsync(userId, ct);
|
|
var scopedRequest = action switch
|
|
{
|
|
"update_diagnosis" => request with
|
|
{
|
|
SurgeryType = null, SurgeryDate = null, Allergies = null,
|
|
DietRestrictions = null, ChronicDiseases = null, FamilyHistory = null
|
|
},
|
|
"update_surgery" => request with
|
|
{
|
|
Diagnosis = null, Allergies = null, DietRestrictions = null,
|
|
ChronicDiseases = null, FamilyHistory = null
|
|
},
|
|
"update_allergies" => new HealthArchiveUpdateRequest(null, null, null, request.Allergies, null, null, null),
|
|
"update_chronic_diseases" => new HealthArchiveUpdateRequest(null, null, null, null, null, request.ChronicDiseases, null),
|
|
"update_diet_restrictions" => new HealthArchiveUpdateRequest(null, null, null, null, request.DietRestrictions, null, null),
|
|
_ => null
|
|
};
|
|
|
|
if (scopedRequest == null)
|
|
return new { success = false, message = $"未知档案操作: {action}" };
|
|
|
|
Apply(current, scopedRequest);
|
|
current.UpdatedAt = DateTime.UtcNow;
|
|
await _archives.SaveChangesAsync(ct);
|
|
return new { success = true };
|
|
}
|
|
|
|
private async Task<HealthArchive> GetOrCreateEntityAsync(Guid userId, CancellationToken ct)
|
|
{
|
|
var archive = await _archives.GetByUserIdAsync(userId, ct);
|
|
if (archive != null) return archive;
|
|
|
|
archive = new HealthArchive { Id = Guid.NewGuid(), UserId = userId, UpdatedAt = DateTime.UtcNow };
|
|
await _archives.AddAsync(archive, ct);
|
|
return archive;
|
|
}
|
|
|
|
private static void Apply(HealthArchive archive, HealthArchiveUpdateRequest request)
|
|
{
|
|
if (request.Diagnosis != null) archive.Diagnosis = request.Diagnosis;
|
|
if (request.SurgeryType != null) archive.SurgeryType = request.SurgeryType;
|
|
if (request.SurgeryDate.HasValue) archive.SurgeryDate = request.SurgeryDate.Value;
|
|
if (request.Allergies != null) archive.Allergies = request.Allergies.ToList();
|
|
if (request.DietRestrictions != null) archive.DietRestrictions = request.DietRestrictions.ToList();
|
|
if (request.ChronicDiseases != null) archive.ChronicDiseases = request.ChronicDiseases.ToList();
|
|
if (request.FamilyHistory != null) archive.FamilyHistory = request.FamilyHistory;
|
|
}
|
|
|
|
private static object ToAiResult(HealthArchiveDto archive) => new
|
|
{
|
|
found = true,
|
|
archive.Diagnosis,
|
|
archive.SurgeryType,
|
|
SurgeryDate = archive.SurgeryDate?.ToString("yyyy-MM-dd"),
|
|
archive.Allergies,
|
|
archive.DietRestrictions,
|
|
archive.ChronicDiseases,
|
|
archive.FamilyHistory,
|
|
};
|
|
|
|
private static HealthArchiveDto ToDto(HealthArchive archive) => new(
|
|
archive.Id,
|
|
archive.UserId,
|
|
archive.Diagnosis,
|
|
archive.SurgeryType,
|
|
archive.SurgeryDate,
|
|
archive.Allergies,
|
|
archive.DietRestrictions,
|
|
archive.ChronicDiseases,
|
|
archive.FamilyHistory,
|
|
archive.UpdatedAt);
|
|
}
|