diff --git a/IRaCIS.Core.Application/BusinessFilter/LegacyController/TrialResourceFilter.cs b/IRaCIS.Core.Application/BusinessFilter/LegacyController/TrialResourceFilter.cs deleted file mode 100644 index d05790c3c..000000000 --- a/IRaCIS.Core.Application/BusinessFilter/LegacyController/TrialResourceFilter.cs +++ /dev/null @@ -1,196 +0,0 @@ -using IRaCIS.Core.Application.Helper; -using IRaCIS.Core.Domain.Share; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Localization; -using System.Text.RegularExpressions; -using ZiggyCreatures.Caching.Fusion; -using static IRaCIS.Core.Domain.Share.StaticData; - -namespace IRaCIS.Core.Application.Filter; - -/// -/// 主要为了 处理项目结束 锁库,不允许操作 -/// -public class TrialResourceFilter : Attribute, IAsyncResourceFilter -{ - private readonly IUserInfo _userInfo; - private readonly IFusionCache _fusionCache; - public IStringLocalizer _localizer; - private readonly IRepository _trialRepository; - private readonly List _trialOptList = new List(); - - - public TrialResourceFilter(IFusionCache fusionCache, IRepository trialRepository, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) - { - _fusionCache = fusionCache; - _userInfo = userInfo; - _localizer = localizer; - _trialRepository = trialRepository; - - if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim()); - if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim()); - if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim()); - - } - - //优先选择异步的方法 - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - // var typeFilter = context.ActionDescriptor.EndpointMetadata.Where(t => t.GetType() == typeof(TypeFilterAttribute)).Select(t => (TypeFilterAttribute)t).ToList().FirstOrDefault(); - //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList(); - - // 获取当前请求的 Host 信息 - var requestHost = context.HttpContext.Request.Host; - - // 检查请求是否来自 localhost:6100 - if (requestHost.Host == "localhost" && (requestHost.Port == 6100|| requestHost.Port==3305)) - { - await next.Invoke(); - - return; - } - - #region 处理新的用户类型,不能操作项目相关接口 - - // 后期列举出具体的类型,其他任何用户类型,都不允许操作 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower()) - { - //---对不起,您的账户没有操作权限。 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); - - return; - } - - #endregion - - - - //TrialId 传递的途径多种,可能在path 可能在body 可能在数组中,也可能在对象中,可能就在url - var trialIdStr = string.Empty; - - if (!string.IsNullOrWhiteSpace(context.HttpContext.Request.Query["trialId"])) - { - trialIdStr = context.HttpContext.Request.Query["trialId"]; - } - - //先尝试从path中取TrialId - else if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId"))) - { - var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId"); - trialIdStr = context.RouteData.Values.Values.ToList()[index] as string; - } - else if (context.HttpContext.Request.Headers["Referer"].ToString().Contains("trialId")) - { - var headerStr = context.HttpContext.Request.Headers["Referer"].ToString(); - - var trialIdIndex = headerStr.IndexOf("trialId"); - - - var matchResult = Regex.Match(headerStr.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}"); - - if (matchResult.Success) - { - trialIdStr = matchResult.Value; - } - else - { - //---正则取请求Refer 中trialId 失败,请联系开发人员核查 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); - } - - } - else - { - #region body 中取数据 - - //设置可以多次读 - context.HttpContext.Request.EnableBuffering(); - var reader = new StreamReader(context.HttpContext.Request.Body); - var contentFromBody = await reader.ReadToEndAsync(); - //读取后,流的位置还原 - context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin); - //context.HttpContext.Request.Body.Position = 0; - - //找到参数位置在字符串中的索引 - var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase); - - if (trialIdIndex > -1) - { - // (?<="trialId" *: *").*?(?=",) - - //使用正则 [0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12} - - var matchResult = Regex.Match(contentFromBody.Substring(trialIdIndex), @"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}"); - - if (matchResult.Success) - { - //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下 - - trialIdStr = matchResult.Value; - - var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7)); - - if (string.IsNullOrWhiteSpace(trialStatusStr)) - { - - //数据库 检查该项目Id不对 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); - - return; - } - } - else - { - //---正则取请求Refer 中trialId 失败,请联系开发人员核查 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); - - return; - } - - //使用字符串取 如果是swagger 可能有时取的不对 因为空格的原因 - //trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 3 - } - - #endregion - } - - //通过path 或者body 找到trialId 了 - if (!string.IsNullOrWhiteSpace(trialIdStr)) - { - var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7)); - - // 这里是统一拦截 项目有关的操作允许情况(特殊的地方,比如项目配置(有的在多种状态(初始化,ongoing)都可以操作,有的仅仅在Initializing)还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口) - if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt)) - { - - await next.Invoke(); - - } - // 项目停止、或者完成 不允许操作 - else - { - //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"])); - - } - - } - //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截 - else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId)) - { - await next.Invoke(); - } - - else - { - //如果项目相关接口没有传递trialId 会来到这里,提醒,以便修改 - - //---该接口参数中,没有传递项目编号,请核对。 - context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_MissingProjectNumber"])); - } - - - } -} diff --git a/IRaCIS.Core.Application/Helper/FileDocProcess/ExcelExportHelper.cs b/IRaCIS.Core.Application/Helper/FileDocProcess/ExcelExportHelper.cs index bf0861df9..0435c3dc6 100644 --- a/IRaCIS.Core.Application/Helper/FileDocProcess/ExcelExportHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileDocProcess/ExcelExportHelper.cs @@ -165,7 +165,7 @@ public static class ExcelExportHelper } //中文替换项目术语 - if (isEn_US == false) + if (isEn_US == false && data.TrialObjectNameList.Count > 0) { var replaceObjectList = data.TrialObjectNameList; @@ -415,7 +415,7 @@ public static class ExcelExportHelper } //中文替换项目术语 - if (isEn_US == false) + if (isEn_US == false && data.TrialObjectNameList.Count > 0) { var replaceObjectList = data.TrialObjectNameList; @@ -526,6 +526,7 @@ public static class ExcelExportHelper var name = dynamicColumnConfig.ColumnNameList[i - dynamicColunmStartIndex]; titelRow.GetCell(i).SetCellValue(name); + templateRow.GetCell(i).SetCellValue(""); } } @@ -538,7 +539,6 @@ public static class ExcelExportHelper templateStream = memoryStream2; } - } #endregion diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index ec3b62da9..4a9ef91de 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -13038,11 +13038,6 @@ 参考处理链接: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0 - - - 主要为了 处理项目结束 锁库,不允许操作 - - 用户登录错误 限制登录 diff --git a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs index ad1b6385c..f1559db0e 100644 --- a/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs +++ b/IRaCIS.Core.Application/Service/Common/ExcelExportService.cs @@ -1840,8 +1840,11 @@ namespace IRaCIS.Core.Application.Service.Common list.Add(new ExportDocumentDes() { Code = StaticData.Export.CommonReadingDetail_Export, ExportCatogory = ExportResult.DetailedTableOfAssessmentResults }); + + list.Add(new ExportDocumentDes() { Code = StaticData.Export.CommonJudgeReadingDetail_Export, ExportCatogory = ExportResult.DetailedTableOfAdjudicationResults }); + if (criterion.CriterionType == CriterionType.RECIST1Point1 || criterion.CriterionType == CriterionType.RECIST1Pointt1_MB || criterion.CriterionType == CriterionType.IRECIST1Point1 || criterion.CriterionType == CriterionType.Lugano2014 || criterion.CriterionType == CriterionType.Lugano2014WithoutPET || criterion.CriterionType == CriterionType.PCWG3) @@ -1849,6 +1852,10 @@ namespace IRaCIS.Core.Application.Service.Common list.Add(new ExportDocumentDes() { Code = StaticData.Export.ReadingLession_Export, ExportCatogory = ExportResult.DetailedTableOfLesions }); } + if (criterion.CriterionType == CriterionType.OCT) + { + list.Add(new ExportDocumentDes() { Code = StaticData.Export.OCT_ReadingLession_Export, ExportCatogory = ExportResult.OCT_ReadingLession_Export }); + } switch (criterion.ArbitrationRule) { @@ -1966,11 +1973,14 @@ namespace IRaCIS.Core.Application.Service.Common { //病灶明细表 export_Template = StaticData.Export.ReadingLession_Export; + } + //病灶明细表 需要单独处理 - if (inQuery.ReadingExportType != ExportResult.DetailedTableOfLesions) + if (inQuery.ReadingExportType != ExportResult.DetailedTableOfLesions && inQuery.ReadingExportType != ExportResult.OCT_ReadingLession_Export) { + //其他可以统一处理 list = await query.ProjectTo(_mapper.ConfigurationProvider, new { @@ -1983,7 +1993,12 @@ namespace IRaCIS.Core.Application.Service.Common } else { - //其他可以统一处理 + //病灶明细表 + if (inQuery.ReadingExportType == ExportResult.OCT_ReadingLession_Export) + { + export_Template = StaticData.Export.OCT_ReadingLession_Export; + } + var taskList = await query.ProjectTo(_mapper.ConfigurationProvider, new { @@ -2055,10 +2070,16 @@ namespace IRaCIS.Core.Application.Service.Common //有三部分组成 外层问题+ 没有配置病灶编号和类型+ 动态的表格问题 var dynamicLessionInfoList = addLessionInfoList.Union(dynamicPartialLessionInfoList).Union(item.QuestionAnswerList).ToList(); - var cloneItem = item.Clone(); - cloneItem.QuestionAnswerList = dynamicLessionInfoList; + //OCT 多个表格,但是只导出一个表格,有的问题答案就是空的 + if (dynamicLessionInfoList.Count > 0) + { + + var cloneItem = item.Clone(); + cloneItem.QuestionAnswerList = dynamicLessionInfoList; + + list.Add(cloneItem); + } - list.Add(cloneItem); } } else diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index bbf7745d7..6f5393bca 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -231,6 +231,9 @@ namespace IRaCIS.Core.Application.Contracts public DateTime? EarliestScanDate { get; set; } public DateTime? LatestScanDate { get; set; } + public string EarliestScanDateStr => EarliestScanDate?.ToString("yyyy-MM-dd") ?? string.Empty; + public string LatestScanDateStr => LatestScanDate?.ToString("yyyy-MM-dd") ?? string.Empty; + public DateTime? SubmitTime { get; set; } @@ -293,7 +296,7 @@ namespace IRaCIS.Core.Application.Contracts public string LatestReplyUserName { get; set; } = String.Empty; public string Content { get; set; } = string.Empty; - public string ContentReplaced => Content.Replace("
","").Replace("
", "").Replace("
", "").Replace("
",""); + public string ContentReplaced => Content.Replace("
", "").Replace("
", "").Replace("
", "").Replace("
", ""); [DictionaryTranslateAttribute("ChallengeIsClosed")] public bool IsClosed { get; set; } @@ -377,7 +380,7 @@ namespace IRaCIS.Core.Application.Contracts //public bool IsUrgent { get; set; } //[ExcelColumn(Name = "FirstGiveMedicineTime", Format = "yyyy-MM-dd")] - public DateTime? FirstGiveMedicineTime { get; set; } + public DateOnly? FirstGiveMedicineTime { get; set; } public string FirstGiveMedicineTimeStr => FirstGiveMedicineTime?.ToString("yyyy-MM-dd"); @@ -740,6 +743,8 @@ namespace IRaCIS.Core.Application.Contracts public DateTime? LatestScanDate { get; set; } + public string LatestScanDateStr => LatestScanDate?.ToString("yyyy-MM-dd") ?? string.Empty; + public List ModalityList { get; set; } public string Modalitys => string.Join(',', ModalityList); diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index 1a5314382..a8e0463ef 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -276,7 +276,7 @@ namespace IRaCIS.Core.Application.Service CreateMap() .ForMember(o => o.LessionCode, t => t.MapFrom(u => u.RowMark)) .ForMember(o => o.LessionType, t => t.MapFrom(u => (int?)u.ReadingQuestionTrial.LesionType)) - .ForMember(o => o.LessionAnswerList, t => t.MapFrom(u => u.LesionAnswerList)); + .ForMember(o => o.LessionAnswerList, t => t.MapFrom(u => u.LesionAnswerList.Where(c => c.ReadingTableQuestionTrial.ExportResultStr.Contains(((int)readingExportType).ToString())))); CreateMap() .ForMember(o => o.LessionCode, t => t.MapFrom(u => u.Lesion.RowMark)) diff --git a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs index 05a21b55a..9eb7ead4c 100644 --- a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs +++ b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicineQuestionService.cs @@ -244,7 +244,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TypeFilter(typeof(TrialResourceFilter))] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task AddOrUpdateReadingMedicineTrialQuestion(ReadingMedicineTrialQuestionAddOrEdit inDto) { var existsQuery = _readingMedicineTrialQuestionRepository diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs index cf76591ed..f4930a553 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs @@ -88,7 +88,7 @@ namespace IRaCIS.Application.Contracts public string CriterionName { get; set; } = string.Empty; - public List TrialObjectNameList { get; set; } + public List TrialObjectNameList { get; set; } = new List(); } public class TrialModalitySelectDto diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs index ccb1ea11b..53d4b2376 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/UserTrialViewModel.cs @@ -88,11 +88,14 @@ namespace IRaCIS.Application.Contracts [ExcelFormat("yyyy-MM-dd")] public DateTime? RemoveTime { get; set; } + public string RemoveTimeStr=> RemoveTime?.ToString("yyyy-MM-dd") ?? string.Empty; + //[ExporterHeader(Format = "yyyy-mm-DD")] [ExcelFormat("yyyy-MM-dd")] public DateTime? JoinTime { get; set; } + public string JoinTimeStr => JoinTime?.ToString("yyyy-MM-dd") ?? string.Empty; //[ExporterHeader(Format = "yyyy-mm-DD hh:mm:ss")] [ExcelFormat("yyyy-MM-dd HH:mm:ss")] diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index 06efc542c..ee9202cc4 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -466,12 +466,17 @@ namespace IRaCIS.Core.Domain.Share DetailedTableOfInterReaderAnalysisResults = 6, + /// + /// 斑块表 + /// + OCT_ReadingLession_Export = 7, + + //访视一致率 - VisitJudgeRatio_Export = 7, + VisitJudgeRatio_Export = 17, //阅片期一致率 - ReadingPeriodJudgeRatio_Export = 8, - + ReadingPeriodJudgeRatio_Export = 18, } diff --git a/IRaCIS.Core.Domain/Trial/Trial.cs b/IRaCIS.Core.Domain/Trial/Trial.cs index 11237a804..2178c8a44 100644 --- a/IRaCIS.Core.Domain/Trial/Trial.cs +++ b/IRaCIS.Core.Domain/Trial/Trial.cs @@ -263,8 +263,7 @@ public partial class Trial : BaseFullDeleteAuditEntity [Comment("项目术语配置Json字符串")] [StringLength(2000)] public List TrialObjectNameList { get; set; } - //[NotMapped] - //public List TrialObjectNameList => JsonConvert.DeserializeObject>(TrialObjectNameConfigStr) ?? new List(); + } [ComplexType] @@ -275,5 +274,4 @@ public class TrialObjectNameConfig public string TrialName { get; set; } public bool IsDefault { get; set; } - } \ No newline at end of file diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index f4f70b2fe..9778e7371 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -67,13 +67,13 @@ public class IRaCISDBContext : DbContext // 使用部分加密值转换器,前 2 个字符不加密,方便模糊搜索 entity.Property(e => e.Name).HasConversion(new PartialEncryptionConverter(2)); - entity.OwnsMany(x => x.TestJsonObjectLsit, ownedNavigationBuilder => - { - ownedNavigationBuilder.ToJson(); - }); + //entity.OwnsMany(x => x.TestJsonObjectLsit, ownedNavigationBuilder => + //{ + // ownedNavigationBuilder.ToJson(); + //}); - //entity.Property(e => e.TestJsonObjectLsit).HasConversion(v => v == null ? "[]" : JsonConvert.SerializeObject(v), - // v => string.IsNullOrEmpty(v) ? null : JsonConvert.DeserializeObject>(v)); + entity.Property(e => e.TestJsonObjectLsit).HasConversion(v => v == null ? "[]" : JsonConvert.SerializeObject(v), + v => string.IsNullOrEmpty(v) ? null : JsonConvert.DeserializeObject>(v)); }); modelBuilder.Entity(entity => @@ -81,7 +81,7 @@ public class IRaCISDBContext : DbContext //项目术语配置 entity.OwnsMany(x => x.TrialObjectNameList, ownedNavigationBuilder => { - ownedNavigationBuilder.ToJson(); + ownedNavigationBuilder.ToJson() ; }); }); @@ -595,8 +595,9 @@ public class TestLength : Entity [StringLength(1000)] public List TestEnumList { get; set; } = new List(); - [MaxLength] public List TestJsonObjectLsit { get; set; } + + public DateOnly? TestDate { get; set; } } diff --git a/IRaCIS.Core.Infra.EFCore/Interceptor/SoftDeleteQueryExtension.cs b/IRaCIS.Core.Infra.EFCore/Interceptor/SoftDeleteQueryExtension.cs index d7acc11a5..c042f5051 100644 --- a/IRaCIS.Core.Infra.EFCore/Interceptor/SoftDeleteQueryExtension.cs +++ b/IRaCIS.Core.Infra.EFCore/Interceptor/SoftDeleteQueryExtension.cs @@ -1,20 +1,44 @@ using IRaCIS.Core.Domain.Models; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using System.Reflection; namespace IRaCIS.Core.Infra.EFCore { + /// + /// modelBuilder.Entity().HasQueryFilter(s => !s.IsDeleted);(这个是自动全局配置的) + /// modelBuilder.Entity().HasQueryFilter(c => !c.SubjectVisit.IsDeleted); (这个没有自动加) 所以有警告 + /// public static class SoftDeleteQueryExtension { public static void AddSoftDeleteQueryFilter( - this IMutableEntityType entityData) + this IMutableEntityType entityType) { var methodToCall = typeof(SoftDeleteQueryExtension) .GetMethod(nameof(GetSoftDeleteFilter), BindingFlags.NonPublic | BindingFlags.Static) - .MakeGenericMethod(entityData.ClrType); + .MakeGenericMethod(entityType.ClrType); var filter = methodToCall.Invoke(null, new object[] { }); - entityData.SetQueryFilter((LambdaExpression)filter); + entityType.SetQueryFilter((LambdaExpression)filter); + + //foreach (var navigation in entityType.GetNavigations()) + //{ + // var targetEntityType = navigation.TargetEntityType; + + // // 如果目标实体实现了 ISoftDelete 接口,递归添加过滤器 + // if (typeof(ISoftDelete).IsAssignableFrom(targetEntityType.ClrType)) + // { + // // 在当前实体的导航属性上添加过滤器 + // var targetEntityFilterMethod = typeof(SoftDeleteQueryExtension) + // .GetMethod(nameof(GetSoftDeleteFilterForNavigation), + // BindingFlags.NonPublic | BindingFlags.Static) + // .MakeGenericMethod(entityType.ClrType, targetEntityType.ClrType); + + // var navigationFilter = targetEntityFilterMethod.Invoke(null, new object[] { navigation }); + // entityType.SetQueryFilter((LambdaExpression)navigationFilter); + // } + //} + } @@ -24,5 +48,27 @@ namespace IRaCIS.Core.Infra.EFCore Expression> filter = x => !x.IsDeleted; return filter; } + + // 获取导航属性的软删除过滤器 + private static LambdaExpression GetSoftDeleteFilterForNavigation( + IMutableNavigation navigation) + where TEntity : class + where TNavigationEntity : class, ISoftDelete + { + // 获取导航属性的表达式 + var parameter = Expression.Parameter(typeof(TEntity), "e"); + var navigationExpression = Expression.Property(parameter, navigation.Name); + + // 获取导航属性中的 IsDeleted 属性 + var isDeletedProperty = Expression.Property(navigationExpression, nameof(ISoftDelete.IsDeleted)); + + // 生成过滤条件:导航属性不为空且未被软删除 + var condition = Expression.AndAlso( + Expression.NotEqual(navigationExpression, Expression.Constant(null, navigationExpression.Type)), // 判断导航属性是否为null + Expression.Equal(isDeletedProperty, Expression.Constant(false)) // 判断导航属性的 IsDeleted 为 false + ); + + return Expression.Lambda>(condition, parameter); + } } } diff --git a/IRaCIS.Core.Infrastructure/Extention/ExportExcelDateConverter.cs b/IRaCIS.Core.Infrastructure/Extention/ExportExcelDateConverter.cs index e24903407..281ececa9 100644 --- a/IRaCIS.Core.Infrastructure/Extention/ExportExcelDateConverter.cs +++ b/IRaCIS.Core.Infrastructure/Extention/ExportExcelDateConverter.cs @@ -19,7 +19,7 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson } public override bool CanConvert(Type objectType) { - + return objectType == typeof(DateTime) || objectType == typeof(DateTime?); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) @@ -37,7 +37,7 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson writer.WriteNull(); } - + } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) @@ -58,7 +58,7 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson } - public class ExportExcelConverterDate + public class ExportExcelConverterDate { public static T ConvertToClientTimeInObject(T obj, string timeZoneId) { @@ -67,7 +67,7 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson return obj; // 将对象序列化为 JSON 字符串 - string json = JsonConvert.SerializeObject(obj,new JsonSerializerSettings() { DateFormatString= "yyyy-MM-dd HH:mm:ss.fff" }); + string json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-dd HH:mm:ss.fff" }); // 将 JSON 字符串反序列化回对象 var deserializedObj = JsonConvert.DeserializeObject(json, new JsonSerializerSettings @@ -80,7 +80,7 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson return deserializedObj!; } - public static string DateTimeInternationalToString(DateTime? dateTime, string? clientZoneId=null) + public static string DateTimeInternationalToString(DateTime? dateTime, string? clientZoneId = null) { var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; @@ -94,15 +94,24 @@ namespace IRaCIS.Core.API._ServiceExtensions.NewtonsoftJson needDealTime = TimeZoneInfo.ConvertTime(needDealTime, TimeZoneInfo.Local, TimeZoneInfo.FindSystemTimeZoneById(clientZoneId)); } - if (isEn_US) + if (needDealTime.Hour == 0 && needDealTime.Minute == 0 && needDealTime.Second == 0 && needDealTime.Millisecond==0) { - //暂时保持一致,等需求确认,修改英文要展示的日期格式 - return needDealTime.ToString("yyyy-MM-dd HH:mm:ss"); + return needDealTime.ToString("yyyy-MM-dd"); } else { - return needDealTime.ToString("yyyy-MM-dd HH:mm:ss"); + if (isEn_US) + { + //暂时保持一致,等需求确认,修改英文要展示的日期格式 + return needDealTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + else + { + return needDealTime.ToString("yyyy-MM-dd HH:mm:ss"); + } } + + } else { diff --git a/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs index 3999919a7..d73a3cea9 100644 --- a/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/_Config/_StaticData.cs @@ -278,6 +278,10 @@ public static class StaticData public const string ReadingLession_Export = "ReadingLession_Export"; + public const string OCT_ReadingLession_Export = "OCT_ReadingLession_Export"; + + + public const string IVUSTheMeasuredValueOfEachMatchedFragment = "IVUS_TheMeasuredValueOfEachMatchedFragment";