Files
AI-Health/backend/src/Health.Application/Reports/ReportContracts.cs
MingNian 4d213b5a44 feat: 后端架构重构 — Endpoint→Service→Repository分层 + AI确认机制 + 异步任务持久化
- 核心业务拆分为 Endpoint → Application Service → Repository 三层
- AI写入操作必须用户确认后才写库(确认卡片机制)
- 报告/饮食/用药分析改为持久化任务队列(原子领取/重试/重启恢复)
- 运动计划修复: 连续真实日期替代周模板
- 用药提醒去重 + 通知Outbox预留
- 认证收拢到AuthService, 管理员收拢到AdminService
- AI会话加用户归属校验防串号
- 提示词调整为患者视角
- 开发假数据已关闭
- 21/21测试通过, 0警告0错误
2026-06-20 20:41:42 +08:00

84 lines
2.5 KiB
C#

using Health.Domain.Entities;
using Health.Domain.Enums;
namespace Health.Application.Reports;
public sealed record ReportUploadFile(
string FileName,
long Length,
Stream Content);
public sealed record ReportDto(
Guid Id,
Guid UserId,
string FileUrl,
string FileType,
string Category,
string Status,
string AiStatus,
string ReviewStatus,
string? Severity,
string? AiSummary,
string? AiIndicators,
string? DoctorComment,
string? DoctorRecommendation,
string? DoctorName,
DateTime? ReviewedAt,
DateTime CreatedAt);
public sealed record ReportUploadResult(
bool Success,
int Code,
string? Message,
ReportDto? Report);
public sealed record ReportAnalysisJob(
Guid TaskId,
Guid ReportId,
string FilePath);
public sealed record StoredReportFile(
string FileUrl,
string FilePath);
public interface IReportService
{
Task<IReadOnlyList<ReportDto>> GetReportsAsync(Guid userId, CancellationToken ct);
Task<ReportDto?> GetReportAsync(Guid userId, Guid reportId, CancellationToken ct);
Task<ReportUploadResult> UploadReportAsync(Guid userId, ReportUploadFile file, CancellationToken ct);
Task<bool> DeleteReportAsync(Guid userId, Guid reportId, CancellationToken ct);
Task<bool> ReanalyzeReportAsync(Guid userId, Guid reportId, CancellationToken ct);
}
public interface IReportAnalysisQueue
{
Task EnqueueAsync(ReportAnalysisJob job, CancellationToken ct = default);
Task RecoverStaleAsync(CancellationToken ct);
Task<ReportAnalysisJob?> TryTakeAsync(CancellationToken ct);
Task CompleteAsync(Guid taskId, CancellationToken ct);
Task RetryAsync(Guid taskId, string error, CancellationToken ct);
}
public interface IReportAnalysisService
{
Task AnalyzeAsync(ReportAnalysisJob job, CancellationToken ct);
}
public interface IReportRepository
{
Task<IReadOnlyList<Report>> ListAsync(Guid userId, CancellationToken ct);
Task<Report?> GetOwnedAsync(Guid userId, Guid reportId, CancellationToken ct);
Task<Report?> GetByIdAsync(Guid reportId, CancellationToken ct);
Task AddAsync(Report report, CancellationToken ct);
void Delete(Report report);
Task SaveChangesAsync(CancellationToken ct);
}
public interface IReportFileStorage
{
Task<StoredReportFile> SaveAsync(ReportUploadFile file, string extension, CancellationToken ct);
string GetLocalFilePath(string fileUrl);
bool Exists(string filePath);
void Delete(string filePath);
}