Merge branch 'Test_IRC_Net8' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is failing Details

IRC_NewDev
hang 2024-08-21 17:26:18 +08:00
commit 9356e6ed7e
13 changed files with 176 additions and 136 deletions

View File

@ -9,6 +9,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using SharpCompress.Common; using SharpCompress.Common;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services.BackGroundJob namespace IRaCIS.Application.Services.BackGroundJob
{ {
@ -21,77 +22,45 @@ namespace IRaCIS.Application.Services.BackGroundJob
Task InitHangfireJobTaskAsync(); Task InitHangfireJobTaskAsync();
} }
public class IRaCISCHangfireJob : IIRaCISHangfireJob public class IRaCISCHangfireJob(IRepository<Trial> _trialRepository,
IEasyCachingProvider _provider,
ILogger<IRaCISCHangfireJob> _logger,
IRepository<SystemAnonymization> _systemAnonymizationRepository,
IRepository<Internationalization> _internationalizationRepository,
IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository
) : IIRaCISHangfireJob
{ {
public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources); public static string JsonFileFolder = Path.Combine(AppContext.BaseDirectory, StaticData.Folder.Resources);
private readonly IRepository<Trial> _trialRepository;
private readonly IEasyCachingProvider _provider;
private readonly ILogger<IRaCISCHangfireJob> _logger;
private readonly IRepository<SystemAnonymization> _systemAnonymizationRepository;
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
private readonly IRepository<Internationalization> _internationalizationRepository;
public IRaCISCHangfireJob(IRepository<Trial> trialRepository, ILogger<IRaCISCHangfireJob> logger, IEasyCachingProvider provider, IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<Internationalization> internationalizationRepository, IRepository<SystemAnonymization> systemAnonymizationRepository)
{
_trialRepository = trialRepository;
_provider = provider;
_logger = logger;
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
_internationalizationRepository = internationalizationRepository;
_systemAnonymizationRepository = systemAnonymizationRepository;
}
public async Task InitHangfireJobTaskAsync() public async Task InitHangfireJobTaskAsync()
{ {
_logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行开始~");
//初始化国际化
//项目状态 立即加载到缓存中
await MemoryCacheTrialStatusAsync();
await MemoryCacheAnonymizeData();
//创建项目缓存 定时任务
HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
//初始化
await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository); await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_internationalizationRepository);
//创建邮件定时任务 //创建邮件定时任务
await InitSysAndTrialCronJobAsync(); await InitSysAndTrialCronJobAsync();
#region 废弃
////项目状态 立即加载到缓存中
//await MemoryCacheTrialStatusAsync();
////await MemoryCacheAnonymizeData();
////创建项目缓存 定时任务
//HangfireJobHelper.AddOrUpdateInitCronJob<IIRaCISHangfireJob>("RecurringJob_Cache_TrialState", t => t.MemoryCacheTrialStatusAsync(), Cron.Daily());
#endregion
_logger.LogInformation("项目启动 hangfire 任务初始化 执行结束"); _logger.LogInformation("项目启动 hangfire 任务初始化 执行结束");
} }
/// <summary>
/// 缓存项目状态
/// </summary>
/// <returns></returns>
public async Task MemoryCacheTrialStatusAsync()
{
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToListAsync();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
public async Task MemoryCacheAnonymizeData()
{
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
}
@ -136,6 +105,36 @@ namespace IRaCIS.Application.Services.BackGroundJob
} }
#region 废弃 前端上传的时候获取
/// <summary>
/// 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
/// </summary>
/// <returns></returns>
public async Task MemoryCacheTrialStatusAsync()
{
var list = await _trialRepository.Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToListAsync();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
public async Task MemoryCacheAnonymizeData()
{
var systemAnonymizationList = await _systemAnonymizationRepository.Where(t => t.IsEnable).ToListAsync();
_provider.Set(StaticData.Anonymize.Anonymize_AddFixedFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_AddIRCInfoFiled, systemAnonymizationList.Where(t => t.IsAdd && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_FixedField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed).ToList(), TimeSpan.FromDays(7));
_provider.Set(StaticData.Anonymize.Anonymize_IRCInfoField, systemAnonymizationList.Where(t => t.IsAdd == false && t.IsFixed == false).ToList(), TimeSpan.FromDays(7));
}
#endregion
} }

View File

@ -9,6 +9,7 @@ using Panda.DynamicWebApi.Attributes;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@ -32,7 +33,7 @@ namespace IRaCIS.Core.Application
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
@ -60,6 +61,9 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_hostEnvironment))] [MemberNotNull(nameof(_hostEnvironment))]
public IWebHostEnvironment _hostEnvironment { get; set; } public IWebHostEnvironment _hostEnvironment { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
#endregion #endregion
@ -81,8 +85,9 @@ namespace IRaCIS.Core.Application
[MemberNotNull(nameof(_localizer))] [MemberNotNull(nameof(_localizer))]
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
[MemberNotNull(nameof(_fusionCache))]
public IFusionCache _fusionCache { get; set; }
} }
[TypeFilter(typeof(UnifiedApiResultFilter))] [TypeFilter(typeof(UnifiedApiResultFilter))]
@ -97,6 +102,8 @@ namespace IRaCIS.Core.Application
public IStringLocalizer _localizer { get; set; } public IStringLocalizer _localizer { get; set; }
public IFusionCache _fusionCache { get; set; }
public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class public static IResponseOutput Null404NotFound<TEntity>(TEntity? businessObject) where TEntity : class
{ {
return new ResponseOutput<string>() return new ResponseOutput<string>()

View File

@ -1,10 +1,12 @@
using EasyCaching.Core; using EasyCaching.Core;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using ZiggyCreatures.Caching.Fusion;
using static IRaCIS.Core.Domain.Share.StaticData; using static IRaCIS.Core.Domain.Share.StaticData;
namespace IRaCIS.Core.Application.Filter namespace IRaCIS.Core.Application.Filter
@ -16,47 +18,36 @@ namespace IRaCIS.Core.Application.Filter
{ {
private readonly IEasyCachingProvider _provider; private readonly IEasyCachingProvider _provider;
private readonly IUserInfo _userInfo; private readonly IUserInfo _userInfo;
private readonly IFusionCache _fusionCache;
public IStringLocalizer _localizer; public IStringLocalizer _localizer;
private readonly List<string> _trialOptList=new List<string>(); private readonly IRepository<Trial> _trialRepository;
private readonly List<string> _trialOptList = new List<string>();
public TrialResourceFilter(IEasyCachingProvider provider, IStringLocalizer localizer , IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null) public TrialResourceFilter(IFusionCache fusionCache, IRepository<Trial> trialRepository, IEasyCachingProvider provider, IStringLocalizer localizer, IUserInfo userInfo, string trialOpt = null, string trialOpt2 = null, string trialOpt3 = null)
{ {
_fusionCache = fusionCache;
_provider = provider; _provider = provider;
_userInfo = userInfo; _userInfo = userInfo;
_localizer = localizer; _localizer = localizer;
//_trialOpt = trialOpt; _trialRepository = trialRepository;
if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt)) _trialOptList.Add(trialOpt.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt2)) _trialOptList.Add(trialOpt2.Trim());
if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim()); if (!string.IsNullOrWhiteSpace(trialOpt3)) _trialOptList.Add(trialOpt3.Trim());
} }
//public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
//{
// _provider = provider;
// _userInfo = userInfo;
//}
//优先选择异步的方法 //优先选择异步的方法
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) 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 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(); //var _trialOptList= typeFilter.Arguments.Select(t => t.ToString()).ToList();
#region 处理新的用户类型,不能操作项目相关接口 #region 处理新的用户类型,不能操作项目相关接口
// 后期列举出具体的类型,其他任何用户类型,都不允许操作 // 后期列举出具体的类型,其他任何用户类型,都不允许操作
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower()!= "TrialDocument/userConfirm".ToLower()) if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA && _userInfo.RequestUrl.ToLower() != "TrialDocument/userConfirm".ToLower())
{ {
//---对不起,您的账户没有操作权限。 //---对不起,您的账户没有操作权限。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_NoAccessPermission"]));
@ -97,7 +88,7 @@ namespace IRaCIS.Core.Application.Filter
} }
else else
{ {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查 //---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
@ -128,20 +119,20 @@ namespace IRaCIS.Core.Application.Filter
if (matchResult.Success) if (matchResult.Success)
{ {
//有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下 //有可能匹配错误 "trialId":"","documentId":"b8180000-3e2c-0016-9fe0-08da33f96236" 从缓存里面验证下
var cacheResultDic = _provider.GetAll<string>(new[] { matchResult.Value });
var trialStatusStr = cacheResultDic[matchResult.Value.ToLower()].Value; trialIdStr = matchResult.Value;
if (!string.IsNullOrWhiteSpace(trialStatusStr)) var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
if (string.IsNullOrWhiteSpace(trialStatusStr))
{ {
trialIdStr = matchResult.Value; //数据库 检查该项目Id不对
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
} }
else else
{ {
//---正则取请求Refer 中trialId 失败,请联系开发人员核查 //---正则取请求Refer 中trialId 失败,请联系开发人员核查
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_ReferTrialIdFailed"]));
} }
@ -153,34 +144,12 @@ namespace IRaCIS.Core.Application.Filter
} }
//通过path 或者body 找到trialId 了 //通过path 或者body 找到trialId 了
if ( !string.IsNullOrWhiteSpace(trialIdStr)) if (!string.IsNullOrWhiteSpace(trialIdStr))
{ {
var trialStatusStr = await _fusionCache.GetOrSetAsync(CacheKeys.Trial(trialIdStr), _ => CacheHelper.GetTrialStatusAsync(Guid.Parse(trialIdStr), _trialRepository), TimeSpan.FromDays(7));
//如果没缓存数据,可能定时任务没执行或者缓存丢失 在此重新缓存
if (_provider.GetCount() == 0)
{
var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
.ToList();
list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
}
var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });
var trialStatusStr = cacheResultDic[trialIdStr].Value;
//意外 导致缓存过期,调整服务器时间,测试不想重启程序
if (string.IsNullOrWhiteSpace(trialStatusStr))
{
var trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;
trialStatusStr = trialRepository?.Where(t => t.Id == Guid.Parse(trialIdStr)).Select(t => t.TrialStatusStr).FirstOrDefault();
}
// 这里是统一拦截 项目有关的操作允许情况(特殊的地方比如项目配置有的在多种状态初始化ongoing都可以操作有的仅仅在Initializing还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口) // 这里是统一拦截 项目有关的操作允许情况(特殊的地方比如项目配置有的在多种状态初始化ongoing都可以操作有的仅仅在Initializing还有 项目添加和更新,不走这里,特殊处理,不然在这里显得很乱,判断是哪个接口)
if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t=>t== TrialOpt.BeforeOngoingCantOpt) ) if (trialStatusStr == StaticData.TrialState.TrialOngoing || _trialOptList.Any(t => t == TrialOpt.BeforeOngoingCantOpt))
{ {
await next.Invoke(); await next.Invoke();
@ -189,14 +158,14 @@ namespace IRaCIS.Core.Application.Filter
// 项目停止、或者完成 不允许操作 // 项目停止、或者完成 不允许操作
else else
{ {
//---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改 //---本次请求被配置规则拦截:项目状态处于进行中时,才允许操作,若此处逻辑有误,请联系开发人员修改
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"])); context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
} }
} }
//添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截 //添加项目 签名系统文档的时候 不做拦截 但是更新项目 签名项目文档的时候需要拦截
else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial ||t ==TrialOpt.SignSystemDocNoTrialId)) else if (_trialOptList.Any(t => t == TrialOpt.AddOrUpdateTrial || t == TrialOpt.SignSystemDocNoTrialId))
{ {
await next.Invoke(); await next.Invoke();
} }

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class CacheKeys
{
public static string Trial(string trialIdStr) => $"TrialId:{trialIdStr}";
// 你可以为其他实体和模块定义更多的键
}
public static class CacheHelper
{
public static async Task<string?> GetTrialStatusAsync(Guid trialId, IRepository<Trial> _trialRepository)
{
var statusStr = await _trialRepository.Where(t => t.Id == trialId, ignoreQueryFilters: true).Select(t => t.TrialStatusStr).FirstOrDefaultAsync();
return statusStr;
}
}
}

View File

@ -13315,7 +13315,7 @@
</member> </member>
<member name="M:IRaCIS.Application.Services.BackGroundJob.IRaCISCHangfireJob.MemoryCacheTrialStatusAsync"> <member name="M:IRaCIS.Application.Services.BackGroundJob.IRaCISCHangfireJob.MemoryCacheTrialStatusAsync">
<summary> <summary>
缓存项目状态 缓存项目状态--之前是启动的时候就获取所有的项目进行缓存,加上定时任务刷新,现在的话,改为是按照需要进行缓存请求数据库
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>

View File

@ -33,7 +33,10 @@ namespace IRaCIS.Core.Application.ViewModel
public class TaskConsistentRuleBasic : TaskConsistentRuleAddOrEdit public class TaskConsistentRuleBasic : TaskConsistentRuleAddOrEdit
{ {
/// <summary>
/// 任务展示访视 读片任务显示是否顺序
/// </summary>
public ReadingOrder IsReadingTaskViewInOrder { get; set; } = ReadingOrder.InOrder;
} }
public class SubjectGeneratedTask public class SubjectGeneratedTask

View File

@ -17,6 +17,7 @@ using IRaCIS.Core.Infra.EFCore.Common;
using System.Linq.Expressions; using System.Linq.Expressions;
using IRaCIS.Core.Domain.Share.Reading; using IRaCIS.Core.Domain.Share.Reading;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
{ {
@ -26,7 +27,7 @@ namespace IRaCIS.Core.Application.Service
/// 访视读片任务 /// 访视读片任务
/// </summary> /// </summary>
[ApiExplorerSettings(GroupName = "Trial")] [ApiExplorerSettings(GroupName = "Trial")]
public class VisitTaskHelpeService : IVisitTaskHelpeService public class VisitTaskHelpeService : BaseService, IVisitTaskHelpeService
{ {
private readonly IRepository<VisitTask> _visitTaskRepository; private readonly IRepository<VisitTask> _visitTaskRepository;
@ -450,6 +451,19 @@ namespace IRaCIS.Core.Application.Service
} }
/// <summary>
/// 获取GetIsClinicalDataSignTest
/// </summary>
/// <param name="visitTask"></param>
/// <returns></returns>
public async Task<bool> GetIsClinicalDataSignTest(Guid visitTask)
{
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTask).FirstNotNullAsync();
var clinicalDataConfirmList = _trialClinicalDataSetRepository.Where(t => t.TrialId == taskinfo.TrialId && t.IsConfirm).Include(t => t.TrialClinicalDataSetCriteriaList).ToList();
Guid readingid = taskinfo.SourceSubjectVisitId == null ? taskinfo.SouceReadModuleId!.Value : taskinfo.SourceSubjectVisitId.Value;
return IsClinicalDataSign(taskinfo.ReadingCategory, taskinfo.VisitTaskNum == 0m, taskinfo.TrialReadingCriterionId, clinicalDataConfirmList, readingid, taskinfo.TrialId); ;
}
// 有可能在任务生成之前 就签名完了临床数据 // 有可能在任务生成之前 就签名完了临床数据
private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId) private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List<ClinicalDataTrialSet> trialClinicalDataSetList, Guid readingId, Guid trialId)
@ -468,7 +482,9 @@ namespace IRaCIS.Core.Application.Service
//CRC 的自动签名 不用管 只用处理PM的就好 //CRC 的自动签名 不用管 只用处理PM的就好
var haveSignedCount = _readingClinicalDataRepository var haveSignedCount = _readingClinicalDataRepository
.Where(t => t.TrialId == trialId && t.IsSign && t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count(); .Where(t => t.TrialId == trialId && t.IsSign
&& t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(x=>x.TrialReadingCriterionId== trialReadingCriterionId)
&& t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count();
var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault(); var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault();
@ -1415,6 +1431,7 @@ namespace IRaCIS.Core.Application.Service
case GenerateTaskCategory.SelfConsistent: case GenerateTaskCategory.SelfConsistent:
var readingCriterionId = generateTaskCommand.GenerataConsistentTaskList.First().TrialReadingCriterionId; var readingCriterionId = generateTaskCommand.GenerataConsistentTaskList.First().TrialReadingCriterionId;
var isReadingTaskViewInOrder = await _trialReadingCriterionRepository.Where(t => t.Id == readingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
var subjectId = generateTaskCommand.GenerataConsistentTaskList.First().SubjectId; var subjectId = generateTaskCommand.GenerataConsistentTaskList.First().SubjectId;
//var trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault(); //var trialReadingCriterion=_trialReadingCriterionRepository.Where(t=>t.Id== trialReadingCriterionId).FirstOrDefault();
@ -1457,7 +1474,11 @@ namespace IRaCIS.Core.Application.Service
foreach (var task in generateTaskCommand.GenerataConsistentTaskList) foreach (var task in generateTaskCommand.GenerataConsistentTaskList)
{ {
var exsitPDF = await _readingClinicalDataRepository.AnyAsync(t => t.TrialId == trialId &&
var exsitPDF = await _readingClinicalDataRepository
.WhereIf(isReadingTaskViewInOrder== ReadingOrder.Random,t=>t.ReadingId== task.SouceReadModuleId|| t.ReadingId == task.SourceSubjectVisitId)
.AnyAsync(t => t.TrialId == trialId &&
t.SubjectId== task.SubjectId&& t.SubjectId== task.SubjectId&&
t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId) t.ClinicalDataTrialSet.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == readingCriterionId)

View File

@ -293,7 +293,8 @@ namespace IRaCIS.Core.Application.Service
//CreateMap<TaskConsistentRule, TaskConsistentRuleView>() //CreateMap<TaskConsistentRule, TaskConsistentRuleView>()
// .ForMember(o => o.GeneratedSubjectCount, t => t.MapFrom(u => u.DoctorVisitTaskList.Where(t => t.IsAnalysisCreate && t.TaskConsistentRuleId == u.Id).Select(t => t.SubjectId).Distinct().Count())) ; // .ForMember(o => o.GeneratedSubjectCount, t => t.MapFrom(u => u.DoctorVisitTaskList.Where(t => t.IsAnalysisCreate && t.TaskConsistentRuleId == u.Id).Select(t => t.SubjectId).Distinct().Count())) ;
CreateMap<TaskConsistentRule, TaskConsistentRuleBasic>(); CreateMap<TaskConsistentRule, TaskConsistentRuleBasic>()
.ForMember(o => o.IsReadingTaskViewInOrder, t => t.MapFrom(u => u.TrialReadingCriterion.IsReadingTaskViewInOrder));
CreateMap<TaskConsistentRuleAddOrEdit, TaskConsistentRule>(); CreateMap<TaskConsistentRuleAddOrEdit, TaskConsistentRule>();

View File

@ -398,7 +398,7 @@ namespace IRaCIS.Core.Application.Contracts
var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters() var result = await _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId && t.TrialId == trialId).IgnoreQueryFilters()
.ProjectTo<LoginReturnDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException(); .ProjectTo<LoginReturnDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync().IfNullThrowException();
var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).Select(t => t.Trial.TrialExtraConfigJsonStr).FirstOrDefault()??string.Empty; var siteSurveryConfig = _trialSiteSurveyRepository.Where(t => t.Id == trialSiteSurveyId).IgnoreQueryFilters().Select(t => t.Trial.TrialExtraConfigJsonStr).FirstOrDefault()??string.Empty;
result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig(); result.SiteSurveyFiledConfig = JsonConvert.DeserializeObject<TrialExtraConfig>(siteSurveryConfig) ?? new TrialExtraConfig();
return result; return result;

View File

@ -23,6 +23,8 @@ using IRaCIS.Application.Contracts;
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Core.Application namespace IRaCIS.Core.Application
{ {
@ -1239,8 +1241,8 @@ namespace IRaCIS.Core.Application
} }
await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), trialStatusStr, TimeSpan.FromDays(7));
await _repository.SaveChangesAsync(); await _repository.SaveChangesAsync();
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@ -1390,7 +1392,7 @@ namespace IRaCIS.Core.Application
{ {
var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync(); var trialCode = await _trialRepository.Where(t => t.Id == trialId).Select(t => t.TrialCode).FirstOrDefaultAsync();
return new TrialPacsInfo() { Ip=optionsMonitor.CurrentValue.IP,Port=optionsMonitor.CurrentValue.Port,TrialCalledAE=$"EI{trialCode}" }; return new TrialPacsInfo() { Ip = optionsMonitor.CurrentValue.IP, Port = optionsMonitor.CurrentValue.Port, TrialCalledAE = $"EI{trialCode}" };
} }
} }
} }

View File

@ -12,6 +12,8 @@ using Microsoft.AspNetCore.Authorization;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Linq; using System.Linq;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Helper;
using ZiggyCreatures.Caching.Fusion;
namespace IRaCIS.Application.Services namespace IRaCIS.Application.Services
{ {
@ -93,7 +95,7 @@ namespace IRaCIS.Application.Services
.WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount) .WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount)
.WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount) .WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount)
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id && t.IsDeleted == false) && t.IsDeleted == false)
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id , isEn_Us= _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc); return await query.ToPagedListAsync(searchParam.PageIndex, searchParam.PageSize, string.IsNullOrWhiteSpace(searchParam.SortField) ? "CreateTime" : searchParam.SortField, searchParam.Asc);
@ -119,7 +121,7 @@ namespace IRaCIS.Application.Services
[HttpGet("{projectId:guid}")] [HttpGet("{projectId:guid}")]
public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId) public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId)
{ {
return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new {isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
} }
@ -216,7 +218,7 @@ namespace IRaCIS.Application.Services
await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id }); await _repository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id });
//添加访视 //添加访视
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true,VisitWindowLeft=-28,VisitWindowRight=0 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true, VisitWindowLeft = -28, VisitWindowRight = 0 });
await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 }); await _repository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 });
@ -234,12 +236,11 @@ namespace IRaCIS.Application.Services
{ {
item.TrialId = trial.Id; item.TrialId = trial.Id;
} }
await _repository.AddRangeAsync(needAddBodyPartList,true);
_provider.Set(trial.Id.ToString(), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7)); await _repository.AddRangeAsync(needAddBodyPartList, true);
await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7));
return ResponseOutput.Ok(trial); return ResponseOutput.Ok(trial);
} }
@ -589,7 +590,7 @@ namespace IRaCIS.Application.Services
await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId);
await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId); await _repository.BatchDeleteAsync<VisitTask>(t => t.TrialId == trialId);
await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId) ; await _repository.BatchDeleteAsync<TrialStateChange>(t => t.TrialId == trialId);
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@ -650,7 +651,7 @@ namespace IRaCIS.Application.Services
.WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code)) .WhereIf(!string.IsNullOrEmpty(searchModel.Code), o => o.TrialCode.Contains(searchModel.Code))
.WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Indication), o => o.Indication.Contains(searchModel.Indication))
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id)) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.Id))
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id ,isEn_Us = _userInfo.IsEn_Us }); .ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.Id, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc); return await query.ToPagedListAsync(searchModel.PageIndex, searchModel.PageSize, string.IsNullOrWhiteSpace(searchModel.SortField) ? "CreateTime" : searchModel.SortField, searchModel.Asc);

View File

@ -340,6 +340,7 @@ namespace IRaCIS.Application.Services
foreach (var waitUploadItem in scpStudyList) foreach (var waitUploadItem in scpStudyList)
{ {
if (isVerifyVisitImageDate) if (isVerifyVisitImageDate)
{ {
//小于当前访视 最近的最晚拍片 //小于当前访视 最近的最晚拍片
@ -349,7 +350,8 @@ namespace IRaCIS.Application.Services
{ {
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误", // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误",
result.Add(new VerifySCPStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] }); result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] });
continue; // 跳过当前迭代
} }
//大于当前访视 最近的最早拍片日期 //大于当前访视 最近的最早拍片日期
@ -358,13 +360,15 @@ namespace IRaCIS.Application.Services
if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate) if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
{ {
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误" // $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"
result.Add(new VerifySCPStudyUploadResult() { ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!]}); result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!] });
continue; // 跳过当前迭代
} }
} }
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault(); var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
var currentStudyResult = new VerifyStudyUploadResult(); var currentStudyResult = new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id };
//数据库不存在该检查 允许上传 //数据库不存在该检查 允许上传
if (verifyStudyInfo == null) if (verifyStudyInfo == null)
@ -391,6 +395,8 @@ namespace IRaCIS.Application.Services
currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName]; currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName];
} }
} }
result.Add(currentStudyResult);
} }
@ -413,7 +419,7 @@ namespace IRaCIS.Application.Services
[UnitOfWork] [UnitOfWork]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand, public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
[FromServices]IRepository<DicomStudy> _dicomstudyRepository, [FromServices] IRepository<DicomStudy> _dicomstudyRepository,
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository, [FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository) [FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
{ {
@ -427,7 +433,7 @@ namespace IRaCIS.Application.Services
var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList(); var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList();
var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList(); var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList();
if (inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t))) if (!(inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t))))
{ {
throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!"); throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!");
} }
@ -505,7 +511,7 @@ namespace IRaCIS.Application.Services
var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList(); var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList();
var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t=>t.SeriesList).ThenInclude(t=>t.SCPInstanceList).FirstOrDefault(); var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t => t.SeriesList).ThenInclude(t => t.SCPInstanceList).FirstOrDefault();
//以最后一次为准 //以最后一次为准
study.IsFromPACS = true; study.IsFromPACS = true;

View File

@ -15,6 +15,7 @@ public static class StaticData
public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>(); public static Dictionary<string, string> Log_Locoalize_Dic = new Dictionary<string, string>();
#region 国际化
public static readonly string En_US_Json = "en-US.json"; public static readonly string En_US_Json = "en-US.json";
public static readonly string Zh_CN_Json = "zh-CN.json"; public static readonly string Zh_CN_Json = "zh-CN.json";
@ -70,9 +71,11 @@ public static class StaticData
} }
#endregion
#region 字典表项固定值 #region 字典表项固定值
public static readonly string Title = "Title";
public static readonly string Title = "Title";
public static readonly string ReadingType = "ReadingType"; public static readonly string ReadingType = "ReadingType";
public static readonly string Subspeciality = "Subspeciality"; public static readonly string Subspeciality = "Subspeciality";
@ -80,6 +83,7 @@ public static class StaticData
public static readonly string Criterion = "Criterion"; public static readonly string Criterion = "Criterion";
public static readonly string ReviewType = "ReviewType"; public static readonly string ReviewType = "ReviewType";
public static readonly string ReadingStandard = "ReadingStandard"; public static readonly string ReadingStandard = "ReadingStandard";
#endregion #endregion