diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
index 275616faa..fc4424054 100644
--- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
+++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml
@@ -1259,6 +1259,128 @@
裁决日期 CODTC
+
+
+ 公共影像导表基类(IVUS / OCT 通用)
+
+
+
+ 研究标识符
+
+
+ 中心编号
+
+
+ 受试者标识符
+
+
+ 受试者唯一标识
+
+
+ 访视名称
+
+
+ 阅片人角色
+
+
+ 拍片日期
+
+
+ 阅片完成时间
+
+
+
+ 访视编号 VISITNUM
+
+
+
+ 访视点备注
+
+
+
+ IVUS 导表模型
+
+
+
+ 靶段
+
+
+ 斑块编号
+
+
+ 外弹力膜面积
+
+
+ 管腔面积
+
+
+ 外弹力膜与管腔面积差值
+
+
+ 回撤中的图像帧数
+
+
+ 分析图像帧数
+
+
+ 总外弹力膜面积 (如无可不填)
+
+
+ 总 PA (如无可不填)
+
+
+ PAV (如无可不填)
+
+
+
+ OCT 导表模型
+
+
+
+ 靶段
+
+
+ 斑块编号
+
+
+ 测量标识
+
+
+ 测量参数名称
+
+
+ 测量参数值
+
+
+ 测量值单位
+
+
+ 斑块类型
+
+
+ 最小纤维帽厚度
+
+
+ 平均纤维帽厚度
+
+
+ 脂质角度平均值
+
+
+ 脂质角度最大值
+
+
+ 巨噬细胞浸润
+
+
+ 巨噬细胞浸润角度
+
+
+ 微通道
+
+
+ 胆固醇结晶
+
取值类型 TUSPID
@@ -1374,35 +1496,6 @@
-
-
- 从失败通知邮件中提取错误信息
-
-
-
-
-
-
- 获取邮件内容摘要(前200个字符)
-
-
-
-
-
-
- 通过收件人信息处理失败通知邮件
-
-
-
-
-
-
- 判断失败通知邮件是否与指定的EmailLog相关
-
-
-
-
-
邮件筛选条件构建
@@ -18171,7 +18264,7 @@
-
+
直接查询相关所有数据
diff --git a/IRaCIS.Core.Application/Service/Common/EmailLogService.cs b/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
index eadb95954..956f3dcb3 100644
--- a/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
+++ b/IRaCIS.Core.Application/Service/Common/EmailLogService.cs
@@ -333,7 +333,7 @@ public class EmailLogService(IRepository _emailLogRepository,
// 第二步:处理收件箱中的邮件发送失败通知
try
{
- await ProcessInboxFailureNotifications();
+ await ProcessInboxFailureNotifications(startDate);
}
catch (Exception ex)
{
@@ -488,7 +488,7 @@ public class EmailLogService(IRepository _emailLogRepository,
/// 处理收件箱中的邮件发送失败通知
///
///
- private async Task ProcessInboxFailureNotifications()
+ public async Task ProcessInboxFailureNotifications(DateTime startTime)
{
using (var client = new ImapClient())
{
@@ -508,7 +508,7 @@ public class EmailLogService(IRepository _emailLogRepository,
.Or(SearchQuery.BodyContains("失败"))
.Or(SearchQuery.BodyContains("错误"))
.Or(SearchQuery.BodyContains("undeliverable"))
- .Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(DateTime.Parse("2025-11-27")));
+ .Or(SearchQuery.BodyContains("delivery failed")).And(SearchQuery.DeliveredAfter(startTime));
var uids = inboxFolder.Search(searchQuery).ToList();
var processedCount = 0;
@@ -529,42 +529,31 @@ public class EmailLogService(IRepository _emailLogRepository,
.Where(x => x.MessageId == originalMessageId)
.FirstOrDefaultAsync();
- if (emailLog != null && emailLog.EmailStateEnum == EmailState.Success)
+ await _emailLogRepository.BatchUpdateNoTrackingAsync(x => x.MessageId == originalMessageId, x => new EmailLog()
{
- // 提取错误信息
- var errorMessage = ExtractErrorMessage(message);
+ EmailStateEnum = EmailState.Error,
+ ErrorInfo = message.TextBody
- // 更新邮件状态为失败
- emailLog.EmailStateEnum = EmailState.Error;
- emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
+ });
- //await _emailLogRepository.UpdateAsync(emailLog);
- updatedCount++;
- }
- }
- else
- {
- // 如果无法从Message-Id匹配,尝试从邮件内容中提取收件人信息进行匹配
- await ProcessFailureNotificationByRecipient(message);
+ updatedCount++;
}
+
processedCount++;
}
catch (Exception ex)
{
- Console.WriteLine($"处理收件箱邮件 UID:{uid} 失败: {ex.Message}");
- // 记录详细异常信息用于调试
- Console.WriteLine($"异常堆栈: {ex.StackTrace}");
+
}
}
- Console.WriteLine($"收件箱失败通知邮件处理完成: 共处理 {processedCount} 封邮件,更新 {updatedCount} 条记录");
+
inboxFolder.Close();
}
catch (Exception ex)
{
Console.WriteLine($"连接收件箱处理失败通知邮件时出错: {ex.Message}");
Console.WriteLine($"异常堆栈: {ex.StackTrace}");
- throw; // 重新抛出异常,让上层调用者决定如何处理
}
finally
{
@@ -599,7 +588,48 @@ public class EmailLogService(IRepository _emailLogRepository,
return originalMessageId;
}
- // 如果邮件头中没有,尝试从邮件正文中提取
+ // 检查邮件附件中是否包含.eml文件(这是最常见的失败通知格式)
+ foreach (var attachment in message.Attachments)
+ {
+ if (attachment is MessagePart messagePart)
+ {
+ // 直接获取嵌入的邮件消息
+ var originalMessageIdFromAttachment = messagePart.Message?.MessageId;
+ if (!string.IsNullOrEmpty(originalMessageIdFromAttachment))
+ {
+ return originalMessageIdFromAttachment.Trim('<', '>');
+ }
+ }
+ else if (attachment is MimePart mimePart)
+ {
+ // 检查文件扩展名是否为.eml
+ var fileName = mimePart.FileName ?? mimePart.ContentType.Name;
+ if (!string.IsNullOrEmpty(fileName) &&
+ (fileName.EndsWith(".eml", StringComparison.OrdinalIgnoreCase) ||
+ mimePart.ContentType.MimeType.Equals("message/rfc822", StringComparison.OrdinalIgnoreCase)))
+ {
+ try
+ {
+ // 解析.eml附件内容
+ using var memoryStream = new MemoryStream();
+ mimePart.Content.DecodeTo(memoryStream);
+ memoryStream.Position = 0;
+
+ var originalMessage = MimeMessage.Load(memoryStream);
+ if (!string.IsNullOrEmpty(originalMessage?.MessageId))
+ {
+ return originalMessage.MessageId.Trim('<', '>');
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"解析.eml附件时出错: {ex.Message}");
+ }
+ }
+ }
+ }
+
+ // 如果邮件头和附件中都没有,尝试从邮件正文中提取
var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
// 尝试匹配常见的Message-Id格式
@@ -621,129 +651,6 @@ public class EmailLogService(IRepository _emailLogRepository,
return null;
}
- ///
- /// 从失败通知邮件中提取错误信息
- ///
- ///
- ///
- private string ExtractErrorMessage(MimeMessage message)
- {
- var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
-
- // 尝试提取具体的错误信息
- // 常见的错误信息模式
- var errorPatterns = new[]
- {
- @"(?i)reason\s*:\s*([^\r\n]+)",
- @"(?i)error\s*:\s*([^\r\n]+)",
- @"(?i)failure\s*:\s*([^\r\n]+)",
- @"(?i)诊断信息[::]\s*([^\r\n]+)",
- @"(?i)错误详情[::]\s*([^\r\n]+)",
- @"(?i)Technical details of permanent failure[::]\s*([^\r\n]+)",
- @"(?i)The error that the other server returned was[::]\s*([^\r\n]+)"
- };
-
- foreach (var pattern in errorPatterns)
- {
- var match = System.Text.RegularExpressions.Regex.Match(content, pattern);
- if (match.Success)
- {
- return match.Groups[1].Value.Trim();
- }
- }
-
- // 如果没有找到具体的错误信息,返回邮件主题和部分内容
- return $"主题: {message.Subject}\n内容摘要: {GetContentSummary(content)}";
- }
-
- ///
- /// 获取邮件内容摘要(前200个字符)
- ///
- ///
- ///
- private string GetContentSummary(string content)
- {
- if (string.IsNullOrEmpty(content))
- return string.Empty;
-
- // 移除HTML标签
- var plainText = System.Text.RegularExpressions.Regex.Replace(content, @"<[^>]+>", string.Empty);
- plainText = System.Text.RegularExpressions.Regex.Replace(plainText, @"\s+", " ");
-
- return plainText.Length > 200 ? plainText.Substring(0, 200) + "..." : plainText;
- }
-
- ///
- /// 通过收件人信息处理失败通知邮件
- ///
- ///
- ///
- private async Task ProcessFailureNotificationByRecipient(MimeMessage message)
- {
- var content = message.HtmlBody ?? message.TextBody ?? string.Empty;
-
- // 尝试从邮件内容中提取原始收件人地址
- var recipientPattern = @"(?:to|To|收件人)[::]\s*([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})";
- var match = System.Text.RegularExpressions.Regex.Match(content, recipientPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
-
- if (match.Success)
- {
- var recipientEmail = match.Groups[1].Value;
-
- // 查找最近发送给该收件人的邮件
- var recentEmailLogs = await _emailLogRepository
- .Where(x => x.EmailRecipientLogList.Any(r => r.RecipientAddress == recipientEmail))
- .Where(x => x.EmailDate >= DateTime.Now.AddDays(-7)) // 最近7天内的邮件
- .OrderByDescending(x => x.EmailDate)
- .Take(5) // 取最近的5封
- .ToListAsync();
-
- foreach (var emailLog in recentEmailLogs)
- {
- if (emailLog.EmailStateEnum == EmailState.Success)
- {
- // 检查邮件主题是否匹配(如果失败通知邮件中包含原始主题)
- if (IsLikelyRelatedEmail(message, emailLog))
- {
- var errorMessage = ExtractErrorMessage(message);
- emailLog.EmailStateEnum = EmailState.Error;
- emailLog.ErrorMessage = errorMessage ?? "邮件发送失败,具体原因未知";
- //await _emailLogRepository.UpdateAsync(emailLog);
- break; // 找到匹配的就停止
- }
- }
- }
- }
- }
-
- ///
- /// 判断失败通知邮件是否与指定的EmailLog相关
- ///
- ///
- ///
- ///
- private bool IsLikelyRelatedEmail(MimeMessage failureMessage, EmailLog emailLog)
- {
- var failureContent = failureMessage.HtmlBody ?? failureMessage.TextBody ?? failureMessage.Subject ?? string.Empty;
- var emailSubject = emailLog.EmailSubject ?? string.Empty;
-
- // 检查主题是否包含在失败通知中
- if (!string.IsNullOrEmpty(emailSubject) &&
- failureContent.Contains(emailSubject, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- // 检查发件人是否匹配
- if (!string.IsNullOrEmpty(emailLog.SenderAddress) &&
- (failureContent.Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase) ||
- failureMessage.From.ToString().Contains(emailLog.SenderAddress, StringComparison.OrdinalIgnoreCase)))
- {
- return true;
- }
-
- return false;
- }
//private string AcquireOAuth2TokenByPassword()
//{
diff --git a/IRaCIS.Core.Application/Service/SiteSurvey/Interface/ITrialSiteSurveyService.cs b/IRaCIS.Core.Application/Service/SiteSurvey/Interface/ITrialSiteSurveyService.cs
index 28c0ac131..1aa63ba8e 100644
--- a/IRaCIS.Core.Application/Service/SiteSurvey/Interface/ITrialSiteSurveyService.cs
+++ b/IRaCIS.Core.Application/Service/SiteSurvey/Interface/ITrialSiteSurveyService.cs
@@ -12,7 +12,7 @@ namespace IRaCIS.Core.Application.Contracts
{
Task AddOrUpdateTrialSiteSurvey(TrialSiteSurveyAddOrEdit addOrEditTrialSiteSurvey);
//Task DeleteTrialSiteSurvey(Guid trialSiteSurveyId);
- Task GetSiteSurveyInfo(Guid trialSiteSurveyId, Guid trialId);
+ Task GetSiteSurveyInfo(Guid? trialSiteSurveyId, Guid trialId);
Task> GetTrialSiteSurveyList(TrialSiteSurveyQueryDTO surveyQueryDTO);
Task GetTrialSurveyInitInfo(Guid trialId);
Task SendVerifyCode(SiteSurveySendVerifyCode userInfo);
diff --git a/IRaCIS.Core.Domain/Common/EmailLog.cs b/IRaCIS.Core.Domain/Common/EmailLog.cs
index 460f1691f..6686b9732 100644
--- a/IRaCIS.Core.Domain/Common/EmailLog.cs
+++ b/IRaCIS.Core.Domain/Common/EmailLog.cs
@@ -41,6 +41,7 @@ public class EmailLog : BaseFullAuditEntity
///
/// 错误信息
///
+ [StringLength(5000)]
public string ErrorInfo { get; set; }
///
@@ -58,8 +59,6 @@ public class EmailLog : BaseFullAuditEntity
///
public EmailState EmailStateEnum { get; set; }
- [StringLength(5000)]
- public string ErrorMessage { get; set; }
///
/// 邮件内容
diff --git a/IRaCIS.Core.Infra.EFCore/Migrations/20251128060451_ErrorInfo.Designer.cs b/IRaCIS.Core.Infra.EFCore/Migrations/20251128060451_ErrorInfo.Designer.cs
new file mode 100644
index 000000000..f553d9efc
--- /dev/null
+++ b/IRaCIS.Core.Infra.EFCore/Migrations/20251128060451_ErrorInfo.Designer.cs
@@ -0,0 +1,21265 @@
+//
+using System;
+using IRaCIS.Core.Infra.EFCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace IRaCIS.Core.Infra.EFCore.Migrations
+{
+ [DbContext(typeof(IRaCISDBContext))]
+ [Migration("20251128060451_ErrorInfo")]
+ partial class ErrorInfo
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.19")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.Attachment", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("编码");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DoctorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ExpiryDate")
+ .HasColumnType("datetime2")
+ .HasComment("过期时间");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsAuthorizedView")
+ .HasColumnType("bit");
+
+ b.Property("IsOfficial")
+ .HasColumnType("bit")
+ .HasComment("是否正式简历");
+
+ b.Property("Language")
+ .HasColumnType("int")
+ .HasComment("1 中文 2为英文");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("文件类型名");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("DoctorId");
+
+ b.ToTable("Attachment", t =>
+ {
+ t.HasComment("医生 - 简历|证书 文档表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocument", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditDocumentTypeEnum")
+ .HasColumnType("int");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("FileFormat")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FilePath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("FileSize")
+ .HasPrecision(18, 2)
+ .HasColumnType("decimal(18,2)");
+
+ b.Property("IsAuthorization")
+ .HasColumnType("bit");
+
+ b.Property("MainFileId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Version")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("MainFileId");
+
+ b.ToTable("AuditDocument", t =>
+ {
+ t.HasComment("稽查文档管理");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditDocumentClosure", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AncestorId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("祖先");
+
+ b.Property("Depth")
+ .HasColumnType("int");
+
+ b.Property("DescendantId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("后代");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AncestorId");
+
+ b.HasIndex("DescendantId");
+
+ b.ToTable("AuditDocumentClosure");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecord", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditContent")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("AuditState")
+ .HasColumnType("int")
+ .HasComment("稽查状态");
+
+ b.Property("AuditTime")
+ .HasColumnType("date")
+ .HasComment("稽查日期");
+
+ b.Property("AuditType")
+ .HasColumnType("int")
+ .HasComment("稽查形式");
+
+ b.Property("BeginTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CompanyName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property("IsViewTrainingRecord")
+ .HasColumnType("bit");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("AuditRecord");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecordIdentityUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditRecordId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IdentityUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditRecordId");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("IdentityUserId");
+
+ b.ToTable("AuditRecordIdentityUser");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.AuditRecordPermission", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditDocumentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditRecordId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditDocumentId");
+
+ b.HasIndex("AuditRecordId");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("AuditRecordPermission");
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CRO", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CROCode")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CROName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CRONameCN")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsTrialLevel")
+ .HasColumnType("bit")
+ .HasComment("是否是项目级别");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CROCompany", t =>
+ {
+ t.HasComment("机构 - CRO");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CheckChallengeDialog", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsCRCNeedReply")
+ .HasColumnType("bit")
+ .HasComment("CRC是否需要回复 前端使用");
+
+ b.Property("ParamInfo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasComment("核查的检查信息Json");
+
+ b.Property("SubjectVisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TalkContent")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("UserTypeEnum")
+ .HasColumnType("int")
+ .HasComment("核查过程中的操作用户类型");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("SubjectVisitId");
+
+ b.ToTable("CheckChallengeDialog", t =>
+ {
+ t.HasComment("一致性核查 - 对话记录表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalAnswerRowInfo", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("RowIndex")
+ .HasColumnType("int");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalAnswerRowInfo", t =>
+ {
+ t.HasComment("受试者 - 临床表单表格问题行记录");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalDataSystemSet", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalDataLevel")
+ .HasColumnType("int");
+
+ b.Property("ClinicalDataSetEnName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalDataSetEnum")
+ .HasColumnType("int")
+ .HasComment("枚举(字典里面取的)");
+
+ b.Property("ClinicalDataSetName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalUploadType")
+ .HasColumnType("int")
+ .HasComment("上传方式");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionEnumListStr")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("EnFileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("EnPath")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsApply")
+ .HasColumnType("bit")
+ .HasComment("是否应用");
+
+ b.Property("IsEnable")
+ .HasColumnType("bit");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("UploadRole")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalDataSystemSet", t =>
+ {
+ t.HasComment("系统 - 临床数据配置");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalDataTrialSet", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalDataLevel")
+ .HasColumnType("int")
+ .HasComment("临床级别");
+
+ b.Property("ClinicalDataSetEnName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalDataSetName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ClinicalUploadType")
+ .HasColumnType("int")
+ .HasComment("上传方式");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionEnumListStr")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("EnFileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("EnPath")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("IsApply")
+ .HasColumnType("bit")
+ .HasComment("是否应用");
+
+ b.Property("IsConfirm")
+ .HasColumnType("bit");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("SystemClinicalDataSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UploadRole")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("SystemClinicalDataSetId");
+
+ b.HasIndex("TrialId");
+
+ b.ToTable("ClinicalDataTrialSet", t =>
+ {
+ t.HasComment("项目 - 临床数据适应标准配置");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalForm", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CheckDate")
+ .HasColumnType("datetime2")
+ .HasComment("检查日期");
+
+ b.Property("ClinicalDataTrialSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("PicturePath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)")
+ .HasComment("截图地址");
+
+ b.Property("ReadingId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("VisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClinicalDataTrialSetId");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("ReadingId");
+
+ b.HasIndex("SubjectId");
+
+ b.ToTable("ClinicalForm", t =>
+ {
+ t.HasComment("受试者 - 临床表单");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalQuestionAnswer", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Answer")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("ClinicalDataTrialSetId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClinicalFormId");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("ClinicalQuestionAnswer", t =>
+ {
+ t.HasComment("受试者 - 临床表单问题答案");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalTableAnswer", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Answer")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)")
+ .HasComment("答案");
+
+ b.Property("ClinicalFormId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("表单Id");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("QuestionId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("问题Id");
+
+ b.Property("RowId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("答案行的Id");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("受试者Id");
+
+ b.Property("TableQuestionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("RowId");
+
+ b.ToTable("ClinicalTableAnswer", t =>
+ {
+ t.HasComment("受试者 - 临床表单表格问题答案");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CommonDocument", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BusinessScenarioEnum")
+ .HasColumnType("int")
+ .HasComment("业务场景");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionTypeEnum")
+ .HasColumnType("int")
+ .HasComment("系统标准枚举");
+
+ b.Property("DeleteUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletedTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileTypeEnum")
+ .HasColumnType("int")
+ .HasComment("类型-上传|导出|邮件附件");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("NameCN")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("UpdateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("UpdateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CommonDocument", t =>
+ {
+ t.HasComment("数据上传 | 数据导出 | 邮件附件 文件记录表 (需要同步)");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionKeyFileRead", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IdentityUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialCriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CriterionKeyFileRead", t =>
+ {
+ t.HasComment("标准阅读关键点");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionNidusSystem", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("IsSystemCriterion")
+ .HasColumnType("bit");
+
+ b.Property("LesionType")
+ .HasColumnType("int")
+ .HasComment("病灶类型");
+
+ b.Property("OrganType")
+ .HasColumnType("int")
+ .HasComment("器官类型");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("CriterionId");
+
+ b.ToTable("CriterionNidusSystem", t =>
+ {
+ t.HasComment("系统标准 - 病灶器官表 (需要同步)");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.CriterionNidusTrial", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LesionType")
+ .HasColumnType("int");
+
+ b.Property("OrganType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.ToTable("CriterionNidusTrial", t =>
+ {
+ t.HasComment("项目标准 - 病灶器官表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.DataInspection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BatchId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("批次Id");
+
+ b.Property("ChildrenTypeId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("子类");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreateUserName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("创建人姓名");
+
+ b.Property("CreateUserRealName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("DoctorUserId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("阅片医生");
+
+ b.Property("EntityName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("被稽查实体名");
+
+ b.Property("GeneralId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("要稽查对象Id");
+
+ b.Property("IP")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("Identification")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("标识");
+
+ b.Property("IsFrontAdd")
+ .HasColumnType("bit")
+ .HasComment("是否是前端添加");
+
+ b.Property("IsSign")
+ .HasColumnType("bit");
+
+ b.Property("JsonDetail")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("LastJsonDetail")
+ .HasColumnType("nvarchar(max)")
+ .HasComment("上一条json");
+
+ b.Property("ModuleTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectRelationParentId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("被稽查对象外键1");
+
+ b.Property("ObjectRelationParentId2")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectRelationParentId3")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ObjectTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("OptTypeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("父ID");
+
+ b.Property("Reason")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("RoleName")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)")
+ .HasComment("角色名称");
+
+ b.Property("SignId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SubjectVisitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialReadingCriterionId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TrialSiteId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("VisitStageId")
+ .HasColumnType("uniqueidentifier")
+ .HasComment("访视计划ID");
+
+ b.Property("VisitTaskId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CreateUserId");
+
+ b.HasIndex("TrialReadingCriterionId");
+
+ b.HasIndex("VisitTaskId");
+
+ b.ToTable("DataInspection", t =>
+ {
+ t.HasComment("稽查 - 记录表");
+ });
+ });
+
+ modelBuilder.Entity("IRaCIS.Core.Domain.Models.DicomInstance", b =>
+ {
+ b.Property("SeqId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Anonymize")
+ .HasColumnType("bit");
+
+ b.Property("BitsAllocated")
+ .HasColumnType("int");
+
+ b.Property("CPIStatus")
+ .HasColumnType("bit");
+
+ b.Property("CorrectedImage")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("CreateTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreateUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DecayCorrection")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("DeleteUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletedTime")
+ .HasColumnType("datetime2");
+
+ b.Property("EncapsulatedDocument")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FileSize")
+ .HasColumnType("bigint");
+
+ b.Property("FrameOfReferenceUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("FrameTime")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("HtmlPath")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ImageColumns")
+ .HasColumnType("int");
+
+ b.Property("ImageOrientationPatient")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ImagePositionPatient")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("ImageRows")
+ .HasColumnType("int");
+
+ b.Property("ImagerPixelSpacing")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("InstanceNumber")
+ .HasColumnType("int");
+
+ b.Property("InstanceTime")
+ .HasColumnType("datetime2");
+
+ b.Property("IsDeleted")
+ .HasColumnType("bit");
+
+ b.Property("IsEncapsulated")
+ .HasColumnType("bit");
+
+ b.Property("IsReading")
+ .HasColumnType("bit");
+
+ b.Property("MediaStorageSOPClassUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("MediaStorageSOPInstanceUID")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("NumberOfFrames")
+ .HasColumnType("int");
+
+ b.Property("Path")
+ .IsRequired()
+ .HasMaxLength(1000)
+ .HasColumnType("nvarchar(1000)");
+
+ b.Property